diff --git a/.github/COMPONENTOWNERS.yml b/.github/COMPONENTOWNERS.yml index 6c01aa197263..8e29ba4702a6 100644 --- a/.github/COMPONENTOWNERS.yml +++ b/.github/COMPONENTOWNERS.yml @@ -16,7 +16,7 @@ components: ## Код ## # /code/ - code/modules/client/preferences_savefile.dm: volas + code/modules/client/: volas ## Конфиги ## config/: volas diff --git a/code/__DEFINES/chat.dm b/code/__DEFINES/chat.dm index e07d939ff4b9..3ea59a986124 100644 --- a/code/__DEFINES/chat.dm +++ b/code/__DEFINES/chat.dm @@ -14,7 +14,6 @@ #define MESSAGE_TYPE_ATTACKLOG "attacklog" #define MESSAGE_TYPE_DEBUG "debug" - // To chat defines #define to_chat_private(usr, msg, type) to_chat(usr, msg, type, confidential = TRUE) diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 7ce18ed805a8..b8a958ebcec3 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -210,3 +210,14 @@ 0, 0, 0, 1, \ 0, 0, 0, 0) +/** +* CHAT COLORS +* +* These are used in both dark and light chat themes and override default (css) colors, +* so should be accessible with both background colors +* (#ffffff for light, #131313 for dark, test it with any color contrast checker) +*/ +#define OOC_COLOR_SUPPORTER "#cca000" // we use it just for nickname +#define OOC_COLOR_EVENTADMIN "#ae566d" +#define OOC_COLOR_CODEADMIN "#257227" +#define OOC_COLOR_ADMIN "#b82b00" diff --git a/code/__DEFINES/fonts.dm b/code/__DEFINES/fonts.dm new file mode 100644 index 000000000000..d28ce7e35d72 --- /dev/null +++ b/code/__DEFINES/fonts.dm @@ -0,0 +1,6 @@ +#define FONT_SYSTEM "System" +#define FONT_FIXEDSYS "Fixedsys" +#define FONT_SMALL_FONTS "Small Fonts" +#define FONT_TIMES_NEW_ROMAN "Times New Roman" +#define FONT_SERIF "Serif" +#define FONT_VERDANA "Verdana" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 274d54af8b73..2bf1b3c27804 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -1,43 +1,77 @@ -//Preference toggles (it had more bits, but updating player saves without wiping method is a bit more complex). -#define SHOW_ANIMATIONS 16 -#define SHOW_PROGBAR 32 - -#define TOGGLES_DEFAULT (SHOW_ANIMATIONS|SHOW_PROGBAR) - -//Chat toggles -#define CHAT_OOC 1 -#define CHAT_DEAD 2 -#define CHAT_GHOSTEARS 4 -#define CHAT_NOCLIENT_ATTACK 8 -#define CHAT_PRAYER 16 -#define CHAT_RADIO 32 -#define CHAT_ATTACKLOGS 64 -#define CHAT_DEBUGLOGS 128 -#define CHAT_LOOC 256 -#define CHAT_GHOSTRADIO 512 -#define CHAT_GHOSTNPC 1024 -#define CHAT_CKEY 2048 - -#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_NOCLIENT_ATTACK|CHAT_GHOSTEARS|CHAT_PRAYER|CHAT_RADIO|CHAT_GHOSTRADIO|CHAT_GHOSTNPC|CHAT_ATTACKLOGS|CHAT_LOOC|CHAT_CKEY) - -#define GLOW_HIGH 0 -#define GLOW_MED 1 //default. -#define GLOW_LOW 2 -#define GLOW_DISABLE 3 //this option must be the highest number - -#define PARALLAX_INSANE -1 //for show offs -#define PARALLAX_HIGH 0 //default. -#define PARALLAX_MED 1 -#define PARALLAX_LOW 2 -#define PARALLAX_DISABLE 3 //this option must be the highest number +// this can be little confusing, but call it as you would call +// /datum/preferences/proc/get_pref(type) +// ex. client.prefs.get_pref() +#define get_pref(type) prefs_player[type].value + +// maximum binds per keybind +#define KEYBINDS_MAXIMUM 3 + +// pref types +#define PREF_TYPE_BOOLEAN "boolean" +#define PREF_TYPE_TEXT "text" +//#define PREF_TYPE_INTEGER "integer" +#define PREF_TYPE_RANGE "range" +#define PREF_TYPE_SELECT "select" +#define PREF_TYPE_HEX "hex" +#define PREF_TYPE_KEYBIND "keybind" +#define PREF_TYPE_CUSTOM "custom" + +// pref domains (categories) +#define PREF_DOMAIN_PLAYER "player" +#define PREF_DOMAIN_KEYBINDS "keybinds" +#define PREF_DOMAIN_META "meta" +#define PREF_DOMAIN_CHARACTER "character" // todo + +// player pref domain subcategories +#define PREF_PLAYER_DISPLAY "display" +#define PREF_PLAYER_EFFECTS "effects" +#define PREF_PLAYER_AUDIO "audio" +#define PREF_PLAYER_UI "ui" +#define PREF_PLAYER_CHAT "chat" +#define PREF_PLAYER_GAME "game" + +// keybinds pref domain subcategories +#define PREF_KEYBINDS_CLIENT "CLIENT" +#define PREF_KEYBINDS_COMMUNICATION "COMMUNICATION" +#define PREF_KEYBINDS_MOVEMENT "MOVEMENT" +#define PREF_KEYBINDS_CARBON "CARBON" +#define PREF_KEYBINDS_HUMAN "HUMAN" +#define PREF_KEYBINDS_ROBOT "ROBOT" +#define PREF_KEYBINDS_EMOTE "EMOTE" +#define PREF_KEYBINDS_MISC "MISC" + +///datum/pref/player/display/zoom_mode +#define SCALING_METHOD_NORMAL "normal" +#define SCALING_METHOD_DISTORT "distort" +//#define SCALING_METHOD_BLUR "blur" // gives worst result so currently not used and players can't choice it + +///datum/pref/player/effects/glowlevel +#define GLOW_HIGH "high" +#define GLOW_MED "med" +#define GLOW_LOW "low" +#define GLOW_DISABLE "disable" + +///datum/pref/player/effects/parallax +#define PARALLAX_INSANE "insane" //for show offs +#define PARALLAX_HIGH "high" //default. +#define PARALLAX_MED "med" +#define PARALLAX_LOW "low" +#define PARALLAX_DISABLE "disable" #define PARALLAX_DELAY_DEFAULT world.tick_lag #define PARALLAX_DELAY_MED 1 #define PARALLAX_DELAY_LOW 2 -#define CHAT_GHOSTSIGHT_ALL 1 -#define CHAT_GHOSTSIGHT_ALLMANUAL 2 -#define CHAT_GHOSTSIGHT_NEARBYMOBS 3 +///datum/pref/player/chat/attack_log +#define ATTACK_LOG_DISABLED "disabled" +#define ATTACK_LOG_BY_CLIENT "by_client" +//#define ATTACK_LOG_BOTH_CLIENT "both_client" // todo +#define ATTACK_LOG_ALL "all" + +///datum/pref/player/game/ghost_skin +#define GHOST_SKIN_CHARACTER "character" +#define GHOST_SKIN_GHOST "ghost" +#define GHOST_SKIN_FLUFF "fluff" //used for alternate_option #define GET_RANDOM_JOB 0 @@ -55,3 +89,22 @@ //recommened client FPS #define RECOMMENDED_FPS 100 + +// ui themes +#define UI_STYLE_WHITE "White" +#define UI_STYLE_MIDNIGHT "Midnight" +#define UI_STYLE_OLD "Old" +#define UI_STYLE_ORANGE "Orange" + +// keybinds weight +#define WEIGHT_HIGHEST 0 +#define WEIGHT_ADMIN 10 +#define WEIGHT_CLIENT 20 +#define WEIGHT_ROBOT 30 +#define WEIGHT_MOB 40 +#define WEIGHT_LIVING 50 +#define WEIGHT_DEAD 60 +#define WEIGHT_EMOTE 70 +#define WEIGHT_LOWEST 999 + + diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index c6daf402629e..ea355aeb8807 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -1,22 +1,25 @@ //volume channels for client's volume sliders. -#define VOL_MUSIC (1<<0) // lobby. -#define VOL_AMBIENT (1<<1) // ambient music/environment sounds. -#define VOL_EFFECTS_MASTER (1<<2) // anything that doesn't go into sub categories (this acts as a master channel for all subs of this type). -//effects sub categories (VOL_EFFECTS_MASTER included, so that we don't need to type it everytime when we want to use just a sub category). -#define VOL_EFFECTS_VOICE_ANNOUNCEMENT (VOL_EFFECTS_MASTER | 1<<3) // voiced global announcements. -#define VOL_EFFECTS_MISC (VOL_EFFECTS_MASTER | 1<<4) // for any sound that may annoy players (like tesla engine). -#define VOL_EFFECTS_INSTRUMENT (VOL_EFFECTS_MASTER | 1<<5) // music instruments! actually this could be merged into spam category. +// OOC audio +#define VOL_LOBBY_MUSIC (1<<0) // music in lobby +#define VOL_NOTIFICATIONS (1<<1) // mainly for ghosts, such as cloning ready, admin pm, etc +#define VOL_ADMIN_SOUNDS (1<<2) // admin sounds or music (fun category) -#define VOL_NOTIFICATIONS (1<<6) // mainly for ghosts, such as cloning ready, admin pm, etc. -#define VOL_ADMIN (1<<7) // admin sounds or music (fun category). - -// jukebox not a VOL_MUSIC sub category because jukebox plays thru javascript, which is not boynd's sound datum. +// IC audio +#define VOL_AMBIENT (1<<3) // ambient music/environment sounds +#define VOL_EFFECTS_MASTER (1<<4) // effects sounds // todo: rename to VOL_EFFECTS when you have time to push 500+ files change +#define VOL_VOICE_ANNOUNCEMENTS (1<<5) // voiced global announcements +#define VOL_MUSIC_INSTRUMENTS (1<<6) // music instruments! +#define VOL_SPAM_EFFECTS (1<<7) // separated channel for some spamming and annoying sounds so player can setup them separately (ex. tesla engine). #define VOL_JUKEBOX (1<<8) -//Misc -#define VOL_LINEAR_TO_NON(vol_raw) ((20 ** clamp(vol_raw * 0.01, 0, 1.0)) - 0.99) / (20 - 0.99) // this converts byond's linear volume into non linear (don't change anything without heavy testing with debug, even 0.01 difference may break the sound or functions that connects with this). -#define SANITIZE_VOL(vol) vol * 0.5 // environment setting can overload sound that use 100% volume (0.5 actually is max, if you want pure sound with anything). +// converts raw preference volume (1-100) to non linear coefficient (0-1) we apply for SANITIZE_VOL(playsound volume) +// to get final client volume before any others environment effects +// (don't change anything without heavy testing with debug, even 0.01 difference may break the sound or functions that connects with this). +#define VOL_LINEAR_TO_NON(vol_raw) ((20 ** clamp(vol_raw * 0.01, 0, 1.0)) - 0.99) / (20 - 0.99) +// environment settings can overload sound that uses 100% volume, so we cap default volume at 50% +// (which means our build is quieter than others!!!) +#define SANITIZE_VOL(vol) vol * 0.5 //sound channels, max is 1024 #define CHANNEL_AMBIENT 1 diff --git a/code/__DEFINES/subsystem.dm b/code/__DEFINES/subsystem.dm index f9b91ad1fdd6..bce85fafcfef 100644 --- a/code/__DEFINES/subsystem.dm +++ b/code/__DEFINES/subsystem.dm @@ -109,6 +109,7 @@ #define SS_WAIT_GNAW 20 #define SS_WAIT_DEFAULT 20 #define SS_WAIT_UNIT_TESTS 20 +#define SS_WAIT_PREFERENCES 30 #define SS_WAIT_SUN 600 #define SS_WAIT_SMARTLIGHT 600 diff --git a/code/__HELPERS/colors.dm b/code/__HELPERS/colors.dm index b81c2ff1aa63..052ede70903c 100644 --- a/code/__HELPERS/colors.dm +++ b/code/__HELPERS/colors.dm @@ -70,17 +70,17 @@ /// Ensures that the lightness value of a color must be greater than the provided minimum. /proc/color_lightness_max(color, min_lightness) - var/list/rgb = rgb2num(color) - var/list/hsl = rgb2hsl(rgb[1], rgb[2], rgb[3]) + var/list/hsl = rgb2num(color, COLORSPACE_HSL) hsl[3] = max(hsl[3], min_lightness) - var/list/transformed_rgb = hsl2rgb(hsl[1], hsl[2], hsl[3]) - return rgb(transformed_rgb[1], transformed_rgb[2], transformed_rgb[3]) + return rgb(hsl[1], hsl[2], hsl[3], space=COLORSPACE_HSL) /// Ensures that the lightness value of a color must be less than the provided maximum. /proc/color_lightness_min(color, max_lightness) - var/list/rgb = rgb2num(color) - var/list/hsl = rgb2hsl(rgb[1], rgb[2], rgb[3]) - // Ensure high lightness (Minimum of 90%) + var/list/hsl = rgb2num(color, COLORSPACE_HSL) hsl[3] = min(hsl[3], max_lightness) - var/list/transformed_rgb = hsl2rgb(hsl[1], hsl[2], hsl[3]) - return rgb(transformed_rgb[1], transformed_rgb[2], transformed_rgb[3]) + return rgb(hsl[1], hsl[2], hsl[3], space=COLORSPACE_HSL) + +/proc/color_lightness_clamp(color, min_lightness, max_lightness) + var/list/hsl = rgb2num(color, COLORSPACE_HSL) + hsl[3] = clamp(hsl[3], min_lightness, max_lightness) + return rgb(hsl[1], hsl[2], hsl[3], space=COLORSPACE_HSL) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index d07f24b357f8..640f7a90575f 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -255,7 +255,7 @@ var/turf/ear = get_turf(M) if(ear) // Ghostship is magic: Ghosts can hear radio chatter from anywhere - if(speaker_coverage[ear] || (isobserver(M) && (M.client) && (M.client.prefs.chat_toggles & CHAT_GHOSTRADIO))) + if(speaker_coverage[ear] || (isobserver(M) && (M.client) && M.client.prefs.get_pref(/datum/pref/player/chat/ghostradio))) . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down. return . @@ -506,7 +506,7 @@ C = M.client if(!C) return - winset(C, "mainwindow", "flash=5") + winset(C, "tcmainwindow", "flash=5") //============VG PORTS============ /proc/recursive_type_check(atom/O, type = /atom) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 0f48cd1cc809..5073edaffc47 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -53,7 +53,7 @@ sort_surgeries() // Keybindings - for(var/KB in subtypesof(/datum/keybinding)) +/* for(var/KB in subtypesof(/datum/keybinding)) var/datum/keybinding/keybinding = KB if(!initial(keybinding.name)) continue @@ -61,7 +61,7 @@ global.keybindings_by_name[instance.name] = instance if(length(instance.hotkey_keys)) for(var/bound_key in instance.hotkey_keys) - global.hotkey_keybinding_list_by_key[bound_key] += list(instance.name) + global.hotkey_keybinding_list_by_key[bound_key] += list(instance.name)*/ init_subtypes(/datum/crafting_recipe, crafting_recipes) init_subtypes(/datum/dirt_cover, global.all_dirt_covers) @@ -248,8 +248,12 @@ global.skillset_names_aliases[skillset.name] = s global.all_emotes = list() - for(var/emote_type in subtypesof(/datum/emote)) - global.all_emotes[emote_type] = new emote_type + global.all_emotes_keys = list() + for(var/emote_type as anything in subtypesof(/datum/emote)) + var/datum/emote/E = new emote_type + global.all_emotes[emote_type] = E + if(E.key && E.key != "list") + global.all_emotes_keys |= E.key global.emotes_for_emote_panel = list() var/emote_icons = 'icons/misc/emotes.dmi' @@ -297,6 +301,12 @@ for(var/datum/ringtone/Ring as anything in subtypesof(/datum/ringtone)) global.ringtones_by_names["[initial(Ring.name)]"] = new Ring + for(var/datum/pref/keybinds/KB as anything in subtypesof(/datum/pref/keybinds)) + if(initial(KB.legacy_keyname)) + legacy_keyname_to_pref[initial(KB.legacy_keyname)] = KB + // little fuckup happened and leap key was not converted on time and lost + legacy_keyname_to_pref["leap"] = /datum/pref/keybinds/human/race_ability + init_washing_items_list() /proc/init_washing_items_list() diff --git a/code/__HELPERS/keys.dm b/code/__HELPERS/keys.dm new file mode 100644 index 000000000000..6a0711d2e969 --- /dev/null +++ b/code/__HELPERS/keys.dm @@ -0,0 +1,61 @@ +// list of valid byond keyboard keys based on https://www.byond.com/docs/ref/#/{skin}/macros +// + some missing from the table that were found experimentally +// not all of them are mapped with js keys and available to bind currently +var/global/list/byond_valid_keys = list ( + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", + "`", "-", "=", "\\", + "\[", "\]", ";", "'", ",", ".", "/", + "Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9", + "North", "South", "East", "West", "Northwest", "Southwest", "Northeast", "Southeast", + "Center", "Return", "Escape", "Tab", "Space", "Back", "Insert", "Delete", "Pause", "Snapshot", + "LWin", "RWin", "Apps", + "Multiply", "Add", "Subtract", "Divide", "Separator", + "Shift", "Ctrl", "Alt", + "VolumeMute", "VolumeUp", "VolumeDown", "MediaPlayPause", "MediaStop", "MediaNext", "MediaPrev", + ) + +// Converts (some) browser keycodes to BYOND keycodes. +/proc/browser_keycode_to_byond(keycode) + keycode = text2num(keycode) + switch(keycode) + // letters and numbers + if(65 to 90, 48 to 57) + return ascii2text(keycode) + if(17) + return "Ctrl" + if(18) + return "Alt" + if(16) + return "Shift" + if(37) + return "West" + if(38) + return "North" + if(39) + return "East" + if(40) + return "South" + if(45) + return "Insert" + if(46) + return "Delete" + if(36) + return "Northwest" + if(35) + return "Southwest" + if(33) + return "Northeast" + if(34) + return "Southeast" + if(112 to 123) + return "F[keycode-111]" + if(96 to 105) + return "Numpad[keycode-96]" + if(188) + return "," + if(190) + return "." + if(189) + return "-" diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm index b17d6b782c4f..20b5d30d03bd 100644 --- a/code/__HELPERS/logging.dm +++ b/code/__HELPERS/logging.dm @@ -48,7 +48,7 @@ global.game_log << "\[[time_stamp()]]DEBUG: [text][log_end]" for(var/client/C as anything in admins) - if(C.prefs.chat_toggles & CHAT_DEBUGLOGS) + if(C.prefs.get_pref(/datum/pref/player/chat/debug_log)) to_chat_debug(C, "DEBUG: [text]") /proc/log_asset(text) @@ -170,7 +170,7 @@ /proc/log_gc(text) global.gc_log << "\[[time_stamp()]] [text][log_end]" for(var/client/C in global.admins) - if(C.prefs.chat_toggles & CHAT_DEBUGLOGS) + if(C.prefs.get_pref(/datum/pref/player/chat/debug_log)) to_chat(C, "GC DEBUG: [text]") #endif diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 907597810240..09050b9f4d01 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -232,7 +232,7 @@ var/holding = user.get_active_hand() var/datum/progressbar/progbar if (progress) - if(user.client && (user.client.prefs.toggles & SHOW_PROGBAR)) + if(user.client?.prefs.get_pref(/datum/pref/player/game/progressbar)) progbar = new(user, time, target) else progress = FALSE @@ -309,7 +309,7 @@ var/datum/progressbar/progbar if (progress) - if(user.client && (user.client.prefs.toggles & SHOW_PROGBAR)) + if(user.client?.prefs.get_pref(/datum/pref/player/game/progressbar)) progbar = new(user, delay, target) else progress = FALSE diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index a9d398eaa9b8..dd66f3d53771 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -45,18 +45,25 @@ return default /proc/sanitize_hexcolor(color, default="#000000") - if(!istext(color)) return default + if(!istext(color)) + return default var/len = length(color) - if(len != 7 && len !=4) return default - if(text2ascii(color,1) != 35) return default //35 is the ascii code for "#" + if(len != 7 && len !=4) + return default + if(text2ascii(color,1) != 35) + return default //35 is the ascii code for "#" . = "#" for(var/i=2,i<=len,i++) var/ascii = text2ascii(color,i) switch(ascii) - if(48 to 57) . += ascii2text(ascii) //numbers 0 to 9 - if(97 to 102) . += ascii2text(ascii) //letters a to f - if(65 to 70) . += ascii2text(ascii+32) //letters A to F - translates to lowercase - else return default + if(48 to 57) + . += ascii2text(ascii) //numbers 0 to 9 + if(97 to 102) + . += ascii2text(ascii) //letters a to f + if(65 to 70) + . += ascii2text(ascii+32) //letters A to F - translates to lowercase + else + return default return . var/global/regex/IP_pattern = regex(@"^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$") diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 4d9beb7a3d61..892058d2b3e7 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -179,6 +179,10 @@ return findtext(text, suffix, start, null) return +/proc/endswith(input_text, ending) + var/input_length = length(ending) + return !!findtext(input_text, ending, -input_length) + /* * Text modification */ diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index e6f6ee88218a..1a624e7f3e06 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -276,59 +276,6 @@ return /datum return text2path(copytext(string_type, 1, last_slash)) -/// Converts an RGB color to an HSL color -/proc/rgb2hsl(red, green, blue) - red /= 255;green /= 255;blue /= 255; - var/max = max(red,green,blue) - var/min = min(red,green,blue) - var/range = max-min - - var/hue=0;var/saturation=0;var/lightness=0; - lightness = (max + min)/2 - if(range != 0) - if(lightness < 0.5) - saturation = range/(max+min) - else - saturation = range/(2-max-min) - - var/dred = ((max-red)/(6*max)) + 0.5 - var/dgreen = ((max-green)/(6*max)) + 0.5 - var/dblue = ((max-blue)/(6*max)) + 0.5 - - if(max==red) - hue = dblue - dgreen - else if(max==green) - hue = dred - dblue + (1/3) - else - hue = dgreen - dred + (2/3) - if(hue < 0) - hue++ - else if(hue > 1) - hue-- - - return list(hue, saturation, lightness) - -/// Converts an HSL color to an RGB color -/proc/hsl2rgb(hue, saturation, lightness) - var/red;var/green;var/blue; - if(saturation == 0) - red = lightness * 255 - green = red - blue = red - else - var/a;var/b; - if(lightness < 0.5) - b = lightness*(1+saturation) - else - b = (lightness+saturation) - (saturation*lightness) - a = 2*lightness - b - - red = round(255 * hue2rgb(a, b, hue+(1/3))) - green = round(255 * hue2rgb(a, b, hue)) - blue = round(255 * hue2rgb(a, b, hue-(1/3))) - - return list(red, green, blue) - /// Converts an ABH color to an RGB color /proc/hue2rgb(a, b, hue) if(hue < 0) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 0c3785628578..f2da3cb6d0ce 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1598,50 +1598,6 @@ var/global/list/WALLITEMS = typecacheof(list( for(var/mob/dead/new_player/N as anything in new_player_list) INVOKE_ASYNC(N, TYPE_PROC_REF(/mob/dead/new_player, show_titlescreen)) -// Converts browser keycodes to BYOND keycodes. -/proc/browser_keycode_to_byond(keycode) - keycode = text2num(keycode) - switch(keycode) - // letters and numbers - if(65 to 90, 48 to 57) - return ascii2text(keycode) - if(17) - return "Ctrl" - if(18) - return "Alt" - if(16) - return "Shift" - if(37) - return "West" - if(38) - return "North" - if(39) - return "East" - if(40) - return "South" - if(45) - return "Insert" - if(46) - return "Delete" - if(36) - return "Northwest" - if(35) - return "Southwest" - if(33) - return "Northeast" - if(34) - return "Southeast" - if(112 to 123) - return "F[keycode-111]" - if(96 to 105) - return "Numpad[keycode-96]" - if(188) - return "," - if(190) - return "." - if(189) - return "-" - // Format a power value in W, kW, MW, or GW /proc/DisplayPower(powerused) if(powerused < 1000) // Less than a kW diff --git a/code/_globalvars/lists/client.dm b/code/_globalvars/lists/client.dm deleted file mode 100644 index ba32eca66c2e..000000000000 --- a/code/_globalvars/lists/client.dm +++ /dev/null @@ -1,32 +0,0 @@ -var/global/list/hotkey_keybinding_list_by_key = list() -var/global/list/keybindings_by_name = list() - -// This is a mapping from JS keys to Byond - ref: https://keycode.info/ -var/global/list/_kbMap = list( - "UP" = "North", - "RIGHT" = "East", - "DOWN" = "South", - "LEFT" = "West", - "INSERT" = "Insert", - "HOME" = "Northwest", - "PAGEUP" = "Northeast", - "DEL" = "Delete", - "END" = "Southwest", - "PAGEDOWN" = "Southeast", - "SPACEBAR" = "Space", - "ALT" = "Alt", - "SHIFT" = "Shift", - "CONTROL" = "Ctrl" - ) - -// Without alt, shift, ctrl and etc because its not necessary -var/global/list/_kbMap_reverse = list( - "North" = "Up", - "East" = "Right", - "South" = "Down", - "West" = "Left", - "Northwest" = "Home", - "Northeast" = "PageUp", - "Southwest" = "End", - "Southeast" = "PageDown", - ) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 7c5f720e4324..58b55dfd8140 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -9,16 +9,21 @@ including inventories and item quick actions. */ -// The default UI style is the first one in the list +// The default UI styles client can choice with color/alpha customization +// some mob types use own style and we don't override it var/global/list/available_ui_styles = list( - "White" = 'icons/hud/screen1_White.dmi', - "Midnight" = 'icons/hud/screen1_Midnight.dmi', - "old" = 'icons/hud/screen1_old.dmi', - "Orange" = 'icons/hud/screen1_Orange.dmi' + UI_STYLE_WHITE = 'icons/hud/screen1_White.dmi', + UI_STYLE_MIDNIGHT = 'icons/hud/screen1_Midnight.dmi', + UI_STYLE_OLD = 'icons/hud/screen1_old.dmi', + UI_STYLE_ORANGE = 'icons/hud/screen1_Orange.dmi', ) -/proc/ui_style2icon(ui_style) - return global.available_ui_styles[ui_style] || global.available_ui_styles[global.available_ui_styles[1]] +var/global/list/customizable_ui_styles = list( + 'icons/hud/screen1_White.dmi', + 'icons/hud/screen1_Midnight.dmi', + 'icons/hud/screen1_old.dmi', + 'icons/hud/screen1_Orange.dmi', + ) /datum/hud var/mob/mymob @@ -46,7 +51,7 @@ var/global/list/available_ui_styles = list( if (!ui_style) // will fall back to the default if any of these are null - ui_style = ui_style2icon(mymob.client?.prefs?.UI_style) + ui_style = global.available_ui_styles[mymob.client?.prefs?.get_pref(/datum/pref/player/ui/ui_style) || UI_STYLE_WHITE] instantiate() @@ -182,6 +187,15 @@ var/global/list/available_ui_styles = list( hud_version = version +/mob/proc/refresh_hud() + var/list/screens = hud_used.main + hud_used.adding + hud_used.hotkeybuttons + for(var/atom/movable/screen/complex/complex as anything in hud_used.complex) + screens += complex + screens += complex.screens + + for(var/atom/movable/screen/screen as anything in screens) + screen.update_by_hud(hud_used) + //Triggered when F12 is pressed (Unless someone changed something in the DMF) /mob/verb/button_pressed_F12() set name = "F12" diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index e495346337cc..b4583e5c5d23 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -1,6 +1,6 @@ /mob/living/carbon/human/add_to_hud(datum/hud/hud) - hud.ui_color = client.prefs.UI_style_color - hud.ui_alpha = client.prefs.UI_style_alpha + hud.ui_color = client.prefs.get_pref(/datum/pref/player/ui/ui_style_color) + hud.ui_alpha = 255 - floor(255*client.prefs.get_pref(/datum/pref/player/ui/ui_style_opacity)/100) ..(hud, FALSE) diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm index 780de628c3e6..6a8a9781d2b3 100644 --- a/code/_onclick/hud/parallax.dm +++ b/code/_onclick/hud/parallax.dm @@ -44,7 +44,7 @@ return FALSE var/client/C = mymob.client - switch(C.prefs.parallax) + switch(C.prefs.get_pref(/datum/pref/player/effects/parallax)) if (PARALLAX_INSANE) C.parallax_throttle = FALSE C.parallax_layers_max = 4 diff --git a/code/_onclick/hud/rendering/planes/_planes.dm b/code/_onclick/hud/rendering/planes/_planes.dm index d991694e1bb3..458d0d13dd80 100644 --- a/code/_onclick/hud/rendering/planes/_planes.dm +++ b/code/_onclick/hud/rendering/planes/_planes.dm @@ -20,17 +20,18 @@ if(!..()) return - if(client.prefs?.ambientocclusion) + if(client.prefs?.get_pref(/datum/pref/player/effects/ambientocclusion)) add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA")) if(!assigned_map) // todo: don't reapply filter if it's already exists? client.mob.clear_fullscreen("blurry") if(client.mob.eye_blurry) - if(client.prefs?.eye_blur_effect) + if(client.prefs?.get_pref(/datum/pref/player/effects/legacy_blur)) + // alternative filter for users with weak PC + client.mob.overlay_fullscreen("blurry", /atom/movable/screen/fullscreen/blurry) + else add_filter("eye_blur_angular", 1, angular_blur_filter(16, 16, clamp(client.mob.eye_blurry * 0.1, 0.2, 0.6))) add_filter("eye_blur_gauss", 1, gauss_blur_filter(clamp(client.mob.eye_blurry * 0.05, 0.1, 0.25))) - else // alternative filter for users with weak PC - client.mob.overlay_fullscreen("blurry", /atom/movable/screen/fullscreen/blurry) /atom/movable/screen/plane_master/game_world_above name = "above game world plane master" diff --git a/code/_onclick/hud/rendering/planes/lighting_planes.dm b/code/_onclick/hud/rendering/planes/lighting_planes.dm index f59538246fd3..f4f663b99872 100644 --- a/code/_onclick/hud/rendering/planes/lighting_planes.dm +++ b/code/_onclick/hud/rendering/planes/lighting_planes.dm @@ -117,7 +117,7 @@ if(!..()) return - var/enabled = client.prefs?.lampsexposure || FALSE + var/enabled = client.prefs?.get_pref(/datum/pref/player/effects/lampsexposure) if(enabled) alpha = 255 @@ -139,7 +139,7 @@ if(!..()) return - var/level = client.prefs?.glowlevel || FALSE + var/level = client.prefs?.get_pref(/datum/pref/player/effects/glowlevel) if(isnull(level)) return @@ -178,7 +178,7 @@ if(!..()) return - var/enabled = client.prefs?.lampsglare || FALSE + var/enabled = client.prefs?.get_pref(/datum/pref/player/effects/lampsglare) if(enabled) add_filter("add_lamps_to_glare", 1, layering_filter(render_source = LIGHTING_LAMPS_RENDER_TARGET, blend_mode = BLEND_OVERLAY)) diff --git a/code/_onclick/hud/tooltip.dm b/code/_onclick/hud/tooltip.dm index f672cee83f9d..710cf0a809f1 100644 --- a/code/_onclick/hud/tooltip.dm +++ b/code/_onclick/hud/tooltip.dm @@ -11,9 +11,8 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT var/looking_at var/state = TRUE - var/font_size = 8 -/atom/movable/screen/tooltip/proc/SetMapText(newValue, font, forcedFontColor = "#ffffff") +/atom/movable/screen/tooltip/proc/SetMapText(newValue, font, font_size, forcedFontColor = "#ffffff") var/style = "font-family:'[font]'; color:[forcedFontColor]; -dm-text-outline: 1px [invertHTMLcolor(forcedFontColor)]; font-weight: bold; font-size: [font_size]px;" maptext = "
[uppertext(newValue)]
" @@ -24,14 +23,14 @@ /client/New(TopicData) . = ..() tooltip = new /atom/movable/screen/tooltip() - if(prefs.tooltip) + if(prefs.get_pref(/datum/pref/player/ui/tooltip)) tooltip.set_state(TRUE) /client/MouseEntered(atom/hoverOn, location, control, params) SHOULD_CALL_PARENT(TRUE) . = ..() tooltip.looking_at = "\ref[hoverOn]" - if(prefs.tooltip && tooltip?.state) + if(prefs.get_pref(/datum/pref/player/ui/tooltip) && tooltip?.state) var/text_in_tooltip = hoverOn.get_name() screen |= tooltip - tooltip.SetMapText(text_in_tooltip, prefs.tooltip_font) + tooltip.SetMapText(text_in_tooltip, prefs.get_pref(/datum/pref/player/ui/tooltip_font), prefs.get_pref(/datum/pref/player/ui/tooltip_size)) diff --git a/code/_onclick/hud/ui_screens/basic.dm b/code/_onclick/hud/ui_screens/basic.dm index de6875e0ca7b..4125261573bb 100644 --- a/code/_onclick/hud/ui_screens/basic.dm +++ b/code/_onclick/hud/ui_screens/basic.dm @@ -395,7 +395,7 @@ screen_loc = ui_holomap plane = HUD_PLANE layer = HUD_LAYER - copy_flags = HUD_COPY_ALPHA || HUD_COPY_COLOR + copy_flags = HUD_COPY_ALPHA | HUD_COPY_COLOR mouse_opacity = MOUSE_OPACITY_TRANSPARENT /atom/movable/screen/holomap/add_to_hud(datum/hud/hud) diff --git a/code/_onclick/hud/ui_screens/complex.dm b/code/_onclick/hud/ui_screens/complex.dm index 4ff0dd0e9e31..5cdeac05cc51 100644 --- a/code/_onclick/hud/ui_screens/complex.dm +++ b/code/_onclick/hud/ui_screens/complex.dm @@ -70,7 +70,7 @@ screen_loc = ui_acti hud_slot = HUD_SLOT_MAIN - copy_flags = HUD_COPY_ICON + copy_flags = HUD_COPY_ICON | HUD_COPY_ALPHA types = list( /atom/movable/screen/intent/help, /atom/movable/screen/intent/push, diff --git a/code/_onclick/hud/ui_screens/inventory.dm b/code/_onclick/hud/ui_screens/inventory.dm index 2af7885a5f07..34224c9eb77f 100644 --- a/code/_onclick/hud/ui_screens/inventory.dm +++ b/code/_onclick/hud/ui_screens/inventory.dm @@ -29,7 +29,7 @@ remove_stored_outline() /atom/movable/screen/inventory/proc/add_stored_outline() - if(!slot_id || !usr.client.prefs.outline_enabled) + if(!slot_id || !usr.client.prefs.get_pref(/datum/pref/player/ui/outline)) return var/obj/item/inv_item = usr.get_item_by_slot(slot_id) if(!inv_item) @@ -114,7 +114,7 @@ icon_state = "craft" screen_loc = ui_crafting - copy_flags = NONE + copy_flags = HUD_COPY_ALPHA /atom/movable/screen/inventory/craft/action() if(check_state()) diff --git a/code/_onclick/hud/ui_screens/screen_objects.dm b/code/_onclick/hud/ui_screens/screen_objects.dm index 08b07800c71a..0475bf02fa24 100644 --- a/code/_onclick/hud/ui_screens/screen_objects.dm +++ b/code/_onclick/hud/ui_screens/screen_objects.dm @@ -52,7 +52,7 @@ /atom/movable/screen/proc/update_by_hud(datum/hud/hud) if((copy_flags & HUD_COPY_ICON) && hud.ui_style) icon = hud.ui_style - if((copy_flags & HUD_COPY_ALPHA) && hud.ui_alpha) + if((copy_flags & HUD_COPY_ALPHA) && !isnull(hud.ui_alpha)) // alpha can be 0 alpha = hud.ui_alpha if((copy_flags & HUD_COPY_COLOR) && hud.ui_color) color = hud.ui_color diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm index afaaf5e2a345..40ba179cf9fe 100644 --- a/code/controllers/subsystem/jobs.dm +++ b/code/controllers/subsystem/jobs.dm @@ -268,7 +268,7 @@ SUBSYSTEM_DEF(job) for(var/mob/dead/new_player/player in player_list) if(player.ready && player.mind && !player.mind.assigned_role) unassigned += player - if(player.client.prefs.randomslot) + if(player.client.prefs.get_pref(/datum/pref/player/meta/random_slot)) player.client.prefs.random_character() Debug("DO, Len: [unassigned.len]") if(unassigned.len == 0) diff --git a/code/controllers/subsystem/preferences.dm b/code/controllers/subsystem/preferences.dm new file mode 100644 index 000000000000..6c6c8f0b6a4f --- /dev/null +++ b/code/controllers/subsystem/preferences.dm @@ -0,0 +1,18 @@ +/*SUBSYSTEM_DEF(preferences) + name = "Preferences" + wait = SS_WAIT_EXPLOSION + flags = SS_TICKER | SS_SHOW_IN_MC_TAB//| SS_NO_INIT + + wait = SS_WAIT_PREFERENCES + + var/list/processing = list() + +/datum/controller/subsystem/preferences/stat_entry() + ..("PTS:[processing.len]") + +/datum/controller/subsystem/preferences/mark_dirty(/datum/preferences/P) + +// PreShutdown & Shutdown + +/datum/controller/subsystem/preferences/fire(resumed = 0) +*/ diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index ef634507afb3..ac8ef62e8e77 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -301,7 +301,7 @@ SUBSYSTEM_DEF(ticker) to_chat(world, "Приятной игры!") for(var/mob/M as anything in player_list) - M.playsound_local(null, 'sound/AI/enjoyyourstay.ogg', VOL_EFFECTS_VOICE_ANNOUNCEMENT, vary = FALSE, frequency = null, ignore_environment = TRUE) + M.playsound_local(null, 'sound/AI/enjoyyourstay.ogg', VOL_VOICE_ANNOUNCEMENTS, vary = FALSE, frequency = null, ignore_environment = TRUE) if(length(SSholiday.holidays)) to_chat(world, "и...") @@ -608,7 +608,7 @@ SUBSYSTEM_DEF(ticker) if(!config.deathmatch_arena) return for(var/mob/living/M in global.player_list) - if(!M.client.prefs.eorg_enabled) + if(!M.client.prefs.get_pref(/datum/pref/player/game/endroundarena)) continue spawn_gladiator(M) @@ -618,7 +618,7 @@ SUBSYSTEM_DEF(ticker) M.mind.transfer_to(L) else L.key = M.key - L.playsound_local(null, 'sound/lobby/Thunderdome.ogg', VOL_MUSIC, vary = FALSE, frequency = null, ignore_environment = TRUE) + L.playsound_local(null, 'sound/lobby/Thunderdome.ogg', VOL_LOBBY_MUSIC, vary = FALSE, frequency = null, ignore_environment = TRUE) L.equipOutfit(/datum/outfit/arena) L.name = L.key L.real_name = L.name diff --git a/code/datums/announcements/_announcements.dm b/code/datums/announcements/_announcements.dm index a08d7b3a9846..6756ef6fcac9 100644 --- a/code/datums/announcements/_announcements.dm +++ b/code/datums/announcements/_announcements.dm @@ -199,7 +199,7 @@ var/global/list/announcement_sounds = list( if((sound == "emer_shut_left" || sound == "crew_shut_left") && IS_ON_ESCAPE_SHUTTLE) continue - M.playsound_local(null, announce_sound, VOL_EFFECTS_VOICE_ANNOUNCEMENT, volume, FALSE, null, channel = CHANNEL_ANNOUNCE, wait = TRUE) + M.playsound_local(null, announce_sound, VOL_VOICE_ANNOUNCEMENTS, volume, FALSE, null, channel = CHANNEL_ANNOUNCE, wait = TRUE) if(faction_filter) // antag announce, don't print it in machinery return diff --git a/code/datums/browser.dm b/code/datums/browser.dm index a02dd5fdfd27..ba3c2d1b6100 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -102,7 +102,7 @@ if(scripts.len) send_asset_list(user, scripts) user << browse(get_content(), "window=[window_id];[window_size][window_options]") - winset(user, "mapwindow.map", "focus=true") // return keyboard focus to map + winset(user, "tcmapwindow.map", "focus=true") // return keyboard focus to map onclose(user, window_id, ref) /datum/browser/proc/close() @@ -160,7 +160,7 @@ if(focusedwindow) winset(user, focusedwindow, "focus=true") else - winset(user, "mapwindow", "focus=true") + winset(user, "tcmapwindow", "focus=true") break if(timeout) addtimer(CALLBACK(src, PROC_REF(close)), timeout) diff --git a/code/datums/components/talking_atom.dm b/code/datums/components/talking_atom.dm index c07b0c2c2f0a..9c0a50a51613 100644 --- a/code/datums/components/talking_atom.dm +++ b/code/datums/components/talking_atom.dm @@ -112,7 +112,7 @@ for(var/mob/M as anything in observer_list) if (!M.client) continue //skip leavers - if(M.client.prefs.chat_toggles & CHAT_GHOSTEARS) + if(M.client.prefs.get_pref(/datum/pref/player/chat/ghostears)) listening |= M for(var/mob/M in listening) diff --git a/code/datums/emotes/emote.dm b/code/datums/emotes/emote.dm index 38aa7fc6d71e..fcfd8d6626d8 100644 --- a/code/datums/emotes/emote.dm +++ b/code/datums/emotes/emote.dm @@ -1,4 +1,5 @@ var/global/list/all_emotes +var/global/list/all_emotes_keys // for emote keybinds, contains unique emote keys + "None" var/global/list/emotes_for_emote_panel // for custom emote panel /* @@ -163,16 +164,17 @@ var/global/list/emotes_for_emote_panel // for custom emote panel if(!M.client) continue + var/is_in_view = FALSE if(M in viewers(get_turf(user), world.view)) M.show_runechat_message(user, null, get_emote_message_3p(user), null, SHOWMSG_VISUAL) + is_in_view = TRUE - switch(M.client.prefs.chat_ghostsight) - if(CHAT_GHOSTSIGHT_ALL) - // ghosts don't need to be checked for deafness, type of message, etc. So to_chat() is better here + // ghosts don't need to be checked for deafness, type of message, etc. So to_chat() is better here + if(is_in_view) + to_chat(M, "[FOLLOW_LINK(M, user)] [msg_3p]") + else if (M.client.prefs.get_pref(/datum/pref/player/chat/ghostsight)) + if(intentional || !M.client.prefs.get_pref(/datum/pref/player/chat/ghostantispam)) to_chat(M, "[FOLLOW_LINK(M, user)] [msg_3p]") - if(CHAT_GHOSTSIGHT_ALLMANUAL) - if(intentional) - to_chat(M, "[FOLLOW_LINK(M, user)] [msg_3p]") if(cloud) add_cloud(user) diff --git a/code/datums/keybinding/_defines.dm b/code/datums/keybinding/_defines.dm deleted file mode 100644 index c2868f904d36..000000000000 --- a/code/datums/keybinding/_defines.dm +++ /dev/null @@ -1,20 +0,0 @@ -#define CATEGORY_CLIENT "CLIENT" -#define CATEGORY_EMOTE "EMOTE" -#define CATEGORY_ADMIN "ADMIN" -#define CATEGORY_XENO "XENO" -#define CATEGORY_CARBON "CARBON" -#define CATEGORY_HUMAN "HUMAN" -#define CATEGORY_ROBOT "ROBOT" -#define CATEGORY_MISC "MISC" -#define CATEGORY_MOVEMENT "MOVEMENT" -#define CATEGORY_COMMUNICATION "COMMUNICATION" - -#define WEIGHT_HIGHEST 0 -#define WEIGHT_ADMIN 10 -#define WEIGHT_CLIENT 20 -#define WEIGHT_ROBOT 30 -#define WEIGHT_MOB 40 -#define WEIGHT_LIVING 50 -#define WEIGHT_DEAD 60 -#define WEIGHT_EMOTE 70 -#define WEIGHT_LOWEST 999 diff --git a/code/datums/keybinding/_keybindings.dm b/code/datums/keybinding/_keybindings.dm deleted file mode 100644 index aa59d9a719c2..000000000000 --- a/code/datums/keybinding/_keybindings.dm +++ /dev/null @@ -1,16 +0,0 @@ -/datum/keybinding - var/list/hotkey_keys - var/name - var/full_name - var/description = "" - var/category = CATEGORY_MISC - var/weight = WEIGHT_LOWEST - -/datum/keybinding/proc/down(client/user) - return FALSE - -/datum/keybinding/proc/up(client/user) - return FALSE - -/datum/keybinding/proc/can_use(client/user) - return TRUE diff --git a/code/datums/keybinding/admin.dm b/code/datums/keybinding/admin.dm deleted file mode 100644 index 05826768e5ac..000000000000 --- a/code/datums/keybinding/admin.dm +++ /dev/null @@ -1,107 +0,0 @@ -/datum/keybinding/admin - category = CATEGORY_ADMIN - weight = WEIGHT_ADMIN - -/datum/keybinding/admin/can_use(client/user) - return user.holder ? TRUE : FALSE - -/datum/keybinding/admin/admin_say - hotkey_keys = list("F5") - name = "admin_say" - full_name = "Admin say" - description = "Talk with other admins." - -/datum/keybinding/admin/admin_say/down(client/user) - user.get_admin_say() - return TRUE - -/datum/keybinding/admin/admin_ghost - hotkey_keys = list("None") - name = "admin_ghost" - full_name = "Aghost" - description = "Go ghost" - -/datum/keybinding/admin/admin_ghost/down(client/user) - user.admin_ghost() - return TRUE - -/datum/keybinding/admin/player_panel_new - hotkey_keys = list("F6") - name = "player_panel_new" - full_name = "Player Panel New" - description = "Opens up the new player panel" - -/datum/keybinding/admin/player_panel_new/down(client/user) - user.holder.player_panel_new() - return TRUE - -/datum/keybinding/admin/toggle_buildmode_self - hotkey_keys = list("F7") - name = "toggle_buildmode_self" - full_name = "Toggle Buildmode Self" - description = "Toggles buildmode" - -/datum/keybinding/admin/toggle_buildmode_self/down(client/user) - user.togglebuildmodeself() - return TRUE - -/datum/keybinding/admin/stealthmode - hotkey_keys = list("CtrlF8") - name = "stealth_mode" - full_name = "Stealth mode" - description = "Enters stealth mode" - -/datum/keybinding/admin/stealthmode/down(client/user) - user.stealth() - return TRUE - -/datum/keybinding/admin/invisimin - hotkey_keys = list("F8") - name = "invisimin" - full_name = "Admin invisibility" - description = "Toggles ghost-like invisibility (Don't abuse this)" - -/datum/keybinding/admin/invisimin/down(client/user) - user.invisimin() - return TRUE - -/datum/keybinding/admin/deadsay - hotkey_keys = list("F10") - name = "dsay" - full_name = "deadsay" - description = "Allows you to send a message to dead chat" - -/datum/keybinding/admin/deadsay/down(client/user) - user.get_dead_say() - return TRUE - -/datum/keybinding/admin/deadmin - hotkey_keys = list("None") - name = "deadmin" - full_name = "Deadmin" - description = "Shed your admin powers" - -/datum/keybinding/admin/deadmin/down(client/user) - user.deadmin_self() - return TRUE - -/datum/keybinding/admin/readmin - hotkey_keys = list("None") - name = "readmin" - full_name = "Readmin" - description = "Regain your admin powers" - -/datum/keybinding/admin/readmin/down(client/user) - user.readmin_self() - return TRUE - - -/datum/keybinding/admin/toggle_combo_hud - hotkey_keys = list("None") - name = "toggle_combo_hud" - full_name = "Toggle Combo HUD" - description = "" - -/datum/keybinding/admin/toggle_combo_hud/down(client/user) - user.toggle_combo_hud() - return TRUE diff --git a/code/datums/keybinding/carbon.dm b/code/datums/keybinding/carbon.dm deleted file mode 100644 index 2da5e0cf33b9..000000000000 --- a/code/datums/keybinding/carbon.dm +++ /dev/null @@ -1,41 +0,0 @@ -/datum/keybinding/carbon - category = CATEGORY_CARBON - weight = WEIGHT_MOB - -/datum/keybinding/carbon/can_use(client/user) - return iscarbon(user.mob) - -/datum/keybinding/carbon/toggle_throw_mode - hotkey_keys = list("R", "Southwest") // PAGEDOWN - name = "toggle_throw_mode" - full_name = "Toggle throw mode" - description = "Toggle throwing the current item or not." - -/datum/keybinding/carbon/toggle_throw_mode/down(client/user) - var/mob/living/carbon/C = user.mob - C.toggle_throw_mode() - return TRUE - - -/datum/keybinding/carbon/give - hotkey_keys = list("None") - name = "Give_Item" - full_name = "Give item" - description = "Give the item you're currently holding" - -/datum/keybinding/carbon/give/down(client/user) - var/mob/living/carbon/C = user.mob - C.give() - return TRUE - - -/datum/keybinding/carbon/crawl - hotkey_keys = list("None") - name = "crawl" - full_name = "Crawl" - description = "" - -/datum/keybinding/carbon/crawl/down(client/user) - var/mob/living/carbon/C = user.mob - C.crawl() - return TRUE diff --git a/code/datums/keybinding/client.dm b/code/datums/keybinding/client.dm deleted file mode 100644 index 698b989453d2..000000000000 --- a/code/datums/keybinding/client.dm +++ /dev/null @@ -1,54 +0,0 @@ -/datum/keybinding/client - category = CATEGORY_CLIENT - weight = WEIGHT_HIGHEST - - -/datum/keybinding/client/admin_help - hotkey_keys = list("F1") - name = "admin_help" - full_name = "Admin Help" - description = "Ask an admin for help." - -/datum/keybinding/client/admin_help/down(client/user) - user.adminhelp() - return TRUE - -/datum/keybinding/client/mentor_help - hotkey_keys = list("F9") - name = "mentor_help" - full_name = "Mentor Help" - description = "Ask an mentors for help." - -/datum/keybinding/client/mentor_help/down(client/user) - user.get_mentorhelp() - return TRUE - -/datum/keybinding/client/screenshot - hotkey_keys = list("None") - name = "screenshot" - full_name = "Screenshot" - description = "Take a screenshot." - -/datum/keybinding/client/screenshot/down(client/user) - winset(user, null, "command=.screenshot [!user.keys_held["shift"] ? "auto" : ""]") - return TRUE - -/datum/keybinding/client/minimal_hud - hotkey_keys = list("F12") - name = "minimal_hud" - full_name = "Minimal HUD" - description = "Hide most HUD features" - -/datum/keybinding/client/minimal_hud/down(client/user) - user.mob.button_pressed_F12() - return TRUE - -/datum/keybinding/client/toggle_fullscreen - hotkey_keys = list("F11") - name = "toggle_fullscreen" - full_name = "Toggle Fullscreen" - description = "Toggle Fullscreen" - -/datum/keybinding/client/toggle_fullscreen/down(client/user) - user.toggle_fullscreen() - return TRUE diff --git a/code/datums/keybinding/communication.dm b/code/datums/keybinding/communication.dm deleted file mode 100644 index cd51c1fc196d..000000000000 --- a/code/datums/keybinding/communication.dm +++ /dev/null @@ -1,38 +0,0 @@ -/datum/keybinding/client/communication - category = CATEGORY_COMMUNICATION - -/datum/keybinding/client/communication/say - hotkey_keys = list("F3", "T") - name = "Say" - full_name = "IC Say" - -/datum/keybinding/client/communication/say/down(client/user) - user.mob.say_wrapper() - return TRUE - -/datum/keybinding/client/communication/ooc - hotkey_keys = list("F2", "O") - name = "OOC" - full_name = "Out Of Character Say (OOC)" - -/datum/keybinding/client/communication/ooc/down(client/user) - user.ooc_wrapper() - return TRUE - -/datum/keybinding/client/communication/looc - hotkey_keys = list("L") - name = "LOOC" - full_name = "Local Out Of Character Say (LOOC)" - -/datum/keybinding/client/communication/looc/down(client/user) - user.looc_wrapper() - return TRUE - -/datum/keybinding/client/communication/me - hotkey_keys = list("F4", "M") - name = "Me" - full_name = "Custom Emote (/Me)" - -/datum/keybinding/client/communication/me/down(client/user) - user.mob.me_wrapper() - return TRUE diff --git a/code/datums/keybinding/human.dm b/code/datums/keybinding/human.dm deleted file mode 100644 index 76b01548bf6c..000000000000 --- a/code/datums/keybinding/human.dm +++ /dev/null @@ -1,49 +0,0 @@ -/datum/keybinding/human - category = CATEGORY_HUMAN - weight = WEIGHT_MOB - -/datum/keybinding/human/can_use(client/user) - return ishuman(user.mob) - -/datum/keybinding/human/quick_equip - hotkey_keys = list("E") - name = "quick_equip" - full_name = "Quick Equip" - description = "Quickly puts an item in the best slot available" - -/datum/keybinding/human/quick_equip/down(client/user) - var/mob/living/carbon/human/H = user.mob - H.quick_equip() - return TRUE - -/datum/keybinding/human/holster - hotkey_keys = list("H") - name = "holster" - full_name = "Holster" - description = "Draw or holster weapon." - -/datum/keybinding/human/holster/down(client/user) - var/mob/living/carbon/human/H = user.mob - H.holster_weapon() - -/datum/keybinding/human/emote_panel - hotkey_keys = list("J") - name = "emote_panel" - full_name = "Emote Panel" - description = "Shows you emote panel." - -/datum/keybinding/human/emote_panel/down(client/user) - var/mob/living/carbon/human/H = user.mob - H.emote_panel() - -/datum/keybinding/human/race_ability - hotkey_keys = list("U") - name = "race_ability" - full_name = "Race Ability" - description = "Activates your racial ability." - -/datum/keybinding/human/race_ability/down(client/user) - var/mob/living/carbon/human/H = user.mob - var/datum/action/A = locate(H.species.race_ability) in H.actions - if(A) - A.Trigger() diff --git a/code/datums/keybinding/living.dm b/code/datums/keybinding/living.dm deleted file mode 100644 index 089cd8990456..000000000000 --- a/code/datums/keybinding/living.dm +++ /dev/null @@ -1,115 +0,0 @@ - -/datum/keybinding/living - category = CATEGORY_HUMAN - weight = WEIGHT_MOB - -/datum/keybinding/living/can_use(client/user) - return isliving(user.mob) - -/datum/keybinding/living/resist - hotkey_keys = list("N") - name = "resist" - full_name = "Resist" - description = "Break free of your current state. Handcuffed? On fire? Resist!" - -/datum/keybinding/living/resist/down(client/user) - var/mob/living/L = user.mob - L.resist() - return TRUE - -/datum/keybinding/living/toggle_move_intent - hotkey_keys = list("C") - name = "toggle_move_intent" - full_name = "Hold to toggle move intent" - description = "Held down to cycle to the other move intent, release to cycle back" - -/datum/keybinding/living/toggle_move_intent/down(client/user) - var/mob/living/L = user.mob - L.set_m_intent(L.m_intent == MOVE_INTENT_WALK ? MOVE_INTENT_RUN : MOVE_INTENT_WALK) - return TRUE - -/datum/keybinding/living/toggle_move_intent/up(client/user) - var/mob/living/L = user.mob - L.set_m_intent(L.m_intent == MOVE_INTENT_WALK ? MOVE_INTENT_RUN : MOVE_INTENT_WALK) - return TRUE - -/datum/keybinding/living/drop_item - hotkey_keys = list("Q", "Northwest") // HOME - name = "drop_item" - full_name = "Drop Item" - description = "" - -/datum/keybinding/living/drop_item/down(client/user) - var/mob/living/L = user.mob - L.drop_item() - return TRUE - -/datum/keybinding/living/crawl - hotkey_keys = list("None") - name = "crawl" - full_name = "Crawl" - description = "You lay down/get up" - -/datum/keybinding/living/crawl/down(client/user) - var/mob/living/L = user.mob - L.crawl() - return TRUE - -/datum/keybinding/living/swap_hands - hotkey_keys = list("X", "Northeast") // PAGEUP - name = "swap_hands" - full_name = "Swap hands" - description = "" - -/datum/keybinding/living/swap_hands/down(client/user) - var/mob/living/L = user.mob - L.swap_hand() - return TRUE - -/datum/keybinding/living/select_help_intent - hotkey_keys = list("1") - name = "select_help_intent" - full_name = "Select help intent" - description = "" - -/datum/keybinding/living/select_help_intent/down(client/user) - if(issilicon(user.mob)) - return - user.mob?.a_intent_change(INTENT_HELP) - return TRUE - -/datum/keybinding/living/select_disarm_intent - hotkey_keys = list("2") - name = "select_push_intent" - full_name = "Select push intent" - description = "" - -/datum/keybinding/living/select_disarm_intent/down(client/user) - if(issilicon(user.mob)) - return - user.mob?.a_intent_change(INTENT_PUSH) - return TRUE - -/datum/keybinding/living/select_grab_intent - hotkey_keys = list("3") - name = "select_grab_intent" - full_name = "Select grab intent" - description = "" - -/datum/keybinding/living/select_grab_intent/down(client/user) - if(issilicon(user.mob)) - return - user.mob?.a_intent_change(INTENT_GRAB) - return TRUE - -/datum/keybinding/living/select_harm_intent - hotkey_keys = list("4") - name = "select_harm_intent" - full_name = "Select harm intent" - description = "" - -/datum/keybinding/living/select_harm_intent/down(client/user) - if(issilicon(user.mob)) - return - user.mob?.a_intent_change(INTENT_HARM) - return TRUE diff --git a/code/datums/keybinding/mob.dm b/code/datums/keybinding/mob.dm deleted file mode 100644 index f34749cb67d4..000000000000 --- a/code/datums/keybinding/mob.dm +++ /dev/null @@ -1,142 +0,0 @@ -/datum/keybinding/mob - category = CATEGORY_HUMAN - weight = WEIGHT_MOB - -/datum/keybinding/mob/stop_pulling - hotkey_keys = list("Delete") - name = "stop_pulling" - full_name = "Stop pulling" - description = "" - -/datum/keybinding/mob/stop_pulling/down(client/user) - var/mob/M = user.mob - if(!M.pulling) - to_chat(user, "You are not pulling anything.") - else - M.stop_pulling() - return TRUE - -/datum/keybinding/mob/cycle_intent_right - hotkey_keys = list("G", "Insert") - name = "cycle_intent_right" - full_name = "Cycle intent right" - description = "" - -/datum/keybinding/mob/cycle_intent_right/down(client/user) - var/mob/M = user.mob - M.a_intent_change(INTENT_HOTKEY_RIGHT) - return TRUE - -/datum/keybinding/mob/cycle_intent_left - hotkey_keys = list("F") - name = "cycle_intent_left" - full_name = "Cycle intent left" - description = "" - -/datum/keybinding/mob/cycle_intent_left/down(client/user) - var/mob/M = user.mob - M.a_intent_change(INTENT_HOTKEY_LEFT) - return TRUE - -/datum/keybinding/mob/activate_inhand - hotkey_keys = list("Z", "Y","Southeast") // Southeast = PAGEDOWN - name = "activate_inhand" - full_name = "Activate in-hand" - description = "Uses whatever item you have inhand" - -/datum/keybinding/mob/activate_inhand/down(client/user) - var/mob/M = user.mob - M.mode() - return TRUE - -/datum/keybinding/mob/target_head_cycle - hotkey_keys = list("Numpad8") - name = "target_head_cycle" - full_name = "Target: Cycle head" - description = "" - -/datum/keybinding/mob/target_head_cycle/down(client/user) - user.body_toggle_head() - return TRUE - -/datum/keybinding/mob/target_r_arm - hotkey_keys = list("Numpad4") - name = "target_r_arm" - full_name = "Target: right arm" - description = "" - -/datum/keybinding/mob/target_r_arm/down(client/user) - user.body_r_arm() - return TRUE - -/datum/keybinding/mob/target_body_chest - hotkey_keys = list("Numpad5") - name = "target_body_chest" - full_name = "Target: Body" - description = "" - -/datum/keybinding/mob/target_body_chest/down(client/user) - user.body_chest() - return TRUE - -/datum/keybinding/mob/target_left_arm - hotkey_keys = list("Numpad6") - name = "target_left_arm" - full_name = "Target: left arm" - description = "" - -/datum/keybinding/mob/target_left_arm/down(client/user) - user.body_l_arm() - return TRUE - -/datum/keybinding/mob/target_right_leg - hotkey_keys = list("Numpad1") - name = "target_right_leg" - full_name = "Target: Right leg" - description = "" - -/datum/keybinding/mob/target_right_leg/down(client/user) - user.body_r_leg() - return TRUE - -/datum/keybinding/mob/target_body_groin - hotkey_keys = list("Numpad2") - name = "target_body_groin" - full_name = "Target: Groin" - description = "" - -/datum/keybinding/mob/target_body_groin/down(client/user) - user.body_groin() - return TRUE - -/datum/keybinding/mob/target_left_leg - hotkey_keys = list("Numpad3") - name = "target_left_leg" - full_name = "Target: left leg" - description = "" - -/datum/keybinding/mob/target_left_leg/down(client/user) - user.body_l_leg() - return TRUE - -/datum/keybinding/mob/prevent_movement - hotkey_keys = list("Ctrl") - name = "block_movement" - full_name = "Block movement" - description = "Prevents you from moving" - -/datum/keybinding/mob/prevent_movement/down(client/user) - user.movement_locked = TRUE - -/datum/keybinding/mob/prevent_movement/up(client/user) - user.movement_locked = FALSE - -/datum/keybinding/mob/click_on_self - hotkey_keys = list("B") - name = "click_on_self" - full_name = "Click On Self" - description = "" - -/datum/keybinding/mob/click_on_self/down(client/user) - var/mob/M = user.mob - M.click_on_self() diff --git a/code/datums/keybinding/movement.dm b/code/datums/keybinding/movement.dm deleted file mode 100644 index efa1b556d22e..000000000000 --- a/code/datums/keybinding/movement.dm +++ /dev/null @@ -1,27 +0,0 @@ -/datum/keybinding/movement - category = CATEGORY_MOVEMENT - weight = WEIGHT_HIGHEST - -/datum/keybinding/movement/north - hotkey_keys = list("W", "North") - name = "North" - full_name = "Move North" - description = "Moves your character north" - -/datum/keybinding/movement/south - hotkey_keys = list("S", "South") - name = "South" - full_name = "Move South" - description = "Moves your character south" - -/datum/keybinding/movement/west - hotkey_keys = list("A", "West") - name = "West" - full_name = "Move West" - description = "Moves your character left" - -/datum/keybinding/movement/east - hotkey_keys = list("D", "East") - name = "East" - full_name = "Move East" - description = "Moves your character east" diff --git a/code/datums/keybinding/robot.dm b/code/datums/keybinding/robot.dm deleted file mode 100644 index 686b42249868..000000000000 --- a/code/datums/keybinding/robot.dm +++ /dev/null @@ -1,62 +0,0 @@ -/datum/keybinding/robot - category = CATEGORY_ROBOT - weight = WEIGHT_ROBOT - -/datum/keybinding/robot/can_use(client/user) - return isrobot(user.mob) - -/datum/keybinding/robot/moduleone - hotkey_keys = list("1") - name = "module_one" - full_name = "Toggle module 1" - description = "Equips or unequips the first module" - -/datum/keybinding/robot/moduleone/down(client/user) - var/mob/living/silicon/robot/R = user.mob - R.toggle_module(1) - return TRUE - -/datum/keybinding/robot/moduletwo - hotkey_keys = list("2") - name = "module_two" - full_name = "Toggle module 2" - description = "Equips or unequips the second module" - -/datum/keybinding/robot/moduletwo/down(client/user) - var/mob/living/silicon/robot/R = user.mob - R.toggle_module(2) - return TRUE - -/datum/keybinding/robot/modulethree - hotkey_keys = list("3") - name = "module_three" - full_name = "Toggle module 3" - description = "Equips or unequips the third module" - -/datum/keybinding/robot/modulethree/down(client/user) - var/mob/living/silicon/robot/R = user.mob - R.toggle_module(3) - return TRUE - -/datum/keybinding/robot/intent_cycle - hotkey_keys = list("4") - name = "cycle_intent" - full_name = "Cycle intent left" - description = "Cycles the intent left" - -/datum/keybinding/robot/intent_cycle/down(client/user) - var/mob/living/silicon/robot/R = user.mob - R.a_intent_change(INTENT_HOTKEY_LEFT) - return TRUE - -/datum/keybinding/robot/unequip_module - hotkey_keys = list("Q") - name = "unequip_module" - full_name = "Unequip module" - description = "Unequips the active module" - -/datum/keybinding/robot/unequip_module/down(client/user) - var/mob/living/silicon/robot/R = user.mob - if(R.module) - R.uneq_active() - return TRUE diff --git a/code/datums/lighting/level_light.dm b/code/datums/lighting/level_light.dm index b3c2c1a29b58..111b2702a8cb 100644 --- a/code/datums/lighting/level_light.dm +++ b/code/datums/lighting/level_light.dm @@ -35,7 +35,7 @@ var/global/list/datum/level_lighting_effect/lighting_effects /datum/level_lighting_effect/random_aurora/New(duration = 60 SECONDS) var/transitions = ceil(duration/transition_delay) for(var/i in 1 to transitions) - colors += list(color_lightness_max(random_color(), 0.70)) + colors += list(color_lightness_max(random_color(), 70)) /* Planetary lighting */ /datum/level_lighting_effect/snow_map_random diff --git a/code/datums/music_player.dm b/code/datums/music_player.dm index 1e3ed0bd3c07..35b939f49c67 100644 --- a/code/datums/music_player.dm +++ b/code/datums/music_player.dm @@ -276,7 +276,7 @@ var/global/datum/notes_storage/note_cache_storage = new var/sound/S = global.note_cache_storage.instrument_sound_notes["[sound_path]/[current_note]"] if(!S) S = global.note_cache_storage.instrument_sound_notes["[sound_path]/[current_note]"] = sound("[sound_path]/[current_note].ogg") - playsound(instrument, S, VOL_EFFECTS_INSTRUMENT, volume, FALSE, null, null, falloff = 5) + playsound(instrument, S, VOL_MUSIC_INSTRUMENTS, volume, FALSE, null, null, falloff = 5) var/pause_time = COUNT_PAUSE(song_tempo) diff --git a/code/datums/runechat.dm b/code/datums/runechat.dm index 6a36e7f27d95..5b23737fa229 100644 --- a/code/datums/runechat.dm +++ b/code/datums/runechat.dm @@ -226,7 +226,7 @@ if(!speaker || isobserver(speaker)) return - if(!client || !client.prefs.show_runechat) + if(!client || !client.prefs.get_pref(/datum/pref/player/ui/runechat)) return if(SSlag_switch.measures[DISABLE_RUNECHAT] && !HAS_TRAIT(speaker, TRAIT_BYPASS_MEASURES)) diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 37ef32c74c87..7feeed7e85ca 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -18,7 +18,7 @@ return RAI.next_music_start = world.time + REPLICATOR_MUSIC_LENGTH - mob_viewer.playsound_local(null, 'sound/music/storm_resurrection.ogg', VOL_MUSIC, null, null, CHANNEL_MUSIC, vary = FALSE, frequency = null, ignore_environment = TRUE) + mob_viewer.playsound_local(null, 'sound/music/storm_resurrection.ogg', VOL_AMBIENT, null, null, CHANNEL_MUSIC, vary = FALSE, frequency = null, ignore_environment = TRUE) /datum/status_effect/swarm_gift diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index e677fa876c7c..ee01d0f86d38 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -451,10 +451,10 @@ /client/var/list/image/outlined_item = list() /atom/movable/proc/apply_outline(color) - if(anchored || !usr.client.prefs.outline_enabled) + if(anchored || !usr.client.prefs.get_pref(/datum/pref/player/ui/outline)) return if(!color) - color = usr.client.prefs.outline_color || COLOR_BLUE_LIGHT + color = usr.client.prefs.get_pref(/datum/pref/player/ui/outline_color) || COLOR_BLUE_LIGHT if(usr.client.outlined_item[src]) return diff --git a/code/game/gamemodes/factions/replicators.dm b/code/game/gamemodes/factions/replicators.dm index 3d534446f26e..b16a9779a4f4 100644 --- a/code/game/gamemodes/factions/replicators.dm +++ b/code/game/gamemodes/factions/replicators.dm @@ -272,7 +272,7 @@ Message ends."} return RAI.next_music_start = world.time + REPLICATOR_MUSIC_LENGTH - R.playsound_local(null, 'sound/music/storm_resurrection.ogg', VOL_MUSIC, null, null, CHANNEL_MUSIC, vary = FALSE, frequency = null, ignore_environment = TRUE) + R.playsound_local(null, 'sound/music/storm_resurrection.ogg', VOL_AMBIENT, null, null, CHANNEL_MUSIC, vary = FALSE, frequency = null, ignore_environment = TRUE) /datum/faction/replicators/proc/victory_animation(turf/T) SSticker.explosion_in_progress = TRUE diff --git a/code/game/gamemodes/modes_gameplays/cult/narsie.dm b/code/game/gamemodes/modes_gameplays/cult/narsie.dm index 2ff14fd2cfb1..f72251940754 100644 --- a/code/game/gamemodes/modes_gameplays/cult/narsie.dm +++ b/code/game/gamemodes/modes_gameplays/cult/narsie.dm @@ -34,7 +34,7 @@ for(var/mob/M in player_list) if(!isnewplayer(M)) to_chat(M, "Н́̿̚Ӓ́̈́Р̔̚͘-̽̔͆С̈́͛͛И̓͊̕ В͒̚͝О̓͒̓С̓̾͑С̔̓͝Т̈́͘̚А͒͑͘Л͐͌̾") - M.playsound_local(null, pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg'), VOL_EFFECTS_VOICE_ANNOUNCEMENT, vary = FALSE, frequency = null, ignore_environment = TRUE) + M.playsound_local(null, pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg'), VOL_VOICE_ANNOUNCEMENTS, vary = FALSE, frequency = null, ignore_environment = TRUE) if(!iscultist(M)) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "narsie", /datum/mood_event/narsie) else diff --git a/code/game/gamemodes/modes_gameplays/cult/rune_datum.dm b/code/game/gamemodes/modes_gameplays/cult/rune_datum.dm index 685126a7a56c..e1b2a0d6c848 100644 --- a/code/game/gamemodes/modes_gameplays/cult/rune_datum.dm +++ b/code/game/gamemodes/modes_gameplays/cult/rune_datum.dm @@ -268,7 +268,7 @@ var/turf = get_turf(all_items[i]) var/list/viewing = list() for(var/mob/M in viewers(turf)) - if(M.client && (M.client.prefs.toggles & SHOW_ANIMATIONS)) + if(M.client?.prefs.get_pref(/datum/pref/player/game/melee_animation)) viewing |= M.client var/image/I = image(uristrune_cache[pick(uristrune_cache)], turf, layer = FLY_LAYER) diff --git a/code/game/gamemodes/modes_gameplays/ninja/suit/SpiderOS/topic.dm b/code/game/gamemodes/modes_gameplays/ninja/suit/SpiderOS/topic.dm index b98f84d03025..cd1ba26fdbc3 100644 --- a/code/game/gamemodes/modes_gameplays/ninja/suit/SpiderOS/topic.dm +++ b/code/game/gamemodes/modes_gameplays/ninja/suit/SpiderOS/topic.dm @@ -71,10 +71,11 @@ useMS.send_pda_message("[P.owner]",sender,"[t]") for(var/mob/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) // src.client is so that ghosts don't have to listen to mice - if(isnewplayer(M)) - continue - to_chat(M, "PDA Message - [U] -> [P.owner]: [t]") + if(M.stat != DEAD || isnewplayer(M)) + continue + if(!M.client.prefs.get_pref(/datum/pref/player/chat/ghostears)) + continue + to_chat(M, "PDA Message - [U] -> [P.owner]: [t]") if (!P.message_silent) playsound(P, 'sound/machines/twobeep.ogg', VOL_EFFECTS_MASTER) diff --git a/code/game/gamemodes/modes_gameplays/nuclear/nuclearbomb.dm b/code/game/gamemodes/modes_gameplays/nuclear/nuclearbomb.dm index 664b93448826..1cb6116ffd92 100644 --- a/code/game/gamemodes/modes_gameplays/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/modes_gameplays/nuclear/nuclearbomb.dm @@ -51,7 +51,7 @@ var/global/bomb_set else bomb_set = TRUE //So long as there is one nuke timing, it means one nuke is armed. timeleft = max(timeleft - 2, 0) // 2 seconds per process() - playsound(src, 'sound/items/timer.ogg', VOL_EFFECTS_MISC, 30, FALSE) + playsound(src, 'sound/items/timer.ogg', VOL_SPAM_EFFECTS, 30, FALSE) if(timeleft <= 120 && COOLDOWN_FINISHED(global, nuclear_siren_cooldown)) for(var/mob/M in player_list) if(!isnewplayer(M)) @@ -469,7 +469,7 @@ var/global/bomb_set playsound(src, 'sound/machines/Alarm.ogg', VOL_EFFECTS_MASTER, null, FALSE, null, 30) for(var/mob/M in player_list) if(!isnewplayer(M)) - M.playsound_local(null, 'sound/machines/Alarm_reverb.ogg', VOL_EFFECTS_VOICE_ANNOUNCEMENT, vary = FALSE, frequency = null, ignore_environment = TRUE) + M.playsound_local(null, 'sound/machines/Alarm_reverb.ogg', VOL_VOICE_ANNOUNCEMENTS, vary = FALSE, frequency = null, ignore_environment = TRUE) update_icon() addtimer(CALLBACK(src, PROC_REF(fail)), 13 SECONDS) //Good taste, right? diff --git a/code/game/gamemodes/roles/changeling.dm b/code/game/gamemodes/roles/changeling.dm index 5313c870c62e..0122a2056ae2 100644 --- a/code/game/gamemodes/roles/changeling.dm +++ b/code/game/gamemodes/roles/changeling.dm @@ -206,6 +206,6 @@ for(var/mob/M in player_list) if(!isnewplayer(M)) to_chat(M, "A terrible roar is coming from somewhere around the station.") - M.playsound_local(null, 'sound/antag/abomination_start.ogg', VOL_EFFECTS_VOICE_ANNOUNCEMENT, vary = FALSE, frequency = null, ignore_environment = TRUE) + M.playsound_local(null, 'sound/antag/abomination_start.ogg', VOL_VOICE_ANNOUNCEMENTS, vary = FALSE, frequency = null, ignore_environment = TRUE) #undef OVEREATING_AMOUNT diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 0297c3de3760..7ae5a0d366d8 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -306,14 +306,14 @@ var/global/message_delay = 0 // To make sure restarting the recentmessages list /* --- Loop through the receivers and categorize them --- */ - if (R.client && !(R.client.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + if (R.client && !R.client.prefs.get_pref(/datum/pref/player/chat/radio)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. continue if(isnewplayer(R)) // we don't want new players to hear messages. rare but generates runtimes. continue // Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates - if(data == BROADCAST_MODE_SYNDICATE && isobserver(R) && R.client && (R.client.prefs.chat_toggles & CHAT_GHOSTRADIO)) + if(data == BROADCAST_MODE_SYNDICATE && isobserver(R) && R.client && R.client.prefs.get_pref(/datum/pref/player/chat/ghostradio)) continue // --- Check for compression --- @@ -586,7 +586,7 @@ var/global/message_delay = 0 // To make sure restarting the recentmessages list /* --- Loop through the receivers and categorize them --- */ - if (R.client && !(R.client.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + if (R.client && !R.client.prefs.get_pref(/datum/pref/player/chat/radio)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. continue diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index ce34416ce86c..e18e48c5d507 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1564,10 +1564,12 @@ tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]"))) for(var/mob/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) // src.client is so that ghosts don't have to listen to mice - if(isnewplayer(M)) - continue - to_chat(M, "PDA Message - [owner] -> [P.owner]: [t]") + if(M.stat != DEAD || isnewplayer(M)) + continue + if(!M.client.prefs.get_pref(/datum/pref/player/chat/ghostears)) + continue + + to_chat(M, "PDA Message - [owner] -> [P.owner]: [t]") if(!conversations.Find("\ref[P]")) conversations.Add("\ref[P]") diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 8db7f4cc6880..83a3408cf1a2 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -471,7 +471,7 @@ var/global/GLOBAL_RADIO_TYPE = 1 // radio type to use var/list/heard_garbled = list() // garbled message for (var/mob/R in receive) - if (R.client && !(R.client.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + if (R.client && !R.client.prefs.get_pref(/datum/pref/player/chat/radio)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. continue if (R.say_understands(M)) if (ishuman(M) && M.GetVoice() != M.real_name) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 63944c940776..cb168766b824 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -216,7 +216,7 @@ var/cooldown = FALSE /obj/item/weapon/bikehorn/proc/honk(mob/user) - playsound(src, 'sound/items/bikehorn.ogg', VOL_EFFECTS_MISC) + playsound(src, 'sound/items/bikehorn.ogg', VOL_SPAM_EFFECTS) if(user.can_waddle()) user.waddle(pick(-14, 0, 14), 4) diff --git a/code/game/objects/items/weapons/hydroponics.dm b/code/game/objects/items/weapons/hydroponics.dm index 42abbac48010..e84fc24da4c8 100644 --- a/code/game/objects/items/weapons/hydroponics.dm +++ b/code/game/objects/items/weapons/hydroponics.dm @@ -243,7 +243,7 @@ var/global/gourd_name = null if(!COOLDOWN_FINISHED(src, last_maraca)) return COOLDOWN_START(src, last_maraca, MARACA_COOLDOWN) - playsound(src, 'sound/musical_instruments/maraca/maraca.ogg', VOL_EFFECTS_INSTRUMENT, 100, TRUE, falloff = 5) + playsound(src, 'sound/musical_instruments/maraca/maraca.ogg', VOL_MUSIC_INSTRUMENTS, 100, TRUE, falloff = 5) #undef MARACA_COOLDOWN diff --git a/code/game/objects/structures/chapel.dm b/code/game/objects/structures/chapel.dm index 8412989331fa..2ccb54014dc4 100644 --- a/code/game/objects/structures/chapel.dm +++ b/code/game/objects/structures/chapel.dm @@ -207,7 +207,7 @@ ADD_TO_GLOBAL_LIST(/obj/effect/effect/bell, bells) for(var/mob/M in player_list) if(M.z == z) // Why do they call them voice announcements if it's just global announcements? - M.playsound_local(null, 'sound/effects/big_bell.ogg', VOL_EFFECTS_VOICE_ANNOUNCEMENT, 75) + M.playsound_local(null, 'sound/effects/big_bell.ogg', VOL_VOICE_ANNOUNCEMENTS, 75) to_chat(M, "[bicon(src)] [src] rings, \"[text]\"") var/swing_angle = adjust_strength(12, strength, 0.25, 32) diff --git a/code/game/sound.dm b/code/game/sound.dm index 39b127d2e516..0878c888af18 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -167,7 +167,7 @@ voluminosity = if FALSE, removes the difference between left and right ear. /mob/proc/playsound_lobbymusic() if(!SSticker || !SSticker.login_music || !client) return - playsound_music(SSticker.login_music, VOL_MUSIC, null, null, CHANNEL_MUSIC) // MAD JAMS + playsound_music(SSticker.login_music, VOL_LOBBY_MUSIC, null, null, CHANNEL_MUSIC) // MAD JAMS /mob/proc/playsound_music(soundin, volume_channel = NONE, repeat = FALSE, wait = FALSE, channel = 0, priority = 0, status = 0) // byond vars sorted by ref order. if(!client || !client.prefs_ready) @@ -180,7 +180,7 @@ voluminosity = if FALSE, removes the difference between left and right ear. but still keep ability to resume admin music on the fly mid position */ - if(!vol && volume_channel != VOL_ADMIN) + if(!vol && volume_channel != VOL_ADMIN_SOUNDS) return var/sound/S @@ -222,248 +222,28 @@ voluminosity = if FALSE, removes the difference between left and right ear. if(!isnum(volume_channel) || !volume_channel) CRASH("type mismatch for volume_channel or volume channel is not set.") - if(volume_channel & VOL_MUSIC) - . = prefs.snd_music_vol - else if(volume_channel & VOL_AMBIENT) - . = prefs.snd_ambient_vol - else if(volume_channel & VOL_EFFECTS_MASTER) - . = prefs.snd_effects_master_vol - switch(volume_channel) // now for sub categories - if(VOL_EFFECTS_VOICE_ANNOUNCEMENT) - . *= prefs.snd_effects_voice_announcement_vol * 0.01 - if(VOL_EFFECTS_MISC) - . *= prefs.snd_effects_misc_vol * 0.01 - if(VOL_EFFECTS_INSTRUMENT) - . *= prefs.snd_effects_instrument_vol * 0.01 - else if(volume_channel & VOL_NOTIFICATIONS) - . = prefs.snd_notifications_vol - else if(volume_channel & VOL_ADMIN) - . = prefs.snd_admin_vol - else if(volume_channel & VOL_JUKEBOX) - . = prefs.snd_jukebox_vol - else - CRASH("unknown volume_channel: [volume_channel]") - - if(. > 0) - . = max(0.002, VOL_LINEAR_TO_NON(.)) // max(master slider won't kill sub slider's volume if both are less than max value). - -/client/proc/set_sound_volume(volume_channel, vol) - vol = clamp(vol, 0, 100) - switch(volume_channel) - if(VOL_MUSIC) - prefs.snd_music_vol = vol - mob.playsound_music_update_volume(volume_channel, CHANNEL_MUSIC) + if(VOL_LOBBY_MUSIC) + . = prefs.get_pref(/datum/pref/player/audio/lobby) if(VOL_AMBIENT) - prefs.snd_ambient_vol = vol - mob.playsound_music_update_volume(volume_channel, CHANNEL_AMBIENT) - mob.playsound_music_update_volume(volume_channel, CHANNEL_AMBIENT_LOOP) + . = prefs.get_pref(/datum/pref/player/audio/ambient) if(VOL_EFFECTS_MASTER) - prefs.snd_effects_master_vol = vol - if(VOL_EFFECTS_VOICE_ANNOUNCEMENT) - prefs.snd_effects_voice_announcement_vol = vol - if(VOL_EFFECTS_MISC) - prefs.snd_effects_misc_vol = vol - if(VOL_EFFECTS_INSTRUMENT) - prefs.snd_effects_instrument_vol = vol + . = prefs.get_pref(/datum/pref/player/audio/effects) + if(VOL_VOICE_ANNOUNCEMENTS) + . = prefs.get_pref(/datum/pref/player/audio/voice_announcements) + if(VOL_SPAM_EFFECTS) + // spam effects is just additional coefficient, by default it uses effects setting + . = prefs.get_pref(/datum/pref/player/audio/effects) * prefs.get_pref(/datum/pref/player/audio/spam_effects) * 0.01 + if(VOL_MUSIC_INSTRUMENTS) + . = prefs.get_pref(/datum/pref/player/audio/instruments) if(VOL_NOTIFICATIONS) - prefs.snd_notifications_vol = vol - if(VOL_ADMIN) - prefs.snd_admin_vol = vol - mob.playsound_music_update_volume(volume_channel, CHANNEL_ADMIN) + . = prefs.get_pref(/datum/pref/player/audio/notifications) + if(VOL_ADMIN_SOUNDS) + . = prefs.get_pref(/datum/pref/player/audio/admin_sounds) if(VOL_JUKEBOX) - var/old_vol = prefs.snd_jukebox_vol - - prefs.snd_jukebox_vol = vol - - if(istype(media)) // will be updated in "/mob/living/Login()" if changed in lobby. - media.update_volume() - - if(!vol && old_vol) // only play/stop if last change is a mute or unmute state. - media.stop_music() - else if(vol && !old_vol) - media.update_music() - -/client/proc/update_volume(href_list) - var/slider - var/vol_raw - - switch(href_list["proc"]) - if("sliderMoved") - slider = text2num(href_list["slider"]) - vol_raw = text2num(href_list["volume"]) - if("save") - if(prefs.save_preferences()) - to_chat(src, "Preferences Saved.") - else - to_chat(src, "Preferences saving failed due to unknown reason.") - return - if("testVolume") - mob.playsound_local(null, 'sound/weapons/saberon.ogg', text2num(href_list["slider"]), vary = FALSE, channel = CHANNEL_VOLUMETEST) - return + . = prefs.get_pref(/datum/pref/player/audio/jukebox) else - return - - if(!isnum(vol_raw) || !isnum(slider)) - return - - set_sound_volume(slider, vol_raw) + CRASH("unknown volume_channel: [volume_channel]") -/client/verb/show_volume_controls() - set name = ".showvolumecontrols" - set hidden = TRUE - - if(!prefs_ready) - to_chat(src, "Preferences not ready, please wait and try again.") - return - - var/list/tables_data = list( - "Music" = list( - "Master" = "[VOL_MUSIC]" - ), - "Ambient" = list( - "Master" = "[VOL_AMBIENT]" - ), - "Effects" = list( - "Master" = "[VOL_EFFECTS_MASTER]", - "Voice" = "[VOL_EFFECTS_VOICE_ANNOUNCEMENT]", - "Misc" = "[VOL_EFFECTS_MISC]", - "Music Instruments" = "[VOL_EFFECTS_INSTRUMENT]" - ), - "Notifications" = list( - "Master" = "[VOL_NOTIFICATIONS]" - ), - "Admin Music/Sounds" = list( - "Master" = "[VOL_ADMIN]" - ), - "Jukebox" = list( - "Master" = "[VOL_JUKEBOX]" - ) - ) - - var/list/prefs_vol_values = list( - "[VOL_MUSIC]" = prefs.snd_music_vol, - "[VOL_AMBIENT]" = prefs.snd_ambient_vol, - "[VOL_EFFECTS_MASTER]" = prefs.snd_effects_master_vol, - "[VOL_EFFECTS_VOICE_ANNOUNCEMENT]" = prefs.snd_effects_voice_announcement_vol, - "[VOL_EFFECTS_MISC]" = prefs.snd_effects_misc_vol, - "[VOL_EFFECTS_INSTRUMENT]" = prefs.snd_effects_instrument_vol, - "[VOL_NOTIFICATIONS]" = prefs.snd_notifications_vol, - "[VOL_ADMIN]" = prefs.snd_admin_vol, - "[VOL_JUKEBOX]" = prefs.snd_jukebox_vol - ) - - var/list/sliders_hint = list( - "[VOL_MUSIC]" = "Lobby music.", - "[VOL_AMBIENT]" = "Music and sound effects of ambient type.", - "[VOL_EFFECTS_MASTER]" = "Controls all sound effects.", - "[VOL_EFFECTS_VOICE_ANNOUNCEMENT]" = "Voiced global announcements.", - "[VOL_EFFECTS_MISC]" = "Anything spammy that may annoy e.g.: tesla engine.", - "[VOL_EFFECTS_INSTRUMENT]" = "Music instruments.", - "[VOL_NOTIFICATIONS]" = "OOC notifications such as admin PM, cloning.", - "[VOL_ADMIN]" = "Admin sounds and music.", - "[VOL_JUKEBOX]" = "In-game jukebox's volume." - ) - - var/dat = {" - - "} - - for(var/category in tables_data) - dat += {" - - - "} - - var/list/sliders_data = tables_data[category] - - for(var/slider_name in sliders_data) - var/slider_id = sliders_data[slider_name] - var/slider_value = prefs_vol_values[slider_id] - var/slider_hint = sliders_hint[slider_id] - dat += {" - - - - - - "} - - dat += {" -
[category]
- [slider_name] (?): - - - -

