Rips out the old keybind system and ports a better version from /tg/ (#17216)

* Initial version

Ripped out old version and added new version

* Update some of the keybinds

* More changes

* Added hotkey sanity checks

* Misc. fixes and features

* Small fix

* Refactor keys_held

* Adds emote keybinds

* Small spelling fixes

* I always forget this one

* Add 1 second cooldown on emotes

* Fix DME

* Don't spam

* Make linter happy

* New MC init
This commit is contained in:
Ling
2023-01-04 16:55:09 +01:00
committed by GitHub
parent b8e070f311
commit 50e3477a6e
66 changed files with 1363 additions and 1470 deletions

View File

@@ -99,6 +99,13 @@
/// Number of identical messages required before the spam-prevention will automute you /// Number of identical messages required before the spam-prevention will automute you
#define SPAM_TRIGGER_AUTOMUTE 10 #define SPAM_TRIGGER_AUTOMUTE 10
///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
///Length of held key buffer
#define HELD_KEY_BUFFER_LENGTH 15
#define STICKYBAN_DB_CACHE_TIME 10 SECONDS #define STICKYBAN_DB_CACHE_TIME 10 SECONDS
#define STICKYBAN_ROGUE_CHECK_TIME 5 #define STICKYBAN_ROGUE_CHECK_TIME 5

View File

@@ -1,202 +0,0 @@
GLOBAL_LIST_INIT(keybinding_validkeys, 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",
"Insert",
"Delete",
"Northwest",
"Southwest",
"Northeast",
"Southeast",
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"Numpad1",
"Numpad2",
"Numpad3",
"Numpad4",
"Numpad5",
"Numpad6",
"Numpad7",
"Numpad8",
"Numpad9",
",",
".",
"&",
"é",
"\"",
"'",
"(",
"§",
"è",
"!",
"ç",
"à",
")",
"-",
"Unbound",
))
// Movement
#define ACTION_MOVENORTH "Move North"
#define ACTION_MOVEWEST "Move West"
#define ACTION_MOVESOUTH "Move South"
#define ACTION_MOVEEAST "Move East"
// Client
#define ACTION_OOC "OOC"
#define ACTION_LOOC "LOOC"
#define ACTION_AHELP "Adminhelp"
#define ACTION_SCREENSHOT "Screenshot"
#define ACTION_MINHUD "Min Hud"
// Mob
#define ACTION_SAY "Say"
#define ACTION_ME "Me"
#define ACTION_STOPPULLING "Stop Pulling"
#define ACTION_INTENTRIGHT "Intent Right"
#define ACTION_INTENTLEFT "Intent Left"
#define ACTION_SWAPHAND "Swap Hand"
#define ACTION_USESELF "Use Self"
#define ACTION_DROP "Drop"
#define ACTION_EQUIP "Equip"
#define ACTION_REST "Rest"
#define ACTION_TARGETHEAD "Target Head"
#define ACTION_TARGETRARM "Target RArm"
#define ACTION_TARGETCHEST "Target Chest"
#define ACTION_TARGETLARM "Target LArm"
#define ACTION_TARGETRLEG "Target RLeg"
#define ACTION_TARGETGROIN "Target Groin"
#define ACTION_TARGETLLEG "Target LLeg"
#define ACTION_GIVE "Give"
#define ACTION_RESIST "Resist"
#define ACTION_TOGGLEWALKRUN "Toggle Walk Run"
#define ACTION_TOGGLETHROW "Toggle Throw"
#define ACTION_INTENTHELP "Intent Help"
#define ACTION_INTENTDISARM "Intent Disarm"
#define ACTION_INTENTGRAB "Intent Grab"
#define ACTION_INTENTHARM "Intent Harm"
// Admin
#define ACTION_ASAY "Adminchat"
#define ACTION_MENTORCHAT "Mentorchat"
#define ACTION_AGHOST "Admin Ghost"
#define ACTION_PLAYERPANEL "Player Panel"
#define ACTION_BUILDMODE "Build Mode"
#define ACTION_STEALTHMIN "Stealthmin"
#define ACTION_DSAY "Deadchat"
#define ACTION_DONATORSAY "Donatorsay"
GLOBAL_LIST_INIT(keybinding_default, list(
ACTION_MOVENORTH = "W",
ACTION_MOVEWEST = "A",
ACTION_MOVESOUTH = "S",
ACTION_MOVEEAST = "D",
ACTION_OOC = "O",
ACTION_LOOC = "L",
ACTION_AHELP = "F1",
ACTION_SCREENSHOT = "F2",
ACTION_MINHUD = "F12",
ACTION_SAY = "T",
ACTION_ME = "M",
ACTION_STOPPULLING = "Delete",
ACTION_INTENTRIGHT = "G",
ACTION_INTENTLEFT = "H",
ACTION_SWAPHAND = "X",
ACTION_USESELF = "Z",
ACTION_DROP = "Q",
ACTION_EQUIP = "E",
ACTION_REST = "V",
ACTION_TARGETHEAD = "Numpad8",
ACTION_TARGETRARM = "Numpad4",
ACTION_TARGETCHEST = "Numpad5",
ACTION_TARGETLARM = "Numpad6",
ACTION_TARGETRLEG = "Numpad1",
ACTION_TARGETGROIN = "Numpad2",
ACTION_TARGETLLEG = "Numpad3",
ACTION_GIVE = "C",
ACTION_RESIST = "B",
ACTION_TOGGLEWALKRUN = "J",
ACTION_TOGGLETHROW = "R",
ACTION_INTENTHELP = "1",
ACTION_INTENTDISARM = "2",
ACTION_INTENTGRAB = "3",
ACTION_INTENTHARM = "4",
ACTION_ASAY = "F3",
ACTION_MENTORCHAT = "F4",
ACTION_AGHOST = "F5",
ACTION_PLAYERPANEL = "F6",
ACTION_BUILDMODE = "F7",
ACTION_STEALTHMIN = "F8",
ACTION_DONATORSAY = "F9",
ACTION_DSAY = "F10",
))
#define BUTTON_KEY_MOVEMENT(name, action, dir) \
button = bindings.get_action_key(action); \
button_bound = TRUE; \
if(!button || button == "" || button == "Unbound") \
button_bound = FALSE; \
dat += "<b>[name]:</b> <a href='?_src_=prefs;keybinding=[action];dir=[dir];task=input' [button_bound ? "" : "style='color:red'"]>[button_bound ? button : "Unbound"]</a><br>"; \
#define BUTTON_KEY(name, action) \
BUTTON_KEY_MOVEMENT(name, action, 0);
#define MAX_KEYPRESS_COMMANDLENGTH 32

View File

@@ -29,6 +29,19 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_records_dsc(datum/data/record/a, datum/data/record/b) /proc/cmp_records_dsc(datum/data/record/a, datum/data/record/b)
return sorttext(a.fields[GLOB.cmp_field], b.fields[GLOB.cmp_field]) return sorttext(a.fields[GLOB.cmp_field], b.fields[GLOB.cmp_field])
// Datum cmp with vars is always slower than a specialist cmp proc, use your judgement.
/proc/cmp_datum_numeric_asc(datum/a, datum/b, variable)
return cmp_numeric_asc(a.vars[variable], b.vars[variable])
/proc/cmp_datum_numeric_dsc(datum/a, datum/b, variable)
return cmp_numeric_dsc(a.vars[variable], b.vars[variable])
/proc/cmp_datum_text_asc(datum/a, datum/b, variable)
return sorttext(b.vars[variable], a.vars[variable])
/proc/cmp_datum_text_dsc(datum/a, datum/b, variable)
return sorttext(a.vars[variable], b.vars[variable])
/proc/cmp_ckey_asc(client/a, client/b) /proc/cmp_ckey_asc(client/a, client/b)
return sorttext(b.ckey, a.ckey) return sorttext(b.ckey, a.ckey)

View File

@@ -59,6 +59,8 @@
var/datum/sprite_accessory/hair_gradient/H = new path() var/datum/sprite_accessory/hair_gradient/H = new path()
GLOB.hair_gradients_list[H.name] = H GLOB.hair_gradients_list[H.name] = H
// Keybindings
init_keybindings()
GLOB.emote_list = init_emote_list() GLOB.emote_list = init_emote_list()
//Skillcapes //Skillcapes

View File

@@ -11,6 +11,12 @@
return text return text
return default return default
/proc/sanitize_islist(value, default)
if(islist(value) && length(value))
return value
if(default)
return default
/proc/sanitize_inlist(value, list/List, default) /proc/sanitize_inlist(value, list/List, default)
if(value in List) if(value in List)
return value return value

View File

@@ -0,0 +1,21 @@
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"
))

View File

@@ -0,0 +1,31 @@
/// Creates and sorts all the keybinding datums
/proc/init_keybindings()
for(var/KB in subtypesof(/datum/keybinding))
var/datum/keybinding/keybinding = KB
if(!initial(keybinding.hotkey_keys))
continue
add_keybinding(new keybinding)
init_emote_keybinds()
/// Adds an instanced keybinding to the global tracker
/proc/add_keybinding(datum/keybinding/instance)
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))
/proc/init_emote_keybinds()
for(var/i in subtypesof(/datum/emote))
var/datum/emote/faketype = i
if(!initial(faketype.key))
continue
var/datum/keybinding/emote/emote_kb = new
emote_kb.link_to_emote(faketype)
add_keybinding(emote_kb)

View File

@@ -1,21 +1,18 @@
// yogs - Replicated for custom keybindings
SUBSYSTEM_DEF(input) SUBSYSTEM_DEF(input)
name = "Input" name = "Input"
wait = 1 //SS_TICKER means this runs every tick wait = 1 //SS_TICKER means this runs every tick
init_order = INIT_ORDER_INPUT init_order = INIT_ORDER_INPUT
init_stage = INITSTAGE_EARLY
flags = SS_TICKER flags = SS_TICKER
priority = FIRE_PRIORITY_INPUT priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
init_stage = INITSTAGE_EARLY init_stage = INITSTAGE_EARLY
var/list/macro_sets var/list/macro_set
var/list/movement_keys
/datum/controller/subsystem/input/Initialize() /datum/controller/subsystem/input/Initialize()
setup_default_macro_sets() setup_default_macro_sets()
setup_default_movement_keys()
initialized = TRUE initialized = TRUE
refresh_client_macro_sets() refresh_client_macro_sets()
@@ -24,85 +21,13 @@ SUBSYSTEM_DEF(input)
// This is for when macro sets are eventualy datumized // This is for when macro sets are eventualy datumized
/datum/controller/subsystem/input/proc/setup_default_macro_sets() /datum/controller/subsystem/input/proc/setup_default_macro_sets()
var/list/static/default_macro_sets macro_set = list(
"Any" = "\"KeyDown \[\[*\]\]\"",
if(default_macro_sets) "Any+UP" = "\"KeyUp \[\[*\]\]\"",
macro_sets = default_macro_sets "Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"",
return "Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"Escape" = "Reset-Held-Keys",
default_macro_sets = list( )
"default" = list(
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"O" = "ooc",
"T" = "say",
"M" = "me",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
),
"old_default" = list(
"Tab" = "\".winset \\\"mainwindow.macro=old_hotkeys map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"",
"Ctrl+T" = "say",
"Ctrl+O" = "ooc",
),
"old_hotkeys" = list(
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"O" = "ooc",
"T" = "say",
"M" = "me",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
),
)
// Because i'm lazy and don't want to type all these out twice
var/list/old_default = default_macro_sets["old_default"]
var/list/static/oldmode_keys = list(
"North", "East", "South", "West",
"Northeast", "Southeast", "Northwest", "Southwest",
"Insert", "Delete", "Ctrl", "Alt",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
)
for(var/i in 1 to oldmode_keys.len)
var/key = oldmode_keys[i]
old_default[key] = "\"KeyDown [key]\""
old_default["[key]+UP"] = "\"KeyUp [key]\""
var/list/static/oldmode_ctrl_override_keys = list(
"W" = "W", "A" = "A", "S" = "S", "D" = "D", // movement
"1" = "1", "2" = "2", "3" = "3", "4" = "4", // intent
"B" = "B", // resist
"E" = "E", // quick equip
"F" = "F", // intent left
"G" = "G", // intent right
"H" = "H", // stop pulling
"Q" = "Q", // drop
"R" = "R", // throw
"X" = "X", // switch hands
"Y" = "Y", // activate item
"Z" = "Z", // activate item
"V" = "V", // rest
)
for(var/i in 1 to oldmode_ctrl_override_keys.len)
var/key = oldmode_ctrl_override_keys[i]
var/override = oldmode_ctrl_override_keys[key]
old_default["Ctrl+[key]"] = "\"KeyDown [override]\""
old_default["Ctrl+[key]+UP"] = "\"KeyUp [override]\""
macro_sets = default_macro_sets
// For initially setting up or resetting to default the movement keys
/datum/controller/subsystem/input/proc/setup_default_movement_keys()
var/static/list/default_movement_keys = list(
"W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD
"North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
)
movement_keys = default_movement_keys.Copy()
// Badmins just wanna have fun ♪ // Badmins just wanna have fun ♪
/datum/controller/subsystem/input/proc/refresh_client_macro_sets() /datum/controller/subsystem/input/proc/refresh_client_macro_sets()

