diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 793d131faaa..8eceebe02b7 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -91,6 +91,8 @@ #define MAX_KEYPRESS_COMMANDLENGTH 16 ///Maximum keys that can be bound to one button #define MAX_COMMANDS_PER_KEY 5 +///Maximum keys per keybind +#define MAX_KEYS_PER_KEYBIND 3 ///Max amount of keypress messages per second over two seconds before client is autokicked #define MAX_KEYPRESS_AUTOKICK 50 ///Length of held key rolling buffer diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index f6f08e5d6d4..773cba1c1e5 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -50,19 +50,23 @@ GLOB.materials_list[D.id] = D sortList(GLOB.materials_list, /proc/cmp_typepaths_asc) - // Keybindings + // Keybindings (classic) for(var/KB in subtypesof(/datum/keybinding)) var/datum/keybinding/keybinding = KB - if(!initial(keybinding.key)) + if(!initial(keybinding.hotkey_keys)) continue var/datum/keybinding/instance = new keybinding - GLOB.keybindings_by_name[initial(instance.name)] = instance - if (!GLOB.keybinding_list_by_key[initial(instance.key)]) - GLOB.keybinding_list_by_key[initial(instance.key)] = list() - GLOB.keybinding_list_by_key[initial(instance.key)] += instance.name - // Sort all the keybindings by their weight - for(var/key in GLOB.keybinding_list_by_key) - GLOB.keybinding_list_by_key[key] = sortList(GLOB.keybinding_list_by_key[key]) + GLOB.keybindings_by_name[instance.name] = instance + + // Classic + if(LAZYLEN(instance.classic_keys)) + for(var/bound_key in instance.classic_keys) + LAZYADD(GLOB.classic_keybinding_list_by_key[bound_key], list(instance.name)) + + // Hotkey + if(LAZYLEN(instance.hotkey_keys)) + for(var/bound_key in instance.hotkey_keys) + LAZYADD(GLOB.hotkey_keybinding_list_by_key[bound_key], list(instance.name)) GLOB.emote_list = init_emote_list() diff --git a/code/_globalvars/lists/client.dm b/code/_globalvars/lists/client.dm index b37c2a81101..5181d870c4f 100644 --- a/code/_globalvars/lists/client.dm +++ b/code/_globalvars/lists/client.dm @@ -1,2 +1,21 @@ -GLOBAL_LIST_EMPTY(keybinding_list_by_key) +GLOBAL_LIST_EMPTY(classic_keybinding_list_by_key) +GLOBAL_LIST_EMPTY(hotkey_keybinding_list_by_key) GLOBAL_LIST_EMPTY(keybindings_by_name) + +// This is a mapping from JS keys to Byond - ref: https://keycode.info/ +GLOBAL_LIST_INIT(_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" + )) diff --git a/code/datums/keybinding/_keybindings.dm b/code/datums/keybinding/_keybindings.dm index eeb5eed7853..ac9c11d1af9 100644 --- a/code/datums/keybinding/_keybindings.dm +++ b/code/datums/keybinding/_keybindings.dm @@ -1,11 +1,19 @@ /datum/keybinding - var/key - var/name - var/full_name - var/description = "" - var/category = CATEGORY_MISC - var/weight = WEIGHT_LOWEST + var/list/hotkey_keys + var/list/classic_keys + var/name + var/full_name + var/description = "" + var/category = CATEGORY_MISC + var/weight = WEIGHT_LOWEST + var/keybind_signal +/datum/keybinding/New() + + // Default keys to the master "hotkey_keys" + if(LAZYLEN(hotkey_keys) && !LAZYLEN(classic_keys)) + classic_keys = hotkey_keys.Copy() + /datum/keybinding/proc/down(client/user) return FALSE diff --git a/code/datums/keybinding/admin.dm b/code/datums/keybinding/admin.dm index 07deb6a7817..833a57254f7 100644 --- a/code/datums/keybinding/admin.dm +++ b/code/datums/keybinding/admin.dm @@ -1,40 +1,40 @@ /datum/keybinding/admin - category = CATEGORY_ADMIN - weight = WEIGHT_ADMIN + category = CATEGORY_ADMIN + weight = WEIGHT_ADMIN /datum/keybinding/admin/admin_say - key = "F3" - name = "admin_say" - full_name = "Admin say" - description = "Talk with other admins." + hotkey_keys = list("F3") + 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 + user.get_admin_say() + return TRUE /datum/keybinding/admin/admin_ghost - key = "F5" - name = "admin_ghost" - full_name = "Aghost" - description = "Go ghost" + hotkey_keys = list("F5") + name = "admin_ghost" + full_name = "Aghost" + description = "Go ghost" /datum/keybinding/admin/admin_ghost/down(client/user) - user.admin_ghost() - return TRUE + user.admin_ghost() + return TRUE /datum/keybinding/admin/player_panel_new - key = "F6" - name = "player_panel_new" - full_name = "Player Panel New" - description = "Opens up the new player panel" + 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 - key = "F7" + hotkey_keys = list("F7") name = "toggle_buildmode_self" full_name = "Toggle Buildmode Self" description = "Toggles buildmode" @@ -44,7 +44,7 @@ return TRUE /datum/keybinding/admin/stealthmode - key = "Ctrl-F8" + hotkey_keys = list("CtrlF8") name = "stealth_mode" full_name = "Stealth mode" description = "Enters stealth mode" @@ -54,7 +54,7 @@ return TRUE /datum/keybinding/admin/invisimin - key = "F8" + hotkey_keys = list("F8") name = "invisimin" full_name = "Admin invisibility" description = "Toggles ghost-like invisibility (Don't abuse this)" @@ -64,7 +64,7 @@ return TRUE /datum/keybinding/admin/deadsay - key = "F10" + hotkey_keys = list("F10") name = "dsay" full_name = "deadsay" description = "Allows you to send a message to dead chat" diff --git a/code/datums/keybinding/carbon.dm b/code/datums/keybinding/carbon.dm index 98bfff54c71..6a65c2b6b13 100644 --- a/code/datums/keybinding/carbon.dm +++ b/code/datums/keybinding/carbon.dm @@ -4,8 +4,9 @@ /datum/keybinding/carbon/toggle_throw_mode - key = "R" - name = "toggle_throw_mode" + hotkey_keys = list("R") + classic_keys = list("Southwest") // END + name = "toggle_throw_mode" full_name = "Toggle throw mode" description = "Toggle throwing the current item or not." category = CATEGORY_CARBON @@ -19,19 +20,21 @@ /datum/keybinding/carbon/select_help_intent - key = "1" + hotkey_keys = list("1") name = "select_help_intent" full_name = "Select help intent" description = "" category = CATEGORY_CARBON /datum/keybinding/carbon/select_help_intent/down(client/user) + if(iscyborg(user.mob)) + return FALSE user.mob?.a_intent_change(INTENT_HELP) return TRUE /datum/keybinding/carbon/select_disarm_intent - key = "2" + hotkey_keys = list("2") name = "select_disarm_intent" full_name = "Select disarm intent" description = "" @@ -43,7 +46,7 @@ /datum/keybinding/carbon/select_grab_intent - key = "3" + hotkey_keys = list("3") name = "select_grab_intent" full_name = "Select grab intent" description = "" @@ -55,12 +58,14 @@ /datum/keybinding/carbon/select_harm_intent - key = "4" + hotkey_keys = list("4") name = "select_harm_intent" full_name = "Select harm intent" description = "" category = CATEGORY_CARBON /datum/keybinding/carbon/select_harm_intent/down(client/user) + if(iscyborg(user.mob)) + return FALSE user.mob?.a_intent_change(INTENT_HARM) return TRUE diff --git a/code/datums/keybinding/client.dm b/code/datums/keybinding/client.dm index 2190c922e5b..b2ae7609cb5 100644 --- a/code/datums/keybinding/client.dm +++ b/code/datums/keybinding/client.dm @@ -1,35 +1,35 @@ /datum/keybinding/client - category = CATEGORY_CLIENT - weight = WEIGHT_HIGHEST + category = CATEGORY_CLIENT + weight = WEIGHT_HIGHEST /datum/keybinding/client/admin_help - key = "F1" - name = "admin_help" - full_name = "Admin Help" - description = "Ask an admin for 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.get_adminhelp() - return TRUE + user.get_adminhelp() + return TRUE /datum/keybinding/client/screenshot - key = "F2" - name = "screenshot" - full_name = "Screenshot" - description = "Take a screenshot." + hotkey_keys = list("F2") + 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 + winset(user, null, "command=.screenshot [!user.keys_held["shift"] ? "auto" : ""]") + return TRUE /datum/keybinding/client/minimal_hud - key = "F12" - name = "minimal_hud" - full_name = "Minimal HUD" - description = "Hide most HUD features" + 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 + user.mob.button_pressed_F12() + return TRUE diff --git a/code/datums/keybinding/human.dm b/code/datums/keybinding/human.dm index 9bdeb506082..adaa0f2b1dd 100644 --- a/code/datums/keybinding/human.dm +++ b/code/datums/keybinding/human.dm @@ -1,37 +1,37 @@ /datum/keybinding/human - category = CATEGORY_HUMAN - weight = WEIGHT_MOB + category = CATEGORY_HUMAN + weight = WEIGHT_MOB /datum/keybinding/human/quick_equip - key = "E" + 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 + var/mob/living/carbon/human/H = user.mob + H.quick_equip() + return TRUE /datum/keybinding/human/quick_equipbelt - key = "Shift-E" - name = "quick_equipbelt" - full_name = "Quick equip belt" - description = "Put held thing in belt or take out most recent thing from belt" + hotkey_keys = list("ShiftE") + name = "quick_equipbelt" + full_name = "Quick equip belt" + description = "Put held thing in belt or take out most recent thing from belt" /datum/keybinding/human/quick_equipbelt/down(client/user) - var/mob/living/carbon/human/H = user.mob - H.smart_equipbelt() - return TRUE + var/mob/living/carbon/human/H = user.mob + H.smart_equipbelt() + return TRUE /datum/keybinding/human/bag_equip - key = "Shift-B" + hotkey_keys = list("ShiftB") name = "bag_equip" full_name = "Bag equip" description = "Put held thing in backpack or take out most recent thing from backpack" /datum/keybinding/human/bag_equip/down(client/user) - var/mob/living/carbon/human/H = user.mob - H.smart_equipbag() - return TRUE + var/mob/living/carbon/human/H = user.mob + H.smart_equipbag() + return TRUE diff --git a/code/datums/keybinding/living.dm b/code/datums/keybinding/living.dm index 94082224a7f..c9d02d0da73 100644 --- a/code/datums/keybinding/living.dm +++ b/code/datums/keybinding/living.dm @@ -1,15 +1,15 @@ /datum/keybinding/living - category = CATEGORY_HUMAN - weight = WEIGHT_MOB + category = CATEGORY_HUMAN + weight = WEIGHT_MOB /datum/keybinding/living/resist - key = "B" - name = "resist" - full_name = "Resist" - description = "Break free of your current state. Handcuffed? on fire? Resist!" + hotkey_keys = list("B") + 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 + var/mob/living/L = user.mob + L.resist() + return TRUE diff --git a/code/datums/keybinding/mob.dm b/code/datums/keybinding/mob.dm index b75449f97af..693b740513c 100644 --- a/code/datums/keybinding/mob.dm +++ b/code/datums/keybinding/mob.dm @@ -4,7 +4,8 @@ /datum/keybinding/mob/face_north - key = "Ctrl-W" + hotkey_keys = list("CtrlW", "CtrlNorth") + classic_keys = list("CtrlNorth") name = "face_north" full_name = "Face North" description = "" @@ -16,7 +17,8 @@ /datum/keybinding/mob/face_east - key = "Ctrl-D" + hotkey_keys = list("CtrlD", "CtrlEast") + classic_keys = list("CtrlEast") name = "face_east" full_name = "Face East" description = "" @@ -28,7 +30,8 @@ /datum/keybinding/mob/face_south - key = "Ctrl-S" + hotkey_keys = list("CtrlS", "CtrlSouth") + classic_keys = list("CtrlSouth") name = "face_south" full_name = "Face South" description = "" @@ -39,7 +42,8 @@ return TRUE /datum/keybinding/mob/face_west - key = "Ctrl-A" + hotkey_keys = list("CtrlA", "CtrlWest") + classic_keys = list("CtrlWest") name = "face_west" full_name = "Face West" description = "" @@ -50,7 +54,8 @@ return TRUE /datum/keybinding/mob/stop_pulling - key = "H" + hotkey_keys = list("H", "Delete") + classic_keys = list("Delete") name = "stop_pulling" full_name = "Stop pulling" description = "" @@ -64,7 +69,7 @@ return TRUE /datum/keybinding/mob/cycle_intent_right - key = "Home" + hotkey_keys = list("Northwest") // HOME name = "cycle_intent_right" full_name = "cycle intent right" description = "" @@ -75,7 +80,7 @@ return TRUE /datum/keybinding/mob/cycle_intent_left - key = "Insert" + hotkey_keys = list("Insert") name = "cycle_intent_left" full_name = "cycle intent left" description = "" @@ -86,7 +91,8 @@ return TRUE /datum/keybinding/mob/swap_hands - key = "X" + hotkey_keys = list("X") + classic_keys = list("Northeast") // PAGEUP name = "swap_hands" full_name = "Swap hands" description = "" @@ -97,7 +103,8 @@ return TRUE /datum/keybinding/mob/activate_inhand - key = "Z" + hotkey_keys = list("Z") + classic_keys = list("Southeast") // PAGEDOWN name = "activate_inhand" full_name = "Activate in-hand" description = "Uses whatever item you have inhand" @@ -108,7 +115,7 @@ return TRUE /datum/keybinding/mob/drop_item - key = "Q" + hotkey_keys = list("Q") name = "drop_item" full_name = "Drop Item" description = "" @@ -125,7 +132,7 @@ return TRUE /datum/keybinding/mob/toggle_move_intent - key = "Alt" + hotkey_keys = list("Alt") 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" @@ -141,7 +148,7 @@ return TRUE /datum/keybinding/mob/toggle_move_intent_alternative - key = "Unbound" + hotkey_keys = list("Unbound") name = "toggle_move_intent_alt" full_name = "press to cycle move intent" description = "Pressing this cycle to the opposite move intent, does not cycle back" @@ -152,7 +159,7 @@ return TRUE /datum/keybinding/mob/target_head_cycle - key = "Numpad8" + hotkey_keys = list("Numpad8") name = "target_head_cycle" full_name = "Target: Cycle head" description = "" @@ -162,7 +169,7 @@ return TRUE /datum/keybinding/mob/target_r_arm - key = "Numpad4" + hotkey_keys = list("Numpad4") name = "target_r_arm" full_name = "Target: right arm" description = "" @@ -172,7 +179,7 @@ return TRUE /datum/keybinding/mob/target_body_chest - key = "Numpad5" + hotkey_keys = list("Numpad5") name = "target_body_chest" full_name = "Target: Body" description = "" @@ -182,7 +189,7 @@ return TRUE /datum/keybinding/mob/target_left_arm - key = "Numpad6" + hotkey_keys = list("Numpad6") name = "target_left_arm" full_name = "Target: left arm" description = "" @@ -192,7 +199,7 @@ return TRUE /datum/keybinding/mob/target_right_leg - key = "Numpad1" + hotkey_keys = list("Numpad1") name = "target_right_leg" full_name = "Target: Right leg" description = "" @@ -202,7 +209,7 @@ return TRUE /datum/keybinding/mob/target_body_groin - key = "Numpad2" + hotkey_keys = list("Numpad2") name = "target_body_groin" full_name = "Target: Groin" description = "" @@ -212,7 +219,7 @@ return TRUE /datum/keybinding/mob/target_left_leg - key = "Numpad3" + hotkey_keys = list("Numpad3") name = "target_left_leg" full_name = "Target: left leg" description = "" diff --git a/code/datums/keybinding/movement.dm b/code/datums/keybinding/movement.dm index 4548dfaddce..c021ca928ed 100644 --- a/code/datums/keybinding/movement.dm +++ b/code/datums/keybinding/movement.dm @@ -3,25 +3,29 @@ weight = WEIGHT_HIGHEST /datum/keybinding/movement/north - key = "W" + hotkey_keys = list("W", "North") + classic_keys = list("North") name = "North" full_name = "Move North" description = "Moves your character north" /datum/keybinding/movement/south - key = "S" + hotkey_keys = list("S", "South") + classic_keys = list("South") name = "South" full_name = "Move South" description = "Moves your character south" /datum/keybinding/movement/west - key = "A" + hotkey_keys = list("A", "West") + classic_keys = list("West") name = "West" full_name = "Move West" description = "Moves your character left" /datum/keybinding/movement/east - key = "D" + hotkey_keys = list("D", "East") + classic_keys = list("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 index 98bfd9b6b23..af06c61d6ba 100644 --- a/code/datums/keybinding/robot.dm +++ b/code/datums/keybinding/robot.dm @@ -4,7 +4,7 @@ /datum/keybinding/robot/moduleone - key = "1" + hotkey_keys = list("1") name = "module_one" full_name = "Toggle module 1" description = "Equips or unequips the first module" @@ -17,7 +17,7 @@ return TRUE /datum/keybinding/robot/moduletwo - key = "2" + hotkey_keys = list("2") name = "module_two" full_name = "Toggle module 2" description = "Equips or unequips the second module" @@ -30,7 +30,7 @@ return TRUE /datum/keybinding/robot/modulethree - key = "3" + hotkey_keys = list("3") name = "module_three" full_name = "Toggle module 3" description = "Equips or unequips the third module" @@ -43,7 +43,7 @@ return TRUE /datum/keybinding/robot/intent_cycle - key = "4" + hotkey_keys = list("4") name = "cycle_intent" full_name = "Cycle intent left" description = "Cycles the intent left" @@ -56,7 +56,7 @@ return TRUE /datum/keybinding/robot/unequip_module - key = "Q" + hotkey_keys = list("Q") name = "unequip_module" full_name = "Unequip module" description = "Unequips the active module" diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index e1a0550fcc1..474a861a5c2 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -797,6 +797,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) // so that the visual focus indicator matches reality. winset(src, null, "input.background-color=[COLOR_INPUT_DISABLED]") + else + winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") + ..() /client/proc/add_verbs_from_config() @@ -869,19 +872,20 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) change_view("[x]x[y]") /client/proc/update_movement_keys() - if(prefs && prefs.key_bindings) - movement_keys = list() - for(var/key in prefs.key_bindings) - for(var/kb_name in prefs.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 + if(!prefs?.key_bindings) + return + movement_keys = list() + for(var/key in prefs.key_bindings) + for(var/kb_name in prefs.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 /client/proc/change_view(new_size) if (isnull(new_size)) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 53a7eb48508..57ce866f112 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -128,7 +128,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) return //we couldn't load character data so just randomize the character appearance + name random_character() //let's create a random character then - rather than a fat, bald and naked man. - key_bindings = deepCopyList(GLOB.keybinding_list_by_key) // give them default keybinds too + addtimer(CALLBACK(src, .proc/load_default_keybindings, C), 5 SECONDS) real_name = pref_species.random_name(gender,1) if(!loaded_preferences_successfully) save_preferences() @@ -136,6 +136,16 @@ GLOBAL_LIST_EMPTY(preferences_datums) menuoptions = list() return + +/datum/preferences/proc/load_default_keybindings(client/C) + if(QDELETED(C)) + return + to_chat(C, "Empty keybindings, setting default to hotkey mode") + hotkeys = TRUE + key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) + C.update_movement_keys() + save_preferences() + #define APPEARANCE_CATEGORY_COLUMN "" #define MAX_MUTANT_ROWS 4 @@ -695,14 +705,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/list/user_binds = list() for (var/key in key_bindings) for(var/kb_name in key_bindings[key]) - user_binds[kb_name] = key + user_binds[kb_name] += list(key) var/list/kb_categories = list() // Group keybinds by category for (var/name in GLOB.keybindings_by_name) var/datum/keybinding/kb = GLOB.keybindings_by_name[name] - if (!(kb.category in kb_categories)) - kb_categories[kb.category] = list() kb_categories[kb.category] += list(kb) dat += "" @@ -711,11 +719,24 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "

