diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index e0a22667ac..78d1264f66 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -67,8 +67,9 @@
#define SPACEVINE_LAYER 4.8
#define SPACEVINE_MOB_LAYER 4.9
//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
-#define GASFIRE_LAYER 5.05
-#define RIPPLE_LAYER 5.1
+#define ABOVE_FLY_LAYER 5.1
+#define GASFIRE_LAYER 5.2
+#define RIPPLE_LAYER 5.3
#define GHOST_LAYER 6
#define LOW_LANDMARK_LAYER 9
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index f70f8c55bc..c7f19e600f 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -278,4 +278,4 @@
#define PULL_PRONE_SLOWDOWN 0.6
#define HUMAN_CARRY_SLOWDOWN 0
-#define TYPING_INDICATOR_TIMEOUT 10 SECONDS
+#define TYPING_INDICATOR_TIMEOUT 30 SECONDS
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index e8a57bb257..a728d13deb 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -69,6 +69,9 @@
return
next_click = world.time + world.tick_lag
+ // Hide typing indicator if we click
+ hide_typing_indicator_auto()
+
if(check_click_intercept(params,A))
return
diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm
index e0ea6350d7..271b18f86f 100644
--- a/code/modules/mob/living/living_movement.dm
+++ b/code/modules/mob/living/living_movement.dm
@@ -1,6 +1,8 @@
/mob/living/Moved()
. = ..()
update_turf_movespeed(loc)
+ //Hide typing indicator if we move.
+ hide_typing_indicator_auto()
/mob/living/CanPass(atom/movable/mover, turf/target)
if((mover.pass_flags & PASSMOB))
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 8cda504149..4ce11b4f86 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -136,3 +136,5 @@
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
+ /// Current state of our typing indicator. Used for cut overlay, DO NOT RUNTIME ASSIGN OTHER THAN FROM SHOW/CLEAR. Used to absolutely ensure we do not get stuck overlays.
+ var/typing_indicator_current
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index bca634ada9..95e504aece 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -4,14 +4,23 @@
set name = "say_keybind"
set hidden = TRUE
set category = "IC"
- return say_verb(message)
+ // If they don't type anything just drop the message.
+ clear_typing_indicator() // clear it immediately!
+ if(!length(message))
+ return
+ return do_sayverb(message)
/mob/verb/say_verb(message as text|null)
set name = "Say"
set category = "IC"
display_typing_indicator()
if(!length(message))
- message = input(usr, "Say something!", "Say") as text|null
+ // We don't use input because that can't be broken out of with ESC key.
+ winset(src, null, "command=\"say_keybind\"")
+ else
+ return do_sayverb(message)
+
+/mob/proc/do_sayverb(message)
clear_typing_indicator() // clear it immediately!
if(!length(message))
return
@@ -20,6 +29,38 @@
return
say(message)
+/mob/verb/me_keybind(message as message)
+ set name = "me_keybind"
+ set hidden = TRUE
+ set category = "IC"
+ // If they don't type anything just drop the message.
+ clear_typing_indicator() // clear it immediately!
+ if(!length(message))
+ return
+ return do_meverb(message)
+
+/mob/verb/me_verb(message as message|null)
+ set name = "Me"
+ set category = "IC"
+ display_typing_indicator()
+ if(!length(message))
+ // Do not use input because it can't be broken out of with ESC key.
+ winset(src, null, "command=\"me_keybind\"")
+ else
+ return do_meverb(message)
+
+/mob/proc/do_meverb(message)
+ clear_typing_indicator() // clear it immediately!
+ if(!length(message))
+ return
+ if(GLOB.say_disabled) //This is here to try to identify lag problems
+ to_chat(usr, "Speech is currently admin-disabled.")
+ return
+
+ message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
+
+ usr.emote("me",1,message,TRUE)
+
/mob/say_mod(input, message_mode)
var/customsayverb = findtext(input, "*")
if(customsayverb && message_mode != MODE_WHISPER_CRIT)
@@ -31,7 +72,6 @@
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
- clear_typing_indicator() // clear it immediately!
if(!length(message))
return
if(GLOB.say_disabled) //This is here to try to identify lag problems
@@ -42,29 +82,6 @@
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
-/mob/verb/me_keybind(message as message)
- set name = "me_keybind"
- set hidden = TRUE
- set category = "IC"
- return me_verb(message)
-
-/mob/verb/me_verb(message as message|null)
- set name = "Me"
- set category = "IC"
- display_typing_indicator()
- if(!length(message))
- message = input(usr, "What do you want to emote?" , "Emote") as message|null
- clear_typing_indicator() // clear it immediately!
- if(!length(message))
- return
- if(GLOB.say_disabled) //This is here to try to identify lag problems
- to_chat(usr, "Speech is currently admin-disabled.")
- return
-
- message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
-
- usr.emote("me",1,message,TRUE)
-
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm
index 4ecf930aee..f28cbe4385 100644
--- a/code/modules/mob/typing_indicator.dm
+++ b/code/modules/mob/typing_indicator.dm
@@ -22,19 +22,21 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays)
* @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) || typing_indicator_timerid)
+ if((!typing_indicator_enabled && !force) || typing_indicator_current)
return
- typing_indicator_timerid = addtimer(CALLBACK(src, .proc/clear_typing_indicator, state_override), timeout_override, TIMER_STOPPABLE)
- add_overlay(get_indicator_overlay(state_override))
+ typing_indicator_current = state_override
+ add_overlay(state_override)
+ typing_indicator_timerid = addtimer(CALLBACK(src, .proc/clear_typing_indicator), 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)
- typing_indicator_timerid = null
- cut_overlay(get_indicator_overlay(state_override))
+/mob/proc/clear_typing_indicator()
+ cut_overlay(typing_indicator_current)
+ typing_indicator_current = null
+ if(typing_indicator_timerid)
+ deltimer(typing_indicator_timerid)
+ typing_indicator_timerid = null
/// Default typing indicator
/obj/effect/overlay/typing_indicator
@@ -42,4 +44,4 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays)
icon = 'icons/mob/talk.dmi'
icon_state = "normal_typing"
appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE
- layer = LARGE_MOB_LAYER
+ layer = ABOVE_FLY_LAYER