[slider_value]

-
- "} - - dat +={" -

 

- - - - "} - - var/datum/browser/popup = new(usr, "volcontrols", "Audio Settings:", 620, 500, null, CSS_THEME_LIGHT) - popup.set_content(dat) - popup.open() + if(. > 0) + . = max(0.002, VOL_LINEAR_TO_NON(.)) // max(master slider won't kill sub slider's volume if both are less than max value). diff --git a/code/game/turfs/turf_snow.dm b/code/game/turfs/turf_snow.dm index caec52a5050c..dc5dfa86c07a 100644 --- a/code/game/turfs/turf_snow.dm +++ b/code/game/turfs/turf_snow.dm @@ -172,7 +172,7 @@ to_chat(user, "No power!") return - playsound(user, P.usesound, VOL_EFFECTS_INSTRUMENT) + playsound(user, P.usesound, VOL_MUSIC_INSTRUMENTS) to_chat(user, "You start [P.drill_verb].") if(!user.is_busy(src) && P.use_tool(src, user, 10, volume = 100)) diff --git a/code/game/verbs/fitviewport.dm b/code/game/verbs/fitviewport.dm deleted file mode 100644 index c584bf6b819c..000000000000 --- a/code/game/verbs/fitviewport.dm +++ /dev/null @@ -1,70 +0,0 @@ -/client/verb/onresize() - set hidden = TRUE - - if(prefs.auto_fit_viewport && !isnewplayer(mob)) - fit_viewport() - -/client/verb/fit_viewport() - set name = "Fit viewport" - set category = "OOC" - set desc = "Fit the width of the map window to match the viewport" - - if(isnewplayer(mob)) // no mapwindow in lobby - to_chat(usr, "You can't fix viewport while in lobby.") - return - - // Fetch aspect ratio - var/view_size = getviewsize(view) - var/aspect_ratio = view_size[1] / view_size[2] - - // Calculate desired pixel width using window size and aspect ratio - var/list/sizes = params2list(winget(src, "mainwindow.mainvsplit;mapwindow", "size")) - - // Client closed the window? Some other error? This is unexpected behaviour, let's - // CRASH with some info. - if(!sizes["mapwindow.size"]) - CRASH("sizes does not contain mapwindow.size key. This means a winget failed to return what we wanted. --- sizes var: [sizes] --- sizes length: [length(sizes)]") - - var/list/map_size = splittext(sizes["mapwindow.size"], "x") - - // Looks like we expect mapwindow.size to be "ixj" where i and j are numbers. - // If we don't get our expected 2 outputs, let's give some useful error info. - if(length(map_size) != 2) - CRASH("map_size of incorrect length --- map_size var: [map_size] --- map_size length: [length(map_size)]") - - var/height = text2num(map_size[2]) - var/desired_width = round(height * aspect_ratio) - if (text2num(map_size[1]) == desired_width) - // Nothing to do - return - - var/split_size = splittext(sizes["mainwindow.mainvsplit.size"], "x") - var/split_width = text2num(split_size[1]) - - // Avoid auto-resizing the statpanel and chat into nothing. - desired_width = min(desired_width, split_width - 300) - - // Calculate and apply a best estimate - // +4 pixels are for the width of the splitter's handle - var/pct = 100 * (desired_width + 4) / split_width - winset(src, "mainwindow.mainvsplit", "splitter=[pct]") - - // Apply an ever-lowering offset until we finish or fail - var/delta - for(var/safety in 1 to 10) - var/after_size = winget(src, "mapwindow", "size") - map_size = splittext(after_size, "x") - var/got_width = text2num(map_size[1]) - - if (got_width == desired_width) - // success - return - else if (isnull(delta)) - // calculate a probable delta value based on the difference - delta = 100 * (desired_width - got_width) / split_width - else if ((delta > 0 && got_width > desired_width) || (delta < 0 && got_width < desired_width)) - // if we overshot, halve the delta and reverse direction - delta = -delta/2 - - pct += delta - winset(src, "mainwindow.split", "splitter=[pct]") diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index f32f9faecb7c..f5c74d93c11c 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -1,5 +1,4 @@ -var/global/normal_ooc_colour = null var/global/bridge_ooc_colour = "#7b804f" /client/verb/ooc(msg as text) @@ -17,7 +16,7 @@ var/global/bridge_ooc_colour = "#7b804f" if(!msg) return - if(!(prefs.chat_toggles & CHAT_OOC)) + if(!prefs.get_pref(/datum/pref/player/chat/ooc)) to_chat(src, "You have OOC muted.") return @@ -53,25 +52,22 @@ var/global/bridge_ooc_colour = "#7b804f" message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") return - var/display_colour = normal_ooc_colour + var/display_colour = null var/ooc_name = key if(holder && !holder.fakekey) - display_colour = "#704f80" + display_colour = OOC_COLOR_EVENTADMIN // we don't use it anymore? if(holder.rights & R_DEBUG && !(holder.rights & R_ADMIN)) - display_colour = "#1b521f" //dark green + display_colour = OOC_COLOR_CODEADMIN else if(holder.rights & R_ADMIN) - if(config.allow_admin_ooccolor) - display_colour = src.prefs.aooccolor - else - display_colour = "#b82e00" //orange + display_colour = (config.allow_admin_ooccolor && prefs.get_pref(/datum/pref/player/chat/aooccolor)) || OOC_COLOR_ADMIN send2ooc(msg, ooc_name, display_colour, src) world.send2bridge( type = list(BRIDGE_OOC), attachment_msg = "OOC: **[(holder && holder.fakekey)? holder.fakekey : ooc_name ]**: [msg]", - attachment_color = (supporter && prefs.ooccolor) ? prefs.ooccolor : display_colour, + attachment_color = (supporter && prefs.get_pref(/datum/pref/player/chat/ooccolor)) || display_colour ) /proc/send2ooc(msg, name, colour, client/sender, display_name, prefix = "OOC") @@ -88,8 +84,8 @@ var/global/bridge_ooc_colour = "#7b804f" display_name = name if(sender) - if(sender.supporter && sender.prefs.ooccolor) - display_name = "[display_name]" + if(sender.supporter && sender.prefs.get_pref(/datum/pref/player/chat/ooccolor)) + display_name = "[display_name]" if(sender.holder && sender.holder.fakekey) if(C.holder) @@ -97,30 +93,9 @@ var/global/bridge_ooc_colour = "#7b804f" else display_name = sender.holder.fakekey - if(C.prefs.chat_toggles & CHAT_OOC) + if(C.prefs.get_pref(/datum/pref/player/chat/ooc)) to_chat(C, "[msg_start]: [display_name?"[display_name]: ":""][msg_end]") -/client/proc/set_global_ooc(newColor as color) - set name = "Set Global OOC Colour" - set desc = "Set to yellow for eye burning goodness. #000000 reset colour." - set category = "OOC" - if(!holder) - return - normal_ooc_colour = newColor != "#000000" ? newColor : null - -/client/verb/set_name_ooc() - set name = "Set Name OOC Colour" - set category = "OOC" - - if(!supporter) - to_chat(usr, "This is only for [config.donate_info_url ? "supporters" : "supporters"][config.allow_byond_membership ? " and Byond Members" : ""].") - return - - var/new_ooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null - if(new_ooccolor) - prefs.ooccolor = normalize_color(new_ooccolor) - prefs.save_preferences() - /client/verb/looc(msg as text) set name = "LOOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite set desc = "Local OOC, seen only by those in view." @@ -135,7 +110,7 @@ var/global/bridge_ooc_colour = "#7b804f" msg = sanitize(msg) if(!msg) return - if(!(prefs.chat_toggles & CHAT_LOOC)) + if(!prefs.get_pref(/datum/pref/player/chat/looc)) to_chat(src, "You have LOOC muted.") return @@ -164,7 +139,7 @@ var/global/bridge_ooc_colour = "#7b804f" is_fake_key = TRUE if(isobserver(mob)) display_name = "(Ghost) [key]" - else if(prefs.chat_toggles & CHAT_CKEY) + else if(prefs.get_pref(/datum/pref/player/chat/show_ckey)) display_name += " ([key])" log_ooc("(LOCAL) [key_name(mob)] : [msg]") @@ -188,13 +163,13 @@ var/global/bridge_ooc_colour = "#7b804f" if (C in admins) continue //they are handled after that - if(C.prefs.chat_toggles & CHAT_LOOC) + if(C.prefs.get_pref(/datum/pref/player/chat/looc)) if(is_fake_key && C.holder) display_name = "[holder.fakekey]/([key])" to_chat(C, "[prefix]: [display_name]: [msg]") for(var/client/C as anything in admins) - if(C.prefs.chat_toggles & CHAT_LOOC) + if(C.prefs.get_pref(/datum/pref/player/chat/looc)) var/track = "" if(isobserver(C.mob) && !isnewplayer(mob)) track = FOLLOW_LINK(C.mob, mob) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 77a24c3d71de..d3184846c7cf 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -18,22 +18,27 @@ var/global/BSACooldown = 0 log_admin("[key_name(usr)] " + message) message_admins("[key_name_admin(usr)] " + message, 1) +// todo: target can be the one who attacked and the one who was attacked +// need to fix misuse and add both mobs here, and ATTACK_LOG_BOTH_CLIENT config /proc/msg_admin_attack(msg, mob/living/target) //Toggleable Attack Messages log_attack(msg) msg = "ATTACK: [msg] [ADMIN_PPJMPFLW(target)]" - - var/require_flags = CHAT_ATTACKLOGS + var/no_client = FALSE if(!target.client && !ishuman(target)) - require_flags |= CHAT_NOCLIENT_ATTACK + no_client = TRUE for(var/client/C as anything in admins) if(!(R_ADMIN & C.holder.rights)) continue - if((C.prefs.chat_toggles & require_flags) != require_flags) + + var/pref_level = C.prefs.get_pref(/datum/pref/player/chat/attack_log) + if(pref_level == ATTACK_LOG_DISABLED) + continue + if(pref_level == ATTACK_LOG_BY_CLIENT && no_client) continue - to_chat_attack_log(C, msg) + to_chat_attack_log(C, msg) ///////////////////////////////////////////////////////////////////////////////////////////////Panels diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c88211e92e56..0f50c7a14160 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -13,7 +13,6 @@ var/global/list/admin_verbs_admin = list( /datum/admins/proc/toggleenter, //toggles whether people can join the current game, /datum/admins/proc/toggleguests, //toggles whether guests can join the current game, /datum/admins/proc/announce, //priority announce something to all clients, - /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, @@ -44,8 +43,6 @@ var/global/list/admin_verbs_admin = list( /client/proc/check_antagonists, /client/proc/admin_memo, //admin memo system. show/delete/write. +SERVER needed to delete admin memos of others, /client/proc/dsay, //talk in deadchat using our ckey/fakekey, - /client/proc/toggleprayers, //toggles prayers on/off, - /client/proc/toggle_hear_radio, //toggles whether we hear the radio, /client/proc/secrets, /datum/admins/proc/toggleooc, //toggles ooc on/off for everyone, /datum/admins/proc/togglelooc, //toggles looc on/off for everyone, @@ -55,9 +52,6 @@ var/global/list/admin_verbs_admin = list( /client/proc/cmd_admin_say, //admin-only ooc chat, /client/proc/free_slot, //frees slot for chosen job, /client/proc/cmd_admin_change_custom_event, - /client/proc/toggleattacklogs, - /client/proc/toggle_noclient_attacklogs, - /client/proc/toggledebuglogs, /client/proc/toggleghostwriters, /client/proc/toggledrones, /client/proc/man_up, @@ -118,7 +112,6 @@ var/global/list/admin_verbs_fun = list( /client/proc/cmd_admin_add_random_ai_law, // /client/proc/make_sound, /client/proc/toggle_random_events, - /client/proc/set_global_ooc, /client/proc/editappear, /client/proc/roll_dices, /client/proc/epileptic_anomaly, @@ -187,7 +180,6 @@ var/global/list/admin_verbs_debug = list( /client/proc/enable_debug_verbs, /*/client/proc/callproc,*/ // /proc/machine_upgrade, - /client/proc/toggledebuglogs, /client/proc/view_runtimes, /client/proc/getdebuglogsbyid, /client/proc/cmd_display_del_log, @@ -233,17 +225,13 @@ var/global/list/admin_verbs_event = list( //verbs which can be hidden - needs work var/global/list/admin_verbs_hideable = list( - /client/proc/set_global_ooc, /datum/admins/proc/library_recycle_bin, /client/proc/deadmin_self, // /client/proc/deadchat, - /client/proc/toggleprayers, - /client/proc/toggle_hear_radio, /datum/admins/proc/show_traitor_panel, /datum/admins/proc/toggleenter, /datum/admins/proc/toggleguests, /datum/admins/proc/announce, - /client/proc/colorooc, /client/proc/admin_ghost, /client/proc/toggle_view_range, /client/proc/getserverlogs, @@ -405,10 +393,6 @@ var/global/list/admin_verbs_hideable = list( to_chat(src, "All of your adminverbs are now visible.") feedback_add_details("admin_verb","TAVVS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - - /client/proc/admin_ghost() set category = "Admin" set name = "Aghost" @@ -501,20 +485,6 @@ var/global/list/admin_verbs_hideable = list( 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 = "OOC" - set name = "Set Admin OOC Color" - if(!holder) - return - if(!config.allow_admin_ooccolor) - to_chat(usr, "Currently disabled by config.") - var/new_aooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null - if(new_aooccolor) - prefs.aooccolor = normalize_color(new_aooccolor) - prefs.save_preferences() - 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/stealth() set category = "Admin" set name = "Stealth Mode" @@ -929,24 +899,6 @@ var/global/list/admin_verbs_hideable = list( var/datum/atom_hud/A = global.huds[ANTAG_HUD_TRAITOR] return A.hudusers[mob] -/client/proc/toggleattacklogs() - set name = "Toggle Attack Log Messages" - set category = "Preferences" - - prefs.chat_toggles ^= CHAT_ATTACKLOGS - prefs.save_preferences() - to_chat(src, "You now [(prefs.chat_toggles & CHAT_ATTACKLOGS) ? "will" : "won't"] get attack log messages.") - feedback_add_details("admin_verb","TALM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/toggle_noclient_attacklogs() - set name = "Toggle No Client Attack Log Messages" - set category = "Preferences" - - prefs.chat_toggles ^= CHAT_NOCLIENT_ATTACK - prefs.save_preferences() - to_chat(src, "You now [(prefs.chat_toggles & CHAT_NOCLIENT_ATTACK) ? "will" : "won't"] get attack log messages for mobs that don't have a client.") - feedback_add_details("admin_verb","TNCALM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /client/proc/toggleghostwriters() set name = "Toggle ghost writers" set category = "Server" @@ -975,15 +927,6 @@ var/global/list/admin_verbs_hideable = list( to_chat(src, "Enabled maint drones.") message_admins("Admin [key_name_admin(usr)] has enabled maint drones.") -/client/proc/toggledebuglogs() - set name = "Toggle Debug Log Messages" - set category = "Preferences" - - prefs.chat_toggles ^= CHAT_DEBUGLOGS - prefs.save_preferences() - to_chat(src, "You now [(prefs.chat_toggles & CHAT_DEBUGLOGS) ? "will" : "won't"] get debug log messages.") - feedback_add_details("admin_verb","TDLM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /client/proc/man_up(mob/T as mob in player_list) set category = "Fun" set name = "Man Up" @@ -991,7 +934,7 @@ var/global/list/admin_verbs_hideable = list( to_chat(T, "Man up and deal with it.") to_chat(T, "Move on.") - T.playsound_local(null, 'sound/voice/ManUp1.ogg', VOL_ADMIN, vary = FALSE, ignore_environment = TRUE) + T.playsound_local(null, 'sound/voice/ManUp1.ogg', VOL_ADMIN_SOUNDS, vary = FALSE, ignore_environment = TRUE) log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.") message_admins("[key_name_admin(usr)] told [key_name(T)] to man up and deal with it.") @@ -1003,7 +946,7 @@ var/global/list/admin_verbs_hideable = list( for (var/mob/T in player_list) to_chat(T, "
Man up.
Deal with it.