[category]

" for (var/i in kb_categories[category]) var/datum/keybinding/kb = i - var/bound_key = user_binds[kb.name] - bound_key = (bound_key) ? bound_key : "Unbound" - - dat += " [bound_key] Default: ( [kb.key] )" - dat += "
" + if(!length(user_binds[kb.name])) + dat += " Unbound" + var/list/default_keys = hotkeys ? kb.hotkey_keys : kb.classic_keys + if(LAZYLEN(default_keys)) + dat += "| Default: [default_keys.Join(", ")]" + dat += "
" + else + var/bound_key = user_binds[kb.name][1] + dat += " [bound_key]" + for(var/bound_key_index in 2 to length(user_binds[kb.name])) + bound_key = user_binds[kb.name][bound_key_index] + dat += " | [bound_key]" + if(length(user_binds[kb.name]) < MAX_KEYS_PER_KEYBIND) + dat += "| Add Secondary" + var/list/default_keys = hotkeys ? kb.classic_keys : kb.hotkey_keys + if(LAZYLEN(default_keys)) + dat += "| Default: [default_keys.Join(", ")]" + dat += "
" dat += "

" dat += "\[Reset to default\]" @@ -742,14 +763,17 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/HTML = {"
Keybinding: [kb.full_name]
[kb.description]

