diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index 5811476ad7..ca0547774f 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -9,6 +9,12 @@
return
var/style = "body"
+
+ //non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
+ if (language && (language.flags & NONVERBAL))
+ if (!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
+ message = stars(message)
+
if(!say_understands(speaker,language))
if(istype(speaker,/mob/living/simple_animal))
var/mob/living/simple_animal/S = speaker
@@ -62,6 +68,11 @@
var/style = "body"
+ //non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
+ if (language && (language.flags & NONVERBAL))
+ if (!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
+ message = stars(message)
+
if(!say_understands(speaker,language))
if(istype(speaker,/mob/living/simple_animal))
var/mob/living/simple_animal/S = speaker
@@ -145,6 +156,22 @@
else
src << "[part_a][speaker_name][part_b][verb], \"[message]\""
+/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
+ if(!client)
+ return
+
+ if(say_understands(speaker, language))
+ message = "[src] [verb], \"[message]\""
+ else
+ message = "[src] [verb]."
+
+ if(src.status_flags & PASSEMOTES)
+ for(var/obj/item/weapon/holder/H in src.contents)
+ H.show_message(message)
+ for(var/mob/living/M in src.contents)
+ M.show_message(message)
+ src.show_message(message)
+
/mob/proc/hear_sleep(var/message)
var/heard = ""
if(prob(15))
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index d35821bb15..fb5ae2fc35 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -6,6 +6,7 @@
var/name = "an unknown language" // Fluff name of language if any.
var/desc = "A language." // Short description for 'Check Languages'.
var/speech_verb = "says" // 'says', 'hisses', 'farts'.
+ var/signlang_verb = list() // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/colour = "body" // CSS style to use for strings in this language.
var/key = "x" // Character used to speak in language eg. :o for Unathi.
var/flags = 0 // Various language flags.
@@ -33,6 +34,10 @@
speech_verb = "mrowls"
colour = "tajaran_signlang"
key = "y" //only "dfpqxyz" left.
+
+ //need to find a way to resolve possesive macros
+ signlang_verb = list("flicks their left ear", "flicks their right ear", "swivels their ears", "twitches their tail", "curls the end of their tail", "arches their tail", "wiggles the end of their tail", "waves their tail about", "holds up a claw", "gestures with their left hand", "gestures with their right hand", "gestures with their tail", "gestures with their ears", "gestures with their whiskers")
+
flags = WHITELISTED | NONVERBAL
/datum/language/skrell
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 627882ab47..7cdcf46392 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -85,17 +85,30 @@ var/list/department_radio_keys = list(
var/turf/T = get_turf(src)
+ //handle nonverbal and sign languages here
+ if (speaking)
+ if (speaking.flags & NONVERBAL)
+ if (prob(50))
+ src.custom_emote(1, "[pick(speaking.signlang_verb)].")
+
+ if (speaking.flags & SIGNLANG)
+ say_signlang(message, pick(speaking.signlang_verb), speaking)
+ return
+
+ //speaking into radios
if(used_radios.len)
italics = 1
message_range = 1
for(var/mob/living/M in hearers(5, src))
if(M != src)
- M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "radio"]")
- if (speech_sound)
- var/turf/source = speaker? get_turf(speaker) : get_turf(src)
- src.playsound_local(source, speech_sound, sound_vol * 0.5, 1)
+ M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "the radio."]")
+ if (speech_sound)
+ src.playsound_local(get_turf(src), speech_sound, sound_vol * 0.5, 1)
+
+ speech_sound = null //so we don't play it twice.
+ //make sure the air can transmit speech
var/datum/gas_mixture/environment = T.return_air()
if(environment)
var/pressure = environment.return_pressure()
@@ -107,9 +120,9 @@ var/list/department_radio_keys = list(
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
var/list/listening = list()
+ var/list/listening_obj = list()
+
if(T)
-
- var/list/objects = list()
var/list/hear = hear(message_range, T)
var/list/hearturfs = list()
@@ -119,11 +132,11 @@ var/list/department_radio_keys = list(
listening += M
hearturfs += M.locs[1]
for(var/obj/O in M.contents)
- objects |= O
+ listening_obj |= O
else if(istype(I, /obj/))
var/obj/O = I
hearturfs += O.locs[1]
- objects |= O
+ listening_obj |= O
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
@@ -132,11 +145,6 @@ var/list/department_radio_keys = list(
if(M.loc && M.locs[1] in hearturfs)
listening |= M
- for(var/obj/O in objects)
- spawn(0)
- if(O) //It's possible that it could be deleted in the meantime.
- O.hear_talk(src, message, verb, speaking)
-
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) del(speech_bubble)
@@ -145,9 +153,17 @@ var/list/department_radio_keys = list(
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
-
+ for(var/obj/O in listening_obj)
+ spawn(0)
+ if(O) //It's possible that it could be deleted in the meantime.
+ O.hear_talk(src, message, verb, speaking)
+
log_say("[name]/[key] : [message]")
+/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
+ for (var/mob/O in viewers(src, null))
+ O.hear_signlang(message, verb, language, src)
+
/obj/effect/speech_bubble
var/mob/parent
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index ea44f73056..2c1b41a953 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -92,10 +92,6 @@
//Language check.
for(var/datum/language/L in src.languages)
if(speaking.name == L.name)
- if (L.flags & NONVERBAL)
- if ((src.sdisabilities & BLIND || src.blinded || src.stat) || !(other in view(src)))
- return 0
-
return 1
return 0
diff --git a/code/setup.dm b/code/setup.dm
index 3f87fb2d2a..5dcf7e8fe1 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -746,7 +746,8 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse
//Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
#define RESTRICTED 2 // Language can only be accquired by spawning or an admin.
-#define NONVERBAL 4 // Language has a significant non-verbal component.
+#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight
+#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
//Flags for zone sleeping
#define ZONE_ACTIVE 1