Move on.

") - T.playsound_local(null, 'sound/voice/ManUp1.ogg', VOL_ADMIN, vary = FALSE, ignore_environment = TRUE) + T.playsound_local(null, 'sound/voice/ManUp1.ogg', VOL_ADMIN_SOUNDS, vary = FALSE, ignore_environment = TRUE) log_admin("[key_name(usr)] told everyone to man up and deal with it.") message_admins("[key_name_admin(usr)] told everyone to man up and deal with it.") @@ -1043,10 +986,10 @@ var/global/list/admin_verbs_hideable = list( var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") if(glob == "No!") - winner.playsound_local(null, 'sound/misc/achievement.ogg', VOL_ADMIN, vary = FALSE, ignore_environment = TRUE) + winner.playsound_local(null, 'sound/misc/achievement.ogg', VOL_ADMIN_SOUNDS, vary = FALSE, ignore_environment = TRUE) else for(var/mob/M in player_list) - M.playsound_local(null, 'sound/misc/achievement.ogg', VOL_ADMIN, vary = FALSE, ignore_environment = TRUE) + M.playsound_local(null, 'sound/misc/achievement.ogg', VOL_ADMIN_SOUNDS, vary = FALSE, ignore_environment = TRUE) to_chat(world, "[bicon(cup)] [winner.name] wins \"[name]\"!") to_chat(winner, "Congratulations!") diff --git a/code/modules/admin/secrets/tgui_secrets/custom_announcement.dm b/code/modules/admin/secrets/tgui_secrets/custom_announcement.dm index 625cc5d19524..f2973384a9a7 100644 --- a/code/modules/admin/secrets/tgui_secrets/custom_announcement.dm +++ b/code/modules/admin/secrets/tgui_secrets/custom_announcement.dm @@ -97,7 +97,7 @@ var/global/list/datum/announcement/announcements_list sound_file = pick(sound_file) else WARNING("No sound file for [sound_name]") - U.playsound_local(null, sound_file, VOL_EFFECTS_VOICE_ANNOUNCEMENT, volume, FALSE, channel = CHANNEL_ANNOUNCE, wait = TRUE) + U.playsound_local(null, sound_file, VOL_VOICE_ANNOUNCEMENTS, volume, FALSE, channel = CHANNEL_ANNOUNCE, wait = TRUE) if("preset_select") if(!(C.holder.rights & (R_FUN | R_EVENT))) return diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index 671111e7d69b..124de3627b7a 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -11,7 +11,7 @@ to_chat(src, "You cannot send DSAY messages (muted).") return - if(!(prefs.chat_toggles & CHAT_DEAD)) + if(!prefs.get_pref(/datum/pref/player/chat/dead)) to_chat(src, "You have deadchat muted.") return @@ -35,10 +35,13 @@ if (isnewplayer(M)) continue - if(M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD)) // show the message to admins who have deadchat toggled on + if(!M.client) + continue + + if(M.client.holder && (M.client.prefs.get_pref(/datum/pref/player/chat/dead))) // show the message to admins who have deadchat toggled on to_chat(M, rendered) - else if(M.stat == DEAD && (M.client.prefs.chat_toggles & CHAT_DEAD)) // show the message to regular ghosts who have deadchat toggled on + else if(M.stat == DEAD && M.client.prefs.get_pref(/datum/pref/player/chat/dead)) // show the message to regular ghosts who have deadchat toggled on to_chat(M, rendered) feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index b925c75e0aac..4dcacc8f1602 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -34,7 +34,7 @@ var/global/list/sounds_cache_local = list() message_admins("[key_name_admin(src)] played sound [S].") for(var/mob/M in player_list) - M.playsound_music(S, VOL_ADMIN, null, TRUE, CHANNEL_ADMIN, 250, SOUND_STREAM) + M.playsound_music(S, VOL_ADMIN_SOUNDS, null, TRUE, CHANNEL_ADMIN, 250, SOUND_STREAM) feedback_add_details("admin_verb","PGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -112,7 +112,7 @@ var/global/list/sounds_cache_local = list() message_admins("[key_name_admin(src)] played server sound [sound_path].") for(var/mob/M in player_list) - M.playsound_music(sound_path, VOL_ADMIN, null, TRUE, CHANNEL_ADMIN, 250, 0) + M.playsound_music(sound_path, VOL_ADMIN_SOUNDS, null, TRUE, CHANNEL_ADMIN, 250, 0) feedback_add_details("admin_verb","PSS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index d81a841f697a..c565fbf53f06 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -72,11 +72,11 @@ if(!M.client) continue - if(M.client.holder && (M.client.prefs.chat_toggles & CHAT_PRAYER)) // Show the message to admins with prayer toggled on + if(M.client.holder && M.client.prefs.get_pref(/datum/pref/player/chat/prayers)) // Show the message to admins with prayer toggled on to_chat(M, admin_msg)//Admins can hear deadchat, if they choose to, no matter if they're blind/deaf or not. continue - if(M.stat == DEAD && (M.client.prefs.chat_toggles & CHAT_DEAD)) + if(M.stat == DEAD && M.client.prefs.get_pref(/datum/pref/player/chat/dead)) if(M.fake_death) //Our changeling with fake_death status must not hear dead chat!! continue @@ -86,7 +86,7 @@ for(var/mob/living/simple_animal/shade/god/G as anything in gods_list) - if(G.client && (G.client.prefs.chat_toggles & CHAT_PRAYER)) + if(G.client && G.client.prefs.get_pref(/datum/pref/player/chat/prayers)) if(G == src) // Don't hear your own prayer. continue if(G.say_understands(src, speaking)) @@ -133,7 +133,7 @@ var/list/viewing = list() for(var/mob/M in viewers(src)) - if(M.client && (M.client.prefs.toggles & SHOW_ANIMATIONS)) + if(M.client?.prefs.get_pref(/datum/pref/player/game/melee_animation)) viewing |= M.client flick_overlay(I, viewing, 10) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index b239318357a3..65d3f2b6e6a9 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -771,7 +771,7 @@ Traitors and the like can also be revived with the previous role mostly intact. var/viewy = clamp(input("Enter view height (1-127)") as num, 1, 127) * 2 + 1 change_view("[viewx]x[viewy]") - if(prefs.auto_fit_viewport) + if(prefs.get_pref(/datum/pref/player/display/auto_fit_viewport)) fit_viewport() log_admin("[key_name(usr)] changed their view range to [viewx]x[viewy].") diff --git a/code/modules/client/character_menu/customkeybindings.dm b/code/modules/client/character_menu/customkeybindings.dm deleted file mode 100644 index 5597344ab2f4..000000000000 --- a/code/modules/client/character_menu/customkeybindings.dm +++ /dev/null @@ -1,194 +0,0 @@ -/datum/preferences/proc/ShowCustomKeybindings(mob/user) - if(!key_bindings.len) - . += "Этот текст вы можете видеть только при ошибке со стороны кода.
" - . += "Попробуйте нажать сверху кнопку Reload Slot. Если это не помогло, то подождите рестарт." - . += "Можете так же сообщить о проблеме в гитхаб репозитория." - return - - // Create an inverted list of keybindings -> key - var/list/user_binds = list() - for (var/key in key_bindings) - for(var/kb_name in key_bindings[key]) - user_binds[kb_name] += list(key) - - var/list/kb_categories = list() - // Group keybinds by category - for (var/name in global.keybindings_by_name) - var/datum/keybinding/kb = global.keybindings_by_name[name] - kb_categories[kb.category] += list(kb) - . += "Hotkeys Mode: [hotkeys ? "Focus on Game" : "Focus on Chat"]" - . += "
" - for (var/category in kb_categories) - . += "

