diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index efd90a01ff..b273ac1eb2 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -29,6 +29,7 @@
// For the client FPS pref and anywhere else
#define MAX_CLIENT_FPS 200
+#define RECOMMENDED_FPS 100
// Some arbitrary defines to be used by self-pruning global lists. (see master_controller)
#define MAX_GEAR_COST 15 // Used in chargen for accessory loadout limit.
diff --git a/code/__defines/preferences.dm b/code/__defines/preferences.dm
index 14adeb62bb..5e03f3217c 100644
--- a/code/__defines/preferences.dm
+++ b/code/__defines/preferences.dm
@@ -16,6 +16,15 @@
#define SAVE_RESET -1
+//randomised elements
+#define RANDOM_ANTAG_ONLY 1
+#define RANDOM_DISABLED 2
+#define RANDOM_ENABLED 3
+
+// randomise_appearance_prefs() and randomize_human_appearance() proc flags
+#define RANDOMIZE_SPECIES (1<<0)
+#define RANDOMIZE_NAME (1<<1)
+
// Values for /datum/preference/savefile_identifier
/// This preference is character specific.
#define PREFERENCE_CHARACTER "character"
diff --git a/code/_global_vars/lists/misc.dm b/code/_global_vars/lists/misc.dm
index 5fb7fadce2..7fbe4c74f1 100644
--- a/code/_global_vars/lists/misc.dm
+++ b/code/_global_vars/lists/misc.dm
@@ -11,3 +11,5 @@ GLOBAL_LIST_EMPTY(tagger_locations)
GLOBAL_LIST_INIT(char_directory_tags, list("Pred", "Pred-Pref", "Prey", "Prey-Pref", "Switch", "Non-Vore", "Unset"))
GLOBAL_LIST_INIT(char_directory_erptags, list("Dominant", "Dom-Pref", "Submissive", "Sub-Pref", "Switch", "No ERP", "Unset"))
GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes
+
+GLOBAL_LIST_INIT(uplink_locations, list("PDA", "Headset", "None"))
diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm
index babe0b58d2..9a0a7ec500 100644
--- a/code/_helpers/_lists.dm
+++ b/code/_helpers/_lists.dm
@@ -975,3 +975,10 @@ var/global/list/json_cache = list()
if(islist(value))
new_value = deep_copy_list_alt(value)
copied_list[key_or_value] = new_value
+
+/// Turns an associative list into a flat list of keys
+/proc/assoc_to_keys(list/input)
+ var/list/keys = list()
+ for(var/key in input)
+ UNTYPED_LIST_ADD(keys, key)
+ return keys
diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm
index 0efc265b49..822db0178b 100644
--- a/code/_helpers/mobs.dm
+++ b/code/_helpers/mobs.dm
@@ -354,7 +354,7 @@ Proc for attack log creation, because really why not
cached_character_icons[cachekey] = .
/proc/not_has_ooc_text(mob/user)
- if (CONFIG_GET(flag/allow_metadata) && (!user.client?.prefs?.metadata || length(user.client.prefs.metadata) < 15))
+ if (CONFIG_GET(flag/allow_metadata) && (!user.client?.prefs?.read_preference(/datum/preference/text/living/ooc_notes) || length(user.client.prefs.read_preference(/datum/preference/text/living/ooc_notes)) < 15))
to_chat(user, span_warning("Please set informative OOC notes related to RP/ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup."))
return TRUE
return FALSE
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index 8d7ed229e4..910644d63f 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -624,5 +624,5 @@ GLOBAL_LIST_EMPTY(text_tag_cache)
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
/proc/sanitize_css_class_name(name)
- var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
- return replacetext(name, regex, "")
+ var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
+ return replacetext(name, regex, "")
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 518c3e03c5..2d70678ae0 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -361,15 +361,51 @@ var/list/global_huds = list(
if(!client)
return 0
- HUD.ui_style = ui_style2icon(client?.prefs?.UI_style)
- HUD.ui_color = client?.prefs?.UI_style_color
- HUD.ui_alpha = client?.prefs?.UI_style_alpha
+ HUD.ui_style = ui_style2icon(read_preference(/datum/preference/choiced/ui_style))
+ HUD.ui_color = read_preference(/datum/preference/color/ui_style_color)
+ HUD.ui_alpha = read_preference(/datum/preference/numeric/ui_style_alpha)
set_hud_used(HUD)
/mob/proc/set_hud_used(datum/hud/new_hud)
hud_used = new_hud
new_hud.build_action_groups()
+/mob/proc/update_ui_style(UI_style_new, UI_style_alpha_new, UI_style_color_new)
+ if(!hud_used)
+ return
+
+ if(!UI_style_alpha_new)
+ UI_style_alpha_new = hud_used.ui_alpha
+ hud_used.ui_alpha = UI_style_alpha_new
+ if(!UI_style_color_new)
+ UI_style_color_new = hud_used.ui_color
+ hud_used.ui_color = UI_style_color_new
+
+ var/list/icons = hud_used.adding + hud_used.other + hud_used.hotkeybuttons
+ icons.Add(zone_sel)
+ icons.Add(gun_setting_icon)
+ icons.Add(item_use_icon)
+ icons.Add(gun_move_icon)
+ icons.Add(radio_use_icon)
+
+ var/icon/ic
+
+ if(UI_style_new)
+ if(isrobot(src))
+ ic = all_ui_styles_robot[UI_style_new]
+ else
+ ic = all_ui_styles[UI_style_new]
+ hud_used.ui_style = ic
+ else
+ ic = hud_used.ui_style
+
+ for(var/obj/screen/I in icons)
+ if(I.name in list(I_HELP, I_HURT, I_DISARM, I_GRAB))
+ continue
+ I.icon = ic
+ I.color = UI_style_color_new
+ I.alpha = UI_style_alpha_new
+
/datum/hud/proc/apply_minihud(var/datum/mini_hud/MH)
if(MH in minihuds)
return
diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm
index 898e71fd46..1d3a4b45cd 100644
--- a/code/game/antagonist/station/traitor.dm
+++ b/code/game/antagonist/station/traitor.dm
@@ -115,21 +115,23 @@ var/datum/antagonist/traitor/traitors
var/loc = ""
var/obj/item/R = locate() //Hide the uplink in a PDA if available, otherwise radio
- if(traitor_mob.client.prefs.uplinklocation == "Headset")
+ var/uplinklocation = traitor_mob.read_preference(/datum/preference/choiced/uplinklocation)
+
+ if(uplinklocation == "Headset")
R = locate(/obj/item/radio) in traitor_mob.contents
if(!R)
R = locate(/obj/item/pda) in traitor_mob.contents
to_chat(traitor_mob, "Could not locate a Radio, installing in PDA instead!")
if (!R)
to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.")
- else if(traitor_mob.client.prefs.uplinklocation == "PDA")
+ else if(uplinklocation == "PDA")
R = locate(/obj/item/pda) in traitor_mob.contents
if(!R)
R = locate(/obj/item/radio) in traitor_mob.contents
to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!")
if(!R)
to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.")
- else if(traitor_mob.client.prefs.uplinklocation == "None")
+ else if(uplinklocation == "None")
to_chat(traitor_mob, "You have elected to not have an AntagCorp portable teleportation relay installed!")
R = null
else
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 5399023c28..f9dcbe3f0b 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -420,7 +420,7 @@ var/list/mob/living/forced_ambiance_list = new
else
L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
else if(src.ambience && src.ambience.len)
- var/ambience_odds = L?.client.prefs.ambience_chance
+ var/ambience_odds = L.read_preference(/datum/preference/numeric/ambience_chance)
if(prob(ambience_odds) && (world.time >= L.client.time_last_ambience_played + 1 MINUTE))
var/sound = pick(ambience)
L << sound(sound, repeat = 0, wait = 0, volume = 50 * volume_mod, channel = CHANNEL_AMBIENCE)
diff --git a/code/game/birthday.dm b/code/game/birthday.dm
index add0a3f7f0..2af06c13ff 100644
--- a/code/game/birthday.dm
+++ b/code/game/birthday.dm
@@ -1,9 +1,12 @@
/mob/living/carbon/human/proc/consider_birthday()
+ var/bday_month = read_preference(/datum/preference/numeric/human/bday_month)
+ var/bday_day = read_preference(/datum/preference/numeric/human/bday_day)
if(!bday_month || !bday_day) //If we don't have one of these set, don't worry about it
return
if(real_name != client.prefs.real_name) //let's not celebrate the birthday of that weird mob we got dropped into
return
- if(!(client.prefs.last_birthday_notification < world_time_year)) //you only get notified once a year
+
+ if(!(read_preference(/datum/preference/numeric/human/last_bday_note) < world_time_year)) //you only get notified once a year
return
if((world_time_month == bday_month) && (world_time_day == bday_day)) //it is your birthday
birthday(1)
@@ -14,23 +17,23 @@
/mob/living/carbon/human/proc/birthday(var/birthday = 0)
var/msg
- var/lastyear = client.prefs.last_birthday_notification
- client.prefs.last_birthday_notification = world_time_year //We only want to ask once a year per character, this persists, update early in case of shenanigans
+ var/lastyear = read_preference(/datum/preference/numeric/human/last_bday_note)
+ write_preference_directly(/datum/preference/numeric/human/last_bday_note, world_time_year) //We only want to ask once a year per character, this persists, update early in case of shenanigans
if(birthday) //woo
msg = "Today is your birthday! Do you want to increase your character's listed age?"
- if(client.prefs.bday_announce)
+ if(read_preference(/datum/preference/toggle/human/bday_announce))
var/list/sounds = list('sound/voice/BIRTH.ogg')
var/oursound = pickweight(sounds)
command_announcement.Announce("Confirmed presence of BIRTHDAY aboard the station! It is [src.real_name]'s birthday or similar sort of celebration, name day, hatchday, WHATEVER! We encourage you to go find [src.real_name] and show them how we celebrate around here! Have a secure day!", "BIRTHDAY!", oursound)
else
msg = "Your birthday has passed! Do you want to increase your character's listed age?" //sad, but thus is the life of an adult
- if(tgui_alert(src, msg,"BIRTHDAY! ([bday_month]/[bday_day])",list("Level me up, baby","No way, I'mma stay young forever")) == "Level me up, baby")
+ if(tgui_alert(src, msg,"BIRTHDAY! ([read_preference(/datum/preference/numeric/human/bday_month)]/[read_preference(/datum/preference/numeric/human/bday_day)])",list("Level me up, baby","No way, I'mma stay young forever")) == "Level me up, baby")
if(lastyear == 0) //We've never been asked, so let's just assume you were keeping track before now and only add 1
age += 1
else
var/howmuch = world_time_year - lastyear
age += howmuch
to_chat(src, span_notice("You are now [age]! Happy birthday!"))
- client.prefs.age = age //Set the age on the character sheet
+ write_preference_directly(/datum/preference/numeric/human/age, age) //Set the age on the character sheet
client.prefs.save_character() //Save the info
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 30738ecd45..add1dfbf02 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -50,7 +50,7 @@ var/global/datum/controller/occupations/job_master
var/datum/job/job = GetJob(rank)
if(!job)
return 0
- if((job.minimum_character_age || job.min_age_by_species) && (player.client.prefs.age < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data["brain"])))
+ if((job.minimum_character_age || job.min_age_by_species) && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data["brain"])))
return 0
if(jobban_isbanned(player, rank))
return 0
@@ -93,7 +93,7 @@ var/global/datum/controller/occupations/job_master
if(!job.player_old_enough(player.client))
Debug("FOC player not old enough, Player: [player]")
continue
- if(job.minimum_character_age && (player.client.prefs.age < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data["brain"])))
+ if(job.minimum_character_age && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data["brain"])))
Debug("FOC character not old enough, Player: [player]")
continue
//VOREStation Code Start
@@ -121,7 +121,7 @@ var/global/datum/controller/occupations/job_master
if(!job)
continue
- if((job.minimum_character_age || job.min_age_by_species) && (player.client.prefs.age < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data["brain"])))
+ if((job.minimum_character_age || job.min_age_by_species) && (player.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(player.client.prefs.species, player.client.prefs.organ_data["brain"])))
continue
if(job.is_species_banned(player.client.prefs.species, player.client.prefs.organ_data["brain"]) == TRUE)
@@ -180,7 +180,7 @@ var/global/datum/controller/occupations/job_master
for(var/mob/V in candidates)
// Log-out during round-start? What a bad boy, no head position for you!
if(!V.client) continue
- var/age = V.client.prefs.age
+ var/age = V.read_preference(/datum/preference/numeric/human/age)
if(age < job.get_min_age(V.client.prefs.species, V.client.prefs.organ_data["brain"])) // Nope.
continue
@@ -660,16 +660,16 @@ var/global/datum/controller/occupations/job_master
fail_deadly = J?.offmap_spawn
//Spawn them at their preferred one
- if(C && C.prefs.spawnpoint)
- if(!(C.prefs.spawnpoint in using_map.allowed_spawns))
+ if(C && C.prefs.read_preference(/datum/preference/choiced/human/spawnpoint))
+ if(!(C.prefs.read_preference(/datum/preference/choiced/human/spawnpoint) in using_map.allowed_spawns))
if(fail_deadly)
to_chat(C, span_warning("Your chosen spawnpoint is unavailable for this map and your job requires a specific spawnpoint. Please correct your spawn point choice."))
return
else
- to_chat(C, span_warning("Your chosen spawnpoint ([C.prefs.spawnpoint]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead."))
+ to_chat(C, span_warning("Your chosen spawnpoint ([C.prefs.read_preference(/datum/preference/choiced/human/spawnpoint)]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead."))
spawnpos = null
else
- spawnpos = spawntypes[C.prefs.spawnpoint]
+ spawnpos = spawntypes[C.prefs.read_preference(/datum/preference/choiced/human/spawnpoint)]
//We will return a list key'd by "turf" and "msg"
. = list("turf","msg")
diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm
index bebed4393d..a3f0e47329 100644
--- a/code/modules/admin/admin_verb_lists_vr.dm
+++ b/code/modules/admin/admin_verb_lists_vr.dm
@@ -35,7 +35,6 @@ var/list/admin_verbs_admin = list(
/datum/admins/proc/announce, //priority announce something to all clients.,
/datum/admins/proc/intercom, //send a fake intercom message, like an arrivals announcement,
/datum/admins/proc/intercom_convo, //send a fake intercom conversation, like an ATC exchange,
- /client/proc/colorooc, //allows us to set a custom colour for everythign we say in ooc,
/client/proc/admin_ghost, //allows us to ghost/reenter body at will,
/datum/admins/proc/show_player_panel, //shows an interface for individual players, with various links (links require additional flags, //VOREStation Add,
/client/proc/player_panel_new, //shows an interface for all players, with links to various panels, //VOREStation Add,
@@ -315,7 +314,6 @@ var/list/admin_verbs_hideable = list(
/datum/admins/proc/toggleenter,
/datum/admins/proc/toggleguests,
/datum/admins/proc/announce,
- /client/proc/colorooc,
/client/proc/admin_ghost,
/client/proc/toggle_view_range,
/datum/admins/proc/view_txt_log,
@@ -405,7 +403,6 @@ var/list/admin_verbs_mod = list(
/client/proc/cmd_event_say,
/datum/admins/proc/show_player_info,
/datum/admins/proc/show_traitor_panel,
- /client/proc/colorooc,
/client/proc/player_panel_new,
/client/proc/dsay,
/datum/admins/proc/show_player_panel,
@@ -499,7 +496,6 @@ var/list/admin_verbs_event_manager = list(
/datum/admins/proc/announce, //priority announce something to all clients.,
/datum/admins/proc/intercom, //send a fake intercom message, like an arrivals announcement,
/datum/admins/proc/intercom_convo, //send a fake intercom conversation, like an ATC exchange,
- /client/proc/colorooc, //allows us to set a custom colour for everythign we say in ooc,
/client/proc/admin_ghost, //allows us to ghost/reenter body at will,
/client/proc/toggle_view_range, //changes how far we can see,
/client/proc/cmd_admin_pm_context, //right-click adminPM interface,
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index abf4005f4b..1a3462e8f2 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -157,20 +157,6 @@
feedback_add_details("admin_verb","S") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
-/client/proc/colorooc()
- set category = "Admin.Misc"
- set name = "OOC Text Color"
- if(!holder) return
- var/response = tgui_alert(src, "Please choose a distinct color that is easy to read and doesn't mix with all the other chat and radio frequency colors.", "Change own OOC color", list("Pick new color", "Reset to default", "Cancel"))
- if(response == "Pick new color")
- prefs.ooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color
- else if(response == "Reset to default")
- prefs.ooccolor = initial(prefs.ooccolor)
- SScharacter_setup.queue_preferences_save(prefs)
-
- feedback_add_details("admin_verb","OC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- return
-
/client/proc/findStealthKey(txt)
if(txt)
for(var/P in GLOB.stealthminID)
diff --git a/code/modules/asset_cache/assets/preferences.dm b/code/modules/asset_cache/assets/preferences.dm
index 3d01471a38..acc1a349b5 100644
--- a/code/modules/asset_cache/assets/preferences.dm
+++ b/code/modules/asset_cache/assets/preferences.dm
@@ -1,3 +1,44 @@
+/// Assets generated from `/datum/preference` icons
+/datum/asset/spritesheet/preferences
+ name = "preferences"
+ early = TRUE
+
+/datum/asset/spritesheet/preferences/create_spritesheets()
+ var/list/to_insert = list()
+
+ for(var/preference_key in GLOB.preference_entries_by_key)
+ var/datum/preference/choiced/preference = GLOB.preference_entries_by_key[preference_key]
+ if(!istype(preference))
+ continue
+
+ if(!preference.should_generate_icons)
+ continue
+
+ for(var/preference_value in preference.get_choices())
+ var/create_icon_of = preference.icon_for(preference_value)
+
+ var/icon/icon
+ var/icon_state
+
+ if(ispath(create_icon_of, /atom))
+ var/atom/atom_icon_source = create_icon_of
+ icon = initial(atom_icon_source.icon)
+ icon_state = initial(atom_icon_source.icon_state)
+ else if(isicon(create_icon_of))
+ icon = create_icon_of
+ else
+ CRASH("[create_icon_of] is an invalid preference value (from [preference_key]:[preference_value]).")
+
+ to_insert[preference.get_spritesheet_key(preference.pref_serialize(preference_value))] = list(icon, icon_state)
+
+ for(var/spritesheet_key in to_insert)
+ var/list/inserting = to_insert[spritesheet_key]
+ Insert(spritesheet_key, inserting[1], inserting[2])
+
+/// Returns the key that will be used in the spritesheet for a given value.
+/datum/preference/proc/get_spritesheet_key(value)
+ return "[savefile_key]___[sanitize_css_class_name(value)]"
+
/// Sends information needed for shared details on individual preferences
/datum/asset/json/preferences
name = "preferences"
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index bf75522f0f..23cdc53b29 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -287,15 +287,6 @@
void = new()
screen += void
- //disabled because we don't use the ingame changelog system any more
- /*
- if((prefs.lastchangelog != changelog_hash) && isnewplayer(src.mob)) //bolds the changelog button on the interface so we know there are updates.
- to_chat(src, span_info("You have unread updates in the changelog."))
- winset(src, "rpane.changelog", "background-color=#eaeaea;font-style=bold")
- if(config.aggressive_changelog)
- src.changes()
- */
-
if(CONFIG_GET(flag/paranoia_logging))
var/alert = FALSE //VOREStation Edit start.
if(isnum(player_age) && player_age == 0)
diff --git a/code/modules/client/preference_setup/antagonism/01_basic.dm b/code/modules/client/preference_setup/antagonism/01_basic.dm
index 7a5701fef5..4ffaa10c95 100644
--- a/code/modules/client/preference_setup/antagonism/01_basic.dm
+++ b/code/modules/client/preference_setup/antagonism/01_basic.dm
@@ -1,23 +1,18 @@
-var/global/list/uplink_locations = list("PDA", "Headset", "None")
-
/datum/category_item/player_setup_item/antagonism/basic
name = "Basic"
sort_order = 1
/datum/category_item/player_setup_item/antagonism/basic/load_character(list/save_data)
- pref.uplinklocation = save_data["uplinklocation"]
pref.exploit_record = save_data["exploit_record"]
pref.antag_faction = save_data["antag_faction"]
pref.antag_vis = save_data["antag_vis"]
/datum/category_item/player_setup_item/antagonism/basic/save_character(list/save_data)
- save_data["uplinklocation"] = pref.uplinklocation
save_data["exploit_record"] = pref.exploit_record
save_data["antag_faction"] = pref.antag_faction
save_data["antag_vis"] = pref.antag_vis
/datum/category_item/player_setup_item/antagonism/basic/sanitize_character()
- pref.uplinklocation = sanitize_inlist(pref.uplinklocation, uplink_locations, initial(pref.uplinklocation))
if(!pref.antag_faction) pref.antag_faction = "None"
if(!pref.antag_vis) pref.antag_vis = "Hidden"
@@ -30,7 +25,7 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None")
/datum/category_item/player_setup_item/antagonism/basic/content(var/mob/user)
. += "Faction: [pref.antag_faction]
"
. += "Visibility: [pref.antag_vis]
"
- . +=span_bold("Uplink Type : [pref.uplinklocation]")
+ . += span_bold("Uplink Type:") + " [pref.read_preference(/datum/preference/choiced/uplinklocation)]"
. +="
"
. +=span_bold("Exploitable information:") + "
"
if(jobban_isbanned(user, "Records"))
@@ -39,8 +34,10 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None")
. +="[TextPreview(pref.exploit_record,40)]
"
/datum/category_item/player_setup_item/antagonism/basic/OnTopic(var/href,var/list/href_list, var/mob/user)
- if (href_list["antagtask"])
- pref.uplinklocation = next_in_list(pref.uplinklocation, uplink_locations)
+ if(href_list["uplinklocation"])
+ var/new_uplinklocation = tgui_input_list(user, "Choose your uplink location:", "Character Preference", GLOB.uplink_locations, pref.read_preference(/datum/preference/choiced/uplinklocation))
+ if(new_uplinklocation && CanUseTopic(user))
+ pref.update_preference_by_type(/datum/preference/choiced/uplinklocation, new_uplinklocation)
return TOPIC_REFRESH
if(href_list["exploitable_record"])
diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm
index 173c6de2a6..ebd7563b74 100644
--- a/code/modules/client/preference_setup/general/01_basic.dm
+++ b/code/modules/client/preference_setup/general/01_basic.dm
@@ -13,48 +13,22 @@
/datum/category_item/player_setup_item/general/basic/load_character(list/save_data)
pref.real_name = save_data["real_name"]
pref.nickname = save_data["nickname"]
- pref.be_random_name = save_data["name_is_always_random"]
pref.biological_gender = save_data["gender"]
pref.identifying_gender = save_data["id_gender"]
- pref.age = save_data["age"]
- pref.bday_month = save_data["bday_month"]
- pref.bday_day = save_data["bday_day"]
- pref.last_birthday_notification = save_data["last_bday_note"]
- pref.bday_announce = save_data["bday_announce"]
- pref.spawnpoint = save_data["spawnpoint"]
- pref.metadata = save_data["OOC_Notes"]
- pref.metadata_likes = save_data["OOC_Notes_Likes"]
- pref.metadata_dislikes = save_data["OOC_Notes_Disikes"]
/datum/category_item/player_setup_item/general/basic/save_character(list/save_data)
save_data["real_name"] = pref.real_name
save_data["nickname"] = pref.nickname
- save_data["name_is_always_random"] = pref.be_random_name
save_data["gender"] = pref.biological_gender
save_data["id_gender"] = pref.identifying_gender
- save_data["age"] = pref.age
- save_data["bday_month"] = pref.bday_month
- save_data["bday_day"] = pref.bday_day
- save_data["last_bday_note"] = pref.last_birthday_notification
- save_data["bday_announce"] = pref.bday_announce
- save_data["spawnpoint"] = pref.spawnpoint
- save_data["OOC_Notes"] = pref.metadata
- save_data["OOC_Notes_Likes"] = pref.metadata_likes
- save_data["OOC_Notes_Disikes"] = pref.metadata_dislikes
/datum/category_item/player_setup_item/general/basic/sanitize_character()
- pref.age = sanitize_integer(pref.age, get_min_age(), get_max_age(), initial(pref.age))
- pref.bday_month = sanitize_integer(pref.bday_month, 0, 12, initial(pref.bday_month))
- pref.bday_day = sanitize_integer(pref.bday_day, 0, 31, initial(pref.bday_day))
- pref.last_birthday_notification = sanitize_integer(pref.last_birthday_notification, 0, 9999, initial(pref.last_birthday_notification))
pref.biological_gender = sanitize_inlist(pref.biological_gender, get_genders(), pick(get_genders()))
pref.identifying_gender = (pref.identifying_gender in all_genders_define_list) ? pref.identifying_gender : pref.biological_gender
pref.real_name = sanitize_name(pref.real_name, pref.species, is_FBP())
if(!pref.real_name)
pref.real_name = random_name(pref.identifying_gender, pref.species)
pref.nickname = sanitize_name(pref.nickname)
- pref.spawnpoint = sanitize_inlist(pref.spawnpoint, spawntypes, initial(pref.spawnpoint))
- pref.be_random_name = sanitize_integer(pref.be_random_name, 0, 1, initial(pref.be_random_name))
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/basic/copy_to_mob(var/mob/living/carbon/human/character)
@@ -75,24 +49,21 @@
character.gender = pref.biological_gender
character.identifying_gender = pref.identifying_gender
- character.age = pref.age
- character.bday_month = pref.bday_month
- character.bday_day = pref.bday_day
/datum/category_item/player_setup_item/general/basic/content()
. = list()
. += span_bold("Name:") + " "
. += "[pref.real_name]
"
. += "Randomize Name
"
- . += "Always Random Name: [pref.be_random_name ? "Yes" : "No"]
"
+ . += "Always Random Name: [pref.read_preference(/datum/preference/toggle/human/name_is_always_random) ? "Yes" : "No"]
"
. += span_bold("Nickname:") + " "
. += "[pref.nickname]"
. += "(Clear)"
. += "
"
. += span_bold("Biological Sex:") + " [gender2text(pref.biological_gender)]
"
. += span_bold("Pronouns:") + " [gender2text(pref.identifying_gender)]
"
- . += span_bold("Age:") + " [pref.age] Birthday: [pref.bday_month]/[pref.bday_day] - Announce?: [pref.bday_announce ? "Yes" : "No"]
"
- . += span_bold("Spawn Point") + ": [pref.spawnpoint]
"
+ . += span_bold("Age:") + " [pref.read_preference(/datum/preference/numeric/human/age)] Birthday: [pref.read_preference(/datum/preference/numeric/human/bday_month)]/[pref.read_preference(/datum/preference/numeric/human/bday_day)] - Announce?: [pref.read_preference(/datum/preference/toggle/human/bday_announce) ? "Yes" : "No"]
"
+ . += span_bold("Spawn Point:") + " [pref.read_preference(/datum/preference/choiced/human/spawnpoint)]
"
if(CONFIG_GET(flag/allow_metadata))
. += span_bold("OOC Notes: EditLikesDislikes") + "
"
. = jointext(.,null)
@@ -114,7 +85,7 @@
return TOPIC_REFRESH
else if(href_list["always_random_name"])
- pref.be_random_name = !pref.be_random_name
+ pref.update_preference_by_type(/datum/preference/toggle/human/name_is_always_random, !pref.read_preference(/datum/preference/toggle/human/name_is_always_random))
return TOPIC_REFRESH
else if(href_list["nickname"])
@@ -149,26 +120,26 @@
else if(href_list["age"])
var/min_age = get_min_age()
var/max_age = get_max_age()
- var/new_age = tgui_input_number(user, "Choose your character's age:\n([min_age]-[max_age])", "Character Preference", pref.age, max_age, min_age)
+ var/new_age = tgui_input_number(user, "Choose your character's age:\n([min_age]-[max_age])", "Character Preference", pref.read_preference(/datum/preference/numeric/human/age), max_age, min_age)
if(new_age && CanUseTopic(user))
- pref.age = max(min(round(text2num(new_age)), max_age), min_age)
+ pref.update_preference_by_type(/datum/preference/numeric/human/age, max(min(round(text2num(new_age)), max_age), min_age))
return TOPIC_REFRESH
else if(href_list["bday_month"])
- var/new_month = tgui_input_number(user, "Choose your character's birth month (number)", "Birthday Month", pref.bday_month, 12, 0)
+ var/new_month = tgui_input_number(user, "Choose your character's birth month (number)", "Birthday Month", pref.read_preference(/datum/preference/numeric/human/bday_month), 12, 0)
if(new_month && CanUseTopic(user))
- pref.bday_month = new_month
+ pref.update_preference_by_type(/datum/preference/numeric/human/bday_month, new_month)
else if((tgui_alert(user, "Would you like to clear the birthday entry?","Clear?",list("No","Yes")) == "Yes") && CanUseTopic(user))
- pref.bday_month = 0
- pref.bday_day = 0
+ pref.update_preference_by_type(/datum/preference/numeric/human/bday_month, 0)
+ pref.update_preference_by_type(/datum/preference/numeric/human/bday_day, 0)
return TOPIC_REFRESH
else if(href_list["bday_day"])
- if(!pref.bday_month)
+ if(!pref.read_preference(/datum/preference/numeric/human/bday_month))
tgui_alert(user,"You must set a birth month before you can set a day.", "Error", list("Okay"))
return
var/max_days
- switch(pref.bday_month)
+ switch(pref.read_preference(/datum/preference/numeric/human/bday_month))
if(1)
max_days = 31
if(2)
@@ -194,16 +165,16 @@
if(12)
max_days = 31
- var/new_day = tgui_input_number(user, "Choose your character's birth day (number, 1-[max_days])", "Birthday Day", pref.bday_day, max_days, 0)
+ var/new_day = tgui_input_number(user, "Choose your character's birth day (number, 1-[max_days])", "Birthday Day", pref.read_preference(/datum/preference/numeric/human/bday_day), max_days, 0)
if(new_day && CanUseTopic(user))
- pref.bday_day = new_day
+ pref.update_preference_by_type(/datum/preference/numeric/human/bday_day, new_day)
else if((tgui_alert(user, "Would you like to clear the birthday entry?","Clear?",list("No","Yes")) == "Yes") && CanUseTopic(user))
- pref.bday_month = 0
- pref.bday_day = 0
+ pref.update_preference_by_type(/datum/preference/numeric/human/bday_month, 0)
+ pref.update_preference_by_type(/datum/preference/numeric/human/bday_day, 0)
return TOPIC_REFRESH
else if(href_list["bday_announce"])
- pref.bday_announce = !pref.bday_announce
+ pref.update_preference_by_type(/datum/preference/toggle/human/bday_announce, !pref.read_preference(/datum/preference/toggle/human/bday_announce))
return TOPIC_REFRESH
else if(href_list["spawnpoint"])
@@ -212,25 +183,25 @@
spawnkeys += spawntype
var/choice = tgui_input_list(user, "Where would you like to spawn when late-joining?", "Late-Join Choice", spawnkeys)
if(!choice || !spawntypes[choice] || !CanUseTopic(user)) return TOPIC_NOACTION
- pref.spawnpoint = choice
+ pref.update_preference_by_type(/datum/preference/choiced/human/spawnpoint, choice)
return TOPIC_REFRESH
else if(href_list["edit_ooc_notes"])
- var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see, such as Roleplay-preferences. This will not be saved permanently unless you click save in the Character Setup panel!", "Game Preference" , html_decode(pref.metadata), multiline = TRUE, prevent_enter = TRUE))
+ var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see, such as Roleplay-preferences. This will not be saved permanently unless you click save in the Character Setup panel!", "Game Preference" , html_decode(pref.read_preference(/datum/preference/text/living/ooc_notes)), multiline = TRUE, prevent_enter = TRUE))
if(new_metadata && CanUseTopic(user))
- pref.metadata = new_metadata
+ pref.update_preference_by_type(/datum/preference/text/living/ooc_notes, new_metadata)
else if(href_list["edit_ooc_note_likes"])
- var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see relating to your LIKED roleplay preferences. This will not be saved permanently unless you click save in the Character Setup panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(pref.metadata_likes), multiline = TRUE, prevent_enter = TRUE))
+ var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see relating to your LIKED roleplay preferences. This will not be saved permanently unless you click save in the Character Setup panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(pref.read_preference(/datum/preference/text/living/ooc_notes_likes)), multiline = TRUE, prevent_enter = TRUE))
if(new_metadata && CanUseTopic(user))
if(new_metadata == "!clear")
new_metadata = ""
- pref.metadata_likes = new_metadata
+ pref.update_preference_by_type(/datum/preference/text/living/ooc_notes_likes, new_metadata)
else if(href_list["edit_ooc_note_dislikes"])
- var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see relating to your DISLIKED roleplay preferences. This will not be saved permanently unless you click save in the Character Setup panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(pref.metadata_dislikes), multiline = TRUE, prevent_enter = TRUE))
+ var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see relating to your DISLIKED roleplay preferences. This will not be saved permanently unless you click save in the Character Setup panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(pref.read_preference(/datum/preference/text/living/ooc_notes_dislikes)), multiline = TRUE, prevent_enter = TRUE))
if(new_metadata && CanUseTopic(user))
if(new_metadata == "!clear")
new_metadata = ""
- pref.metadata_dislikes = new_metadata
+ pref.update_preference_by_type(/datum/preference/text/living/ooc_notes_dislikes, new_metadata)
return ..()
/datum/category_item/player_setup_item/general/basic/proc/get_genders()
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index c0128fccba..9c7e35989b 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -8,15 +8,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/list/bgstate_options = list("steel", "000", "midgrey", "FFF", "white", "techmaint", "desert", "grass", "snow")
var/ear_style // Type of selected ear style
- var/r_ears = 30 // Ear color.
- var/g_ears = 30 // Ear color
- var/b_ears = 30 // Ear color
- var/r_ears2 = 30 // Ear extra color.
- var/g_ears2 = 30 // Ear extra color
- var/b_ears2 = 30 // Ear extra color
- var/r_ears3 = 30 // Ear tertiary color.
- var/g_ears3 = 30 // Ear tertiary color
- var/b_ears3 = 30 // Ear tertiary color
/// The typepath of the character's selected secondary ears.
var/ear_secondary_style
@@ -27,26 +18,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/list/ear_secondary_colors = list()
var/tail_style // Type of selected tail style
- var/r_tail = 30 // Tail/Taur color
- var/g_tail = 30 // Tail/Taur color
- var/b_tail = 30 // Tail/Taur color
- var/r_tail2 = 30 // For extra overlay.
- var/g_tail2 = 30 // For extra overlay.
- var/b_tail2 = 30 // For extra overlay.
- var/r_tail3 = 30 // For tertiary overlay.
- var/g_tail3 = 30 // For tertiary overlay.
- var/b_tail3 = 30 // For tertiary overlay.
var/wing_style // Type of selected wing style
- var/r_wing = 30 // Wing color
- var/g_wing = 30 // Wing color
- var/b_wing = 30 // Wing color
- var/r_wing2 = 30 // Wing extra color
- var/g_wing2 = 30 // Wing extra color
- var/b_wing2 = 30 // Wing extra color
- var/r_wing3 = 30 // Wing tertiary color
- var/g_wing3 = 30 // Wing tertiary color
- var/b_wing3 = 30 // Wing tertiary color
var/datum/browser/markings_subwindow = null
@@ -105,25 +78,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
/datum/category_item/player_setup_item/general/body/load_character(list/save_data)
pref.species = save_data["species"]
- pref.r_hair = save_data["hair_red"]
- pref.g_hair = save_data["hair_green"]
- pref.b_hair = save_data["hair_blue"]
- pref.r_facial = save_data["facial_red"]
- pref.r_grad = save_data["grad_red"]
- pref.g_grad = save_data["grad_green"]
- pref.b_grad = save_data["grad_blue"]
- pref.g_facial = save_data["facial_green"]
- pref.b_facial = save_data["facial_blue"]
pref.s_tone = save_data["skin_tone"]
- pref.r_skin = save_data["skin_red"]
- pref.g_skin = save_data["skin_green"]
- pref.b_skin = save_data["skin_blue"]
pref.h_style = save_data["hair_style_name"]
pref.f_style = save_data["facial_style_name"]
pref.grad_style = save_data["grad_style_name"]
- pref.r_eyes = save_data["eyes_red"]
- pref.g_eyes = save_data["eyes_green"]
- pref.b_eyes = save_data["eyes_blue"]
pref.b_type = save_data["b_type"]
pref.disabilities = save_data["disabilities"]
pref.organ_data = check_list_copy(save_data["organ_data"])
@@ -134,67 +92,22 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
for(var/j in pref.body_markings[i])
pref.body_markings[i][j] = check_list_copy(pref.body_markings[i][j])
pref.synth_color = save_data["synth_color"]
- pref.r_synth = save_data["synth_red"]
- pref.g_synth = save_data["synth_green"]
- pref.b_synth = save_data["synth_blue"]
pref.synth_markings = save_data["synth_markings"]
pref.bgstate = save_data["bgstate"]
pref.body_descriptors = check_list_copy(save_data["body_descriptors"])
pref.ear_style = save_data["ear_style"]
- pref.r_ears = save_data["r_ears"]
- pref.g_ears = save_data["g_ears"]
- pref.b_ears = save_data["b_ears"]
- pref.r_ears2 = save_data["r_ears2"]
- pref.g_ears2 = save_data["g_ears2"]
- pref.b_ears2 = save_data["b_ears2"]
- pref.r_ears3 = save_data["r_ears3"]
- pref.g_ears3 = save_data["g_ears3"]
- pref.b_ears3 = save_data["b_ears3"]
pref.ear_secondary_style = save_data["ear_secondary_style"]
pref.ear_secondary_colors = save_data["ear_secondary_colors"]
pref.tail_style = save_data["tail_style"]
- pref.r_tail = save_data["r_tail"]
- pref.g_tail = save_data["g_tail"]
- pref.b_tail = save_data["b_tail"]
- pref.r_tail2 = save_data["r_tail2"]
- pref.g_tail2 = save_data["g_tail2"]
- pref.b_tail2 = save_data["b_tail2"]
- pref.r_tail3 = save_data["r_tail3"]
- pref.g_tail3 = save_data["g_tail3"]
- pref.b_tail3 = save_data["b_tail3"]
pref.wing_style = save_data["wing_style"]
- pref.r_wing = save_data["r_wing"]
- pref.g_wing = save_data["g_wing"]
- pref.b_wing = save_data["b_wing"]
- pref.r_wing2 = save_data["r_wing2"]
- pref.g_wing2 = save_data["g_wing2"]
- pref.b_wing2 = save_data["b_wing2"]
- pref.r_wing3 = save_data["r_wing3"]
- pref.g_wing3 = save_data["g_wing3"]
- pref.b_wing3 = save_data["b_wing3"]
pref.digitigrade = save_data["digitigrade"]
/datum/category_item/player_setup_item/general/body/save_character(list/save_data)
save_data["species"] = pref.species
- save_data["hair_red"] = pref.r_hair
- save_data["hair_green"] = pref.g_hair
- save_data["hair_blue"] = pref.b_hair
- save_data["grad_red"] = pref.r_grad
- save_data["grad_green"] = pref.g_grad
- save_data["grad_blue"] = pref.b_grad
- save_data["facial_red"] = pref.r_facial
- save_data["facial_green"] = pref.g_facial
- save_data["facial_blue"] = pref.b_facial
save_data["skin_tone"] = pref.s_tone
- save_data["skin_red"] = pref.r_skin
- save_data["skin_green"] = pref.g_skin
- save_data["skin_blue"] = pref.b_skin
save_data["hair_style_name"] = pref.h_style
save_data["facial_style_name"] = pref.f_style
save_data["grad_style_name"] = pref.grad_style
- save_data["eyes_red"] = pref.r_eyes
- save_data["eyes_green"] = pref.g_eyes
- save_data["eyes_blue"] = pref.b_eyes
save_data["b_type"] = pref.b_type
save_data["disabilities"] = pref.disabilities
save_data["organ_data"] = check_list_copy(pref.organ_data)
@@ -206,68 +119,23 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
body_markings[i][j] = check_list_copy(body_markings[i][j])
save_data["body_markings"] = body_markings
save_data["synth_color"] = pref.synth_color
- save_data["synth_red"] = pref.r_synth
- save_data["synth_green"] = pref.g_synth
- save_data["synth_blue"] = pref.b_synth
save_data["synth_markings"] = pref.synth_markings
save_data["bgstate"] = pref.bgstate
save_data["body_descriptors"] = check_list_copy(pref.body_descriptors)
save_data["ear_style"] = pref.ear_style
- save_data["r_ears"] = pref.r_ears
- save_data["g_ears"] = pref.g_ears
- save_data["b_ears"] = pref.b_ears
- save_data["r_ears2"] = pref.r_ears2
- save_data["g_ears2"] = pref.g_ears2
- save_data["b_ears2"] = pref.b_ears2
- save_data["r_ears3"] = pref.r_ears3
- save_data["g_ears3"] = pref.g_ears3
- save_data["b_ears3"] = pref.b_ears3
save_data["ear_secondary_style"] = pref.ear_secondary_style
save_data["ear_secondary_colors"] = pref.ear_secondary_colors
save_data["tail_style"] = pref.tail_style
- save_data["r_tail"] = pref.r_tail
- save_data["g_tail"] = pref.g_tail
- save_data["b_tail"] = pref.b_tail
- save_data["r_tail2"] = pref.r_tail2
- save_data["g_tail2"] = pref.g_tail2
- save_data["b_tail2"] = pref.b_tail2
- save_data["r_tail3"] = pref.r_tail3
- save_data["g_tail3"] = pref.g_tail3
- save_data["b_tail3"] = pref.b_tail3
save_data["wing_style"] = pref.wing_style
- save_data["r_wing"] = pref.r_wing
- save_data["g_wing"] = pref.g_wing
- save_data["b_wing"] = pref.b_wing
- save_data["r_wing2"] = pref.r_wing2
- save_data["g_wing2"] = pref.g_wing2
- save_data["b_wing2"] = pref.b_wing2
- save_data["r_wing3"] = pref.r_wing3
- save_data["g_wing3"] = pref.g_wing3
- save_data["b_wing3"] = pref.b_wing3
save_data["digitigrade"] = pref.digitigrade
/datum/category_item/player_setup_item/general/body/sanitize_character()
if(!pref.species || !(pref.species in GLOB.playable_species))
pref.species = SPECIES_HUMAN
- pref.r_hair = sanitize_integer(pref.r_hair, 0, 255, initial(pref.r_hair))
- pref.g_hair = sanitize_integer(pref.g_hair, 0, 255, initial(pref.g_hair))
- pref.b_hair = sanitize_integer(pref.b_hair, 0, 255, initial(pref.b_hair))
- pref.r_grad = sanitize_integer(pref.r_grad, 0, 255, initial(pref.r_grad))
- pref.g_grad = sanitize_integer(pref.g_grad, 0, 255, initial(pref.g_grad))
- pref.b_grad = sanitize_integer(pref.b_grad, 0, 255, initial(pref.b_grad))
- pref.r_facial = sanitize_integer(pref.r_facial, 0, 255, initial(pref.r_facial))
- pref.g_facial = sanitize_integer(pref.g_facial, 0, 255, initial(pref.g_facial))
- pref.b_facial = sanitize_integer(pref.b_facial, 0, 255, initial(pref.b_facial))
pref.s_tone = sanitize_integer(pref.s_tone, -185, 34, initial(pref.s_tone))
- pref.r_skin = sanitize_integer(pref.r_skin, 0, 255, initial(pref.r_skin))
- pref.g_skin = sanitize_integer(pref.g_skin, 0, 255, initial(pref.g_skin))
- pref.b_skin = sanitize_integer(pref.b_skin, 0, 255, initial(pref.b_skin))
pref.h_style = sanitize_inlist(pref.h_style, hair_styles_list, initial(pref.h_style))
pref.f_style = sanitize_inlist(pref.f_style, facial_hair_styles_list, initial(pref.f_style))
pref.grad_style = sanitize_inlist(pref.grad_style, GLOB.hair_gradients, initial(pref.grad_style))
- pref.r_eyes = sanitize_integer(pref.r_eyes, 0, 255, initial(pref.r_eyes))
- pref.g_eyes = sanitize_integer(pref.g_eyes, 0, 255, initial(pref.g_eyes))
- pref.b_eyes = sanitize_integer(pref.b_eyes, 0, 255, initial(pref.b_eyes))
pref.b_type = sanitize_text(pref.b_type, initial(pref.b_type))
pref.disabilities = sanitize_integer(pref.disabilities, 0, 65535, initial(pref.disabilities))
@@ -282,16 +150,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options))
pref.bgstate = "000"
- pref.r_ears = sanitize_integer(pref.r_ears, 0, 255, initial(pref.r_ears))
- pref.g_ears = sanitize_integer(pref.g_ears, 0, 255, initial(pref.g_ears))
- pref.b_ears = sanitize_integer(pref.b_ears, 0, 255, initial(pref.b_ears))
- pref.r_ears2 = sanitize_integer(pref.r_ears2, 0, 255, initial(pref.r_ears2))
- pref.g_ears2 = sanitize_integer(pref.g_ears2, 0, 255, initial(pref.g_ears2))
- pref.b_ears2 = sanitize_integer(pref.b_ears2, 0, 255, initial(pref.b_ears2))
- pref.r_ears3 = sanitize_integer(pref.r_ears3, 0, 255, initial(pref.r_ears3))
- pref.g_ears3 = sanitize_integer(pref.g_ears3, 0, 255, initial(pref.g_ears3))
- pref.b_ears3 = sanitize_integer(pref.b_ears3, 0, 255, initial(pref.b_ears3))
-
// sanitize secondary ears
pref.ear_secondary_colors = SANITIZE_LIST(pref.ear_secondary_colors)
if(length(pref.ear_secondary_colors) > length(GLOB.fancy_sprite_accessory_color_channel_names))
@@ -299,24 +157,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
for(var/i in 1 to length(pref.ear_secondary_colors))
pref.ear_secondary_colors[i] = sanitize_hexcolor(pref.ear_secondary_colors[i], "#ffffff")
- pref.r_tail = sanitize_integer(pref.r_tail, 0, 255, initial(pref.r_tail))
- pref.g_tail = sanitize_integer(pref.g_tail, 0, 255, initial(pref.g_tail))
- pref.b_tail = sanitize_integer(pref.b_tail, 0, 255, initial(pref.b_tail))
- pref.r_tail2 = sanitize_integer(pref.r_tail2, 0, 255, initial(pref.r_tail2))
- pref.g_tail2 = sanitize_integer(pref.g_tail2, 0, 255, initial(pref.g_tail2))
- pref.b_tail2 = sanitize_integer(pref.b_tail2, 0, 255, initial(pref.b_tail2))
- pref.r_tail3 = sanitize_integer(pref.r_tail3, 0, 255, initial(pref.r_tail3))
- pref.g_tail3 = sanitize_integer(pref.g_tail3, 0, 255, initial(pref.g_tail3))
- pref.b_tail3 = sanitize_integer(pref.b_tail3, 0, 255, initial(pref.b_tail3))
- pref.r_wing = sanitize_integer(pref.r_wing, 0, 255, initial(pref.r_wing))
- pref.g_wing = sanitize_integer(pref.g_wing, 0, 255, initial(pref.g_wing))
- pref.b_wing = sanitize_integer(pref.b_wing, 0, 255, initial(pref.b_wing))
- pref.r_wing2 = sanitize_integer(pref.r_wing2, 0, 255, initial(pref.r_wing2))
- pref.g_wing2 = sanitize_integer(pref.g_wing2, 0, 255, initial(pref.g_wing2))
- pref.b_wing2 = sanitize_integer(pref.b_wing2, 0, 255, initial(pref.b_wing2))
- pref.r_wing3 = sanitize_integer(pref.r_wing3, 0, 255, initial(pref.r_wing3))
- pref.g_wing3 = sanitize_integer(pref.g_wing3, 0, 255, initial(pref.g_wing3))
- pref.b_wing3 = sanitize_integer(pref.b_wing3, 0, 255, initial(pref.b_wing3))
pref.digitigrade = sanitize_integer(pref.digitigrade, 0, 1, initial(pref.digitigrade))
pref.sanitize_body_styles()
@@ -324,32 +164,14 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character)
// Copy basic values
- character.r_eyes = pref.r_eyes
- character.g_eyes = pref.g_eyes
- character.b_eyes = pref.b_eyes
character.h_style = pref.h_style
- character.r_hair = pref.r_hair
- character.g_hair = pref.g_hair
- character.b_hair = pref.b_hair
- character.r_grad = pref.r_grad
- character.g_grad = pref.g_grad
- character.b_grad = pref.b_grad
character.f_style = pref.f_style
- character.r_facial = pref.r_facial
- character.g_facial = pref.g_facial
- character.b_facial = pref.b_facial
- character.r_skin = pref.r_skin
- character.g_skin = pref.g_skin
- character.b_skin = pref.b_skin
character.s_tone = pref.s_tone
character.h_style = pref.h_style
character.f_style = pref.f_style
character.grad_style= pref.grad_style
character.b_type = pref.b_type
character.synth_color = pref.synth_color
- character.r_synth = pref.r_synth
- character.g_synth = pref.g_synth
- character.b_synth = pref.b_synth
character.synth_markings = pref.synth_markings
if(character.species.digi_allowed)
character.digitigrade = pref.digitigrade
@@ -363,15 +185,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/list/ear_styles = pref.get_available_styles(global.ear_styles_list)
character.ear_style = ear_styles[pref.ear_style]
- character.r_ears = pref.r_ears
- character.b_ears = pref.b_ears
- character.g_ears = pref.g_ears
- character.r_ears2 = pref.r_ears2
- character.b_ears2 = pref.b_ears2
- character.g_ears2 = pref.g_ears2
- character.r_ears3 = pref.r_ears3
- character.b_ears3 = pref.b_ears3
- character.g_ears3 = pref.g_ears3
// apply secondary ears; sanitize again to prevent runtimes in rendering
character.ear_secondary_style = ear_styles[pref.ear_secondary_style]
@@ -379,27 +192,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/list/tail_styles = pref.get_available_styles(global.tail_styles_list)
character.tail_style = tail_styles[pref.tail_style]
- character.r_tail = pref.r_tail
- character.b_tail = pref.b_tail
- character.g_tail = pref.g_tail
- character.r_tail2 = pref.r_tail2
- character.b_tail2 = pref.b_tail2
- character.g_tail2 = pref.g_tail2
- character.r_tail3 = pref.r_tail3
- character.b_tail3 = pref.b_tail3
- character.g_tail3 = pref.g_tail3
var/list/wing_styles = pref.get_available_styles(global.wing_styles_list)
character.wing_style = wing_styles[pref.wing_style]
- character.r_wing = pref.r_wing
- character.b_wing = pref.b_wing
- character.g_wing = pref.g_wing
- character.r_wing2 = pref.r_wing2
- character.b_wing2 = pref.b_wing2
- character.g_wing2 = pref.g_wing2
- character.r_wing3 = pref.r_wing3
- character.b_wing3 = pref.b_wing3
- character.g_wing3 = pref.g_wing3
character.set_gender(pref.biological_gender)
@@ -613,25 +408,25 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
. += span_bold("Hair") + "
"
if(has_flag(mob_species, HAS_HAIR_COLOR))
- . += "Change Color [color_square(pref.r_hair, pref.g_hair, pref.b_hair)] "
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/hair_color))] "
. += " Style: < > [pref.h_style]
" //The < & > in this line is correct-- those extra characters are the arrows you click to switch between styles.
. += span_bold("Gradient") + "
"
- . += "Change Color [color_square(pref.r_grad, pref.g_grad, pref.b_grad)] "
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/grad_color))] "
. += " Style: < > [pref.grad_style]
"
. += "
Facial
"
if(has_flag(mob_species, HAS_HAIR_COLOR))
- . += "Change Color [color_square(pref.r_facial, pref.g_facial, pref.b_facial)] "
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/facial_color))] "
. += " Style: < > [pref.f_style]
" //Same as above with the extra > & < characters
if(has_flag(mob_species, HAS_EYE_COLOR))
. += "
Eyes
"
- . += "Change Color [color_square(pref.r_eyes, pref.g_eyes, pref.b_eyes)]
"
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/eyes_color))]
"
if(has_flag(mob_species, HAS_SKIN_COLOR))
. += "
Body Color
"
- . += "Change Color [color_square(pref.r_skin, pref.g_skin, pref.b_skin)]
"
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/skin_color))]
"
if(mob_species.digi_allowed)
. += "
Digitigrade?: [pref.digitigrade ? "Yes" : "No"]
"
@@ -644,11 +439,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(istype(ear))
. += " Style: [ear.name]
"
if(ear.do_colouration)
- . += "Change Color [color_square(pref.r_ears, pref.g_ears, pref.b_ears)]
"
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/ears_color1))]
"
if(ear.extra_overlay)
- . += "Change Secondary Color [color_square(pref.r_ears2, pref.g_ears2, pref.b_ears2)]
"
+ . += "Change Secondary Color [color_square(hex = pref.read_preference(/datum/preference/color/human/ears_color2))]
"
if(ear.extra_overlay2)
- . += "Change Tertiary Color [color_square(pref.r_ears3, pref.g_ears3, pref.b_ears3)]
"
+ . += "Change Tertiary Color [color_square(hex = pref.read_preference(/datum/preference/color/human/ears_color3))]
"
else
. += " Style: Select
"
@@ -667,11 +462,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(istype(tail))
. += " Style: [tail.name]
"
if(tail.do_colouration)
- . += "Change Color [color_square(pref.r_tail, pref.g_tail, pref.b_tail)]
"
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/tail_color1))]
"
if(tail.extra_overlay)
- . += "Change Secondary Color [color_square(pref.r_tail2, pref.g_tail2, pref.b_tail2)]
"
+ . += "Change Secondary Color [color_square(hex = pref.read_preference(/datum/preference/color/human/tail_color2))]
"
if(tail.extra_overlay2)
- . += "Change Tertiary Color [color_square(pref.r_tail3, pref.g_tail3, pref.b_tail3)]
"
+ . += "Change Tertiary Color [color_square(hex = pref.read_preference(/datum/preference/color/human/tail_color3))]
"
else
. += " Style: Select
"
@@ -681,11 +476,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(istype(wings))
. += " Style: [wings.name]
"
if(wings.do_colouration)
- . += "Change Color [color_square(pref.r_wing, pref.g_wing, pref.b_wing)]
"
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/wing_color1))]
"
if(wings.extra_overlay)
- . += "Change Secondary Color [color_square(pref.r_wing2, pref.g_wing2, pref.b_wing2)]
"
+ . += "Change Secondary Color [color_square(hex = pref.read_preference(/datum/preference/color/human/wing_color2))]
"
if(wings.extra_overlay2)
- . += "Change Secondary Color [color_square(pref.r_wing3, pref.g_wing3, pref.b_wing3)]
"
+ . += "Change Secondary Color [color_square(hex = pref.read_preference(/datum/preference/color/human/wing_color3))]
"
else
. += " Style: Select
"
@@ -699,7 +494,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
. += span_bold("Allow Synth markings:") + " [pref.synth_markings ? "Yes" : "No"]
"
. += span_bold("Allow Synth color:") + " [pref.synth_color ? "Yes" : "No"]
"
if(pref.synth_color)
- . += "Change Color [color_square(pref.r_synth, pref.g_synth, pref.b_synth)]"
+ . += "Change Color [color_square(hex = pref.read_preference(/datum/preference/color/human/synth_color))]"
. = jointext(.,null)
@@ -780,9 +575,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.f_style = facial_hair_styles_list["Shaved"]
//reset hair colour and skin colour
- pref.r_hair = 0//hex2num(copytext(new_hair, 2, 4))
- pref.g_hair = 0//hex2num(copytext(new_hair, 4, 6))
- pref.b_hair = 0//hex2num(copytext(new_hair, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/hair_color, "#000000")
pref.s_tone = -75
reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case.
@@ -792,7 +585,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/min_age = get_min_age()
var/max_age = get_max_age()
- pref.age = max(min(pref.age, max_age), min_age)
+ pref.update_preference_by_type(/datum/preference/numeric/human/age, max(min(pref.read_preference(/datum/preference/numeric/human/age), max_age), min_age))
pref.blood_color = setting_species.blood_color // VOREstation edit
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -800,21 +593,17 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["hair_color"])
if(!has_flag(mob_species, HAS_HAIR_COLOR))
return TOPIC_NOACTION
- var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference", rgb(pref.r_hair, pref.g_hair, pref.b_hair)) as color|null
+ var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/hair_color)) as color|null
if(new_hair && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
- pref.r_hair = hex2num(copytext(new_hair, 2, 4))
- pref.g_hair = hex2num(copytext(new_hair, 4, 6))
- pref.b_hair = hex2num(copytext(new_hair, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/hair_color, new_hair)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["grad_color"])
if(!has_flag(mob_species, HAS_HAIR_COLOR))
return TOPIC_NOACTION
- var/new_grad = input(user, "Choose your character's secondary hair color:", "Character Preference", rgb(pref.r_grad, pref.g_grad, pref.b_grad)) as color|null
+ var/new_grad = input(user, "Choose your character's secondary hair color:", "Character Preference", pref.read_preference(/datum/preference/color/human/grad_color)) as color|null
if(new_grad && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
- pref.r_grad = hex2num(copytext(new_grad, 2, 4))
- pref.g_grad = hex2num(copytext(new_grad, 4, 6))
- pref.b_grad = hex2num(copytext(new_grad, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/grad_color, new_grad)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["hair_style"])
@@ -858,11 +647,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["facial_color"])
if(!has_flag(mob_species, HAS_HAIR_COLOR))
return TOPIC_NOACTION
- var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", rgb(pref.r_facial, pref.g_facial, pref.b_facial)) as color|null
+ var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/facial_color)) as color|null
if(new_facial && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
- pref.r_facial = hex2num(copytext(new_facial, 2, 4))
- pref.g_facial = hex2num(copytext(new_facial, 4, 6))
- pref.b_facial = hex2num(copytext(new_facial, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/facial_color, new_facial)
return TOPIC_REFRESH_UPDATE_PREVIEW
if(href_list["digitigrade"])
@@ -873,11 +660,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["eye_color"])
if(!has_flag(mob_species, HAS_EYE_COLOR))
return TOPIC_NOACTION
- var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference", rgb(pref.r_eyes, pref.g_eyes, pref.b_eyes)) as color|null
+ var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/eyes_color)) as color|null
if(new_eyes && has_flag(mob_species, HAS_EYE_COLOR) && CanUseTopic(user))
- pref.r_eyes = hex2num(copytext(new_eyes, 2, 4))
- pref.g_eyes = hex2num(copytext(new_eyes, 4, 6))
- pref.b_eyes = hex2num(copytext(new_eyes, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/eyes_color, new_eyes)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["skin_tone"])
@@ -891,11 +676,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["skin_color"])
if(!has_flag(mob_species, HAS_SKIN_COLOR))
return TOPIC_NOACTION
- var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference", rgb(pref.r_skin, pref.g_skin, pref.b_skin)) as color|null
+ var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference", pref.read_preference(/datum/preference/color/human/skin_color)) as color|null
if(new_skin && has_flag(mob_species, HAS_SKIN_COLOR) && CanUseTopic(user))
- pref.r_skin = hex2num(copytext(new_skin, 2, 4))
- pref.g_skin = hex2num(copytext(new_skin, 4, 6))
- pref.b_skin = hex2num(copytext(new_skin, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/skin_color, new_skin)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["facial_style"])
@@ -1253,11 +1036,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["synth2_color"])
- var/new_color = input(user, "Choose your character's synth colour: ", "Character Preference", rgb(pref.r_synth, pref.g_synth, pref.b_synth)) as color|null
+ var/new_color = input(user, "Choose your character's synth colour: ", "Character Preference", pref.read_preference(/datum/preference/color/human/synth_color)) as color|null
if(new_color && CanUseTopic(user))
- pref.r_synth = hex2num(copytext(new_color, 2, 4))
- pref.g_synth = hex2num(copytext(new_color, 4, 6))
- pref.b_synth = hex2num(copytext(new_color, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/synth_color, new_color)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["synth_markings"])
@@ -1277,29 +1058,23 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["ear_color"])
var/new_earc = input(user, "Choose your character's ear colour:", "Character Preference",
- rgb(pref.r_ears, pref.g_ears, pref.b_ears)) as color|null
+ pref.read_preference(/datum/preference/color/human/ears_color1)) as color|null
if(new_earc)
- pref.r_ears = hex2num(copytext(new_earc, 2, 4))
- pref.g_ears = hex2num(copytext(new_earc, 4, 6))
- pref.b_ears = hex2num(copytext(new_earc, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/ears_color1, new_earc)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["ear_color2"])
var/new_earc2 = input(user, "Choose your character's ear colour:", "Character Preference",
- rgb(pref.r_ears2, pref.g_ears2, pref.b_ears2)) as color|null
+ pref.read_preference(/datum/preference/color/human/ears_color2)) as color|null
if(new_earc2)
- pref.r_ears2 = hex2num(copytext(new_earc2, 2, 4))
- pref.g_ears2 = hex2num(copytext(new_earc2, 4, 6))
- pref.b_ears2 = hex2num(copytext(new_earc2, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/ears_color2, new_earc2)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["ear_color3"])
var/new_earc3 = input(user, "Choose your character's tertiary ear colour:", "Character Preference",
- rgb(pref.r_ears3, pref.g_ears3, pref.b_ears3)) as color|null
+ pref.read_preference(/datum/preference/color/human/ears_color3)) as color|null
if(new_earc3)
- pref.r_ears3 = hex2num(copytext(new_earc3, 2, 4))
- pref.g_ears3 = hex2num(copytext(new_earc3, 4, 6))
- pref.b_ears3 = hex2num(copytext(new_earc3, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/ears_color3, new_earc3)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["ear_secondary_style"])
@@ -1336,29 +1111,23 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["tail_color"])
var/new_tailc = input(user, "Choose your character's tail/taur colour:", "Character Preference",
- rgb(pref.r_tail, pref.g_tail, pref.b_tail)) as color|null
+ pref.read_preference(/datum/preference/color/human/tail_color1)) as color|null
if(new_tailc)
- pref.r_tail = hex2num(copytext(new_tailc, 2, 4))
- pref.g_tail = hex2num(copytext(new_tailc, 4, 6))
- pref.b_tail = hex2num(copytext(new_tailc, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/tail_color1, new_tailc)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["tail_color2"])
var/new_tailc2 = input(user, "Choose your character's secondary tail/taur colour:", "Character Preference",
- rgb(pref.r_tail2, pref.g_tail2, pref.b_tail2)) as color|null
+ pref.read_preference(/datum/preference/color/human/tail_color2)) as color|null
if(new_tailc2)
- pref.r_tail2 = hex2num(copytext(new_tailc2, 2, 4))
- pref.g_tail2 = hex2num(copytext(new_tailc2, 4, 6))
- pref.b_tail2 = hex2num(copytext(new_tailc2, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/tail_color2, new_tailc2)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["tail_color3"])
var/new_tailc3 = input(user, "Choose your character's tertiary tail/taur colour:", "Character Preference",
- rgb(pref.r_tail3, pref.g_tail3, pref.b_tail3)) as color|null
+ pref.read_preference(/datum/preference/color/human/tail_color3)) as color|null
if(new_tailc3)
- pref.r_tail3 = hex2num(copytext(new_tailc3, 2, 4))
- pref.g_tail3 = hex2num(copytext(new_tailc3, 4, 6))
- pref.b_tail3 = hex2num(copytext(new_tailc3, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/tail_color3, new_tailc3)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["wing_style"])
@@ -1370,29 +1139,23 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else if(href_list["wing_color"])
var/new_wingc = input(user, "Choose your character's wing colour:", "Character Preference",
- rgb(pref.r_wing, pref.g_wing, pref.b_wing)) as color|null
+ pref.read_preference(/datum/preference/color/human/wing_color1)) as color|null
if(new_wingc)
- pref.r_wing = hex2num(copytext(new_wingc, 2, 4))
- pref.g_wing = hex2num(copytext(new_wingc, 4, 6))
- pref.b_wing = hex2num(copytext(new_wingc, 6, 8))
+ pref.update_preference_by_type(/datum/preference/color/human/wing_color1, new_wingc)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["wing_color2"])
- var/new_wingc2 = input(user, "Choose your character's secondary wing colour:", "Character Preference",
- rgb(pref.r_wing2, pref.g_wing2, pref.b_wing2)) as color|null
- if(new_wingc2)
- pref.r_wing2 = hex2num(copytext(new_wingc2, 2, 4))
- pref.g_wing2 = hex2num(copytext(new_wingc2, 4, 6))
- pref.b_wing2 = hex2num(copytext(new_wingc2, 6, 8))
+ var/new_wingc = input(user, "Choose your character's secondary wing colour:", "Character Preference",
+ pref.read_preference(/datum/preference/color/human/wing_color2)) as color|null
+ if(new_wingc)
+ pref.update_preference_by_type(/datum/preference/color/human/wing_color2, new_wingc)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["wing_color3"])
- var/new_wingc3 = input(user, "Choose your character's tertiary wing colour:", "Character Preference",
- rgb(pref.r_wing3, pref.g_wing3, pref.b_wing3)) as color|null
- if(new_wingc3)
- pref.r_wing3 = hex2num(copytext(new_wingc3, 2, 4))
- pref.g_wing3 = hex2num(copytext(new_wingc3, 4, 6))
- pref.b_wing3 = hex2num(copytext(new_wingc3, 6, 8))
+ var/new_wingc = input(user, "Choose your character's tertiary wing colour:", "Character Preference",
+ pref.read_preference(/datum/preference/color/human/wing_color3)) as color|null
+ if(new_wingc)
+ pref.update_preference_by_type(/datum/preference/color/human/wing_color3, new_wingc)
return TOPIC_REFRESH_UPDATE_PREVIEW
return ..()
diff --git a/code/modules/client/preference_setup/general/06_flavor.dm b/code/modules/client/preference_setup/general/06_flavor.dm
index 4690dc4deb..5754da7a4a 100644
--- a/code/modules/client/preference_setup/general/06_flavor.dm
+++ b/code/modules/client/preference_setup/general/06_flavor.dm
@@ -48,9 +48,6 @@
character.flavor_texts["hands"] = pref.flavor_texts["hands"]
character.flavor_texts["legs"] = pref.flavor_texts["legs"]
character.flavor_texts["feet"] = pref.flavor_texts["feet"]
- character.ooc_notes = pref.metadata //VOREStation Add
- character.ooc_notes_likes = pref.metadata_likes
- character.ooc_notes_dislikes = pref.metadata_dislikes
character.custom_link = pref.custom_link
/datum/category_item/player_setup_item/general/flavor/content(var/mob/user)
diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm
deleted file mode 100644
index 1d67d38661..0000000000
--- a/code/modules/client/preference_setup/global/01_ui.dm
+++ /dev/null
@@ -1,182 +0,0 @@
-/datum/category_item/player_setup_item/player_global/ui
- name = "UI"
- sort_order = 1
-
-/datum/category_item/player_setup_item/player_global/ui/load_preferences(datum/json_savefile/savefile)
- pref.UI_style = savefile.get_entry("UI_style")
- pref.UI_style_color = savefile.get_entry("UI_style_color")
- pref.UI_style_alpha = savefile.get_entry("UI_style_alpha")
- pref.ooccolor = savefile.get_entry("ooccolor")
- pref.tooltipstyle = savefile.get_entry("tooltipstyle")
- pref.client_fps = savefile.get_entry("client_fps")
- pref.ambience_freq = savefile.get_entry("ambience_freq")
- pref.ambience_chance = savefile.get_entry("ambience_chance")
- pref.tgui_fancy = savefile.get_entry("tgui_fancy")
- pref.tgui_lock = savefile.get_entry("tgui_lock")
- pref.tgui_input_mode = savefile.get_entry("tgui_input_mode")
- pref.tgui_large_buttons = savefile.get_entry("tgui_large_buttons")
- pref.tgui_swapped_buttons = savefile.get_entry("tgui_swapped_buttons")
- pref.obfuscate_key = savefile.get_entry("obfuscate_key")
- pref.obfuscate_job = savefile.get_entry("obfuscate_job")
- pref.chat_timestamp = savefile.get_entry("chat_timestamp")
-
-/datum/category_item/player_setup_item/player_global/ui/save_preferences(datum/json_savefile/savefile)
- savefile.set_entry("UI_style", pref.UI_style)
- savefile.set_entry("UI_style_color", pref.UI_style_color)
- savefile.set_entry("UI_style_alpha", pref.UI_style_alpha)
- savefile.set_entry("ooccolor", pref.ooccolor)
- savefile.set_entry("tooltipstyle", pref.tooltipstyle)
- savefile.set_entry("client_fps", pref.client_fps)
- savefile.set_entry("ambience_freq", pref.ambience_freq)
- savefile.set_entry("ambience_chance", pref.ambience_chance)
- savefile.set_entry("tgui_fancy", pref.tgui_fancy)
- savefile.set_entry("tgui_lock", pref.tgui_lock)
- savefile.set_entry("tgui_input_mode", pref.tgui_input_mode)
- savefile.set_entry("tgui_large_buttons", pref.tgui_large_buttons)
- savefile.set_entry("tgui_swapped_buttons", pref.tgui_swapped_buttons)
- savefile.set_entry("obfuscate_key", pref.obfuscate_key)
- savefile.set_entry("obfuscate_job", pref.obfuscate_job)
- savefile.set_entry("chat_timestamp", pref.chat_timestamp)
-
-/datum/category_item/player_setup_item/player_global/ui/sanitize_preferences()
- pref.UI_style = sanitize_inlist(pref.UI_style, all_ui_styles, initial(pref.UI_style))
- pref.UI_style_color = sanitize_hexcolor(pref.UI_style_color, initial(pref.UI_style_color))
- pref.UI_style_alpha = sanitize_integer(pref.UI_style_alpha, 0, 255, initial(pref.UI_style_alpha))
- pref.ooccolor = sanitize_hexcolor(pref.ooccolor, initial(pref.ooccolor))
- pref.tooltipstyle = sanitize_inlist(pref.tooltipstyle, all_tooltip_styles, initial(pref.tooltipstyle))
- pref.client_fps = sanitize_integer(pref.client_fps, 0, MAX_CLIENT_FPS, initial(pref.client_fps))
- pref.ambience_freq = sanitize_integer(pref.ambience_freq, 0, 60, initial(pref.ambience_freq)) // No more than once per hour.
- pref.ambience_chance = sanitize_integer(pref.ambience_chance, 0, 100, initial(pref.ambience_chance)) // 0-100 range.
- pref.tgui_fancy = sanitize_integer(pref.tgui_fancy, 0, 1, initial(pref.tgui_fancy))
- pref.tgui_lock = sanitize_integer(pref.tgui_lock, 0, 1, initial(pref.tgui_lock))
- pref.tgui_input_mode = sanitize_integer(pref.tgui_input_mode, 0, 1, initial(pref.tgui_input_mode))
- pref.tgui_large_buttons = sanitize_integer(pref.tgui_large_buttons, 0, 1, initial(pref.tgui_large_buttons))
- pref.tgui_swapped_buttons = sanitize_integer(pref.tgui_swapped_buttons, 0, 1, initial(pref.tgui_swapped_buttons))
- pref.obfuscate_key = sanitize_integer(pref.obfuscate_key, 0, 1, initial(pref.obfuscate_key))
- pref.obfuscate_job = sanitize_integer(pref.obfuscate_job, 0, 1, initial(pref.obfuscate_job))
- pref.chat_timestamp = sanitize_integer(pref.chat_timestamp, 0, 1, initial(pref.chat_timestamp))
-
-/datum/category_item/player_setup_item/player_global/ui/content(var/mob/user)
- . = span_bold("UI Style:") + " [pref.UI_style]
"
- . += span_bold("Custom UI") + " (recommended for White UI):
"
- . += "-Color: [pref.UI_style_color] [color_square(hex = pref.UI_style_color)] reset
"
- . += "-Alpha(transparency): [pref.UI_style_alpha] reset
"
- . += span_bold("Tooltip Style:") + " [pref.tooltipstyle]
"
- . += span_bold("Client FPS:") + " [pref.client_fps]
"
- . += span_bold("Random Ambience Frequency:") + " [pref.ambience_freq]
"
- . += span_bold("Ambience Chance:") + " [pref.ambience_chance]
"
- . += span_bold("TGUI Window Mode:") + " [(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
"
- . += span_bold("TGUI Window Placement:") + " [(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]
"
- . += span_bold("TGUI Input Framework:") + " [(pref.tgui_input_mode) ? "Enabled" : "Disabled (default)"]
"
- . += span_bold("TGUI Large Buttons:") + " [(pref.tgui_large_buttons) ? "Enabled (default)" : "Disabled"]
"
- . += span_bold("TGUI Swapped Buttons:") + " [(pref.tgui_swapped_buttons) ? "Enabled" : "Disabled (default)"]
"
- . += span_bold("Obfuscate Ckey:") + " [(pref.obfuscate_key) ? "Enabled" : "Disabled (default)"]
"
- . += span_bold("Obfuscate Job:") + " [(pref.obfuscate_job) ? "Enabled" : "Disabled (default)"]
"
- . += span_bold("Chat Timestamps:") + " [(pref.chat_timestamp) ? "Enabled" : "Disabled (default)"]
"
- if(can_select_ooc_color(user))
- . += span_bold("OOC Color:")
- if(pref.ooccolor == initial(pref.ooccolor))
- . += "Using Default
"
- else
- . += "[pref.ooccolor] [color_square(hex = pref.ooccolor)]reset
"
-
-/datum/category_item/player_setup_item/player_global/ui/OnTopic(var/href,var/list/href_list, var/mob/user)
- if(href_list["select_style"])
- var/UI_style_new = tgui_input_list(user, "Choose UI style.", "Character Preference", all_ui_styles, pref.UI_style)
- if(!UI_style_new || !CanUseTopic(user)) return TOPIC_NOACTION
- pref.UI_style = UI_style_new
- return TOPIC_REFRESH
-
- else if(href_list["select_color"])
- var/UI_style_color_new = input(user, "Choose UI color, dark colors are not recommended!", "Global Preference", pref.UI_style_color) as color|null
- if(isnull(UI_style_color_new) || !CanUseTopic(user)) return TOPIC_NOACTION
- pref.UI_style_color = UI_style_color_new
- return TOPIC_REFRESH
-
- else if(href_list["select_alpha"])
- var/UI_style_alpha_new = tgui_input_number(user, "Select UI alpha (transparency) level, between 50 and 255.", "Global Preference", pref.UI_style_alpha, 255, 50)
- if(isnull(UI_style_alpha_new) || (UI_style_alpha_new < 50 || UI_style_alpha_new > 255) || !CanUseTopic(user)) return TOPIC_NOACTION
- pref.UI_style_alpha = UI_style_alpha_new
- return TOPIC_REFRESH
-
- else if(href_list["select_ooc_color"])
- var/new_ooccolor = input(user, "Choose OOC color:", "Global Preference") as color|null
- if(new_ooccolor && can_select_ooc_color(user) && CanUseTopic(user))
- pref.ooccolor = new_ooccolor
- return TOPIC_REFRESH
-
- else if(href_list["select_tooltip_style"])
- var/tooltip_style_new = tgui_input_list(user, "Choose tooltip style.", "Global Preference", all_tooltip_styles, pref.tooltipstyle)
- if(!tooltip_style_new || !CanUseTopic(user)) return TOPIC_NOACTION
- pref.tooltipstyle = tooltip_style_new
- return TOPIC_REFRESH
-
- else if(href_list["select_client_fps"])
- var/fps_new = tgui_input_number(user, "Input Client FPS (1-200, 0 uses server FPS)", "Global Preference", pref.client_fps, 200, 0)
- if(isnull(fps_new) || !CanUseTopic(user)) return TOPIC_NOACTION
- if(fps_new < 0 || fps_new > MAX_CLIENT_FPS) return TOPIC_NOACTION
- pref.client_fps = fps_new
- if(pref.client)
- pref.client.fps = fps_new
- return TOPIC_REFRESH
-
- else if(href_list["select_ambience_freq"])
- var/ambience_new = tgui_input_number(user, "Input how often you wish to hear ambience repeated! (1-60 MINUTES, 0 for disabled)", "Global Preference", pref.ambience_freq, 60, 0)
- if(isnull(ambience_new) || !CanUseTopic(user)) return TOPIC_NOACTION
- if(ambience_new < 0 || ambience_new > 60) return TOPIC_NOACTION
- pref.ambience_freq = ambience_new
- return TOPIC_REFRESH
-
- else if(href_list["select_ambience_chance"])
- var/ambience_chance_new = tgui_input_number(user, "Input the chance you'd like to hear ambience played to you (On area change, or by random ambience). 35 means a 35% chance to play ambience. This is a range from 0-100. 0 disables ambience playing entirely. This is also affected by Ambience Frequency.", "Global Preference", pref.ambience_freq, 100, 0)
- if(isnull(ambience_chance_new) || !CanUseTopic(user)) return TOPIC_NOACTION
- if(ambience_chance_new < 0 || ambience_chance_new > 100) return TOPIC_NOACTION
- pref.ambience_chance = ambience_chance_new
- return TOPIC_REFRESH
-
- else if(href_list["tgui_fancy"])
- pref.tgui_fancy = !pref.tgui_fancy
- return TOPIC_REFRESH
-
- else if(href_list["tgui_lock"])
- pref.tgui_lock = !pref.tgui_lock
- return TOPIC_REFRESH
-
- else if(href_list["tgui_input_mode"])
- pref.tgui_input_mode = !pref.tgui_input_mode
- return TOPIC_REFRESH
-
- else if(href_list["tgui_large_buttons"])
- pref.tgui_large_buttons = !pref.tgui_large_buttons
- return TOPIC_REFRESH
-
- else if(href_list["tgui_swapped_buttons"])
- pref.tgui_swapped_buttons = !pref.tgui_swapped_buttons
- return TOPIC_REFRESH
-
- else if(href_list["obfuscate_key"])
- pref.obfuscate_key = !pref.obfuscate_key
- return TOPIC_REFRESH
-
- else if(href_list["obfuscate_job"])
- pref.obfuscate_job = !pref.obfuscate_job
- return TOPIC_REFRESH
-
- else if(href_list["chat_timestamps"])
- pref.chat_timestamp = !pref.chat_timestamp
- return TOPIC_REFRESH
-
- else if(href_list["reset"])
- switch(href_list["reset"])
- if("ui")
- pref.UI_style_color = initial(pref.UI_style_color)
- if("alpha")
- pref.UI_style_alpha = initial(pref.UI_style_alpha)
- if("ooc")
- pref.ooccolor = initial(pref.ooccolor)
- return TOPIC_REFRESH
-
- return ..()
-
-/datum/category_item/player_setup_item/player_global/ui/proc/can_select_ooc_color(var/mob/user)
- return CONFIG_GET(flag/allow_admin_ooccolor) && check_rights(R_ADMIN|R_EVENT|R_FUN, 0, user)
diff --git a/code/modules/client/preference_setup/global/02_settings.dm b/code/modules/client/preference_setup/global/02_settings.dm
deleted file mode 100644
index 3fddd3552e..0000000000
--- a/code/modules/client/preference_setup/global/02_settings.dm
+++ /dev/null
@@ -1,20 +0,0 @@
-/datum/category_item/player_setup_item/player_global/settings
- name = "Settings"
- sort_order = 2
-
-/datum/category_item/player_setup_item/player_global/settings/load_preferences(datum/json_savefile/savefile)
- pref.lastchangelog = savefile.get_entry("lastchangelog")
- pref.lastnews = savefile.get_entry("lastnews")
- pref.lastlorenews = savefile.get_entry("lastlorenews")
- pref.default_slot = savefile.get_entry("default_slot")
-
-/datum/category_item/player_setup_item/player_global/settings/save_preferences(datum/json_savefile/savefile)
- savefile.set_entry("lastchangelog", pref.lastchangelog)
- savefile.set_entry("lastnews", pref.lastnews)
- savefile.set_entry("lastlorenews", pref.lastlorenews)
- savefile.set_entry("default_slot", pref.default_slot)
-
-/datum/category_item/player_setup_item/player_global/settings/sanitize_preferences()
- pref.lastchangelog = sanitize_text(pref.lastchangelog, initial(pref.lastchangelog))
- pref.lastnews = sanitize_text(pref.lastnews, initial(pref.lastnews))
- pref.default_slot = sanitize_integer(pref.default_slot, 1, CONFIG_GET(number/character_slots), initial(pref.default_slot))
diff --git a/code/modules/client/preference_setup/global/04_ooc.dm b/code/modules/client/preference_setup/global/04_ooc.dm
deleted file mode 100644
index 18ac5deec9..0000000000
--- a/code/modules/client/preference_setup/global/04_ooc.dm
+++ /dev/null
@@ -1,42 +0,0 @@
-/datum/category_item/player_setup_item/player_global/ooc
- name = "OOC"
- sort_order = 4
-
-/datum/category_item/player_setup_item/player_global/ooc/load_preferences(datum/json_savefile/savefile)
- pref.ignored_players = savefile.get_entry("ignored_players")
-
-
-/datum/category_item/player_setup_item/player_global/ooc/save_preferences(datum/json_savefile/savefile)
- savefile.set_entry("ignored_players", pref.ignored_players)
-
-/*
-/datum/category_item/player_setup_item/player_global/ooc/sanitize_preferences()
- if(isnull(pref.ignored_players))
- pref.ignored_players = list()
-
-/datum/category_item/player_setup_item/player_global/ooc/content(var/mob/user)
- . += span_bold("OOC:") + "
"
- . += "Ignored Players
"
- for(var/ignored_player in pref.ignored_players)
- . += "[ignored_player] (Unignore)
"
- . += "(Ignore Player)"
-
-/datum/category_item/player_setup_item/player_global/ooc/OnTopic(var/href,var/list/href_list, var/mob/user)
- if(href_list["unignore_player"])
- if(CanUseTopic(user))
- pref.ignored_players -= href_list["unignore_player"]
- return TOPIC_REFRESH
-
- if(href_list["ignore_player"])
- if(CanUseTopic(user))
- var/player_to_ignore = input(user, "Who do you want to ignore?","Ignore") as null|text
- if(player_to_ignore)
- player_to_ignore = sanitize(ckey(player_to_ignore))
- if(player_to_ignore == user.ckey)
- to_chat(user, span_notice("You can't ignore yourself."))
- return TOPIC_REFRESH
- pref.ignored_players |= player_to_ignore
- return TOPIC_REFRESH
-
- return ..()
-*/
diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm
index 493481e066..6b501f9505 100644
--- a/code/modules/client/preference_setup/occupation/occupation.dm
+++ b/code/modules/client/preference_setup/occupation/occupation.dm
@@ -151,7 +151,7 @@
if(job.is_species_banned(user.client.prefs.species, user.client.prefs.organ_data["brain"]) == TRUE)
. += "[rank]
\[THIS RACE/BRAIN TYPE CANNOT TAKE THIS ROLE.\] | "
continue
- if((job.minimum_character_age || job.min_age_by_species) && user.client && (user.client.prefs.age < job.get_min_age(user.client.prefs.species, user.client.prefs.organ_data["brain"])))
+ if((job.minimum_character_age || job.min_age_by_species) && user.client && (user.read_preference(/datum/preference/numeric/human/age) < job.get_min_age(user.client.prefs.species, user.client.prefs.organ_data["brain"])))
. += "[rank] \[MINIMUM CHARACTER AGE FOR SELECTED RACE/BRAIN TYPE: [job.get_min_age(user.client.prefs.species, user.client.prefs.organ_data["brain"])]\] | "
continue
if((pref.job_civilian_low & ASSISTANT) && job.type != /datum/job/assistant)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 32b39ec9fe..f88a4e7b84 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -15,36 +15,11 @@ var/list/preferences_datums = list()
var/last_id
//game-preferences
- var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
- var/ooccolor = "#010000" //Whatever this is set to acts as 'reset' color and is thus unusable as an actual custom color
var/be_special = 0 //Special role selection
- var/UI_style = "Midnight"
- var/UI_style_color = "#ffffff"
- var/UI_style_alpha = 255
- var/tooltipstyle = "Midnight" //Style for popup tooltips
- var/client_fps = 40
- var/ambience_freq = 5 // How often we're playing repeating ambience to a client.
- var/ambience_chance = 35 // What's the % chance we'll play ambience (in conjunction with the above frequency)
-
- var/tgui_fancy = TRUE
- var/tgui_lock = FALSE
- var/tgui_input_mode = FALSE // All the Input Boxes (Text,Number,List,Alert)
- var/tgui_large_buttons = TRUE
- var/tgui_swapped_buttons = FALSE
- var/obfuscate_key = FALSE
- var/obfuscate_job = FALSE
- var/chat_timestamp = FALSE
//character preferences
var/real_name //our character's name
- var/be_random_name = 0 //whether we are a random name every round
var/nickname //our character's nickname
- var/age = 30 //age of character
- var/bday_month = 0 //Birthday month
- var/bday_day = 0 //Birthday day
- var/last_birthday_notification = 0 //The last year we were notified about our birthday
- var/bday_announce = FALSE //Public announcement for birthdays
- var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
var/b_type = "A+" //blood type (not-chooseable)
var/blood_reagents = "default" //blood restoration reagents
var/headset = 1 //headset type
@@ -52,24 +27,9 @@ var/list/preferences_datums = list()
var/pdachoice = 1 //PDA type
var/shoe_hater = FALSE //RS ADD - if true, will spawn with no shoes
var/h_style = "Bald" //Hair type
- var/r_hair = 0 //Hair color
- var/g_hair = 0 //Hair color
- var/b_hair = 0 //Hair color
var/grad_style = "none" //Gradient style
- var/r_grad = 0 //Gradient color
- var/g_grad = 0 //Gradient color
- var/b_grad = 0 //Gradient color
var/f_style = "Shaved" //Face hair type
- var/r_facial = 0 //Face hair color
- var/g_facial = 0 //Face hair color
- var/b_facial = 0 //Face hair color
var/s_tone = -75 //Skin tone
- var/r_skin = 238 //Skin color // Vorestation edit, so color multi sprites can aren't BLACK AS THE VOID by default.
- var/g_skin = 206 //Skin color // Vorestation edit, so color multi sprites can aren't BLACK AS THE VOID by default.
- var/b_skin = 179 //Skin color // Vorestation edit, so color multi sprites can aren't BLACK AS THE VOID by default.
- var/r_eyes = 0 //Eye color
- var/g_eyes = 0 //Eye color
- var/b_eyes = 0 //Eye color
var/species = SPECIES_HUMAN //Species datum to use.
var/species_preview //Used for the species selection window.
var/list/alternate_languages = list() //Secondary language(s)
@@ -80,9 +40,6 @@ var/list/preferences_datums = list()
var/gear_slot = 1 //The current gear save slot
var/list/traits //Traits which modifier characters for better or worse (mostly worse).
var/synth_color = 0 //Lets normally uncolorable synth parts be colorable.
- var/r_synth //Used with synth_color to color synth parts that normaly can't be colored.
- var/g_synth //Same as above
- var/b_synth //Same as above
var/synth_markings = 1 //Enable/disable markings on synth parts. //VOREStation Edit - 1 by default
var/digitigrade = 0
@@ -122,6 +79,11 @@ var/list/preferences_datums = list()
//Keeps track of preferrence for not getting any wanted jobs
var/alternate_option = 1
+ //character preferences
+ var/slot_randomized //keeps track of round-to-round randomization of the character slot, prevents overwriting
+
+ var/list/randomise = list()
+
// maps each organ to either null(intact), "cyborg" or "amputated"
// will probably not be able to do this for head and torso ;)
var/list/organ_data = list()
@@ -144,14 +106,6 @@ var/list/preferences_datums = list()
var/economic_status = "Average"
- var/uplinklocation = "PDA"
-
- // OOC Metadata:
- var/metadata = ""
- var/metadata_likes = ""
- var/metadata_dislikes = ""
- var/list/ignored_players = list()
-
var/client/client = null
var/client_ckey = null
@@ -373,7 +327,7 @@ var/list/preferences_datums = list()
// This needs to happen before anything else becuase it sets some variables.
character.set_species(species)
// Special Case: This references variables owned by two different datums, so do it here.
- if(be_random_name)
+ if(read_preference(/datum/preference/toggle/human/name_is_always_random))
real_name = random_name(identifying_gender,species)
// Ask the preferences datums to apply their own settings to the new mob
@@ -383,7 +337,7 @@ var/list/preferences_datums = list()
if(preference.savefile_identifier != PREFERENCE_CHARACTER)
continue
- preference.apply_to_human(character, read_preference(preference.type))
+ preference.apply_pref_to(character, read_preference(preference.type))
// VOREStation Edit - Sync up all their organs and species one final time
character.force_update_organs()
@@ -515,23 +469,15 @@ var/list/preferences_datums = list()
character.gender = biological_gender
character.identifying_gender = identifying_gender
- character.r_eyes = r_eyes
- character.g_eyes = g_eyes
- character.b_eyes = b_eyes
character.h_style = h_style
- character.r_hair = r_hair
- character.g_hair = g_hair
- character.b_hair = b_hair
- character.r_grad = r_grad
- character.g_grad = g_grad
- character.b_grad = b_grad
+
+ var/datum/preference/color/hair_color = GLOB.preference_entries[/datum/preference/color/human/hair_color]
+ hair_color.apply_pref_to(character, read_preference(/datum/preference/color/human/hair_color))
+
+ var/datum/preference/color/grad_color = GLOB.preference_entries[/datum/preference/color/human/grad_color]
+ grad_color.apply_pref_to(character, read_preference(/datum/preference/color/human/grad_color))
+
character.f_style = f_style
- character.r_facial = r_facial
- character.g_facial = g_facial
- character.b_facial = b_facial
- character.r_skin = r_skin
- character.g_skin = g_skin
- character.b_skin = b_skin
character.s_tone = s_tone
character.h_style = h_style
character.grad_style= grad_style
@@ -539,49 +485,50 @@ var/list/preferences_datums = list()
character.grad_style= grad_style
character.b_type = b_type
character.synth_color = synth_color
- character.r_synth = r_synth
- character.g_synth = g_synth
- character.b_synth = b_synth
+
+ var/datum/preference/color/synth_color_color = GLOB.preference_entries[/datum/preference/color/human/synth_color]
+ synth_color_color.apply_pref_to(character, read_preference(/datum/preference/color/human/synth_color))
+
character.synth_markings = synth_markings
var/list/ear_styles = get_available_styles(global.ear_styles_list)
character.ear_style = ear_styles[ear_style]
- character.r_ears = r_ears
- character.b_ears = b_ears
- character.g_ears = g_ears
- character.r_ears2 = r_ears2
- character.b_ears2 = b_ears2
- character.g_ears2 = g_ears2
- character.r_ears3 = r_ears3
- character.b_ears3 = b_ears3
- character.g_ears3 = g_ears3
+
+ var/datum/preference/color/ears_color1 = GLOB.preference_entries[/datum/preference/color/human/ears_color1]
+ ears_color1.apply_pref_to(character, read_preference(/datum/preference/color/human/ears_color1))
+
+ var/datum/preference/color/ears_color2 = GLOB.preference_entries[/datum/preference/color/human/ears_color2]
+ ears_color2.apply_pref_to(character, read_preference(/datum/preference/color/human/ears_color2))
+
+ var/datum/preference/color/ears_color3 = GLOB.preference_entries[/datum/preference/color/human/ears_color3]
+ ears_color3.apply_pref_to(character, read_preference(/datum/preference/color/human/ears_color3))
character.ear_secondary_style = ear_styles[ear_secondary_style]
character.ear_secondary_colors = SANITIZE_LIST(ear_secondary_colors)
var/list/tail_styles = get_available_styles(global.tail_styles_list)
character.tail_style = tail_styles[tail_style]
- character.r_tail = r_tail
- character.b_tail = b_tail
- character.g_tail = g_tail
- character.r_tail2 = r_tail2
- character.b_tail2 = b_tail2
- character.g_tail2 = g_tail2
- character.r_tail3 = r_tail3
- character.b_tail3 = b_tail3
- character.g_tail3 = g_tail3
+
+ var/datum/preference/color/tail_color1 = GLOB.preference_entries[/datum/preference/color/human/tail_color1]
+ tail_color1.apply_pref_to(character, read_preference(/datum/preference/color/human/tail_color1))
+
+ var/datum/preference/color/tail_color2 = GLOB.preference_entries[/datum/preference/color/human/tail_color2]
+ tail_color2.apply_pref_to(character, read_preference(/datum/preference/color/human/tail_color2))
+
+ var/datum/preference/color/tail_color3 = GLOB.preference_entries[/datum/preference/color/human/tail_color3]
+ tail_color3.apply_pref_to(character, read_preference(/datum/preference/color/human/tail_color3))
var/list/wing_styles = get_available_styles(global.wing_styles_list)
character.wing_style = wing_styles[wing_style]
- character.r_wing = r_wing
- character.b_wing = b_wing
- character.g_wing = g_wing
- character.r_wing2 = r_wing2
- character.b_wing2 = b_wing2
- character.g_wing2 = g_wing2
- character.r_wing3 = r_wing3
- character.b_wing3 = b_wing3
- character.g_wing3 = g_wing3
+
+ var/datum/preference/color/wing_color1 = GLOB.preference_entries[/datum/preference/color/human/wing_color1]
+ wing_color1.apply_pref_to(character, read_preference(/datum/preference/color/human/wing_color1))
+
+ var/datum/preference/color/wing_color2 = GLOB.preference_entries[/datum/preference/color/human/wing_color2]
+ wing_color2.apply_pref_to(character, read_preference(/datum/preference/color/human/wing_color2))
+
+ var/datum/preference/color/wing_color3 = GLOB.preference_entries[/datum/preference/color/human/wing_color3]
+ wing_color3.apply_pref_to(character, read_preference(/datum/preference/color/human/wing_color3))
character.set_gender(biological_gender)
@@ -658,9 +605,9 @@ var/list/preferences_datums = list()
character.flavor_texts["legs"] = flavor_texts["legs"]
character.flavor_texts["feet"] = flavor_texts["feet"]
if (copy_ooc_notes)
- character.ooc_notes = metadata
- character.ooc_notes_dislikes = metadata_dislikes
- character.ooc_notes_likes = metadata_likes
+ character.ooc_notes = read_preference(/datum/preference/text/living/ooc_notes)
+ character.ooc_notes_dislikes = read_preference(/datum/preference/text/living/ooc_notes_dislikes)
+ character.ooc_notes_likes = read_preference(/datum/preference/text/living/ooc_notes_likes)
character.weight = weight_vr
character.weight_gain = weight_gain
diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm
index d3ad859249..834ce4c489 100644
--- a/code/modules/client/preferences/_preference.dm
+++ b/code/modules/client/preferences/_preference.dm
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/// Produce a random value for the purposes of character randomization.
/// Will just create a default value by default.
-/datum/preference/proc/create_random_value(datum/preferences/preferences)
+/datum/preference/proc/create_random_value(datum/preferences/preferences, datum/species/current_species)
return create_informed_default_value(preferences)
/// Returns whether or not a preference can be randomized.
@@ -220,6 +220,17 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
SHOULD_NOT_SLEEP(TRUE)
apply_to_client(client, value)
+/// Apply this preference onto the given liivng mob.
+/// Calls the according procs depending on type.
+/datum/preference/proc/apply_pref_to(mob/living, value)
+ apply_to_living(living, value)
+ if(isanimal(living))
+ apply_to_animal(living, value)
+ else if(ishuman(living))
+ apply_to_human(living, value)
+ else if(issilicon(living))
+ apply_to_silicon(living, value)
+
/// Apply this preference onto the given human.
/// Must be overriden by subtypes.
/// Called when the savefile_identifier == PREFERENCE_CHARACTER.
@@ -228,6 +239,30 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
SHOULD_CALL_PARENT(FALSE)
CRASH("`apply_to_human()` was not implemented for [type]!")
+/// Apply this preference onto the given silicon.
+/// Must be overriden by subtypes.
+/// Called when the savefile_identifier == PREFERENCE_CHARACTER.
+/datum/preference/proc/apply_to_silicon(mob/living/silicon/target, value)
+ SHOULD_NOT_SLEEP(TRUE)
+ SHOULD_CALL_PARENT(FALSE)
+ CRASH("`apply_to_human()` was not implemented for [type]!")
+
+/// Apply this preference onto the given animal.
+/// Must be overriden by subtypes.
+/// Called when the savefile_identifier == PREFERENCE_CHARACTER.
+/datum/preference/proc/apply_to_animal(mob/living/simple_mob/target, value)
+ SHOULD_NOT_SLEEP(TRUE)
+ SHOULD_CALL_PARENT(FALSE)
+ CRASH("`apply_to_human()` was not implemented for [type]!")
+
+/// Apply this preference onto the given living.
+/// Must be overriden by subtypes.
+/// Called when the savefile_identifier == PREFERENCE_CHARACTER.
+/datum/preference/proc/apply_to_living(mob/living/target, value)
+ SHOULD_NOT_SLEEP(TRUE)
+ SHOULD_CALL_PARENT(FALSE)
+ CRASH("`apply_to_human()` was not implemented for [type]!")
+
/// Returns which savefile to use for a given savefile identifier
/datum/preferences/proc/get_save_data_for_savefile_identifier(savefile_identifier)
RETURN_TYPE(/list)
@@ -281,6 +316,10 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/mob/proc/read_preference(preference_type)
return client?.prefs?.read_preference(preference_type)
+/// Write a /datum/preference type and return its value directly to the json.
+/mob/proc/write_preference_directly(preference_type, preference_value)
+ return client?.prefs?.write_preference_by_type(preference_type, preference_value)
+
/// Set a /datum/preference entry.
/// Returns TRUE for a successful preference application.
/// Returns FALSE if it is invalid.
@@ -292,6 +331,23 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
value_cache[preference.type] = new_value
return success
+/// 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
+/datum/preferences/proc/write_preference_by_type(preference_type, preference_value)
+ var/datum/preference/preference_entry = GLOB.preference_entries[preference_type]
+ if(isnull(preference_entry))
+ CRASH("Preference type `[preference_type]` is invalid!")
+
+ if(!write_preference(preference_entry, preference_entry.pref_serialize(preference_value)))
+ return
+
+ if(preference_entry.savefile_identifier == PREFERENCE_CHARACTER)
+ var/save_data = get_save_data_for_savefile_identifier(preference_entry.savefile_identifier)
+ player_setup.save_character(save_data)
+ else
+ savefile.save()
+ return TRUE
+
/// Will perform an update on the preference, but not write to the savefile.
/// This will, for instance, update the character preference view.
/// Performs sanity checks.
@@ -315,6 +371,13 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
return TRUE
+/datum/preferences/proc/update_preference_by_type(preference_type, preference_value)
+ var/datum/preference/preference_entry = GLOB.preference_entries[preference_type]
+ if(isnull(preference_entry))
+ CRASH("Preference type `[preference_type]` is invalid!")
+
+ return update_preference(preference_entry, preference_value)
+
/// Checks that a given value is valid.
/// Must be overriden by subtypes.
/// Any type can be passed through.
@@ -354,8 +417,9 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
// if(!(savefile_key in species.get_features()))
// return FALSE
- if(!should_show_on_page(preferences.current_window))
- return FALSE
+ // TODO: Restore when tgui
+ // if(!should_show_on_page(preferences.current_window))
+ // return FALSE
return TRUE
@@ -444,8 +508,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
if(should_generate_icons)
var/list/icons = list()
- // for(var/choice in choices) // TODO: Pref spritesheet asset
- // icons[choice] = get_spritesheet_key(choice)
+ for(var/choice in choices)
+ icons[choice] = get_spritesheet_key(choice)
data["icons"] = icons
@@ -454,6 +518,54 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
return data
+/datum/preference/choiced/human
+ abstract_type = /datum/preference/choiced/human
+
+/datum/preference/choiced/human/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/choiced/human/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/choiced/human/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/choiced/living
+ abstract_type = /datum/preference/choiced/living
+
+/datum/preference/choiced/living/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/choiced/living/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/choiced/living/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/choiced/silicon
+ abstract_type = /datum/preference/choiced/silicon
+
+/datum/preference/choiced/silicon/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/choiced/silicon/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/choiced/silicon/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/choiced/animal
+ abstract_type = /datum/preference/choiced/animal
+
+/datum/preference/choiced/animal/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/choiced/animal/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/choiced/animal/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
/// A preference that represents an RGB color of something.
/// Will give the value as 6 hex digits, without a hash.
/datum/preference/color
@@ -471,6 +583,54 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/datum/preference/color/is_valid(value)
return findtext(value, GLOB.is_color)
+/datum/preference/color/human
+ abstract_type = /datum/preference/color/human
+
+/datum/preference/color/human/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/color/human/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/color/human/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/color/living
+ abstract_type = /datum/preference/color/living
+
+/datum/preference/color/living/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/color/living/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/color/living/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/color/silicon
+ abstract_type = /datum/preference/color/silicon
+
+/datum/preference/color/silicon/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/color/silicon/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/color/silicon/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/color/animal
+ abstract_type = /datum/preference/color/animal
+
+/datum/preference/color/animal/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/color/animal/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/color/animal/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
/// A numeric preference with a minimum and maximum value
/datum/preference/numeric
/// The minimum value
@@ -505,6 +665,54 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
"step" = step,
)
+/datum/preference/numeric/human
+ abstract_type = /datum/preference/numeric/human
+
+/datum/preference/numeric/human/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/numeric/human/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/numeric/human/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/numeric/living
+ abstract_type = /datum/preference/numeric/living
+
+/datum/preference/numeric/living/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/numeric/living/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/numeric/living/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/numeric/silicon
+ abstract_type = /datum/preference/numeric/silicon
+
+/datum/preference/numeric/silicon/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/numeric/silicon/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/numeric/silicon/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/numeric/animal
+ abstract_type = /datum/preference/numeric/animal
+
+/datum/preference/numeric/animal/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/numeric/animal/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/numeric/animal/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
/// A preference whose value is always TRUE or FALSE
/datum/preference/toggle
abstract_type = /datum/preference/toggle
@@ -521,6 +729,53 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/datum/preference/toggle/is_valid(value)
return value == TRUE || value == FALSE
+/datum/preference/toggle/human
+ abstract_type = /datum/preference/toggle/human
+
+/datum/preference/toggle/human/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/toggle/human/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/toggle/human/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/toggle/living
+ abstract_type = /datum/preference/toggle/living
+
+/datum/preference/toggle/living/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/toggle/living/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/toggle/living/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/toggle/silicon
+ abstract_type = /datum/preference/toggle/silicon
+
+/datum/preference/toggle/silicon/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/toggle/silicon/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/toggle/silicon/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/toggle/animal
+ abstract_type = /datum/preference/toggle/animal
+
+/datum/preference/toggle/animal/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/toggle/animal/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/toggle/animal/apply_to_silicon(mob/living/silicon/target, value)
+ return
/// A string-based preference accepting arbitrary string values entered by the user, with a maximum length.
/datum/preference/text
@@ -544,3 +799,51 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/datum/preference/text/compile_constant_data()
return list("maximum_length" = maximum_value_length)
+
+/datum/preference/text/human
+ abstract_type = /datum/preference/text/human
+
+/datum/preference/text/human/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/text/human/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/text/human/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/text/living
+ abstract_type = /datum/preference/text/living
+
+/datum/preference/text/living/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/text/living/apply_to_silicon(mob/living/silicon/target, value)
+ return
+
+/datum/preference/text/living/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/text/silicon
+ abstract_type = /datum/preference/text/silicon
+
+/datum/preference/text/silicon/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/text/silicon/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/text/silicon/apply_to_animal(mob/living/simple_mob, value)
+ return
+
+/datum/preference/text/animal
+ abstract_type = /datum/preference/text/animal
+
+/datum/preference/text/animal/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/text/animal/apply_to_living(mob/living/target, value)
+ return
+
+/datum/preference/text/animal/apply_to_silicon(mob/living/silicon/target, value)
+ return
diff --git a/code/modules/client/preferences/middleware/random.dm b/code/modules/client/preferences/middleware/random.dm
new file mode 100644
index 0000000000..f61401b4f0
--- /dev/null
+++ b/code/modules/client/preferences/middleware/random.dm
@@ -0,0 +1,84 @@
+/// Middleware for handling randomization preferences
+/datum/preference_middleware/random
+ action_delegations = list(
+ "randomize_character" = PROC_REF(randomize_character),
+ "set_random_preference" = PROC_REF(set_random_preference),
+ )
+
+/datum/preference_middleware/random/get_character_preferences(mob/user)
+ return list(
+ "randomization" = preferences.randomise,
+ )
+
+/datum/preference_middleware/random/get_constant_data()
+ var/list/randomizable = list()
+
+ for (var/preference_type in GLOB.preference_entries)
+ var/datum/preference/preference = GLOB.preference_entries[preference_type]
+ if (!preference.is_randomizable())
+ continue
+
+ randomizable += preference.savefile_key
+
+ return list(
+ "randomizable" = randomizable,
+ )
+
+/datum/preference_middleware/random/proc/randomize_character()
+ for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
+ if (preferences.should_randomize(preference))
+ preferences.write_preference(preference, preference.create_random_value(preferences))
+
+ // preferences.character_preview_view.update_body()
+
+ return TRUE
+
+/datum/preference_middleware/random/proc/set_random_preference(list/params, mob/user)
+ var/requested_preference_key = params["preference"]
+ var/value = params["value"]
+
+ var/datum/preference/requested_preference = GLOB.preference_entries_by_key[requested_preference_key]
+ if (isnull(requested_preference))
+ return FALSE
+
+ if (!requested_preference.is_randomizable())
+ return FALSE
+
+ if (value == RANDOM_ANTAG_ONLY)
+ preferences.randomise[requested_preference_key] = RANDOM_ANTAG_ONLY
+ else if (value == RANDOM_ENABLED)
+ preferences.randomise[requested_preference_key] = RANDOM_ENABLED
+ else if (value == RANDOM_DISABLED)
+ preferences.randomise -= requested_preference_key
+ else
+ return FALSE
+
+ return TRUE
+
+/// Returns if a preference should be randomized.
+/datum/preferences/proc/should_randomize(datum/preference/preference, is_antag)
+ if (!preference.is_randomizable())
+ return FALSE
+
+ var/requested_randomization = randomise[preference.savefile_key]
+
+ //if (istype(preference, /datum/preference/name))
+ // requested_randomization = read_preference(/datum/preference/choiced/random_name)
+
+ switch (requested_randomization)
+ if (RANDOM_ENABLED)
+ return TRUE
+ if (RANDOM_ANTAG_ONLY)
+ return is_antag
+ else
+ return FALSE
+
+/// Given randomization flags, will return whether or not this preference should be randomized.
+/datum/preference/proc/included_in_randomization_flags(randomize_flags)
+ return TRUE
+
+// /datum/preference/name/included_in_randomization_flags(randomize_flags)
+// return !!(randomize_flags & RANDOMIZE_NAME)
+
+// /datum/preference/choiced/species/included_in_randomization_flags(randomize_flags)
+// return !!(randomize_flags & RANDOMIZE_SPECIES)
diff --git a/code/modules/client/preferences/migrations/16_colors.dm b/code/modules/client/preferences/migrations/16_colors.dm
new file mode 100644
index 0000000000..f915acf4c3
--- /dev/null
+++ b/code/modules/client/preferences/migrations/16_colors.dm
@@ -0,0 +1,25 @@
+/// Moves r_g_b_ affixes to single hex colors
+/datum/preferences/proc/migration_16_colors(datum/json_savefile/S)
+ for(var/slot in 1 to CONFIG_GET(number/character_slots))
+ var/list/prefs = S.get_entry("character[slot]", null)
+ if(!islist(prefs))
+ continue
+
+ prefs["hair_color"] = rgb(prefs["hair_red"], prefs["hair_green"], prefs["hair_blue"])
+ prefs["facial_color"] = rgb(prefs["facial_red"], prefs["facial_green"], prefs["facial_blue"])
+ prefs["grad_color"] = rgb(prefs["grad_red"], prefs["grad_green"], prefs["grad_blue"])
+ prefs["skin_color"] = rgb(prefs["skin_red"], prefs["skin_green"], prefs["skin_blue"])
+ prefs["eyes_color"] = rgb(prefs["eyes_red"], prefs["eyes_green"], prefs["eyes_blue"])
+ prefs["synth_color_rgb"] = rgb(prefs["synth_red"], prefs["synth_green"], prefs["synth_blue"])
+
+ prefs["ears_color1"] = rgb(prefs["r_ears"], prefs["g_ears"], prefs["b_ears"])
+ prefs["ears_color2"] = rgb(prefs["r_ears2"], prefs["g_ears2"], prefs["b_ears2"])
+ prefs["ears_color3"] = rgb(prefs["r_ears3"], prefs["g_ears3"], prefs["b_ears3"])
+
+ prefs["tail_color1"] = rgb(prefs["r_tail"], prefs["g_tail"], prefs["b_tail"])
+ prefs["tail_color2"] = rgb(prefs["r_tail2"], prefs["g_tail2"], prefs["b_tail2"])
+ prefs["tail_color3"] = rgb(prefs["r_tail3"], prefs["g_tail3"], prefs["b_tail3"])
+
+ prefs["wing_color1"] = rgb(prefs["r_wing"], prefs["g_wing"], prefs["b_wing"])
+ prefs["wing_color2"] = rgb(prefs["r_wing2"], prefs["g_wing2"], prefs["b_wing2"])
+ prefs["wing_color3"] = rgb(prefs["r_wing3"], prefs["g_wing3"], prefs["b_wing3"])
diff --git a/code/modules/client/preferences/types/character/antagonism/01_basic.dm b/code/modules/client/preferences/types/character/antagonism/01_basic.dm
new file mode 100644
index 0000000000..64ecf7ce4c
--- /dev/null
+++ b/code/modules/client/preferences/types/character/antagonism/01_basic.dm
@@ -0,0 +1,18 @@
+/datum/preference/choiced/uplinklocation
+ category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
+ savefile_key = "uplinklocation"
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+/datum/preference/choiced/uplinklocation/init_possible_values()
+ return GLOB.uplink_locations
+
+// No application
+/datum/preference/choiced/uplinklocation/apply_to_living(mob/living/target, value)
+ return
+/datum/preference/choiced/uplinklocation/apply_to_animal(mob/living/simple_mob/target, value)
+ return
+/datum/preference/choiced/uplinklocation/apply_to_human(mob/living/carbon/human/target, value)
+ return
+/datum/preference/choiced/uplinklocation/apply_to_silicon(mob/living/silicon/target, value)
+ return
diff --git a/code/modules/client/preferences/types/character/general/01_basic.dm b/code/modules/client/preferences/types/character/general/01_basic.dm
new file mode 100644
index 0000000000..3449486c23
--- /dev/null
+++ b/code/modules/client/preferences/types/character/general/01_basic.dm
@@ -0,0 +1,175 @@
+// Toggles
+/datum/preference/toggle/human/bday_announce
+ category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
+ savefile_key = "bday_announce"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+/datum/preference/toggle/human/bday_announce/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+
+// Numerics
+/datum/preference/numeric/human/age
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "age"
+ savefile_identifier = PREFERENCE_CHARACTER
+
+ step = 1
+ minimum = 18
+ maximum = 250
+
+/datum/preference/numeric/human/age/apply_to_human(mob/living/carbon/human/target, value)
+ target.age = value
+ return
+
+/datum/preference/numeric/human/age/create_default_value()
+ return 18
+
+/datum/preference/numeric/human/age/create_random_value(datum/preferences/preferences, datum/species/current_species)
+ return rand(current_species.min_age, current_species.max_age)
+
+/datum/preference/numeric/human/bday_month
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "bday_month"
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+ step = 1
+ minimum = 0
+ maximum = 12
+
+/datum/preference/numeric/human/bday_month/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/numeric/human/bday_month/create_default_value()
+ return 0
+
+/datum/preference/numeric/human/bday_day
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "bday_day"
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+ step = 1
+ minimum = 0
+ maximum = 31
+
+/datum/preference/numeric/human/bday_day/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/numeric/human/bday_day/create_default_value()
+ return 0
+
+/datum/preference/numeric/human/last_bday_note
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "last_bday_note"
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+ step = 1
+ minimum = 0
+ maximum = 9999
+
+/datum/preference/numeric/human/last_bday_note/apply_to_human(mob/living/carbon/human/target, value)
+ return
+
+/datum/preference/numeric/human/last_bday_note/create_default_value()
+ return 0
+
+/datum/preference/numeric/human/last_bday_note/is_accessible(datum/preferences/preferences)
+ ..()
+ return FALSE
+
+/datum/preference/text/living/ooc_notes
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "OOC_Notes"
+ maximum_value_length = MAX_MESSAGE_LEN * 4
+ can_randomize = FALSE
+
+/datum/preference/text/living/ooc_notes/apply_to_living(mob/living/target, value)
+ target.ooc_notes = value
+ return
+
+/datum/preference/text/living/ooc_notes_likes
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "OOC_Notes_Likes"
+ maximum_value_length = MAX_MESSAGE_LEN * 2
+ can_randomize = FALSE
+
+/datum/preference/text/living/ooc_notes_likes/apply_to_living(mob/living/target, value)
+ target.ooc_notes_likes = value
+ return
+
+/datum/preference/text/living/ooc_notes_dislikes
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "OOC_Notes_Disikes"
+ maximum_value_length = MAX_MESSAGE_LEN * 2
+ can_randomize = FALSE
+
+/datum/preference/text/living/ooc_notes_dislikes/apply_to_living(mob/living/target, value)
+ target.ooc_notes_dislikes = value
+ return
+
+// CHOMP specific, but added here not to forget
+/datum/preference/toggle/living/ooc_notes_style
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "OOC_Notes_System"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+/datum/preference/toggle/living/ooc_notes_style/apply_to_living(mob/living/target, value)
+ // target.ooc_notes_style // Not available on virgo
+ return
+
+/datum/preference/text/living/ooc_notes_maybes
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "OOC_Notes_Maybes"
+ maximum_value_length = MAX_MESSAGE_LEN * 2
+ can_randomize = FALSE
+
+/datum/preference/text/living/ooc_notes_maybes/apply_to_living(mob/living/target, value)
+ // target.ooc_notes_maybes = value // Not available on virgo
+ return
+
+/datum/preference/text/living/ooc_notes_favs
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "OOC_Notes_Favs"
+ maximum_value_length = MAX_MESSAGE_LEN * 2
+ can_randomize = FALSE
+
+/datum/preference/text/living/ooc_notes_favs/apply_to_living(mob/living/target, value)
+ // target.ooc_notes_favs = value // Not available on virgo
+ return
+
+/datum/preference/toggle/human/name_is_always_random
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "name_is_always_random"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+/datum/preference/toggle/human/name_is_always_random/apply_to_human(mob/living/carbon/human/target, value)
+ return // handled in copy_to
+
+/datum/preference/choiced/human/spawnpoint
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "spawnpoint"
+ savefile_identifier = PREFERENCE_CHARACTER
+ can_randomize = FALSE
+
+/datum/preference/choiced/human/spawnpoint/init_possible_values()
+ var/list/spawnkeys = list()
+ for(var/spawntype in spawntypes)
+ spawnkeys += spawntype
+ return spawnkeys
+
+/datum/preference/choiced/human/spawnpoint/apply_to_human(mob/living/carbon/human/target, value)
+ return // handled in job_controller
diff --git a/code/modules/client/preferences/types/character/general/03_body.dm b/code/modules/client/preferences/types/character/general/03_body.dm
new file mode 100644
index 0000000000..8037bbe21a
--- /dev/null
+++ b/code/modules/client/preferences/types/character/general/03_body.dm
@@ -0,0 +1,166 @@
+/datum/preference/color/human/hair_color
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "hair_color"
+ can_randomize = FALSE
+
+/datum/preference/color/human/hair_color/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_hair = hex2num(copytext(value, 2, 4))
+ target.g_hair = hex2num(copytext(value, 4, 6))
+ target.b_hair = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/grad_color
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "grad_color"
+ can_randomize = FALSE
+
+/datum/preference/color/human/grad_color/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_grad = hex2num(copytext(value, 2, 4))
+ target.g_grad = hex2num(copytext(value, 4, 6))
+ target.b_grad = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/facial_color
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "facial_color"
+ can_randomize = FALSE
+
+/datum/preference/color/human/facial_color/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_facial = hex2num(copytext(value, 2, 4))
+ target.g_facial = hex2num(copytext(value, 4, 6))
+ target.b_facial = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/eyes_color
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "eyes_color"
+ can_randomize = FALSE
+
+/datum/preference/color/human/eyes_color/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_eyes = hex2num(copytext(value, 2, 4))
+ target.g_eyes = hex2num(copytext(value, 4, 6))
+ target.b_eyes = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/skin_color
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "skin_color"
+ can_randomize = FALSE
+
+/datum/preference/color/human/skin_color/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_skin = hex2num(copytext(value, 2, 4))
+ target.g_skin = hex2num(copytext(value, 4, 6))
+ target.b_skin = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/synth_color
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "synth_color"
+ can_randomize = FALSE
+
+/datum/preference/color/human/synth_color/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_synth = hex2num(copytext(value, 2, 4))
+ target.g_synth = hex2num(copytext(value, 4, 6))
+ target.b_synth = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/tail_color1
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "tail_color1"
+ can_randomize = FALSE
+
+/datum/preference/color/human/tail_color1/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_tail = hex2num(copytext(value, 2, 4))
+ target.g_tail = hex2num(copytext(value, 4, 6))
+ target.b_tail = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/tail_color2
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "tail_color2"
+ can_randomize = FALSE
+
+/datum/preference/color/human/tail_color2/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_tail2 = hex2num(copytext(value, 2, 4))
+ target.g_tail2 = hex2num(copytext(value, 4, 6))
+ target.b_tail2 = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/tail_color3
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "tail_color3"
+ can_randomize = FALSE
+
+/datum/preference/color/human/tail_color3/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_tail3 = hex2num(copytext(value, 2, 4))
+ target.g_tail3 = hex2num(copytext(value, 4, 6))
+ target.b_tail3 = hex2num(copytext(value, 6, 8))
+
+
+/datum/preference/color/human/wing_color1
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "wing_color1"
+ can_randomize = FALSE
+
+/datum/preference/color/human/wing_color1/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_wing = hex2num(copytext(value, 2, 4))
+ target.g_wing = hex2num(copytext(value, 4, 6))
+ target.b_wing = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/wing_color2
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "wing_color2"
+ can_randomize = FALSE
+
+/datum/preference/color/human/wing_color2/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_wing2 = hex2num(copytext(value, 2, 4))
+ target.g_wing2 = hex2num(copytext(value, 4, 6))
+ target.b_wing2 = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/wing_color3
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "wing_color3"
+ can_randomize = FALSE
+
+/datum/preference/color/human/wing_color3/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_wing3 = hex2num(copytext(value, 2, 4))
+ target.g_wing3 = hex2num(copytext(value, 4, 6))
+ target.b_wing3 = hex2num(copytext(value, 6, 8))
+
+
+/datum/preference/color/human/ears_color1
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "ears_color1"
+ can_randomize = FALSE
+
+/datum/preference/color/human/ears_color1/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_ears = hex2num(copytext(value, 2, 4))
+ target.g_ears = hex2num(copytext(value, 4, 6))
+ target.b_ears = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/ears_color2
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "ears_color2"
+ can_randomize = FALSE
+
+/datum/preference/color/human/ears_color2/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_ears2 = hex2num(copytext(value, 2, 4))
+ target.g_ears2 = hex2num(copytext(value, 4, 6))
+ target.b_ears2 = hex2num(copytext(value, 6, 8))
+
+/datum/preference/color/human/ears_color3
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "ears_color3"
+ can_randomize = FALSE
+
+/datum/preference/color/human/ears_color3/apply_to_human(mob/living/carbon/human/target, value)
+ target.r_ears3 = hex2num(copytext(value, 2, 4))
+ target.g_ears3 = hex2num(copytext(value, 4, 6))
+ target.b_ears3 = hex2num(copytext(value, 6, 8))
diff --git a/code/modules/client/preferences/types/admin.dm b/code/modules/client/preferences/types/game/admin.dm
similarity index 80%
rename from code/modules/client/preferences/types/admin.dm
rename to code/modules/client/preferences/types/game/admin.dm
index f066bc041e..de30ef2cc3 100644
--- a/code/modules/client/preferences/types/admin.dm
+++ b/code/modules/client/preferences/types/game/admin.dm
@@ -71,3 +71,18 @@
savefile_key = "CHAT_ADSAY"
default_value = TRUE
savefile_identifier = PREFERENCE_PLAYER
+
+/// The color admins will speak in for OOC.
+/datum/preference/color/ooc_color
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "ooccolor"
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/color/ooc_color/create_default_value()
+ return "#010000"
+
+/datum/preference/color/ooc_color/is_accessible(datum/preferences/preferences)
+ if(!..(preferences))
+ return FALSE
+
+ return CONFIG_GET(flag/allow_admin_ooccolor) && check_rights(R_ADMIN|R_EVENT|R_FUN, 0, preferences.client)
diff --git a/code/modules/client/preferences/types/auto_fit_viewport.dm b/code/modules/client/preferences/types/game/auto_fit_viewport.dm
similarity index 100%
rename from code/modules/client/preferences/types/auto_fit_viewport.dm
rename to code/modules/client/preferences/types/game/auto_fit_viewport.dm
diff --git a/code/modules/client/preferences/types/chat.dm b/code/modules/client/preferences/types/game/chat.dm
similarity index 100%
rename from code/modules/client/preferences/types/chat.dm
rename to code/modules/client/preferences/types/game/chat.dm
diff --git a/code/modules/client/preferences/types/game/fps.dm b/code/modules/client/preferences/types/game/fps.dm
new file mode 100644
index 0000000000..079be8a0fb
--- /dev/null
+++ b/code/modules/client/preferences/types/game/fps.dm
@@ -0,0 +1,20 @@
+/datum/preference/numeric/fps
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "client_fps"
+ savefile_identifier = PREFERENCE_PLAYER
+
+ minimum = -1
+ maximum = MAX_CLIENT_FPS
+
+/datum/preference/numeric/fps/create_default_value()
+ return -1
+
+/datum/preference/numeric/fps/apply_to_client(client/client, value)
+ client.fps = (value < 0) ? RECOMMENDED_FPS : value
+
+/datum/preference/numeric/fps/compile_constant_data()
+ var/list/data = ..()
+
+ data["recommended_fps"] = RECOMMENDED_FPS
+
+ return data
diff --git a/code/modules/client/preferences/types/ghost.dm b/code/modules/client/preferences/types/game/ghost.dm
similarity index 100%
rename from code/modules/client/preferences/types/ghost.dm
rename to code/modules/client/preferences/types/game/ghost.dm
diff --git a/code/modules/client/preferences/types/game/ignored_players.dm b/code/modules/client/preferences/types/game/ignored_players.dm
new file mode 100644
index 0000000000..27e0c8addd
--- /dev/null
+++ b/code/modules/client/preferences/types/game/ignored_players.dm
@@ -0,0 +1,17 @@
+/datum/preference/ignored_players
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "ignored_players"
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/ignored_players/is_valid(value)
+ return TRUE
+
+/datum/preference/ignored_players/pref_deserialize(input, datum/preferences/preferences)
+ return SANITIZE_LIST(input)
+
+/datum/preference/ignored_players/create_default_value()
+ return list()
+
+/datum/preference/ignored_players/is_accessible(datum/preferences/preferences)
+ . = ..()
+ return FALSE
diff --git a/code/modules/client/preferences/types/misc.dm b/code/modules/client/preferences/types/game/misc.dm
similarity index 94%
rename from code/modules/client/preferences/types/misc.dm
rename to code/modules/client/preferences/types/game/misc.dm
index 3efea58893..7259eae5eb 100644
--- a/code/modules/client/preferences/types/misc.dm
+++ b/code/modules/client/preferences/types/game/misc.dm
@@ -11,18 +11,6 @@
PH.set_ao(VIS_OBJS, value)
PH.set_ao(VIS_MOBS, value)
-/datum/preference/toggle/mob_tooltips
- category = PREFERENCE_CATEGORY_GAME_PREFERENCES
- savefile_key = "MOB_TOOLTIPS"
- default_value = TRUE
- savefile_identifier = PREFERENCE_PLAYER
-
-/datum/preference/toggle/inv_tooltips
- category = PREFERENCE_CATEGORY_GAME_PREFERENCES
- savefile_key = "INV_TOOLTIPS"
- default_value = TRUE
- savefile_identifier = PREFERENCE_PLAYER
-
/datum/preference/toggle/attack_icons
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "ATTACK_ICONS"
@@ -93,3 +81,15 @@
winset(client, null, "browser-options=[DEFAULT_CLIENT_BROWSER_OPTIONS],devtools")
else
winset(client, null, "browser-options=[DEFAULT_CLIENT_BROWSER_OPTIONS]")
+
+/datum/preference/toggle/obfuscate_key
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "obfuscate_key"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/obfuscate_job
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "obfuscate_job"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_PLAYER
diff --git a/code/modules/client/preferences/types/runechat.dm b/code/modules/client/preferences/types/game/runechat.dm
similarity index 100%
rename from code/modules/client/preferences/types/runechat.dm
rename to code/modules/client/preferences/types/game/runechat.dm
diff --git a/code/modules/client/preferences/types/sound.dm b/code/modules/client/preferences/types/game/sound.dm
similarity index 89%
rename from code/modules/client/preferences/types/sound.dm
rename to code/modules/client/preferences/types/game/sound.dm
index 83c4109bd0..8b120e89e0 100644
--- a/code/modules/client/preferences/types/sound.dm
+++ b/code/modules/client/preferences/types/game/sound.dm
@@ -147,3 +147,23 @@
savefile_key = "DIGEST_NOISES"
default_value = TRUE
savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/numeric/ambience_freq
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "ambience_freq"
+ savefile_identifier = PREFERENCE_PLAYER
+ minimum = 0
+ maximum = 60
+
+/datum/preference/numeric/ambience_freq/create_default_value()
+ return 5
+
+/datum/preference/numeric/ambience_chance
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "ambience_chance"
+ savefile_identifier = PREFERENCE_PLAYER
+ minimum = 0
+ maximum = 100
+
+/datum/preference/numeric/ambience_chance/create_default_value()
+ return 35
diff --git a/code/modules/client/preferences/types/game/tooltip.dm b/code/modules/client/preferences/types/game/tooltip.dm
new file mode 100644
index 0000000000..4e4b7659c5
--- /dev/null
+++ b/code/modules/client/preferences/types/game/tooltip.dm
@@ -0,0 +1,22 @@
+/datum/preference/toggle/mob_tooltips
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "MOB_TOOLTIPS"
+ default_value = TRUE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/inv_tooltips
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "INV_TOOLTIPS"
+ default_value = TRUE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/choiced/tooltip_style
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "tooltipstyle"
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/choiced/tooltip_style/init_possible_values()
+ return all_tooltip_styles
+
+/datum/preference/choiced/tooltip_style/create_default_value()
+ return all_tooltip_styles[1]
diff --git a/code/modules/client/preferences/types/ui.dm b/code/modules/client/preferences/types/game/ui.dm
similarity index 66%
rename from code/modules/client/preferences/types/ui.dm
rename to code/modules/client/preferences/types/game/ui.dm
index 9458652192..1d770dc3e7 100644
--- a/code/modules/client/preferences/types/ui.dm
+++ b/code/modules/client/preferences/types/game/ui.dm
@@ -21,6 +21,35 @@
if(before != client.tgui_panel.oldchat)
client.nuke_chat()
+/datum/preference/toggle/tgui_fancy
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "tgui_fancy"
+ default_value = TRUE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/tgui_lock
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "tgui_lock"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/tgui_input_mode
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "tgui_input_mode"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/tgui_large_buttons
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "tgui_large_buttons"
+ default_value = TRUE
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/tgui_swapped_buttons
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "tgui_swapped_buttons"
+ default_value = FALSE
+ savefile_identifier = PREFERENCE_PLAYER
/datum/preference/toggle/tgui_say
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
diff --git a/code/modules/client/preferences/types/game/ui_style.dm b/code/modules/client/preferences/types/game/ui_style.dm
new file mode 100644
index 0000000000..2591c22f2c
--- /dev/null
+++ b/code/modules/client/preferences/types/game/ui_style.dm
@@ -0,0 +1,49 @@
+/datum/preference/choiced/ui_style
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "UI_style"
+ savefile_identifier = PREFERENCE_PLAYER
+ should_generate_icons = TRUE
+
+/datum/preference/choiced/ui_style/init_possible_values()
+ return assoc_to_keys(all_ui_styles)
+
+/datum/preference/choiced/ui_style/icon_for(value)
+ var/icon/icon_file = all_ui_styles[value]
+
+ var/icon/icon = icon(icon_file, "r_hand_inactive")
+ icon.Crop(1, 1, ICON_SIZE_X * 2, ICON_SIZE_Y)
+ icon.Blend(icon(icon_file, "l_hand_inactive"), ICON_OVERLAY, ICON_SIZE_X)
+
+ return icon
+
+/datum/preference/choiced/ui_style/create_default_value()
+ return all_ui_styles[1]
+
+/datum/preference/choiced/ui_style/apply_to_client_updated(client/client, value)
+ client.mob?.update_ui_style(UI_style_new = value)
+
+/datum/preference/numeric/ui_style_alpha
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "UI_style_alpha"
+ savefile_identifier = PREFERENCE_PLAYER
+
+ minimum = 50
+ maximum = 255
+ step = 1
+
+/datum/preference/numeric/ui_style_alpha/create_default_value()
+ return 255
+
+/datum/preference/numeric/ui_style_alpha/apply_to_client_updated(client/client, value)
+ client.mob?.update_ui_style(UI_style_alpha_new = value)
+
+/datum/preference/color/ui_style_color
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "UI_style_color"
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/color/ui_style_color/create_default_value()
+ return COLOR_WHITE
+
+/datum/preference/color/ui_style_color/apply_to_client_updated(client/client, value)
+ client.mob?.update_ui_style(UI_style_color_new = value)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index b0ec02a892..a7e278fddc 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -1,5 +1,5 @@
#define SAVEFILE_VERSION_MIN 8
-#define SAVEFILE_VERSION_MAX 15
+#define SAVEFILE_VERSION_MAX 16
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -69,6 +69,16 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v15.")
to_chat(client, span_danger("v15 savefile migration complete."))
+ // Migration for colors
+ if(current_version < 16)
+ log_debug("[client_ckey] preferences migrating from [current_version] to v16....")
+ to_chat(client, span_danger("Migrating savefile from version [current_version] to v16..."))
+
+ migration_16_colors(S)
+
+ log_debug("[client_ckey] preferences successfully migrated from [current_version] to v16.")
+ to_chat(client, span_danger("v16 savefile migration complete."))
+
/datum/preferences/proc/update_character(current_version, list/save_data)
// Migration from BYOND savefiles to JSON: Important milemark.
@@ -105,6 +115,22 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
CRASH("Attempted to load savefile without first loading a path!")
savefile = new /datum/json_savefile(load_and_save ? path : null)
+// General preferences, have to be preloaded
+/datum/preferences/proc/load_early_prefs()
+ default_slot = savefile.get_entry("default_slot", default_slot)
+ lastnews = savefile.get_entry("lastnews", lastnews)
+ lastlorenews = savefile.get_entry("lastlorenews", lastlorenews)
+
+/datum/preferences/proc/sanitize_early_prefs()
+ default_slot = sanitize_integer(default_slot, 1, CONFIG_GET(number/character_slots), initial(default_slot))
+ lastnews = sanitize_text(lastnews, initial(lastnews))
+ lastlorenews = sanitize_text(lastlorenews, initial(lastlorenews))
+
+/datum/preferences/proc/save_early_prefs()
+ savefile.set_entry("default_slot", default_slot)
+ savefile.set_entry("lastnews", lastnews)
+ savefile.set_entry("lastlorenews", lastlorenews)
+
/datum/preferences/proc/load_preferences()
if(!savefile)
stack_trace("Attempted to load the preferences of [client] without a savefile; did you forget to call load_savefile?")
@@ -123,6 +149,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
apply_all_client_preferences()
+ load_early_prefs()
+ sanitize_early_prefs()
+
//try to fix any outdated data if necessary
if(needs_update >= 0)
var/bacpath = "[path].updatebac" //todo: if the savefile version is higher then the server, check the backup, and give the player a prompt to load the backup
@@ -177,6 +206,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(preference_type in value_cache)
write_preference(preference, preference.pref_serialize(value_cache[preference_type]))
+ save_early_prefs()
savefile.save()
return TRUE
@@ -244,10 +274,24 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
return FALSE
var/tree_key = "character[default_slot]"
+ var/first_save = FALSE
if(!(tree_key in savefile.get_entry()))
savefile.set_entry(tree_key, list())
+ first_save = TRUE
var/save_data = savefile.get_entry(tree_key)
+ for(var/datum/preference/preference as anything in get_preferences_in_priority_order())
+ if(preference.savefile_identifier != PREFERENCE_CHARACTER && !first_save)
+ continue
+
+ if(!(preference.type in recently_updated_keys) && !first_save)
+ continue
+
+ recently_updated_keys -= preference.type
+
+ if(preference.type in value_cache)
+ write_preference(preference, preference.pref_serialize(value_cache[preference.type]))
+
save_data["version"] = SAVEFILE_VERSION_MAX //load_character will sanitize any bad data, so assume up-to-date.
player_setup.save_character(save_data)
diff --git a/code/modules/client/preferences_tgui.dm b/code/modules/client/preferences_tgui.dm
index 9e3b430f68..068580432c 100644
--- a/code/modules/client/preferences_tgui.dm
+++ b/code/modules/client/preferences_tgui.dm
@@ -13,7 +13,7 @@
/datum/preferences/ui_assets(mob/user)
var/list/assets = list(
- // get_asset_datum(/datum/asset/spritesheet/preferences),
+ get_asset_datum(/datum/asset/spritesheet/preferences),
get_asset_datum(/datum/asset/json/preferences),
)
@@ -79,6 +79,34 @@
return TRUE
+ if("set_color_preference")
+ var/requested_preference_key = params["preference"]
+
+ var/datum/preference/requested_preference = GLOB.preference_entries_by_key[requested_preference_key]
+ if(isnull(requested_preference))
+ return FALSE
+
+ if(!istype(requested_preference, /datum/preference/color))
+ return FALSE
+
+ var/default_value = read_preference(requested_preference.type)
+
+ // Yielding
+ var/new_color = input(
+ usr,
+ "Select new color",
+ null,
+ default_value || COLOR_WHITE,
+ ) as color | null
+
+ if(!new_color)
+ return FALSE
+
+ if(!update_preference(requested_preference, new_color))
+ return FALSE
+
+ return TRUE
+
for(var/datum/preference_middleware/preference_middleware as anything in middleware)
var/delegation = preference_middleware.action_delegations[action]
if(!isnull(delegation))
diff --git a/code/modules/client/preferences_toggle_procs.dm b/code/modules/client/preferences_toggle_procs.dm
index fbd61f46ea..841b8110dc 100644
--- a/code/modules/client/preferences_toggle_procs.dm
+++ b/code/modules/client/preferences_toggle_procs.dm
@@ -14,16 +14,6 @@
feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/verb/toggle_chat_timestamps()
- set name = "Toggle Chat Timestamps"
- set category = "Preferences.Chat"
- set desc = "Toggles whether or not messages in chat will display timestamps. Enabling this will not add timestamps to messages that have already been sent."
-
- prefs.chat_timestamp = !prefs.chat_timestamp //There is no preference datum for tgui input lock, nor for any TGUI prefs.
- SScharacter_setup.queue_preferences_save(prefs)
-
- to_chat(src, span_notice("You have toggled chat timestamps: [prefs.chat_timestamp ? "ON" : "OFF"]."))
-
// Not attached to a pref datum because those are strict binary toggles
/client/verb/toggle_examine_mode()
set name = "Toggle Examine Mode"
diff --git a/code/modules/client/ui_style.dm b/code/modules/client/ui_style.dm
index 9cd68b8606..479d59d181 100644
--- a/code/modules/client/ui_style.dm
+++ b/code/modules/client/ui_style.dm
@@ -55,27 +55,11 @@ var/global/list/all_tooltip_styles = list(
if(!UI_style_color_new) return
//update UI
- var/list/icons = usr.hud_used.adding + usr.hud_used.other + usr.hud_used.hotkeybuttons
- icons.Add(usr.zone_sel)
- icons.Add(usr.gun_setting_icon)
- icons.Add(usr.item_use_icon)
- icons.Add(usr.gun_move_icon)
- icons.Add(usr.radio_use_icon)
-
- var/icon/ic = all_ui_styles[UI_style_new]
- if(isrobot(usr))
- ic = all_ui_styles_robot[UI_style_new]
-
- for(var/obj/screen/I in icons)
- if(I.name in list(I_HELP, I_HURT, I_DISARM, I_GRAB)) continue
- I.icon = ic
- I.color = UI_style_color_new
- I.alpha = UI_style_alpha_new
-
+ usr.update_ui_style(UI_style_new, UI_style_alpha_new, UI_style_color_new)
if(tgui_alert(usr, "Like it? Save changes?","Save?",list("Yes", "No")) == "Yes")
- prefs.UI_style = UI_style_new
- prefs.UI_style_alpha = UI_style_alpha_new
- prefs.UI_style_color = UI_style_color_new
+ usr.write_preference_directly(/datum/preference/choiced/ui_style, UI_style_new)
+ usr.write_preference_directly(/datum/preference/numeric/ui_style_alpha, UI_style_alpha_new)
+ usr.write_preference_directly(/datum/preference/color/ui_style_color, UI_style_color_new)
SScharacter_setup.queue_preferences_save(prefs)
to_chat(usr, "UI was saved")
diff --git a/code/modules/client/verbs/ignore.dm b/code/modules/client/verbs/ignore.dm
index 9981348f2b..ac1461ff64 100644
--- a/code/modules/client/verbs/ignore.dm
+++ b/code/modules/client/verbs/ignore.dm
@@ -6,40 +6,40 @@
if(!key_to_ignore)
return
key_to_ignore = ckey(sanitize(key_to_ignore))
- if(prefs && prefs.ignored_players)
- if(key_to_ignore in prefs.ignored_players)
- to_chat(usr, span_warning("[key_to_ignore] is already being ignored."))
- return
- if(key_to_ignore == usr.ckey)
- to_chat(usr, span_notice("You can't ignore yourself."))
- return
- prefs.ignored_players |= key_to_ignore
- SScharacter_setup.queue_preferences_save(prefs)
- to_chat(usr, span_notice("Now ignoring [key_to_ignore]."))
+ var/list/ignored_players = prefs?.read_preference(/datum/preference/ignored_players)
+ if(!ignored_players)
+ return
+ if(key_to_ignore in ignored_players)
+ to_chat(usr, span_warning("[key_to_ignore] is already being ignored."))
+ return
+ if(key_to_ignore == usr.ckey)
+ to_chat(usr, span_notice("You can't ignore yourself."))
+ return
+
+ ignored_players |= key_to_ignore
+ prefs.write_preference_by_type(/datum/preference/ignored_players, ignored_players)
+ to_chat(usr, span_notice("Now ignoring [key_to_ignore]."))
/client/verb/unignore()
set name = "Unignore"
set category = "OOC.Chat Settings"
set desc = "Reverts your ignoring of a specific player."
- if(!prefs)
- to_chat(usr, span_warning("Preferences not found."))
- return
-
- if(!prefs.ignored_players?.len)
+ var/list/ignored_players = prefs?.read_preference(/datum/preference/ignored_players)
+ if(!LAZYLEN(ignored_players))
to_chat(usr, span_warning("You aren't ignoring any players."))
return
- var/key_to_unignore = tgui_input_list(usr, "Ignored players", "Unignore", prefs.ignored_players)
+ var/key_to_unignore = tgui_input_list(usr, "Ignored players", "Unignore", ignored_players)
if(!key_to_unignore)
return
key_to_unignore = ckey(sanitize(key_to_unignore))
- if(!(key_to_unignore in prefs.ignored_players))
+ if(!(key_to_unignore in ignored_players))
to_chat(usr, span_warning("[key_to_unignore] isn't being ignored."))
return
- prefs.ignored_players -= key_to_unignore
- SScharacter_setup.queue_preferences_save(prefs)
+ ignored_players -= key_to_unignore
+ prefs.write_preference_by_type(/datum/preference/ignored_players, ignored_players)
to_chat(usr, span_notice("Reverted ignore on [key_to_unignore]."))
/mob/proc/is_key_ignored(var/key_to_check)
@@ -49,7 +49,8 @@
/client/proc/is_key_ignored(var/key_to_check)
key_to_check = ckey(key_to_check)
- if(key_to_check in prefs.ignored_players)
+ var/list/ignored_players = prefs?.read_preference(/datum/preference/ignored_players)
+ if(key_to_check in ignored_players)
if(GLOB.directory[key_to_check] in GLOB.admins) // This is here so this is only evaluated if someone is actually being blocked.
return 0
return 1
diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm
index b07704693e..1dd7a74506 100644
--- a/code/modules/client/verbs/ooc.dm
+++ b/code/modules/client/verbs/ooc.dm
@@ -73,8 +73,9 @@
display_name = "[holder.fakekey]/([src.key])"
else
display_name = holder.fakekey
- if(holder && !holder.fakekey && (holder.rights & R_ADMIN|R_FUN|R_EVENT) && CONFIG_GET(flag/allow_admin_ooccolor) && (src.prefs.ooccolor != initial(src.prefs.ooccolor))) // keeping this for the badmins
- to_chat(target, span_ooc("" + create_text_tag("ooc", "OOC:", target) + " [display_name]: [span_message(msg)]"))
+ var/pref_color = prefs.read_preference(/datum/preference/color/ooc_color)
+ if(holder && !holder.fakekey && (holder.rights & R_ADMIN|R_FUN|R_EVENT) && CONFIG_GET(flag/allow_admin_ooccolor) && pref_color != "#010000") // keeping this for the badmins
+ to_chat(target, span_ooc("" + create_text_tag("ooc", "OOC:", target) + " [display_name]: [span_message(msg)]"))
else
to_chat(target, span_ooc("" + create_text_tag("ooc", "OOC:", target) + " [display_name]: " + span_message(msg)) + "")
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index 1ad8ceb73c..5b2d31cdfc 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -138,10 +138,7 @@
ai_holder.on_hear_say(speaker, multilingual_to_message(message_pieces))
/mob/proc/on_hear_say(var/message, var/mob/speaker = null)
- var/time = say_timestamp()
if(client)
- if(client.prefs.chat_timestamp)
- message = "[time] [message]"
message = span_game(span_say(message))
if(speaker && !speaker.client)
message = span_npc_say(message)
@@ -154,10 +151,7 @@
to_chat(src, span_game(span_say(message)))
/mob/living/silicon/on_hear_say(var/message, var/mob/speaker = null)
- var/time = say_timestamp()
if(client)
- if(client.prefs.chat_timestamp)
- message = "[time] [message]"
message = span_game(span_say(message))
if(speaker && !speaker.client)
message = span_npc_say(message)
@@ -219,13 +213,8 @@
else
on_hear_radio(part_a, part_b, speaker_name, track, part_c, message, part_d, part_e)
-/proc/say_timestamp()
- return span_say_quote("\[[time2text(world.timeofday, "hh:mm")]\]")
-
/mob/proc/on_hear_radio(part_a, part_b, speaker_name, track, part_c, formatted, part_d, part_e)
var/time = ""
- if(client.prefs.chat_timestamp)
- time = say_timestamp()
var/final_message = "[part_b][speaker_name][part_c][formatted][part_d]"
if(check_mentioned(formatted) && client?.prefs?.read_preference(/datum/preference/toggle/check_mention))
final_message = "[time][part_a]" + span_large(span_bold("[final_message]")) + "[part_e]"
@@ -235,8 +224,6 @@
/mob/observer/dead/on_hear_radio(part_a, part_b, speaker_name, track, part_c, formatted, part_d, part_e)
var/time = ""
- if(client.prefs.chat_timestamp)
- time = say_timestamp()
var/final_message = "[part_b][track][part_c][formatted][part_d]"
if(check_mentioned(formatted) && client?.prefs?.read_preference(/datum/preference/toggle/check_mention))
final_message = "[time][part_a]" + span_large(span_bold("[final_message]")) + "[part_e]"
@@ -246,8 +233,6 @@
/mob/living/silicon/on_hear_radio(part_a, part_b, speaker_name, track, part_c, formatted, part_d, part_e)
var/time = ""
- if(client.prefs.chat_timestamp)
- time = say_timestamp()
var/final_message = "[part_b][speaker_name][part_c][formatted][part_d]"
if(check_mentioned(formatted) && client?.prefs?.read_preference(/datum/preference/toggle/check_mention))
final_message = "[time][part_a]" + span_large(span_bold("[final_message]")) + "[part_e]"
@@ -257,8 +242,6 @@
/mob/living/silicon/ai/on_hear_radio(part_a, part_b, speaker_name, track, part_c, formatted, part_d, part_e)
var/time = ""
- if(client.prefs.chat_timestamp)
- time = say_timestamp()
var/final_message = "[part_b][track][part_c][formatted][part_d]"
if(check_mentioned(formatted) && client?.prefs?.read_preference(/datum/preference/toggle/check_mention))
final_message = "[time][part_a]" + span_large(span_bold("[final_message]")) + "[part_e]"
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index b1244ee799..2e15db1258 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -45,8 +45,6 @@
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/age = 30 //Player's age (pure fluff)
- var/bday_month = 0 //Character birth month
- var/bday_day = 0 //Character birthday day
var/b_type = "A+" //Player's bloodtype
var/datum/robolimb/synthetic //If they are a synthetic (aka synthetic torso). Also holds the datum for the type of robolimb.
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index a599ff38e2..5fa23cb821 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -62,7 +62,7 @@
//Check if we're on fire
handle_fire()
- if(client && !(client.prefs.ambience_freq == 0)) // Handle re-running ambience to mobs if they've remained in an area, AND have an active client assigned to them, and do not have repeating ambience disabled.
+ if(client) // Handle re-running ambience to mobs if they've remained in an area, AND have an active client assigned to them, and do not have repeating ambience disabled.
handle_ambience()
//stuff in the stomach
@@ -109,7 +109,11 @@
return
/mob/living/proc/handle_ambience() // If you're in an ambient area and have not moved out of it for x time as configured per-client, and do not have it disabled, we're going to play ambience again to you, to help break up the silence.
- if(world.time >= (lastareachange + client.prefs.ambience_freq MINUTES)) // Every 5 minutes (by default, set per-client), we're going to run a 35% chance (by default, also set per-client) to play ambience.
+ var/pref = read_preference(/datum/preference/numeric/ambience_freq)
+ if(!pref)
+ return
+
+ if(world.time >= (lastareachange + pref MINUTES)) // Every 5 minutes (by default, set per-client), we're going to run a 35% chance (by default, also set per-client) to play ambience.
var/area/A = get_area(src)
if(A)
lastareachange = world.time // This will refresh the last area change to prevent this call happening LITERALLY every life tick.
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index e2e3b10d2f..1b53fc9565 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -726,7 +726,7 @@
ooc_notes_window(usr)
// to_chat(usr, span_filter_notice("[src]'s Metainfo:
[ooc_notes]"))
else if(client)
- to_chat(usr, span_filter_notice("[src]'s Metainfo:
[client.prefs.metadata]"))
+ to_chat(usr, span_filter_notice("[src]'s Metainfo:
[client.prefs.read_preference(/datum/preference/text/living/ooc_notes)]"))
else
to_chat(usr, span_filter_notice("[src] does not have any stored infomation!"))
else
diff --git a/code/modules/mob/living/living_vr.dm b/code/modules/mob/living/living_vr.dm
index 57d054e424..2161c54951 100644
--- a/code/modules/mob/living/living_vr.dm
+++ b/code/modules/mob/living/living_vr.dm
@@ -32,7 +32,7 @@
var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see, such as Roleplay-preferences. This will not be saved permanently unless you click save in the OOC notes panel!", "Game Preference" , html_decode(ooc_notes), multiline = TRUE, prevent_enter = TRUE))
if(new_metadata && CanUseTopic(usr))
ooc_notes = new_metadata
- client.prefs.metadata = new_metadata
+ client.prefs.update_preference_by_type(/datum/preference/text/living/ooc_notes, new_metadata)
to_chat(usr, span_filter_notice("OOC notes updated. Don't forget to save!"))
log_admin("[key_name(usr)] updated their OOC notes mid-round.")
ooc_notes_window(usr)
@@ -45,7 +45,7 @@
var/new_metadata = strip_html_simple(tgui_input_text(usr, "Enter any information you'd like others to see, such as Roleplay-preferences. This will not be saved permanently unless you click save in the OOC notes panel!", "Game Preference" , html_decode(ooc_notes), multiline = TRUE, prevent_enter = TRUE))
if(new_metadata && CanUseTopic(usr))
ooc_notes = new_metadata
- client.prefs.metadata = new_metadata
+ client.prefs.update_preference_by_type(/datum/preference/text/living/ooc_notes, new_metadata)
to_chat(usr, span_filter_notice("OOC notes updated. Don't forget to save!"))
log_admin("[key_name(usr)] updated their OOC notes mid-round.")
ooc_notes_window(usr)
@@ -58,7 +58,7 @@
if(new_metadata == "!clear")
new_metadata = ""
ooc_notes_likes = new_metadata
- client.prefs.metadata_likes = new_metadata
+ client.prefs.update_preference_by_type(/datum/preference/text/living/ooc_notes_likes, new_metadata)
to_chat(usr, span_filter_notice("OOC note likes have been updated. Don't forget to save!"))
log_admin("[key_name(usr)] updated their OOC note likes mid-round.")
if(reopen)
@@ -72,7 +72,7 @@
if(new_metadata == "!clear")
new_metadata = ""
ooc_notes_dislikes = new_metadata
- client.prefs.metadata_dislikes = new_metadata
+ client.prefs.update_preference_by_type(/datum/preference/text/living/ooc_notes_dislikes, new_metadata)
to_chat(usr, span_filter_notice("OOC note dislikes have been updated. Don't forget to save!"))
log_admin("[key_name(usr)] updated their OOC note dislikes mid-round.")
if(reopen)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 74467c67a9..a484ca2af1 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -210,11 +210,9 @@ var/list/ai_verbs_default = list(
// Vorestation Edit: Meta Info for AI's. Mostly used for Holograms
if (client)
- var/meta_info = client.prefs.metadata
- if (meta_info)
- ooc_notes = meta_info
- ooc_notes_likes = client.prefs.metadata_likes
- ooc_notes_dislikes = client.prefs.metadata_dislikes
+ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes)
+ ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes)
+ ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes)
if (malf && !(mind in malf.current_antagonists))
show_laws()
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 8d22b5e96d..0e2d1056f9 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -149,9 +149,9 @@
..()
// Vorestation Edit: Meta Info for pAI
if (client.prefs)
- ooc_notes = client.prefs.metadata
- ooc_notes_likes = client.prefs.metadata_likes
- ooc_notes_dislikes = client.prefs.metadata_dislikes
+ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes)
+ ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes)
+ ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes)
src << sound('sound/effects/pai_login.ogg', volume = 75) //VOREStation Add
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 1c07efe363..a65e36aef5 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -404,11 +404,9 @@
else
flavor_text = client.prefs.flavour_texts_robot["Default"]
// Vorestation Edit: and meta info
- var/meta_info = client.prefs.metadata
- if (meta_info)
- ooc_notes = meta_info
- ooc_notes_likes = client.prefs.metadata_likes
- ooc_notes_dislikes = client.prefs.metadata_dislikes
+ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes)
+ ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes)
+ ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes)
custom_link = client.prefs.custom_link
/mob/living/silicon/robot/verb/namepick()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
index f30f34a184..d356e40416 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
@@ -17,9 +17,9 @@
/mob/living/proc/login_prefs()
- ooc_notes = client.prefs.metadata
- ooc_notes_likes = client.prefs.metadata_likes
- ooc_notes_dislikes = client.prefs.metadata_dislikes
+ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes)
+ ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes)
+ ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes)
digestable = client.prefs_vr.digestable
devourable = client.prefs_vr.devourable
absorbable = client.prefs_vr.absorbable
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 49b1a81ec2..c311aba294 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -36,11 +36,6 @@
qdel(hud_used) //remove the hud objects
new /datum/hud(src)
- if(client.prefs && client.prefs.client_fps)
- client.fps = client.prefs.client_fps
- else
- client.fps = 0 // Results in using the server FPS
-
next_move = 1
disconnect_time = null //VOREStation Addition: clear the disconnect time
sight |= SEE_SELF
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index dfbb609727..7d304fd678 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -69,8 +69,6 @@
//return QDEL_HINT_HARDDEL_NOW Just keep track of mob references. They delete SO much faster now.
/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
- var/time = say_timestamp()
-
if(!client && !teleop) return
if (type)
@@ -92,12 +90,7 @@
if(stat == UNCONSCIOUS || sleeping > 0)
to_chat(src, span_filter_notice(span_italics("... You can almost hear someone talking ...")))
else
- if(client && client.prefs.chat_timestamp)
- // TG-Chat filters latch directly to the spans, we no longer need that
- //msg = replacetext(msg, new/regex("^(]*)?>)((?:.|\\n)*)", ""), "$1[time] $2") // Insteres timestamps after the first qualifying span
- //msg = replacetext(msg, new/regex("^\[^<]((?:.|\\n)*)", ""), "[time] $1") // Spanless messages also get timestamped
- to_chat(src,"[time] [msg]")
- else if(teleop)
+ if(teleop)
to_chat(teleop, create_text_tag("body", "BODY:", teleop.client) + "[msg]")
else
to_chat(src,msg)
@@ -479,13 +472,6 @@
set category = "OOC.Resources"
src << link("https://wiki.vore-station.net/Changelog")
- /*
- if(prefs.lastchangelog != changelog_hash)
- prefs.lastchangelog = changelog_hash
- SScharacter_setup.queue_preferences_save(prefs)
- winset(src, "rpane.changelog", "background-color=none;font-style=;")
- */
-
/mob/verb/observe()
set name = "Observe"
set category = "OOC.Game"
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 76c28cb5a7..76cb63eaa4 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -138,11 +138,13 @@
var/datum/job/refJob = null
for(var/mob/new_player/player in player_list)
refJob = player.client.prefs.get_highest_job()
- if(player.client.prefs.obfuscate_key && player.client.prefs.obfuscate_job)
+ var/obfuscate_key = player.client.prefs.read_preference(/datum/preference/toggle/obfuscate_key)
+ var/obfuscate_job = player.client.prefs.read_preference(/datum/preference/toggle/obfuscate_job)
+ if(obfuscate_key && obfuscate_job)
. += "Anonymous User [player.ready ? "Ready!" : null]"
- else if(player.client.prefs.obfuscate_key)
+ else if(obfuscate_key)
. += "Anonymous User [player.ready ? "(Playing as: [refJob ? refJob.title : "Unknown"])" : null]"
- else if(player.client.prefs.obfuscate_job)
+ else if(obfuscate_job)
. += "[player.key] [player.ready ? "Ready!" : null]"
else
. += "[player.key] [player.ready ? "(Playing as: [refJob ? refJob.title : "Unknown"])" : null]"
@@ -193,7 +195,7 @@
announce_ghost_joinleave(src)
- if(client.prefs.be_random_name)
+ if(client.prefs.read_preference(/datum/preference/toggle/human/name_is_always_random))
client.prefs.real_name = random_name(client.prefs.identifying_gender)
observer.real_name = client.prefs.real_name
observer.name = observer.real_name
diff --git a/code/modules/mob/new_player/new_player_vr.dm b/code/modules/mob/new_player/new_player_vr.dm
index d1587a6f43..0edc039deb 100644
--- a/code/modules/mob/new_player/new_player_vr.dm
+++ b/code/modules/mob/new_player/new_player_vr.dm
@@ -12,7 +12,7 @@
pass = FALSE
//No OOC notes
- if (CONFIG_GET(flag/allow_metadata) && (!client?.prefs?.metadata || length(client.prefs.metadata) < 15))
+ if (CONFIG_GET(flag/allow_metadata) && (!client?.prefs?.read_preference(/datum/preference/text/living/ooc_notes) || length(client.prefs.read_preference(/datum/preference/text/living/ooc_notes)) < 15))
to_chat(src,span_warning("Please set informative OOC notes related to RP/ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup."))
pass = FALSE
diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm
index b2a03e9cf9..634e7b8637 100644
--- a/code/modules/mob/new_player/preferences_setup.dm
+++ b/code/modules/mob/new_player/preferences_setup.dm
@@ -1,4 +1,38 @@
/datum/preferences
+
+/datum/preferences/proc/randomise_appearance_prefs_update(randomize_flags = ALL, datum/species/current_species)
+ randomise_appearance_prefs(randomize_flags, current_species)
+
+/datum/preferences/proc/randomise_appearance_prefs_write(randomize_flags = ALL, datum/species/current_species)
+ randomise_appearance_prefs(randomize_flags, current_species, TRUE)
+
+/// Fully randomizes everything in the character.
+/datum/preferences/proc/randomise_appearance_prefs(randomize_flags = ALL, datum/species/current_species, write = FALSE)
+ for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
+ if (!preference.included_in_randomization_flags(randomize_flags))
+ continue
+ if (preference.is_randomizable())
+ if(write)
+ write_preference(preference, preference.create_random_value(src, current_species))
+ else
+ update_preference(preference, preference.create_random_value(src, current_species))
+
+/* Currently not used
+/// Randomizes the character according to preferences.
+/datum/preferences/proc/apply_character_randomization_prefs(antag_override = FALSE)
+ switch (read_preference(/datum/preference/choiced/random_body))
+ if (RANDOM_ANTAG_ONLY)
+ if (!antag_override)
+ return
+
+ if (RANDOM_DISABLED)
+ return
+
+ for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
+ if (should_randomize(preference, antag_override))
+ write_preference(preference, preference.create_random_value(src))
+*/
+
//The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/randomize_appearance_and_body_for(var/mob/living/carbon/human/H)
var/datum/species/current_species = GLOB.all_species[species ? species : "Human"]
@@ -10,18 +44,12 @@
if(current_species.appearance_flags & HAS_SKIN_TONE)
s_tone = random_skin_tone()
if(current_species.appearance_flags & HAS_SKIN_COLOR)
- r_skin = rand (0,255)
- g_skin = rand (0,255)
- b_skin = rand (0,255)
+ update_preference_by_type(/datum/preference/color/human/skin_color, rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
if(current_species.appearance_flags & HAS_EYE_COLOR)
randomize_eyes_color()
if(current_species.appearance_flags & HAS_HAIR_COLOR)
randomize_hair_color("hair")
randomize_hair_color("facial")
- if(current_species.appearance_flags & HAS_SKIN_COLOR)
- r_skin = rand (0,255)
- g_skin = rand (0,255)
- b_skin = rand (0,255)
if(current_species.appearance_flags & HAS_UNDERWEAR)
all_underwear.Cut()
for(var/datum/category_group/underwear/WRC in global_underwear.categories)
@@ -32,7 +60,7 @@
headset = rand(1,3)
backbag = rand(1,6)
pdachoice = rand(1,7)
- age = rand(current_species.min_age, current_species.max_age)
+ randomise_appearance_prefs_update(current_species = current_species)
b_type = RANDOM_BLOOD_TYPE
if(H)
copy_to(H,1)
@@ -40,9 +68,7 @@
/datum/preferences/proc/randomize_hair_color(var/target = "hair")
if(prob (75) && target == "facial") // Chance to inherit hair color
- r_facial = r_hair
- g_facial = g_hair
- b_facial = b_hair
+ update_preference_by_type(/datum/preference/color/human/facial_color, read_preference(/datum/preference/color/human/hair_color))
return
var/red
@@ -90,13 +116,9 @@
switch(target)
if("hair")
- r_hair = red
- g_hair = green
- b_hair = blue
+ update_preference_by_type(/datum/preference/color/human/hair_color, rgb(red, green, blue))
if("facial")
- r_facial = red
- g_facial = green
- b_facial = blue
+ update_preference_by_type(/datum/preference/color/human/facial_color, rgb(red, green, blue))
/datum/preferences/proc/randomize_eyes_color()
var/red
@@ -142,9 +164,7 @@
green = max(min(green + rand (-25, 25), 255), 0)
blue = max(min(blue + rand (-25, 25), 255), 0)
- r_eyes = red
- g_eyes = green
- b_eyes = blue
+ update_preference_by_type(/datum/preference/color/human/eyes_color, rgb(red, green, blue))
/datum/preferences/proc/randomize_skin_color()
var/red
@@ -190,9 +210,7 @@
green = max(min(green + rand (-25, 25), 255), 0)
blue = max(min(blue + rand (-25, 25), 255), 0)
- r_skin = red
- g_skin = green
- b_skin = blue
+ update_preference_by_type(/datum/preference/color/human/skin_color, rgb(red, green, blue))
/datum/preferences/proc/dress_preview_mob(var/mob/living/carbon/human/mannequin)
if(!mannequin.dna) // Special handling for preview icons before SSAtoms has initailized.
diff --git a/code/modules/tgui/modules/late_choices.dm b/code/modules/tgui/modules/late_choices.dm
index 1a3f86eeab..e7a93b41ac 100644
--- a/code/modules/tgui/modules/late_choices.dm
+++ b/code/modules/tgui/modules/late_choices.dm
@@ -50,14 +50,14 @@
return TRUE
var/min_age = job.get_min_age(prefs.species, prefs.organ_data["brain"])
- if(prefs.age >= min_age)
+ if(prefs.read_preference(/datum/preference/numeric/human/age) >= min_age)
return TRUE
return FALSE
/datum/tgui_module/late_choices/tgui_data(mob/new_player/user)
var/list/data = ..()
- var/name = user.client.prefs.be_random_name ? "friend" : user.client.prefs.real_name
+ var/name = user.client.prefs.read_preference(/datum/preference/toggle/human/name_is_always_random) ? "friend" : user.client.prefs.real_name
data["name"] = name
data["duration"] = roundduration2text()
@@ -134,4 +134,4 @@
tgui_alert_async(new_user,"Your current species, [new_user.client.prefs.species], is not available for play on the station.")
return 0
- new_user.AttemptLateSpawn(job, new_user.client.prefs.spawnpoint)
+ new_user.AttemptLateSpawn(job, new_user.read_preference(/datum/preference/choiced/human/spawnpoint))
diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm
index ad5675d092..c95ab2ff64 100644
--- a/code/modules/tgui/tgui.dm
+++ b/code/modules/tgui/tgui.dm
@@ -104,7 +104,7 @@
if(!window.is_ready())
window.initialize(
strict_mode = TRUE,
- fancy = user.client.prefs.tgui_fancy,
+ fancy = user.read_preference(/datum/preference/toggle/tgui_fancy),
assets = list(
// FIXME: Delete this when 516 is required!
user.client.byond_version >= 516 \
@@ -269,8 +269,8 @@
"window" = list(
"key" = window_key,
"size" = window_size,
- "fancy" = user.client.prefs.tgui_fancy,
- "locked" = user.client.prefs.tgui_lock,
+ "fancy" = user.read_preference(/datum/preference/toggle/tgui_fancy),
+ "locked" = user.read_preference(/datum/preference/toggle/tgui_lock),
),
"client" = list(
"ckey" = user.client.ckey,
diff --git a/code/modules/tgui_input/alert.dm b/code/modules/tgui_input/alert.dm
index 9b658090b9..80a80228ac 100644
--- a/code/modules/tgui_input/alert.dm
+++ b/code/modules/tgui_input/alert.dm
@@ -31,7 +31,7 @@
// return tgui_input_list(user, message, title, buttons, timeout, autofocus)
// Client does NOT have tgui_input on: Returns regular input
- if(!user.client.prefs.tgui_input_mode || strict_byond)
+ if(!user.read_preference(/datum/preference/toggle/tgui_input_mode) || strict_byond)
if(length(buttons) == 2)
return alert(user, message, title, buttons[1], buttons[2])
if(length(buttons) == 3)
@@ -109,8 +109,8 @@
data["autofocus"] = autofocus
data["buttons"] = buttons
data["message"] = message
- data["large_buttons"] = user.client.prefs.tgui_large_buttons
- data["swapped_buttons"] = !user.client.prefs.tgui_swapped_buttons
+ data["large_buttons"] = user.read_preference(/datum/preference/toggle/tgui_large_buttons)
+ data["swapped_buttons"] = !user.read_preference(/datum/preference/toggle/tgui_swapped_buttons)
data["title"] = title
return data
diff --git a/code/modules/tgui_input/checkboxes.dm b/code/modules/tgui_input/checkboxes.dm
index 1d67fea059..1732f474e1 100644
--- a/code/modules/tgui_input/checkboxes.dm
+++ b/code/modules/tgui_input/checkboxes.dm
@@ -25,7 +25,7 @@
if(isnull(user.client))
return null
- if(!user.client.prefs.tgui_input_mode)
+ if(!user.read_preference(/datum/preference/toggle/tgui_input_mode))
return input(user, message, title) as null|anything in items
var/datum/tgui_checkbox_input/input = new(user, message, title, items, min_checked, max_checked, timeout, ui_state)
input.tgui_interact(user)
@@ -108,9 +108,9 @@
data["items"] = items
data["min_checked"] = min_checked
data["max_checked"] = max_checked
- data["large_buttons"] = user.client.prefs.tgui_large_buttons
+ data["large_buttons"] = user.read_preference(/datum/preference/toggle/tgui_large_buttons)
data["message"] = message
- data["swapped_buttons"] = !user.client.prefs.tgui_swapped_buttons
+ data["swapped_buttons"] = !user.read_preference(/datum/preference/toggle/tgui_swapped_buttons)
data["title"] = title
return data
diff --git a/code/modules/tgui_input/list.dm b/code/modules/tgui_input/list.dm
index bd51aee060..00531a09a5 100644
--- a/code/modules/tgui_input/list.dm
+++ b/code/modules/tgui_input/list.dm
@@ -26,7 +26,7 @@
return null
/// Client does NOT have tgui_input on: Returns regular input
- if(!user.client.prefs.tgui_input_mode && !strict_modern)
+ if(!user.read_preference(/datum/preference/toggle/tgui_input_mode) && !strict_modern)
return input(user, message, title, default) as null|anything in items
var/datum/tgui_list_input/input = new(user, message, title, items, default, timeout, ui_state)
if(input.invalid)
@@ -125,9 +125,9 @@
var/list/data = list()
data["init_value"] = default || items[1]
data["items"] = items
- data["large_buttons"] = user.client.prefs.tgui_large_buttons
+ data["large_buttons"] = user.read_preference(/datum/preference/toggle/tgui_large_buttons)
data["message"] = message
- data["swapped_buttons"] = !user.client.prefs.tgui_swapped_buttons
+ data["swapped_buttons"] = !user.read_preference(/datum/preference/toggle/tgui_swapped_buttons)
data["title"] = title
return data
diff --git a/code/modules/tgui_input/number.dm b/code/modules/tgui_input/number.dm
index ddb7f8a195..b6d7419108 100644
--- a/code/modules/tgui_input/number.dm
+++ b/code/modules/tgui_input/number.dm
@@ -29,7 +29,7 @@
return null
// Client does NOT have tgui_input on: Returns regular input
- if(!user.client.prefs.tgui_input_mode)
+ if(!user.read_preference(/datum/preference/toggle/tgui_input_mode))
var/input_number = input(user, message, title, default) as null|num
return clamp(round_value ? round(input_number) : input_number, min_value, max_value)
var/datum/tgui_input_number/number_input = new(user, message, title, default, max_value, min_value, timeout, round_value, ui_state)
@@ -121,11 +121,11 @@
/datum/tgui_input_number/tgui_static_data(mob/user)
var/list/data = list()
data["init_value"] = default // Default is a reserved keyword
- data["large_buttons"] = user.client.prefs.tgui_large_buttons
+ data["large_buttons"] = user.read_preference(/datum/preference/toggle/tgui_large_buttons)
data["max_value"] = max_value
data["message"] = message
data["min_value"] = min_value
- data["swapped_buttons"] = !user.client.prefs.tgui_swapped_buttons
+ data["swapped_buttons"] = !user.read_preference(/datum/preference/toggle/tgui_swapped_buttons)
data["title"] = title
data["round_value"] = round_value
return data
diff --git a/code/modules/tgui_input/text.dm b/code/modules/tgui_input/text.dm
index d02ef216ac..a4a7f080a5 100644
--- a/code/modules/tgui_input/text.dm
+++ b/code/modules/tgui_input/text.dm
@@ -29,7 +29,7 @@
return null
// Client does NOT have tgui_input on: Returns regular input
- if(!user.client.prefs.tgui_input_mode)
+ if(!user.read_preference(/datum/preference/toggle/tgui_input_mode))
if(encode)
if(multiline)
return stripped_multiline_input(user, message, title, default, PREVENT_CHARACTER_TRIM_LOSS(max_length))
@@ -115,12 +115,12 @@
/datum/tgui_input_text/tgui_static_data(mob/user)
var/list/data = list()
- data["large_buttons"] = user.client.prefs.tgui_large_buttons
+ data["large_buttons"] = user.read_preference(/datum/preference/toggle/tgui_large_buttons)
data["max_length"] = max_length
data["message"] = message
data["multiline"] = multiline
data["placeholder"] = default // Default is a reserved keyword
- data["swapped_buttons"] = !user.client.prefs.tgui_swapped_buttons
+ data["swapped_buttons"] = !user.read_preference(/datum/preference/toggle/tgui_swapped_buttons)
data["title"] = title
return data
diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm
index 5556c525a6..27c0e79d6f 100644
--- a/code/modules/tooltip/tooltip.dm
+++ b/code/modules/tooltip/tooltip.dm
@@ -123,7 +123,7 @@ Notes:
/proc/openToolTip(mob/user = null, atom/movable/tip_src = null, params = null, title = "", content = "", theme = "")
if(!istype(user) || !user.client?.tooltips)
return
- var/ui_style = user.client?.prefs?.tooltipstyle
+ var/ui_style = user.read_preference(/datum/preference/choiced/tooltip_style)
if(!theme && ui_style)
theme = lowertext(ui_style)
if(!theme)
diff --git a/code/modules/vore/persist/persist_vr.dm b/code/modules/vore/persist/persist_vr.dm
index bc96b1d82a..463f12aab7 100644
--- a/code/modules/vore/persist/persist_vr.dm
+++ b/code/modules/vore/persist/persist_vr.dm
@@ -91,7 +91,7 @@
// Okay we can start saving the data
if(new_spawn_point_type && prefs.persistence_settings & PERSIST_SPAWN)
- prefs.spawnpoint = initial(new_spawn_point_type.display_name)
+ prefs.update_preference_by_type(/datum/preference/choiced/human/spawnpoint, initial(new_spawn_point_type.display_name))
if(ishuman(occupant) && occupant.stat != DEAD)
var/mob/living/carbon/human/H = occupant
testing("Persist (PID): Saving stuff from [H] to [prefs] (\ref[prefs]).")
@@ -112,20 +112,14 @@
// This basically needs to be the reverse of /datum/category_item/player_setup_item/general/body/copy_to_mob() ~Leshana
/proc/apply_coloration_to_prefs(var/mob/living/carbon/human/character, var/datum/preferences/prefs)
if(!istype(character)) return
- prefs.r_eyes = character.r_eyes
- prefs.g_eyes = character.g_eyes
- prefs.b_eyes = character.b_eyes
prefs.h_style = character.h_style
- prefs.r_hair = character.r_hair
- prefs.g_hair = character.g_hair
- prefs.b_hair = character.b_hair
+
+ prefs.update_preference_by_type(/datum/preference/color/human/eyes_color, rgb(character.r_eyes, character.g_eyes, character.b_eyes))
+ prefs.update_preference_by_type(/datum/preference/color/human/hair_color, rgb(character.r_hair, character.g_hair, character.b_hair))
+ prefs.update_preference_by_type(/datum/preference/color/human/facial_color, rgb(character.r_facial, character.g_facial, character.b_facial))
+ prefs.update_preference_by_type(/datum/preference/color/human/skin_color, rgb(character.r_skin, character.g_skin, character.b_skin))
+
prefs.f_style = character.f_style
- prefs.r_facial = character.r_facial
- prefs.g_facial = character.g_facial
- prefs.b_facial = character.b_facial
- prefs.r_skin = character.r_skin
- prefs.g_skin = character.g_skin
- prefs.b_skin = character.b_skin
prefs.s_tone = character.s_tone
prefs.h_style = character.h_style
prefs.f_style = character.f_style
@@ -137,38 +131,24 @@
if(character.ear_style) prefs.ear_style = character.ear_style.name
if(character.tail_style) prefs.tail_style = character.tail_style.name
if(character.wing_style) prefs.wing_style = character.wing_style.name
- prefs.r_ears = character.r_ears
- prefs.g_ears = character.g_ears
- prefs.b_ears = character.b_ears
- prefs.r_ears2 = character.r_ears2
- prefs.g_ears2 = character.g_ears2
- prefs.b_ears2 = character.b_ears2
- prefs.r_ears3 = character.r_ears3
- prefs.g_ears3 = character.g_ears3
- prefs.b_ears3 = character.b_ears3
+
+ prefs.update_preference_by_type(/datum/preference/color/human/ears_color1, rgb(character.r_ears, character.g_ears, character.b_ears))
+ prefs.update_preference_by_type(/datum/preference/color/human/ears_color2, rgb(character.r_ears2, character.g_ears2, character.b_ears2))
+ prefs.update_preference_by_type(/datum/preference/color/human/ears_color3, rgb(character.r_ears3, character.g_ears3, character.b_ears3))
// secondary ears
prefs.ear_secondary_style = character.ear_secondary_style?.name
prefs.ear_secondary_colors = character.ear_secondary_colors
- prefs.r_tail = character.r_tail
- prefs.b_tail = character.b_tail
- prefs.g_tail = character.g_tail
- prefs.r_tail2 = character.r_tail2
- prefs.b_tail2 = character.b_tail2
- prefs.g_tail2 = character.g_tail2
- prefs.r_tail3 = character.r_tail3
- prefs.b_tail3 = character.b_tail3
- prefs.g_tail3 = character.g_tail3
- prefs.r_wing = character.r_wing
- prefs.b_wing = character.b_wing
- prefs.g_wing = character.g_wing
- prefs.r_wing2 = character.r_wing2
- prefs.b_wing2 = character.b_wing2
- prefs.g_wing2 = character.g_wing2
- prefs.r_wing3 = character.r_wing3
- prefs.b_wing3 = character.b_wing3
- prefs.g_wing3 = character.g_wing3
+ prefs.update_preference_by_type(/datum/preference/color/human/tail_color1, rgb(character.r_tail, character.g_tail, character.b_tail))
+ prefs.update_preference_by_type(/datum/preference/color/human/tail_color2, rgb(character.r_tail2, character.g_tail2, character.b_tail2))
+ prefs.update_preference_by_type(/datum/preference/color/human/tail_color3, rgb(character.r_tail3, character.g_tail3, character.b_tail3))
+
+ // TODO: This will break if update_preference_by_type starts to respect is_accessible
+ prefs.update_preference_by_type(/datum/preference/color/human/wing_color1, rgb(character.r_wing, character.g_wing, character.b_wing))
+ prefs.update_preference_by_type(/datum/preference/color/human/wing_color2, rgb(character.r_wing2, character.g_wing2, character.b_wing2))
+ prefs.update_preference_by_type(/datum/preference/color/human/wing_color3, rgb(character.r_wing3, character.g_wing3, character.b_wing3))
+
prefs.custom_species = character.custom_species
prefs.digitigrade = character.digitigrade
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx
index f9f8fec97b..62098710d8 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx
@@ -1,4 +1,9 @@
-import { CheckboxInput, FeatureToggle } from '../base';
+import {
+ CheckboxInput,
+ Feature,
+ FeatureColorInput,
+ FeatureToggle,
+} from '../base';
export const CHAT_ATTACKLOGS: FeatureToggle = {
name: 'Attack Log Messages',
@@ -48,3 +53,11 @@ export const CHAT_ADSAY: FeatureToggle = {
description: 'Enables seeing deadchat when not observing.',
component: CheckboxInput,
};
+
+export const ooccolor: Feature = {
+ name: 'OOC Color',
+ category: 'ADMIN',
+ description:
+ 'The color your OOC messages will be. Set to #010000 to use default',
+ component: FeatureColorInput,
+};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/fps.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/fps.tsx
new file mode 100644
index 0000000000..31f9d5276f
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/fps.tsx
@@ -0,0 +1,56 @@
+import { Dropdown, Stack } from 'tgui-core/components';
+
+import { NumberInput } from '../../../../../components';
+import { Feature, FeatureNumericData, FeatureValueProps } from '../base';
+
+type FpsServerData = FeatureNumericData & {
+ recommended_fps: number;
+};
+
+const FpsInput = (props: FeatureValueProps) => {
+ const { handleSetValue, serverData } = props;
+
+ let recommened = `Recommended`;
+ if (serverData) {
+ recommened += ` (${serverData.recommended_fps})`;
+ }
+
+ return (
+
+
+ {
+ if (value === recommened) {
+ handleSetValue(-1);
+ } else {
+ handleSetValue(serverData?.recommended_fps || 60);
+ }
+ }}
+ width="100%"
+ options={[recommened, 'Custom']}
+ />
+
+
+
+ {serverData && props.value !== -1 && (
+ {
+ props.handleSetValue(value);
+ }}
+ minValue={1}
+ maxValue={serverData.maximum}
+ value={props.value}
+ step={1}
+ />
+ )}
+
+
+ );
+};
+
+export const client_fps: Feature = {
+ name: 'FPS',
+ category: 'GAMEPLAY',
+ component: FpsInput,
+};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/misc.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/misc.tsx
index b3e062348c..30af7c11b3 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/misc.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/misc.tsx
@@ -7,20 +7,6 @@ export const AMBIENT_OCCLUSION_PREF: FeatureToggle = {
component: CheckboxInput,
};
-export const MOB_TOOLTIPS: FeatureToggle = {
- name: 'Enable mob tooltips',
- category: 'GAMEPLAY',
- description: 'Enable tooltips when hovering over mobs.',
- component: CheckboxInput,
-};
-
-export const INV_TOOLTIPS: FeatureToggle = {
- name: 'Enable inventory tooltips',
- category: 'GAMEPLAY',
- description: 'Enable tooltips when hovering over inventory items.',
- component: CheckboxInput,
-};
-
export const ATTACK_ICONS: FeatureToggle = {
name: 'Attack Icons',
category: 'GAMEPLAY',
@@ -96,3 +82,17 @@ export const BrowserDevTools: FeatureToggle = {
'When enabled, you can right click -> inspect to open Microsoft Edge dev tools. BYOND 516+ Only.',
component: CheckboxInput,
};
+
+export const obfuscate_key: FeatureToggle = {
+ name: 'Obfuscate Key',
+ category: 'UI',
+ description: 'Hide your byond ckey from other players in the lobby',
+ component: CheckboxInput,
+};
+
+export const obfuscate_job: FeatureToggle = {
+ name: 'Obfuscate Job',
+ category: 'UI',
+ description: 'Hide your job from other players in the lobby',
+ component: CheckboxInput,
+};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sound.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sound.tsx
index 937fe35486..5fa5d207a1 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sound.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sound.tsx
@@ -1,4 +1,9 @@
-import { CheckboxInput, FeatureToggle } from '../base';
+import {
+ CheckboxInput,
+ FeatureNumberInput,
+ FeatureNumeric,
+ FeatureToggle,
+} from '../base';
export const SOUND_MIDI: FeatureToggle = {
name: 'Play Admin MIDIs',
@@ -154,3 +159,19 @@ export const DIGEST_NOISES: FeatureToggle = {
description: 'Enable hearing vore digestion noises.',
component: CheckboxInput,
};
+
+export const ambience_freq: FeatureNumeric = {
+ name: 'Ambience Frequency',
+ category: 'SOUNDS',
+ description:
+ 'How often you wish to hear ambience repeated! (1-60 MINUTES, 0 for disabled)',
+ component: FeatureNumberInput,
+};
+
+export const ambience_chance: FeatureNumeric = {
+ name: 'Ambience Chance',
+ category: 'SOUNDS',
+ description:
+ "The chance you'd like to hear ambience played to you (On area change, or by random ambience). 35 means a 35% chance to play ambience. This is a range from 0-100. 0 disables ambience playing entirely. This is also affected by Ambience Frequency.",
+ component: FeatureNumberInput,
+};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/tooltip.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/tooltip.tsx
new file mode 100644
index 0000000000..52527bd0fe
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/tooltip.tsx
@@ -0,0 +1,22 @@
+import { CheckboxInput, FeatureChoiced, FeatureToggle } from '../base';
+import { FeatureDropdownInput } from '../dropdowns';
+
+export const MOB_TOOLTIPS: FeatureToggle = {
+ name: 'Enable mob tooltips',
+ category: 'TOOLTIPS',
+ description: 'Enable tooltips when hovering over mobs.',
+ component: CheckboxInput,
+};
+
+export const INV_TOOLTIPS: FeatureToggle = {
+ name: 'Enable inventory tooltips',
+ category: 'TOOLTIPS',
+ description: 'Enable tooltips when hovering over inventory items.',
+ component: CheckboxInput,
+};
+
+export const tooltipstyle: FeatureChoiced = {
+ name: 'Tooltip Style',
+ category: 'TOOLTIPS',
+ component: FeatureDropdownInput,
+};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui.tsx
index 45a0f8bb68..4a388e06ba 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui.tsx
@@ -19,6 +19,42 @@ export const VCHAT_ENABLE: FeatureToggle = {
component: CheckboxInput,
};
+export const tgui_fancy: FeatureToggle = {
+ name: 'TGUI: Fancy Mode',
+ category: 'UI',
+ description: 'When enabled, hide the title bar and fully style tgui windows.',
+ component: CheckboxInput,
+};
+
+export const tgui_lock: FeatureToggle = {
+ name: 'TGUI: Window Lock',
+ category: 'UI',
+ description:
+ 'When enabled, forces windows to spawn on the primary monitor - otherwise, any monitor.',
+ component: CheckboxInput,
+};
+
+export const tgui_input_mode: FeatureToggle = {
+ name: 'TGUI: Input Framework',
+ category: 'UI',
+ description: 'Enable TGUI based input for most input dialogs.',
+ component: CheckboxInput,
+};
+
+export const tgui_large_buttons: FeatureToggle = {
+ name: 'TGUI: Large Buttons',
+ category: 'UI',
+ description: 'Use large buttons in TGUI Input windows.',
+ component: CheckboxInput,
+};
+
+export const tgui_swapped_buttons: FeatureToggle = {
+ name: 'TGUI: Swapped Buttons',
+ category: 'UI',
+ description: 'Swap the position of OK and Cancel buttons.',
+ component: CheckboxInput,
+};
+
export const TGUI_SAY: FeatureToggle = {
name: 'Say: Use TGUI',
category: 'UI',
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx
new file mode 100644
index 0000000000..9c048b18da
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx
@@ -0,0 +1,84 @@
+import { classes } from 'common/react';
+import { Box, Dropdown, Stack } from 'tgui-core/components';
+
+import {
+ Feature,
+ FeatureChoiced,
+ FeatureChoicedServerData,
+ FeatureColorInput,
+ FeatureNumberInput,
+ FeatureNumeric,
+ FeatureValueProps,
+ sortChoices,
+} from '../base';
+
+const UIStyleInput = (
+ props: FeatureValueProps,
+) => {
+ const { serverData, value } = props;
+ if (!serverData) {
+ return null;
+ }
+
+ const { icons } = serverData;
+
+ if (!icons) {
+ return ui_style had no icons!;
+ }
+
+ const choices = Object.fromEntries(
+ Object.entries(icons).map(([name, icon]) => {
+ return [
+ name,
+
+
+
+
+
+ {name}
+ ,
+ ];
+ }),
+ );
+
+ return (
+ {
+ return {
+ displayText: label,
+ value: dataValue,
+ };
+ },
+ )}
+ />
+ );
+};
+
+export const UI_style: FeatureChoiced = {
+ name: 'UI Style',
+ category: 'UI',
+ component: UIStyleInput,
+};
+
+export const UI_style_alpha: FeatureNumeric = {
+ name: 'UI Alpha',
+ category: 'UI',
+ component: FeatureNumberInput,
+};
+
+export const UI_style_color: Feature = {
+ name: 'UI Color',
+ category: 'UI',
+ component: FeatureColorInput,
+};
diff --git a/vorestation.dme b/vorestation.dme
index b045f13606..7f0b1f0ef9 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2087,10 +2087,7 @@
#include "code\modules\client\preference_setup\general\04_equipment.dm"
#include "code\modules\client\preference_setup\general\05_background.dm"
#include "code\modules\client\preference_setup\general\06_flavor.dm"
-#include "code\modules\client\preference_setup\global\01_ui.dm"
-#include "code\modules\client\preference_setup\global\02_settings.dm"
#include "code\modules\client\preference_setup\global\03_pai.dm"
-#include "code\modules\client\preference_setup\global\04_ooc.dm"
#include "code\modules\client\preference_setup\loadout\gear_tweaks.dm"
#include "code\modules\client\preference_setup\loadout\gear_tweaks_vr.dm"
#include "code\modules\client\preference_setup\loadout\loadout.dm"
@@ -2137,17 +2134,26 @@
#include "code\modules\client\preferences\_preference.dm"
#include "code\modules\client\preferences\preferences_tg.dm"
#include "code\modules\client\preferences\middleware\_middleware.dm"
+#include "code\modules\client\preferences\middleware\random.dm"
#include "code\modules\client\preferences\migrations\13_preferences.dm"
#include "code\modules\client\preferences\migrations\14_nifs.dm"
#include "code\modules\client\preferences\migrations\15_nif_path.dm"
-#include "code\modules\client\preferences\types\admin.dm"
-#include "code\modules\client\preferences\types\auto_fit_viewport.dm"
-#include "code\modules\client\preferences\types\chat.dm"
-#include "code\modules\client\preferences\types\ghost.dm"
-#include "code\modules\client\preferences\types\misc.dm"
-#include "code\modules\client\preferences\types\runechat.dm"
-#include "code\modules\client\preferences\types\sound.dm"
-#include "code\modules\client\preferences\types\ui.dm"
+#include "code\modules\client\preferences\migrations\16_colors.dm"
+#include "code\modules\client\preferences\types\character\antagonism\01_basic.dm"
+#include "code\modules\client\preferences\types\character\general\01_basic.dm"
+#include "code\modules\client\preferences\types\character\general\03_body.dm"
+#include "code\modules\client\preferences\types\game\admin.dm"
+#include "code\modules\client\preferences\types\game\auto_fit_viewport.dm"
+#include "code\modules\client\preferences\types\game\chat.dm"
+#include "code\modules\client\preferences\types\game\fps.dm"
+#include "code\modules\client\preferences\types\game\ghost.dm"
+#include "code\modules\client\preferences\types\game\ignored_players.dm"
+#include "code\modules\client\preferences\types\game\misc.dm"
+#include "code\modules\client\preferences\types\game\runechat.dm"
+#include "code\modules\client\preferences\types\game\sound.dm"
+#include "code\modules\client\preferences\types\game\tooltip.dm"
+#include "code\modules\client\preferences\types\game\ui.dm"
+#include "code\modules\client\preferences\types\game\ui_style.dm"
#include "code\modules\client\verbs\advanced_who.dm"
#include "code\modules\client\verbs\character_directory.dm"
#include "code\modules\client\verbs\ignore.dm"