diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index f688e10034cc..5cc0a089ed5d 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -187,3 +187,5 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
+
+#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob))
\ No newline at end of file
diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm
index d30eb36132f4..74a166968609 100644
--- a/code/__DEFINES/say.dm
+++ b/code/__DEFINES/say.dm
@@ -49,4 +49,10 @@
#define LOGCHAT "chat"
#define LOGASAY "adminsay"
#define LOGCOMMENT "comment"
-#define LOGOOC "ooc"
\ No newline at end of file
+#define LOGOOC "ooc"
+
+
+#define LINGHIVE_NONE 0
+#define LINGHIVE_OUTSIDER 1
+#define LINGHIVE_LING 2
+#define LINGHIVE_LINK 3
\ No newline at end of file
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index e819060afbce..aeadfcf94e3c 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(atoms)
initialized = INITIALIZATION_INNEW_MAPLOAD
LAZYINITLIST(late_loaders)
-
+
var/count
var/list/mapload_arg = list(TRUE)
if(atoms)
@@ -60,10 +60,10 @@ SUBSYSTEM_DEF(atoms)
A.LateInitialize()
testing("Late initialized [late_loaders.len] atoms")
late_loaders.Cut()
-
+
if(atoms)
. = created_atoms + atoms
- created_atoms = null
+ created_atoms = null
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
var/the_type = A.type
@@ -77,7 +77,7 @@ SUBSYSTEM_DEF(atoms)
if(start_tick != world.time)
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
-
+
var/qdeleted = FALSE
if(result != INITIALIZE_HINT_NORMAL)
@@ -92,12 +92,12 @@ SUBSYSTEM_DEF(atoms)
qdeleted = TRUE
else
BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
-
+
if(!A) //possible harddel
qdeleted = TRUE
else if(!A.initialized)
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
-
+
return qdeleted || QDELING(A)
/datum/controller/subsystem/atoms/proc/map_loader_begin()
diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm
index de605cb5548e..43803aa64756 100644
--- a/code/controllers/subsystem/radio.dm
+++ b/code/controllers/subsystem/radio.dm
@@ -3,6 +3,13 @@ SUBSYSTEM_DEF(radio)
flags = SS_NO_FIRE|SS_NO_INIT
var/list/datum/radio_frequency/frequencies = list()
+ var/list/saymodes = list()
+
+/datum/controller/subsystem/radio/PreInit(timeofday)
+ for(var/_SM in subtypesof(/datum/saymode))
+ var/datum/saymode/SM = new _SM()
+ saymodes[SM.key] = SM
+ return ..()
/datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null)
var/f_text = num2text(new_frequency)
diff --git a/code/datums/saymode.dm b/code/datums/saymode.dm
new file mode 100644
index 000000000000..6aa1c48d8abd
--- /dev/null
+++ b/code/datums/saymode.dm
@@ -0,0 +1,112 @@
+/datum/saymode
+ var/key
+ var/mode
+
+//Return FALSE if you have handled the message. Otherwise, return TRUE and saycode will continue doing saycode things.
+//user = whoever said the message
+//message = the message
+//language = the language.
+/datum/saymode/proc/handle_message(mob/living/user, message, datum/language/language)
+ return TRUE
+
+
+/datum/saymode/changeling
+ key = "g"
+ mode = MODE_CHANGELING
+
+/datum/saymode/changeling/handle_message(mob/living/user, message, datum/language/language)
+ switch(user.lingcheck())
+ if(LINGHIVE_LINK)
+ var/msg = "[user.mind]: [message]"
+ for(var/_M in GLOB.mob_list)
+ var/mob/M = _M
+ if(M in GLOB.dead_mob_list)
+ var/link = FOLLOW_LINK(M, user)
+ to_chat(M, "[link] [msg]")
+ else
+ switch(M.lingcheck())
+ if(LINGHIVE_LINK, LINGHIVE_LING)
+ to_chat(M, msg)
+ if(LINGHIVE_OUTSIDER)
+ if(prob(40))
+ to_chat(M, "We can faintly sense an outsider trying to communicate through the hivemind...")
+ if(LINGHIVE_LING)
+ var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
+ var/msg = "[changeling.changelingID]: [message]"
+ log_talk(src,"[changeling.changelingID]/[user.key] : [message]",LOGSAY)
+ for(var/_M in GLOB.mob_list)
+ var/mob/M = _M
+ if(M in GLOB.dead_mob_list)
+ var/link = FOLLOW_LINK(M, user)
+ to_chat(M, "[link] [msg]")
+ else
+ switch(M.lingcheck())
+ if(LINGHIVE_LINK)
+ to_chat(M, msg)
+ if(LINGHIVE_LING)
+ to_chat(M, msg)
+ if(LINGHIVE_OUTSIDER)
+ if(prob(40))
+ to_chat(M, "We can faintly sense another of our kind trying to communicate through the hivemind...")
+ if(LINGHIVE_OUTSIDER)
+ to_chat(user, "Our senses have not evolved enough to be able to communicate this way...")
+ return FALSE
+
+
+/datum/saymode/xeno
+ key = "a"
+ mode = MODE_ALIEN
+
+/datum/saymode/xeno/handle_message(mob/living/user, message, datum/language/language)
+ if(user.hivecheck())
+ user.alien_talk(message)
+ return FALSE
+
+
+/datum/saymode/vocalcords
+ key = "x"
+ mode = MODE_VOCALCORDS
+
+/datum/saymode/vocalcords/handle_message(mob/living/user, message, datum/language/language)
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ var/obj/item/organ/vocal_cords/V = C.getorganslot(ORGAN_SLOT_VOICE)
+ if(V && V.can_speak_with())
+ V.handle_speech(message) //message
+ V.speak_with(message) //action
+ return FALSE
+
+
+/datum/saymode/binary //everything that uses .b (silicons, drones, blobbernauts/spores, swarmers)
+ key = "b"
+ mode = MODE_BINARY
+
+/datum/saymode/binary/handle_message(mob/living/user, message, datum/language/language)
+ if(isswarmer(user))
+ var/mob/living/simple_animal/hostile/swarmer/S = user
+ S.swarmer_chat(message)
+ return FALSE
+ if(isblobmonster(user))
+ var/mob/living/simple_animal/hostile/blob/B = user
+ B.blob_chat(message)
+ return FALSE
+ if(isdrone(user))
+ var/mob/living/simple_animal/drone/D = user
+ D.drone_chat(message)
+ return FALSE
+ if(user.binarycheck())
+ user.robot_talk(message)
+ return FALSE
+ return FALSE
+
+
+/datum/saymode/holopad
+ key = "h"
+ mode = MODE_HOLOPAD
+
+/datum/saymode/holopad/handle_message(mob/living/user, message, datum/language/language)
+ if(isAI(user))
+ var/mob/living/silicon/ai/AI = user
+ AI.holopad_talk(message, language)
+ return FALSE
+ return FALSE
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index 5572bbd9d889..c5c813ecfcd2 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -56,13 +56,6 @@
return 1
return ..()
-/mob/living/simple_animal/hostile/blob/handle_inherent_channels(message, message_mode)
- if(message_mode == MODE_BINARY)
- blob_chat(message)
- return 1
- else
- ..()
-
/mob/living/simple_animal/hostile/blob/proc/blob_chat(msg)
var/spanned_message = say_quote(msg, get_spans())
var/rendered = "\[Blob Telepathy\] [real_name] [spanned_message]"
diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm
index d6ceb4edd0a6..cd7c94413729 100644
--- a/code/game/gamemodes/changeling/powers/linglink.dm
+++ b/code/game/gamemodes/changeling/powers/linglink.dm
@@ -50,7 +50,7 @@
to_chat(target, "A migraine throbs behind your eyes, you hear yourself screaming - but your mouth has not opened!")
for(var/mi in GLOB.mob_list)
var/mob/M = mi
- if(M.lingcheck() == 2)
+ if(M.lingcheck() == LINGHIVE_LING)
to_chat(M, "We can sense a foreign presence in the hivemind...")
target.mind.linglink = 1
target.say(":g AAAAARRRRGGGGGHHHHH!!")
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 0287dadfdb2f..c26bb584ee86 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -120,13 +120,6 @@
if(statpanel("Status"))
stat("Resources:",resources)
-/mob/living/simple_animal/hostile/swarmer/handle_inherent_channels(message, message_mode)
- if(message_mode == MODE_BINARY)
- swarmer_chat(message)
- return ITALICS | REDUCE_RANGE
- else
- . = ..()
-
/mob/living/simple_animal/hostile/swarmer/get_spans()
return ..() | SPAN_ROBOT
diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm
index 0cfbf5d17006..0f8e9e60bdcb 100644
--- a/code/modules/mob/living/brain/say.dm
+++ b/code/modules/mob/living/brain/say.dm
@@ -21,7 +21,7 @@
return ITALICS | REDUCE_RANGE
/mob/living/brain/lingcheck()
- return 0
+ return LINGHIVE_NONE
/mob/living/brain/treat_message(message)
message = capitalize(message)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index c9a8ee6a6abe..a05cc80d319d 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1009,4 +1009,15 @@
/mob/living/proc/add_abilities_to_panel()
for(var/obj/effect/proc_holder/A in abilities)
- statpanel("[A.panel]",A.get_panel_text(),A)
\ No newline at end of file
+ statpanel("[A.panel]",A.get_panel_text(),A)
+
+/mob/living/lingcheck()
+ if(mind)
+ var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
+ if(changeling)
+ if(changeling.changeling_speak)
+ return LINGHIVE_LING
+ return LINGHIVE_OUTSIDER
+ if(mind && mind.linglink)
+ return LINGHIVE_LINK
+ return LINGHIVE_NONE
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 2056bcba25f5..739b4e358491 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -37,41 +37,42 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
//kinda localization -- rastaf0
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
// Location
- "ê" = "right hand",
- "ä" = "left hand",
- "ø" = "intercom",
+ "ê" = "right hand",
+ "ä" = "left hand",
+ "ø" = "intercom",
// Department
- "ð" = "department",
- "ñ" = "Command",
- "ò" = "Science",
- "ü" = "Medical",
- "ó" = "Engineering",
- "û" = "Security",
- "ã" = "Supply",
- "ì" = "Service",
+ "ð" = "department",
+ "ñ" = "Command",
+ "ò" = "Science",
+ "ü" = "Medical",
+ "ó" = "Engineering",
+ "û" = "Security",
+ "ã" = "Supply",
+ "ì" = "Service",
// Faction
- "Ã¥" = "Syndicate",
- "Ã" = "CentCom",
+ "å" = "Syndicate",
+ "í" = "CentCom",
// Species
- "è" = "binary",
- "ï" = "changeling",
- "ô" = "alientalk",
+ "è" = "binary",
+ "ï" = "changeling",
+ "ô" = "alientalk",
// Admin
- "ç" = "admin",
- "â" = "deadmin",
+ "ç" = "admin",
+ "â" = "deadmin",
// Misc
- "ù" = "AI Private",
- "÷" = "cords"
+ "ù" = "AI Private",
+ "÷" = "cords"
))
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE)
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
+ var/key = get_key(message)
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
@@ -134,8 +135,11 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
// AIs use inherent channels for the holopad. Most inherent channels
// ignore the language argument however.
- if(handle_inherent_channels(message, message_mode, language)) //Hiveminds, binary chat & holopad.
- return
+ var/datum/saymode/SM = SSradio.saymodes[key]
+ if(key && SM)
+ if(!SM.handle_message(src, message, language))
+ return
+
if(!can_speak_vocal(message))
to_chat(src, "You find yourself unable to speak!")
@@ -264,7 +268,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
/mob/proc/binarycheck()
- return 0
+ return FALSE
/mob/living/can_speak(message) //For use outside of Say()
if(can_speak_basic(message) && can_speak_vocal(message))
@@ -307,6 +311,11 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/key_symbol = lowertext(copytext(message, 2, 3))
return GLOB.department_radio_keys[key_symbol]
+/mob/living/proc/get_key(message)
+ var/key = copytext(message, 1, 2)
+ if(key in GLOB.department_radio_prefixes)
+ return lowertext(copytext(message, 2, 3))
+
/mob/living/proc/get_message_language(message)
if(copytext(message, 1, 2) == ",")
var/key = copytext(message, 2, 3)
@@ -316,60 +325,6 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return LD
return null
-/mob/living/proc/handle_inherent_channels(message, message_mode)
- if(message_mode == MODE_CHANGELING)
- switch(lingcheck())
- if(3)
- var/msg = "[src.mind]: [message]"
- for(var/_M in GLOB.mob_list)
- var/mob/M = _M
- if(M in GLOB.dead_mob_list)
- var/link = FOLLOW_LINK(M, src)
- to_chat(M, "[link] [msg]")
- else
- switch(M.lingcheck())
- if(3)
- to_chat(M, msg)
- if(2)
- to_chat(M, msg)
- if(1)
- if(prob(40))
- to_chat(M, "We can faintly sense an outsider trying to communicate through the hivemind...")
- if(2)
- var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
- var/msg = "[changeling.changelingID]: [message]"
- log_talk(src,"[changeling.changelingID]/[key] : [message]",LOGSAY)
- for(var/_M in GLOB.mob_list)
- var/mob/M = _M
- if(M in GLOB.dead_mob_list)
- var/link = FOLLOW_LINK(M, src)
- to_chat(M, "[link] [msg]")
- else
- switch(M.lingcheck())
- if(3)
- to_chat(M, msg)
- if(2)
- to_chat(M, msg)
- if(1)
- if(prob(40))
- to_chat(M, "We can faintly sense another of our kind trying to communicate through the hivemind...")
- if(1)
- to_chat(src, "Our senses have not evolved enough to be able to communicate this way...")
- return TRUE
- if(message_mode == MODE_ALIEN)
- if(hivecheck())
- alien_talk(message)
- return TRUE
- if(message_mode == MODE_VOCALCORDS)
- if(iscarbon(src))
- var/mob/living/carbon/C = src
- var/obj/item/organ/vocal_cords/V = C.getorganslot(ORGAN_SLOT_VOICE)
- if(V && V.can_speak_with())
- V.handle_speech(message) //message
- V.speak_with(message) //action
- return TRUE
- return FALSE
-
/mob/living/proc/treat_message(message)
if(getBrainLoss() >= 60)
message = derpspeech(message, stuttering)
@@ -408,22 +363,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return ITALICS | REDUCE_RANGE
if(MODE_BINARY)
- if(binarycheck())
- robot_talk(message)
return ITALICS | REDUCE_RANGE //Does not return 0 since this is only reached by humans, not borgs or AIs.
return 0
-/mob/living/lingcheck() //1 is ling w/ no hivemind. 2 is ling w/hivemind. 3 is ling victim being linked into hivemind.
- if(mind)
- var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
- if(changeling)
- if(changeling.changeling_speak)
- return 2
- return 1
- if(mind && mind.linglink)
- return 3
- return 0
-
/mob/living/say_mod(input, message_mode)
if(message_mode == MODE_WHISPER)
. = verb_whisper
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index 13f0609c0d87..b55fa2a6634d 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -31,15 +31,6 @@
else
return ..()
-/mob/living/silicon/ai/handle_inherent_channels(message, message_mode, language)
- . = ..()
- if(.)
- return .
-
- if(message_mode == MODE_HOLOPAD)
- holopad_talk(message, language)
- return 1
-
//For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(message, language)
diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm
index f3e7baa0d9c1..f10ac438588e 100644
--- a/code/modules/mob/living/silicon/say.dm
+++ b/code/modules/mob/living/silicon/say.dm
@@ -57,14 +57,3 @@
return MODE_ROBOT
else
return .
-
-/mob/living/silicon/handle_inherent_channels(message, message_mode)
- . = ..()
- if(.)
- return .
-
- if(message_mode == MODE_BINARY)
- if(binarycheck())
- robot_talk(message)
- return 1
- return 0
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/say.dm b/code/modules/mob/living/simple_animal/friendly/drone/say.dm
index fb0c0c06145d..16bf370f0236 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/say.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/say.dm
@@ -3,14 +3,6 @@
/////////////
//Drone speach
-/mob/living/simple_animal/drone/handle_inherent_channels(message, message_mode)
- if(message_mode == MODE_BINARY)
- drone_chat(message)
- return 1
- else
- ..()
-
-
/mob/living/simple_animal/drone/get_spans()
return ..() | SPAN_ROBOT
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index b0491c657bfe..7ffa7f8ed0e4 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -79,4 +79,4 @@
return 0
/mob/proc/lingcheck()
- return 0
+ return LINGHIVE_NONE
diff --git a/tgstation.dme b/tgstation.dme
index 69bd4b80485b..ea6efb181602 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -267,6 +267,7 @@
#include "code\datums\recipe.dm"
#include "code\datums\riding.dm"
#include "code\datums\ruins.dm"
+#include "code\datums\saymode.dm"
#include "code\datums\shuttles.dm"
#include "code\datums\soullink.dm"
#include "code\datums\spawners_menu.dm"