[category]

" - . += "" - for (var/i in kb_categories[category]) - var/datum/keybinding/kb = i - if(!length(user_binds[kb.name]) || (user_binds[kb.name][1] == "None" && length(user_binds[kb.name]) == 1)) - . += "" - var/list/default_keys = kb.hotkey_keys - var/class - if(compare_list(user_binds[kb.name], default_keys)) - class = "class='disabled fluid'" - else - class = "class='white fluid' href ='?_src_=prefs;preference=keybinding_reset;keybinding=[kb.name];old_keys=[jointext(user_binds[kb.name], ",")]" - - . += {""} - . += "" - else - var/bound_key = user_binds[kb.name][1] - var/normal_name = _kbMap_reverse[bound_key] ? _kbMap_reverse[bound_key] : bound_key - . += "" - for(var/bound_key_index in 2 to length(user_binds[kb.name])) - bound_key = user_binds[kb.name][bound_key_index] - normal_name = _kbMap_reverse[bound_key] ? _kbMap_reverse[bound_key] : bound_key - . += "" - if(length(user_binds[kb.name]) < MAX_KEYS_PER_KEYBIND) - . += "" - for(var/j in 1 to MAX_KEYS_PER_KEYBIND - (length(user_binds[kb.name]) + 1)) - . += "" - var/list/default_keys = kb.hotkey_keys - . += {""} - . += "" - . += "
[kb.full_name]NoneReset
[kb.full_name][normal_name][normal_name]NoneReset
" - - . += "

" - . += "Reset to default" - . += "
" - -/datum/preferences/proc/CaptureKeybinding(mob/user, datum/keybinding/kb, old_key) - var/HTML = {" -
- Keybinding: [kb.full_name]
[kb.description] -

