diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index db246eb543a..366cd3e5945 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -6,7 +6,8 @@
var/throw_speed = 2
var/throw_range = 7
var/mob/pulledby = null
- var/languages = 0 //For say() and Hear()
+ var/languages_spoken = 0 //For say() and Hear()
+ var/languages_understood = 0
var/verb_say = "says"
var/verb_ask = "asks"
var/verb_exclaim = "exclaims"
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 70b4d58be49..a56ada0193f 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -84,7 +84,7 @@ This file's folder contains:
Ratvar, the Clockwork Justiciar, lies derelict and forgotten in an unseen realm."
var/mob/living/simple_animal/drone/D = M
D.update_drone_hack(TRUE, TRUE)
- D.languages |= HUMAN
+ D.languages_spoken |= HUMAN
else if(!silent)
M << "Your world glows a brilliant yellow! All at once it comes to you. Ratvar, the Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm."
diff --git a/code/game/gamemodes/devil/true_devil/_true_devil.dm b/code/game/gamemodes/devil/true_devil/_true_devil.dm
index 59adea33464..768501f4f36 100644
--- a/code/game/gamemodes/devil/true_devil/_true_devil.dm
+++ b/code/game/gamemodes/devil/true_devil/_true_devil.dm
@@ -17,7 +17,8 @@
var/ascended = 0
sight = (SEE_TURFS | SEE_OBJS)
status_flags = CANPUSH
- languages = ALL //The devil speaks all languages meme
+ languages_spoken = ALL //The devil speaks all languages meme
+ languages_understood = ALL //The devil speaks all languages meme
mob_size = MOB_SIZE_LARGE
var/mob/living/oldform
var/list/devil_overlays[DEVIL_TOTAL_LAYERS]
diff --git a/code/game/gamemodes/handofgod/god.dm b/code/game/gamemodes/handofgod/god.dm
index 98e620af048..8a9d3be7cde 100644
--- a/code/game/gamemodes/handofgod/god.dm
+++ b/code/game/gamemodes/handofgod/god.dm
@@ -8,7 +8,8 @@
see_in_dark = 0
see_invisible = 55
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
- languages = HUMAN | MONKEY | ALIEN | ROBOT | SLIME | DRONE | SWARMER
+ languages_spoken = HUMAN | MONKEY | ALIEN | ROBOT | SLIME | DRONE | SWARMER
+ languages_understood = HUMAN | MONKEY | ALIEN | ROBOT | SLIME | DRONE | SWARMER
hud_possible = list(ANTAG_HUD)
mouse_opacity = 0 //can't be clicked
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index caa390984df..7cd0cfb392d 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -81,7 +81,8 @@
melee_damage_type = STAMINA
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD)
- languages = SWARMER
+ languages_spoken = SWARMER
+ languages_understood = SWARMER
environment_smash = 0
attacktext = "shocks"
attack_sound = 'sound/effects/EMPulse.ogg'
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index 67384418a95..e77e473ae26 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -23,7 +23,8 @@
sight = SEE_SELF
see_invisible = SEE_INVISIBLE_NOLIGHTING
see_in_dark = 8
- languages = ALL
+ languages_spoken = ALL
+ languages_understood = ALL
response_help = "passes through"
response_disarm = "swings through"
response_harm = "punches through"
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index f776b3929fd..aa6500e9b37 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -37,7 +37,8 @@ var/const/HOLOPAD_MODE = RANGE_BASED
icon_state = "holopad0"
layer = LOW_OBJ_LAYER
flags = HEAR
- languages = ROBOT | HUMAN
+ languages_spoken = ROBOT | HUMAN
+ languages_understood = ROBOT | HUMAN
var/list/masters = list()//List of AIs that use the holopad
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm
index eb7b344c1fb..66c70792338 100644
--- a/code/game/machinery/telecomms/broadcasting.dm
+++ b/code/game/machinery/telecomms/broadcasting.dm
@@ -70,7 +70,8 @@
var/atom/movable/virtualspeaker/virt = PoolOrNew(/atom/movable/virtualspeaker,null)
virt.name = name
virt.job = job
- virt.languages = AM.languages
+ virt.languages_spoken = AM.languages_spoken
+ virt.languages_understood = AM.languages_understood
virt.source = AM
virt.radio = radio
virt.verb_say = verb_say
@@ -135,9 +136,9 @@
if(isobserver(M) && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTRADIO))
receive |= M
- var/rendered = virt.compose_message(virt, virt.languages, message, freq, spans) //Always call this on the virtualspeaker to advoid issues.
+ var/rendered = virt.compose_message(virt, virt.languages_spoken, message, freq, spans) //Always call this on the virtualspeaker to advoid issues.
for(var/atom/movable/hearer in receive)
- hearer.Hear(rendered, virt, AM.languages, message, freq, spans)
+ hearer.Hear(rendered, virt, AM.languages_spoken, message, freq, spans)
if(length(receive))
// --- This following recording is intended for research and feedback in the use of department radio channels ---
@@ -258,7 +259,7 @@
// --- Can understand the speech ---
- if (R.languages & M.languages)
+ if (R.languages_understood & M.languages_spoken)
heard_normal += R
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index f9c0d7e0c64..804137dd3ab 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -30,7 +30,8 @@
// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
flags = CONDUCT | HEAR
slot_flags = SLOT_BELT
- languages = HUMAN | ROBOT
+ languages_spoken = HUMAN | ROBOT
+ languages_understood = HUMAN | ROBOT
throw_speed = 3
throw_range = 7
w_class = 2
@@ -315,7 +316,7 @@
"server" = null,
"reject" = 0,
"level" = 0,
- "languages" = languages,
+ "languages" = languages_spoken,
"spans" = spans,
"verb_say" = M.verb_say,
"verb_ask" = M.verb_ask,
@@ -360,7 +361,7 @@
"server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = position.z, // The source's z level
- "languages" = M.languages, //The languages M is talking in.
+ "languages" = M.languages_spoken, //The languages M is talking in.
"spans" = spans, //the span classes of this message.
"verb_say" = M.verb_say, //the verb used when talking normally
"verb_ask" = M.verb_ask, //the verb used when asking
@@ -410,7 +411,7 @@
"server" = null,
"reject" = 0,
"level" = position.z,
- "languages" = languages,
+ "languages" = languages_spoken,
"spans" = spans,
"verb_say" = M.verb_say,
"verb_ask" = M.verb_ask,
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index 9dab01bd5e9..a459766ec94 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -6,7 +6,8 @@
w_class = 2
flags = HEAR
slot_flags = SLOT_BELT
- languages = ALL //this is a translator, after all.
+ languages_spoken = ALL //this is a translator, after all.
+ languages_understood = ALL //this is a translator, after all.
materials = list(MAT_METAL=60, MAT_GLASS=30)
force = 2
throwforce = 0
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 3972d2d2979..03e450e8a40 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -1,5 +1,6 @@
/obj
- languages = HUMAN
+ languages_spoken = HUMAN
+ languages_understood = HUMAN
var/crit_fail = 0
var/unacidable = 0 //universal "unacidabliness" var, here so you can use it in any obj.
animate_movement = 2
diff --git a/code/game/say.dm b/code/game/say.dm
index e4d53e7b5b5..1671832b9ac 100644
--- a/code/game/say.dm
+++ b/code/game/say.dm
@@ -31,9 +31,9 @@ var/list/freqtospan = list(
return 1
/atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans)
- var/rendered = compose_message(src, languages, message, , spans)
+ var/rendered = compose_message(src, languages_spoken, message, , spans)
for(var/atom/movable/AM in get_hearers_in_view(range, src))
- AM.Hear(rendered, src, languages, message, , spans)
+ AM.Hear(rendered, src, languages_spoken, message, , spans)
//To get robot span classes, stuff like that.
/atom/movable/proc/get_spans()
@@ -78,7 +78,7 @@ var/list/freqtospan = list(
return "[verb_say], \"[input]\""
/atom/movable/proc/lang_treat(atom/movable/speaker, message_langs, raw_message, list/spans)
- if(languages & message_langs)
+ if(languages_understood & message_langs)
var/atom/movable/AM = speaker.GetSource()
if(AM) //Basically means "if the speaker is virtual"
if(AM.verb_say != speaker.verb_say || AM.verb_ask != speaker.verb_ask || AM.verb_exclaim != speaker.verb_exclaim || AM.verb_yell != speaker.verb_yell) //If the saymod was changed
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 59ee81466af..088c3713073 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -550,10 +550,10 @@ var/list/admin_verbs_hideable = list(
var/message = input(usr, "What do you want the message to be?", "Make Sound") as text | null
if(!message)
return
- var/templanguages = O.languages
- O.languages |= ALL
+ var/templanguages = O.languages_spoken
+ O.languages_spoken |= ALL
O.say(message)
- O.languages = templanguages
+ O.languages_spoken = templanguages
log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z] say \"[message]\"")
message_admins("[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. say \"[message]\"")
feedback_add_details("admin_verb","OS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index bcd9ac349f0..abb4ef31ce3 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -518,13 +518,13 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
person = H
people += H
if(person) //Basic talk
- target << target.compose_message(person,person.languages,pick(speak_messages),null,person.get_spans())
+ target << target.compose_message(person,person.languages_understood,pick(speak_messages),null,person.get_spans())
else // Radio talk
var/list/humans = list()
for(var/mob/living/carbon/human/H in living_mob_list)
humans += H
person = pick(humans)
- target << target.compose_message(person,person.languages,pick(radio_messages),"1459",person.get_spans())
+ target << target.compose_message(person,person.languages_understood,pick(radio_messages),"1459",person.get_spans())
qdel(src)
/obj/effect/hallucination/message
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 5f721b106ec..b9392c9deda 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -16,7 +16,8 @@ var/list/image/ghost_images_simple = list() //this is a list of all ghost images
see_invisible = SEE_INVISIBLE_OBSERVER
see_in_dark = 100
invisibility = INVISIBILITY_OBSERVER
- languages = ALL
+ languages_spoken = ALL
+ languages_understood = ALL
var/can_reenter_corpse
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 3a79cc02f61..27fd4d679f6 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -11,7 +11,8 @@
dna = null
faction = list("alien")
ventcrawler = 2
- languages = ALIEN
+ languages_spoken = ALIEN
+ languages_understood = ALIEN
sight = SEE_MOBS
see_in_dark = 4
verb_say = "hisses"
diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm
index b51044a221c..a8c82a97520 100644
--- a/code/modules/mob/living/carbon/brain/brain.dm
+++ b/code/modules/mob/living/carbon/brain/brain.dm
@@ -1,7 +1,8 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/brain
- languages = HUMAN
+ languages_spoken = HUMAN
+ languages_understood = HUMAN
var/obj/item/device/mmi/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index d631c731d78..826b009e249 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -1,6 +1,7 @@
var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
- languages = HUMAN
+ languages_spoken = HUMAN
+ languages_understood = HUMAN
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
//Hair colour and style
var/hair_color = "000"
diff --git a/code/modules/mob/living/carbon/human/whisper.dm b/code/modules/mob/living/carbon/human/whisper.dm
index ef0bbd93d1b..c24342572ce 100644
--- a/code/modules/mob/living/carbon/human/whisper.dm
+++ b/code/modules/mob/living/carbon/human/whisper.dm
@@ -71,14 +71,14 @@
for(var/atom/movable/AM in listening)
if(istype(AM,/obj/item/device/radio))
continue
- AM.Hear(rendered, src, languages, message, , spans)
+ AM.Hear(rendered, src, languages_spoken, message, , spans)
message = stars(message)
rendered = "[GetVoice()][alt_name] [whispers], "
for(var/atom/movable/AM in eavesdropping)
if(istype(AM,/obj/item/device/radio))
continue
- AM.Hear(rendered, src, languages, message, , spans)
+ AM.Hear(rendered, src, languages_spoken, message, , spans)
if(critical) //Dying words.
succumb(1)
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index f2d3ede4024..344fcf1c7f7 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -6,7 +6,8 @@
icon_state = "monkey1"
gender = NEUTER
pass_flags = PASSTABLE
- languages = MONKEY
+ languages_spoken = MONKEY
+ languages_understood = MONKEY
ventcrawler = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index a456046c5d5..4b6d6c05ebc 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -1,6 +1,7 @@
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
- languages = HUMAN
+ languages_spoken = HUMAN
+ languages_understood = HUMAN
sight = 0
see_in_dark = 2
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 3aa10d00342..7b4793a4cca 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -136,7 +136,7 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
else
deaf_message = "You can't hear yourself!"
deaf_type = 2 // Since you should be able to hear yourself without looking
- if(!(message_langs & languages) || force_compose) //force_compose is so AIs don't end up without their hrefs.
+ if(!(message_langs & languages_understood) || force_compose) //force_compose is so AIs don't end up without their hrefs.
message = compose_message(speaker, message_langs, raw_message, radio_freq, spans)
show_message(message, 2, deaf_message, deaf_type)
return message
@@ -147,9 +147,9 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTEARS) || (get_dist(M, src) <= 7)) && client) // client is so that ghosts don't have to listen to mice
listening |= M
- var/rendered = compose_message(src, languages, message, , spans)
+ var/rendered = compose_message(src, languages_spoken, message, , spans)
for(var/atom/movable/AM in listening)
- AM.Hear(rendered, src, languages, message, , spans)
+ AM.Hear(rendered, src, languages_spoken, message, , spans)
//speech bubble
var/list/speech_bubble_recipients = list()
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index a330a5e53e4..7ccef7e871b 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -253,7 +253,9 @@
med.remove_hud_from(src)
if("translator")
if(href_list["toggle"])
- languages = (languages == ALL) ? (HUMAN | ROBOT) : ALL
+ var/on_already = ((languages_understood == ALL) && (languages_spoken == ALL))
+ languages_spoken = on_already ? (HUMAN | ROBOT) : ALL
+ languages_understood = on_already ? (HUMAN | ROBOT) : ALL
if("doorjack")
if(href_list["jack"])
if(src.cable && src.cable.machine)
@@ -311,7 +313,7 @@
if(s == "medical HUD")
dat += "Medical Analysis Suite[(src.medHUD) ? " On" : " Off"]
"
if(s == "universal translator")
- dat += "Universal Translator[(languages == ALL) ? " On" : " Off"]
"
+ dat += "Universal Translator[((languages_spoken == ALL) && (languages_understood == ALL)) ? " On" : " Off"]
"
if(s == "projection array")
dat += "Projection Array
"
if(s == "camera jack")
@@ -464,7 +466,7 @@
/mob/living/silicon/pai/proc/softwareTranslator()
. = {"