diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index 0970b23a16..8a8e0ac7c9 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -8,6 +8,12 @@ SUBSYSTEM_DEF(input) var/list/macro_sets var/list/movement_keys + /*! Special thing (until we get custom keybinds that also support clientside macros :weary:) that lets us do stuff like look up "which key is say/me bound to". Special format too, the value of a key should be list(key, modifier1, modifier2, ...). "default" unless override. + * USE get_key_for_macro_id or get_typing_indicator_binds TO ACCESS! + */ + var/list/macro_set_reverse_lookups + /// cache these for speed. + var/list/typing_indicator_binds /datum/controller/subsystem/input/Initialize() setup_default_macro_sets() @@ -58,6 +64,32 @@ SUBSYSTEM_DEF(input) ), ) + macro_set_reverse_lookups = list( + "default" = list( + "say" = list("T"), + "whisper" = list("T", "Ctrl"), + "me" = list("M"), + "subtle" = list("M", "Ctrl") + ), + "old_default" = list( + "say" = list("T", "Ctrl"), + ), + "old_hotkeys" = list( + "say" = list("T"), + "me" = list("M"), + ) + ) + + typing_indicator_binds = list() + var/static/list/typing_indicator_verbs = list("me", "say") + for(var/check_verb in typing_indicator_verbs) + for(var/macro_set in macro_set_reverse_lookups) + var/list/keylist = macro_set_reverse_lookups[macro_set][check_verb] + if(!keylist) + continue + var/key = keylist[1] + typing_indicator_binds[key] = TRUE + // Because i'm lazy and don't want to type all these out twice var/list/old_default = default_macro_sets["old_default"] @@ -117,3 +149,10 @@ SUBSYSTEM_DEF(input) for(var/i in 1 to length(clients)) var/client/C = clients[i] C.keyLoop() + +/datum/controller/subsystem/input/proc/get_key_for_macro_id(macro_id, macroset) + return macro_set_reverse_lookups[macroset][macro_id] || macro_set_reverse_lookups["default"][macro_id] + +/// Returns an associative list of keys without modifiers like ctrl. You have to do another lookup, this is for the first check to be faster. +/datum/controller/subsystem/input/proc/get_typing_indicator_binds(macroset) + return typing_indicator_binds[macroset] diff --git a/code/modules/keybindings/bindings_living.dm b/code/modules/keybindings/bindings_living.dm index ec6c5dd539..b338c5e899 100644 --- a/code/modules/keybindings/bindings_living.dm +++ b/code/modules/keybindings/bindings_living.dm @@ -23,5 +23,4 @@ lay_down() return - return ..() \ No newline at end of file diff --git a/code/modules/keybindings/bindings_mob.dm b/code/modules/keybindings/bindings_mob.dm index 964ee65047..6d413b4166 100644 --- a/code/modules/keybindings/bindings_mob.dm +++ b/code/modules/keybindings/bindings_mob.dm @@ -3,6 +3,17 @@ // Or we can have NPC's send actual keypresses and detect that by seeing no client /mob/key_down(_key, client/user) + if(SSinput.typing_indicator_binds[_key]) + var/macroset = winget(user, "mainwindow", "macro") + var/list/L = SSinput.macro_set_reverse_lookups[macroset] + var/valid = TRUE + if(length(L) > 1) + for(var/modifier in 2 to length(L)) + if(!client.keys_held[modifier]) + valid = FALSE + break + if(valid) + display_typing_indicator() switch(_key) if("Delete", "H") if(!pulling) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b1bc47ea4a..52e14a43e4 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -106,6 +106,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both. var/should_draw_citadel = FALSE + /// Our default override for typing indicator state + var/typing_indicator_state + /////////// // PROCS // /////////// @@ -2218,3 +2221,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/start_wagging_tail(mob/living/carbon/human/H) /datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H) + + +/////// TYPING INDICATORS /////// +/datum/species/proc/get_typing_indicator_state() + return typing_indicator_state diff --git a/code/modules/mob/living/carbon/human/typing_indicator.dm b/code/modules/mob/living/carbon/human/typing_indicator.dm new file mode 100644 index 0000000000..6d420c1f7b --- /dev/null +++ b/code/modules/mob/living/carbon/human/typing_indicator.dm @@ -0,0 +1,2 @@ +/mob/living/carbon/human/get_typing_indicator_icon_state() + return dna?.species?.get_typing_indicator_state() || ..() diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 35b49cce8e..f90b285d2d 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -354,7 +354,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(cultslurring) message = cultslur(message) - + if(clockcultslurring) message = CLOCK_CULT_SLUR(message) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index c45f6eec13..7a3959ed8f 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -128,3 +128,13 @@ var/flavor_text = "" var/flavor_text_2 = "" //version of the above that only lasts for the current round. + + ///////TYPING INDICATORS/////// + /// Set to true if we want to show typing indicators. + var/typing_indicator_enabled = FALSE + /// Default icon_state of our typing indicator. Currently only supports paths (because anything else is, as of time of typing this, unnecesary. + var/typing_indicator_state = /obj/effect/overlay/typing_indicator + /// The timer that will remove our indicator for early aborts (like when an user finishes their message) + var/typing_indicator_timerid + /// Default typing indicator timeout + var/typing_indicator_timeout = 30 SECONDS diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm new file mode 100644 index 0000000000..92710e2434 --- /dev/null +++ b/code/modules/mob/typing_indicator.dm @@ -0,0 +1,44 @@ +/// state = overlay/image/object/type/whatever add_overlay will accept +GLOBAL_LIST_EMPTY(typing_indicator_overlays) + +/// Fetches the typing indicator we'll use from GLOB.typing_indicator_overlays +/mob/proc/get_indicator_overlay(state) + . = GLOB.typing_indicator_overlays[state] + if(.) + return + // doesn't exist, make it and cache it + if(ispath(state)) + . = GLOB.typing_indicator_overlays[state] = state + // We only support paths for now because anything else isn't necessary yet. + +/// Gets the state we will use for typing indicators. Defaults to src.typing_indicator_state +/mob/proc/get_typing_indicator_icon_state() + return typing_indicator_state + +/*! + * Displays typing indicator. + * @param timeout_override - Sets how long until this will disappear on its own without the user finishing their message or logging out. Defaults to src.typing_indicator_timeout + * @param state_override - Sets the state that we will fetch. Defaults to src.get_typing_indicator_icon_state() + * @param force - shows even if src.typing_indcator_enabled is FALSE. + */ +/mob/proc/display_typing_indicator(timeout_override = typing_indicator_timeout, state_override = get_typing_indicator_icon_state(), force = FALSE) + if(!typing_indicator_enabled || force) + return + add_overlay(get_indicator_overlay(state_override)) + addtimer(CALLBACK(src, .proc/clear_typing_indicator, state_override), timeout_override, TIMER_STOPPABLE) + +/*! + * Removes typing indicator. + * @param state_override Sets the state that we will remove. Defaults to src.get_typing_indicator_icon_state() + */ +/mob/proc/clear_typing_indicator(state_override = get_typing_indicator_icon_state()) + deltimer(typing_indicator_timerid) + cut_overlay(get_indicator_overlay(state_override)) + +/// Default typing indicator +/obj/effect/overlay/typing_indicator + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + icon = 'icons/mob/talk.dmi' + icon_state = "default_typing" + appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE + layer = LARGE_MOB_LAYER diff --git a/icons/mob/talk.dmi b/icons/mob/talk.dmi index 05fe6f5623..2e300b5a29 100644 Binary files a/icons/mob/talk.dmi and b/icons/mob/talk.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 9ecf1ddd5e..5f14d2285a 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -79,8 +79,8 @@ #include "code\__DEFINES\obj_flags.dm" #include "code\__DEFINES\pinpointers.dm" #include "code\__DEFINES\pipe_construction.dm" -#include "code\__DEFINES\power.dm" #include "code\__DEFINES\pool.dm" +#include "code\__DEFINES\power.dm" #include "code\__DEFINES\preferences.dm" #include "code\__DEFINES\procpath.dm" #include "code\__DEFINES\profile.dm" @@ -2109,6 +2109,7 @@ #include "code\modules\mob\say_vr.dm" #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" +#include "code\modules\mob\typing_indicator.dm" #include "code\modules\mob\update_icons.dm" #include "code\modules\mob\camera\camera.dm" #include "code\modules\mob\dead\dead.dm" @@ -2231,6 +2232,7 @@ #include "code\modules\mob\living\carbon\human\say.dm" #include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\status_procs.dm" +#include "code\modules\mob\living\carbon\human\typing_indicator.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\species_types\abductors.dm" #include "code\modules\mob\living\carbon\human\species_types\android.dm"