- Press any key to change
Press ESC to clear
-
- - "} - winshow(user, "capturekeypress", TRUE) - var/datum/browser/popup = new(user, "capturekeypress", "
Keybindings
", 350, 300) - popup.set_content(HTML) - popup.open(FALSE) - -/datum/preferences/proc/toggle_hotkeys_mode() - hotkeys = !hotkeys - if(hotkeys) - winset(usr, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") - else - winset(usr, null, "input.focus=true input.background-color=[COLOR_INPUT_DISABLED]") - save_preferences() - - -/datum/preferences/proc/process_link_custom_keybindings(mob/user, list/href_list) - if(!user) - return - switch(href_list["preference"]) - if("hotkeys") - toggle_hotkeys_mode() - - if("keybindings_capture") - var/datum/keybinding/kb = global.keybindings_by_name[href_list["keybinding"]] - var/old_key = href_list["old_key"] - CaptureKeybinding(user, kb, old_key) - return - - if("keybindings_set") - var/kb_name = href_list["keybinding"] - if(!kb_name) - user << browse(null, "window=capturekeypress") - ShowChoices(user) - return - - var/clear_key = text2num(href_list["clear_key"]) - var/old_key = href_list["old_key"] - if(clear_key) - if(key_bindings[old_key]) - key_bindings[old_key] -= kb_name - if(!(kb_name in key_bindings["None"])) - LAZYADD(key_bindings["None"], kb_name) - if(!length(key_bindings[old_key])) - key_bindings -= old_key - user << browse(null, "window=capturekeypress") - user.client.set_macros() - save_preferences() - ShowChoices(user) - return - - var/new_key = uppertext(href_list["key"]) - var/AltMod = text2num(href_list["alt"]) ? "Alt" : "" - var/CtrlMod = text2num(href_list["ctrl"]) ? "Ctrl" : "" - var/ShiftMod = text2num(href_list["shift"]) ? "Shift" : "" - var/numpad = text2num(href_list["numpad"]) ? "Numpad" : "" - - if(!new_key) // Just in case (; - not work although keyCode 186 and nothing should break) - user << browse(null, "window=capturekeypress") - return - - if(global._kbMap[new_key]) - new_key = global._kbMap[new_key] - - var/full_key - switch(new_key) - if("Alt") - full_key = "[new_key][CtrlMod][ShiftMod]" - if("Ctrl") - full_key = "[AltMod][new_key][ShiftMod]" - if("Shift") - full_key = "[AltMod][CtrlMod][new_key]" - else - full_key = "[AltMod][CtrlMod][ShiftMod][numpad][new_key]" - if(kb_name in key_bindings[full_key]) //We pressed the same key combination that was already bound here, so let's remove to re-add and re-sort. - key_bindings[full_key] -= kb_name - if(key_bindings[old_key]) - key_bindings[old_key] -= kb_name - if(!length(key_bindings[old_key])) - key_bindings -= old_key - key_bindings[full_key] += list(kb_name) - key_bindings[full_key] = sortList(key_bindings[full_key]) - - user << browse(null, "window=capturekeypress") - user.client.set_macros() - save_preferences() - - if("keybindings_reset") - key_bindings = deepCopyList(global.hotkey_keybinding_list_by_key) - user.client.set_macros() - save_preferences() - - if("keybinding_reset") - var/kb_name = href_list["keybinding"] - var/list/old_keys = splittext(href_list["old_keys"], ",") - - for(var/old_key in old_keys) - if(!key_bindings[old_key]) - continue - key_bindings[old_key] -= kb_name - if(!length(key_bindings[old_key])) - key_bindings -= old_key - - var/datum/keybinding/kb = global.keybindings_by_name[kb_name] - for(var/key in kb.hotkey_keys) - key_bindings[key] += list(kb_name) - key_bindings[key] = sortList(key_bindings[key]) - user.client.set_macros() - save_preferences() diff --git a/code/modules/client/character_menu/emote_panel_editor.dm b/code/modules/client/character_menu/emote_panel_editor.dm index 613e45f04133..37fc194f623f 100644 --- a/code/modules/client/character_menu/emote_panel_editor.dm +++ b/code/modules/client/character_menu/emote_panel_editor.dm @@ -2,12 +2,12 @@ var/datum/emote_panel_editor /datum/emote_panel_editor - var/list/custom_emote_panel + var/list/enabled_emotes var/datum/preferences/prefs /datum/emote_panel_editor/New(client/user) src.prefs = user.prefs - src.custom_emote_panel = prefs.custom_emote_panel + src.enabled_emotes = prefs.enabled_emotes_emote_panel /datum/emote_panel_editor/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -27,12 +27,13 @@ if(!(emote in global.emotes_for_emote_panel)) return - if(emote in custom_emote_panel) - custom_emote_panel -= emote + if(emote in enabled_emotes) + enabled_emotes -= emote else - custom_emote_panel += emote + enabled_emotes += emote - prefs.save_preferences() + var/list/disabled_emotes = global.emotes_for_emote_panel - enabled_emotes + prefs.set_pref(/datum/pref/player/meta/disabled_emotes_emote_panel, disabled_emotes) return TRUE @@ -42,7 +43,7 @@ /datum/emote_panel_editor/tgui_data(mob/user) var/list/data = list() - data["customEmotes"] = custom_emote_panel + data["customEmotes"] = enabled_emotes data["allHumanEmotes"] = global.emotes_for_emote_panel return data diff --git a/code/modules/client/character_menu/general.dm b/code/modules/client/character_menu/general.dm index fe457852f4e4..cd7390cd346c 100644 --- a/code/modules/client/character_menu/general.dm +++ b/code/modules/client/character_menu/general.dm @@ -18,7 +18,7 @@ if(species == IPC) // only ipc can change their voice at this moment . += "
Voice: [neuter_gender_voice == MALE ? "Male" : "Female"]" . += "
Height: [height]" - . += "
Randomized Character Slot: [randomslot ? "Yes" : "No"]" + . += "
Randomized Character Slot: [get_pref(/datum/pref/player/meta/random_slot) ? "Yes" : "No"]" . += "
" . += "" . += "" @@ -617,7 +617,8 @@ neuter_gender_voice = neuter_gender_voice == MALE ? FEMALE : MALE if("randomslot") - randomslot = !randomslot + var/random_slot = get_pref(/datum/pref/player/meta/random_slot) + set_pref(/datum/pref/player/meta/random_slot, !random_slot) if("name") be_random_name = !be_random_name diff --git a/code/modules/client/character_menu/global.dm b/code/modules/client/character_menu/global.dm deleted file mode 100644 index bd05ffe4a670..000000000000 --- a/code/modules/client/character_menu/global.dm +++ /dev/null @@ -1,221 +0,0 @@ -/datum/preferences/proc/ShowGlobal(mob/user) - . = "" - . += "" - . += "" - . += "" - . += "" - . += "
" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - //if(user.client) TG - // if(user.client.holder) - // . += "Announce Login:[(toggles & ANNOUNCE_LOGIN)?"On":"Off"]
" - - // if(unlock_content || check_rights_for(user.client, R_ADMIN)) - // . += "OOC:   Change
" - - // if(unlock_content) - // . += "BYOND Membership Publicity:[(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" - // . += "Ghost Form:[ghost_form]
" - . += "
UI Style: [UI_style]
Custom UI(recommended for White UI):
Change color
Alpha(transparency): [UI_style_alpha]
Reset custom UI
TGUI Window Mode: [tgui_fancy ? "Fancy (default)" : "Compatible (slower)"]
TGUI Window Placement: [tgui_lock ? "Primary Monitor" : "Free (default)"]
Outline: [outline_enabled ? "Enabled" : "Disabled"]
" - . += "
Outline Color:     Change
" - . += "
FPS: [clientfps]

OOC Notes: [length(metadata)>0?"[copytext_char(metadata, 1, 3)]...":"\[...\]"]
" - . += "
" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "" - . += "
Preferences:
Ghost ears:[(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
Ghost hear NPCs:[(chat_toggles & CHAT_GHOSTNPC) ? "All Speech" : "Nearest Creatures"]
Ghost sight:[(chat_ghostsight == CHAT_GHOSTSIGHT_ALL) ? "All Emotes" : ((chat_ghostsight == CHAT_GHOSTSIGHT_ALLMANUAL) ? "All manual-only emotes" : "Nearest Creatures")]
Ghost radio:[(chat_toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]
OOC:[(chat_toggles & CHAT_OOC) ? "Shown" : "Hidden"]
LOOC:[(chat_toggles & CHAT_LOOC) ? "Shown" : "Hidden"]
Parallax (Fancy Space)" - switch (parallax) - if (PARALLAX_LOW) - . += "Low" - if (PARALLAX_MED) - . += "Medium" - if (PARALLAX_INSANE) - . += "Insane" - if (PARALLAX_DISABLE) - . += "Disabled" - else - . += "High" - . += "
Lobby Animation:[lobbyanimation ? "Enabled" : "Disabled"]
Ambient Occlusion:[ambientocclusion ? "Enabled" : "Disabled"]
Fit Viewport:[auto_fit_viewport ? "Auto" : "Manual"]
Melee Animations:[(toggles & SHOW_ANIMATIONS) ? "Yes" : "No"]
Progress Bar:[(toggles & SHOW_PROGBAR) ? "Yes" : "No"]
Name of Items:[tooltip ? "Hide" : "Show"]
Change Font of Names of Items:Change
Change Names Size:[tooltip_size]
" - . += "
" - -/datum/preferences/proc/process_link_glob(mob/user, list/href_list) - switch(href_list["task"]) - if("input") - if(href_list["preference"] == "metadata") - var/new_metadata = sanitize(input(user, "Enter any OOC information you'd like others to see:", "Game Preference", input_default(metadata)) as message|null) - if(new_metadata) - metadata = new_metadata - - if("reset") - UI_style_color = initial(UI_style_color) - UI_style_alpha = initial(UI_style_alpha) - - switch(href_list["preference"]) - - if("UIcolor") - var/UI_style_color_new = input(user, "Choose your UI color, dark colors are not recommended!") as color|null - if(!UI_style_color_new) return - UI_style_color = UI_style_color_new - - if("UIalpha") - var/UI_style_alpha_new = input(user, "Select a new alpha(transparence) parametr for UI, between 50 and 255") as num|null - if(!UI_style_alpha_new || !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return - UI_style_alpha = UI_style_alpha_new - - if("ui") - var/pickedui = input(user, "Choose your UI style.", "Character Preference", UI_style) as null|anything in sortList(global.available_ui_styles) - if(pickedui) - UI_style = pickedui - - if("tgui_fancy") - tgui_fancy = !tgui_fancy - - if("tgui_lock") - tgui_lock = !tgui_lock - - if("tooltip_show") - parent?.toggle_tooltip() - - if("change_size_tooltip") - parent?.change_size_tooltip() - - if("change_font_tooltip") - parent?.change_font_tooltip() - - if("outline_enabled") - outline_enabled = !outline_enabled - - if("outline_color") - var/pickedOutlineColor = input(user, "Choose your outline color.", "General Preference", outline_color) as color|null - if(pickedOutlineColor) - outline_color = pickedOutlineColor - - if("change_fps") - var/desiredfps = input(user, "Choose your desired fps.\n-1 means recommended value (currently:[RECOMMENDED_FPS])\n0 means world fps (currently:[world.fps])", "Character Preference", clientfps) as null|num - if (!isnull(desiredfps)) - clientfps = sanitize_integer(desiredfps, -1, 1000, clientfps) - parent.fps = (clientfps < 0) ? RECOMMENDED_FPS : clientfps - - if("parallaxup") - parallax = WRAP(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) - if (parent && parent.mob && parent.mob.hud_used) - parent.mob.hud_used.update_parallax_pref() - - if("parallaxdown") - parallax = WRAP(parallax - 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) - if (parent && parent.mob && parent.mob.hud_used) - parent.mob.hud_used.update_parallax_pref() - - if("ambientocclusion") - ambientocclusion = !ambientocclusion - if(parent && parent.screen && parent.screen.len) - parent.update_plane_masters(/atom/movable/screen/plane_master/game_world) - - if("lobbyanimation") - lobbyanimation = !lobbyanimation // shouldn't prefs changes be saved somewhere here? - if(isnewplayer(user)) - var/mob/dead/new_player/M = user - M.show_titlescreen() - - if("auto_fit_viewport") - auto_fit_viewport = !auto_fit_viewport - if(auto_fit_viewport && parent) - parent.fit_viewport() - - if("ghost_sight") - switch(chat_ghostsight) - if(CHAT_GHOSTSIGHT_ALL) - chat_ghostsight = CHAT_GHOSTSIGHT_ALLMANUAL - if(CHAT_GHOSTSIGHT_ALLMANUAL) - chat_ghostsight = CHAT_GHOSTSIGHT_NEARBYMOBS - if(CHAT_GHOSTSIGHT_NEARBYMOBS) - chat_ghostsight = CHAT_GHOSTSIGHT_ALL - - if("ghost_ears") - chat_toggles ^= CHAT_GHOSTEARS - - if("npc_ghost_ears") - chat_toggles ^= CHAT_GHOSTNPC - - if("ghost_radio") - chat_toggles ^= CHAT_GHOSTRADIO - - if("see_ooc") - chat_toggles ^= CHAT_OOC - - if("see_looc") - chat_toggles ^= CHAT_LOOC - - if("see_animations") - toggles ^= SHOW_ANIMATIONS - - if("see_progbar") - toggles ^= SHOW_PROGBAR diff --git a/code/modules/client/character_menu/load_slot.dm b/code/modules/client/character_menu/load_slot.dm index f477b7fd9c38..61f47795bc14 100644 --- a/code/modules/client/character_menu/load_slot.dm +++ b/code/modules/client/character_menu/load_slot.dm @@ -9,7 +9,7 @@ S["real_name"] >> name if(!name) name = "Character [i]" - if(i==default_slot) + if(i==get_pref(/datum/pref/player/meta/default_slot)) name = "[name]" . += "[name]
" . += "" diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 6b470e732a73..5fd5cb993be1 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -27,7 +27,7 @@ var/area = null var/mentorhelped = FALSE var/supporter = 0 - var/prefs_ready = FALSE + var/prefs_ready = FALSE // drop it to datum /////////////// //SOUND STUFF// @@ -109,8 +109,6 @@ // Last world.time that the player tried to request their resources. var/last_ui_resource_send = 0 - var/fullscreen = NONE - /// Messages currently seen by this client var/list/seen_messages diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 5614b68d3049..8f526c8be9b0 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -106,12 +106,7 @@ var/global/list/blacklisted_builds = list( asset_cache_preload_data(href_list["asset_cache_preload_data"]) return - //byond bug ID:2694120 - if(href_list["reset_macros"]) - reset_macros(skip_alert = TRUE) - return - - // Keypress passthrough + // Keypress passthrough for some non-tgui interfaces (we should remove it in the future) if(href_list["__keydown"]) var/keycode = browser_keycode_to_byond(href_list["__keydown"]) if(keycode) @@ -147,7 +142,6 @@ var/global/list/blacklisted_builds = list( if("usr") hsrc = mob if("prefs") return prefs.process_link(usr,href_list) if("vars") return view_var_Topic(href,href_list,hsrc) - if("updateVolume") return update_volume(href_list) switch(href_list["action"]) if ("openLink") @@ -247,16 +241,16 @@ var/global/list/blacklisted_builds = list( update_supporter_status() //preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum) - if(preferences_datums[ckey]) - prefs = preferences_datums[ckey] + if(global.preferences_datums[ckey]) + prefs = global.preferences_datums[ckey] prefs.reattach_to_client(src) else prefs = new /datum/preferences(src) - preferences_datums[ckey] = prefs + global.preferences_datums[ckey] = prefs prefs.last_ip = address //these are gonna be used for banning prefs.last_id = computer_id //these are gonna be used for banning - fps = (prefs.clientfps < 0) ? RECOMMENDED_FPS : prefs.clientfps + fps = prefs.get_pref(/datum/pref/player/display/fps) prefs.save_preferences() @@ -307,11 +301,11 @@ var/global/list/blacklisted_builds = list( // Set config based title for main window if (config.server_name) - winset(src, "mainwindow", "title='[world.name]: [config.server_name]'") + winset(src, "tcmainwindow", "title='[world.name]: [config.server_name]'") else - winset(src, "mainwindow", "title='[world.name]'") + winset(src, "tcmainwindow", "title='[world.name]'") - if(prefs.lastchangelog != changelog_hash) // Bolds the changelog button on the interface so we know there are updates. + if(prefs.get_pref(/datum/pref/player/meta/lastchangelog) != changelog_hash) // Bolds the changelog button on the interface so we know there are updates. to_chat(src, "You have unread updates in the changelog.") winset(src, "rpane.changelog", "font-style=bold") @@ -319,8 +313,9 @@ var/global/list/blacklisted_builds = list( if(!tooltips) tooltips = new /datum/tooltip(src) - if(prefs.auto_fit_viewport) - fit_viewport() + // client screen options + update_fullscreen() // we need it? + update_map_zoom() if(!cob) cob = new() @@ -686,7 +681,7 @@ var/global/list/blacklisted_builds = list( var/list/modifiers = params2list(params) if(modifiers[DRAG]) return - if (prefs.hotkeys) + if (prefs.get_pref(/datum/pref/player/game/hotkey_mode)) winset(src, null, "input.background-color=[COLOR_INPUT_DISABLED]") else winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") @@ -783,51 +778,31 @@ var/global/list/blacklisted_builds = list( * Arguments: * * direct_prefs - the preference we're going to get keybinds from */ -/client/proc/update_special_keybinds(datum/preferences/direct_prefs) +/client/proc/update_movement_keybinds(datum/preferences/direct_prefs) var/datum/preferences/D = prefs || direct_prefs - if(!D?.key_bindings) + if(!D?.prefs_keybinds) return movement_keys = list() - for(var/key in D.key_bindings) - for(var/kb_name in D.key_bindings[key]) - switch(kb_name) - if("North") - movement_keys[key] = NORTH - if("East") - movement_keys[key] = EAST - if("West") - movement_keys[key] = WEST - if("South") - movement_keys[key] = SOUTH - -#define MAXIMAZED (1<<0) -#define FULLSCREEN (1<<1) - -/client/verb/toggle_fullscreen() - set name = "Toggle Fullscreen" - set category = "OOC" - - fullscreen ^= FULLSCREEN - - if(fullscreen & FULLSCREEN) - if(winget(usr, "mainwindow", "is-maximized") == "true") - fullscreen |= MAXIMAZED - else - fullscreen &= ~MAXIMAZED - winset(usr, "mainwindow", "titlebar=false") - winset(usr, "mainwindow", "can-resize=false") - winset(usr, "mainwindow", "is-maximized=false") - winset(usr, "mainwindow", "is-maximized=true") - winset(usr, "mainwindow", "menu=") - else - if(!(fullscreen & MAXIMAZED)) - winset(usr, "mainwindow", "is-maximized=false") - winset(usr, "mainwindow", "titlebar=true") - winset(usr, "mainwindow", "can-resize=true") - winset(usr, "mainwindow", "menu=menu") -#undef MAXIMAZED -#undef FULLSCREEN + var/datum/pref/keybinds/P = D.prefs_keybinds[/datum/pref/keybinds/movement/north] + for(var/key in splittext(P.value, " ")) + if(length(key)) + movement_keys[key] = NORTH + + P = D.prefs_keybinds[/datum/pref/keybinds/movement/east] + for(var/key in splittext(P.value, " ")) + if(length(key)) + movement_keys[key] = EAST + + P = D.prefs_keybinds[/datum/pref/keybinds/movement/west] + for(var/key in splittext(P.value, " ")) + if(length(key)) + movement_keys[key] = WEST + + P = D.prefs_keybinds[/datum/pref/keybinds/movement/south] + for(var/key in splittext(P.value, " ")) + if(length(key)) + movement_keys[key] = SOUTH // ckey = datum/stat/leave_stat var/global/list/disconnected_ckey_by_stat = list() @@ -847,13 +822,6 @@ var/global/list/disconnected_ckey_by_stat = list() global.disconnected_ckey_by_stat[ckey] = stat -/client/proc/change_view(new_size) - if (isnull(new_size)) - CRASH("change_view called without argument.") - - view = new_size - mob.reload_fullscreen() - /client/proc/open_filter_editor(atom/in_atom) if(holder) holder.filteriffic = new /datum/filter_editor(in_atom) diff --git a/code/modules/client/client_settings_menu.dm b/code/modules/client/client_settings_menu.dm new file mode 100644 index 000000000000..a939e245d04e --- /dev/null +++ b/code/modules/client/client_settings_menu.dm @@ -0,0 +1,169 @@ +/client + var/datum/client_settings/settings + +/client/verb/client_settings() + set name = "Settings" + set category = "OOC" + + open_settings_menu() + +/client/proc/open_settings_menu(tab) + if(!prefs_ready) + to_chat(usr, "Need more time for initialization!") + return + + if(!settings) + settings = new /datum/client_settings(src) + settings.tgui_interact(usr, tab) + +/datum/client_settings + var/active_tab = PREF_PLAYER_DISPLAY + +/datum/client_settings/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ClientSettings", "Client Settings") + ui.set_autoupdate(FALSE) + ui.open() + +/datum/client_settings/tgui_data(mob/user, tab) + if(tab) + active_tab = tab + var/list/data = list("active_tab" = active_tab, "settings" = list()) + + var/client/C = user.client + + // todo: more static data can be moved to tgui_static + switch(active_tab) + if("keybinds") + var/datum/pref/keybinds/P + for(var/type in user.client.prefs.prefs_keybinds) + P = user.client.prefs.prefs_keybinds[type] + + if(P.admins_only && !C.holder) + continue + if(P.supporters_only && !C.supporter) + continue + + data["settings"] += list(list( + "type" = "[P.type]", + "name" = P.name, + "category" = P.category, + "description" = P.description, + "value" = P.value, + "v_type" = P.value_type, + "v_parameters" = P.value_parameters, + "default" = P.value == initial(P.value), + "admins_only" = P.admins_only, + "supporters_only" = P.supporters_only, + )) + else + var/datum/pref/player/P + for(var/type in user.client.prefs.prefs_player) + P = user.client.prefs.prefs_player[type] + if(P.category != active_tab) + continue + + if(P.admins_only && !C.holder) + continue + if(P.supporters_only && !C.supporter) + continue + + data["settings"] += list(list( + "type" = "[P.type]", + "name" = P.name, + "description" = P.description, + "value" = P.value, + "v_type" = P.value_type, + "v_parameters" = P.value_parameters, + "default" = P.value == initial(P.value), + "admins_only" = P.admins_only, + "supporters_only" = P.supporters_only, + )) + + return data + +/datum/client_settings/tgui_static_data(mob/user) + var/static/tabs = list( + PREF_PLAYER_DISPLAY = "Экран", + PREF_PLAYER_EFFECTS = "Эффекты", + PREF_PLAYER_AUDIO = "Аудио", + PREF_PLAYER_UI = "Интерфейс", + PREF_PLAYER_CHAT = "Чат", + PREF_PLAYER_GAME = "Игра", + PREF_DOMAIN_KEYBINDS = "Управление", + ) + + var/static/pref_keybinds_ordered = list( + PREF_KEYBINDS_CLIENT, + PREF_KEYBINDS_COMMUNICATION, + PREF_KEYBINDS_MOVEMENT, + PREF_KEYBINDS_CARBON, + PREF_KEYBINDS_HUMAN, + PREF_KEYBINDS_ROBOT, + PREF_KEYBINDS_EMOTE, + PREF_KEYBINDS_MISC, + ) + + var/static/tabs_tips = list( + PREF_PLAYER_EFFECTS = "Рекомендуется изменять настройки во время игры - так вы сможете сразу увидеть результат.", + "keybinds" = "Некоторые клавиши или сочетания могут быть не доступны для назначения, проблема будет решена с Byond 516.", + ) + + var/list/data = list() + data["tabs"] = tabs + data["tabs_tips"] = tabs_tips + data["keybinds_order"] = pref_keybinds_ordered + return data + +/datum/client_settings/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + if(.) + return + + var/client/C = ui.user.client + + if(action == "set_tab") + active_tab = params["tab"] + return TRUE + + var/datum/pref/pref_type = text2path(params["type"]) + if(!pref_type) + return FALSE + + // first validate that we have permissions to change this pref + if(initial(pref_type.admins_only) && !C.holder) + return FALSE + if(initial(pref_type.supporters_only) && !C.supporter) + return FALSE + + if(ispath(pref_type, /datum/pref/player)) + if(ispath(pref_type, /datum/pref/player/meta)) + return + + switch(action) + if("set_value") + C.prefs.set_pref(pref_type, params["value"]) + if("modify_color_value") + var/current_color = C.prefs.get_pref(pref_type) + var/new_color = input(C, "Выберите новый цвет", "Выбор цвета", current_color) as color|null + if(!new_color) + return FALSE + else + C.prefs.set_pref(pref_type, new_color) + if("reset_value") + C.prefs.set_pref(pref_type, initial(pref_type.value)) + + else if(ispath(pref_type, /datum/pref/keybinds)) + switch(action) + if("set_value") + C.prefs.set_keybind_pref(pref_type, params["value"]) + if("set_keybind_value") + C.prefs.set_keybind_pref(pref_type, params["key"], params["index"], params["altMod"], params["ctrlMod"], params["shiftMod"]) + if("reset_value") + C.prefs.set_keybind_pref(pref_type, initial(pref_type.value)) + + return TRUE + +/datum/client_settings/tgui_state(mob/user) + return global.always_state diff --git a/code/modules/client/client_view.dm b/code/modules/client/client_view.dm new file mode 100644 index 000000000000..68cd52ec2744 --- /dev/null +++ b/code/modules/client/client_view.dm @@ -0,0 +1,111 @@ +// see also: /datum/component/zoom + +// fetches prefs and reloads client zoom settings +// note: this has nothing to do with zoom component, zoom component works with change_view +/client/proc/update_map_zoom() + var/autozoom = prefs.get_pref(/datum/pref/player/display/auto_zoom) + var/zoom = autozoom ? 0 : prefs.get_pref(/datum/pref/player/display/zoom) * 0.01 + var/zoom_mode = prefs.get_pref(/datum/pref/player/display/zoom_mode) + winset(src, "tcmapwindow.map", "zoom=[zoom];zoom-mode=[zoom_mode]") + +// changes tiles count client can see +/client/proc/change_view(new_size) + if (isnull(new_size)) + CRASH("change_view called without argument.") + + view = new_size + mob.reload_fullscreen() + +/client/verb/toggle_fullscreen() + set name = "Toggle Fullscreen" + set category = "OOC" + + var/fullscreen = prefs.get_pref(/datum/pref/player/display/fullscreen) + prefs.set_pref(/datum/pref/player/display/fullscreen, !fullscreen) + + update_fullscreen() + +/client/proc/update_fullscreen() + set name = "Toggle Fullscreen" + set category = "OOC" + + if(prefs.get_pref(/datum/pref/player/display/fullscreen)) + winset(src, "tcmainwindow", "menu=") + winset(src, "tcmainwindow", "is-fullscreen=true") + else + winset(src, "tcmainwindow", "menu=menu") + winset(src, "tcmainwindow", "is-fullscreen=false") + +// basically, resizes right column so that map windows don't have black bars +/client/verb/fit_viewport() + set name = "Fit viewport" + set category = "OOC" + set desc = "Fit the width of the map window to match the viewport" + + if(isnewplayer(mob)) // no tcmapwindow in lobby + to_chat(usr, "You can't fix viewport while in lobby.") + return + + // Fetch aspect ratio + var/view_size = getviewsize(view) + var/aspect_ratio = view_size[1] / view_size[2] + + // Calculate desired pixel width using window size and aspect ratio + var/list/sizes = params2list(winget(src, "tcmainwindow.split;tcmapwindow", "size")) + + // Client closed the window? Some other error? This is unexpected behaviour, let's + // CRASH with some info. + if(!sizes["tcmapwindow.size"]) + CRASH("sizes does not contain tcmapwindow.size key. This means a winget failed to return what we wanted. --- sizes var: [sizes] --- sizes length: [length(sizes)]") + + var/list/map_size = splittext(sizes["tcmapwindow.size"], "x") + + // Looks like we expect tcmapwindow.size to be "ixj" where i and j are numbers. + // If we don't get our expected 2 outputs, let's give some useful error info. + if(length(map_size) != 2) + CRASH("map_size of incorrect length --- map_size var: [map_size] --- map_size length: [length(map_size)]") + + var/height = text2num(map_size[2]) + var/desired_width = round(height * aspect_ratio) + if (text2num(map_size[1]) == desired_width) + // Nothing to do + return + + var/split_size = splittext(sizes["tcmainwindow.split.size"], "x") + var/split_width = text2num(split_size[1]) + + // Avoid auto-resizing the statpanel and chat into nothing. + desired_width = min(desired_width, split_width - 300) + + // Calculate and apply a best estimate + // +4 pixels are for the width of the splitter's handle + var/pct = 100 * (desired_width + 4) / split_width + winset(src, "tcmainwindow.split", "splitter=[pct]") + + // Apply an ever-lowering offset until we finish or fail + var/delta + for(var/safety in 1 to 10) + var/after_size = winget(src, "tcmapwindow", "size") + map_size = splittext(after_size, "x") + var/got_width = text2num(map_size[1]) + + if (got_width == desired_width) + // success + return + else if (isnull(delta)) + // calculate a probable delta value based on the difference + delta = 100 * (desired_width - got_width) / split_width + else if ((delta > 0 && got_width > desired_width) || (delta < 0 && got_width < desired_width)) + // if we overshot, halve the delta and reverse direction + delta = -delta/2 + + pct += delta + winset(src, "tcmainwindow.split", "splitter=[pct]") + +// called automatically from skin on any columns resize, +/client/verb/handle_autofit() + set name = ".handleautofit" + set hidden = TRUE + + if(prefs.get_pref(/datum/pref/player/display/auto_fit_viewport) && !isnewplayer(mob)) + fit_viewport() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index da3ada93aecb..091322f3e41e 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1,3 +1,4 @@ +// list contains all clients /datum/preferences so we can keep them persistent in case of client disconnects var/global/list/datum/preferences/preferences_datums = list() #define MAX_SAVE_SLOTS 10 @@ -12,9 +13,14 @@ var/global/list/datum/preferences/preferences_datums = list() // todo: after moving preferences to new datumized system we should rename this to something like client_data /datum/preferences var/client/parent + + // list of new datumized preferences + var/list/datum/pref/prefs_player = list() + var/list/datum/pref/prefs_keybinds = list() + var/prefs_dirty = FALSE // list of dirty DOMAINS!! + //doohickeys for savefiles var/path - var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used var/savefile_version = 0 //non-preference stuff @@ -32,51 +38,10 @@ var/global/list/datum/preferences/preferences_datums = list() var/admin_cid_request_cache var/admin_ip_request_cache - //game-preferences - var/UI_style = null - var/UI_style_color = "#ffffff" - var/UI_style_alpha = 255 - var/aooccolor = "#b82e00" - var/ooccolor = "#002eb8" - var/toggles = TOGGLES_DEFAULT - var/chat_toggles = TOGGLES_DEFAULT_CHAT - var/chat_ghostsight = CHAT_GHOSTSIGHT_ALL - var/lastchangelog = "" //Saved changlog filesize to detect if there was a change - var/clientfps = -1 - - // Custom Keybindings - var/list/key_bindings = list() - // If hotkey mode is enabled, then clicking the map will automatically - // unfocus the text bar. This removes the red color from the text bar - // so that the visual focus indicator matches reality. - var/hotkeys = TRUE - - var/tooltip = TRUE - var/tooltip_font = "Small Fonts" - var/tooltip_size = 8 - - var/outline_enabled = TRUE - var/outline_color = COLOR_BLUE_LIGHT - var/eorg_enabled = TRUE - - var/show_runechat = TRUE - - var/list/custom_emote_panel = list() - - //TGUI - var/tgui_fancy = TRUE - var/tgui_lock = FALSE - - //sound volume preferences - var/snd_music_vol = 100 - var/snd_ambient_vol = 100 - var/snd_effects_master_vol = 100 - var/snd_effects_voice_announcement_vol = 100 - var/snd_effects_misc_vol = 100 - var/snd_effects_instrument_vol = 100 - var/snd_notifications_vol = 100 - var/snd_admin_vol = 100 - var/snd_jukebox_vol = 100 + /// Cached list of keybindings, keys mapped to /datum/pref/keybinds + var/list/key_bindings_by_key = list() + + var/list/enabled_emotes_emote_panel //antag preferences var/list/be_role = list() @@ -160,25 +125,8 @@ var/global/list/datum/preferences/preferences_datums = list() var/list/allowed_quirks = list() - // OOC Metadata: - var/metadata = "" var/slot_name = "" - // Whether or not to use randomized character slots - var/randomslot = 0 - // jukebox volume - var/volume = 100 - var/parallax = PARALLAX_HIGH - var/ambientocclusion = TRUE - var/auto_fit_viewport = TRUE - var/lobbyanimation = FALSE - // lighting settings - var/glowlevel = GLOW_MED // or bloom - var/lampsexposure = TRUE // idk how we should name it - var/lampsglare = FALSE // aka lens flare - //Impacts performance clientside - var/eye_blur_effect = TRUE - //custom loadout var/list/gear = list() var/gear_tab = "General" @@ -196,18 +144,43 @@ var/global/list/datum/preferences/preferences_datums = list() if(!parent.holder) init_chat_bans() - UI_style = global.available_ui_styles[1] - custom_emote_panel = global.emotes_for_emote_panel + // todo: rewrite this part + for(var/datum/pref/player/P as anything in subtypesof(/datum/pref/player)) + if(initial(P.name)) + prefs_player[initial(P.type)] = new P + for(var/datum/pref/keybinds/P as anything in subtypesof(/datum/pref/keybinds)) + if(initial(P.name)) + prefs_keybinds[initial(P.type)] = new P + + var/character_loaded = FALSE + if(istype(C)) if(!IsGuestKey(C.key)) load_path(C.ckey) if(load_preferences()) - if(load_character()) - return - gender = pick(MALE, FEMALE) - real_name = random_name(gender) - key_bindings = deepCopyList(global.hotkey_keybinding_list_by_key) // give them default keybinds too - C?.set_macros() + character_loaded = load_character() + + // part below is init of default parameters + // in case if we can't load it from saves + if(!character_loaded) + gender = pick(MALE, FEMALE) + real_name = random_name(gender) + + init_keybinds(C) // todo: update it in load + init_emote_panel(C) + +/datum/preferences/proc/init_emote_panel(client/client) + var/list/disabled_emotes = params2list(get_pref(/datum/pref/player/meta/disabled_emotes_emote_panel)) + enabled_emotes_emote_panel = global.emotes_for_emote_panel - disabled_emotes + +/datum/preferences/proc/init_keybinds(client/client) + for(var/type in prefs_keybinds) + var/datum/pref/keybinds/KB = prefs_keybinds[type] + if(KB.value_type != PREF_TYPE_KEYBIND) + continue + var/list/keybinds = splittext(KB.value, " ") + for(var/key in keybinds) + key_bindings_by_key[key] += list(KB) // reattach existing datum to client if client was disconnected and connects again /datum/preferences/proc/reattach_to_client(client/client) @@ -227,12 +200,45 @@ var/global/list/datum/preferences/preferences_datums = list() return muted = MUTE_NONE while(query.NextRow()) - world.log << "NR [query.item[1]] : [mute_ban_bitfield[query.item[1]]]" muted |= mute_ban_bitfield[query.item[1]] +// replaced with macro for speed +///datum/preferences/proc/get_pref(type) +// return prefs_player[type].value + +/datum/preferences/proc/set_pref(type, new_value) + var/datum/pref/player/write_pref = prefs_player[type] + + if(write_pref.update_value(new_value, parent)) + mark_dirty() + +/datum/preferences/proc/set_keybind_pref(type, new_value, index, altMod, ctrlMod, shiftMod) + var/datum/pref/keybinds/write_pref = prefs_keybinds[type] + + if(index) + var/sanitized_key = write_pref.satinize_key(new_value, altMod, ctrlMod, shiftMod) + new_value = "" + var/list/keybinds = splittext(write_pref.value, " ") + for(var/i in 1 to KEYBINDS_MAXIMUM) + if(i == index) + new_value += sanitized_key + else if(i <= keybinds.len) + new_value += keybinds[i] + new_value += " " + + if(write_pref.update_value(new_value, parent)) + mark_dirty() + +// mark as needed to update +/datum/preferences/proc/mark_dirty() + prefs_dirty = TRUE + //SSpreferences.mark_dirty(src) + /datum/preferences/proc/ShowChoices(mob/user) if(!user || !user.client) return - update_preview_icon() + + // generates and updates preview icon, with tgui update should be replaced for map_view element + parent.show_character_previews(generate_preview_icon()) var/dat = "" dat += "
" @@ -253,11 +259,9 @@ var/global/list/datum/preferences/preferences_datums = list() dat += "[menu_type=="general"?"General":"General"] - " dat += "[menu_type=="occupation"?"Occupation":"Occupation"] - " dat += "[menu_type=="roles"?"Roles":"Roles"] - " - dat += "[menu_type=="glob"?"Global":"Global"] - " dat += "[menu_type=="loadout"?"Loadout":"Loadout"] - " dat += "[menu_type=="quirks"?"Quirks":"Quirks"] - " dat += "[menu_type=="fluff"?"Fluff":"Fluff"] - " - dat += "[menu_type=="custom_keybindings"?"Custom Keybindings":"Custom Keybindings"]" dat += "
Close" dat += "" else @@ -271,8 +275,6 @@ var/global/list/datum/preferences/preferences_datums = list() dat += ShowOccupation(user) if("roles") dat += ShowRoles(user) - if("glob") - dat += ShowGlobal(user) if("load_slot") dat += ShowLoadSlot(user) if("loadout") @@ -281,8 +283,6 @@ var/global/list/datum/preferences/preferences_datums = list() dat += ShowQuirks(user) if("fluff") dat += ShowFluffMenu(user) - if("custom_keybindings") - dat += ShowCustomKeybindings(user) dat += "" winshow(user, "preferences_window", TRUE) @@ -312,7 +312,13 @@ var/global/list/datum/preferences/preferences_datums = list() load_character() if("changeslot") - load_character(text2num(href_list["num"])) + var/slot = text2num(href_list["num"]) + + if(isnum(slot) && slot >= 1 && slot <= GET_MAX_SAVE_SLOTS(parent)) + set_pref(/datum/pref/player/meta/default_slot, slot) + load_character() + else + to_chat(user, "You have no access to this slot, please contact maintainers.") if("general") menu_type = "general" @@ -335,9 +341,6 @@ var/global/list/datum/preferences/preferences_datums = list() if("fluff") menu_type = "fluff" - if("custom_keybindings") - menu_type = "custom_keybindings" - if("load_slot") if(!IsGuestKey(user.key)) menu_type = "load_slot" @@ -356,9 +359,6 @@ var/global/list/datum/preferences/preferences_datums = list() if("roles") process_link_roles(user, href_list) - if("glob") - process_link_glob(user, href_list) - if("loadout") process_link_loadout(user, href_list) @@ -369,9 +369,6 @@ var/global/list/datum/preferences/preferences_datums = list() process_link_fluff(user, href_list) return 1 - if("custom_keybindings") - process_link_custom_keybindings(user, href_list) - ShowChoices(user) return 1 @@ -395,7 +392,6 @@ var/global/list/datum/preferences/preferences_datums = list() character.set_species(species) character.flavor_text = flavor_text - character.metadata = metadata character.med_record = med_record character.sec_record = sec_record character.gen_record = gen_record diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 451201be5e9e..1c0c4debe425 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -1,3 +1,5 @@ +var/global/list/legacy_keyname_to_pref = list() + //This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped. #define SAVEFILE_VERSION_MIN 8 @@ -44,36 +46,149 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car return SAVEFILE_UP_TO_DATE -/datum/preferences/proc/update_preferences(current_version, savefile/S) - /* JUST AN EXAMPLE for future updates. - if(current_version < 10) - toggles |= MEMBER_PUBLIC - */ - if(current_version < 15) - S["warns"] << null - S["warnbans"] << null - - if(current_version < 16) - S["aooccolor"] << S["ooccolor"] - aooccolor = ooccolor - - if(current_version < 25) - var/const/SOUND_ADMINHELP = 1 - var/const/SOUND_MIDI = 2 - var/const/SOUND_AMBIENCE = 4 - var/const/SOUND_LOBBY = 8 - var/const/SOUND_STREAMING = 64 - - toggles &= ~(SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|SOUND_STREAMING) - S["toggles"] << toggles - if(current_version < 26) - for(var/role in be_role) - if(!CanBeRole(role)) - be_role -= role - - if(current_version < 44) - custom_emote_panel = global.emotes_for_emote_panel +/datum/preferences/proc/convert_preferences(savefile/S) + // audio + set_pref(/datum/pref/player/audio/lobby, S["snd_music_vol"]) + set_pref(/datum/pref/player/audio/ambient, S["snd_ambient_vol"]) + set_pref(/datum/pref/player/audio/notifications, S["snd_notifications_vol"]) + set_pref(/datum/pref/player/audio/admin_sounds, S["snd_admin_vol"]) + set_pref(/datum/pref/player/audio/jukebox, S["snd_jukebox_vol"]) + + set_pref(/datum/pref/player/audio/effects, S["snd_effects_master_vol"]) + var/effects_coeff = S["snd_effects_master_vol"] * 0.01 + set_pref(/datum/pref/player/audio/voice_announcements, S["snd_effects_voice_announcement_vol"] * effects_coeff) + set_pref(/datum/pref/player/audio/instruments, S["snd_effects_instrument_vol"] * effects_coeff) + set_pref(/datum/pref/player/audio/spam_effects, S["snd_effects_misc_vol"]) // no coefficient as this still depends on the effects audio slider + + // ui + set_pref(/datum/pref/player/display/auto_fit_viewport, S["auto_fit_viewport"]) + set_pref(/datum/pref/player/ui/ui_style, S["UI_style"]) + set_pref(/datum/pref/player/ui/ui_style_color, S["UI_style_color"]) + var/converted_alpha = 100 - floor(100*S["UI_style_alpha"]/255) + set_pref(/datum/pref/player/ui/ui_style_opacity, converted_alpha) + set_pref(/datum/pref/player/ui/outline, S["outline_enabled"]) + set_pref(/datum/pref/player/ui/outline_color, S["outline_color"]) + set_pref(/datum/pref/player/ui/runechat, S["show_runechat"]) + set_pref(/datum/pref/player/ui/tooltip, S["tooltip"]) + set_pref(/datum/pref/player/ui/tooltip_font, S["tooltip_font"]) + set_pref(/datum/pref/player/ui/tooltip_size, S["tooltip_size"]) + + //set_pref(/datum/pref/player/ui/..., S["tgui_fancy"]) // removed, we don't support ie8 already and 516 is coming + set_pref(/datum/pref/player/ui/tgui_lock, S["tgui_lock"]) + + // graphics + var/converted_fps = S["clientfps"] == -1 ? RECOMMENDED_FPS : S["clientfps"] // before -1 was for default, but it's confusing and we don't change it too often + set_pref(/datum/pref/player/display/fps, converted_fps) + + var/converted_parallax + switch(S["parallax"]) + if(-1) + converted_parallax = PARALLAX_INSANE + if(0) + converted_parallax = PARALLAX_HIGH + if(1) + converted_parallax = PARALLAX_MED + if(2) + converted_parallax = PARALLAX_LOW + if(3) + converted_parallax = PARALLAX_DISABLE + set_pref(/datum/pref/player/effects/parallax, converted_parallax) + set_pref(/datum/pref/player/effects/lobbyanimation, S["lobbyanimation"]) + + var/converted_blur_effect = !S["eye_blur_effect"] + set_pref(/datum/pref/player/effects/legacy_blur, converted_blur_effect) + + set_pref(/datum/pref/player/effects/ambientocclusion, S["ambientocclusion"]) + + var/converted_glowlevel + switch(S["glowlevel"]) + if(0) + converted_glowlevel = GLOW_HIGH + if(1) + converted_glowlevel = GLOW_MED + if(2) + converted_glowlevel = GLOW_LOW + if(3) + converted_glowlevel = GLOW_DISABLE + set_pref(/datum/pref/player/effects/glowlevel, converted_glowlevel) + set_pref(/datum/pref/player/effects/lampsexposure, S["lampsexposure"]) + set_pref(/datum/pref/player/effects/lampsglare, S["lampsglare"]) + + // game + #define SHOW_ANIMATIONS 16 + #define SHOW_PROGBAR 32 + set_pref(/datum/pref/player/game/melee_animation, S["toggles"] & SHOW_ANIMATIONS) + set_pref(/datum/pref/player/game/progressbar, S["toggles"] & SHOW_PROGBAR) + #undef SHOW_ANIMATIONS + #undef SHOW_PROGBAR + + set_pref(/datum/pref/player/game/endroundarena, S["eorg_enabled"]) + + // chat + set_pref(/datum/pref/player/chat/ooccolor, S["ooccolor"]) + set_pref(/datum/pref/player/chat/aooccolor, S["aooccolor"]) + + var/const/CHAT_OOC = 1 + var/const/CHAT_DEAD = 2 + var/const/CHAT_GHOSTEARS = 4 // merged into /ghostears + //var/const/CHAT_NOCLIENT_ATTACK = 8 // merged into new /attack_log + var/const/CHAT_PRAYER = 16 + var/const/CHAT_RADIO = 32 + //var/const/CHAT_ATTACKLOGS = 64 // merged into new /attack_log + var/const/CHAT_DEBUGLOGS = 128 + var/const/CHAT_LOOC = 256 + var/const/CHAT_GHOSTRADIO = 512 + //var/const/CHAT_GHOSTNPC = 1024 // merged into new /ghostantispam + var/const/CHAT_CKEY = 2048 + + set_pref(/datum/pref/player/chat/ooc, S["chat_toggles"] & CHAT_OOC) + set_pref(/datum/pref/player/chat/dead, S["chat_toggles"] & CHAT_DEAD) + set_pref(/datum/pref/player/chat/ghostears, S["chat_toggles"] & CHAT_GHOSTEARS) + set_pref(/datum/pref/player/chat/prayers, S["chat_toggles"] & CHAT_PRAYER) + set_pref(/datum/pref/player/chat/radio, S["chat_toggles"] & CHAT_RADIO) + set_pref(/datum/pref/player/chat/debug_log, S["chat_toggles"] & CHAT_DEBUGLOGS) + set_pref(/datum/pref/player/chat/looc, S["chat_toggles"] & CHAT_LOOC) + set_pref(/datum/pref/player/chat/ghostradio, S["chat_toggles"] & CHAT_GHOSTRADIO) + set_pref(/datum/pref/player/chat/show_ckey, S["chat_toggles"] & CHAT_CKEY) + + var/const/CHAT_GHOSTSIGHT_ALL = 1 + //var/const/CHAT_GHOSTSIGHT_ALLMANUAL = 2 // merged into new /ghostantispam + var/const/CHAT_GHOSTSIGHT_NEARBYMOBS = 3 + + var/converted_chat_ghostsight + switch(S["chat_ghostsight"]) + if(CHAT_GHOSTSIGHT_ALL) + converted_chat_ghostsight = TRUE + if(CHAT_GHOSTSIGHT_NEARBYMOBS) + converted_chat_ghostsight = FALSE + set_pref(/datum/pref/player/chat/ghostsight, converted_chat_ghostsight) + + // meta domain + set_pref(/datum/pref/player/meta/lastchangelog, S["lastchangelog"]) + set_pref(/datum/pref/player/meta/default_slot, S["default_slot"]) + set_pref(/datum/pref/player/meta/random_slot, S["randomslot"]) + set_pref(/datum/pref/player/game/hotkey_mode, S["hotkeys"]) + + // emote panel + var/list/old_emotes_list = S["emote_panel"] + if(length(old_emotes_list)) + var/list/disabled_emotes = global.emotes_for_emote_panel - old_emotes_list + set_pref(/datum/pref/player/meta/disabled_emotes_emote_panel, disabled_emotes) + + // keibinds + var/list/old_keybinds = S["key_bindings"] + var/list/keyname_to_bind = list() + for(var/key in old_keybinds) + for(var/keyname in old_keybinds[key]) + keyname_to_bind[keyname] = "[keyname_to_bind[keyname] ? "[keyname_to_bind[keyname]] " : "" ][key]" + + for(var/keyname in keyname_to_bind) + var/pref_type = legacy_keyname_to_pref[keyname] + if(keyname == "None") + set_keybind_pref(pref_type, "") + else + set_keybind_pref(pref_type, keyname_to_bind[keyname]) /datum/preferences/proc/update_character(current_version, savefile/S) if(current_version < 17) @@ -118,6 +233,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car player_alt_titles -= J.title + if(current_version < 26) + for(var/role in be_role) + if(!CanBeRole(role)) + be_role -= role + if(current_version < 27) job_preferences = list() //It loaded null from nonexistant savefile field. var/job_civilian_high = 0 @@ -196,7 +316,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car med_record = fix_cyrillic(med_record) sec_record = fix_cyrillic(sec_record) gen_record = fix_cyrillic(gen_record) - metadata = fix_cyrillic(metadata) home_system = fix_cyrillic(home_system) citizenship = fix_cyrillic(citizenship) faction = fix_cyrillic(faction) @@ -206,7 +325,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["med_record"] << med_record S["sec_record"] << sec_record S["gen_record"] << gen_record - S["OOC_Notes"] << metadata S["home_system"] << home_system S["citizenship"] << citizenship S["faction"] << faction @@ -298,49 +416,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car ResetQuirks() break -/// checks through keybindings for outdated unbound keys and updates them -/datum/preferences/proc/check_keybindings() - if(!parent) - return - - // When loading from savefile key_binding can be null - // This happens when player had savefile created before new kb system, but hotkeys was not saved - if(!length(key_bindings)) - key_bindings = deepCopyList(global.hotkey_keybinding_list_by_key) // give them default keybinds too - - var/list/user_binds = list() - for (var/key in key_bindings) - for(var/kb_name in key_bindings[key]) - user_binds[kb_name] += list(key) - var/list/notadded = list() - for (var/name in global.keybindings_by_name) - var/datum/keybinding/kb = global.keybindings_by_name[name] - if(length(user_binds[kb.name])) - continue // key is unbound and or bound to something - var/addedbind = FALSE - for(var/hotkeytobind in kb.hotkey_keys) - if(!length(key_bindings[hotkeytobind])) - LAZYADD(key_bindings[hotkeytobind], kb.name) - addedbind = TRUE - if(!addedbind) - notadded += kb - if(length(notadded)) - addtimer(CALLBACK(src, PROC_REF(announce_conflict), notadded), 5 SECONDS) - -/datum/preferences/proc/announce_conflict(list/notadded) - to_chat(parent, "KEYBINDING CONFLICT!!!\n\ - There are new keybindings that have defaults bound to keys you already set, They will default to Unbound. You can bind them in Setup Character or Game Preferences\n\ - Or you can click here to go straight to the keybindings page") - for(var/item in notadded) - var/datum/keybinding/conflicted = item - to_chat(parent, "[conflicted.category]: [conflicted.full_name] needs updating") - LAZYADD(key_bindings["None"], conflicted.name) // set it to unbound to prevent this from opening up again in the future - /datum/preferences/proc/load_path(ckey, filename = "preferences.sav") if(!ckey) return path = "data/player_saves/[ckey[1]]/[ckey]/[filename]" +// loads and updates all old preferences if needed /datum/preferences/proc/load_preferences() if(!path) return 0 @@ -351,120 +432,25 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car return 0 S.cd = "/" + // convert old preferences to datumized system, if we haven't done so already + //if + convert_preferences(S) + + // todo new update and examples + var/needs_update = savefile_needs_update(S) if(needs_update == SAVEFILE_TOO_OLD) // fatal, can't load any data return 0 - //General preferences - S["ooccolor"] >> ooccolor - S["aooccolor"] >> aooccolor - S["lastchangelog"] >> lastchangelog - S["UI_style"] >> UI_style - S["UI_style_color"] >> UI_style_color - S["UI_style_alpha"] >> UI_style_alpha - S["clientfps"] >> clientfps - S["default_slot"] >> default_slot - S["chat_toggles"] >> chat_toggles - S["toggles"] >> toggles - S["chat_ghostsight"] >> chat_ghostsight - S["randomslot"] >> randomslot - S["parallax"] >> parallax - S["ambientocclusion"] >> ambientocclusion - S["glowlevel"] >> glowlevel - S["lampsexposure"] >> lampsexposure - S["lampsglare"] >> lampsglare - S["eye_blur_effect"] >> eye_blur_effect - S["auto_fit_viewport"] >> auto_fit_viewport - S["lobbyanimation"] >> lobbyanimation - S["tooltip"] >> tooltip - S["tooltip_size"] >> tooltip_size - S["tooltip_font"] >> tooltip_font - S["outline_enabled"] >> outline_enabled - S["outline_color"] >> outline_color - S["eorg_enabled"] >> eorg_enabled - S["show_runechat"] >> show_runechat - S["emote_panel"] >> custom_emote_panel - - // Custom hotkeys - S["key_bindings"] >> key_bindings - check_keybindings() - S["hotkeys"] >> hotkeys - - //TGUI - S["tgui_fancy"] >> tgui_fancy - S["tgui_lock"] >> tgui_lock - - //Sound preferences - S["snd_music_vol"] >> snd_music_vol - S["snd_ambient_vol"] >> snd_ambient_vol - S["snd_effects_master_vol"] >> snd_effects_master_vol - S["snd_effects_voice_announcement_vol"] >> snd_effects_voice_announcement_vol - S["snd_effects_misc_vol"] >> snd_effects_misc_vol - S["snd_effects_instrument_vol"] >> snd_effects_instrument_vol - S["snd_notifications_vol"] >> snd_notifications_vol - S["snd_admin_vol"] >> snd_admin_vol - S["snd_jukebox_vol"] >> snd_jukebox_vol - - //*** FOR FUTURE UPDATES, SO YOU KNOW WHAT TO DO ***// - //try to fix any outdated data if necessary - if(needs_update >= 0) - update_preferences(needs_update, S) // needs_update = savefile_version if we need an update (positive integer) - - //Sanitize - ooccolor = normalize_color(sanitize_hexcolor(ooccolor, initial(ooccolor))) - aooccolor = normalize_color(sanitize_hexcolor(aooccolor, initial(aooccolor))) - lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) - UI_style = sanitize_inlist(UI_style, global.available_ui_styles, global.available_ui_styles[1]) - clientfps = sanitize_integer(clientfps, -1, 1000, -1) - default_slot = sanitize_integer(default_slot, 1, GET_MAX_SAVE_SLOTS(parent), initial(default_slot)) - toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) - chat_toggles = sanitize_integer(chat_toggles, 0, 65535, initial(chat_toggles)) - chat_ghostsight = sanitize_integer(chat_ghostsight, CHAT_GHOSTSIGHT_ALL, CHAT_GHOSTSIGHT_NEARBYMOBS, CHAT_GHOSTSIGHT_ALL) - randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) - UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) - UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) - key_bindings = sanitize_keybindings(key_bindings) - hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys)) - tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy)) - tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock)) - parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, PARALLAX_HIGH) - ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) - glowlevel = sanitize_integer(glowlevel, GLOW_HIGH, GLOW_DISABLE, initial(glowlevel)) - eye_blur_effect = sanitize_integer(eye_blur_effect, 0, 1, initial(eye_blur_effect)) - lampsexposure = sanitize_integer(lampsexposure, 0, 1, initial(lampsexposure)) - lampsglare = sanitize_integer(lampsglare, 0, 1, initial(lampsglare)) - lobbyanimation = sanitize_integer(lobbyanimation, 0, 1, initial(lobbyanimation)) - auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport)) - tooltip = sanitize_integer(tooltip, 0, 1, initial(tooltip)) - tooltip_size = sanitize_integer(tooltip_size, 1, 15, initial(tooltip_size)) - outline_enabled = sanitize_integer(outline_enabled, 0, 1, initial(outline_enabled)) - outline_color = normalize_color(sanitize_hexcolor(outline_color, initial(outline_color))) - eorg_enabled = sanitize_integer(eorg_enabled, 0, 1, initial(eorg_enabled)) - show_runechat = sanitize_integer(show_runechat, 0, 1, initial(show_runechat)) - custom_emote_panel = sanitize_emote_panel(custom_emote_panel) - - snd_music_vol = sanitize_integer(snd_music_vol, 0, 100, initial(snd_music_vol)) - snd_ambient_vol = sanitize_integer(snd_ambient_vol, 0, 100, initial(snd_ambient_vol)) - snd_effects_master_vol = sanitize_integer(snd_effects_master_vol, 0, 100, initial(snd_effects_master_vol)) - snd_effects_voice_announcement_vol = sanitize_integer(snd_effects_voice_announcement_vol, 0, 100, initial(snd_effects_voice_announcement_vol)) - snd_effects_misc_vol = sanitize_integer(snd_effects_misc_vol, 0, 100, initial(snd_effects_misc_vol)) - snd_effects_instrument_vol = sanitize_integer(snd_effects_instrument_vol, 0, 100, initial(snd_effects_instrument_vol)) - snd_notifications_vol = sanitize_integer(snd_notifications_vol, 0, 100, initial(snd_notifications_vol)) - snd_admin_vol = sanitize_integer(snd_admin_vol, 0, 100, initial(snd_admin_vol)) - snd_jukebox_vol = sanitize_integer(snd_jukebox_vol, 0, 100, initial(snd_jukebox_vol)) - if(needs_update >= 0) //save the updated version - var/old_default_slot = default_slot for (var/slot in S.dir) //but first, update all current character slots. if (copytext(slot, 1, 10) != "character") continue var/slotnum = text2num(copytext(slot, 10)) if (!slotnum) continue - default_slot = slotnum - if (load_character()) - save_character() - default_slot = old_default_slot + if (load_character(slotnum)) // loads and updates character + save_character(slotnum) save_preferences() return 1 @@ -479,55 +465,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["version"] << SAVEFILE_VERSION_MAX - //general preferences - S["ooccolor"] << ooccolor - S["aooccolor"] << aooccolor - S["lastchangelog"] << lastchangelog - S["UI_style"] << UI_style - S["UI_style_color"] << UI_style_color - S["UI_style_alpha"] << UI_style_alpha - S["clientfps"] << clientfps - S["default_slot"] << default_slot - S["toggles"] << toggles - S["chat_toggles"] << chat_toggles - S["chat_ghostsight"] << chat_ghostsight - S["randomslot"] << randomslot - S["parallax"] << parallax - S["ambientocclusion"] << ambientocclusion - S["glowlevel"] << glowlevel - S["eye_blur_effect"] << eye_blur_effect - S["lampsexposure"] << lampsexposure - S["lampsglare"] << lampsglare - S["lobbyanimation"] << lobbyanimation - S["auto_fit_viewport"] << auto_fit_viewport - S["tooltip"] << tooltip - S["tooltip_size"] << tooltip_size - S["tooltip_font"] << tooltip_font - S["emote_panel"] << custom_emote_panel - - - // Custom hotkeys - S["key_bindings"] << key_bindings - S["hotkeys"] << hotkeys - - S["outline_enabled"] << outline_enabled - S["outline_color"] << outline_color - S["eorg_enabled"] << eorg_enabled - S["show_runechat"] << show_runechat - //TGUI - S["tgui_fancy"] << tgui_fancy - S["tgui_lock"] << tgui_lock - - //Sound preferences - S["snd_music_vol"] << snd_music_vol - S["snd_ambient_vol"] << snd_ambient_vol - S["snd_effects_master_vol"] << snd_effects_master_vol - S["snd_effects_voice_announcement_vol"] << snd_effects_voice_announcement_vol - S["snd_effects_misc_vol"] << snd_effects_misc_vol - S["snd_effects_instrument_vol"] << snd_effects_instrument_vol - S["snd_notifications_vol"] << snd_notifications_vol - S["snd_admin_vol"] << snd_admin_vol - S["snd_jukebox_vol"] << snd_jukebox_vol return 1 /datum/preferences/proc/load_saved_character(dir) @@ -541,7 +478,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car return 0 //Character - S["OOC_Notes"] >> metadata S["real_name"] >> real_name S["name_is_always_random"] >> be_random_name S["gender"] >> gender @@ -624,7 +560,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car repetitive_updates_character(needs_update, S) //Sanitize - metadata = sanitize_text(metadata, initial(metadata)) real_name = sanitize_name(real_name) if(isnull(species)) @@ -721,28 +656,29 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car return 0 S.cd = "/" if(!slot) - slot = default_slot - slot = sanitize_integer(slot, 1, GET_MAX_SAVE_SLOTS(parent), initial(default_slot)) - if(slot != default_slot) - default_slot = slot - S["default_slot"] << slot + slot = get_pref(/datum/pref/player/meta/default_slot) + if(!slot) + CRASH("Attempt to access saves with empty slot") S.cd = "/character[slot]" load_saved_character(S.cd) return 1 -/datum/preferences/proc/save_character() +/datum/preferences/proc/save_character(slot) if(!path) return 0 var/savefile/S = new /savefile(path) if(!S) return 0 - S.cd = "/character[default_slot]" + if(!slot) + slot = get_pref(/datum/pref/player/meta/default_slot) + if(!slot) + CRASH("Attempt to access saves with empty slot") + S.cd = "/character[slot]" S["version"] << SAVEFILE_VERSION_MAX // load_character will sanitize any bad data, so assume up-to-date. //Character - S["OOC_Notes"] << metadata S["real_name"] << real_name S["name_is_always_random"] << be_random_name S["gender"] << gender @@ -814,14 +750,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car return 1 -/proc/sanitize_keybindings(value) - var/list/base_bindings = sanitize_islist(value,list()) - for(var/key in base_bindings) - base_bindings[key] = base_bindings[key] & global.keybindings_by_name - if(!length(base_bindings[key])) - base_bindings -= key - return base_bindings - /proc/sanitize_emote_panel(value) var/list/emote_panel = SANITIZE_LIST(value) var/list/sanitized_emote_panel = list() diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index cbe84d100dea..05c3a223840d 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -1,86 +1,8 @@ //toggles -/client/verb/toggle_ghost_ears() - set name = "Show/Hide GhostEars" - set category = "Preferences" - set desc = ".Toggle Between seeing all mob speech, and only speech of nearby mobs." - prefs.chat_toggles ^= CHAT_GHOSTEARS - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].") - prefs.save_preferences() - feedback_add_details("admin_verb","TGE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_ghost_npc() - set name = "Show/Hide GhostNPCsSpeech" - set category = "Preferences" - set desc = ".Toggle Between seeing all non-player mobs speech, and only speech of nearby non-player mobs." - prefs.chat_toggles ^= CHAT_GHOSTNPC - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTNPC) ? "see all non-player mobs speech in the world" : "only see speech from nearby non-player mobs"].") - prefs.save_preferences() - feedback_add_details("admin_verb","TGN") - -/client/verb/toggle_ghost_radio() - set name = "Enable/Disable GhostRadio" - set category = "Preferences" - set desc = ".Toggle between hearing all radio chatter, or only from nearby speakers." - prefs.chat_toggles ^= CHAT_GHOSTRADIO - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].") - prefs.save_preferences() - feedback_add_details("admin_verb","TGR") - -/client/proc/toggle_hear_radio() - set name = "Show/Hide RadioChatter" - set category = "Preferences" - set desc = "Toggle seeing radiochatter from radios and speakers." - if(!holder) return - prefs.chat_toggles ^= CHAT_RADIO - prefs.save_preferences() - to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers") - feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/deadchat() // Deadchat toggle is usable by anyone. - set name = "Show/Hide Deadchat" - set category = "Preferences" - set desc ="Toggles seeing deadchat." - prefs.chat_toggles ^= CHAT_DEAD - prefs.save_preferences() - - if(src.holder) - to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") - else - to_chat(src, "As a ghost, you will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") - - feedback_add_details("admin_verb","TDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/toggleprayers() - set name = "Show/Hide Prayers" - set category = "Preferences" - set desc = "Toggles seeing prayers." - prefs.chat_toggles ^= CHAT_PRAYER - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.") - feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/listen_ooc() - set name = "Show/Hide OOC" - set category = "Preferences" - set desc = "Toggles seeing OutOfCharacter chat." - prefs.chat_toggles ^= CHAT_OOC - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.") - feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/listen_looc() - set name = "Show/Hide LOOC" - set category = "Preferences" - set desc = "Toggles seeing Local OutOfCharacter chat." - prefs.chat_toggles ^= CHAT_LOOC - prefs.save_preferences() - - to_chat(src, "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.") - feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/verb/toggle_be_role(role in special_roles) set name = "Toggle SpecialRole Candidacy" - set category = "Preferences" + set category = "OOC" set desc = "Toggles which special roles you would like to be a candidate for, during events." var/role_type = role if(!role_type) return @@ -94,7 +16,7 @@ /client/verb/toggle_ignored_role() set name = "Toggle Ignore Roles" - set category = "Preferences" + set category = "OOC" set desc = "Toggles ignore questions" var/role = input(usr, "Ignored Qustions for Roles in current Round:") as null|anything in prefs.ignore_question @@ -104,329 +26,9 @@ to_chat(src, "You will receive requests for \"[role]\" again") feedback_add_details("admin_verb","TBeSpecialIgnore") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/verb/change_ui() - set name = "Change UI" - set category = "Preferences" - set desc = "Configure your user interface." - - if(!ishuman(usr)) - to_chat(usr, "This only for human") - return - - var/UI_style_new = input(usr, "Select a style, we recommend White for customization") as null|anything in sortList(global.available_ui_styles) - if(!UI_style_new) - return - - var/UI_alpha_new = input(usr, "Select a new alpha(transparence) parametr for UI, between 50 and 255") as num - if(!UI_alpha_new || !(UI_alpha_new <= 255 && UI_alpha_new >= 50)) - return - - var/UI_color_new = input(usr, "Choose your UI color, dark colors are not recommended!") as color|null - if(!UI_color_new) - return - - var/datum/hud/hud = usr.hud_used - - //update UI - var/list/screens = hud.main + hud.adding + hud.hotkeybuttons - - for(var/atom/movable/screen/complex/complex as anything in hud.complex) - screens += complex.screens - - var/ui_style = ui_style2icon(UI_style_new) - var/list/icon_states = icon_states(ui_style) // so it wont break hud with dmi that has no specific icon_state. - - hud.ui_style = ui_style - hud.ui_color = UI_color_new - hud.ui_alpha = UI_alpha_new - - for(var/atom/movable/screen/screen as anything in screens) - if(screen.alpha && (screen.icon_state in icon_states)) - screen.update_by_hud(hud) - - if(tgui_alert(usr, "Like it? Save changes?",, list("Yes", "No")) == "Yes") - prefs.UI_style = UI_style_new - prefs.UI_style_alpha = UI_alpha_new - prefs.UI_style_color = UI_color_new - prefs.save_preferences() - to_chat(usr, "UI was saved") - return - - hud.ui_style = ui_style2icon(prefs.UI_style) - hud.ui_color = prefs.UI_style_color - hud.ui_alpha = prefs.UI_style_alpha - - for(var/atom/movable/screen/screen as anything in screens) - if(screen.alpha && (screen.icon_state in icon_states)) - screen.update_by_hud(hud) - -/client/verb/toggle_lobby_animation() - set name = "Toggle Lobby Animation" - set category = "Preferences" - set desc = "Toggles lobby animations." - prefs.lobbyanimation = !prefs.lobbyanimation - prefs.save_preferences() - if(isnewplayer(mob)) - var/mob/dead/new_player/M = mob - M.show_titlescreen() - if(prefs.lobbyanimation) - to_chat(src, "You have enabled lobby animation.") - else - to_chat(src, "You have disabled lobby animation.") - -/client/verb/toggle_anim_attacks() - set name = "Show/Hide Melee Animations" - set category = "Preferences" - set desc = "Toggles seeing melee attack animations." - prefs.toggles ^= SHOW_ANIMATIONS - prefs.save_preferences() - to_chat(src, "You will [(prefs.toggles & SHOW_ANIMATIONS) ? "now" : "no longer"] see melee attack animations.") - feedback_add_details("admin_verb","MAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_progress_bar() - set name = "Show/Hide Progress Bar" - set category = "Preferences" - set desc = "Toggles visibility of progress bars." - prefs.toggles ^= SHOW_PROGBAR - prefs.save_preferences() - to_chat(src, "You will [(prefs.toggles & SHOW_PROGBAR) ? "now" : "no longer"] see progress bars.") - feedback_add_details("admin_verb","PRB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/set_ckey_show() - set name = "Show/Hide Ckey" - set desc = "Toggle between showing your Ckey in LOOC and dead chat." - set category = "Preferences" - prefs.chat_toggles ^= CHAT_CKEY - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_toggles & CHAT_CKEY) ? "now" : "no longer"] show your ckey in LOOC and deadchat.") - feedback_add_details("admin_verb","SC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_ambient_occlusion() - set name = "Toggle Ambient Occlusion" - set category = "Preferences" - set desc = "Toggle ambient occlusion." - - prefs.ambientocclusion = !prefs.ambientocclusion - to_chat(src, "Ambient Occlusion: [prefs.ambientocclusion ? "Enabled" : "Disabled"].") - prefs.save_preferences() - update_plane_masters(/atom/movable/screen/plane_master/game_world) - feedback_add_details("admin_verb","TAC") - -/client/verb/set_glow_level() - set name = "Lighting: Glow Level" - set category = "Preferences" - - var/new_setting = input(src, "Set glow level of light sources:") as null|anything in list("Disable", "Low", "Medium (Default)", "High") - if(!new_setting) - return - - switch(new_setting) - if("Disable") - prefs.glowlevel = GLOW_DISABLE - if("Low") - prefs.glowlevel = GLOW_LOW - if("Medium (Default)") - prefs.glowlevel = GLOW_MED - if("High") - prefs.glowlevel = GLOW_HIGH - - to_chat(src, "Glow level: [new_setting].") - prefs.save_preferences() - update_plane_masters(/atom/movable/screen/plane_master/lamps_selfglow) - feedback_add_details("admin_verb","LGL") - -/client/verb/toggle_lamp_exposure() - set name = "Lighting: Lamp Exposure" - set category = "Preferences" - - prefs.lampsexposure = !prefs.lampsexposure - to_chat(src, "Lamp exposure: [prefs.lampsexposure ? "Enabled" : "Disabled"].") - prefs.save_preferences() - update_plane_masters(/atom/movable/screen/plane_master/exposure) - feedback_add_details("admin_verb","LEXP") - -/client/verb/toggle_lamps_glare() - set name = "Lighting: Lamp Glare" - set category = "Preferences" - - prefs.lampsglare = !prefs.lampsglare - to_chat(src, "Glare: [prefs.lampsglare ? "Enabled" : "Disabled"].") - prefs.save_preferences() - update_plane_masters(/atom/movable/screen/plane_master/lamps_glare) - feedback_add_details("admin_verb","GLR") - -/client/verb/eye_blur_effect() - set name = "Blur effect" - set category = "Preferences" - - prefs.eye_blur_effect = !prefs.eye_blur_effect - to_chat(src, "Blur effect: [prefs.eye_blur_effect ? "Enabled" : "Old design"].") - prefs.save_preferences() - update_plane_masters(/atom/movable/screen/plane_master/game_world) - feedback_add_details("admin_verb","EBE") - -/client/verb/set_parallax_quality() - set name = "Set Parallax Quality" - set category = "Preferences" - set desc = "Set space parallax quality." - - var/new_setting = input(src, "Parallax quality:") as null|anything in list("Disable", "Low", "Medium", "High", "Insane") - if(!new_setting) - return - - switch(new_setting) - if("Disable") - prefs.parallax = PARALLAX_DISABLE - if("Low") - prefs.parallax = PARALLAX_LOW - if("Medium") - prefs.parallax = PARALLAX_MED - if("High") - prefs.parallax = PARALLAX_HIGH - if("Insane") - prefs.parallax = PARALLAX_INSANE - - to_chat(src, "Parallax (Fancy Space): [new_setting].") - prefs.save_preferences() - feedback_add_details("admin_verb","TPX") - - if (mob && mob.hud_used) - mob.hud_used.update_parallax_pref() - -/client/verb/toggle_ghost_sight() - set name = "Change Ghost Sight Options" - set category = "Preferences" - set desc = "Toggle between seeing all mob emotes, all manual-only emotes and only emotes of nearby mobs." - - var/new_setting = input(src, "Ghost Sight Options:") as null|anything in list("Absolutely all emotes", "All manual-only", "Only emotes of nearby mobs") - if(!new_setting) - return - - switch(new_setting) - if("Absolutely all emotes") - to_chat(src, "As a ghost, you will now see absolutely all emotes in the world.") - prefs.chat_ghostsight = CHAT_GHOSTSIGHT_ALL - if("All manual-only") - to_chat(src, "As a ghost, you will now see all manual-only(me, *emote, etc) emotes in the world.") - prefs.chat_ghostsight = CHAT_GHOSTSIGHT_ALLMANUAL - if("Only emotes of nearby mobs") - to_chat(src, "As a ghost, you will now see only see emotes from nearby mobs") - prefs.chat_ghostsight = CHAT_GHOSTSIGHT_NEARBYMOBS - - prefs.save_preferences() - feedback_add_details("admin_verb","CGSO") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_fancy_tgui() - set name = "Toggle Fancy TGUI" - set category = "Preferences" - set desc = "Toggle Fancy TGUI" - - prefs.tgui_fancy = !prefs.tgui_fancy - prefs.save_preferences() - feedback_add_details("admin_verb", "TFTGUI") - -/client/verb/toggle_tooltip() - set name = "Tooltip: Show/Hide" - set category = "Preferences" - set desc = "Toggle Name of Items" - - prefs.tooltip = !prefs.tooltip - - if(prefs.tooltip) - tooltip.set_state(TRUE) - else - tooltip.set_state(FALSE) - - prefs.save_preferences() - to_chat(src, "Name of items [prefs.tooltip ? "enabled" : "disabled"].") - feedback_add_details("admin_verb", "TTIP") - -/client/verb/change_font_tooltip() - set name = "Tooltip: Change Font" - set category = "Preferences" - set desc = "Toggle Font of Names of Items" - - var/list/fonts = list("System", "Fixedsys", "Small Fonts", "Times New Roman", "Serif", "Verdana", "Custom Font") - - var/font = input(usr, "Font of Names of Items:", "Font", prefs.tooltip_font) as null|anything in fonts | prefs.tooltip_font - - if(font == "Custom Font") - font = sanitize(input("Enter the font that you have on your computer:", "Font") as null|text) - - if(!font) - return - - prefs.tooltip_font = font - - prefs.save_preferences() - feedback_add_details("admin_verb", "FTIP") - -/client/verb/change_size_tooltip() - set name = "Tooltip: Change Size" - set category = "Preferences" - set desc = "Change Size of Names of Items" - - prefs.tooltip_size = input(usr, "Введите размер Названий Предметов") as num - - tooltip.font_size = prefs.tooltip_size - prefs.save_preferences() - feedback_add_details("admin_verb", "LTIP") - -/client/verb/toggle_outline() - set name = "Toggle Outline" - set category = "Preferences" - set desc = "Toggle Outline" - - prefs.outline_enabled = !prefs.outline_enabled - prefs.save_preferences() - to_chat(src, "Outline is [prefs.outline_enabled ? "enabled" : "disabled"].") - feedback_add_details("admin_verb", "TO") - -/client/verb/change_outline_color() - set name = "Change Outline Color" - set category = "Preferences" - set desc = "Change Outline Color" - - var/pickedOutlineColor = input(usr, "Choose your outline color.", "General Preference", prefs.outline_color) as color|null - if(!pickedOutlineColor) - return - prefs.outline_color = pickedOutlineColor - prefs.save_preferences() - to_chat(src, "Outline color changed.") - feedback_add_details("admin_verb", "COC") - -/client/verb/toggle_eorg() - set name = "Toggle End of Round Deathmatch" - set category = "Preferences" - set desc = "At the end of the round you will be teleported to thunderdome to freely bash your fellow colleagues." - - prefs.eorg_enabled = !prefs.eorg_enabled - prefs.save_preferences() - to_chat(src, "You [prefs.eorg_enabled ? "will be" : "won't be"] teleported to Thunderdome at round end.") - feedback_add_details("admin_verb", "ED") - -/client/verb/toggle_runechat() - set name = "Toggle Runechat (Above-Head-Speech)" - set category = "Preferences" - prefs.show_runechat = !prefs.show_runechat - - to_chat(src, "Runechat is [prefs.show_runechat ? "enabled" : "disabled"].") - feedback_add_details("admin_verb", "TRC") - -/client/verb/toggle_hotkeys_mode() - set name = "Toggle Hotkeys Mode" - set category = "Preferences" - - prefs.toggle_hotkeys_mode() - if(prefs.hotkeys) - to_chat(src, "Режим хоткеев переключен: при клике в окно игры фокус будет переключен на окно игры") - else - to_chat(src, "Режим хоткеев переключен: при клике в окно игры фокус останется на чате.") - feedback_add_details("admin_verb", "thm") - /client/verb/edit_emote_panel() set name = "Edit Emote Panel" - set category = "Preferences" + set category = "OOC" if(!emote_panel_editor) emote_panel_editor = new /datum/emote_panel_editor(src) diff --git a/code/modules/client/settings/_pref.dm b/code/modules/client/settings/_pref.dm new file mode 100644 index 000000000000..20bdf8ed7903 --- /dev/null +++ b/code/modules/client/settings/_pref.dm @@ -0,0 +1,76 @@ +/datum/pref + // related to json name (or table in DB) + var/domain // player | character | keybinds | meta + + // mostly for sorting prefs in settings menu + var/category + + var/name + + var/description + + // current value and also default value with initial() + var/value + + // one of PREF_TYPE_*, defines how we show preference at frontend and how we validate it + var/value_type = PREF_TYPE_CUSTOM // = COLOR | NUMBER | LIST | BOOLEAN | TEXT + + // ambivalent value depending on value_type: + // PREF_TYPE_RANGE - list(min, max, step (optional), unit (optional)) + // PREF_TYPE_SELECT - list(value, value, value) or list(value = "humanised name", value = "humanised name", value = "humanised name") + // PREF_TYPE_TEXT - list(max_length) + // not used for other types + var/list/value_parameters + + // just so we can filter and not confuse players with preferences that they can't use + var/admins_only = FALSE + var/supporters_only = FALSE + +// default sanitize procedures, override it if you need something more +/datum/pref/proc/sanitize_value(new_value, client/client) + + switch(value_type) + if(PREF_TYPE_TEXT) + var/max_length = (length(value_parameters) ? value_parameters[1] : MAX_PAPER_MESSAGE_LEN) + . = sanitize(new_value, max_length) + if(PREF_TYPE_RANGE) + var/min = value_parameters[1] + var/max = value_parameters[2] + if(isnum(new_value) && new_value >= min && new_value <= max) + . = new_value + else + . = initial(value) + WARNING("Can't sanitize [type] new value [new_value], fallback to default.") + if(PREF_TYPE_SELECT) + if(new_value in value_parameters) + . = new_value + else + . = initial(value) + WARNING("Can't sanitize [type] new value [new_value], fallback to default.") + if(PREF_TYPE_HEX) + var/hex = sanitize_hexcolor(new_value, null) + if(hex) + . = hex + else + . = initial(value) + WARNING("Can't sanitize [type] new value [new_value], fallback to default.") + if(PREF_TYPE_BOOLEAN) + . = !!new_value + else // any custom types + CRASH("Not implemented sanitize for [src.type]!") + + return . + +/datum/pref/proc/update_value(new_value, client/client) + var/old_value = value + value = sanitize_value(new_value, client) + + if(old_value != value && client) + on_update(client, old_value) + return TRUE + + return FALSE + +// override if you need to trigger any special updates after value change (reload planes, update sound volume, etc.) +/datum/pref/proc/on_update(client/client, old_value) + return FALSE diff --git a/code/modules/client/settings/keybinds/_keybinds.dm b/code/modules/client/settings/keybinds/_keybinds.dm new file mode 100644 index 000000000000..bf6396144f92 --- /dev/null +++ b/code/modules/client/settings/keybinds/_keybinds.dm @@ -0,0 +1,103 @@ +// keybinds value formatted as list of binds separated by space +// maximum 3 (KEYBINDS_MAXIMUM) binds and two spaces (or leading space) means empty bind in between +// combinations with alt/ctrl/shift use "+" +// +// "+" is chosen because it should not be possible (i think) to use +// as a key: "+" key is basically "Shift+=", and byond uses "Add" for numpad "+" + +/datum/pref/keybinds + domain = PREF_DOMAIN_KEYBINDS + value_type = PREF_TYPE_KEYBIND + + value = "" + + category = PREF_KEYBINDS_MISC + + // probably there was a plan to trigger keybinds in weight order, but currently it is not used anywhere + // maybe we should just remove it + var/weight = WEIGHT_LOWEST + + // legacy name for migration of old savefiles, you should not use it with new keybindings + var/legacy_keyname + +/datum/pref/keybinds/sanitize_value(new_value, client/client) + if(value_type != PREF_TYPE_KEYBIND) + return ..() + + var/list/new_keybinds = splittext(new_value, " ") + + if(!length(new_keybinds)) + return "" + + // skip any validation madness if it's just default + if(value == new_value) + return value + + new_value = "" + + // I hate this part + for(var/i in 1 to min(KEYBINDS_MAXIMUM, new_keybinds.len)) + var/raw_key = new_keybinds[i] + var/key + + var/altMod = FALSE + if(endswith(raw_key, "Alt")) + key = "Alt" + else if(findtext(raw_key, "Alt")) + altMod = TRUE + + var/ctrlMod = FALSE + if(endswith(raw_key, "Ctrl")) + key = "Ctrl" + else if(findtext(raw_key, "Ctrl")) + ctrlMod = TRUE + + var/shiftMod = FALSE + if(endswith(raw_key, "Shift")) + key = "Shift" + else if(findtext(raw_key, "Shift")) + shiftMod = TRUE + + if(!key) + // old saves keybind mods don't have separator, new keybind mods separated with + + var/static/list/filter_list = list("Alt", "Ctrl", "Shift", "+") + key = replace_characters(raw_key, filter_list) + + key = satinize_key(key, altMod, ctrlMod, shiftMod) + + new_value += "[key] " + + return trim_right(new_value) + +/datum/pref/keybinds/on_update(client/client, old_value) + if(value_type != PREF_TYPE_KEYBIND) + return ..() + + if(!client || !client.prefs) // offline update or prefs still initializing + return + + client.reset_held_keys() + + var/list/old_keybinds = splittext(old_value, " ") + for(var/key in old_keybinds) + client.prefs.key_bindings_by_key[key] -= list(src) + + var/list/new_keybinds = splittext(value, " ") + for(var/key in new_keybinds) + client.prefs.key_bindings_by_key[key] += list(src) + +/datum/pref/keybinds/proc/satinize_key(key, altMod, ctrlMod, shiftMod) + if(!length(key)) + return "" + if(!(key in global.byond_valid_keys)) + return "" + return "[altMod ? "Alt+" : ""][ctrlMod ? "Ctrl+" : ""][shiftMod ? "Shift+" : ""][key]" + +/datum/pref/keybinds/proc/down(client/user) + return FALSE + +/datum/pref/keybinds/proc/up(client/user) + return FALSE + +/datum/pref/keybinds/proc/can_use(client/user) + return TRUE diff --git a/code/modules/client/settings/keybinds/admin.dm b/code/modules/client/settings/keybinds/admin.dm new file mode 100644 index 000000000000..8acae37bc9f2 --- /dev/null +++ b/code/modules/client/settings/keybinds/admin.dm @@ -0,0 +1,113 @@ +/datum/pref/keybinds/admin + category = PREF_KEYBINDS_CLIENT + weight = WEIGHT_ADMIN + + admins_only = TRUE + +/datum/pref/keybinds/admin/can_use(client/user) + return user.holder ? TRUE : FALSE + +/datum/pref/keybinds/admin/admin_say + name = "Admin say" + description = "Talk with other admins." + value = "F5" + + legacy_keyname = "admin_say" + +/datum/pref/keybinds/admin/admin_say/down(client/user) + user.get_admin_say() + return TRUE + +/datum/pref/keybinds/admin/admin_ghost + name = "Aghost" + description = "Go ghost" + + legacy_keyname = "admin_ghost" + +/datum/pref/keybinds/admin/admin_ghost/down(client/user) + user.admin_ghost() + return TRUE + +/datum/pref/keybinds/admin/player_panel_new + name = "Player Panel New" + description = "Opens up the new player panel" + value = "F6" + + legacy_keyname = "player_panel_new" + +/datum/pref/keybinds/admin/player_panel_new/down(client/user) + user.holder.player_panel_new() + return TRUE + +/datum/pref/keybinds/admin/toggle_buildmode_self + name = "Toggle Buildmode Self" + description = "Toggles buildmode" + value = "F7" + + legacy_keyname = "toggle_buildmode_self" + +/datum/pref/keybinds/admin/toggle_buildmode_self/down(client/user) + user.togglebuildmodeself() + return TRUE + +/datum/pref/keybinds/admin/stealthmode + name = "Stealth mode" + description = "Enters stealth mode" + value = "Ctrl+F8" + + legacy_keyname = "stealth_mode" + +/datum/pref/keybinds/admin/stealthmode/down(client/user) + user.stealth() + return TRUE + +/datum/pref/keybinds/admin/invisimin + name = "Admin invisibility" + description = "Toggles ghost-like invisibility (Don't abuse this)" + value = "F8" + + legacy_keyname = "invisimin" + +/datum/pref/keybinds/admin/invisimin/down(client/user) + user.invisimin() + return TRUE + +/datum/pref/keybinds/admin/deadsay + name = "deadsay" + description = "Allows you to send a message to dead chat" + value = "F10" + + legacy_keyname = "dsay" + +/datum/pref/keybinds/admin/deadsay/down(client/user) + user.get_dead_say() + return TRUE + +/datum/pref/keybinds/admin/deadmin + name = "Deadmin" + description = "Shed your admin powers" + + legacy_keyname = "deadmin" + +/datum/pref/keybinds/admin/deadmin/down(client/user) + user.deadmin_self() + return TRUE + +/datum/pref/keybinds/admin/readmin + name = "Readmin" + description = "Regain your admin powers" + + legacy_keyname = "readmin" + +/datum/pref/keybinds/admin/readmin/down(client/user) + user.readmin_self() + return TRUE + +/datum/pref/keybinds/admin/toggle_combo_hud + name = "Toggle Combo HUD" + + legacy_keyname = "toggle_combo_hud" + +/datum/pref/keybinds/admin/toggle_combo_hud/down(client/user) + user.toggle_combo_hud() + return TRUE diff --git a/code/modules/client/settings/keybinds/carbon.dm b/code/modules/client/settings/keybinds/carbon.dm new file mode 100644 index 000000000000..3b28114e3243 --- /dev/null +++ b/code/modules/client/settings/keybinds/carbon.dm @@ -0,0 +1,29 @@ +/datum/pref/keybinds/carbon + category = PREF_KEYBINDS_CARBON + weight = WEIGHT_MOB + +/datum/pref/keybinds/carbon/can_use(client/user) + return iscarbon(user.mob) + +/datum/pref/keybinds/carbon/toggle_throw_mode + name = "Toggle throw mode" + description = "Toggle throwing the current item or not." + value = "R Southwest" // Southwest - PAGEDOWN + + legacy_keyname = "toggle_throw_mode" + +/datum/pref/keybinds/carbon/toggle_throw_mode/down(client/user) + var/mob/living/carbon/C = user.mob + C.toggle_throw_mode() + return TRUE + +/datum/pref/keybinds/carbon/give + name = "Give item" + description = "Give the item you're currently holding" + + legacy_keyname = "Give_Item" + +/datum/pref/keybinds/carbon/give/down(client/user) + var/mob/living/carbon/C = user.mob + C.give() + return TRUE diff --git a/code/modules/client/settings/keybinds/client.dm b/code/modules/client/settings/keybinds/client.dm new file mode 100644 index 000000000000..5604a6afd128 --- /dev/null +++ b/code/modules/client/settings/keybinds/client.dm @@ -0,0 +1,35 @@ +/datum/pref/keybinds/client + category = PREF_KEYBINDS_CLIENT + weight = WEIGHT_HIGHEST + +/datum/pref/keybinds/client/screenshot + name = "Screenshot" + description = "Take a screenshot." + + legacy_keyname = "screenshot" + +/datum/pref/keybinds/client/screenshot/down(client/user) + winset(user, null, "command=.screenshot [!user.keys_held["shift"] ? "auto" : ""]") + return TRUE + +/datum/pref/keybinds/client/minimal_hud + name = "Minimal HUD" + description = "Hide most HUD features" + value = "F12" + + legacy_keyname = "minimal_hud" + +/datum/pref/keybinds/client/minimal_hud/down(client/user) + user.mob.button_pressed_F12() + return TRUE + +/datum/pref/keybinds/client/toggle_fullscreen + name = "Toggle Fullscreen" + description = "Toggle Fullscreen" + value = "F11" + + legacy_keyname = "toggle_fullscreen" + +/datum/pref/keybinds/client/toggle_fullscreen/down(client/user) + user.toggle_fullscreen() + return TRUE diff --git a/code/modules/client/settings/keybinds/communication.dm b/code/modules/client/settings/keybinds/communication.dm new file mode 100644 index 000000000000..f85f3785d6c6 --- /dev/null +++ b/code/modules/client/settings/keybinds/communication.dm @@ -0,0 +1,65 @@ +/datum/pref/keybinds/communication + category = PREF_KEYBINDS_COMMUNICATION + weight = WEIGHT_HIGHEST + +/datum/pref/keybinds/communication/admin_help + name = "Admin Help" + description = "Ask an admin for help." + value = "F1" + + legacy_keyname = "admin_help" + +/datum/pref/keybinds/communication/admin_help/down(client/user) + user.adminhelp() + return TRUE + +/datum/pref/keybinds/communication/mentor_help + name = "Mentor Help" + description = "Ask an mentors for help." + value = "F9" + + legacy_keyname = "mentor_help" + +/datum/pref/keybinds/communication/mentor_help/down(client/user) + user.get_mentorhelp() + return TRUE + +/datum/pref/keybinds/communication/say + name = "IC Say" + value = "F3 T" + + legacy_keyname = "Say" + +/datum/pref/keybinds/communication/say/down(client/user) + user.mob.say_wrapper() + return TRUE + +/datum/pref/keybinds/communication/ooc + name = "Out Of Character Say (OOC)" + value = "F2 O" + + legacy_keyname = "OOC" + +/datum/pref/keybinds/communication/ooc/down(client/user) + user.ooc_wrapper() + return TRUE + +/datum/pref/keybinds/communication/looc + name = "Local Out Of Character Say (LOOC)" + value = "L" + + legacy_keyname = "LOOC" + +/datum/pref/keybinds/communication/looc/down(client/user) + user.looc_wrapper() + return TRUE + +/datum/pref/keybinds/communication/me + name = "Custom Emote (/Me)" + value = "F4 M" + + legacy_keyname = "Me" + +/datum/pref/keybinds/communication/me/down(client/user) + user.mob.me_wrapper() + return TRUE diff --git a/code/modules/client/settings/keybinds/emotes.dm b/code/modules/client/settings/keybinds/emotes.dm new file mode 100644 index 000000000000..a939abf0aea7 --- /dev/null +++ b/code/modules/client/settings/keybinds/emotes.dm @@ -0,0 +1,64 @@ +// even tho keybinds prefs domain are part compatible with other pref types, using this in mix was not planed first +// should be ok, but need to keep it in mind while working with keybinds +/datum/pref/keybinds/emote_select + category = PREF_KEYBINDS_EMOTE + weight = WEIGHT_MOB + value_type = PREF_TYPE_SELECT + value = "None" + +/datum/pref/keybinds/emote_select/New() + // will use all currently existing emotes keys in build as possible values + // prefs automatically fallback to default if value is not valid anymore + var/static/list/possible_values + if(!possible_values) + possible_values = list("None") + global.all_emotes_keys // all datums reference one static value instead of list per datum + value_parameters = possible_values + +/datum/pref/keybinds/emote_key + category = PREF_KEYBINDS_EMOTE + weight = WEIGHT_MOB + + var/emote_pref_type + +/datum/pref/keybinds/emote_key/down(client/user) + var/emote = user.prefs.prefs_keybinds[emote_pref_type].value + if(emote == "None") + return + user.mob.emote(emote, intentional = TRUE, fallback_notice = TRUE) + +// copypaste below + +/datum/pref/keybinds/emote_select/num_1 + name = "Emote 1" + +/datum/pref/keybinds/emote_key/num_1 + name = "Emote key 1" + emote_pref_type = /datum/pref/keybinds/emote_select/num_1 + +/datum/pref/keybinds/emote_select/num_2 + name = "Emote 2" + +/datum/pref/keybinds/emote_key/num_2 + name = "Emote key 2" + emote_pref_type = /datum/pref/keybinds/emote_select/num_2 + +/datum/pref/keybinds/emote_select/num_3 + name = "Emote 3" + +/datum/pref/keybinds/emote_key/num_3 + name = "Emote key 3" + emote_pref_type = /datum/pref/keybinds/emote_select/num_3 + +/datum/pref/keybinds/emote_select/num_4 + name = "Emote 4" + +/datum/pref/keybinds/emote_key/num_4 + name = "Emote key 4" + emote_pref_type = /datum/pref/keybinds/emote_select/num_4 + +/datum/pref/keybinds/emote_select/num_5 + name = "Emote 5" + +/datum/pref/keybinds/emote_key/num_5 + name = "Emote key 5" + emote_pref_type = /datum/pref/keybinds/emote_select/num_5 diff --git a/code/modules/client/settings/keybinds/human.dm b/code/modules/client/settings/keybinds/human.dm new file mode 100644 index 000000000000..83f670126667 --- /dev/null +++ b/code/modules/client/settings/keybinds/human.dm @@ -0,0 +1,53 @@ +/datum/pref/keybinds/human + category = PREF_KEYBINDS_HUMAN + weight = WEIGHT_MOB + +/datum/pref/keybinds/human/can_use(client/user) + return ishuman(user.mob) + +/datum/pref/keybinds/human/quick_equip + name = "Quick Equip" + description = "Quickly puts an item in the best slot available" + value = "E" + + legacy_keyname = "quick_equip" + +/datum/pref/keybinds/human/quick_equip/down(client/user) + var/mob/living/carbon/human/H = user.mob + H.quick_equip() + return TRUE + +/datum/pref/keybinds/human/holster + name = "Holster" + description = "Draw or holster weapon." + value = "H" + + legacy_keyname = "holster" + +/datum/pref/keybinds/human/holster/down(client/user) + var/mob/living/carbon/human/H = user.mob + H.holster_weapon() + +/datum/pref/keybinds/human/emote_panel + name = "Emote Panel" + description = "Shows you emote panel." + value = "J" + + legacy_keyname = "emote_panel" + +/datum/pref/keybinds/human/emote_panel/down(client/user) + var/mob/living/carbon/human/H = user.mob + H.emote_panel() + +/datum/pref/keybinds/human/race_ability + name = "Race Ability" + description = "Activates your racial ability." + value = "U" + + legacy_keyname = "race_ability" // or leap + +/datum/pref/keybinds/human/race_ability/down(client/user) + var/mob/living/carbon/human/H = user.mob + var/datum/action/A = locate(H.species.race_ability) in H.actions + if(A) + A.Trigger() diff --git a/code/modules/client/settings/keybinds/living.dm b/code/modules/client/settings/keybinds/living.dm new file mode 100644 index 000000000000..0c9eee898fc1 --- /dev/null +++ b/code/modules/client/settings/keybinds/living.dm @@ -0,0 +1,116 @@ +/datum/pref/keybinds/living + category = PREF_KEYBINDS_HUMAN + weight = WEIGHT_MOB + +/datum/pref/keybinds/living/can_use(client/user) + return isliving(user.mob) + +/datum/pref/keybinds/living/resist + name = "Resist" + description = "Break free of your current state. Handcuffed? On fire? Resist!" + value = "N" + + legacy_keyname = "resist" + +/datum/pref/keybinds/living/resist/down(client/user) + var/mob/living/L = user.mob + L.resist() + return TRUE + +/datum/pref/keybinds/living/toggle_move_intent + name = "Hold to toggle move intent" + description = "Held down to cycle to the other move intent, release to cycle back" + value = "C" + + legacy_keyname = "toggle_move_intent" + +/datum/pref/keybinds/living/toggle_move_intent/down(client/user) + var/mob/living/L = user.mob + L.set_m_intent(L.m_intent == MOVE_INTENT_WALK ? MOVE_INTENT_RUN : MOVE_INTENT_WALK) + return TRUE + +/datum/pref/keybinds/living/toggle_move_intent/up(client/user) + var/mob/living/L = user.mob + L.set_m_intent(L.m_intent == MOVE_INTENT_WALK ? MOVE_INTENT_RUN : MOVE_INTENT_WALK) + return TRUE + +/datum/pref/keybinds/living/drop_item + name = "Drop Item" + value = "Q Northwest" // Northwest - HOME + + legacy_keyname = "drop_item" + +/datum/pref/keybinds/living/drop_item/down(client/user) + var/mob/living/L = user.mob + L.drop_item() + return TRUE + +/datum/pref/keybinds/living/crawl + name = "Crawl" + description = "You lay down/get up" + + legacy_keyname = "crawl" + +/datum/pref/keybinds/living/crawl/down(client/user) + var/mob/living/L = user.mob + L.crawl() + return TRUE + +/datum/pref/keybinds/living/swap_hands + name = "Swap hands" + value = "X Northeast" // Northeast - PAGEUP + + legacy_keyname = "swap_hands" + +/datum/pref/keybinds/living/swap_hands/down(client/user) + var/mob/living/L = user.mob + L.swap_hand() + return TRUE + +/datum/pref/keybinds/living/select_help_intent + name = "Select help intent" + value = "1" + + legacy_keyname = "select_help_intent" + +/datum/pref/keybinds/living/select_help_intent/down(client/user) + if(issilicon(user.mob)) + return + user.mob?.a_intent_change(INTENT_HELP) + return TRUE + +/datum/pref/keybinds/living/select_disarm_intent + name = "Select push intent" + value = "2" + + legacy_keyname = "select_push_intent" + +/datum/pref/keybinds/living/select_disarm_intent/down(client/user) + if(issilicon(user.mob)) + return + user.mob?.a_intent_change(INTENT_PUSH) + return TRUE + +/datum/pref/keybinds/living/select_grab_intent + name = "Select grab intent" + value = "3" + + legacy_keyname = "select_grab_intent" + +/datum/pref/keybinds/living/select_grab_intent/down(client/user) + if(issilicon(user.mob)) + return + user.mob?.a_intent_change(INTENT_GRAB) + return TRUE + +/datum/pref/keybinds/living/select_harm_intent + name = "Select harm intent" + value = "4" + + legacy_keyname = "select_harm_intent" + +/datum/pref/keybinds/living/select_harm_intent/down(client/user) + if(issilicon(user.mob)) + return + user.mob?.a_intent_change(INTENT_HARM) + return TRUE diff --git a/code/modules/client/settings/keybinds/mob.dm b/code/modules/client/settings/keybinds/mob.dm new file mode 100644 index 000000000000..cd8c29fb5bb1 --- /dev/null +++ b/code/modules/client/settings/keybinds/mob.dm @@ -0,0 +1,144 @@ +/datum/pref/keybinds/mob + category = PREF_KEYBINDS_HUMAN + weight = WEIGHT_MOB + +/datum/pref/keybinds/mob/stop_pulling + name = "Stop pulling" + value = "Delete" + + legacy_keyname = "stop_pulling" + +/datum/pref/keybinds/mob/stop_pulling/down(client/user) + var/mob/M = user.mob + if(!M.pulling) + to_chat(user, "You are not pulling anything.") + else + M.stop_pulling() + return TRUE + +/datum/pref/keybinds/mob/cycle_intent_right + name = "Cycle intent right" + value = "G Insert" + + legacy_keyname = "cycle_intent_right" + +/datum/pref/keybinds/mob/cycle_intent_right/down(client/user) + var/mob/M = user.mob + M.a_intent_change(INTENT_HOTKEY_RIGHT) + return TRUE + +/datum/pref/keybinds/mob/cycle_intent_left + name = "Cycle intent left" + value = "F" + + legacy_keyname = "cycle_intent_left" + +/datum/pref/keybinds/mob/cycle_intent_left/down(client/user) + var/mob/M = user.mob + M.a_intent_change(INTENT_HOTKEY_LEFT) + return TRUE + +/datum/pref/keybinds/mob/activate_inhand + name = "Activate in-hand" + description = "Uses whatever item you have inhand" + value = "Z Y Southeast" // Southeast - PAGEDOWN + + legacy_keyname = "activate_inhand" + +/datum/pref/keybinds/mob/activate_inhand/down(client/user) + var/mob/M = user.mob + M.mode() + return TRUE + +/datum/pref/keybinds/mob/target_head_cycle + name = "Target: Cycle head" + value = "Numpad8" + + legacy_keyname = "target_head_cycle" + +/datum/pref/keybinds/mob/target_head_cycle/down(client/user) + user.body_toggle_head() + return TRUE + +/datum/pref/keybinds/mob/target_r_arm + name = "Target: right arm" + value = "Numpad4" + + legacy_keyname = "target_r_arm" + +/datum/pref/keybinds/mob/target_r_arm/down(client/user) + user.body_r_arm() + return TRUE + +/datum/pref/keybinds/mob/target_body_chest + name = "Target: Body" + value = "Numpad5" + + legacy_keyname = "target_body_chest" + +/datum/pref/keybinds/mob/target_body_chest/down(client/user) + user.body_chest() + return TRUE + +/datum/pref/keybinds/mob/target_left_arm + name = "Target: left arm" + value = "Numpad6" + + legacy_keyname = "target_left_arm" + +/datum/pref/keybinds/mob/target_left_arm/down(client/user) + user.body_l_arm() + return TRUE + +/datum/pref/keybinds/mob/target_right_leg + name = "Target: Right leg" + value = "Numpad1" + + legacy_keyname = "target_right_leg" + +/datum/pref/keybinds/mob/target_right_leg/down(client/user) + user.body_r_leg() + return TRUE + +/datum/pref/keybinds/mob/target_body_groin + name = "Target: Groin" + value = "Numpad2" + + legacy_keyname = "target_body_groin" + +/datum/pref/keybinds/mob/target_body_groin/down(client/user) + user.body_groin() + return TRUE + +/datum/pref/keybinds/mob/target_left_leg + name = "Target: left leg" + value = "Numpad3" + + legacy_keyname = "target_left_leg" + +/datum/pref/keybinds/mob/target_left_leg/down(client/user) + user.body_l_leg() + return TRUE + +/datum/pref/keybinds/mob/prevent_movement + name = "Block movement" + description = "Prevents you from moving" + value = "Ctrl" + + legacy_keyname = "block_movement" + +/datum/pref/keybinds/mob/prevent_movement/down(client/user) + user.movement_locked = TRUE + +/datum/pref/keybinds/mob/prevent_movement/up(client/user) + user.movement_locked = FALSE + +/datum/pref/keybinds/mob/click_on_self + name = "Click On Self" + value = "B" + + legacy_keyname = "click_on_self" + +/datum/pref/keybinds/mob/click_on_self/down(client/user) + var/mob/M = user.mob + M.click_on_self() diff --git a/code/modules/client/settings/keybinds/movement.dm b/code/modules/client/settings/keybinds/movement.dm new file mode 100644 index 000000000000..dd5e921a9e95 --- /dev/null +++ b/code/modules/client/settings/keybinds/movement.dm @@ -0,0 +1,35 @@ +/datum/pref/keybinds/movement + category = PREF_KEYBINDS_MOVEMENT + weight = WEIGHT_HIGHEST + +/datum/pref/keybinds/movement/on_update(client/client, old_value) + ..() + client?.update_movement_keybinds() + +/datum/pref/keybinds/movement/north + name = "Move North" + description = "Moves your character north" + value = "W North" + + legacy_keyname = "North" + +/datum/pref/keybinds/movement/south + name = "Move South" + description = "Moves your character south" + value = "S South" + + legacy_keyname = "South" + +/datum/pref/keybinds/movement/west + name = "Move West" + description = "Moves your character left" + value = "A West" + + legacy_keyname = "West" + +/datum/pref/keybinds/movement/east + name = "Move East" + description = "Moves your character east" + value = "D East" + + legacy_keyname = "East" diff --git a/code/modules/client/settings/keybinds/robot.dm b/code/modules/client/settings/keybinds/robot.dm new file mode 100644 index 000000000000..3a89b4e0f267 --- /dev/null +++ b/code/modules/client/settings/keybinds/robot.dm @@ -0,0 +1,67 @@ +/datum/pref/keybinds/robot + category = PREF_KEYBINDS_ROBOT + weight = WEIGHT_ROBOT + +/datum/pref/keybinds/robot/can_use(client/user) + return isrobot(user.mob) + +/datum/pref/keybinds/robot/moduleone + name = "Toggle module 1" + description = "Equips or unequips the first module" + value = "1" + + legacy_keyname = "module_one" + +/datum/pref/keybinds/robot/moduleone/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.toggle_module(1) + return TRUE + +/datum/pref/keybinds/robot/moduletwo + name = "Toggle module 2" + description = "Equips or unequips the second module" + value = "2" + + legacy_keyname = "module_two" + +/datum/pref/keybinds/robot/moduletwo/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.toggle_module(2) + return TRUE + +/datum/pref/keybinds/robot/modulethree + name = "Toggle module 3" + description = "Equips or unequips the third module" + value = "3" + + legacy_keyname = "module_three" + +/datum/pref/keybinds/robot/modulethree/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.toggle_module(3) + return TRUE + +/datum/pref/keybinds/robot/intent_cycle + name = "Cycle intent left" + description = "Cycles the intent left" + value = "4" + + legacy_keyname = "cycle_intent" + +/datum/pref/keybinds/robot/intent_cycle/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.a_intent_change(INTENT_HOTKEY_LEFT) + return TRUE + +/datum/pref/keybinds/robot/unequip_module + name = "Unequip module" + description = "Unequips the active module" + value = "Q" + + legacy_keyname = "unequip_module" + +/datum/pref/keybinds/robot/unequip_module/down(client/user) + var/mob/living/silicon/robot/R = user.mob + if(R.module) + R.uneq_active() + return TRUE diff --git a/code/modules/client/settings/player/_player.dm b/code/modules/client/settings/player/_player.dm new file mode 100644 index 000000000000..87403af3d7d4 --- /dev/null +++ b/code/modules/client/settings/player/_player.dm @@ -0,0 +1,2 @@ +/datum/pref/player + domain = PREF_DOMAIN_PLAYER diff --git a/code/modules/client/settings/player/audio.dm b/code/modules/client/settings/player/audio.dm new file mode 100644 index 000000000000..35f5d05eff2d --- /dev/null +++ b/code/modules/client/settings/player/audio.dm @@ -0,0 +1,99 @@ +// do not use these prefs dirrectly, see /code/game/sound.dm for sound methods + +/datum/pref/player/audio + category = PREF_PLAYER_AUDIO + value_type = PREF_TYPE_RANGE + value_parameters = list(0, 100) + + var/volume_channel + +/datum/pref/player/audio/on_update(client/client, old_value) + client?.mob?.playsound_local(null, 'sound/weapons/saberon.ogg', volume_channel, vary = FALSE, channel = CHANNEL_VOLUMETEST) + +/datum/pref/player/audio/lobby + name = "Музыка в лобби" + description = "Громкость музыки в лобби игры." + value = 100 + + volume_channel = VOL_LOBBY_MUSIC + +/datum/pref/player/audio/lobby/on_update(client/client, old_value) + client?.mob?.playsound_music_update_volume(VOL_LOBBY_MUSIC, CHANNEL_MUSIC) + ..() + +/datum/pref/player/audio/ambient + name = "Эмбиент" + description = "Громкость эффектов окружающей среды - звуки станции, музыка отделов." + value = 100 + + volume_channel = VOL_AMBIENT + +/datum/pref/player/audio/ambient/on_update(client/client, old_value) + client?.mob?.playsound_music_update_volume(VOL_AMBIENT, CHANNEL_AMBIENT) + client?.mob?.playsound_music_update_volume(VOL_AMBIENT, CHANNEL_AMBIENT_LOOP) + ..() + +/datum/pref/player/audio/effects + name = "Эффекты" + description = "Громкость игровых эффектов" + value = 100 + + volume_channel = VOL_EFFECTS_MASTER + +/datum/pref/player/audio/spam_effects + name = "Модификатор спам-эффектов" + description = "Дополнительный модификатор громкости для некоторых, возможно надоедливых, игровых эффектов - теслы, эммитеры, хонк-и и некоторые другие." + value = 100 + + volume_channel = VOL_SPAM_EFFECTS + +/datum/pref/player/audio/voice_announcements + name = "Голосовые аннонсы" + description = "Громкость озвученных игровых аудио-аннонсов, вроде оповещений с ЦК." + value = 100 + + volume_channel = VOL_VOICE_ANNOUNCEMENTS + +/datum/pref/player/audio/instruments + name = "Музыкальные инструменты" + description = "Громкость музыки, проигрываемой музыкальными инструментами - пианино, гитара и т.п. Джубокс не относится к этой категории." + value = 100 + + volume_channel = VOL_MUSIC_INSTRUMENTS + +/datum/pref/player/audio/notifications + name = "Уведомления" + description = "Громкость различных важных уведомлений игрока - личные сообщения админов и менторов, запросы на воскрешение." + value = 100 + + volume_channel = VOL_NOTIFICATIONS + +/datum/pref/player/audio/admin_sounds + name = "Админские звуки" + description = "Музыка и звуки, проигрываемые администраторами." + value = 100 + + volume_channel = VOL_ADMIN_SOUNDS + +/datum/pref/player/audio/admin_sounds/on_update(client/client, old_value) + client?.mob?.playsound_music_update_volume(VOL_ADMIN_SOUNDS, CHANNEL_ADMIN) + ..() + +/datum/pref/player/audio/jukebox + name = "Jukebox" + description = "Громкость музыкального автомата." + value = 100 + + volume_channel = VOL_JUKEBOX + +/datum/pref/player/audio/jukebox/on_update(client/client, old_value) + ..() + var/datum/media_manager/media = client?.media + if(istype(media)) // will be updated in "/mob/living/Login()" if changed in lobby. + media.update_volume() + + if(!value && old_value) // only play/stop if last change is a mute or unmute state. + media.stop_music() + else if(value && !old_value) + media.update_music() + diff --git a/code/modules/client/settings/player/chat.dm b/code/modules/client/settings/player/chat.dm new file mode 100644 index 000000000000..f29a669971d8 --- /dev/null +++ b/code/modules/client/settings/player/chat.dm @@ -0,0 +1,117 @@ +/datum/pref/player/chat + category = PREF_PLAYER_CHAT + +/* ooc chat settings */ + +/datum/pref/player/chat/show_ckey + name = "Показывать кей в LOOC/Ghost" + description = "Показать или скрыть ваш никнейм (имя Byond-аккаунта), когда вы общаетесь в LOOC и Ghost чатах." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/chat/ooccolor + name = "Цвет имени OOC" + description = "Ваш персональный цвет никнейма в OOC чате. Не даст поставить слишком темные или светлые и не читаемые цвета." + value_type = PREF_TYPE_HEX + value = OOC_COLOR_SUPPORTER + + supporters_only = TRUE + +/datum/pref/player/chat/ooccolor/sanitize_value(new_value) + . = ..() + if(.) + . = color_lightness_clamp(., 20, 80) // so people don't abuse unreadable colors + +/datum/pref/player/chat/aooccolor + name = "Цвет текста OOC" + description = "Ваш персональный цвет в OOC чате. Не даст поставить слишком темные или светлые и не читаемые цвета." + value_type = PREF_TYPE_HEX + value = OOC_COLOR_ADMIN + + admins_only = TRUE + +/datum/pref/player/chat/aooccolor/sanitize_value(new_value) + . = ..() + if(.) + . = color_lightness_clamp(., 20, 80) // so people don't abuse unreadable colors + +/datum/pref/player/chat/ooc + name = "OOC чат" + description = "Показывать или скрыть Out of Character чат - общий серверный не игровой чат." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/chat/looc + name = "LOOC чат" + description = "Показывать или скрыть Local OOC чат - как и общий серверный не игровой чат, но действует в пределах экрана." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/chat/dead + name = "Чат мертвых" + description = "Показывать или скрыть общий чат мертвых и обсерверов." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/* ghost chat settings */ + +/datum/pref/player/chat/ghostears + name = "Призрачные уши" + description = "Включить слышимость всех разговоров от других мобов и персонажей в игре, когда вы призрак. Если выключено - вы будете слышать только в пределах экрана." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/chat/ghostsight + name = "Призрачное зрение" + description = "Включить видимость всех эмоутов от других мобов и персонажей в игре, когда вы призрак. Если выключено - вы будете видеть только в пределах экрана." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/chat/ghostradio + name = "Призрачное радио" + description = "Включить слышимость всех разговоров по радио на станции будучи призраком. Если выключено - вы будете слышать только те источники радио, которые в пределах экрана." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/chat/ghostantispam + name = "Призрачный антиспам" + description = "Включите, если вы хотите подавить незначительные автоматические сообщения за пределами экрана, будь то эмоуты или разговоры, если их инициатор не игрок." + value_type = PREF_TYPE_BOOLEAN + value = FALSE + +/* admin chat settings */ + +/datum/pref/player/chat/attack_log + name = "Логи атак" + value_type = PREF_TYPE_SELECT + value = ATTACK_LOG_BY_CLIENT + value_parameters = list( + ATTACK_LOG_DISABLED = "Выключены", + ATTACK_LOG_BY_CLIENT = "Только на клиентов", + ATTACK_LOG_ALL = "Все" + ) + + admins_only = TRUE + +/datum/pref/player/chat/debug_log + name = "Дебаг логи" + value_type = PREF_TYPE_BOOLEAN + value = FALSE + + admins_only = TRUE + +/datum/pref/player/chat/radio // how is it different with ghostradio??? + name = "Радио чат" + description = "Переключает видимость радиосообщений с радио и спикеров." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + + admins_only = TRUE + +/datum/pref/player/chat/prayers + name = "Молитвы" + description = "Показать/скрыть молитвы игроков" + value_type = PREF_TYPE_BOOLEAN + value = TRUE + + admins_only = TRUE diff --git a/code/modules/client/settings/player/display.dm b/code/modules/client/settings/player/display.dm new file mode 100644 index 000000000000..7b614c43d229 --- /dev/null +++ b/code/modules/client/settings/player/display.dm @@ -0,0 +1,68 @@ +/datum/pref/player/display + category = PREF_PLAYER_DISPLAY + +/datum/pref/player/display/fps + name = "Кадры в секунду" + description = "Может сильно влиять на производительность игры. Выставьте значение меньше, если испытываете проблемы." + value_type = PREF_TYPE_RANGE + value = RECOMMENDED_FPS + value_parameters = list(1, 240) + +/datum/pref/player/display/fps/on_update(client/client, old_value) + if(client) + client.fps = value + +/datum/pref/player/display/fullscreen + name = "Полноэкранный режим" + value_type = PREF_TYPE_BOOLEAN + value = FALSE + +/datum/pref/player/display/fullscreen/on_update(client/client, old_value) + client?.update_fullscreen() + +/datum/pref/player/display/auto_fit_viewport + name = "Подгонять область просмотра" + description = "Убирает вертикальные черные полосы, автоматически подстраивая ширину игровой области под высоту." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/display/auto_fit_viewport/on_update(client/client, old_value) + if(value && client && !isnewplayer(client.mob)) // if new value requires to fit + client.fit_viewport() + +/datum/pref/player/display/auto_zoom + name = "Автомасштабирование" + description = "Подобрать масштаб автоматически, чтобы заполнить весь экран." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/display/auto_zoom/on_update(client/client, old_value) + client?.update_map_zoom() + +/datum/pref/player/display/zoom + name = "Масштабирование" + description = {"Масштабирование основного игрового экрана. Значения, кратные 100 (100, 200, 300, 400), дают лучшее качество спрайтов на любых методах масштабирования. В противном случае рекомендуется использовать автомасштабирование. +Эта опция игнорируется, если включено Автомасштабирование!"} + value_type = PREF_TYPE_RANGE + value = 100 + value_parameters = list(50, 400, 50, "%") + +/datum/pref/player/display/zoom/on_update(client/client, old_value) + client?.update_map_zoom() + +/datum/pref/player/display/zoom_mode + name = "Метод масштабирования" + description = {"Метод сглаживания, используемый при масштабировании спрайтов. + +Nearest Neighbor - даёт наибольшую четкость изображения, но при не крастных 100 масштабированиях (в т.ч. автомасштабе) может вызывать небольшие артефакты. + +Point Sampling - работает одинаково хорошо на любом масштабе, но делает изображение менее четким."} + value_type = PREF_TYPE_SELECT + value = SCALING_METHOD_DISTORT + value_parameters = list( + SCALING_METHOD_DISTORT = "Nearest Neighbor", + SCALING_METHOD_NORMAL = "Point Sampling" + ) + +/datum/pref/player/display/zoom_mode/on_update(client/client, old_value) + client?.update_map_zoom() diff --git a/code/modules/client/settings/player/effects.dm b/code/modules/client/settings/player/effects.dm new file mode 100644 index 000000000000..dc737ef1aa9b --- /dev/null +++ b/code/modules/client/settings/player/effects.dm @@ -0,0 +1,81 @@ +/datum/pref/player/effects + category = PREF_PLAYER_EFFECTS + +/datum/pref/player/effects/ambientocclusion + name = "Окружающее затенение" + description = "Добавляет затенение для объектов в игре, помогает придать объем изображению." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/effects/ambientocclusion/on_update(client/client, old_value) + client?.update_plane_masters(/atom/movable/screen/plane_master/game_world) + +/datum/pref/player/effects/parallax + name = "Качество параллакса" + description = "Качество анимации фонов в космосе. На высоких настройках может негативно влиять на производительность." + value_type = PREF_TYPE_SELECT + value = PARALLAX_HIGH + value_parameters = list( + PARALLAX_DISABLE = "Выключено", + PARALLAX_LOW = "Низкое", + PARALLAX_MED = "Среднее", + PARALLAX_HIGH = "Высокое", + PARALLAX_INSANE = "Безумное" + ) + +/datum/pref/player/effects/parallax/on_update(client/client, old_value) + if(client?.mob?.hud_used) + client.mob.hud_used.update_parallax_pref() + +/datum/pref/player/effects/glowlevel // aka light sources bloom + name = "Уровень свечения" + description = "Добавляет легкий блюр источникам света. Подберите значение на свой вкус." + value_type = PREF_TYPE_SELECT + value = GLOW_MED + value_parameters = list( + GLOW_DISABLE = "Выключено", + GLOW_LOW = "Низкое", + GLOW_MED = "Среднее", + GLOW_HIGH = "Высокое" + ) + +/datum/pref/player/effects/glowlevel/on_update(client/client, old_value) + client?.update_plane_masters(/atom/movable/screen/plane_master/lamps_selfglow) + +/datum/pref/player/effects/lampsexposure // still idk how to name it properly, spot light effect? + name = "Направленный свет от ламп" + description = "Визуально улучшает свет от ламп. Может влиять на производительность." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/effects/lampsexposure/on_update(client/client, old_value) + client?.update_plane_masters(/atom/movable/screen/plane_master/exposure) + +/datum/pref/player/effects/lampsglare + name = "Блик на источниках света" + description = "На случай, если вы фанат Джей Джей Абрамса." + value_type = PREF_TYPE_BOOLEAN + value = FALSE + +/datum/pref/player/effects/lampsglare/on_update(client/client, old_value) + client?.update_plane_masters(/atom/movable/screen/plane_master/lamps_glare) + +/datum/pref/player/effects/legacy_blur + name = "Старый блюр зрения" + description = "Использовать старый, менее затратный для производительности, эффект для повреждения/помех зрения персонажа." + value_type = PREF_TYPE_BOOLEAN + value = FALSE + +/datum/pref/player/effects/legacy_blur/on_update(client/client, old_value) + client?.update_plane_masters(/atom/movable/screen/plane_master/game_world) + +/datum/pref/player/effects/lobbyanimation + name = "Анимация экрана лобби" + description = "Включает анимированное лобби. На некоторых системах может лагать." + value_type = PREF_TYPE_BOOLEAN + value = FALSE + +/datum/pref/player/effects/lobbyanimation/on_update(client/client, old_value) + if(client && isnewplayer(client.mob)) + var/mob/dead/new_player/M = client.mob + M.show_titlescreen() diff --git a/code/modules/client/settings/player/game.dm b/code/modules/client/settings/player/game.dm new file mode 100644 index 000000000000..56a7f7e5eac0 --- /dev/null +++ b/code/modules/client/settings/player/game.dm @@ -0,0 +1,53 @@ +/datum/pref/player/game + category = PREF_PLAYER_GAME + +// If hotkey mode is enabled, then clicking the map will automatically +// unfocus the text bar. This removes the red color from the text bar +// so that the visual focus indicator matches reality. +/datum/pref/player/game/hotkey_mode + name = "Hotkey mode" + description = {"Если включено - фокус клавиатуры будет оставаться на игре. Рекомендуется, если вы используете WASD для движения и горячие клавиши. +Если выключено - фокус будет оставаться на чате. Этот вариант больше подходит тем, кто хочет использовать стрелочки для движения и печатать на ходу."} + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/game/hotkey_mode/on_update(client/client, old_value) + if(value) + winset(client, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") + else + winset(client, null, "input.focus=true input.background-color=[COLOR_INPUT_DISABLED]") + +/datum/pref/player/game/melee_animation // todo: not only melee currently + name = "Анимация ближнего боя" + description = "Показывать или нет анимацию рукопашных атак." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/game/progressbar + name = "Индикатор прогресса" + description = "Показывать или нет анимированную шкалу для действий." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/game/endroundarena + name = "Арена конца раунда" + description = "Если включено - по окончанию раунда и до момента рестарта вы будете телепортированы на специальную гладиаторскую арену, где сможете выпустить весь накопившийся за раунд пар." + value_type = PREF_TYPE_BOOLEAN + value = FALSE + +/datum/pref/player/game/ghost_skin + name = "Вид призрака" + description = {"Вид вашего приведения, если вы умерли или зашли в раунд как обсервер. +Выбор флаффа будет работать только в том случае, если у вас имеется залитый и одобренный флафф соответствующего типа."} + value_type = PREF_TYPE_SELECT + value = GHOST_SKIN_CHARACTER + value_parameters = list( + GHOST_SKIN_CHARACTER = "Персонаж", + GHOST_SKIN_GHOST = "Приведение", + GHOST_SKIN_FLUFF = "Флафф" + ) + +/datum/pref/player/game/ghost_skin/on_update(client/client, old_value) + if(client && isobserver(client.mob)) + var/mob/dead/observer/O = client.mob + O.update_skin() diff --git a/code/modules/client/settings/player/meta.dm b/code/modules/client/settings/player/meta.dm new file mode 100644 index 000000000000..f06648d2e0f6 --- /dev/null +++ b/code/modules/client/settings/player/meta.dm @@ -0,0 +1,53 @@ +// for special cases where we handle some prefs differently +// these settings are hidden from client settings menu + +/datum/pref/player/meta + +/datum/pref/player/meta/lastchangelog + name = "lastchangelog" + value = "" + value_type = PREF_TYPE_TEXT + +/datum/pref/player/meta/default_slot + name = "default_slot" + value = 1 + value_type = PREF_TYPE_CUSTOM + +/datum/pref/player/meta/default_slot/sanitize_value(new_value, client/client) + if(!client) // for automatic clientless updates in the future + return 1 + + return sanitize_integer(new_value, 1, GET_MAX_SAVE_SLOTS(client), initial(new_value)) + +/datum/pref/player/meta/random_slot + name = "random_slot" + value = FALSE + value_type = PREF_TYPE_BOOLEAN + +// i don't want to create pref for every emote, and don't want to update prefs with any changes to emotes / emote panel +// emotes in panel are opt-out so this is a list of disabled emotes for the emote panel, empty by default, +// and we don't need to touch this in the future - sanitize will update it with any changes +// +// i don't like how this looks, but i have no better idea how to rewrite it +/datum/pref/player/meta/disabled_emotes_emote_panel + name = "disabled_emotes" + value = "" + value_type = PREF_TYPE_CUSTOM + +/datum/pref/player/meta/disabled_emotes_emote_panel/sanitize_value(new_value, client/client) + var/list/new_list + if(islist(new_value)) + new_list = new_value + else + new_list = params2list(new_value) + + if(!length(new_list)) + return "" + + var/list/valid_emotes + // clean any not valid (probably removed) emotes + for(var/emote in new_list) + if(emote in global.emotes_for_emote_panel) + valid_emotes += emote + + return list2params(valid_emotes) diff --git a/code/modules/client/settings/player/ui.dm b/code/modules/client/settings/player/ui.dm new file mode 100644 index 000000000000..39662141e8b1 --- /dev/null +++ b/code/modules/client/settings/player/ui.dm @@ -0,0 +1,96 @@ +/datum/pref/player/ui + category = PREF_PLAYER_UI + +/datum/pref/player/ui/runechat + name = "Runechat" + description = "Чат над головой персонажей." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/ui/ui_style + name = "Стиль UI" + description = "Стиль интерфейса игры." + value_type = PREF_TYPE_SELECT + value = UI_STYLE_WHITE + value_parameters = list(UI_STYLE_WHITE, UI_STYLE_MIDNIGHT, UI_STYLE_OLD, UI_STYLE_ORANGE) + +/datum/pref/player/ui/ui_style/on_update(client/client, old_value) + // check if current hud customizable and we can change it + // borgs, aliens, etc. use their own hud we should not touch + // todo: we can look for updates by copy_flags + var/datum/hud/current_style = client?.mob?.hud_used?.ui_style + if(current_style in global.customizable_ui_styles) + client.mob.hud_used.ui_style = global.available_ui_styles[value] + client.mob.refresh_hud() + +/datum/pref/player/ui/ui_style_color + name = "Цвет UI" + description = "Цвет интерфейса игры, опция лучше всего работает с белым стилем." + value_type = PREF_TYPE_HEX + value = "#ffffff" + +/datum/pref/player/ui/ui_style_color/on_update(client/client, old_value) + // same, don't color special huds + var/datum/hud/current_style = client?.mob?.hud_used?.ui_style + if(current_style in global.customizable_ui_styles) + client.mob.hud_used.ui_color = value + client.mob.refresh_hud() + +/datum/pref/player/ui/ui_style_opacity + name = "Прозрачность UI" + description = "Прозрачность интерфейса игры." + value_type = PREF_TYPE_RANGE + value = 0 + value_parameters = list(0, 100) + +/datum/pref/player/ui/ui_style_opacity/on_update(client/client, old_value) + var/datum/hud/current_style = client?.mob?.hud_used?.ui_style + if(current_style in global.customizable_ui_styles) + client.mob.hud_used.ui_alpha = 255 - floor(255*value/100) + client.mob.refresh_hud() + +/datum/pref/player/ui/outline + name = "Подсветка предметов" + description = "По наведению мышью на предмет в игре, у него появится соответствующий контур." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/ui/outline_color + name = "Цвет подсветки" + value_type = PREF_TYPE_HEX + value = "#33ccff" + +/datum/pref/player/ui/tooltip + name = "Всплывающая подсказка" + description = "Подсказка в верхней части экрана, появляющаяся по наведению мышью на предмет в игре." + value_type = PREF_TYPE_BOOLEAN + value = TRUE + +/datum/pref/player/ui/tooltip/on_update(client/client, old_value) + client.tooltip.set_state(value) + +// i don't understand why we need it in preferences, pls don't add more fonts or styles preferences like this +/datum/pref/player/ui/tooltip_font + name = "Шрифт подсказки" + value_type = PREF_TYPE_SELECT + value = FONT_SMALL_FONTS + value_parameters = list( + FONT_SYSTEM, + FONT_FIXEDSYS, + FONT_SMALL_FONTS, + FONT_TIMES_NEW_ROMAN, + FONT_SERIF, + FONT_VERDANA + ) + +/datum/pref/player/ui/tooltip_size + name = "Размер подсказки" + value_type = PREF_TYPE_RANGE + value = 8 + value_parameters = list(1, 15) + +/datum/pref/player/ui/tgui_lock + name = "TGUI только на основном мониторе" + description = "Блокирует перемещение окон tgui за пределы экрана." + value_type = PREF_TYPE_BOOLEAN + value = FALSE diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index 651303df1e8e..f156c6abea0e 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -46,11 +46,9 @@ if(!(next_move_dir_sub & movement)) next_move_dir_add |= movement - // Client-level keybindings are ones anyone should be able to do at any time - // Things like taking screenshots, hitting tab, and adminhelps. - var/AltMod = keys_held["Alt"] ? "Alt" : "" - var/CtrlMod = keys_held["Ctrl"] ? "Ctrl" : "" - var/ShiftMod = keys_held["Shift"] ? "Shift" : "" + var/AltMod = keys_held["Alt"] ? "Alt+" : "" + var/CtrlMod = keys_held["Ctrl"] ? "Ctrl+" : "" + var/ShiftMod = keys_held["Shift"] ? "Shift+" : "" var/full_key switch(_key) if("Alt", "Ctrl", "Shift") @@ -61,16 +59,16 @@ key_combos_held[_key] = full_key else full_key = _key + + if(findtext(full_key, "+", -1)) + full_key = copytext(full_key, 1, -1) + var/keycount = 0 - for(var/kb_name in prefs.key_bindings[full_key]) + for(var/datum/pref/keybinds/kb as anything in prefs.key_bindings_by_key[full_key]) keycount++ - var/datum/keybinding/kb = global.keybindings_by_name[kb_name] if(kb.can_use(src) && kb.down(src) && keycount >= MAX_COMMANDS_PER_KEY) break - holder?.key_down(full_key, src) - mob.key_down(full_key, src) - /client/verb/keyUp(_key as text) set instant = TRUE set hidden = TRUE @@ -92,9 +90,6 @@ // We don't do full key for release, because for mod keys you // can hold different keys and releasing any should be handled by the key binding specifically - for (var/kb_name in prefs.key_bindings[_key]) - var/datum/keybinding/kb = global.keybindings_by_name[kb_name] + for(var/datum/pref/keybinds/kb as anything in prefs.key_bindings_by_key[_key]) if(kb.can_use(src) && kb.up(src)) break - holder?.key_up(_key, src) - mob.key_up(_key, src) diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm index 19de92be004c..a0b47cf45ffe 100644 --- a/code/modules/keybindings/setup.dm +++ b/code/modules/keybindings/setup.dm @@ -1,9 +1,5 @@ // Set a client's focus to an object and override these procs on that object to let it handle keypresses -/datum/proc/key_down(key, client/user) // Called when a key is pressed down initially - return -/datum/proc/key_up(key, client/user) // Called when a key is released - return /datum/proc/keyLoop(client/user) // Called once every frame set waitfor = FALSE return @@ -24,23 +20,7 @@ winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") - update_special_keybinds() - -// byond bug ID:2694120 -/client/verb/reset_macros_wrapper() - set category = "OOC" - set name = "Fix keybindings" - - reset_macros() - -/client/proc/reset_macros(skip_alert = FALSE) - var/ans - if(!skip_alert) - ans = tgui_alert(src, "Change your keyboard language to ENG and press Ok", "Reset macros") - - if(skip_alert || ans == "Ok") - set_macros() - to_chat(src, "Keybindings were fixed") // not yet but set_macros works fast enough + update_movement_keybinds() /** * Manually clears any held keys, in case due to lag or other undefined behavior a key gets stuck. diff --git a/code/modules/mob/dead/new_player/lobby.dm b/code/modules/mob/dead/new_player/lobby.dm index 1a0b244ff481..2796ad4d89da 100644 --- a/code/modules/mob/dead/new_player/lobby.dm +++ b/code/modules/mob/dead/new_player/lobby.dm @@ -122,6 +122,7 @@ var/global/lobby_screen = "lobby"
SETUP "} + dat += "
" if(config.alt_lobby_menu) dat += {"JOIN"} @@ -136,6 +137,7 @@ var/global/lobby_screen = "lobby" dat += {"[has_quality ? QUALITY_READY : QUALITY_NOT_READY]"} dat += {"OBSERVE"} + dat += {"SETTINGS"} dat += "

" dat += {"CHANGELOG"} @@ -143,7 +145,7 @@ var/global/lobby_screen = "lobby" if(global.custom_lobby_image) dat += {""} - else if (client.prefs.lobbyanimation) + else if (client.prefs.get_pref(/datum/pref/player/effects/lobbyanimation)) dat += {"