mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-17 05:03:28 +00:00
* Splits mutant_bodyparts.dmi into several subfiles. (#71408) Splits the `mutant_bodyparts.dmi` file up, as was suggested, but not implemented, in #69302. The following new files were created in the `icons\mob\species` folder, containing the listed sprites: - `lizard\lizard_misc.dmi`: Snouts, horns, frills, and body markings. Anything I didn't feel needed an entire file to itself. - `lizard\lizard_spines.dmi`: Lizard spines, both animated and not. - `lizard\lizard_tails.dmi`: Lizard tails, both animated and not. - `human\cat_features.dmi`: Felinid ears and tails. - `monkey\monkey_tail.dmi`: The monkey tail. - `mush_cap.dmi`: The lone mushperson cap, so easily forgotten. Additionally, I moved `wings.dmi` from `mob\clothing` to `mob\species`. I'm not sure what it was doing there. `mutant_bodyparts.dmi` was something of a mess, with parts from four different species thrown together haphazardly. It probably made sense in earlier days when "mutant humans" were few and far between, but splitting it up makes it more intuitive to find these sprites, and brings it in line with other species - namely, moths. It also means that any future sprites of these types added will not bloat an oversized file even more. Moving the wings file to the species folder just makes sense, because wings are not a type of clothing. 🆑 refactor: Removed mutant_bodyparts.dmi and distributed its sprites in a more sensible and granular manner. /🆑 * External Organ Rework: new bodypart_overlay system (#72734) Bodypart overlays are now drawn by the new /datum/bodypart_overlay datum. External organs no longer draw anything and instead add a special /datum/bodypart_overlay/mutant to the bodypart, which draws everything Makes it way easier to add custom overlays to limbs, since the whole system is now modularized and external organs are just one implementation of it I haven't moved anything but external organs to this new system, I'll move eyes, bodymarkings, hair, lipstick etc to this later New pipeline is as follows: - External organ added to limb - External organ adds /datum/bodypart_overlay/mutant to limb to bodypart_overlays - Limb updates its icon, looks for all /datum/bodypart_overlay in bodypart_overlays - Very cool new overlay on your limb! closes #71820 🆑 refactor: External organs have been near-completely refactored. admin: Admin-spawned external organs will load with a random icon and color fix: fixes angel wings not working for non-humans (it was so fucking broken) fix: fixes external organs being invisible if they werent initialized with a human /🆑 External organs are cool but are pretty limited in some ways. Making stuff like synthetic organs is kinda fucked. I tried and it was dogshit. Now you can just give an icon state and icon and you're good (using /datum/bodypart_accessory/simple) Stuff like eyes, cat ears and hair seem like good choices for extorgans, but don't quite work for it because their icons work a lot differently. This solves for it completely since any organ (or object or whatever) can add it's own icon to a bodypart. Want to add an iron plate to someones head? Go ahead. Want a heart to stick out of someones chest? No problem. Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> * Makes the whole thing compile, although it most likely doesn't work * Whoopsie daisy * Now it's starting to work * ok monkey * Fixes tails some more * Moth wings should be wings not moth wings * Podpeople hair, yeah. * Okay no more handle_mutant_bodyparts() * Removed an useless variable from is_hidden() * Fixes some more can_draw_on_bodypart (I'm gonna have to fix it upstream too) * Removes the second useless argument of is_hidden() * No, cat tails are no longer allowed to be snowflake * Removes some useless variables from humans * Whoops I forgot to commit this one * How did I miss this one? * Okay, yeah, tails and some other stuff show up now. Pod people hair too. Just many of them don't. Good enough for today. * Okay so after a lot of pain and suffering, many mutant_bodyparts are now functional * Everything works, except for ears, some of the taur layering, and moth markings (which never worked it seems) * Alright skintones seem to work rather well now(?) * Okay, my bad, now they do * Moth markings can't be selected and won't be added anymore (since they're broken and integrated into the regular markings system anyway) * Spines are no longer just matching the color of the limb they're attached to * Moves taur organ and bodypart_overlay out of the sprite_accessory file for taurs, and fixes the taur rendering * Linters moment * Alright, spines are working and overlaying properly now They just need to have a FRONT overlay for the /tg/ ones if we want them to display above the lizard tails, we already have that for vox spines thankfully. * Disables moth_markings for good * Fixes some rendering bugs * Makes ears work (almost, rest of the code has MODsuit stuff in it too :( ) * Made the MODsuit overlays work :) * Fixed horns and spines * Fixes all of the screenshot tests * Removes the Body Markings option from Appearances, use Augments+ instead (because that one works and is just better) * Bye bye handle_mutant_bodyparts(), I won't miss you :) * Forgot to take this out, whoops * Fixes the moth antennae being unticked * Removes some commented code in a modular file * Fixes part of the create_and_destroy unit test * Fixes a pretty big issue that caused some sprite_accessories to be removed from the global list because of the alter_form action (deep copies ftw) * Fixes the runtimes related to pod_hair * Gives the vox a better look in the prefs menu * Fixes the appearance of functional wings * Makes synths able to access their robotic wings * Podpeople don't cause runtimes during CI anymore * Fixes the random appearance of locked functional wings * Fixed cat and lizard tails using the /tg/ sprites (we have slightly modified ones) * Fixes the coloring on multi-colored sprites * Fixes the code for the screenshot of the mammal screenshots and preview, so it has a tail * Fixes the screenshot tests for a few species * Fixes tails going invisible when wagging * Fixes a runtime with horns * Fixes showing/hiding mutant bodyparts not working at all * (Hopefully) fully fixes all the issues related to extra and extra2-related icon_states. * Fixes synth stuff and starts working on pod hair again * I DID IT PODPEOPLE HAVE HAIR AGAIN * Fixes the podpeople hair showing up on more than just podpeople * Fixes the IPC screens showing up on species outside of synthetics * Fixes a runtime in the pod_hair and the synth_screen's apply_to_human * Updates the screenshots for podpeople and synths * Fixes an issue with a certain type of organs * Fixes another runtime, whoops * Fixes the markings from /tg/'s Body Markings not being available in our markings system * Re-adds support for taur-variants of certain mutant bodyparts * Hopefully fixes a few more runtimes * Adds some debug variable in the code for now, likely to be removed later if really necessary. This will make my life easier. * Whoops, that needed to be backwards. :clown: * Fixes the top snouts not rendering at all * Fixes the issues where bodytypes weren't handled properly, and thus snouts were getting squished * Fixes the weird placement of the Xeno Head Emissives in the prefs menu * Removes a no-longer-necessary override of post_set_preference() in the limbs_and_markings middleware * Reverts an unnecessary SKYRAT EDIT inside of commented out code * No longer creates a new body every time we change prefs in the prefs menu, we reusing now lads I know there's commented out code but I'm going to remove that in another commit * Removed some more dead code. * Fixes jellyfish ears being all white * Fixes plasmaman limbs not displaying because I accidentally hardcoded the limb_id for all augments to "robotic" --------- Co-authored-by: lizardqueenlexi <105025397+lizardqueenlexi@users.noreply.github.com> Co-authored-by: Time-Green <timkoster1@hotmail.com> Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
600 lines
20 KiB
Plaintext
600 lines
20 KiB
Plaintext
GLOBAL_LIST_EMPTY(preferences_datums)
|
|
|
|
/datum/preferences
|
|
var/client/parent
|
|
/// The path to the general savefile for this datum
|
|
var/path
|
|
/// Whether or not we allow saving/loading. Used for guests, if they're enabled
|
|
var/load_and_save = TRUE
|
|
/// Ensures that we always load the last used save, QOL
|
|
var/default_slot = 1
|
|
/// The maximum number of slots we're allowed to contain
|
|
var/max_save_slots = 30 //SKYRAT EDIT - ORIGINAL 3
|
|
|
|
/// Bitflags for communications that are muted
|
|
var/muted = NONE
|
|
/// Last IP that this client has connected from
|
|
var/last_ip
|
|
/// Last CID that this client has connected from
|
|
var/last_id
|
|
|
|
/// Cached changelog size, to detect new changelogs since last join
|
|
var/lastchangelog = ""
|
|
|
|
/// List of ROLE_X that the client wants to be eligible for
|
|
var/list/be_special = list() //Special role selection
|
|
|
|
/// Custom keybindings. Map of keybind names to keyboard inputs.
|
|
/// For example, by default would have "swap_hands" -> list("X")
|
|
var/list/key_bindings = list()
|
|
|
|
/// Cached list of keybindings, mapping keys to actions.
|
|
/// For example, by default would have "X" -> list("swap_hands")
|
|
var/list/key_bindings_by_key = list()
|
|
|
|
var/toggles = TOGGLES_DEFAULT
|
|
var/db_flags
|
|
var/chat_toggles = TOGGLES_DEFAULT_CHAT
|
|
var/ghost_form = "ghost"
|
|
|
|
//character preferences
|
|
var/slot_randomized //keeps track of round-to-round randomization of the character slot, prevents overwriting
|
|
|
|
var/list/randomise = list()
|
|
|
|
//Quirk list
|
|
var/list/all_quirks = list()
|
|
|
|
//Job preferences 2.0 - indexed by job title , no key or value implies never
|
|
var/list/job_preferences = list()
|
|
|
|
/// The current window, PREFERENCE_TAB_* in [`code/__DEFINES/preferences.dm`]
|
|
var/current_window = PREFERENCE_TAB_CHARACTER_PREFERENCES
|
|
|
|
var/unlock_content = 0
|
|
|
|
var/list/ignoring = list()
|
|
|
|
var/list/exp = list()
|
|
|
|
var/action_buttons_screen_locs = list()
|
|
|
|
///Someone thought we were nice! We get a little heart in OOC until we join the server past the below time (we can keep it until the end of the round otherwise)
|
|
var/hearted
|
|
///If we have a hearted commendations, we honor it every time the player loads preferences until this time has been passed
|
|
var/hearted_until
|
|
///What outfit typepaths we've favorited in the SelectEquipment menu
|
|
var/list/favorite_outfits = list()
|
|
|
|
/// A preview of the current character
|
|
var/atom/movable/screen/map_view/char_preview/character_preview_view
|
|
|
|
/// A list of instantiated middleware
|
|
var/list/datum/preference_middleware/middleware = list()
|
|
|
|
/// The json savefile for this datum
|
|
var/datum/json_savefile/savefile
|
|
|
|
/// The savefile relating to character preferences, PREFERENCE_CHARACTER
|
|
var/list/character_data
|
|
|
|
/// A list of keys that have been updated since the last save.
|
|
var/list/recently_updated_keys = list()
|
|
|
|
/// A cache of preference entries to values.
|
|
/// Used to avoid expensive READ_FILE every time a preference is retrieved.
|
|
var/value_cache = list()
|
|
|
|
/// If set to TRUE, will update character_profiles on the next ui_data tick.
|
|
var/tainted_character_profiles = FALSE
|
|
|
|
/datum/preferences/Destroy(force, ...)
|
|
QDEL_NULL(character_preview_view)
|
|
QDEL_LIST(middleware)
|
|
value_cache = null
|
|
//SKYRAT EDIT ADDITION
|
|
if(pref_species)
|
|
QDEL_NULL(pref_species)
|
|
//SKYRAT EDIT END
|
|
return ..()
|
|
|
|
/datum/preferences/New(client/parent)
|
|
src.parent = parent
|
|
|
|
for (var/middleware_type in subtypesof(/datum/preference_middleware))
|
|
middleware += new middleware_type(src)
|
|
|
|
if(IS_CLIENT_OR_MOCK(parent))
|
|
load_and_save = !is_guest_key(parent.key)
|
|
load_path(parent.ckey)
|
|
if(load_and_save && !fexists(path))
|
|
try_savefile_type_migration()
|
|
unlock_content = !!parent.IsByondMember() || GLOB.donator_list[parent.ckey] //SKYRAT EDIT - ADDED DONATOR CHECK
|
|
if(unlock_content)
|
|
max_save_slots = 50 //SKYRAT EDIT - ORIGINAL 8
|
|
else
|
|
CRASH("attempted to create a preferences datum without a client or mock!")
|
|
load_savefile()
|
|
|
|
// give them default keybinds and update their movement keys
|
|
key_bindings = deep_copy_list(GLOB.default_hotkeys)
|
|
key_bindings_by_key = get_key_bindings_by_key(key_bindings)
|
|
randomise = get_default_randomization()
|
|
|
|
var/loaded_preferences_successfully = load_preferences()
|
|
if(loaded_preferences_successfully)
|
|
if(load_character())
|
|
// SKYRAT EDIT START - Sanitizing preferences
|
|
sanitize_languages()
|
|
sanitize_quirks()
|
|
// SKYRAT EDIT END
|
|
return // SKYRAT EDIT - Don't remove this. Just don't. Nothing is worth forced random characters.
|
|
//we couldn't load character data so just randomize the character appearance + name
|
|
randomise_appearance_prefs() //let's create a random character then - rather than a fat, bald and naked man.
|
|
if(parent)
|
|
apply_all_client_preferences()
|
|
parent.set_macros()
|
|
|
|
if(!loaded_preferences_successfully)
|
|
save_preferences()
|
|
save_character() //let's save this new random character so it doesn't keep generating new ones.
|
|
|
|
/datum/preferences/ui_interact(mob/user, datum/tgui/ui)
|
|
// There used to be code here that readded the preview view if you "rejoined"
|
|
// I'm making the assumption that ui close will be called whenever a user logs out, or loses a window
|
|
// If this isn't the case, kill me and restore the code, thanks
|
|
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
character_preview_view = create_character_preview_view(user)
|
|
|
|
ui = new(user, src, "PreferencesMenu")
|
|
ui.set_autoupdate(FALSE)
|
|
ui.open()
|
|
|
|
// HACK: Without this the character starts out really tiny because of some BYOND bug.
|
|
// You can fix it by changing a preference, so let's just forcably update the body to emulate this.
|
|
// Lemon from the future: this issue appears to replicate if the byond map (what we're relaying here)
|
|
// Is shown while the client's mouse is on the screen. As soon as their mouse enters the main map, it's properly scaled
|
|
// I hate this place
|
|
addtimer(CALLBACK(character_preview_view, TYPE_PROC_REF(/atom/movable/screen/map_view/char_preview, update_body)), 1 SECONDS)
|
|
|
|
/datum/preferences/ui_state(mob/user)
|
|
return GLOB.always_state
|
|
|
|
// Without this, a hacker would be able to edit other people's preferences if
|
|
// they had the ref to Topic to.
|
|
/datum/preferences/ui_status(mob/user, datum/ui_state/state)
|
|
return user.client == parent ? UI_INTERACTIVE : UI_CLOSE
|
|
|
|
/datum/preferences/ui_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
if (tainted_character_profiles)
|
|
data["character_profiles"] = create_character_profiles()
|
|
tainted_character_profiles = FALSE
|
|
|
|
//SKYRAT EDIT BEGIN
|
|
data["preview_selection"] = preview_pref
|
|
|
|
data["quirks_balance"] = GetQuirkBalance()
|
|
data["positive_quirk_count"] = GetPositiveQuirkCount()
|
|
//SKYRAT EDIT END
|
|
|
|
data["character_preferences"] = compile_character_preferences(user)
|
|
|
|
data["active_slot"] = default_slot
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
data += preference_middleware.get_ui_data(user)
|
|
|
|
return data
|
|
|
|
/datum/preferences/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
// SKYRAT EDIT ADDITION START
|
|
if(CONFIG_GET(flag/disable_erp_preferences))
|
|
data["preview_options"] = list(PREVIEW_PREF_JOB, PREVIEW_PREF_LOADOUT, PREVIEW_PREF_UNDERWEAR, PREVIEW_PREF_NAKED)
|
|
else
|
|
data["preview_options"] = list(PREVIEW_PREF_JOB, PREVIEW_PREF_LOADOUT, PREVIEW_PREF_UNDERWEAR, PREVIEW_PREF_NAKED, PREVIEW_PREF_NAKED_AROUSED)
|
|
// SKYRAT EDIT ADDITION END
|
|
|
|
data["character_profiles"] = create_character_profiles()
|
|
|
|
data["character_preview_view"] = character_preview_view.assigned_map
|
|
data["overflow_role"] = SSjob.GetJobType(SSjob.overflow_role).title
|
|
data["window"] = current_window
|
|
|
|
data["content_unlocked"] = unlock_content
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
data += preference_middleware.get_ui_static_data(user)
|
|
|
|
return data
|
|
|
|
/datum/preferences/ui_assets(mob/user)
|
|
var/list/assets = list(
|
|
get_asset_datum(/datum/asset/spritesheet/preferences),
|
|
get_asset_datum(/datum/asset/json/preferences),
|
|
)
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
assets += preference_middleware.get_ui_assets()
|
|
|
|
return assets
|
|
|
|
/datum/preferences/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if (.)
|
|
return
|
|
|
|
if(SSlag_switch.measures[DISABLE_CREATOR] && action != "change_slot")
|
|
to_chat(usr, "The creator has been disabled. Please do not ahelp.")
|
|
return
|
|
|
|
log_creator("[key_name(usr)] ACTED [action] | PREFERENCE: [params["preference"]] | VALUE: [params["value"]]")
|
|
|
|
switch (action)
|
|
if ("change_slot")
|
|
// Save existing character
|
|
save_character()
|
|
|
|
// SAFETY: `load_character` performs sanitization the slot number
|
|
if (!load_character(params["slot"]))
|
|
tainted_character_profiles = TRUE
|
|
randomise_appearance_prefs()
|
|
save_character()
|
|
|
|
// SKYRAT EDIT START - Sanitizing languages
|
|
if(sanitize_languages())
|
|
save_character()
|
|
// SKYRAT EDIT END
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
preference_middleware.on_new_character(usr)
|
|
|
|
character_preview_view.update_body()
|
|
|
|
return TRUE
|
|
if ("rotate")
|
|
/* SKYRAT EDIT - Bi-directional prefs menu rotation - ORIGINAL:
|
|
character_preview_view.dir = turn(character_preview_view.dir, -90)
|
|
*/ // ORIGINAL END - SKYRAT EDIT START:
|
|
var/backwards = params["backwards"]
|
|
character_preview_view.dir = turn(character_preview_view.dir, backwards ? 90 : -90)
|
|
// SKYRAT EDIT END
|
|
|
|
return TRUE
|
|
if ("set_preference")
|
|
var/requested_preference_key = params["preference"]
|
|
var/value = params["value"]
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
if (preference_middleware.pre_set_preference(usr, requested_preference_key, value))
|
|
return TRUE
|
|
|
|
var/datum/preference/requested_preference = GLOB.preference_entries_by_key[requested_preference_key]
|
|
if (isnull(requested_preference))
|
|
return FALSE
|
|
|
|
// SAFETY: `update_preference` performs validation checks
|
|
if (!update_preference(requested_preference, value))
|
|
return FALSE
|
|
|
|
if (istype(requested_preference, /datum/preference/name))
|
|
tainted_character_profiles = TRUE
|
|
//SKYRAT EDIT
|
|
update_mutant_bodyparts(requested_preference)
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
if (preference_middleware.post_set_preference(usr, requested_preference_key, value))
|
|
return TRUE
|
|
//SKYRAT EDIT END
|
|
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
|
|
//SKYRAT EDIT ADDITION
|
|
if("update_preview")
|
|
preview_pref = params["updated_preview"]
|
|
character_preview_view.update_body()
|
|
return TRUE
|
|
|
|
if ("open_loadout")
|
|
if(parent.open_loadout_ui)
|
|
parent.open_loadout_ui.ui_interact(usr)
|
|
else
|
|
var/datum/loadout_manager/tgui = new(usr)
|
|
tgui.ui_interact(usr)
|
|
return TRUE
|
|
if ("set_tricolor_preference")
|
|
var/requested_preference_key = params["preference"]
|
|
var/index_key = params["value"]
|
|
|
|
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/tri_color))
|
|
return FALSE
|
|
|
|
var/default_value_list = read_preference(requested_preference.type)
|
|
if (!islist(default_value_list))
|
|
return FALSE
|
|
var/default_value = default_value_list[index_key]
|
|
|
|
// Yielding
|
|
var/new_color = input(
|
|
usr,
|
|
"Select new color",
|
|
null,
|
|
default_value || COLOR_WHITE,
|
|
) as color | null
|
|
|
|
if (!new_color)
|
|
return FALSE
|
|
|
|
default_value_list[index_key] = new_color
|
|
|
|
if (!update_preference(requested_preference, default_value_list))
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
// For the quirks in the prefs menu.
|
|
if ("get_quirks_balance")
|
|
return TRUE
|
|
//SKYRAT EDIT END
|
|
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
var/delegation = preference_middleware.action_delegations[action]
|
|
if (!isnull(delegation))
|
|
return call(preference_middleware, delegation)(params, usr)
|
|
|
|
return FALSE
|
|
|
|
/datum/preferences/ui_close(mob/user)
|
|
save_character()
|
|
save_preferences()
|
|
QDEL_NULL(character_preview_view)
|
|
|
|
/datum/preferences/Topic(href, list/href_list)
|
|
. = ..()
|
|
if (.)
|
|
return
|
|
|
|
if (href_list["open_keybindings"])
|
|
current_window = PREFERENCE_TAB_KEYBINDINGS
|
|
update_static_data(usr)
|
|
ui_interact(usr)
|
|
return TRUE
|
|
|
|
/datum/preferences/proc/create_character_preview_view(mob/user)
|
|
character_preview_view = new(null, src)
|
|
character_preview_view.generate_view("character_preview_[REF(character_preview_view)]")
|
|
character_preview_view.update_body()
|
|
character_preview_view.display_to(user)
|
|
|
|
return character_preview_view
|
|
|
|
/datum/preferences/proc/compile_character_preferences(mob/user)
|
|
var/list/preferences = list()
|
|
|
|
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
|
|
if (!preference.is_accessible(src))
|
|
continue
|
|
|
|
LAZYINITLIST(preferences[preference.category])
|
|
|
|
var/value = read_preference(preference.type)
|
|
var/data = preference.compile_ui_data(user, value)
|
|
|
|
preferences[preference.category][preference.savefile_key] = data
|
|
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
var/list/append_character_preferences = preference_middleware.get_character_preferences(user)
|
|
if (isnull(append_character_preferences))
|
|
continue
|
|
|
|
for (var/category in append_character_preferences)
|
|
if (category in preferences)
|
|
preferences[category] += append_character_preferences[category]
|
|
else
|
|
preferences[category] = append_character_preferences[category]
|
|
|
|
return preferences
|
|
|
|
/// Applies all PREFERENCE_PLAYER preferences
|
|
/datum/preferences/proc/apply_all_client_preferences()
|
|
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
|
|
if (preference.savefile_identifier != PREFERENCE_PLAYER)
|
|
continue
|
|
|
|
value_cache -= preference.type
|
|
preference.apply_to_client(parent, read_preference(preference.type))
|
|
|
|
/// A preview of a character for use in the preferences menu
|
|
/atom/movable/screen/map_view/char_preview
|
|
name = "character_preview"
|
|
|
|
/// The body that is displayed
|
|
var/mob/living/carbon/human/dummy/body
|
|
/// The preferences this refers to
|
|
var/datum/preferences/preferences
|
|
|
|
/atom/movable/screen/map_view/char_preview/Initialize(mapload, datum/preferences/preferences)
|
|
. = ..()
|
|
src.preferences = preferences
|
|
|
|
/atom/movable/screen/map_view/char_preview/Destroy()
|
|
QDEL_NULL(body)
|
|
preferences?.character_preview_view = null
|
|
preferences = null
|
|
return ..()
|
|
|
|
/// Updates the currently displayed body
|
|
/atom/movable/screen/map_view/char_preview/proc/update_body()
|
|
if (isnull(body))
|
|
create_body()
|
|
else
|
|
body.wipe_state()
|
|
appearance = preferences.render_new_preview_appearance(body)
|
|
|
|
/atom/movable/screen/map_view/char_preview/proc/create_body()
|
|
QDEL_NULL(body)
|
|
|
|
body = new
|
|
|
|
// Without this, it doesn't show up in the menu
|
|
body.appearance_flags |= KEEP_TOGETHER // SKYRAT EDIT - Fix pixel scaling - ORIGINAL: body.appearance_flags &= ~KEEP_TOGETHER
|
|
|
|
/datum/preferences/proc/create_character_profiles()
|
|
var/list/profiles = list()
|
|
|
|
for (var/index in 1 to max_save_slots)
|
|
// It won't be updated in the savefile yet, so just read the name directly
|
|
if (index == default_slot)
|
|
profiles += read_preference(/datum/preference/name/real_name)
|
|
continue
|
|
|
|
var/tree_key = "character[index]"
|
|
var/save_data = savefile.get_entry(tree_key)
|
|
var/name = save_data?["real_name"]
|
|
|
|
if (isnull(name))
|
|
profiles += null
|
|
continue
|
|
|
|
profiles += name
|
|
|
|
return profiles
|
|
|
|
/datum/preferences/proc/set_job_preference_level(datum/job/job, level)
|
|
if (!job)
|
|
return FALSE
|
|
|
|
if (level == JP_HIGH)
|
|
var/datum/job/overflow_role = SSjob.overflow_role
|
|
var/overflow_role_title = initial(overflow_role.title)
|
|
|
|
for(var/other_job in job_preferences)
|
|
if(job_preferences[other_job] == JP_HIGH)
|
|
// Overflow role needs to go to NEVER, not medium!
|
|
if(other_job == overflow_role_title)
|
|
job_preferences[other_job] = null
|
|
else
|
|
job_preferences[other_job] = JP_MEDIUM
|
|
|
|
if(level == null)
|
|
job_preferences -= job.title
|
|
else
|
|
job_preferences[job.title] = level
|
|
|
|
return TRUE
|
|
|
|
/datum/preferences/proc/GetQuirkBalance()
|
|
var/bal = 0
|
|
for(var/V in all_quirks)
|
|
var/datum/quirk/T = SSquirks.quirks[V]
|
|
bal -= initial(T.value)
|
|
//SKYRAT EDIT ADDITION
|
|
for(var/key in augments)
|
|
var/datum/augment_item/aug = GLOB.augment_items[augments[key]]
|
|
bal -= aug.cost
|
|
//SKYRAT EDIT END
|
|
return bal
|
|
|
|
/datum/preferences/proc/GetPositiveQuirkCount()
|
|
. = 0
|
|
for(var/q in all_quirks)
|
|
if(SSquirks.quirk_points[q] > 0)
|
|
.++
|
|
|
|
/datum/preferences/proc/validate_quirks()
|
|
if(GetQuirkBalance() < 0)
|
|
all_quirks = list()
|
|
|
|
/// Sanitizes the preferences, applies the randomization prefs, and then applies the preference to the human mob.
|
|
/datum/preferences/proc/safe_transfer_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE, is_antag = FALSE)
|
|
apply_character_randomization_prefs(is_antag)
|
|
apply_prefs_to(character, icon_updates)
|
|
|
|
/// Applies the given preferences to a human mob.
|
|
/datum/preferences/proc/apply_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE, visuals_only = FALSE) // SKYRAT EDIT - Customization - ORIGINAL: /datum/preferences/proc/apply_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE)
|
|
character.dna.features = MANDATORY_FEATURE_LIST //SKYRAT EDIT CHANGE - We need to instansiate the list with the basic features.
|
|
|
|
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
|
|
if (preference.savefile_identifier != PREFERENCE_CHARACTER)
|
|
continue
|
|
|
|
preference.apply_to_human(character, read_preference(preference.type), src)
|
|
|
|
// SKYRAT EDIT ADDITION START - middleware apply human prefs
|
|
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
|
|
preference_middleware.apply_to_human(character, src, visuals_only = visuals_only)
|
|
// SKYRAT EDIT ADDITION END
|
|
|
|
character.dna.real_name = character.real_name
|
|
|
|
if(icon_updates)
|
|
character.icon_render_keys = list()
|
|
character.update_body(is_creating = TRUE)
|
|
|
|
|
|
/// Returns whether the parent mob should have the random hardcore settings enabled. Assumes it has a mind.
|
|
/datum/preferences/proc/should_be_random_hardcore(datum/job/job, datum/mind/mind)
|
|
if(!read_preference(/datum/preference/toggle/random_hardcore))
|
|
return FALSE
|
|
if(job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) //No command staff
|
|
return FALSE
|
|
for(var/datum/antagonist/antag as anything in mind.antag_datums)
|
|
if(antag.get_team()) //No team antags
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/// Inverts the key_bindings list such that it can be used for key_bindings_by_key
|
|
/datum/preferences/proc/get_key_bindings_by_key(list/key_bindings)
|
|
var/list/output = list()
|
|
|
|
for (var/action in key_bindings)
|
|
for (var/key in key_bindings[action])
|
|
LAZYADD(output[key], action)
|
|
|
|
return output
|
|
|
|
/// Returns the default `randomise` variable ouptut
|
|
/datum/preferences/proc/get_default_randomization()
|
|
var/list/default_randomization = list()
|
|
|
|
for (var/preference_key in GLOB.preference_entries_by_key)
|
|
var/datum/preference/preference = GLOB.preference_entries_by_key[preference_key]
|
|
if (preference.is_randomizable() && preference.randomize_by_default)
|
|
default_randomization[preference_key] = RANDOM_ENABLED
|
|
|
|
return default_randomization
|