diff --git a/beestation.dme b/beestation.dme index 91f6f964e1b09..7a1958ecd56dc 100644 --- a/beestation.dme +++ b/beestation.dme @@ -2432,6 +2432,7 @@ #include "code\modules\client\verbs\ooc.dm" #include "code\modules\client\verbs\ping.dm" #include "code\modules\client\verbs\suicide.dm" +#include "code\modules\client\verbs\typing.dm" #include "code\modules\client\verbs\who.dm" #include "code\modules\clothing\chameleon.dm" #include "code\modules\clothing\clothing.dm" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 3263780f5015f..e8aab4b2cbbec 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -277,6 +277,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// this object has been frozen #define TRAIT_FROZEN "frozen" + +/// Trait given to a mob that is currently thinking (giving off the "thinking" icon), used in an IC context +#define TRAIT_THINKING_IN_CHARACTER "currently_thinking_IC" + ///Turf trait for when a turf is transparent #define TURF_Z_TRANSPARENT_TRAIT "turf_z_transparent" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index fea059205dc72..d2ce6e78b2ab1 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -128,6 +128,9 @@ /// Trait given to an atom/movable when they orbit something. #define ORBITING_TRAIT "orbiting" +/// This trait comes from when a mob is currently typing. +#define CURRENTLY_TYPING_TRAIT "currently_typing" + #define VENTCRAWLING_TRAIT "ventcrawling" #define SPECIES_FLIGHT_TRAIT "species-flight" #define NO_GRAVITY_TRAIT "no-gravity" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index af9e7b2e6796e..5ea9b2d0bc1df 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -93,6 +93,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NOMOBSWAP" = TRAIT_NOMOBSWAP, "TRAIT_XRAY_VISION" = TRAIT_XRAY_VISION, "TRAIT_THERMAL_VISION" = TRAIT_THERMAL_VISION, + "TRAIT_THINKING_IN_CHARACTER" = TRAIT_THINKING_IN_CHARACTER, "TRAIT_ABDUCTOR_TRAINING" = TRAIT_ABDUCTOR_TRAINING, "TRAIT_ABDUCTOR_SCIENTIST_TRAINING" = TRAIT_ABDUCTOR_SCIENTIST_TRAINING, "TRAIT_SURGEON" = TRAIT_SURGEON, diff --git a/code/datums/mocking/client.dm b/code/datums/mocking/client.dm index 05bfd5eab0cc6..8aa24279176a3 100644 --- a/code/datums/mocking/client.dm +++ b/code/datums/mocking/client.dm @@ -6,5 +6,7 @@ /// The view of the client, similar to /client/var/view var/view = "17x15" + var/typing_indicators + /datum/client_interface/proc/should_include_for_role(banning_key = BAN_ROLE_ALL_ANTAGONISTS, role_preference_key = null, poll_ignore_key = null, req_hours = 0, feedback = FALSE) return TRUE diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 31802de2e8c0d..e936068946c1f 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -115,6 +115,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( cmd_mentor_pm(href_list["mentor_msg"], null) return TRUE + if(href_list["commandbar_typing"]) + handle_commandbar_typing(href_list) + switch(href_list["_src_"]) if("holder") hsrc = holder @@ -209,6 +212,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( tgui_say = new(src, "tgui_say") tgui_asay = new(src, "tgui_asay") + initialize_commandbar_spy() + GLOB.ahelp_tickets.ClientLogin(src) GLOB.mhelp_tickets.ClientLogin(src) GLOB.interviews.client_login(src) diff --git a/code/modules/client/verbs/typing.dm b/code/modules/client/verbs/typing.dm new file mode 100644 index 0000000000000..0fa583baa1cb6 --- /dev/null +++ b/code/modules/client/verbs/typing.dm @@ -0,0 +1,70 @@ +#define IC_VERBS list("say", "me", "whisper") + +/client/var/commandbar_thinking = FALSE +/client/var/commandbar_typing = FALSE + +/client/proc/initialize_commandbar_spy() + src << output('html/typing_indicator.html', "commandbar_spy") + +/client/proc/handle_commandbar_typing(href_list) + //if (!typing_indicators) //check pref + // return + if (length(href_list["verb"]) < 1 || !(LOWER_TEXT(href_list["verb"]) in IC_VERBS) || text2num(href_list["argument_length"]) < 1) + if (commandbar_typing) + commandbar_typing = FALSE + stop_typing() + + if (commandbar_thinking) + commandbar_thinking = FALSE + stop_thinking() + return + + if (!commandbar_thinking) + commandbar_thinking = TRUE + start_thinking() + + if (!commandbar_typing) + commandbar_typing = TRUE + start_typing() + + +/** Sets the mob as "thinking" - with indicator and the TRAIT_THINKING_IN_CHARACTER trait */ +/client/proc/start_thinking() + //if(!typing_indicators) + // return FALSE + /// Special exemptions + if(isabductor(mob)) + return FALSE + ADD_TRAIT(mob, TRAIT_THINKING_IN_CHARACTER, CURRENTLY_TYPING_TRAIT) + mob.create_thinking_indicator() + +/** Removes typing/thinking indicators and flags the mob as not thinking */ +/client/proc/stop_thinking() + mob?.remove_all_indicators() + +/** + * Handles the user typing. After a brief period of inactivity, + * signals the client mob to revert to the "thinking" icon. + */ +/client/proc/start_typing() + var/mob/client_mob = mob + client_mob.remove_thinking_indicator() + if(!HAS_TRAIT(client_mob, TRAIT_THINKING_IN_CHARACTER)) + return FALSE + client_mob.create_typing_indicator() + addtimer(CALLBACK(src, PROC_REF(stop_typing)), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_STOPPABLE) + +/** + * Callback to remove the typing indicator after a brief period of inactivity. + * If the user was typing IC, the thinking indicator is shown. + */ +/client/proc/stop_typing() + if(isnull(mob)) + return FALSE + var/mob/client_mob = mob + client_mob.remove_typing_indicator() + if(!HAS_TRAIT(client_mob, TRAIT_THINKING_IN_CHARACTER)) + return FALSE + client_mob.create_thinking_indicator() + +#undef IC_VERBS diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index af0c9c8b07bbe..2e56b19125619 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -258,8 +258,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/eavesdrop_range = 0 if(message_mods[WHISPER_MODE]) //If we're whispering eavesdrop_range = EAVESDROP_EXTRA_RANGE + var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source, SEE_INVISIBLE_MAXIMUM) var/list/the_dead = list() + for(var/mob/M as() in GLOB.player_list) if(!M) //yogs continue //yogs | null in player_list for whatever reason :shrug: diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 6161f9d1e4901..9969981ccadf7 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -233,9 +233,7 @@ CREATION_TEST_IGNORE_SELF(/mob) ///Is the mob actively shifting? var/shifting - ///Currently possesses a typing indicator icon - var/typing_indicator = FALSE - /// Thinking indicator - mob has input window open - var/thinking_indicator = FALSE - /// User is thinking in character. Used to revert to thinking state after stop_typing - var/thinking_IC = FALSE + ///the icon currently used for the typing indicator's bubble + var/active_typing_indicator + ///the icon currently used for the thinking indicator's bubble + var/active_thinking_indicator diff --git a/code/modules/tgui_input/say_modal/typing.dm b/code/modules/tgui_input/say_modal/typing.dm index 2325440d36ff3..248e419cc5fe5 100644 --- a/code/modules/tgui_input/say_modal/typing.dm +++ b/code/modules/tgui_input/say_modal/typing.dm @@ -1,8 +1,6 @@ -/// Thinking -GLOBAL_DATUM_INIT(thinking_indicator, /mutable_appearance, mutable_appearance('icons/mob/talk.dmi', "default3", CALCULATE_MOB_OVERLAY_LAYER(TYPING_LAYER))) + /// Typing GLOBAL_DATUM_INIT(blind_typing_indicator, /mutable_appearance, mutable_appearance('icons/mob/talk.dmi', "default0", (-TYPING_LAYER), BLIND_FEATURE_PLANE, appearance_flags = KEEP_TOGETHER)) -GLOBAL_DATUM_INIT(typing_indicator, /mutable_appearance, mutable_appearance('icons/mob/talk.dmi', "default0", CALCULATE_MOB_OVERLAY_LAYER(TYPING_LAYER))) /** Creates a thinking indicator over the mob. */ /mob/proc/create_thinking_indicator() @@ -33,21 +31,17 @@ GLOBAL_DATUM_INIT(typing_indicator, /mutable_appearance, mutable_appearance('ico remove_all_indicators() return ..() -/** Sets the mob as "thinking" - with indicator and variable thinking_IC */ +/** Sets the mob as "thinking" - with indicator and the TRAIT_THINKING_IN_CHARACTER trait */ /datum/tgui_say/proc/start_thinking() - if(!window_open || !istype(client.mob)) - return FALSE - /// Special exemptions - if(isabductor(client.mob)) + if(!window_open) return FALSE - client.mob.thinking_IC = TRUE - client.mob.create_thinking_indicator() + return client.start_thinking() /** Removes typing/thinking indicators and flags the mob as not thinking */ /datum/tgui_say/proc/stop_thinking() if(!istype(client.mob)) return FALSE - client.mob.remove_all_indicators() + return client.stop_thinking() /** * Handles the user typing. After a brief period of inactivity, @@ -56,53 +50,48 @@ GLOBAL_DATUM_INIT(typing_indicator, /mutable_appearance, mutable_appearance('ico /datum/tgui_say/proc/start_typing() if(!istype(client.mob)) return FALSE - client.mob.remove_thinking_indicator() - if(!window_open || !client.mob.thinking_IC) + if(!window_open) return FALSE - client.mob.create_typing_indicator() - addtimer(CALLBACK(src, PROC_REF(stop_typing)), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_STOPPABLE) + return client.start_typing() /** - * Callback to remove the typing indicator after a brief period of inactivity. + * Remove the typing indicator after a brief period of inactivity or during say events. * If the user was typing IC, the thinking indicator is shown. */ /datum/tgui_say/proc/stop_typing() - if(!client?.mob) - return FALSE - client.mob.remove_typing_indicator() - if(!window_open || !client.mob.thinking_IC) + if(!window_open) return FALSE - client.mob.create_thinking_indicator() + client.stop_typing() /// Overrides for overlay creation /mob/living/create_thinking_indicator() - if(thinking_indicator || typing_indicator || !thinking_IC || stat != CONSCIOUS ) + if(active_thinking_indicator || active_typing_indicator || stat != CONSCIOUS || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER)) return FALSE - add_overlay(GLOB.thinking_indicator) - thinking_indicator = TRUE + active_thinking_indicator = mutable_appearance('icons/mob/talk.dmi', "[bubble_icon]3", TYPING_LAYER) + add_overlay(active_thinking_indicator) /mob/living/remove_thinking_indicator() - if(!thinking_indicator) + if(!active_thinking_indicator) return FALSE - cut_overlay(GLOB.thinking_indicator) - thinking_indicator = FALSE + cut_overlay(active_thinking_indicator) + active_thinking_indicator = null /mob/living/create_typing_indicator(override = FALSE) - if(typing_indicator || ((thinking_indicator || !thinking_IC) && !override) || stat != CONSCIOUS) + if(active_typing_indicator || ((active_thinking_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER)) && !override) || stat != CONSCIOUS) return FALSE - add_overlay(GLOB.typing_indicator) + active_typing_indicator = mutable_appearance('icons/mob/talk.dmi', "[bubble_icon]0", TYPING_LAYER) + add_overlay(active_typing_indicator) add_overlay(GLOB.blind_typing_indicator) - typing_indicator = TRUE /mob/living/remove_typing_indicator() - if(!typing_indicator) + if(!active_typing_indicator) return FALSE - cut_overlay(GLOB.typing_indicator) + cut_overlay(active_typing_indicator) cut_overlay(GLOB.blind_typing_indicator) - typing_indicator = FALSE + active_typing_indicator = null /mob/living/remove_all_indicators() - thinking_IC = FALSE + REMOVE_TRAIT(src, TRAIT_THINKING_IN_CHARACTER, CURRENTLY_TYPING_TRAIT) remove_thinking_indicator() remove_typing_indicator() diff --git a/html/typing_indicator.html b/html/typing_indicator.html new file mode 100644 index 0000000000000..2988edff55fa0 --- /dev/null +++ b/html/typing_indicator.html @@ -0,0 +1,46 @@ + + +
+ + + + + + diff --git a/icons/mob/talk.dmi b/icons/mob/talk.dmi index 429e54980382a..1beb0adf98636 100644 Binary files a/icons/mob/talk.dmi and b/icons/mob/talk.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index e8643569a7a5a..335f2d218e238 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -119,6 +119,15 @@ window "mainwindow" anchor2 = none is-visible = false saved-params = "" + elem "commandbar_spy" + type = BROWSER + is-default = false + pos = 0,0 + size = 200x200 + anchor1 = -1,-1 + anchor2 = -1,-1 + is-visible = false + saved-params = "" window "mapwindow" elem "mapwindow"