View File

@@ -148,8 +148,8 @@
to_chat(src, span_warning("You cannot speak, your other self is controlling your body!")) to_chat(src, span_warning("You cannot speak, your other self is controlling your body!"))
return FALSE return FALSE
/mob/living/split_personality/emote(act, m_type = null, message = null, intentional = FALSE) /mob/living/split_personality/emote(act, m_type = null, message = null, intentional = FALSE, is_keybind = FALSE)
return return FALSE
///////////////BRAINWASHING//////////////////// ///////////////BRAINWASHING////////////////////

View File

@@ -78,10 +78,13 @@
user.visible_message(msg, visible_message_flags = EMOTE_MESSAGE) user.visible_message(msg, visible_message_flags = EMOTE_MESSAGE)
/// For handling emote cooldown, return true to allow the emote to happen /// For handling emote cooldown, return true to allow the emote to happen
/datum/emote/proc/check_cooldown(mob/user, intentional, update=TRUE) /datum/emote/proc/check_cooldown(mob/user, intentional, update=TRUE, is_keybind = FALSE)
if(!intentional) if(!intentional)
return TRUE return TRUE
if(user.emotes_used && user.emotes_used[src] + cooldown > world.time) var/cd = cooldown
if (is_keybind)
cd = 1 SECONDS // cooldown when used as a keybind
if(user.emotes_used && user.emotes_used[src] + cd > world.time)
return FALSE return FALSE
if(!update) if(!update)
return TRUE return TRUE

View File

@@ -0,0 +1,20 @@
#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

View File

@@ -0,0 +1,23 @@
/datum/keybinding
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
/datum/keybinding/proc/up(client/user)
return FALSE
/datum/keybinding/proc/can_use(client/user)
return TRUE

View File

@@ -0,0 +1,104 @@
/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("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
/datum/keybinding/admin/admin_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
/datum/keybinding/admin/player_panel
hotkey_keys = list("F6")
name = "player_panel"
full_name = "Player Panel"
description = "Opens up the player panel"
/datum/keybinding/admin/player_panel/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("Ctrl-F8")
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("Unbound")
name = "deadmin"
full_name = "Deadmin"
description = "Shed your admin powers"
/datum/keybinding/admin/deadmin/down(client/user)
user.deadmin()
return TRUE
/datum/keybinding/admin/readmin
hotkey_keys = list("Unbound")
name = "readmin"
full_name = "Readmin"
description = "Regain your admin powers"
/datum/keybinding/admin/readmin/down(client/user)
user.readmin()
return TRUE

View File

@@ -0,0 +1,77 @@
/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")
classic_keys = list("Southwest")
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)
if (!iscarbon(user.mob))
return FALSE
var/mob/living/carbon/C = user.mob
C.toggle_throw_mode()
return TRUE
/datum/keybinding/carbon/select_help_intent
hotkey_keys = list("1")
name = "select_help_intent"
full_name = "Select help intent"
description = ""
/datum/keybinding/carbon/select_help_intent/down(client/user)
user.mob?.a_intent_change(INTENT_HELP)
return TRUE
/datum/keybinding/carbon/select_disarm_intent
hotkey_keys = list("2")
name = "select_disarm_intent"
full_name = "Select disarm intent"
description = ""
/datum/keybinding/carbon/select_disarm_intent/down(client/user)
user.mob?.a_intent_change(INTENT_DISARM)
return TRUE
/datum/keybinding/carbon/select_grab_intent
hotkey_keys = list("3")
name = "select_grab_intent"
full_name = "Select grab intent"
description = ""
/datum/keybinding/carbon/select_grab_intent/down(client/user)
user.mob?.a_intent_change(INTENT_GRAB)
return TRUE
/datum/keybinding/carbon/select_harm_intent
hotkey_keys = list("4")
name = "select_harm_intent"
full_name = "Select harm intent"
description = ""
/datum/keybinding/carbon/select_harm_intent/down(client/user)
user.mob?.a_intent_change(INTENT_HARM)
return TRUE
/datum/keybinding/carbon/give
hotkey_keys = list("G")
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

View File

@@ -0,0 +1,36 @@
/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.get_adminhelp()
return TRUE
/datum/keybinding/client/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
/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

View File

@@ -0,0 +1,56 @@
/datum/keybinding/client/communication
category = CATEGORY_COMMUNICATION
/datum/keybinding/client/communication/say
hotkey_keys = list("T")
name = "Say"
full_name = "IC Say"
description = ""
/datum/keybinding/client/communication/emote
hotkey_keys = list("M")
name = "Emote"
full_name = "Emote"
description = ""
/datum/keybinding/client/communication/ooc
hotkey_keys = list("O")
name = "OOC"
full_name = "OOC"
description = ""
/datum/keybinding/client/communication/looc
hotkey_keys = list("L")
name = "LOOC"
full_name = "LOOC"
description = ""
/datum/keybinding/client/communication/donor_say
hotkey_keys = list("F9")
name = "donor_say"
full_name = "Donator Say"
description = ""
/datum/keybinding/client/communication/donor_say/can_use(client/user)
return is_donator(user)
/datum/keybinding/client/communication/donor_say/down(client/user)
user.get_donator_say()
/datum/keybinding/client/communication/mentor_say
hotkey_keys = list("F4")
name = "mentor_say"
full_name = "Mentor Say"
description = ""
/datum/keybinding/client/communication/mentor_say/can_use(client/user)
return is_mentor(user)
/datum/keybinding/client/communication/mentor_say/down(client/user)
user.get_mentor_say()

View File

@@ -0,0 +1,14 @@
/datum/keybinding/emote
category = CATEGORY_EMOTE
weight = WEIGHT_EMOTE
var/emote_key
/datum/keybinding/emote/proc/link_to_emote(datum/emote/faketype)
hotkey_keys = list("Unbound")
emote_key = initial(faketype.key)
name = initial(faketype.key)
full_name = capitalize(initial(faketype.key))
description = "Do the emote '*[emote_key]'"
/datum/keybinding/emote/down(client/user)
return user.mob.emote(emote_key, intentional=TRUE, is_keybind=TRUE)

View File

@@ -0,0 +1,42 @@
/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/quick_equipbelt
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
/datum/keybinding/human/bag_equip
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

View File

@@ -0,0 +1,30 @@
/datum/keybinding/living
category = CATEGORY_HUMAN
weight = WEIGHT_MOB
/datum/keybinding/living/can_use(client/user)
return isliving(user.mob)
/datum/keybinding/carbon/rest
hotkey_keys = list("U")
name = "rest"
full_name = "Rest"
description = "Lay down, or get up."
/datum/keybinding/carbon/lay_down/down(client/user)
var/mob/living/carbon/C = user.mob
C.lay_down()
return TRUE
/datum/keybinding/living/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

View File

@@ -0,0 +1,230 @@
/datum/keybinding/mob
category = CATEGORY_HUMAN
weight = WEIGHT_MOB
/datum/keybinding/mob/stop_pulling
hotkey_keys = list("H", "Delete")
classic_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, "<span class='notice'>You are not pulling anything.</span>")
else
M.stop_pulling()
return TRUE
/datum/keybinding/mob/cycle_intent_right
hotkey_keys = list("Northwest") // HOME
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("Insert")
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/swap_hands
hotkey_keys = list("X")
classic_keys = list("Northeast") // PAGEUP
name = "swap_hands"
full_name = "Swap hands"
description = ""
/datum/keybinding/mob/swap_hands/down(client/user)
var/mob/M = user.mob
M.swap_hand()
return TRUE
/datum/keybinding/mob/activate_inhand
hotkey_keys = list("Z")
classic_keys = list("Southeast") // PAGEDOWN
name = "activate_inhand"
full_name = "Activate in-hand"
description = "Uses whatever item you have in your active hand"
/datum/keybinding/mob/activate_inhand/down(client/user)
var/mob/M = user.mob
M.mode()
return TRUE
/datum/keybinding/mob/drop_item
hotkey_keys = list("Q")
name = "drop_item"
full_name = "Drop Item"
description = ""
/datum/keybinding/mob/drop_item/down(client/user)
if(iscyborg(user.mob)) //cyborgs can't drop items
return FALSE
var/mob/M = user.mob
var/obj/item/I = M.get_active_held_item()
if(!I)
to_chat(user, "<span class='warning'>You have nothing to drop in your hand!</span>")
else
user.mob.dropItemToGround(I)
return TRUE
/datum/keybinding/mob/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/mob/toggle_move_intent/down(client/user)
var/mob/M = user.mob // Broken?
M.toggle_move_intent()
return TRUE
/datum/keybinding/mob/toggle_move_intent/up(client/user)
var/mob/M = user.mob
M.toggle_move_intent()
return TRUE
/datum/keybinding/mob/toggle_move_intent_alternative
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"
/datum/keybinding/mob/toggle_move_intent_alternative/down(client/user)
var/mob/M = user.mob
M.toggle_move_intent()
return TRUE
/datum/keybinding/mob/target_head_cycle
hotkey_keys = list("Numpad8")
name = "target_head_cycle"
full_name = "Target: Cycle Head"
description = "Pressing this key targets the head, and continued presses will cycle to the eyes and mouth. This will impact where you hit people, and can be used for surgery."
/datum/keybinding/mob/target_head_cycle/down(client/user)
user.body_toggle_head()
return TRUE
/datum/keybinding/mob/target_eyes
hotkey_keys = list("Numpad7")
name = "target_eyes"
full_name = "Target: Eyes"
description = "Pressing this key targets the eyes. This will impact where you hit people, and can be used for surgery."
/datum/keybinding/mob/target_eyes/down(client/user)
user.body_eyes()
return TRUE
/datum/keybinding/mob/target_mouth
hotkey_keys = list("Numpad9")
name = "target_mouths"
full_name = "Target: Mouth"
description = "Pressing this key targets the mouth. This will impact where you hit people, and can be used for surgery."
/datum/keybinding/mob/target_mouth/down(client/user)
user.body_mouth()
return TRUE
/datum/keybinding/mob/target_r_arm
hotkey_keys = list("Numpad4")
name = "target_r_arm"
full_name = "Target: Right arm"
description = "Pressing this key targets the right arm. This will impact where you hit people, and can be used for surgery."
/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 = "Pressing this key targets the body. This will impact where you hit people, and can be used for surgery."
/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 = "Pressing this key targets the body. This will impact where you hit people, and can be used for surgery."
/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 = "Pressing this key targets the right leg. This will impact where you hit people, and can be used for surgery."
/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 = "Pressing this key targets the groin. This will impact where you hit people, and can be used for surgery."
/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 = "Pressing this key targets the left leg. This will impact where you hit people, and can be used for surgery."
/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

View File

@@ -0,0 +1,31 @@
/datum/keybinding/movement
category = CATEGORY_MOVEMENT
weight = WEIGHT_HIGHEST
/datum/keybinding/movement/north
hotkey_keys = list("W", "North")
classic_keys = list("North")
name = "North"
full_name = "Move North"
description = "Moves your character north"
/datum/keybinding/movement/south
hotkey_keys = list("S", "South")
classic_keys = list("South")
name = "South"
full_name = "Move South"
description = "Moves your character south"
/datum/keybinding/movement/west
hotkey_keys = list("A", "West")
classic_keys = list("West")
name = "West"
full_name = "Move West"
description = "Moves your character left"
/datum/keybinding/movement/east
hotkey_keys = list("D", "East")
classic_keys = list("East")
name = "East"
full_name = "Move East"
description = "Moves your character east"

View File