Press any key to change
Press ESC to clear
@@ -1512,49 +1536,39 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/clear_key = text2num(href_list["clear_key"]) var/old_key = href_list["old_key"] if(clear_key) - if(old_key != "Unbound") // if it was already set + if(key_bindings[old_key]) key_bindings[old_key] -= kb_name - key_bindings["Unbound"] += list(kb_name) + if(!length(key_bindings[old_key])) + key_bindings -= old_key user << browse(null, "window=capturekeypress") save_preferences() ShowChoices(user) return - var/key = href_list["key"] - var/numpad = text2num(href_list["numpad"]) - var/AltMod = text2num(href_list["alt"]) ? "Alt-" : "" - var/CtrlMod = text2num(href_list["ctrl"]) ? "Ctrl-" : "" - var/ShiftMod = text2num(href_list["shift"]) ? "Shift-" : "" + 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" : "" // var/key_code = text2num(href_list["key_code"]) - var/new_key = uppertext(key) + if(GLOB._kbMap[new_key]) + new_key = GLOB._kbMap[new_key] - // This is a mapping from JS keys to Byond - ref: https://keycode.info/ - var/static/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" - ) - new_key = _kbMap[new_key] ? _kbMap[new_key] : new_key - - if (numpad) - new_key = "Numpad[new_key]" - - var/full_key = "[AltMod][CtrlMod][ShiftMod][new_key]" - if(!key_bindings[old_key]) - key_bindings[old_key] = list() - key_bindings[old_key] -= kb_name + 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(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]) @@ -1563,7 +1577,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) save_preferences() if("keybindings_reset") - key_bindings = deepCopyList(GLOB.keybinding_list_by_key) + var/choice = tgalert(user, "Would you prefer 'hotkey' or 'classic' defaults?", "Setup keybindings", "Hotkey", "Classic", "Cancel") + if(choice == "Cancel") + ShowChoices(user) + return + hotkeys = (choice == "Hotkey") + key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key) + user.client.update_movement_keys() if("action_buttons") buttons_locked = !buttons_locked diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 829e675947c..a811f7bd8df 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -5,7 +5,7 @@ // You do not need to raise this if you are adding new values that have sane defaults. // Only raise this value when changing the meaning/format/name/layout of an existing value // where you would want the updater procs below to run -#define SAVEFILE_VERSION_MAX 27 +#define SAVEFILE_VERSION_MAX 28 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -127,9 +127,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(S["facial_style_name"]) S["facial_style_name"] >> facial_hairstyle - if(current_version < 27) - key_bindings = deepCopyList(GLOB.keybinding_list_by_key) - WRITE_FILE(S["key_bindings"], key_bindings) + if(current_version < 28) + WRITE_FILE(S["key_bindings"], null) /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) @@ -219,7 +218,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car be_special = SANITIZE_LIST(be_special) pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style)) pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color)) - key_bindings = sanitize_islist(key_bindings, deepCopyList(GLOB.keybinding_list_by_key)) + key_bindings = sanitize_islist(key_bindings, list()) + + if(!length(key_bindings)) + key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key) + parent.update_movement_keys() + addtimer(CALLBACK(src, .proc/load_default_keybindings, parent), 5 SECONDS) + return TRUE /datum/preferences/proc/save_preferences() diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index 1b52d7d45b5..36eb9aef932 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -35,6 +35,11 @@ message_admins("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.") QDEL_IN(src, 1) return + + //Focus Chat failsafe. Overrides movement checks to prevent WASD. + if(!prefs.hotkeys && length(_key) == 1 && _key != "Alt" && _key != "Ctrl" && _key != "Shift") + winset(src, null, "input.focus=true ; input.text=[url_encode(_key)]") + return //offset by 1 because the buffer address is 0 indexed because the math was simpler keys_held[current_key_address + 1] = _key @@ -47,12 +52,15 @@ // 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/full_key = "[AltMod][CtrlMod][ShiftMod][_key]" - if(_key == "Alt" || _key == "Ctrl" || _key == "Shift") // only add modifiers if the key is not a modifier already - full_key = _key + 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") + full_key = "[AltMod][CtrlMod][ShiftMod]" + else + full_key = "[AltMod][CtrlMod][ShiftMod][_key]" var/keycount = 0 for(var/kb_name in prefs.key_bindings[full_key]) keycount++ @@ -60,8 +68,8 @@ if(kb.down(src) && keycount >= MAX_COMMANDS_PER_KEY) break - holder?.key_down(full_key, src) - mob.focus?.key_down(full_key, src) + holder?.key_down(_key, src) + mob.focus?.key_down(_key, src) /client/verb/keyUp(_key as text) set instant = TRUE diff --git a/code/modules/keybindings/bindings_living.dm b/code/modules/keybindings/bindings_living.dm deleted file mode 100644 index 7ae8b9960f6..00000000000 --- a/code/modules/keybindings/bindings_living.dm +++ /dev/null @@ -1,7 +0,0 @@ -/mob/living/key_down(_key, client/user) - switch(_key) - if("B") - resist() - return - - return ..() diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 45781962d2b..e2b6b9d304d 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -176,7 +176,7 @@ return if("1", "2", "3", "4", "5", "6", "7", "8", "9") _key = text2num(_key) - if(client.keys_held["Ctrl"]) //do we assign a new hotkey? + if(user.keys_held["Ctrl"]) //do we assign a new hotkey? cam_hotkeys[_key] = eyeobj.loc to_chat(src, "Location saved to Camera Group [_key].") return diff --git a/interface/interface.dm b/interface/interface.dm index 79efd7a2ea2..76fb3f64fbb 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -75,25 +75,6 @@ to_chat(src, "The Github URL is not set in the server configuration.") return -/client/verb/hotkeys_help() - set name = "hotkeys-help" - set category = "OOC" - - var/adminhotkeys = {" -Admin: -\tF3 = asay -\tF5 = Aghost (admin-ghost) -\tF6 = player-panel -\tF7 = Buildmode -\tF8 = Invisimin -\tCtrl+F8 = Stealthmin -"} - - mob.hotkey_help() - - if(holder) - to_chat(src, adminhotkeys) - /client/verb/changelog() set name = "Changelog" set category = "OOC" @@ -104,120 +85,3 @@ Admin: prefs.lastchangelog = GLOB.changelog_hash prefs.save_preferences() winset(src, "infowindow.changelog", "font-style=;") - - -/mob/proc/hotkey_help() - var/hotkey_mode = {" -Hotkey-Mode: (hotkey-mode must be on) -\tTAB = toggle hotkey-mode -\ta = left -\ts = down -\td = right -\tw = up -\tq = drop -\te = equip -\tr = throw -\tm = me -\tt = say -\to = OOC -\tb = resist -\th = stop pulling -\tx = swap-hand -\tz = activate held object (or y) -\tShift+e = Put held item into belt(or belt slot) or take out most recent item added. -\tShift+b = Put held item into backpack(or back slot) or take out most recent item added. -\tf = cycle-intents-left -\tg = cycle-intents-right -\t1 = help-intent -\t2 = disarm-intent -\t3 = grab-intent -\t4 = harm-intent -\tNumpad = Body target selection (Press 8 repeatedly for Head->Eyes->Mouth) -\tAlt(HOLD) = Alter movement intent -"} - - var/other = {" -Any-Mode: (hotkey doesn't need to be on) -\tCtrl+a = left -\tCtrl+s = down -\tCtrl+d = right -\tCtrl+w = up -\tCtrl+q = drop -\tCtrl+e = equip -\tCtrl+r = throw -\tCtrl+b = resist -\tCtrl+h = stop pulling -\tCtrl+o = OOC -\tCtrl+x = swap-hand -\tCtrl+z = activate held object (or Ctrl+y) -\tCtrl+f = cycle-intents-left -\tCtrl+g = cycle-intents-right -\tCtrl+1 = help-intent -\tCtrl+2 = disarm-intent -\tCtrl+3 = grab-intent -\tCtrl+4 = harm-intent -\tCtrl+'+/-' OR -\tShift+Mousewheel = Ghost zoom in/out -\tDEL = stop pulling -\tINS = cycle-intents-right -\tHOME = drop -\tPGUP = swap-hand -\tPGDN = activate held object -\tEND = throw -\tCtrl+Numpad = Body target selection (Press 8 repeatedly for Head->Eyes->Mouth) -"} - - to_chat(src, hotkey_mode) - to_chat(src, other) - -/mob/living/silicon/robot/hotkey_help() - //h = talk-wheel has a nonsense tag in it because \th is an escape sequence in BYOND. - var/hotkey_mode = {" -Hotkey-Mode: (hotkey-mode must be on) -\tTAB = toggle hotkey-mode -\ta = left -\ts = down -\td = right -\tw = up -\tq = unequip active module -\th = stop pulling -\tm = me -\tt = say -\to = OOC -\tx = cycle active modules -\tb = resist -\tz = activate held object (or y) -\tf = cycle-intents-left -\tg = cycle-intents-right -\t1 = activate module 1 -\t2 = activate module 2 -\t3 = activate module 3 -\t4 = toggle intents -"} - - var/other = {" -Any-Mode: (hotkey doesn't need to be on) -\tCtrl+a = left -\tCtrl+s = down -\tCtrl+d = right -\tCtrl+w = up -\tCtrl+q = unequip active module -\tCtrl+x = cycle active modules -\tCtrl+b = resist -\tCtrl+h = stop pulling -\tCtrl+o = OOC -\tCtrl+z = activate held object (or Ctrl+y) -\tCtrl+f = cycle-intents-left -\tCtrl+g = cycle-intents-right -\tCtrl+1 = activate module 1 -\tCtrl+2 = activate module 2 -\tCtrl+3 = activate module 3 -\tCtrl+4 = toggle intents -\tDEL = stop pulling -\tINS = toggle intents -\tPGUP = cycle active modules -\tPGDN = activate held object -"} - - to_chat(src, hotkey_mode) - to_chat(src, other) diff --git a/interface/skin.dmf b/interface/skin.dmf index b2f1f195c92..7bb67123a81 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -40,11 +40,6 @@ menu "menu" command = "adminhelp" category = "&Help" saved-params = "is-checked" - elem - name = "&Hotkeys" - command = "hotkeys-help" - category = "&Help" - saved-params = "is-checked" window "mainwindow"