@@ -0,0 +1,66 @@
/datum/keybinding/robot
category = CATEGORY_ROBOT
weight = WEIGHT_ROBOT
/datum/keybinding/robot/can_use(client/user)
return iscyborg(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
R.uneq_active()
return TRUE

View File

@@ -673,7 +673,7 @@
if(internal_damage & MECHA_INT_CONTROL_LOST) if(internal_damage & MECHA_INT_CONTROL_LOST)
set_glide_size(DELAY_TO_GLIDE_SIZE(step_in * check_eva())) set_glide_size(DELAY_TO_GLIDE_SIZE(step_in * check_eva()))
move_result = mechsteprand() move_result = mechsteprand()
else if(dir != direction && (!strafe || occupant?.client?.prefs.bindings.isheld_key("Alt"))) else if(dir != direction && (!strafe || occupant.client.movement_locked))
move_result = mechturn(direction) move_result = mechturn(direction)
else else
set_glide_size(DELAY_TO_GLIDE_SIZE(step_in * check_eva())) set_glide_size(DELAY_TO_GLIDE_SIZE(step_in * check_eva()))

View File

@@ -321,7 +321,7 @@
return return
return ..() return ..()
/mob/living/simple_animal/horror/emote(act, m_type = null, message = null, intentional = FALSE) /mob/living/simple_animal/horror/emote(act, m_type = null, message = null, intentional = FALSE, is_keybind = FALSE)
if(victim) if(victim)
to_chat(src, span_warning("You cannot emote while inside a host!")) to_chat(src, span_warning("You cannot emote while inside a host!"))
return return

View File

@@ -308,7 +308,7 @@
var/link = FOLLOW_LINK(M, H.victim) var/link = FOLLOW_LINK(M, H.victim)
to_chat(M, "[link] [rendered]") to_chat(M, "[link] [rendered]")
/mob/living/captive_brain/emote(act, m_type = null, message = null, intentional = FALSE) /mob/living/captive_brain/emote(act, m_type = null, message = null, intentional = FALSE, is_keybind = FALSE)
return return
/datum/action/innate/resist_control /datum/action/innate/resist_control

View File

@@ -149,3 +149,19 @@
var/list/active_music = list() var/list/active_music = list()
var/datum/music/playing_music = null var/datum/music/playing_music = null
var/mentor_position = null var/mentor_position = null
///custom movement keys for this client
var/list/movement_keys = list()
///Are we locking our movement input?
var/movement_locked = FALSE
/// A buffer of currently held keys.
var/list/keys_held = list()
/*
** These next two vars are to apply movement for keypresses and releases made while move delayed.
** Because discarding that input makes the game less responsive.
*/
/// On next move, add this dir to the move that would otherwise be done
var/next_move_dir_add
/// On next move, subtract this dir from the move that would otherwise be done
var/next_move_dir_sub

View File

@@ -905,6 +905,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
// so that the visual focus indicator matches reality. // so that the visual focus indicator matches reality.
winset(src, null, "input.background-color=[COLOR_INPUT_DISABLED]") 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() /client/proc/add_verbs_from_config()
@@ -979,6 +982,40 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
/client/proc/rescale_view(change, min, max) /client/proc/rescale_view(change, min, max)
view_size.setTo(clamp(change, min, max), clamp(change, min, max)) view_size.setTo(clamp(change, min, max), clamp(change, min, max))
/**
* Updates the keybinds for special keys
*
* Handles adding macros for the keys that need it
* And adding movement keys to the clients movement_keys list
* At the time of writing this, communication(OOC, Say, IC) require macros
* Arguments:
* * direct_prefs - the preference we're going to get keybinds from
*/
/client/proc/update_special_keybinds(datum/preferences/direct_prefs)
var/datum/preferences/D = prefs || direct_prefs
if(!D?.key_bindings)
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
if("Say")
winset(src, "default-[REF(key)]", "parent=default;name=[key];command=say")
if("Emote")
winset(src, "default-[REF(key)]", "parent=default;name=[key];command=me")
if("OOC")
winset(src, "default-[REF(key)]", "parent=default;name=[key];command=ooc")
if("LOOC")
winset(src, "default-[REF(key)]", "parent=default;name=[key];command=looc")
/client/proc/change_view(new_size) /client/proc/change_view(new_size)
if (isnull(new_size)) if (isnull(new_size))
CRASH("change_view called without argument.") CRASH("change_view called without argument.")

View File

@@ -27,7 +27,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/UI_style = null var/UI_style = null
var/buttons_locked = FALSE var/buttons_locked = FALSE
var/hotkeys = TRUE // yogs - Rebindable Keybindings var/hotkeys = TRUE
// Custom Keybindings
var/list/key_bindings = list()
var/tgui_fancy = TRUE var/tgui_fancy = TRUE
var/tgui_lock = FALSE var/tgui_lock = FALSE
var/windowflashing = TRUE var/windowflashing = TRUE
@@ -177,6 +179,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
return return
//we couldn't load character data so just randomize the character appearance + name //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. random_character() //let's create a random character then - rather than a fat, bald and naked man.
key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) // give them default keybinds and update their movement keys
C?.set_macros()
real_name = pref_species.random_name(gender,1) real_name = pref_species.random_name(gender,1)
if(!loaded_preferences_successfully) if(!loaded_preferences_successfully)
save_preferences() save_preferences()
@@ -740,7 +744,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Balloon Alerts:</b> <a href='?_src_=prefs;task=input;preference=balloon_alerts'>[disable_balloon_alerts ? "Disabled" : "Enabled"]</a><br>" dat += "<b>Balloon Alerts:</b> <a href='?_src_=prefs;task=input;preference=balloon_alerts'>[disable_balloon_alerts ? "Disabled" : "Enabled"]</a><br>"
dat += "<br>" dat += "<br>"
dat += "<b>Action Buttons:</b> <a href='?_src_=prefs;preference=action_buttons'>[(buttons_locked) ? "Locked In Place" : "Unlocked"]</a><br>" dat += "<b>Action Buttons:</b> <a href='?_src_=prefs;preference=action_buttons'>[(buttons_locked) ? "Locked In Place" : "Unlocked"]</a><br>"
//dat += "<b>Keybindings:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Default"]</a><br>" // yogs - Custom keybindings dat += "<b>Hotkey mode:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Default"]</a><br>"
dat += "<br>" dat += "<br>"
dat += "<b>PDA Color:</b> <span style='border:1px solid #161616; background-color: [pda_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=pda_color;task=input'>Change</a><BR>" dat += "<b>PDA Color:</b> <span style='border:1px solid #161616; background-color: [pda_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=pda_color;task=input'>Change</a><BR>"
dat += "<b>PDA Style:</b> <a href='?_src_=prefs;task=input;preference=pda_style'>[pda_style]</a><br>" dat += "<b>PDA Style:</b> <a href='?_src_=prefs;task=input;preference=pda_style'>[pda_style]</a><br>"
@@ -982,78 +986,47 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b><a href='http://www.yogstation.net/donate'>Donate here</b>" dat += "<b><a href='http://www.yogstation.net/donate'>Donate here</b>"
dat += "</tr></table>" dat += "</tr></table>"
// yogs end // yogs end
// yogs start - Custom keybindings
if (4) // Keybindings if (4) // Keybindings
dat += "<center><a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Default"]</a>" // Create an inverted list of keybindings -> key
dat += "<a href='?_src_=prefs;preference=reset_bindings'>Reset to default</a></center>" var/list/user_binds = list()
if(hotkeys) for (var/key in key_bindings)
var/button for(var/kb_name in key_bindings[key])
var/button_bound user_binds[kb_name] += list(key)
dat += "<table><tr><td width='340px' height='300px' valign='top'>" var/list/kb_categories = list()
dat += "<h2>Client</h2>" // Group keybinds by category
BUTTON_KEY_MOVEMENT("Move North (up)", ACTION_MOVENORTH, NORTH) for (var/name in GLOB.keybindings_by_name)
BUTTON_KEY_MOVEMENT("Move West (left)", ACTION_MOVEWEST, WEST) var/datum/keybinding/kb = GLOB.keybindings_by_name[name]
BUTTON_KEY_MOVEMENT("Move South (down)", ACTION_MOVESOUTH, SOUTH) kb_categories[kb.category] += list(kb)
BUTTON_KEY_MOVEMENT("Move East (right)", ACTION_MOVEEAST, EAST)
BUTTON_KEY("OOC", ACTION_OOC) dat += "<style>label { display: inline-block; width: 200px; }</style><body>"
BUTTON_KEY("LOOC", ACTION_LOOC)
BUTTON_KEY("Adminhelp", ACTION_AHELP)
BUTTON_KEY("Screenshot", ACTION_SCREENSHOT)
BUTTON_KEY("Minimal HUD", ACTION_MINHUD)
for (var/category in kb_categories)
dat += "<h3>[category]</h3>"
for (var/i in kb_categories[category])
var/datum/keybinding/kb = i
if(!length(user_binds[kb.name]) || user_binds[kb.name][1] == "Unbound")
dat += "<label>[kb.full_name]</label> <a href ='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=["Unbound"]'>Unbound</a>"
var/list/default_keys = hotkeys ? kb.hotkey_keys : kb.classic_keys
if(LAZYLEN(default_keys))
dat += "| Default: [default_keys.Join(", ")]"
dat += "<br>"
else
var/bound_key = user_binds[kb.name][1]
dat += "<label>[kb.full_name]</label> <a href ='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=[bound_key]'>[bound_key]</a>"
for(var/bound_key_index in 2 to length(user_binds[kb.name]))
bound_key = user_binds[kb.name][bound_key_index]
dat += " | <a href ='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=[bound_key]'>[bound_key]</a>"
if(length(user_binds[kb.name]) < MAX_KEYS_PER_KEYBIND)
dat += "| <a href ='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name]'>Add Secondary</a>"
var/list/default_keys = hotkeys ? kb.classic_keys : kb.hotkey_keys
if(LAZYLEN(default_keys))
dat += "| Default: [default_keys.Join(", ")]"
dat += "<br>"
dat += "<h2>Mob</h2>" dat += "<br><br>"
BUTTON_KEY("Say", ACTION_SAY) dat += "<a href ='?_src_=prefs;preference=keybindings_reset'>\[Reset to default\]</a>"
BUTTON_KEY("Emote", ACTION_ME) dat += "</body>"
BUTTON_KEY("Stop pulling", ACTION_STOPPULLING)
BUTTON_KEY("Cycle intent clockwise", ACTION_INTENTRIGHT)
BUTTON_KEY("Cycle intent counter-clockwise", ACTION_INTENTLEFT)
BUTTON_KEY("Swap hands", ACTION_SWAPHAND)
BUTTON_KEY("Use item on self", ACTION_USESELF)
BUTTON_KEY("Drop", ACTION_DROP)
BUTTON_KEY("Equip", ACTION_EQUIP)
BUTTON_KEY("Rest", ACTION_REST)
BUTTON_KEY("Toggle Walk Run", ACTION_TOGGLEWALKRUN)
dat += "</td><td width='300px' height='300px' valign='top'>"
dat += "<h2>Mob</h2>"
BUTTON_KEY("Target head", ACTION_TARGETHEAD)
BUTTON_KEY("Target right arm", ACTION_TARGETRARM)
BUTTON_KEY("Target chest", ACTION_TARGETCHEST)
BUTTON_KEY("Target left arm", ACTION_TARGETLARM)
BUTTON_KEY("Target right leg", ACTION_TARGETRLEG)
BUTTON_KEY("Target groin", ACTION_TARGETGROIN)
BUTTON_KEY("Target left leg", ACTION_TARGETLLEG)
BUTTON_KEY("Offer item", ACTION_GIVE)
BUTTON_KEY("Resist", ACTION_RESIST)
BUTTON_KEY("Toggle throw", ACTION_TOGGLETHROW)
BUTTON_KEY("Help intent", ACTION_INTENTHELP)
BUTTON_KEY("Disarm intent", ACTION_INTENTDISARM)
BUTTON_KEY("Grab intent", ACTION_INTENTGRAB)
BUTTON_KEY("Harm intent", ACTION_INTENTHARM)
if(parent)
if(parent.mentor_datum)
dat += "<h2>Mentor</h2>"
BUTTON_KEY("Mentorsay", ACTION_MENTORCHAT)
if(parent.holder)
dat += "<h2>Admin</h2>"
BUTTON_KEY("Adminchat", ACTION_ASAY)
BUTTON_KEY("Admin ghost", ACTION_AGHOST)
BUTTON_KEY("Player panel", ACTION_PLAYERPANEL)
BUTTON_KEY("Toggle build mode", ACTION_BUILDMODE)
BUTTON_KEY("Stealth mode", ACTION_STEALTHMIN)
BUTTON_KEY("Deadchat", ACTION_DSAY)
dat += "</td></tr></table>"
else
dat += "<b>Default keybindings selected</b>"
// yogs end
dat += "<hr><center>" dat += "<hr><center>"
if(!IsGuestKey(user.key)) if(!IsGuestKey(user.key))
@@ -1072,6 +1045,31 @@ GLOBAL_LIST_EMPTY(preferences_datums)
#undef APPEARANCE_CATEGORY_COLUMN #undef APPEARANCE_CATEGORY_COLUMN
#undef MAX_MUTANT_ROWS #undef MAX_MUTANT_ROWS
/datum/preferences/proc/CaptureKeybinding(mob/user, datum/keybinding/kb, var/old_key)
var/HTML = {"
<div id='focus' style="outline: 0;" tabindex=0>Keybinding: [kb.full_name]<br>[kb.description]<br><br><b>Press any key to change<br>Press ESC to clear</b></div>
<script>
var deedDone = false;
document.onkeyup = function(e) {
if(deedDone){ return; }
var alt = e.altKey ? 1 : 0;
var ctrl = e.ctrlKey ? 1 : 0;
var shift = e.shiftKey ? 1 : 0;
var numpad = (95 < e.keyCode && e.keyCode < 112) ? 1 : 0;
var escPressed = e.keyCode == 27 ? 1 : 0;
var url = 'byond://?_src_=prefs;preference=keybindings_set;keybinding=[kb.name];old_key=[old_key];clear_key='+escPressed+';key='+e.key+';alt='+alt+';ctrl='+ctrl+';shift='+shift+';numpad='+numpad+';key_code='+e.keyCode;
window.location=url;
deedDone = true;
}
document.getElementById('focus').focus();
</script>
"}
winshow(user, "capturekeypress", TRUE)
var/datum/browser/popup = new(user, "capturekeypress", "<div align='center'>Keybindings</div>", 350, 300)
popup.set_content(HTML)
popup.open(FALSE)
onclose(user, "capturekeypress", src)
/datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Research Director", "Head of Personnel"), widthPerColumn = 295, height = 620) /datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Research Director", "Head of Personnel"), widthPerColumn = 295, height = 620)
if(!SSjob) if(!SSjob)
return return
@@ -2033,10 +2031,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
disable_alternative_announcers = !disable_alternative_announcers disable_alternative_announcers = !disable_alternative_announcers
if("balloon_alerts") if("balloon_alerts")
disable_balloon_alerts = !disable_balloon_alerts disable_balloon_alerts = !disable_balloon_alerts
// yogs start - Custom keybindings
if(href_list["keybinding"])
update_keybindings(user, href_list["keybinding"], href_list["dir"])
// yogs end
else else
switch(href_list["preference"]) switch(href_list["preference"])
if("publicity") if("publicity")
@@ -2055,11 +2049,78 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("hotkeys") if("hotkeys")
hotkeys = !hotkeys hotkeys = !hotkeys
if(hotkeys) if(hotkeys)
bindings.bind_movement() // yogs - Rebindable keys winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]")
winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_DISABLED] mainwindow.macro=default") // yogs - Rebindable keys
else else
bindings.unbind_movement() // yogs - Rebindable keys winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_DISABLED]")
winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default")
if("keybindings_capture")
var/datum/keybinding/kb = GLOB.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
LAZYADD(key_bindings["Unbound"], 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" : ""
// var/key_code = text2num(href_list["key_code"])
if(GLOB._kbMap[new_key])
new_key = GLOB._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")
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.set_macros()
if("chat_on_map") if("chat_on_map")
chat_on_map = !chat_on_map chat_on_map = !chat_on_map
if("see_chat_non_mob") if("see_chat_non_mob")
@@ -2231,10 +2292,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if (href_list["tab"]) if (href_list["tab"])
current_tab = text2num(href_list["tab"]) current_tab = text2num(href_list["tab"])
// yogs start - Custom keybindings
if("reset_bindings")
reset_keybindings()
if("mood") if("mood")
yogtoggles ^= PREF_MOOD yogtoggles ^= PREF_MOOD

View File

@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults. // 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 // 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 // where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 38 #define SAVEFILE_VERSION_MAX 39
/* /*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -51,6 +51,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
toggles |= SOUND_ALT toggles |= SOUND_ALT
if (current_version < 37) if (current_version < 37)
chat_toggles |= CHAT_TYPING_INDICATOR chat_toggles |= CHAT_TYPING_INDICATOR
if (current_version < 39)
key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key)
parent.set_macros()
to_chat(parent, "<span class='userdanger'>Empty keybindings, setting default to [hotkeys ? "Hotkey" : "Classic"] mode</span>")
return return
/datum/preferences/proc/update_character(current_version, savefile/S) /datum/preferences/proc/update_character(current_version, savefile/S)
@@ -153,6 +157,43 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
toggles |= SOUND_VOX toggles |= SOUND_VOX
/// checks through keybindings for outdated unbound keys and updates them
/datum/preferences/proc/check_keybindings()
if(!parent)
return
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 GLOB.keybindings_by_name)
var/datum/keybinding/kb = GLOB.keybindings_by_name[name]
if(length(user_binds[kb.name]))
continue // key is unbound and or bound to something
var/addedbind = FALSE
if(hotkeys)
for(var/hotkeytobind in kb.hotkey_keys)
if(!length(key_bindings[hotkeytobind]) || hotkeytobind == "Unbound") //Only bind to the key if nothing else is bound expect for Unbound
LAZYADD(key_bindings[hotkeytobind], kb.name)
addedbind = TRUE
else
for(var/classickeytobind in kb.classic_keys)
if(!length(key_bindings[classickeytobind]) || classickeytobind == "Unbound") //Only bind to the key if nothing else is bound expect for Unbound
LAZYADD(key_bindings[classickeytobind], kb.name)
addedbind = TRUE
if(!addedbind)
notadded += kb
save_preferences() //Save the players pref so that new keys that were set to Unbound as default are permanently stored
if(length(notadded))
addtimer(CALLBACK(src, .proc/announce_conflict, notadded), 5 SECONDS)
/datum/preferences/proc/announce_conflict(list/notadded)
to_chat(parent, "<span class='warningplain'><b><u>Keybinding Conflict</u></b></span>\n\
<span class='warningplain'><b>There are new <a href='?_src_=prefs;preference=tab;tab=4'>keybindings</a> that default to keys you've already bound. The new ones will be unbound.</b></span>")
for(var/item in notadded)
var/datum/keybinding/conflicted = item
to_chat(parent, span_danger("[conflicted.category]: [conflicted.full_name] needs updating"))
/datum/preferences/proc/load_path(ckey,filename="preferences.sav") /datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey) if(!ckey)
return return
@@ -224,8 +265,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
READ_FILE(S["flare"], flare) READ_FILE(S["flare"], flare)
READ_FILE(S["bar_choice"], bar_choice) READ_FILE(S["bar_choice"], bar_choice)
READ_FILE(S["show_credits"], show_credits) READ_FILE(S["show_credits"], show_credits)
READ_FILE(S["alternative_announcers"] , disable_alternative_announcers) READ_FILE(S["alternative_announcers"], disable_alternative_announcers)
READ_FILE(S["balloon_alerts"] , disable_balloon_alerts) READ_FILE(S["balloon_alerts"], disable_balloon_alerts)
READ_FILE(S["key_bindings"], key_bindings)
check_keybindings()
// yogs start - Donor features // yogs start - Donor features
READ_FILE(S["donor_pda"], donor_pda) READ_FILE(S["donor_pda"], donor_pda)
@@ -287,6 +330,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
bar_choice = sanitize_text(bar_choice, initial(bar_choice)) bar_choice = sanitize_text(bar_choice, initial(bar_choice))
disable_alternative_announcers = sanitize_integer(disable_alternative_announcers, FALSE, TRUE, initial(disable_alternative_announcers)) disable_alternative_announcers = sanitize_integer(disable_alternative_announcers, FALSE, TRUE, initial(disable_alternative_announcers))
disable_balloon_alerts = sanitize_integer(disable_balloon_alerts, FALSE, TRUE, initial(disable_balloon_alerts)) disable_balloon_alerts = sanitize_integer(disable_balloon_alerts, FALSE, TRUE, initial(disable_balloon_alerts))
key_bindings = sanitize_islist(key_bindings, list())
var/bar_sanitize = FALSE var/bar_sanitize = FALSE
for(var/A in GLOB.potential_box_bars) for(var/A in GLOB.potential_box_bars)
@@ -306,8 +350,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
accent = sanitize_text(accent, initial(accent)) // Can't use sanitize_inlist since it doesn't support falsely default values. accent = sanitize_text(accent, initial(accent)) // Can't use sanitize_inlist since it doesn't support falsely default values.
// yogs end // yogs end
load_keybindings(S) // yogs - Custom keybindings
return TRUE return TRUE
/datum/preferences/proc/save_preferences() /datum/preferences/proc/save_preferences()
@@ -371,6 +413,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["bar_choice"], bar_choice) WRITE_FILE(S["bar_choice"], bar_choice)
WRITE_FILE(S["alternative_announcers"], disable_alternative_announcers) WRITE_FILE(S["alternative_announcers"], disable_alternative_announcers)
WRITE_FILE(S["balloon_alerts"], disable_balloon_alerts) WRITE_FILE(S["balloon_alerts"], disable_balloon_alerts)
WRITE_FILE(S["key_bindings"], key_bindings)
// yogs start - Donor features & Yogstoggle // yogs start - Donor features & Yogstoggle
WRITE_FILE(S["yogtoggles"], yogtoggles) WRITE_FILE(S["yogtoggles"], yogtoggles)
@@ -385,8 +428,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["mood_tail_wagging"], mood_tail_wagging) WRITE_FILE(S["mood_tail_wagging"], mood_tail_wagging)
// yogs end // yogs end
save_keybindings(S) // yogs - Custom keybindings
return TRUE return TRUE
/datum/preferences/proc/load_character(slot) /datum/preferences/proc/load_character(slot)

View File

@@ -2,6 +2,11 @@ GLOBAL_VAR_INIT(OOC_COLOR, null)//If this is null, use the CSS for OOC. Otherwis
GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
GLOBAL_VAR_INIT(mentor_ooc_colour, YOGS_MENTOR_OOC_COLOUR) // yogs - mentor ooc color GLOBAL_VAR_INIT(mentor_ooc_colour, YOGS_MENTOR_OOC_COLOUR) // yogs - mentor ooc color
/client/verb/ooc_wrapper()
set hidden = TRUE
var/message = input("", "OOC \"text\"") as null|text
ooc(message)
/client/verb/ooc(msg as text) /client/verb/ooc(msg as text)
set name = "OOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite set name = "OOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite
set category = "OOC" set category = "OOC"

View File

@@ -0,0 +1,11 @@
/**
* Manually clears any held keys, in case due to lag or other undefined behavior a key gets stuck.
*
* Hardcoded to the ESC key.
*/
/client/verb/reset_held_keys()
set name = "Reset Held Keys"
set hidden = TRUE
for(var/key in keys_held)
keyUp(key)

View File

@@ -1,25 +0,0 @@
// yogs - Replicated for custom keybindings
/datum/admins/key_down(_key, client/user)
switch(_key)
if("F3")
user.get_admin_say()
return
if("F5")
user.admin_ghost()
return
if("F6")
player_panel_new()
return
if("F7")
user.togglebuildmodeself()
return
if("F8")
if(user.keys_held["Ctrl"])
user.stealth()
else
user.invisimin()
return
if("F10")
user.get_dead_say()
return
..()

View File

@@ -1,19 +1,21 @@
// yogs - Replicated for custom keybindings
// You might be wondering why this isn't client level. If focus is null, we don't want you to move. // You might be wondering why this isn't client level. If focus is null, we don't want you to move.
// Only way to do that is to tie the behavior into the focus's keyLoop(). // Only way to do that is to tie the behavior into the focus's keyLoop().
/atom/movable/keyLoop(client/user) /atom/movable/keyLoop(client/user)
if(!user.keys_held["Ctrl"]) var/movement_dir = NONE
var/movement_dir = NONE for(var/_key in user.keys_held)
for(var/_key in user.keys_held) movement_dir = movement_dir | user.movement_keys[_key]
movement_dir = movement_dir | SSinput.movement_keys[_key] if(user.next_move_dir_add)
if(user.next_move_dir_add) movement_dir |= user.next_move_dir_add
movement_dir |= user.next_move_dir_add if(user.next_move_dir_sub)
if(user.next_move_dir_sub) movement_dir &= ~user.next_move_dir_sub
movement_dir &= ~user.next_move_dir_sub // Sanity checks in case you hold left and right and up to make sure you only go up
// Sanity checks in case you hold left and right and up to make sure you only go up if((movement_dir & NORTH) && (movement_dir & SOUTH))
if((movement_dir & NORTH) && (movement_dir & SOUTH)) movement_dir &= ~(NORTH|SOUTH)
movement_dir &= ~(NORTH|SOUTH) if((movement_dir & EAST) && (movement_dir & WEST))
if((movement_dir & EAST) && (movement_dir & WEST)) movement_dir &= ~(EAST|WEST)
movement_dir &= ~(EAST|WEST)
if(user.movement_locked)
setDir(movement_dir)
else
user.Move(get_step(src, movement_dir), movement_dir) user.Move(get_step(src, movement_dir), movement_dir)

View File

@@ -1,25 +0,0 @@
// yogs - Replicated for custom keybindings
/mob/living/carbon/key_down(_key, client/user)
switch(_key)
if("R", "Southwest") // Southwest is End
toggle_throw_mode()
return
if("V")
lay_down()
return
if("J")
toggle_move_intent()
return
if("1")
a_intent_change(INTENT_HELP)
return
if("2")
a_intent_change(INTENT_DISARM)
return
if("3")
a_intent_change(INTENT_GRAB)
return
if("4")
a_intent_change(INTENT_HARM)
return
return ..()

View File

@@ -5,50 +5,64 @@
set instant = TRUE set instant = TRUE
set hidden = TRUE set hidden = TRUE
if(length(keys_held) >= HELD_KEY_BUFFER_LENGTH && !keys_held[_key])
keyUp(keys_held[1]) //We are going over the number of possible held keys, so let's remove the first one.
keys_held[_key] = world.time keys_held[_key] = world.time
var/movement = SSinput.movement_keys[_key] if(!movement_locked)
if(!(next_move_dir_sub & movement) && !keys_held["Ctrl"]) var/movement = movement_keys[_key]
next_move_dir_add |= movement if(!(next_move_dir_sub & movement))
next_move_dir_add |= movement
//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
// Client-level keybindings are ones anyone should be able to do at any time // Client-level keybindings are ones anyone should be able to do at any time
// Things like taking screenshots, hitting tab, and adminhelps. // 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
switch(_key) switch(_key)
if("F1") if("Alt", "Ctrl", "Shift")
if(keys_held["Ctrl"] && keys_held["Shift"]) // Is this command ever used? full_key = "[AltMod][CtrlMod][ShiftMod]"
winset(src, null, "command=.options") else
else full_key = "[AltMod][CtrlMod][ShiftMod][_key]"
get_adminhelp() var/keycount = 0
return for(var/kb_name in prefs.key_bindings[full_key])
if("F2") // Screenshot. Hold shift to choose a name and location to save in keycount++
winset(src, null, "command=.screenshot [!keys_held["shift"] ? "auto" : ""]") var/datum/keybinding/kb = GLOB.keybindings_by_name[kb_name]
return if(kb.can_use(src) && kb.down(src) && keycount >= MAX_COMMANDS_PER_KEY)
if("F12") // Toggles minimal HUD break
mob.button_pressed_F12()
return
if(holder) holder?.key_down(_key, src)
holder.key_down(_key, src) mob.focus?.key_down(_key, src)
if(mob.focus)
mob.focus.key_down(_key, src)
/client/verb/keyUp(_key as text) /client/verb/keyUp(_key as text)
set instant = TRUE set instant = TRUE
set hidden = TRUE set hidden = TRUE
keys_held -= _key if(!keys_held[_key])
var/movement = SSinput.movement_keys[_key] return
if(!(next_move_dir_add & movement))
next_move_dir_sub |= movement
if(holder) keys_held -= _key
holder.key_up(_key, src) if(!movement_locked)
if(mob.focus) var/movement = movement_keys[_key]
mob.focus.key_up(_key, src) if(!(next_move_dir_add & movement))
next_move_dir_sub |= movement
// 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 = GLOB.keybindings_by_name[kb_name]
if(kb.can_use(src) && kb.up(src))
break
holder?.key_up(_key, src)
mob.focus?.key_up(_key, src)
// Called every game tick // Called every game tick
/client/keyLoop() /client/keyLoop()
if(holder) holder?.keyLoop(src)
holder.keyLoop(src) mob.focus?.keyLoop(src)
if(mob.focus)
mob.focus.keyLoop(src)

View File

@@ -1,66 +0,0 @@
// yogs - Replicated for custom keybindings
/mob/living/carbon/human/key_down(_key, client/user)
if(client.keys_held["Shift"])
switch(_key)
if("E") // Put held thing in belt or take out most recent thing from belt
if(incapacitated())
return
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_belt = get_item_by_slot(SLOT_BELT)
if(!equipped_belt) // We also let you equip a belt like this
if(!thing)
to_chat(user, span_notice("You have no belt to take something out of."))
return
if(equip_to_slot_if_possible(thing, SLOT_BELT))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_belt, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_belt.attack_hand(src)
else
to_chat(user, span_notice("You can't fit anything in."))
return
if(thing) // put thing in belt
if(!SEND_SIGNAL(equipped_belt, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
to_chat(user, span_notice("You can't fit anything in."))
return
if(!equipped_belt.contents.len) // nothing to take out
to_chat(user, span_notice("There's nothing in your belt to take out."))
return
var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from belt
return
if("B") // Put held thing in backpack or take out most recent thing from backpack
if(incapacitated())
return
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_back = get_item_by_slot(SLOT_BACK)
if(!equipped_back) // We also let you equip a backpack like this
if(!thing)
to_chat(user, span_notice("You have no backpack to take something out of."))
return
if(equip_to_slot_if_possible(thing, SLOT_BACK))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_back, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_back.attack_hand(src)
else
to_chat(user, span_notice("You can't fit anything in."))
return
if(thing) // put thing in backpack
if(!SEND_SIGNAL(equipped_back, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
to_chat(user, span_notice("You can't fit anything in."))
return
if(!equipped_back.contents.len) // nothing to take out
to_chat(user, span_notice("There's nothing in your backpack to take out."))
return
var/obj/item/stored = equipped_back.contents[equipped_back.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from backpack
return
return ..()

View File

@@ -1,8 +0,0 @@
// yogs - Replicated for custom keybindings
/mob/living/key_down(_key, client/user)
switch(_key)
if("B")
resist()
return
return ..()

View File

@@ -1,83 +0,0 @@
// yogs - Replicated for custom keybindings
// Technically the client argument is unncessary here since that SHOULD be src.client but let's not assume things
// All it takes is one badmin setting their focus to someone else's client to mess things up
// Or we can have NPC's send actual keypresses and detect that by seeing no client
/mob/key_down(_key, client/user)
switch(_key)
if("Delete", "H")
if(!pulling)
to_chat(src, span_notice("You are not pulling anything."))
else
stop_pulling()
return
if("Insert", "G")
a_intent_change(INTENT_HOTKEY_RIGHT)
return
if("F")
a_intent_change(INTENT_HOTKEY_LEFT)
return
if("X", "Northeast") // Northeast is Page-up
swap_hand()
return
if("Y", "Z", "Southeast") // Southeast is Page-down
mode() // attack_self(). No idea who came up with "mode()"
return
if("Q", "Northwest") // Northwest is Home
var/obj/item/I = get_active_held_item()
if(!I)
to_chat(src, span_warning("You have nothing to drop in your hand!"))
else
dropItemToGround(I)
return
if("E")
quick_equip()
return
if("Alt")
toggle_move_intent()
return
//Bodypart selections
if("Numpad8")
user.body_toggle_head()
return
if("Numpad4")
user.body_r_arm()
return
if("Numpad5")
user.body_chest()
return
if("Numpad6")
user.body_l_arm()
return
if("Numpad1")
user.body_r_leg()
return
if("Numpad2")
user.body_groin()
return
if("Numpad3")
user.body_l_leg()
return
if(client.keys_held["Ctrl"])
switch(SSinput.movement_keys[_key])
if(NORTH)
northface()
return
if(SOUTH)
southface()
return
if(WEST)
westface()
return
if(EAST)
eastface()
return
return ..()
/mob/key_up(_key, client/user)
switch(_key)
if("Alt")
toggle_move_intent()
return
return ..()

View File

@@ -1,13 +0,0 @@
// yogs - Replicated for custom keybindings
/mob/living/silicon/robot/key_down(_key, client/user)
switch(_key)
if("1", "2", "3")
toggle_module(text2num(_key))
return
if("4")
a_intent_change(INTENT_HOTKEY_LEFT)
return
if("Q")
uneq_active()
return
return ..()

View File

@@ -1,10 +1,3 @@
/client
var/list/keys_held = list() // A list of any keys held currently
// These next two vars are to apply movement for keypresses and releases made while move delayed.
// Because discarding that input makes the game less responsive.
var/next_move_dir_add // On next move, add this dir to the move that would otherwise be done
var/next_move_dir_sub // On next move, subtract this dir from the move that would otherwise be done
// Set a client's focus to an object and override these procs on that object to let it handle keypresses // 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 /datum/proc/key_down(key, client/user) // Called when a key is pressed down initially
@@ -17,34 +10,32 @@
// removes all the existing macros // removes all the existing macros
/client/proc/erase_all_macros() /client/proc/erase_all_macros()
var/list/macro_sets = params2list(winget(src, null, "macros"))
var/erase_output = "" var/erase_output = ""
for(var/i in 1 to macro_sets.len) var/list/macro_set = params2list(winget(src, "default.*", "command")) // The third arg doesnt matter here as we're just removing them all
var/setname = macro_sets[i] for(var/k in 1 to length(macro_set))
var/list/macro_set = params2list(winget(src, "[setname].*", "command")) // The third arg doesnt matter here as we're just removing them all var/list/split_name = splittext(macro_set[k], ".")
for(var/k in 1 to macro_set.len) var/macro_name = "[split_name[1]].[split_name[2]]" // [3] is "command"
var/list/split_name = splittext(macro_set[k], ".") erase_output = "[erase_output];[macro_name].parent=null"
var/macro_name = "[split_name[1]].[split_name[2]]" // [3] is "command"
erase_output = "[erase_output];[macro_name].parent=null"
winset(src, null, erase_output) winset(src, null, erase_output)
/client/proc/set_macros() /client/proc/set_macros()
set waitfor = FALSE set waitfor = FALSE
//Reset the buffer
for(var/key in keys_held)
keyUp(key)
erase_all_macros() erase_all_macros()
var/list/macro_sets = SSinput.macro_sets var/list/macro_set = SSinput.macro_set
for(var/i in 1 to macro_sets.len) for(var/k in 1 to length(macro_set))
var/setname = macro_sets[i] var/key = macro_set[k]
if(setname != "default") var/command = macro_set[key]
winclone(src, "default", setname) winset(src, "default-[REF(key)]", "parent=default;name=[key];command=[command]")
var/list/macro_set = macro_sets[setname]
for(var/k in 1 to macro_set.len)
var/key = macro_set[k]
var/command = macro_set[key]
winset(src, "[setname]-[REF(key)]", "parent=[setname];name=[key];command=[command]")
if(prefs?.hotkeys) if(prefs?.hotkeys)
winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=default") winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]")
else else
winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default") winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_DISABLED]")
update_special_keybinds()

View File

@@ -23,5 +23,5 @@
/mob/camera/canUseStorage() /mob/camera/canUseStorage()
return FALSE return FALSE
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE) /mob/camera/emote(act, m_type=1, message = null, intentional = FALSE, is_keybind = FALSE)
return return FALSE

View File

@@ -1,5 +1,18 @@
///How confused a carbon must be before they will vomit
#define BEYBLADE_PUKE_THRESHOLD 30
///How must nutrition is lost when a carbon pukes
#define BEYBLADE_PUKE_NUTRIENT_LOSS 60
///How often a carbon becomes penalized
#define BEYBLADE_DIZZINESS_PROBABILITY 20
///How long the screenshake lasts
#define BEYBLADE_DIZZINESS_DURATION 20
///How much confusion a carbon gets every time they are penalized
#define BEYBLADE_CONFUSION_INCREMENT 10
///A max for how much confusion a carbon will be for beyblading
#define BEYBLADE_CONFUSION_LIMIT 40
//The code execution of the emote datum is located at code/datums/emotes.dm //The code execution of the emote datum is located at code/datums/emotes.dm
/mob/proc/emote(act, m_type = null, message = null, intentional = FALSE) /mob/proc/emote(act, m_type = null, message = null, intentional = FALSE, is_keybind = FALSE)
act = lowertext(act) act = lowertext(act)
var/param = message var/param = message
var/custom_param = findchar(act, " ") var/custom_param = findchar(act, " ")
@@ -16,7 +29,7 @@
return FALSE return FALSE
var/silenced = FALSE var/silenced = FALSE
for(var/datum/emote/P in key_emotes) for(var/datum/emote/P in key_emotes)
if(!P.check_cooldown(src, intentional)) if(!P.check_cooldown(src, intentional, is_keybind=is_keybind))
silenced = TRUE silenced = TRUE
continue continue
if(P.run_emote(src, param, m_type, intentional)) if(P.run_emote(src, param, m_type, intentional))
@@ -39,6 +52,30 @@
if(.) if(.)
user.SpinAnimation(7,1) user.SpinAnimation(7,1)
/datum/emote/flip/check_cooldown(mob/user, intentional, update=TRUE, is_keybind = FALSE)
. = ..()
if(!.)
return
if (!is_keybind)
return
if(!can_run_emote(user, intentional=intentional))
return
if(isliving(user))
var/mob/living/flippy_mcgee = user
if(prob(20))
flippy_mcgee.Knockdown(1 SECONDS)
flippy_mcgee.visible_message(
span_notice("[flippy_mcgee] attempts to do a flip and falls over, what a doofus!"),
span_notice("You attempt to do a flip while still off balance from the last flip and fall down!")
)
if(prob(50))
flippy_mcgee.adjustBruteLoss(1)
else
flippy_mcgee.visible_message(
span_notice("[flippy_mcgee] stumbles a bit after their flip."),
span_notice("You stumble a bit from still being off balance from your last flip.")
)
/datum/emote/spin /datum/emote/spin
key = "spin" key = "spin"
key_third_person = "spins" key_third_person = "spins"
@@ -47,7 +84,7 @@
mob_type_ignore_stat_typecache = list(/mob/dead/observer) mob_type_ignore_stat_typecache = list(/mob/dead/observer)
cooldown = 0 SECONDS cooldown = 0 SECONDS
/datum/emote/spin/run_emote(mob/user, params , type_override, intentional) /datum/emote/spin/run_emote(mob/user, params ,type_override, intentional)
. = ..() . = ..()
if(.) if(.)
if(iscyborg(user) && user.has_buckled_mobs()) if(iscyborg(user) && user.has_buckled_mobs())
@@ -61,3 +98,30 @@
else else
//we want to hold off on doing the spin if they are a cyborg and have someone buckled to them //we want to hold off on doing the spin if they are a cyborg and have someone buckled to them
user.spin(20,1) user.spin(20,1)
/datum/emote/spin/check_cooldown(mob/living/carbon/user, intentional, update=TRUE, is_keybind = FALSE)
. = ..()
if(!.)
return
if (!is_keybind)
return
if(!can_run_emote(user, intentional=intentional))
return
if(!iscarbon(user))
return
var/current_confusion = user.confused
if(current_confusion > BEYBLADE_PUKE_THRESHOLD)
user.vomit(BEYBLADE_PUKE_NUTRIENT_LOSS, distance = 0)
return
if(prob(BEYBLADE_DIZZINESS_PROBABILITY))
to_chat(user, "<span class='warning'>You feel woozy from spinning.</span>")
user.Dizzy(BEYBLADE_DIZZINESS_DURATION)
if(current_confusion < BEYBLADE_CONFUSION_LIMIT)
user.confused += BEYBLADE_CONFUSION_INCREMENT
#undef BEYBLADE_PUKE_THRESHOLD
#undef BEYBLADE_PUKE_NUTRIENT_LOSS
#undef BEYBLADE_DIZZINESS_PROBABILITY
#undef BEYBLADE_DIZZINESS_DURATION
#undef BEYBLADE_CONFUSION_INCREMENT
#undef BEYBLADE_CONFUSION_LIMIT

View File

@@ -270,3 +270,65 @@
qdel(slot) qdel(slot)
for(var/obj/item/I in held_items) for(var/obj/item/I in held_items)
qdel(I) qdel(I)
/mob/living/carbon/human/proc/smart_equipbag() // take most recent item out of bag or place held item in bag
if(incapacitated())
return
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_back = get_item_by_slot(SLOT_BACK)
if(!equipped_back) // We also let you equip a backpack like this
if(!thing)
to_chat(src, "<span class='warning'>You have no backpack to take something out of!</span>")
return
if(equip_to_slot_if_possible(thing, SLOT_BACK))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_back, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_back.attack_hand(src)
else
to_chat(src, "<span class='warning'>You can't fit anything in!</span>")
return
if(thing) // put thing in backpack
if(!SEND_SIGNAL(equipped_back, COMSIG_TRY_STORAGE_INSERT, thing, src))
to_chat(src, "<span class='warning'>You can't fit anything in!</span>")
return
if(!equipped_back.contents.len) // nothing to take out
to_chat(src, "<span class='warning'>There's nothing in your backpack to take out!</span>")
return
var/obj/item/stored = equipped_back.contents[equipped_back.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from backpack
return
/mob/living/carbon/human/proc/smart_equipbelt() // put held thing in belt or take most recent item out of belt
if(incapacitated())
return
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_belt = get_item_by_slot(SLOT_BELT)
if(!equipped_belt) // We also let you equip a belt like this
if(!thing)
to_chat(src, "<span class='warning'>You have no belt to take something out of!</span>")
return
if(equip_to_slot_if_possible(thing, SLOT_BELT))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_belt, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_belt.attack_hand(src)
else
to_chat(src, "<span class='warning'>You can't fit anything in!</span>")
return
if(thing) // put thing in belt
if(!SEND_SIGNAL(equipped_belt, COMSIG_TRY_STORAGE_INSERT, thing, src))
to_chat(src, "<span class='warning'>You can't fit anything in!</span>")
return
if(!equipped_belt.contents.len) // nothing to take out
to_chat(src, "<span class='warning'>There's nothing in your belt to take out!</span>")
return
var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from belt
return

View File

@@ -214,7 +214,7 @@
return return
if("1", "2", "3", "4", "5", "6", "7", "8", "9") if("1", "2", "3", "4", "5", "6", "7", "8", "9")
_key = text2num(_key) _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 cam_hotkeys[_key] = eyeobj.loc
to_chat(src, "Location saved to Camera Group [_key].") to_chat(src, "Location saved to Camera Group [_key].")
return return

View File

@@ -300,10 +300,10 @@
verb_say = pick(speak_emote) verb_say = pick(speak_emote)
. = ..() . = ..()
/mob/living/simple_animal/emote(act, m_type=1, message = null, intentional = FALSE) /mob/living/simple_animal/emote(act, m_type=1, message = null, intentional = FALSE, is_keybind = FALSE)
if(stat) if(stat)
return return FALSE
. = ..() return ..()
/mob/living/simple_animal/proc/set_varspeed(var_value) /mob/living/simple_animal/proc/set_varspeed(var_value)
speed = var_value speed = var_value

View File

@@ -28,9 +28,11 @@
/datum/emote/slime/mood/run_emote(mob/user, params, type_override, intentional) /datum/emote/slime/mood/run_emote(mob/user, params, type_override, intentional)
. = ..() . = ..()
var/mob/living/simple_animal/slime/S = user if(!.)
S.mood = mood return
S.regenerate_icons() var/mob/living/simple_animal/slime/slime_user = user
slime_user.mood = mood
slime_user.regenerate_icons()
/datum/emote/slime/mood/sneaky /datum/emote/slime/mood/sneaky
key = "moodsneaky" key = "moodsneaky"

View File

@@ -351,7 +351,8 @@
return return
//bodypart selection verbs - Cyberboss //bodypart selection verbs - Cyberboss
//8:repeated presses toggles through head - eyes - mouth //8: repeated presses toggles through head - eyes - mouth
//9: eyes 8: head 7: mouth
//4: r-arm 5: chest 6: l-arm //4: r-arm 5: chest 6: l-arm
//1: r-leg 2: groin 3: l-leg //1: r-leg 2: groin 3: l-leg
@@ -364,6 +365,8 @@
* *
* (bound to 8) - repeated presses toggles through head - eyes - mouth * (bound to 8) - repeated presses toggles through head - eyes - mouth
*/ */
///Hidden verb to target the head, bound to 8
/client/verb/body_toggle_head() /client/verb/body_toggle_head()
set name = "body-toggle-head" set name = "body-toggle-head"
set hidden = TRUE set hidden = TRUE
@@ -383,6 +386,29 @@
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(next_in_line, mob) selector.set_selected_zone(next_in_line, mob)
///Hidden verb to target the eyes, bound to 7
/client/verb/body_eyes()
set name = "body-eyes"
set hidden = TRUE
if(!check_has_body_select())
return
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_PRECISE_EYES, mob)
///Hidden verb to target the mouth, bound to 9
/client/verb/body_mouth()
set name = "body-mouth"
set hidden = TRUE
if(!check_has_body_select())
return
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_PRECISE_MOUTH, mob)
///Hidden verb to target the right arm, bound to 4 ///Hidden verb to target the right arm, bound to 4
/client/verb/body_r_arm() /client/verb/body_r_arm()
set name = "body-r-arm" set name = "body-r-arm"

View File

@@ -1,5 +1,11 @@
//Speech verbs. //Speech verbs.
/mob/verb/say_wrapper()
set name = ".Say"
set hidden = TRUE
var/message = input("", "Say \"text\"") as null|text
say_verb(message)
///Say verb ///Say verb
/mob/verb/say_verb(message as text) /mob/verb/say_verb(message as text)
set name = "Say" set name = "Say"

View File

@@ -347,7 +347,7 @@
to_chat(src, span_warning("You find yourself unable to speak, you aren't in control of your body!")) to_chat(src, span_warning("You find yourself unable to speak, you aren't in control of your body!"))
return FALSE return FALSE
/mob/living/passenger/emote(act, m_type = null, message = null, intentional = FALSE) /mob/living/passenger/emote(act, m_type = null, message = null, intentional = FALSE, is_keybind = FALSE)
to_chat(src, span_warning("You find yourself unable to emote, you aren't in control of your body!")) to_chat(src, span_warning("You find yourself unable to emote, you aren't in control of your body!"))
return return

View File

@@ -91,27 +91,7 @@
else else
to_chat(src, span_danger("The Github URL is not set in the server configuration.")) to_chat(src, span_danger("The Github URL is not set in the server configuration."))
return return
// yogs start - Rebindable Hotkeys
/*
/client/verb/hotkeys_help()
set name = "hotkeys-help"
set category = "OOC"
var/adminhotkeys = {"<font color='purple'>
Admin:
\tF3 = asay
\tF5 = Aghost (admin-ghost)
\tF6 = player-panel
\tF7 = Buildmode
\tF8 = Invisimin
\tCtrl+F8 = Stealthmin
</font>"}
mob.hotkey_help()
if(holder)
to_chat(src, adminhotkeys)
*/
/client/verb/changelog() /client/verb/changelog()
set name = "Changelog" set name = "Changelog"
set category = "OOC" set category = "OOC"
@@ -122,122 +102,3 @@ Admin:
prefs.lastchangelog = GLOB.changelog_hash prefs.lastchangelog = GLOB.changelog_hash
prefs.save_preferences() prefs.save_preferences()
winset(src, "infowindow.changelog", "font-style=;") winset(src, "infowindow.changelog", "font-style=;")
/*
/mob/proc/hotkey_help()
var/hotkey_mode = {"<font color='purple'>
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
\t<B></B>h = 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
</font>"}
var/other = {"<font color='purple'>
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)
</font>"}
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 = {"<font color='purple'>
Hotkey-Mode: (hotkey-mode must be on)
\tTAB = toggle hotkey-mode
\ta = left
\ts = down
\td = right
\tw = up
\tq = unequip active module
\t<B></B>h = 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
</font>"}
var/other = {"<font color='purple'>
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
</font>"}
to_chat(src, hotkey_mode)
to_chat(src, other)
*/
// yogs end

View File

@@ -40,11 +40,6 @@ menu "menu"
command = "adminhelp" command = "adminhelp"
category = "&Help" category = "&Help"
saved-params = "is-checked" saved-params = "is-checked"
elem
name = "&Hotkeys"
command = "hotkeys-help"
category = "&Help"
saved-params = "is-checked"
window "mainwindow" window "mainwindow"

View File

@@ -136,7 +136,6 @@
#include "code\__DEFINES\{yogs_defines}\flavor_misc.dm" #include "code\__DEFINES\{yogs_defines}\flavor_misc.dm"
#include "code\__DEFINES\{yogs_defines}\is_helpers.dm" #include "code\__DEFINES\{yogs_defines}\is_helpers.dm"
#include "code\__DEFINES\{yogs_defines}\jobs.dm" #include "code\__DEFINES\{yogs_defines}\jobs.dm"
#include "code\__DEFINES\{yogs_defines}\keybindings.dm"
#include "code\__DEFINES\{yogs_defines}\logging.dm" #include "code\__DEFINES\{yogs_defines}\logging.dm"
#include "code\__DEFINES\{yogs_defines}\mentor.dm" #include "code\__DEFINES\{yogs_defines}\mentor.dm"
#include "code\__DEFINES\{yogs_defines}\misc.dm" #include "code\__DEFINES\{yogs_defines}\misc.dm"
@@ -200,7 +199,9 @@
#include "code\_globalvars\misc.dm" #include "code\_globalvars\misc.dm"
#include "code\_globalvars\regexes.dm" #include "code\_globalvars\regexes.dm"
#include "code\_globalvars\religion.dm" #include "code\_globalvars\religion.dm"
#include "code\_globalvars\lists\client.dm"
#include "code\_globalvars\lists\flavor_misc.dm" #include "code\_globalvars\lists\flavor_misc.dm"
#include "code\_globalvars\lists\keybindings.dm"
#include "code\_globalvars\lists\maintenance_loot.dm" #include "code\_globalvars\lists\maintenance_loot.dm"
#include "code\_globalvars\lists\mapping.dm" #include "code\_globalvars\lists\mapping.dm"
#include "code\_globalvars\lists\medals.dm" #include "code\_globalvars\lists\medals.dm"
@@ -293,6 +294,7 @@
#include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\garbage.dm"
#include "code\controllers\subsystem\icon_smooth.dm" #include "code\controllers\subsystem\icon_smooth.dm"
#include "code\controllers\subsystem\idlenpcpool.dm" #include "code\controllers\subsystem\idlenpcpool.dm"
#include "code\controllers\subsystem\input.dm"
#include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\ipintel.dm"
#include "code\controllers\subsystem\job.dm" #include "code\controllers\subsystem\job.dm"
#include "code\controllers\subsystem\language.dm" #include "code\controllers\subsystem\language.dm"
@@ -567,6 +569,18 @@
#include "code\datums\helper_datums\icon_snapshot.dm" #include "code\datums\helper_datums\icon_snapshot.dm"
#include "code\datums\helper_datums\stack_end_detector.dm" #include "code\datums\helper_datums\stack_end_detector.dm"
#include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\teleport.dm"
#include "code\datums\keybinding\_defines.dm"
#include "code\datums\keybinding\_keybindings.dm"
#include "code\datums\keybinding\admin.dm"
#include "code\datums\keybinding\carbon.dm"
#include "code\datums\keybinding\client.dm"
#include "code\datums\keybinding\communication.dm"
#include "code\datums\keybinding\emote.dm"
#include "code\datums\keybinding\human.dm"
#include "code\datums\keybinding\living.dm"
#include "code\datums\keybinding\mob.dm"
#include "code\datums\keybinding\movement.dm"
#include "code\datums\keybinding\robot.dm"
#include "code\datums\looping_sounds\_looping_sound.dm" #include "code\datums\looping_sounds\_looping_sound.dm"
#include "code\datums\looping_sounds\item_sounds.dm" #include "code\datums\looping_sounds\item_sounds.dm"
#include "code\datums\looping_sounds\machinery_sounds.dm" #include "code\datums\looping_sounds\machinery_sounds.dm"
@@ -1838,6 +1852,7 @@
#include "code\modules\client\verbs\linkforum.dm" #include "code\modules\client\verbs\linkforum.dm"
#include "code\modules\client\verbs\ooc.dm" #include "code\modules\client\verbs\ooc.dm"
#include "code\modules\client\verbs\ping.dm" #include "code\modules\client\verbs\ping.dm"
#include "code\modules\client\verbs\reset_held_keys.dm"
#include "code\modules\client\verbs\suicide.dm" #include "code\modules\client\verbs\suicide.dm"
#include "code\modules\client\verbs\who.dm" #include "code\modules\client\verbs\who.dm"
#include "code\modules\clothing\chameleon.dm" #include "code\modules\clothing\chameleon.dm"
@@ -2200,6 +2215,8 @@
#include "code\modules\jobs\job_types\station_engineer.dm" #include "code\modules\jobs\job_types\station_engineer.dm"
#include "code\modules\jobs\job_types\virologist.dm" #include "code\modules\jobs\job_types\virologist.dm"
#include "code\modules\jobs\job_types\warden.dm" #include "code\modules\jobs\job_types\warden.dm"
#include "code\modules\keybindings\bindings_atom.dm"
#include "code\modules\keybindings\bindings_client.dm"
#include "code\modules\keybindings\focus.dm" #include "code\modules\keybindings\focus.dm"
#include "code\modules\keybindings\setup.dm" #include "code\modules\keybindings\setup.dm"
#include "code\modules\language\aphasia.dm" #include "code\modules\language\aphasia.dm"
@@ -3391,7 +3408,6 @@
#include "yogstation\code\controllers\configuration\entries\general.dm" #include "yogstation\code\controllers\configuration\entries\general.dm"
#include "yogstation\code\controllers\configuration\entries\yogstation_config.dm" #include "yogstation\code\controllers\configuration\entries\yogstation_config.dm"
#include "yogstation\code\controllers\subsystem\bluespace_locker.dm" #include "yogstation\code\controllers\subsystem\bluespace_locker.dm"
#include "yogstation\code\controllers\subsystem\input.dm"
#include "yogstation\code\controllers\subsystem\jobs.dm" #include "yogstation\code\controllers\subsystem\jobs.dm"
#include "yogstation\code\controllers\subsystem\mapping.dm" #include "yogstation\code\controllers\subsystem\mapping.dm"
#include "yogstation\code\controllers\subsystem\ticker.dm" #include "yogstation\code\controllers\subsystem\ticker.dm"
@@ -3652,7 +3668,6 @@
#include "yogstation\code\modules\cargo\exports\weapons.dm" #include "yogstation\code\modules\cargo\exports\weapons.dm"
#include "yogstation\code\modules\client\client_defines.dm" #include "yogstation\code\modules\client\client_defines.dm"
#include "yogstation\code\modules\client\client_procs.dm" #include "yogstation\code\modules\client\client_procs.dm"
#include "yogstation\code\modules\client\ooc.dm"
#include "yogstation\code\modules\client\preferences.dm" #include "yogstation\code\modules\client\preferences.dm"
#include "yogstation\code\modules\client\preferences_savefile.dm" #include "yogstation\code\modules\client\preferences_savefile.dm"
#include "yogstation\code\modules\client\preferences_toggles.dm" #include "yogstation\code\modules\client\preferences_toggles.dm"
@@ -3739,15 +3754,6 @@
#include "yogstation\code\modules\jobs\job_types\psychiatrist.dm" #include "yogstation\code\modules\jobs\job_types\psychiatrist.dm"
#include "yogstation\code\modules\jobs\job_types\space_bartender.dm" #include "yogstation\code\modules\jobs\job_types\space_bartender.dm"
#include "yogstation\code\modules\jobs\job_types\tourist.dm" #include "yogstation\code\modules\jobs\job_types\tourist.dm"
#include "yogstation\code\modules\keybindings\bindings_admin.dm"
#include "yogstation\code\modules\keybindings\bindings_atom.dm"
#include "yogstation\code\modules\keybindings\bindings_carbon.dm"
#include "yogstation\code\modules\keybindings\bindings_client.dm"
#include "yogstation\code\modules\keybindings\bindings_human.dm"
#include "yogstation\code\modules\keybindings\bindings_living.dm"
#include "yogstation\code\modules\keybindings\bindings_mob.dm"
#include "yogstation\code\modules\keybindings\bindings_robot.dm"
#include "yogstation\code\modules\keybindings\keys.dm"
#include "yogstation\code\modules\language\darkspeak.dm" #include "yogstation\code\modules\language\darkspeak.dm"
#include "yogstation\code\modules\language\japanese.dm" #include "yogstation\code\modules\language\japanese.dm"
#include "yogstation\code\modules\libvg\utf8.dm" #include "yogstation\code\modules\libvg\utf8.dm"

View File

@@ -1,120 +0,0 @@
SUBSYSTEM_DEF(input)
name = "Input"
wait = 1 //SS_TICKER means this runs every tick
init_order = INIT_ORDER_INPUT
flags = SS_TICKER
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
init_stage = INITSTAGE_EARLY
var/list/macro_sets
var/list/movement_arrows
/datum/controller/subsystem/input/Initialize()
setup_default_macro_sets()
setup_default_movement_keys()
initialized = TRUE
refresh_client_macro_sets()
return SS_INIT_SUCCESS
/datum/controller/subsystem/input/proc/setup_default_macro_sets()
var/list/static/default_macro_sets
if(default_macro_sets)
macro_sets = default_macro_sets
return
default_macro_sets = list(
"default" = list(
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
),
"old_default" = list(
"Tab" = "\".winset \\\"mainwindow.macro=old_hotkeys map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"",
"Ctrl+T" = "say",
"Ctrl+O" = "ooc",
"CTRL+L" = "looc",
),
"old_hotkeys" = list(
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
),
)
// Because i'm lazy and don't want to type all these out twice
var/list/old_default = default_macro_sets["old_default"]
var/list/old_hotkeys = default_macro_sets["old_hotkeys"]
var/list/default = default_macro_sets["default"]
var/list/static/oldmode_keys = list(
"North", "East", "South", "West",
"Northeast", "Southeast", "Northwest", "Southwest",
"Insert", "Delete", "Ctrl", "Alt",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
)
for(var/i in 1 to oldmode_keys.len)
var/key = oldmode_keys[i]
old_default[key] = "\"KeyDown [key]\""
old_default["[key]+UP"] = "\"KeyUp [key]\""
var/list/static/oldmode_ctrl_override_keys = list(
"W" = "W", "A" = "A", "S" = "S", "D" = "D", // movement
"1" = "1", "2" = "2", "3" = "3", "4" = "4", // intent
"B" = "B", // resist
"E" = "E", // quick equip
"F" = "F", // intent left
"G" = "G", // intent right
"H" = "H", // stop pulling
"Q" = "Q", // drop
"R" = "R", // throw
"X" = "X", // switch hands
"Y" = "Y", // activate item
"Z" = "Z", // activate item
)
for(var/i in 1 to oldmode_ctrl_override_keys.len)
var/key = oldmode_ctrl_override_keys[i]
var/override = oldmode_ctrl_override_keys[key]
old_default["Ctrl+[key]"] = "\"KeyDown [override]\""
old_default["Ctrl+[key]+UP"] = "\"KeyUp [override]\""
// basically when these keys are pressed, we want to make sure to clear/set ctrl's state if we need to.
var/list/static/ctrl_sensitive_keys = list(
"North", "East", "South", "West",
"W", "A", "S", "D"
)
for(var/i in 1 to ctrl_sensitive_keys.len)
var/key = ctrl_sensitive_keys[i]
old_hotkeys["Ctrl+[key]"] = "\"KeyDown Ctrl\""
old_hotkeys["[key]"] = "\"KeyUp Ctrl\""
default["Ctrl+[key]"] = "\"KeyDown Ctrl\""
default["[key]"] = "\"KeyUp Ctrl\""
macro_sets = default_macro_sets
/datum/controller/subsystem/input/proc/setup_default_movement_keys()
var/static/list/arrow_keys = list(
"North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
)
movement_arrows = arrow_keys.Copy()
/datum/controller/subsystem/input/proc/refresh_client_macro_sets()
var/list/clients = GLOB.clients
for(var/i in 1 to clients.len)
var/client/user = clients[i]
user.set_macros()
/datum/controller/subsystem/input/fire()
var/list/clients = GLOB.clients // Let's sing the list cache song
for(var/i in 1 to clients.len)
var/client/C = clients[i]
C.keyLoop()

View File

@@ -1,3 +0,0 @@
/client/proc/get_ooc()
var/msg = input(src, null, "ooc \"text\"") as text|null
ooc(msg)

View File

@@ -8,14 +8,3 @@
var/purrbation = null var/purrbation = null
var/afreeze = FALSE var/afreeze = FALSE
var/accent = null // What accent to use (as the string name of that accent). NULL means no accent. var/accent = null // What accent to use (as the string name of that accent). NULL means no accent.
var/datum/keybindings/bindings = new
/datum/preferences/proc/update_keybindings(mob/user, action, dir)
var/keybind = input(user, "Select [action] button", "Keybinding Preference") as null|anything in GLOB.keybinding_validkeys
if(keybind)
bindings.key_setbinding(keybind, action, text2num(dir))
/datum/preferences/proc/reset_keybindings()
bindings.from_list(GLOB.keybinding_default)

View File

@@ -1,14 +1,3 @@
/datum/preferences/proc/load_keybindings(var/savefile/S)
var/list/keybindings
S["keybindings"] >> keybindings
if(!islist(keybindings) || !keybindings.len)
keybindings = GLOB.keybinding_default
bindings.from_list(keybindings)
/datum/preferences/proc/save_keybindings(var/savefile/S)
WRITE_FILE(S["keybindings"], bindings.to_list())
/datum/preferences/update_character(current_version, savefile/S) /datum/preferences/update_character(current_version, savefile/S)
.=..() .=..()
var/value = 0 var/value = 0

View File

@@ -1,3 +1,8 @@
/client/verb/looc_wrapper()
set hidden = TRUE
var/message = input("", "LOOC \"text\"") as null|text
looc(message)
/client/verb/looc(msg as text) /client/verb/looc(msg as text)
set name = "LOOC" set name = "LOOC"
set category = "OOC" set category = "OOC"
@@ -121,7 +126,3 @@
return return
else else
GLOB.dlooc_allowed = !GLOB.dlooc_allowed GLOB.dlooc_allowed = !GLOB.dlooc_allowed
/client/proc/get_looc()
var/msg = input(src, null, "looc \"text\"") as text|null
looc(msg)

View File

@@ -1,24 +0,0 @@
/datum/admins/key_down(datum/keyinfo/I, client/user)
switch(I.action)
if(ACTION_ASAY)
user.get_admin_say()
return
if(ACTION_AGHOST)
user.admin_ghost()
return
if(ACTION_PLAYERPANEL)
player_panel_new()
return
if(ACTION_BUILDMODE)
user.togglebuildmodeself()
return
if(ACTION_STEALTHMIN)
if(user.prefs.bindings.isheld_key("Ctrl"))
user.stealth()
else
user.invisimin()
return
if(ACTION_DSAY)
user.get_dead_say()
return
..()

View File

@@ -1,19 +0,0 @@
// You might be wondering why this isn't client level. If focus is null, we don't want you to move.
// Only way to do that is to tie the behavior into the focus's keyLoop().
/atom/movable/keyLoop(client/user)
if(!user.prefs.bindings.isheld_key("Ctrl"))
var/movement_dir = NONE
var/list/keys = SSinput.movement_arrows + user.prefs.bindings.movement_keys
for(var/_key in user.prefs.bindings.keys_held)
movement_dir |= keys[_key]
if(user.next_move_dir_add)
movement_dir |= user.next_move_dir_add
if(user.next_move_dir_sub)
movement_dir &= ~user.next_move_dir_sub
// Sanity checks in case you hold left and right and up to make sure you only go up
if((movement_dir & NORTH) && (movement_dir & SOUTH))
movement_dir &= ~(NORTH|SOUTH)
if((movement_dir & EAST) && (movement_dir & WEST))
movement_dir &= ~(EAST|WEST)
user.Move(get_step(src, movement_dir), movement_dir)

View File

@@ -1,25 +0,0 @@
/mob/living/carbon/key_down(datum/keyinfo/I, client/user)
switch(I.action)
if(ACTION_TOGGLETHROW)
toggle_throw_mode()
return
if(ACTION_REST)
lay_down()
return
if(ACTION_TOGGLEWALKRUN)
toggle_move_intent()
return
if(ACTION_INTENTHELP)
a_intent_change(INTENT_HELP)
return
if(ACTION_INTENTDISARM)
a_intent_change(INTENT_DISARM)
return
if(ACTION_INTENTGRAB)
a_intent_change(INTENT_GRAB)
return
if(ACTION_INTENTHARM)
a_intent_change(INTENT_HARM)
return
return ..()

View File

@@ -1,92 +0,0 @@
// Clients aren't datums so we have to define these procs indpendently.
// These verbs are called for all key press and release events
/client/verb/keyDown(_key as text)
set instant = TRUE
set hidden = TRUE
if(length(_key) > MAX_KEYPRESS_COMMANDLENGTH)
log_admin("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.")
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
var/datum/keybindings/bind = prefs.bindings
bind.set_key_down(_key)
var/movement = bind.get_movement_dir(_key)
if(!(next_move_dir_sub & movement) && !bind.isheld_key("Ctrl"))
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/A = bind.get_key_action(_key)
if(!A)
return
switch(A)
if(ACTION_AHELP)
get_adminhelp()
return
if(ACTION_SCREENSHOT) // Screenshot. Hold shift to choose a name and location to save in
winset(src, null, "command=.screenshot [!bind.isheld_key("shift") ? "auto" : ""]")
return
if(ACTION_MINHUD) // Toggles minimal HUD
mob.button_pressed_F12()
return
if(ACTION_OOC)
get_ooc()
return
if(ACTION_MENTORCHAT)
if(is_mentor(src))
get_mentor_say()
return
if(ACTION_DONATORSAY)
if(is_donator(usr))
get_donator_say()
return
if(ACTION_LOOC)
get_looc()
return
var/datum/keyinfo/I = bind.to_keyinfo(_key, A)
if(holder)
holder.key_down(I, src)
if(mob?.focus)
mob.focus.key_down(I, src)
/client/verb/keyUp(_key as text)
set instant = TRUE
set hidden = TRUE
if(length(_key) > MAX_KEYPRESS_COMMANDLENGTH)
log_admin("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.")
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
var/datum/keybindings/bind = prefs.bindings
bind.set_key_up(_key)
var/movement = bind.get_movement_dir(_key)
if(!(next_move_dir_add & movement))
next_move_dir_sub |= movement
var/A = bind.get_key_action(_key)
if(!A)
return
var/datum/keyinfo/I = bind.to_keyinfo(_key, A)
if(holder)
holder.key_up(I, src)
if(mob?.focus)
mob.focus.key_up(I, src)
// Called every game tick
/client/keyLoop()
if(holder)
holder.keyLoop(src)
if(mob?.focus)
mob.focus.keyLoop(src)

View File

@@ -1,95 +0,0 @@
/mob/living/carbon/human/key_down(datum/keyinfo/I, client/user)
if(user.prefs.bindings.isheld_key("Shift"))
switch(I.action)
if(ACTION_EQUIP) // Put held thing in belt or take out most recent thing from belt
if(incapacitated())
return
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_belt = get_item_by_slot(SLOT_BELT)
if(!equipped_belt) // We also let you equip a belt like this
if(!thing)
to_chat(user, span_notice("You have no belt to take something out of."))
return
if(equip_to_slot_if_possible(thing, SLOT_BELT))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_belt, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_belt.attack_hand(src)
else
to_chat(user, span_notice("You can't fit anything in."))
return
if(thing) // put thing in belt
if(!SEND_SIGNAL(equipped_belt, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
to_chat(user, span_notice("You can't fit anything in."))
return
if(!equipped_belt.contents.len) // nothing to take out
to_chat(user, span_notice("There's nothing in your belt to take out."))
return
var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from belt
return
if(ACTION_RESIST) // Put held thing in backpack or take out most recent thing from backpack
if(incapacitated())
return
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_back = get_item_by_slot(SLOT_BACK)
if(!equipped_back) // We also let you equip a backpack like this
if(!thing)
to_chat(user, span_notice("You have no backpack to take something out of."))
return
if(equip_to_slot_if_possible(thing, SLOT_BACK))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_back, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_back.attack_hand(src)
else
to_chat(user, span_notice("You can't fit anything in."))
return
if(thing) // put thing in backpack
if(!SEND_SIGNAL(equipped_back, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
to_chat(user, span_notice("You can't fit anything in."))
return
if(!equipped_back.contents.len) // nothing to take out
to_chat(user, span_notice("There's nothing in your backpack to take out."))
return
var/obj/item/stored = equipped_back.contents[equipped_back.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from backpack
return
if(ACTION_DROP) // Put held thing in suit storage or take thing out of suit storage
var/obj/item/thing = get_active_held_item()
var/obj/item/equipped_suit = get_item_by_slot(SLOT_S_STORE)
if(!equipped_suit)
if(!thing)
to_chat(user, span_notice("You have no suit storage to take something out of."))
return
if(equip_to_slot_if_possible(thing, SLOT_S_STORE))
update_inv_hands()
return
if(!SEND_SIGNAL(equipped_suit, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_suit.attack_hand(src)
else
to_chat(user, span_notice("You can't fit anything in."))
return
if(thing) // put thing in suit storage
if(!SEND_SIGNAL(equipped_suit, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
to_chat(user, span_notice("You can't fit anything in."))
return
if(!equipped_suit.contents.len) // nothing to take out
to_chat(user, span_notice("There's nothing in your suit storage to take out."))
return
var/obj/item/stored = equipped_suit.contents[equipped_suit.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from suit storage
return
return ..()

View File

@@ -1,7 +0,0 @@
/mob/living/key_down(datum/keyinfo/I, client/user)
switch(I.action)
if(ACTION_RESIST)
resist()
return
return ..()

View File

@@ -1,104 +0,0 @@
// Technically the client argument is unncessary here since that SHOULD be src.client but let's not assume things
// All it takes is one badmin setting their focus to someone else's client to mess things up
// Or we can have NPC's send actual keypresses and detect that by seeing no client
/mob/key_down(datum/keyinfo/I, client/user)
switch(I.action)
if(ACTION_SAY)
get_say()
return
if(ACTION_ME)
me_verb()
return
if(ACTION_STOPPULLING)
if(!pulling)
to_chat(src, span_notice("You are not pulling anything."))
else
stop_pulling()
return
if(ACTION_INTENTRIGHT)
a_intent_change(INTENT_HOTKEY_RIGHT)
return
if(ACTION_INTENTLEFT)
a_intent_change(INTENT_HOTKEY_LEFT)
return
if(ACTION_SWAPHAND)
swap_hand()
return
if(ACTION_USESELF)
mode() // attack_self(). No idea who came up with "mode()"
return
if(ACTION_DROP)
var/obj/item/T = get_active_held_item()
if(!T)
to_chat(src, span_warning("You have nothing to drop in your hand!"))
else
dropItemToGround(T)
return
if(ACTION_EQUIP)
quick_equip()
return
//Bodypart selections
if(ACTION_TARGETHEAD)
user.body_toggle_head()
return
if(ACTION_TARGETRARM)
user.body_r_arm()
return
if(ACTION_TARGETCHEST)
user.body_chest()
return
if(ACTION_TARGETLARM)
user.body_l_arm()
return
if(ACTION_TARGETRLEG)
user.body_r_leg()
return
if(ACTION_TARGETGROIN)
user.body_groin()
return
if(ACTION_TARGETLLEG)
user.body_l_leg()
return
if(ACTION_GIVE)
if (iscarbon(src))
var/mob/living/carbon/O = src
O.give()
return
return ..()
/mob/keyLoop(client/user)
if(user.prefs.bindings.isheld_key("Ctrl"))
var/list/keys = SSinput.movement_arrows + user.prefs.bindings.movement_keys
var/dir = NONE
for(var/_key in user.prefs.bindings.keys_held)
dir = keys[_key]
switch(dir)
if(NORTH)
if(user.prefs.bindings.isheld_key("Shift"))
northshift()
else
northface()
return
if(SOUTH)
if(user.prefs.bindings.isheld_key("Shift"))
southshift()
else
southface()
return
if(WEST)
if(user.prefs.bindings.isheld_key("Shift"))
westshift()
else
westface()
return
if(EAST)
if(user.prefs.bindings.isheld_key("Shift"))
eastshift()
else
eastface()
return
return ..()

View File

@@ -1,19 +0,0 @@
/mob/living/silicon/robot/key_down(datum/keyinfo/I, client/user)
switch(I.action)
if(ACTION_INTENTHELP)
toggle_module(1)
return
if(ACTION_INTENTDISARM)
toggle_module(2)
return
if(ACTION_INTENTGRAB)
toggle_module(3)
return
if(ACTION_INTENTLEFT)
a_intent_change(INTENT_HOTKEY_LEFT)
return
if(ACTION_DROP)
uneq_active()
return
return ..()

View File

@@ -1,89 +0,0 @@
/datum/keyinfo
var/action
var/key
/datum/keybindings
var/list/keys
var/list/old_keys = list()
var/list/keys_held = list()
var/list/movement_keys = list()
/datum/keybindings/New()
from_list(GLOB.keybinding_default)
/datum/keybindings/proc/key_setbinding(_key, _action, _dir = 0)
unbind_old_keys(_key)
keys[_action] = _key
if(_dir)
key_setmovement(_key, _dir)
/datum/keybindings/proc/key_setmovement(_key, _dir)
var/old_key = get_movement_key(_dir)
movement_keys -= old_key
movement_keys[_key] = _dir
/datum/keybindings/proc/unbind_movement()
movement_keys = list()
old_keys = keys.Copy()
keys = GLOB.keybinding_default
/datum/keybindings/proc/bind_movement()
movement_keys = list()
movement_keys[get_action_key(ACTION_MOVENORTH)] = NORTH
movement_keys[get_action_key(ACTION_MOVEWEST)] = WEST
movement_keys[get_action_key(ACTION_MOVESOUTH)] = SOUTH
movement_keys[get_action_key(ACTION_MOVEEAST)] = EAST
if(old_keys.len)
keys = old_keys.Copy()
old_keys = list()
/datum/keybindings/proc/unbind_old_keys(_key)
movement_keys -= _key
for(var/A in keys)
var/K = keys[A]
if(K == _key)
keys[A] = "Unbound"
/datum/keybindings/proc/set_key_down(_key)
keys_held[_key] = world.time
/datum/keybindings/proc/set_key_up(_key)
keys_held -= _key
/datum/keybindings/proc/get_key_action(_key)
for(var/A in keys)
var/K = keys[A]
if(K == _key)
return A
/datum/keybindings/proc/get_action_key(_action)
return keys[_action]
/datum/keybindings/proc/get_movement_dir(_key)
return movement_keys[_key]
/datum/keybindings/proc/get_movement_key(_dir)
for(var/K in movement_keys)
var/D = movement_keys[K]
if(D == _dir)
return K
/datum/keybindings/proc/isheld_key(_key)
return keys_held[_key]
/datum/keybindings/proc/to_keyinfo(_key, _action)
var/datum/keyinfo/I = new
I.key = _key
I.action = _action
return I
/datum/keybindings/proc/from_list(list/_list)
keys = _list.Copy()
bind_movement()
/datum/keybindings/proc/to_list()
return keys