diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index e121f55216..6d8ee456e7 100644
--- a/code/__defines/is_helpers.dm
+++ b/code/__defines/is_helpers.dm
@@ -13,6 +13,8 @@
#define isitem(D) istype(D, /obj/item)
+#define isradio(A) istype(A, /obj/item/device/radio)
+
#define isairlock(A) istype(A, /obj/machinery/door/airlock)
#define isorgan(A) istype(A, /obj/item/organ/external)
@@ -51,5 +53,9 @@
//---------------
//#define isturf(D) istype(D, /turf) //Built in
+<<<<<<< HEAD
#define isopenspace(A) istype(A, /turf/simulated/open)
#define isspace(A) istype(A, /turf/space)
+=======
+#define isopenspace(A) istype(A, /turf/simulated/open)
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 22f8c86e43..e1505934e8 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -374,3 +374,7 @@ var/global/list/##LIST_NAME = list();\
#define MOUSE_OPACITY_TRANSPARENT 0
#define MOUSE_OPACITY_ICON 1
#define MOUSE_OPACITY_OPAQUE 2
+
+// Used by radios to indicate that they have sent a message via something other than subspace
+#define RADIO_CONNECTION_FAIL 0
+#define RADIO_CONNECTION_NON_SUBSPACE 1
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 4fec2cba82..ab86d71df2 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -92,22 +92,11 @@ var/const/HOLOPAD_MODE = RANGE_BASED
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
-/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb, datum/language/speaking)
- if(M)
+/obj/machinery/hologram/holopad/hear_talk(mob/M, list/message_pieces, verb)
+ if(M && LAZYLEN(masters))
for(var/mob/living/silicon/ai/master in masters)
- if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad.
- if(speaking)
- text = speaking.scramble(text)
- else
- text = stars(text)
- var/name_used = M.GetVoice()
- //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
- var/rendered
- if(speaking)
- rendered = "Holopad received, [name_used] [speaking.format_message(text, verb)]"
- else
- rendered = "Holopad received, [name_used] [verb], \"[text]\""
- master.show_message(rendered, 2)
+ if(masters[master] && M != master)
+ master.relay_speech(M, message_pieces, verb)
/obj/machinery/hologram/holopad/see_emote(mob/living/M, text)
if(M)
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index b3c524a5ad..89c1fd30ac 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -86,7 +86,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], DATA_NORMAL,
signal.data["compression"], signal.data["level"], signal.frequency,
+<<<<<<< HEAD
signal.data["verb"], signal.data["language"], forced_radios)
+=======
+ signal.data["verb"])
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
/** #### - Simple Broadcast - #### **/
@@ -111,9 +115,14 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
+<<<<<<< HEAD
signal.data["realname"], signal.data["vname"], DATA_FAKE,
signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"], signal.data["language"], forced_radios)
+=======
+ signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency,
+ signal.data["verb"])
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
if(!message_delay)
message_delay = 1
@@ -270,18 +279,30 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
+<<<<<<< HEAD
signal.data["realname"], signal.data["vname"], DATA_NORMAL,
signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], signal.data["language"], forced_radios)
+=======
+ signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency,
+ signal.data["verb"])
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
else
if(intercept)
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
+<<<<<<< HEAD
signal.data["realname"], signal.data["vname"], DATA_ANTAG,
signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], signal.data["language"], forced_radios)
+=======
+ signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency,
+ signal.data["verb"])
+
+
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
/**
@@ -341,10 +362,16 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
**/
/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
+<<<<<<< HEAD
var/vmask, var/vmessage, var/obj/item/device/radio/radio,
var/message, var/name, var/job, var/realname, var/vname,
var/data, var/compression, var/list/level, var/freq, var/verbage = "says",
var/datum/language/speaking = null, var/list/forced_radios)
+=======
+ var/vmask, var/list/vmessage_pieces, var/obj/item/device/radio/radio,
+ var/list/message_pieces, var/name, var/job, var/realname, var/vname,
+ var/data, var/compression, var/list/level, var/freq, var/verbage = "says")
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
/* ###### Prepare the radio connection ###### */
@@ -412,7 +439,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
for (var/mob/R in receive)
/* --- Loop through the receivers and categorize them --- */
- if (!R.is_preference_enabled(/datum/client_preference/holder/hear_radio))
+ if(!R.is_preference_enabled(/datum/client_preference/holder/hear_radio))
continue
if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes.
@@ -429,10 +456,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Can understand the speech ---
- if (!M || R.say_understands(M))
+ if(!M || R.say_understands(M))
// - Not human or wearing a voice mask -
- if (!M || !ishuman(M) || vmask)
+ if(!M || !ishuman(M) || vmask)
heard_masked += R
// - Human and not wearing voice mask -
@@ -443,7 +470,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
else
// - The speaker has a prespecified "voice message" to display if not understood -
- if (vmessage)
+ if(vmessage_pieces)
heard_voice += R
// - Just display a garbled message -
@@ -452,7 +479,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* ###### Begin formatting and sending the message ###### */
- if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
+ if(length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
/* --- Some miscellaneous variables to format the string output --- */
var/freq_text = get_frequency_name(display_freq)
@@ -468,12 +495,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Filter the message; place it in quotes apply a verb ---
-
var/quotedmsg = null
if(M)
- quotedmsg = M.say_quote(message)
+ quotedmsg = "[M.say_quote(multilingual_to_message(message_pieces))], \"[multilingual_to_message(message_pieces)]\""
else
- quotedmsg = "says, \"[message]\""
+ quotedmsg = "says, \"[multilingual_to_message(message_pieces)]\""
// --- This following recording is intended for research and feedback in the use of department radio channels ---
@@ -514,44 +540,41 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
//End of research and feedback code.
/* ###### Send the message ###### */
-
-
/* --- Process all the mobs that heard a masked voice (understood) --- */
-
- if (length(heard_masked))
+ if(length(heard_masked))
for (var/mob/R in heard_masked)
- R.hear_radio(message,verbage, speaking, part_a, part_b, part_c, M, 0, name)
+ R.hear_radio(message_pieces, verbage, part_a, part_b, part_c, M, 0, name)
/* --- Process all the mobs that heard the voice normally (understood) --- */
-
- if (length(heard_normal))
+ if(length(heard_normal))
for (var/mob/R in heard_normal)
- R.hear_radio(message, verbage, speaking, part_a, part_b, part_c, M, 0, realname)
+ R.hear_radio(message_pieces, verbage, part_a, part_b, part_c, M, 0, realname)
/* --- Process all the mobs that heard the voice normally (did not understand) --- */
-
- if (length(heard_voice))
+ if(length(heard_voice))
for (var/mob/R in heard_voice)
- R.hear_radio(message,verbage, speaking, part_a, part_b, part_c, M,0, vname)
+ R.hear_radio(message_pieces, verbage, part_a, part_b, part_c, M,0, vname)
/* --- Process all the mobs that heard a garbled voice (did not understand) --- */
// Displays garbled message (ie "f*c* **u, **i*er!")
-
- if (length(heard_garbled))
+ if(length(heard_garbled))
for (var/mob/R in heard_garbled)
- R.hear_radio(message, verbage, speaking, part_a, part_b, part_c, M, 1, vname)
-
+ R.hear_radio(message_pieces, verbage, part_a, part_b, part_c, M, 1, vname)
/* --- Complete gibberish. Usually happens when there's a compressed message --- */
-
- if (length(heard_gibberish))
+ if(length(heard_gibberish))
for (var/mob/R in heard_gibberish)
- R.hear_radio(message, verbage, speaking, part_a, part_b, part_c, M, 1)
+ R.hear_radio(message_pieces, verbage, part_a, part_b, part_c, M, 1)
return 1
+<<<<<<< HEAD
/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level, var/list/forced_radios)
+=======
+/proc/Broadcast_SimpleMessage(var/source, var/frequency, list/message_pieces, var/data, var/mob/M, var/compression, var/level)
+ var/text = multilingual_to_message(message_pieces)
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
/* ###### Prepare the radio connection ###### */
if(!M)
@@ -633,7 +656,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Can understand the speech ---
- if (R.say_understands(M))
+ if(R.say_understands(M))
heard_normal += R
@@ -646,7 +669,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* ###### Begin formatting and sending the message ###### */
- if (length(heard_normal) || length(heard_garbled) || length(heard_gibberish))
+ if(length(heard_normal) || length(heard_garbled) || length(heard_gibberish))
/* --- Some miscellaneous variables to format the string output --- */
var/part_a = "" // goes in the actual output
@@ -701,7 +724,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Process all the mobs that heard the voice normally (understood) --- */
- if (length(heard_normal))
+ if(length(heard_normal))
var/rendered = "[part_a][source][part_b]\"[text]\"[part_c]"
for (var/mob/R in heard_normal)
@@ -710,7 +733,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Process all the mobs that heard a garbled voice (did not understand) --- */
// Displays garbled message (ie "f*c* **u, **i*er!")
- if (length(heard_garbled))
+ if(length(heard_garbled))
var/quotedmsg = "\"[stars(text)]\""
var/rendered = "[part_a][source][part_b][quotedmsg][part_c]"
@@ -720,7 +743,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Complete gibberish. Usually happens when there's a compressed message --- */
- if (length(heard_gibberish))
+ if(length(heard_gibberish))
var/quotedmsg = "\"[Gibberish(text, compression + 50)]\""
var/rendered = "[part_a][Gibberish(source, compression + 50)][part_b][quotedmsg][part_c]"
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 1fffddbd1f..ac6e56cee3 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -602,7 +602,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
var/encryption = "null" // encryption key: ie "password"
var/salt = "null" // encryption salt: ie "123comsat"
// would add up to md5("password123comsat")
- var/language = "human"
var/obj/item/device/radio/headset/server_radio = null
/obj/machinery/telecomms/server/New()
@@ -643,12 +642,11 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
log.parameters["mobtype"] = signal.data["mobtype"]
log.parameters["job"] = signal.data["job"]
log.parameters["key"] = signal.data["key"]
- log.parameters["vmessage"] = signal.data["message"]
+ log.parameters["vmessage"] = multilingual_to_message(signal.data["message"])
log.parameters["vname"] = signal.data["vname"]
- log.parameters["message"] = signal.data["message"]
+ log.parameters["message"] = multilingual_to_message(signal.data["message"])
log.parameters["name"] = signal.data["name"]
log.parameters["realname"] = signal.data["realname"]
- log.parameters["language"] = signal.data["language"]
var/race = "unknown"
if(ishuman(M))
@@ -677,7 +675,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// If the signal is still compressed, make the log entry gibberish
if(signal.data["compression"] > 0)
- log.parameters["message"] = Gibberish(signal.data["message"], signal.data["compression"] + 50)
+ log.parameters["message"] = Gibberish(multilingual_to_message(signal.data["message"]), signal.data["compression"] + 50)
log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50)
log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50)
log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50)
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index b58956579a..b5d3351b21 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -119,134 +119,6 @@
melee_can_hit = 1
return
-/*
-/obj/mecha/combat/proc/mega_shake(target)
- if(!istype(target, /obj) && !istype(target, /mob)) return
- if(istype(target, /mob))
- var/mob/M = target
- M.make_dizzy(3)
- M.adjustBruteLoss(1)
- M.updatehealth()
- for (var/mob/V in viewers(src))
- V.show_message("[src.name] shakes [M] like a rag doll.")
- return
-*/
-
-/*
- if(energy>0 && can_move)
- if(step(src,direction))
- can_move = 0
- spawn(step_in) can_move = 1
- if(overload)
- energy = energy-2
- health--
- else
- energy--
- return 1
-
- return 0
-*/
-/*
-/obj/mecha/combat/hear_talk(mob/M as mob, text)
- ..()
- if(am && M==occupant)
- if(findtext(text,""))
- sam()
- return
-
-/obj/mecha/combat/proc/sam()
- if(am)
- var/window = {"
-
-
-
-
-
-
-
-
- "}
- occupant << browse(window, "window=sam;size=800x600;")
- onclose(occupant, "sam", src)
- return
-*/
/obj/mecha/combat/moved_inside(var/mob/living/carbon/human/H as mob)
if(..())
if(H.client)
@@ -275,10 +147,3 @@
if(top_filter.get("close"))
am = null
return
- /*
- if(top_filter.get("saminput"))
- if(md5(top_filter.get("saminput")) == am)
- occupant_message("From the lies of the Antipath, Circuit preserve us.")
- am = null
- return
- */
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index d9198cc6e7..1e4f4dc8ae 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -290,10 +290,9 @@
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
return
-/obj/mecha/hear_talk(mob/M as mob, text)
- if(M==occupant && radio.broadcasting)
- radio.talk_into(M, text)
- return
+/obj/mecha/hear_talk(mob/M, list/message_pieces, verb)
+ if(M == occupant && radio.broadcasting)
+ radio.talk_into(M, message_pieces)
////////////////////////////
///// Action processing ////
diff --git a/code/game/objects/items/devices/communicator/phone.dm b/code/game/objects/items/devices/communicator/phone.dm
index 3042b06fa9..d7816fbb82 100644
--- a/code/game/objects/items/devices/communicator/phone.dm
+++ b/code/game/objects/items/devices/communicator/phone.dm
@@ -227,12 +227,12 @@
..()
// Proc: hear_talk()
-// Parameters: 4 (M - the mob the speech originated from, text - what is being said, verb - the word used to describe how text is being said, speaking - language
-// being used)
+// Parameters: 3 (M - the mob the speech originated from,
+// list/message_pieces - what is being said w/ baked languages,
+// verb - the word used to describe how text is being said)
// Description: Relays the speech to all linked communicators.
-/obj/item/device/communicator/hear_talk(mob/living/M, text, verb, datum/language/speaking)
+/obj/item/device/communicator/hear_talk(mob/M, list/message_pieces, verb)
for(var/obj/item/device/communicator/comm in communicating)
-
var/turf/T = get_turf(comm)
if(!T) return
//VOREStation Edit Start for commlinks
@@ -246,18 +246,10 @@
//VOREStation Edit End
for(var/mob/mob in mobs_to_relay)
- //Can whoever is hearing us understand?
- if(!mob.say_understands(M, speaking))
- if(speaking)
- text = speaking.scramble(text)
- else
- text = stars(text)
+ var/message = mob.combine_message(message_pieces, verb, M)
var/name_used = M.GetVoice()
var/rendered = null
- if(speaking) //Language being used
- rendered = "[bicon(src)] [name_used] [speaking.format_message(text, verb)]"
- else
- rendered = "[bicon(src)] [name_used] [verb], \"[text]\""
+ rendered = "[bicon(src)] [name_used] [message]"
mob.show_message(rendered, 2)
// Proc: show_message()
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 0a12b31df2..7e7bbdb629 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -10,53 +10,52 @@
var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!")
/obj/item/device/megaphone/proc/can_broadcast(var/mob/living/user)
- if (user.client)
+ if(user.client)
if(user.client.prefs.muted & MUTE_IC)
to_chat(user, "You cannot speak in IC (muted).")
- return 0
+ return FALSE
if(!(ishuman(user) || user.isSynthetic()))
to_chat(user, "You don't know how to use this!")
- return 0
+ return FALSE
if(user.silent)
- return 0
- if(spamcheck)
- to_chat(user, "\The [src] needs to recharge!")
- return 0
- return 1
+ return FALSE
+ if(spamcheck > world.time)
+ to_chat(user, "[src] needs to recharge!")
+ return FALSE
+ if(loc != user)
+ return FALSE
+ if(user.stat != CONSCIOUS)
+ return FALSE
+ return TRUE
/obj/item/device/megaphone/proc/do_broadcast(var/mob/living/user, var/message)
- if ((src.loc == user && usr.stat == 0))
- if(emagged)
- if(insults)
- user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"")
- insults--
- else
- to_chat(user, "*BZZZZzzzzzt*")
+ if(emagged)
+ if(insults)
+ user.audible_message("[user.GetVoice()][user.GetAltName()] broadcasts, \"[pick(insultmsg)]\"")
+ insults--
else
- user.audible_message("[user] broadcasts, \"[message]\"")
-
- spamcheck = 1
- spawn(20)
- spamcheck = 0
- return
-
-/obj/item/device/megaphone/attack_self(mob/living/user as mob)
- if(!can_broadcast(user))
- return
+ to_chat(user, "*BZZZZzzzzzt*")
+ else
+ user.audible_message("[user.GetVoice()][user.GetAltName()] broadcasts, \"[message]\"")
+/obj/item/device/megaphone/attack_self(var/mob/living/user)
var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text)
if(!message)
return
message = capitalize(message)
+ if(!can_broadcast(user))
+ return
+
+ spamcheck = world.time + 20
do_broadcast(user, message)
/obj/item/device/megaphone/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- to_chat(user, "You overload \the [src]'s voice synthesizer.")
- emagged = 1
+ to_chat(user, "You overload [src]'s voice synthesizer.")
+ emagged = TRUE
insults = rand(1, 3)//to prevent caps spam.
- return 1
+ return TRUE
/obj/item/device/megaphone/super
name = "gigaphone"
@@ -130,41 +129,35 @@
broadcast_color = new_color
/obj/item/device/megaphone/super/do_broadcast(var/mob/living/user, var/message)
- if ((src.loc == user && usr.stat == 0))
- if(emagged)
- if(insults)
- user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"")
- if(broadcast_size >= 11)
- var/turf/T = get_turf(user)
- playsound(T, 'sound/items/AirHorn.ogg', 100, 1)
- for(var/mob/living/carbon/M in oviewers(4, T))
- if(M.get_ear_protection() >= 2)
- continue
- M.sleeping = 0
- M.stuttering += 20
- M.ear_deaf += 30
- M.Weaken(3)
- if(prob(30))
- M.Stun(10)
- M.Paralyse(4)
- else
- M.make_jittery(50)
- insults--
- else
- user.audible_message("*BZZZZzzzzzt*")
- if(prob(40) && insults <= 0)
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(2, 1, get_turf(user))
- s.start()
- user.visible_message("\The [src] sparks violently!")
- spawn(30)
- explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1)
- qdel(src)
- return
+ if(emagged)
+ if(insults)
+ user.audible_message("[user.GetVoice()][user.GetAltName()] broadcasts, \"[pick(insultmsg)]\"")
+ if(broadcast_size >= 11)
+ var/turf/T = get_turf(user)
+ playsound(T, 'sound/items/AirHorn.ogg', 100, 1)
+ for(var/mob/living/carbon/M in oviewers(4, T))
+ if(M.get_ear_protection() >= 2)
+ continue
+ M.sleeping = 0
+ M.stuttering += 20
+ M.ear_deaf += 30
+ M.Weaken(3)
+ if(prob(30))
+ M.Stun(10)
+ M.Paralyse(4)
+ else
+ M.make_jittery(50)
+ insults--
else
- user.audible_message("[user] broadcasts, \"[message]\"")
-
- spamcheck = 1
- spawn(20)
- spamcheck = 0
- return
+ user.audible_message("*BZZZZzzzzzt*")
+ if(prob(40) && insults <= 0)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(2, 1, get_turf(user))
+ s.start()
+ user.visible_message("\The [src] sparks violently!")
+ spawn(30)
+ explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1)
+ qdel(src)
+ return
+ else
+ user.audible_message("[user.GetVoice()][user.GetAltName()] broadcasts, \"[message]\"")
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 67ad07567f..580a59616d 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -43,15 +43,17 @@
to_chat(user, "The following channels are available:")
to_chat(user, radio_desc)
-/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, message, channel)
- if (channel == "special")
- if (translate_binary)
+/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, list/message_pieces, channel)
+ if(channel == "special")
+ if(translate_binary)
var/datum/language/binary = GLOB.all_languages["Robot Talk"]
- binary.broadcast(M, message)
- if (translate_hive)
+ binary.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
+ return RADIO_CONNECTION_NON_SUBSPACE
+ if(translate_hive)
var/datum/language/hivemind = GLOB.all_languages["Hivemind"]
- hivemind.broadcast(M, message)
- return null
+ hivemind.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
+ return RADIO_CONNECTION_NON_SUBSPACE
+ return RADIO_CONNECTION_FAIL
return ..()
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 69b5192abb..afe58f7308 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -216,7 +216,7 @@ var/global/list/default_medbay_channels = list(
return can_admin_interact()
/obj/item/device/radio/proc/text_wires()
- if (b_stat)
+ if(b_stat)
return wires.GetInteractWindow()
return
@@ -244,31 +244,31 @@ var/global/list/default_medbay_channels = list(
return TRUE
usr.set_machine(src)
- if (href_list["track"])
+ if(href_list["track"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
if(A && target)
A.ai_actual_track(target)
. = 1
- else if (href_list["freq"])
+ else if(href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
- if ((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ))
+ if((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ))
new_frequency = sanitize_frequency(new_frequency)
set_frequency(new_frequency)
if(hidden_uplink)
if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
usr << browse(null, "window=radio")
. = 1
- else if (href_list["talk"])
+ else if(href_list["talk"])
ToggleBroadcast()
. = 1
- else if (href_list["listen"])
+ else if(href_list["listen"])
var/chan_name = href_list["ch_name"]
- if (!chan_name)
+ if(!chan_name)
ToggleReception()
else
- if (channels[chan_name] & FREQ_LISTENING)
+ if(channels[chan_name] & FREQ_LISTENING)
channels[chan_name] &= ~FREQ_LISTENING
else
channels[chan_name] |= FREQ_LISTENING
@@ -287,13 +287,18 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/list/zlevels) //BS12 EDIT
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
+<<<<<<< HEAD
if (channel == "department")
+=======
+ if(channel == "department")
+ //to_world("DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"")
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
channel = channels[1]
connection = secure_radio_connections[channel]
else
connection = radio_connection
channel = null
- if (!istype(connection))
+ if(!istype(connection))
return
if(!LAZYLEN(zlevels))
@@ -303,32 +308,37 @@ var/global/list/default_medbay_channels = list(
A.SetName(from)
Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src,
+<<<<<<< HEAD
message, from, "Automated Announcement", from, "synthesized voice",
4, 0, zlevels, connection.frequency, "states")
+=======
+ message_to_multilingual(message), from, "Automated Announcement", from, "synthesized voice",
+ 4, 0, list(0), connection.frequency, "states")
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
// Interprets the message mode when talking into a radio, possibly returning a connection datum
-/obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, message, message_mode)
+/obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, list/message_pieces, message_mode)
// If a channel isn't specified, send to common.
if(!message_mode || message_mode == "headset")
return radio_connection
// Otherwise, if a channel is specified, look for it.
if(channels && channels.len > 0)
- if (message_mode == "department") // Department radio shortcut
+ if(message_mode == "department") // Department radio shortcut
message_mode = channels[1]
- if (channels[message_mode]) // only broadcast if the channel is set on
+ if(channels[message_mode]) // only broadcast if the channel is set on
return secure_radio_connections[message_mode]
// If we were to send to a channel we don't have, drop it.
- return null
+ return RADIO_CONNECTION_FAIL
-/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel, var/verb = "says", var/datum/language/speaking = null)
- if(!on) return FALSE // the device has to be on
+/obj/item/device/radio/talk_into(mob/living/M as mob, list/message_pieces, channel, var/verb = "says")
+ if(!on)
+ return FALSE // the device has to be on
// Fix for permacell radios, but kinda eh about actually fixing them.
- if(!M || !message) return FALSE
-
- if(speaking && (speaking.flags & (SIGNLANG|NONVERBAL))) return FALSE
+ if(!M || !message_pieces)
+ return FALSE
if(istype(M)) M.trigger_aiming(TARGET_CAN_RADIO)
@@ -352,11 +362,22 @@ var/global/list/default_medbay_channels = list(
*/
//#### Grab the connection datum ####//
- var/datum/radio_frequency/connection = handle_message_mode(M, message, channel)
- if (!istype(connection))
+ var/message_mode = handle_message_mode(M, message_pieces, channel)
+ switch(message_mode)
+ if(RADIO_CONNECTION_FAIL)
+ return FALSE
+ if(RADIO_CONNECTION_NON_SUBSPACE)
+ return TRUE
+
+ if(!istype(message_mode, /datum/radio_frequency)) //if not a special case, it should be returning a radio connection
return FALSE
+<<<<<<< HEAD
var/pos_z = get_z(src)
+=======
+ var/datum/radio_frequency/connection = message_mode
+ var/turf/position = get_turf(src)
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
//#### Tagging the signal with all appropriate identity values ####//
@@ -372,24 +393,24 @@ var/global/list/default_medbay_channels = list(
var/jobname // the mob's "job"
// --- Human: use their actual job ---
- if (ishuman(M))
+ if(ishuman(M))
var/mob/living/carbon/human/H = M
jobname = H.get_assignment()
// --- Carbon Nonhuman ---
- else if (iscarbon(M)) // Nonhuman carbon mob
+ else if(iscarbon(M)) // Nonhuman carbon mob
jobname = "No id"
// --- AI ---
- else if (isAI(M))
+ else if(isAI(M))
jobname = "AI"
// --- Cyborg ---
- else if (isrobot(M))
+ else if(isrobot(M))
jobname = "Cyborg"
// --- Personal AI (pAI) ---
- else if (istype(M, /mob/living/silicon/pai))
+ else if(istype(M, /mob/living/silicon/pai))
jobname = "Personal AI"
// --- Unidentifiable mob ---
@@ -400,7 +421,7 @@ var/global/list/default_medbay_channels = list(
// --- Modifications to the mob's identity ---
// The mob is disguising their identity:
- if (ishuman(M) && M.GetVoice() != real_name)
+ if(ishuman(M) && M.GetVoice() != real_name)
displayname = M.GetVoice()
jobname = "Unknown"
voicemask = 1
@@ -469,9 +490,48 @@ var/global/list/default_medbay_channels = list(
return FALSE
// First, we want to generate a new radio signal
+<<<<<<< HEAD
signal.transmission_method = TRANSMISSION_SUBSPACE
//#### Sending the signal to all subspace receivers ####//
+=======
+ var/datum/signal/signal = new
+ signal.transmission_method = 2 // 2 would be a subspace transmission.
+ // transmission_method could probably be enumerated through #define. Would be neater.
+
+ // --- Finally, tag the actual signal with the appropriate values ---
+ signal.data = list(
+ // Identity-associated tags:
+ "mob" = M, // store a reference to the mob
+ "mobtype" = M.type, // the mob's type
+ "realname" = real_name, // the mob's real name
+ "name" = displayname, // the mob's display name
+ "job" = jobname, // the mob's job
+ "key" = mobkey, // the mob's key
+ "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
+ "vname" = M.voice_name, // the name to display if the voice wasn't understood
+ "vmask" = voicemask, // 1 if the mob is using a voice gas mask
+
+ // We store things that would otherwise be kept in the actual mob
+ // so that they can be logged even AFTER the mob is deleted or something
+
+ // Other tags:
+ "compression" = rand(45,50), // compressed radio signal
+ "message" = message_pieces, // the actual sent message
+ "connection" = connection, // the radio connection to use
+ "radio" = src, // stores the radio used for transmission
+ "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
+ "traffic" = 0, // dictates the total traffic sum that the signal went through
+ "type" = 0, // determines what type of radio input it is: normal broadcast
+ "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
+ "verb" = verb
+ )
+ signal.frequency = connection.frequency // Quick frequency set
+
+ //#### Sending the signal to all subspace receivers ####//
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
@@ -487,6 +547,20 @@ var/global/list/default_medbay_channels = list(
else if(adhoc_fallback) //Less huzzah, we have to fallback
to_chat(loc, "\The [src] pings as it falls back to local radio transmission.")
subspace_transmission = FALSE
+<<<<<<< HEAD
+=======
+ return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
+ src, message_pieces, displayname, jobname, real_name, M.voice_name,
+ signal.transmission_method, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb)
+
+ /* ###### Intercoms and station-bounced radios ###### */
+
+ var/filter_type = 2
+
+ /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
+ if(istype(src, /obj/item/device/radio/intercom))
+ filter_type = 1
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
else //Oh well
return FALSE
@@ -504,9 +578,25 @@ var/global/list/default_medbay_channels = list(
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
+<<<<<<< HEAD
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
+=======
+ "compression" = 0, // uncompressed radio signal
+ "message" = message_pieces, // the actual sent message
+ "connection" = connection, // the radio connection to use
+ "radio" = src, // stores the radio used for transmission
+ "slow" = 0,
+ "traffic" = 0,
+ "type" = 0,
+ "server" = null,
+ "reject" = 0,
+ "level" = position.z,
+ "verb" = verb
+ )
+ signal.frequency = connection.frequency // Quick frequency set
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
@@ -520,21 +610,45 @@ var/global/list/default_medbay_channels = list(
//Nothing handled any sort of remote radio-ing and returned before now, just squawk on this zlevel.
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
+<<<<<<< HEAD
src, message, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"], using_map.get_map_levels(pos_z), connection.frequency, verb, speaking)
+=======
+ src, message_pieces, displayname, jobname, real_name, M.voice_name,
+ filter_type, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency, verb)
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
-/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null)
- if (broadcasting)
+/obj/item/device/radio/hear_talk(mob/M, list/message_pieces, verb)
+ if(broadcasting)
if(get_dist(src, M) <= canhear_range)
- talk_into(M, msg,null,verb,speaking)
+ talk_into(M, message_pieces, null, verb)
+<<<<<<< HEAD
+=======
+/*
+/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
+
+ if((R.frequency == frequency && message))
+ return TRUE
+ else if
+
+ else
+ return null
+ return
+*/
+
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
/obj/item/device/radio/proc/receive_range(freq, level)
// check if this radio can receive on the given frequency, and if so,
// what the range is in which mobs will hear the radio
// returns: -1 if can't receive, range otherwise
+<<<<<<< HEAD
+=======
+
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
if(wires.IsIndexCut(WIRE_RECEIVE))
return -1
if(!listening)
@@ -551,20 +665,20 @@ var/global/list/default_medbay_channels = list(
if(freq in CENT_FREQS)
if(!(src.centComm))//Checks to see if it's allowed on that frequency, based on the encryption keys
return -1
- if (!on)
+ if(!on)
return -1
- if (!freq) //recieved on main frequency
- if (!listening)
+ if(!freq) //recieved on main frequency
+ if(!listening)
return -1
else
var/accept = (freq==frequency && listening)
- if (!accept)
+ if(!accept)
for (var/ch_name in channels)
var/datum/radio_frequency/RF = secure_radio_connections[ch_name]
- if (RF && RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
+ if(RF && RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
accept = 1
break
- if (!accept)
+ if(!accept)
return -1
return canhear_range
@@ -577,8 +691,8 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/examine(mob/user)
. = ..()
- if ((in_range(src, user) || loc == user))
- if (b_stat)
+ if((in_range(src, user) || loc == user))
+ if(b_stat)
user.show_message("\The [src] can be attached and modified!")
else
user.show_message("\The [src] can not be modified or attached!")
@@ -587,11 +701,11 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
user.set_machine(src)
- if (!W.is_screwdriver())
+ if(!W.is_screwdriver())
return
b_stat = !( b_stat )
if(!istype(src, /obj/item/device/radio/beacon))
- if (b_stat)
+ if(b_stat)
user.show_message("\The [src] can now be attached and modified!")
else
user.show_message("\The [src] can no longer be modified or attached!")
@@ -631,7 +745,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/borg/talk_into()
. = ..()
- if (isrobot(src.loc))
+ if(isrobot(src.loc))
var/mob/living/silicon/robot/R = src.loc
var/datum/robot_component/C = R.components["radio"]
R.cell_use_power(C.active_usage)
@@ -639,7 +753,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.set_machine(src)
- if (!(W.is_screwdriver() || istype(W, /obj/item/device/encryptionkey)))
+ if(!(W.is_screwdriver() || istype(W, /obj/item/device/encryptionkey)))
return
if(W.is_screwdriver())
@@ -713,7 +827,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/borg/Topic(href, href_list)
if(..())
return TRUE
- if (href_list["mode"])
+ if(href_list["mode"])
var/enable_subspace_transmission = text2num(href_list["mode"])
if(enable_subspace_transmission != subspace_transmission)
subspace_transmission = !subspace_transmission
@@ -727,7 +841,7 @@ var/global/list/default_medbay_channels = list(
else
recalculateChannels()
. = 1
- if (href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio.
+ if(href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio.
var/do_shut_up = text2num(href_list["shutup"])
if(do_shut_up != shut_up)
shut_up = !shut_up
diff --git a/code/game/objects/items/devices/spy_bug.dm b/code/game/objects/items/devices/spy_bug.dm
index 1f15d36b12..5d8587272d 100644
--- a/code/game/objects/items/devices/spy_bug.dm
+++ b/code/game/objects/items/devices/spy_bug.dm
@@ -126,10 +126,7 @@
linkedmonitor.unpair(src)
linkedmonitor = null
..()
-/*
-/obj/item/device/camerabug/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
- radio.hear_talk(M, msg, speaking)
-*/
+
/obj/item/device/bug_monitor
name = "mobile camera pod monitor"
desc = "A portable camera console designed to work with mobile camera pods."
@@ -208,10 +205,7 @@
return
return 1
-/*
-/obj/item/device/bug_monitor/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
- return radio.hear_talk(M, msg, speaking)
-*/
+
/obj/item/device/bug_monitor/spy
name = "\improper PDA"
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index c2320dcf44..bdb35fb643 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -86,15 +86,10 @@
update_icon()
-/obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg, var/verb="says", datum/language/speaking=null)
+/obj/item/device/taperecorder/hear_talk(mob/M, list/message_pieces, verb)
+ var/msg = multilingual_to_message(message_pieces, requires_machine_understands = TRUE, with_capitalization = TRUE)
if(mytape && recording)
-
- if(speaking)
- if(!speaking.machine_understands)
- msg = speaking.scramble(msg)
- mytape.record_speech("[M.name] [speaking.format_message_plain(msg, verb)]")
- else
- mytape.record_speech("[M.name] [verb], \"[msg]\"")
+ mytape.record_speech("[M.name] [verb], \"[msg]\"")
/obj/item/device/taperecorder/see_emote(mob/M as mob, text, var/emote_type)
diff --git a/code/game/objects/items/devices/translator.dm b/code/game/objects/items/devices/translator.dm
index fc6352de29..868481d51e 100644
--- a/code/game/objects/items/devices/translator.dm
+++ b/code/game/objects/items/devices/translator.dm
@@ -33,8 +33,8 @@
icon_state = "[initial(icon_state)]"
to_chat(user, "You disable \the [src].")
-/obj/item/device/universal_translator/hear_talk(var/mob/speaker, var/message, var/vrb, var/datum/language/language)
- if(!listening || !istype(speaker))
+/obj/item/device/universal_translator/hear_talk(mob/M, list/message_pieces, verb)
+ if(!listening || !istype(M))
return
//Show the "I heard something" animation.
@@ -46,34 +46,38 @@
return
var/mob/living/L = loc
+ if(visual && ((L.sdisabilities & BLIND) || L.eye_blind))
+ return
+ if(audio && ((L.sdisabilities & DEAF) || L.ear_deaf))
+ return
- if(!language)
- return //Borgs were causing runtimes when passing language=null
+ // Using two for loops kinda sucks, but I think it's more efficient
+ // to shortcut past string building if we're just going to discard the string
+ // anyways.
+ if(user_understands(M, L, message_pieces))
+ return
- if (language && (language.flags & NONVERBAL))
- return //Not gonna translate sign language
+ var/new_message = ""
- if (!language.machine_understands)
- return //Any other languages that it can't translate.
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking.flags & NONVERBAL)
+ continue
+ if(!S.speaking.machine_understands)
+ new_message += stars(S.message) + " "
+ continue
- if (visual && ((L.sdisabilities & BLIND) || L.eye_blind))
- return //Can't see the screen, don't get the message
+ new_message += (S.message + " ")
- if (audio && ((L.sdisabilities & DEAF) || L.ear_deaf))
- return //Can't hear the translation, don't get the message
+ if(!L.say_understands(null, langset))
+ new_message = langset.scramble(new_message)
- //Only translate if they can't understand, otherwise pointlessly spammy
- //I'll just assume they don't look at the screen in that case
+ to_chat(L, "[src] translates, \"[new_message]\"")
- //They don't understand the spoken language we're translating FROM
- if(!L.say_understands(speaker,language))
- //They understand the output language
- if(L.say_understands(null,langset))
- to_chat(L, "[src] translates, \"[message]\"")
-
- //They don't understand the output language
- else
- to_chat(L, "[src] translates, \"[langset.scramble(message)]\"")
+/obj/item/device/universal_translator/proc/user_understands(mob/M, mob/living/L, list/message_pieces)
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking && !L.say_understands(M, S.speaking))
+ return FALSE
+ return TRUE
//Let's try an ear-worn version
/obj/item/device/universal_translator/ear
diff --git a/code/game/objects/items/devices/tvcamera.dm b/code/game/objects/items/devices/tvcamera.dm
index 3fdaa5e79f..67bafbc1bd 100644
--- a/code/game/objects/items/devices/tvcamera.dm
+++ b/code/game/objects/items/devices/tvcamera.dm
@@ -38,9 +38,9 @@
radio.icon_state = src.icon_state
update_icon()
-/obj/item/device/tvcamera/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
- radio.hear_talk(M,msg,verb,speaking)
- ..()
+/obj/item/device/tvcamera/hear_talk(mob/M, list/message_pieces, verb)
+ radio.hear_talk(M, message_pieces, verb)
+ . = ..()
/obj/item/device/tvcamera/attack_self(mob/user)
add_fingerprint(user)
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 0de385500e..34f44ffc8d 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -227,7 +227,8 @@ Implant Specifics:
"}
Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."}
return dat
-/obj/item/weapon/implant/explosive/hear_talk(mob/M as mob, msg)
+/obj/item/weapon/implant/explosive/hear_talk(mob/M, list/message_pieces, verb)
+ var/msg = multilingual_to_message(message_pieces)
hear(msg)
return
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index faafdb62f3..a14a62eaa8 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -162,9 +162,9 @@
/obj/proc/hides_under_flooring()
return 0
-/obj/proc/hear_talk(mob/M as mob, text, verb, datum/language/speaking)
+/obj/proc/hear_talk(mob/M, list/message_pieces, verb)
if(talking_atom)
- talking_atom.catchMessage(text, M)
+ talking_atom.catchMessage(multilingual_to_message(message_pieces), M)
/*
var/mob/mo = locate(/mob) in src
if(mo)
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm
index c95d2869e9..3806bd60ba 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/holder.dm
@@ -155,11 +155,11 @@
master.receive_signal()
return 1
-/obj/item/device/assembly_holder/hear_talk(mob/living/M as mob, msg, verb, datum/language/speaking)
+/obj/item/device/assembly_holder/hear_talk(mob/M, list/message_pieces, verb)
if(a_right)
- a_right.hear_talk(M,msg,verb,speaking)
+ a_right.hear_talk(M, message_pieces, verb)
if(a_left)
- a_left.hear_talk(M,msg,verb,speaking)
+ a_left.hear_talk(M, message_pieces, verb)
/obj/item/device/assembly_holder/timer_igniter
name = "timer-igniter assembly"
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 8ebf8278a8..8990e01d63 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -7,7 +7,8 @@
var/listening = 0
var/recorded //the activation message
-/obj/item/device/assembly/voice/hear_talk(mob/living/M as mob, msg)
+/obj/item/device/assembly/voice/hear_talk(mob/M, list/message_pieces, verb)
+ var/msg = multilingual_to_message(message_pieces)
if(listening)
recorded = msg
listening = 0
diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm
index 37504035c0..a084633642 100644
--- a/code/modules/integrated_electronics/subtypes/input.dm
+++ b/code/modules/integrated_electronics/subtypes/input.dm
@@ -527,13 +527,15 @@
listening_objects -= src
return ..()
-/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
+/obj/item/integrated_circuit/input/microphone/hear_talk(mob/M, list/message_pieces, verb)
+ var/msg = multilingual_to_message(message_pieces, requires_machine_understands = TRUE)
+
var/translated = FALSE
if(M && msg)
- if(speaking)
- if(!speaking.machine_understands)
- msg = speaking.scramble(msg)
- if(!istype(speaking, /datum/language/common))
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ // S.speaking && here is not redundant, it's preventing `S.speaking = null` from flagging
+ // as a translation, when it is not.
+ if(S.speaking && !istype(S.speaking, /datum/language/common))
translated = TRUE
set_pin_data(IC_OUTPUT, 1, M.GetVoice())
set_pin_data(IC_OUTPUT, 2, msg)
@@ -577,25 +579,41 @@
var/datum/language/newlang = GLOB.all_languages[lang]
my_langs |= newlang
-/obj/item/integrated_circuit/input/microphone/sign/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
+/obj/item/integrated_circuit/input/microphone/sign/hear_talk(mob/M, list/message_pieces, verb)
+ var/msg = multilingual_to_message(message_pieces)
+
var/translated = FALSE
if(M && msg)
- if(speaking)
- if(!((speaking.flags & NONVERBAL) || (speaking.flags & SIGNLANG)))
- translated = TRUE
- msg = speaking.scramble(msg, my_langs)
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking)
+ if(!((S.speaking.flags & NONVERBAL) || (S.speaking.flags & SIGNLANG)))
+ translated = TRUE
+ msg = stars(msg)
+ break
set_pin_data(IC_OUTPUT, 1, M.GetVoice())
set_pin_data(IC_OUTPUT, 2, msg)
push_data()
if(!translated)
activate_pin(1)
- if(translated)
+ else
activate_pin(2)
/obj/item/integrated_circuit/input/microphone/sign/hear_signlang(text, verb, datum/language/speaking, mob/M as mob)
- hear_talk(M, text, verb, speaking)
- return
+ var/translated = FALSE
+ if(M && text)
+ if(speaking)
+ if(!((speaking.flags & NONVERBAL) || (speaking.flags & SIGNLANG)))
+ translated = TRUE
+ text = speaking.scramble(text, my_langs)
+ set_pin_data(IC_OUTPUT, 1, M.GetVoice())
+ set_pin_data(IC_OUTPUT, 2, text)
+
+ push_data()
+ if(!translated)
+ activate_pin(1)
+ else
+ activate_pin(2)
/obj/item/integrated_circuit/input/sensor
name = "sensor"
diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm
index dc44a55168..49ab8f2710 100644
--- a/code/modules/mob/dead/observer/say.dm
+++ b/code/modules/mob/dead/observer/say.dm
@@ -1,63 +1,42 @@
-/mob/observer/dead/say(var/message)
+/mob/observer/dead/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
message = sanitize(message)
- if (!message)
- return
-
- log_ghostsay(message, src)
-
- if (src.client)
- if(message)
- client.handle_spam_prevention(MUTE_DEADCHAT)
- if(src.client.prefs.muted & MUTE_DEADCHAT)
- to_chat(src, "You cannot talk in deadchat (muted).")
- return
-
- . = src.say_dead(message)
-
-
-/mob/observer/dead/emote(var/act, var/type, var/message)
- //message = sanitize(message) - already sanitized in verb/me_verb()
-
if(!message)
return
- if(act != "me")
+ log_ghostsay(message, src)
+
+ if (client)
+ if(message)
+ client.handle_spam_prevention(MUTE_DEADCHAT)
+ if(client.prefs.muted & MUTE_DEADCHAT)
+ to_chat(src, "You cannot talk in deadchat (muted).")
+ return
+
+ . = say_dead(message)
+
+
+/mob/observer/dead/me_verb(message as text)
+ if(!message)
return
log_ghostemote(message, src)
- if(src.client)
+ if(client)
if(message)
client.handle_spam_prevention(MUTE_DEADCHAT)
- if(src.client.prefs.muted & MUTE_DEADCHAT)
+ if(client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "You cannot emote in deadchat (muted).")
return
- . = src.emote_dead(message)
+ . = emote_dead(message)
-/*
- for (var/mob/M in hearers(null, null))
- if (!M.stat)
- if(M.job == "Chaplain")
- if (prob (49))
- M.show_message("You hear muffled speech... but nothing is there...", 2)
- if(prob(20))
- playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1)
- else
- M.show_message("You hear muffled speech... you can almost make out some words...", 2)
-// M.show_message("[stutter(message)]", 2)
- if(prob(30))
- playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1)
- else
- if (prob(50))
- return
- else if (prob (95))
- M.show_message("You hear muffled speech... but nothing is there...", 2)
- if(prob(20))
- playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1)
- else
- M.show_message("You hear muffled speech... you can almost make out some words...", 2)
-// M.show_message("[stutter(message)]", 2)
- playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1)
-*/
+/mob/observer/dead/handle_track(message, verb = "says", mob/speaker = null, speaker_name, hard_to_hear)
+ return "[speaker_name] ([ghost_follow_link(speaker, src)])"
+
+/mob/observer/dead/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
+ var/speaker_name = ..()
+ //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
+ if(speaker && (speaker_name != speaker.real_name) && !isAI(speaker))
+ speaker_name = "[speaker.real_name] ([speaker_name])"
+ return speaker_name
\ No newline at end of file
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index fa2784116a..ff08be434a 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -1,54 +1,96 @@
// At minimum every mob has a hear_say proc.
+/mob/proc/combine_message(var/list/message_pieces, var/verb, var/mob/speaker, always_stars = FALSE, var/radio = FALSE)
+ var/iteration_count = 0
+ var/msg = "" // This is to make sure that the pieces have actually added something
+ . = "[verb], \""
+ for(var/datum/multilingual_say_piece/SP in message_pieces)
+ iteration_count++
+ var/piece = SP.message
+ if(piece == "")
+ continue
-/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
+ if(SP.speaking && SP.speaking.flags & INNATE) // Snowflake for noise lang
+ if(radio)
+ return SP.speaking.format_message_radio(piece)
+ else
+ return SP.speaking.format_message(piece)
+
+ if(iteration_count == 1)
+ piece = capitalize(piece)
+
+ if(always_stars)
+ piece = stars(piece)
+ else if(!say_understands(speaker, SP.speaking))
+ piece = saypiece_scramble(SP)
+ if(isliving(speaker))
+ var/mob/living/S = speaker
+ if(istype(S.say_list) && length(S.say_list.speak))
+ piece = pick(S.say_list.speak)
+
+ if(!SP.speaking) // Catch the most generic case first
+ piece = "[piece]"
+ else if(radio) // SP.speaking == TRUE enforced by previous !SP.speaking
+ piece = SP.speaking.format_message_radio(piece)
+ else // SP.speaking == TRUE && radio == FALSE
+ piece = SP.speaking.format_message(piece)
+
+ msg += (piece + " ")
+
+ if(msg == "")
+ // There is literally no content left in this message, we need to shut this shit down
+ . = "" // hear_say will suppress it
+ else
+ . = trim(. + trim(msg))
+ . += "\""
+
+/mob/proc/saypiece_scramble(datum/multilingual_say_piece/SP)
+ if(SP.speaking)
+ return SP.speaking.scramble(SP.message)
+ else
+ return stars(SP.message)
+
+/mob/proc/hear_say(var/list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(!client && !teleop)
- return
+ return FALSE
- if(speaker && !speaker.client && istype(src,/mob/observer/dead) && is_preference_enabled(/datum/client_preference/ghost_ears) && !(speaker in view(src)))
+ if(isobserver(src) && is_preference_enabled(/datum/client_preference/ghost_ears))
+ if(speaker && !speaker.client && !(speaker in view(src)))
//Does the speaker have a client? It's either random stuff that observers won't care about (Experiment 97B says, 'EHEHEHEHEHEHEHE')
//Or someone snoring. So we make it where they won't hear it.
- return
+ return FALSE
//make sure the air can transmit speech - hearer's side
var/turf/T = get_turf(src)
- if ((T) && (!(istype(src, /mob/observer/dead)))) //Ghosts can hear even in vacuum.
+ if(T && !isobserver(src)) //Ghosts can hear even in vacuum.
var/datum/gas_mixture/environment = T.return_air()
- var/pressure = (environment)? environment.return_pressure() : 0
+ var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
- return
+ return FALSE
- if (pressure < ONE_ATMOSPHERE*0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
+ if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = 1
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
- if(sleeping || stat == 1)
- hear_sleep(message)
- return
-
- //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(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
- if(!say_understands(speaker,language))
- if(language)
- message = language.scramble(message, languages)
- else
- message = stars(message)
-
var/speaker_name = speaker.name
- if(istype(speaker, /mob/living/carbon/human))
+ if(ishuman(speaker))
var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice()
+ var/message = combine_message(message_pieces, verb, speaker)
+ if(message == "")
+ return
+
+ if(sleeping || stat == UNCONSCIOUS)
+ hear_sleep(message)
+ return FALSE
+
if(italics)
message = "[message]"
message = encode_html_emphasis(message)
var/track = null
- if(istype(src, /mob/observer/dead))
+ if(isobserver(src))
if(italics && is_preference_enabled(/datum/client_preference/ghost_radio))
return
if(speaker_name != speaker.real_name && speaker.real_name)
@@ -58,31 +100,27 @@
message = "[message]"
if(is_deaf())
- if(!language || !(language.flags & INNATE)) // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set
- if(speaker == src)
- to_chat(src, "You cannot hear yourself speak!")
- else
- to_chat(src, "[speaker_name][alt_name] talks but you cannot hear.")
+ if(speaker == src)
+ to_chat(src, "You cannot hear yourself speak!")
+ else
+ to_chat(src, "[speaker_name][speaker.GetAltName()] makes a noise, possibly speech, but you cannot hear them.")
else
var/message_to_send = null
- if(language)
- message_to_send = "[speaker_name][alt_name] [track][language.format_message(message, verb)]"
- else
- message_to_send = "[speaker_name][alt_name] [track][verb], \"[message]\""
- if(check_mentioned(message) && is_preference_enabled(/datum/client_preference/check_mention))
+ message_to_send = "[speaker_name][speaker.GetAltName()] [track][message]"
+ if(check_mentioned(multilingual_to_message(message_pieces)) && is_preference_enabled(/datum/client_preference/check_mention))
message_to_send = "[message_to_send]"
on_hear_say(message_to_send)
- if (speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
- var/turf/source = speaker? get_turf(speaker) : get_turf(src)
- src.playsound_local(source, speech_sound, sound_vol, 1)
+ if(speech_sound && (get_dist(speaker, src) <= world.view && z == speaker.z))
+ var/turf/source = speaker ? get_turf(speaker) : get_turf(src)
+ playsound_local(source, speech_sound, sound_vol, 1)
// Done here instead of on_hear_say() since that is NOT called if the mob is clientless (which includes most AI mobs).
-/mob/living/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
+/mob/living/hear_say(var/list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
..()
if(has_AI()) // Won't happen if no ai_holder exists or there's a player inside w/o autopilot active.
- ai_holder.on_hear_say(speaker, message)
+ ai_holder.on_hear_say(speaker, multilingual_to_message(message_pieces))
/mob/proc/on_hear_say(var/message)
to_chat(src, message)
@@ -124,114 +162,25 @@
return tagged_message
-/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
-
+/mob/proc/hear_radio(var/list/message_pieces, var/verb = "says", var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0, var/vname = "")
if(!client)
return
- if(sleeping || stat==1) //If unconscious or sleeping
+ var/message = combine_message(message_pieces, verb, speaker, always_stars = hard_to_hear, radio = TRUE)
+ if(sleeping || stat == UNCONSCIOUS) //If unconscious or sleeping
hear_sleep(message)
return
- var/track = null
-
- //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(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
- if(!say_understands(speaker,language))
- if(language)
- message = language.scramble(message, languages)
- else
- message = stars(message)
-
- if(hard_to_hear)
- message = stars(message)
-
- var/speaker_name = speaker.name
-
- if(vname)
- speaker_name = vname
-
- if(istype(speaker, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = speaker
- if(H.voice)
- speaker_name = H.voice
-
- if(hard_to_hear)
- speaker_name = "unknown"
-
- var/changed_voice
-
- if(istype(src, /mob/living/silicon/ai) && !hard_to_hear)
- var/jobname // the mob's "job"
- var/mob/living/carbon/human/impersonating //The crew member being impersonated, if any.
-
- if (ishuman(speaker))
- var/mob/living/carbon/human/H = speaker
-
- if(H.wear_mask && istype(H.wear_mask,/obj/item/clothing/mask/gas/voice))
- changed_voice = 1
- var/list/impersonated = new()
- var/mob/living/carbon/human/I = impersonated[speaker_name]
-
- if(!I)
- for(var/mob/living/carbon/human/M in mob_list)
- if(M.real_name == speaker_name)
- I = M
- impersonated[speaker_name] = I
- break
-
- // If I's display name is currently different from the voice name and using an agent ID then don't impersonate
- // as this would allow the AI to track I and realize the mismatch.
- if(I && !(I.name != speaker_name && I.wear_id && istype(I.wear_id,/obj/item/weapon/card/id/syndicate)))
- impersonating = I
- jobname = impersonating.get_assignment()
- else
- jobname = "Unknown"
- else
- jobname = H.get_assignment()
-
- else if (iscarbon(speaker)) // Nonhuman carbon mob
- jobname = "No id"
- else if (isAI(speaker))
- jobname = "AI"
- else if (isrobot(speaker))
- jobname = "Cyborg"
- else if (istype(speaker, /mob/living/silicon/pai))
- jobname = "Personal AI"
- else
- jobname = "Unknown"
-
- if(changed_voice)
- if(impersonating)
- track = "[speaker_name] ([jobname])"
- else
- track = "[speaker_name] ([jobname])"
- else
- track = "[speaker_name] ([jobname])"
-
- if(istype(src, /mob/observer/dead))
- if(speaker_name != speaker.real_name && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
- speaker_name = "[speaker.real_name] ([speaker_name])"
- track = "[speaker_name] ([ghost_follow_link(speaker, src)])"
+ var/speaker_name = handle_speaker_name(speaker, vname, hard_to_hear)
+ var/track = handle_track(message, verb, speaker, speaker_name, hard_to_hear)
message = encode_html_emphasis(message)
- var/formatted
- if(language)
- formatted = "[language.format_message_radio(message, verb)][part_c]"
- else
- formatted = "[verb], \"[message]\"[part_c]"
-
-
if((sdisabilities & DEAF) || ear_deaf)
if(prob(20))
to_chat(src, "You feel your headset vibrate but can hear nothing from it!")
else
- on_hear_radio(part_a, speaker_name, track, part_b, formatted)
+ on_hear_radio(part_a, speaker_name, track, part_b, message)
/proc/say_timestamp()
return "\[[stationtime2text()]\]"
@@ -296,9 +245,40 @@
heardword = copytext(heardword,2)
if(copytext(heardword,-1) in punctuation)
heardword = copytext(heardword,1,length(heardword))
- heard = "...You hear something about...[heardword]"
+ heard = "...You hear something about...[heardword]"
else
- heard = "...You almost hear someone talking..."
+ heard = "...You almost hear someone talking..."
- to_chat(src,heard)
+ to_chat(src, heard)
+
+/mob/proc/handle_speaker_name(mob/speaker, vname, hard_to_hear)
+ var/speaker_name = "unknown"
+ if(speaker)
+ speaker_name = speaker.name
+
+ if(ishuman(speaker))
+ var/mob/living/carbon/human/H = speaker
+ if(H.voice)
+ speaker_name = H.voice
+
+ if(vname)
+ speaker_name = vname
+
+ if(hard_to_hear)
+ speaker_name = "unknown"
+
+ return speaker_name
+
+/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, hard_to_hear)
+ return
+
+/mob/proc/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null)
+ var/message = combine_message(message_pieces, verb, speaker)
+
+ var/name = speaker.name
+ if(!say_understands(speaker))
+ name = speaker.voice_name
+
+ var/rendered = "[name] [message]"
+ to_chat(src, rendered)
\ No newline at end of file
diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm
index 8fa9efcd73..03daea6197 100644
--- a/code/modules/mob/language/generic.dm
+++ b/code/modules/mob/language/generic.dm
@@ -5,12 +5,6 @@
key = ""
flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER
-/datum/language/noise/format_message(message, verb)
- return "[message]"
-
-/datum/language/noise/format_message_plain(message, verb)
- return message
-
/datum/language/noise/format_message_radio(message, verb)
return "[message]"
@@ -143,6 +137,17 @@
var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands
return (hands || !iscarbon(speaker))
+/datum/language/sign/scramble(var/input, var/list/known_languages)
+ return stars(input)
+
+// This is a little weird because broadcast is traditionally for hivemind languages
+// But in practice, it's just a way for a language to override all other languages and bypass hear_say
+// which is exactly what sign language does.
+/datum/language/sign/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
+ log_say("(SIGN) [message]", speaker)
+ speaker.say_signlang(message, pick(signlang_verb), src)
+
+
// Silly language for those times when you try to talk a languague you normally can't
/datum/language/gibberish
name = LANGUAGE_GIBBERISH
diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm
index 215376cd44..14d6fb853d 100644
--- a/code/modules/mob/language/language.dm
+++ b/code/modules/mob/language/language.dm
@@ -113,13 +113,13 @@
return scrambled_text
/datum/language/proc/format_message(message, verb)
- return "[verb], \"[capitalize(message)]\""
+ return "[message]"
/datum/language/proc/format_message_plain(message, verb)
- return "[verb], \"[capitalize(message)]\""
+ return "[capitalize(message)]"
/datum/language/proc/format_message_radio(message, verb)
- return "[verb], \"[capitalize(message)]\""
+ return "[capitalize(message)]"
/datum/language/proc/get_talkinto_msg_range(message)
// if you yell, you'll be heard from two tiles over instead of one
@@ -129,7 +129,7 @@
log_say("(HIVE) [message]", speaker)
if(!speaker_mask) speaker_mask = speaker.name
- message = format_message(message, get_spoken_verb(message))
+ message = "[get_spoken_verb(message)], \"[format_message(message, get_spoken_verb(message))]\""
for(var/mob/player in player_list)
player.hear_broadcast(src, speaker, speaker_mask, message)
@@ -233,36 +233,36 @@
return prefix in config.language_prefixes
//TBD
+/mob/proc/check_lang_data()
+ . = ""
+
+ for(var/datum/language/L in languages)
+ if(!(L.flags & NONGLOBAL))
+ . += "[L.name] ([get_language_prefix()][L.key])
[L.desc]
"
+
+/mob/living/check_lang_data()
+ . = ""
+
+ if(default_language)
+ . += "Current default language: [default_language] - reset
"
+
+ for(var/datum/language/L in languages)
+ if(!(L.flags & NONGLOBAL))
+ if(L == default_language)
+ . += "[L.name] ([get_language_prefix()][L.key]) - default - reset
[L.desc]
"
+ else if (can_speak(L))
+ . += "[L.name] ([get_language_prefix()][L.key]) - set default
[L.desc]
"
+ else
+ . += "[L.name] ([get_language_prefix()][L.key]) - cannot speak!
[L.desc]
"
+
/mob/verb/check_languages()
set name = "Check Known Languages"
set category = "IC"
set src = usr
- var/dat = "Known Languages
"
-
- for(var/datum/language/L in languages)
- if(!(L.flags & NONGLOBAL))
- dat += "[L.name] ([get_language_prefix()][L.key])
[L.desc]
"
-
- src << browse(dat, "window=checklanguage")
- return
-
-/mob/living/check_languages()
- var/dat = "Known Languages
"
-
- if(default_language)
- dat += "Current default language: [default_language] - reset
"
-
- for(var/datum/language/L in languages)
- if(!(L.flags & NONGLOBAL))
- if(L == default_language)
- dat += "[L.name] ([get_language_prefix()][L.key]) - default - reset
[L.desc]
"
- else if (can_speak(L))
- dat += "[L.name] ([get_language_prefix()][L.key]) - set default
[L.desc]
"
- else
- dat += "[L.name] ([get_language_prefix()][L.key]) - cannot speak!
[L.desc]
"
-
- src << browse(dat, "window=checklanguage")
+ var/datum/browser/popup = new(src, "checklanguage", "Known Languages", 420, 470)
+ popup.set_content(check_lang_data())
+ popup.open()
/mob/living/Topic(href, href_list)
if(href_list["default_lang"])
diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm
index 93959c2f1f..d2ed3a3890 100644
--- a/code/modules/mob/language/station.dm
+++ b/code/modules/mob/language/station.dm
@@ -94,6 +94,10 @@
key = "l"
flags = WHITELISTED | SIGNLANG | NO_STUTTER | NONVERBAL
+/datum/language/tajsign/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
+ log_say("(SIGN) [message]", speaker)
+ speaker.say_signlang(message, pick(signlang_verb), src)
+
/datum/language/tajsign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format
var/list/allowed_species = list(SPECIES_TAJ, SPECIES_TESHARI) // Need a tail and ears and such to use this.
if(iscarbon(speaker))
diff --git a/code/modules/mob/living/autohiss.dm b/code/modules/mob/living/autohiss.dm
index 4ee08dec85..7a3999ea36 100644
--- a/code/modules/mob/living/autohiss.dm
+++ b/code/modules/mob/living/autohiss.dm
@@ -6,7 +6,7 @@
#define AUTOHISS_NUM 3
-/mob/living/proc/handle_autohiss(message, datum/language/L)
+/mob/proc/handle_autohiss(message, datum/language/L)
return message // no autohiss at this level
/mob/living/carbon/human/handle_autohiss(message, datum/language/L)
diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm
index 5e9f496646..4ea28b3eea 100644
--- a/code/modules/mob/living/bot/bot.dm
+++ b/code/modules/mob/living/bot/bot.dm
@@ -144,12 +144,8 @@
/mob/living/bot/attack_ai(var/mob/user)
return attack_hand(user)
-/mob/living/bot/say(var/message)
- var/verb = "beeps"
-
- message = sanitize(message)
-
- ..(message, null, verb)
+/mob/living/bot/say_quote(var/message, var/datum/language/speaking = null)
+ return "beeps"
/mob/living/bot/speech_bubble_appearance()
return "machine"
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 42f7dece0c..149eba55eb 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -1,5 +1,4 @@
/mob/living/carbon/alien
-
name = "alien"
desc = "What IS that?"
icon = 'icons/mob/alien.dmi'
@@ -52,4 +51,23 @@
return //Consider adding cuffs and hats to this, for the sake of fun.
/mob/living/carbon/alien/cannot_use_vents()
- return
\ No newline at end of file
+ return
+
+/mob/living/carbon/alien/get_default_language()
+ if(default_language)
+ return default_language
+ return GLOB.all_languages["Xenomorph"]
+
+/mob/living/carbon/alien/say_quote(var/message, var/datum/language/speaking = null)
+ var/verb = "hisses"
+ var/ending = copytext(message, length(message))
+
+ if(speaking && (speaking.name != "Galactic Common")) //this is so adminbooze xenos speaking common have their custom verbs,
+ verb = speaking.get_spoken_verb(ending) //and use normal verbs for their own languages and non-common languages
+ else
+ if(ending == "!")
+ verb = "roars"
+ else if(ending == "?")
+ verb = "hisses curiously"
+ return verb
+
diff --git a/code/modules/mob/living/carbon/alien/diona/say_understands.dm b/code/modules/mob/living/carbon/alien/diona/say_understands.dm
index 3f68a44cff..b42109059e 100644
--- a/code/modules/mob/living/carbon/alien/diona/say_understands.dm
+++ b/code/modules/mob/living/carbon/alien/diona/say_understands.dm
@@ -1,6 +1,5 @@
-/mob/living/carbon/alien/diona/say_understands(var/mob/other,var/datum/language/speaking = null)
-
- if (istype(other, /mob/living/carbon/human) && !speaking)
+/mob/living/carbon/alien/diona/say_understands(var/mob/other, var/datum/language/speaking = null)
+ if(ishuman(other) && !speaking)
if(languages.len >= 2) // They have sucked down some blood.
- return 1
+ return TRUE
return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/emote.dm b/code/modules/mob/living/carbon/alien/emote.dm
index 8b4744bdc3..6c9cca88fb 100644
--- a/code/modules/mob/living/carbon/alien/emote.dm
+++ b/code/modules/mob/living/carbon/alien/emote.dm
@@ -1,131 +1,107 @@
-/mob/living/carbon/alien/emote(var/act,var/m_type=1,var/message = null)
-
+/mob/living/carbon/alien/emote(var/act, var/m_type=1, var/message = null)
var/param = null
- if (findtext(act, "-", 1, null))
+ if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
- if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
- act = copytext(act,1,length(act))
var/muzzled = is_muzzled()
switch(act)
- if ("me")
- if(silent)
- return
- if (src.client)
- if (client.prefs.muted & MUTE_IC)
- to_chat(src, "You cannot send IC messages (muted).")
- return
- if (stat)
- return
- if(!(message))
- return
- return custom_emote(m_type, message)
-
- if ("custom")
- return custom_emote(m_type, message)
if("sign")
- if (!src.restrained())
- message = text("The alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null))
- m_type = 1
- if ("burp")
- if (!muzzled)
+ if(!restrained())
+ var/num = null
+ if(text2num(param))
+ num = "the number [text2num(param)]"
+ if(num)
+ message = "[src] signs [num]."
+ m_type = 1
+ if("burp")
+ if(!muzzled)
message = "[src] burps."
m_type = 2
if("deathgasp")
- message = "The [src.name] lets out a waning guttural screech, green blood bubbling from its maw."
+ message = "[src] lets out a waning guttural screech, green blood bubbling from its maw."
m_type = 2
if("scratch")
- if (!src.restrained())
- message = "The [src.name] scratches."
+ if(!restrained())
+ message = "[src] scratches."
m_type = 1
if("whimper")
- if (!muzzled)
- message = "The [src.name] whimpers."
+ if(!muzzled)
+ message = "[src] whimpers."
m_type = 2
if("tail")
- message = "The [src.name] waves its tail."
+ message = "[src] waves its tail."
m_type = 1
if("gasp")
- message = "The [src.name] gasps."
+ message = "[src] gasps."
m_type = 2
if("shiver")
- message = "The [src.name] shivers."
+ message = "[src] shivers."
m_type = 2
if("drool")
- message = "The [src.name] drools."
+ message = "[src] drools."
m_type = 1
if("scretch")
- if (!muzzled)
- message = "The [src.name] scretches."
+ if(!muzzled)
+ message = "[src] scretches."
m_type = 2
if("choke")
- message = "The [src.name] chokes."
+ message = "[src] chokes."
m_type = 2
if("moan")
- message = "The [src.name] moans!"
+ message = "[src] moans!"
m_type = 2
if("nod")
- message = "The [src.name] nods its head."
+ message = "[src] nods its head."
m_type = 1
// if("sit")
-// message = "The [src.name] sits down." //Larvan can't sit down, /N
+// message = "[src] sits down." //Larvan can't sit down, /N
// m_type = 1
if("sway")
- message = "The [src.name] sways around dizzily."
+ message = "[src] sways around dizzily."
m_type = 1
if("sulk")
- message = "The [src.name] sulks down sadly."
+ message = "[src] sulks down sadly."
m_type = 1
if("twitch")
- message = "The [src.name] twitches."
+ message = "[src] twitches."
m_type = 1
if("twitch_v")
- message = "The [src.name] twitches violently."
+ message = "[src] twitches violently."
m_type = 1
if("dance")
- if (!src.restrained())
- message = "The [src.name] dances around happily."
+ if(!restrained())
+ message = "[src] dances around happily."
m_type = 1
if("roll")
- if (!src.restrained())
- message = "The [src.name] rolls."
+ if(!restrained())
+ message = "[src] rolls."
m_type = 1
if("shake")
- message = "The [src.name] shakes its head."
+ message = "[src] shakes its head."
m_type = 1
if("gnarl")
- if (!muzzled)
- message = "The [src.name] gnarls and shows its teeth.."
+ if(!muzzled)
+ message = "[src] gnarls and shows its teeth.."
m_type = 2
if("jump")
- message = "The [src.name] jumps!"
+ message = "[src] jumps!"
m_type = 1
if("hiss_")
- message = "The [src.name] hisses softly."
+ message = "[src] hisses softly."
m_type = 1
if("collapse")
Paralyse(2)
- message = text("[] collapses!", src)
+ message = "[src] collapses!"
m_type = 2
if("chirp")
- message = "The [src.name] chirps!"
- playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0)
+ message = "[src] chirps!"
+ playsound(loc, 'sound/misc/nymphchirp.ogg', 50, 0)
m_type = 2
if("help")
- to_chat(src, "burp, chirp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper")
- else
- to_chat(src, "Invalid Emote: [act]")
- if ((message && src.stat == 0))
- log_emote(message, src)
- if (m_type & 1)
- for(var/mob/O in viewers(src, null))
- O.show_message(message, m_type)
- //Foreach goto(703)
- else
- for(var/mob/O in hearers(src, null))
- O.show_message(message, m_type)
- //Foreach goto(746)
- return
\ No newline at end of file
+ to_chat(src, "burp, chirp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper")
+
+ if(!stat)
+ ..(act, m_type, message)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm
deleted file mode 100644
index 8621339927..0000000000
--- a/code/modules/mob/living/carbon/alien/say.dm
+++ /dev/null
@@ -1,25 +0,0 @@
-/mob/living/carbon/alien/say(var/message)
- var/verb = "says"
- var/message_range = world.view
-
- if(client)
- if(client.prefs.muted & MUTE_IC)
- to_chat(src, "You cannot speak in IC (Muted).")
- return
-
- message = sanitize(message)
-
- if(stat == 2)
- return say_dead(message)
-
- if(copytext(message,1,2) == "*")
- return emote(copytext(message,2))
-
- var/datum/language/speaking = parse_language(message)
-
- message = trim(message)
-
- if(!message || stat)
- return
-
- ..(message, speaking, verb, null, null, message_range, null)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm
index a75deb25d0..a8a0b8fb01 100644
--- a/code/modules/mob/living/carbon/brain/brain.dm
+++ b/code/modules/mob/living/carbon/brain/brain.dm
@@ -18,36 +18,19 @@
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
- if(stat!=DEAD) //If not dead.
+ if(stat != DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
return ..()
/mob/living/carbon/brain/say_understands(var/other)//Goddamn is this hackish, but this say code is so odd
- if (istype(other, /mob/living/silicon/ai))
- if(!(container && istype(container, /obj/item/device/mmi)))
- return 0
- else
- return 1
- if (istype(other, /mob/living/silicon/decoy))
- if(!(container && istype(container, /obj/item/device/mmi)))
- return 0
- else
- return 1
- if (istype(other, /mob/living/silicon/pai))
- if(!(container && istype(container, /obj/item/device/mmi)))
- return 0
- else
- return 1
- if (istype(other, /mob/living/silicon/robot))
- if(!(container && istype(container, /obj/item/device/mmi)))
- return 0
- else
- return 1
- if (istype(other, /mob/living/carbon/human))
- return 1
- if (istype(other, /mob/living/simple_mob/slime))
- return 1
+ if(istype(container, /obj/item/device/mmi))
+ if(issilicon(other))
+ return TRUE
+ if(ishuman(other))
+ return TRUE
+ if(isslime(other))
+ return TRUE
return ..()
/mob/living/carbon/brain/update_canmove()
diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm
index bc4623647b..05706fe299 100644
--- a/code/modules/mob/living/carbon/brain/emote.dm
+++ b/code/modules/mob/living/carbon/brain/emote.dm
@@ -2,79 +2,46 @@
if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes
return
- if (findtext(act, "-", 1, null))
+ if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
act = copytext(act, 1, t1)
- if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
- act = copytext(act,1,length(act))
-
- if(src.stat == DEAD)
+ if(stat == DEAD)
return
switch(act)
- if ("me")
- if(silent)
- return
- if (src.client)
- if (client.prefs.muted & MUTE_IC)
- to_chat(src, "You cannot send IC messages (muted).")
- return
- if (stat)
- return
- if(!(message))
- return
- return custom_emote(m_type, message)
-
- if ("custom")
- return custom_emote(m_type, message)
- if ("alarm")
+ if("alarm")
to_chat(src, "You sound an alarm.")
message = "[src] sounds an alarm."
m_type = 2
- if ("alert")
+ if("alert")
to_chat(src, "You let out a distressed noise.")
message = "[src] lets out a distressed noise."
m_type = 2
- if ("notice")
+ if("notice")
to_chat(src, "You play a loud tone.")
message = "[src] plays a loud tone."
m_type = 2
- if ("flash")
+ if("flash")
message = "The lights on [src] flash quickly."
m_type = 1
- if ("blink")
+ if("blink")
message = "[src] blinks."
m_type = 1
- if ("whistle")
+ if("whistle")
to_chat(src, "You whistle.")
message = "[src] whistles."
m_type = 2
- if ("beep")
+ if("beep")
to_chat(src, "You beep.")
message = "[src] beeps."
m_type = 2
- if ("boop")
+ if("boop")
to_chat(src, "You boop.")
message = "[src] boops."
m_type = 2
- if ("help")
- to_chat(src, "alarm,alert,notice,flash,blink,whistle,beep,boop")
- else
- to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
+ if("help")
+ to_chat(src, "alarm, alert, notice, flash, blink, whistle, beep, boop")
- if (message)
- log_emote(message, src)
-
- for(var/mob/M in dead_mob_list)
- if (!M.client || istype(M, /mob/new_player))
- continue //skip monkeys, leavers, and new_players
- if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_sight) && !(M in viewers(src,null)))
- M.show_message(message)
-
-
- if (m_type & 1)
- for (var/mob/O in viewers(src, null))
- O.show_message(message, m_type)
- else if (m_type & 2)
- for (var/mob/O in hearers(src.loc, null))
- O.show_message(message, m_type)
\ No newline at end of file
+ if(!stat)
+ ..(act, m_type, message)
+
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm
index 0493b2d92d..e03067db1a 100644
--- a/code/modules/mob/living/carbon/brain/say.dm
+++ b/code/modules/mob/living/carbon/brain/say.dm
@@ -1,6 +1,6 @@
//TODO: Convert this over for languages.
-/mob/living/carbon/brain/say(var/message)
- if (silent)
+/mob/living/carbon/brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
+ if(silent)
return
message = sanitize(message)
@@ -8,39 +8,22 @@
if(!(container && container.can_speak))
return //Certain objects can speak, like MMIs. Most others cannot. -Q
else
- var/datum/language/speaking = parse_language(message)
- if(speaking)
- message = copytext(message, 2+length(speaking.key))
- var/verb = "says"
- var/ending = copytext(message, length(message))
- if (speaking)
- verb = speaking.get_spoken_verb(ending)
- else
- if(ending=="!")
- verb=pick("exclaims","shouts","yells")
- if(ending=="?")
- verb="asks"
-
- if(prob(emp_damage*4))
+ if(prob(emp_damage * 4))
if(prob(10))//10% chance to drop the message entirely
return
else
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
- if(speaking && speaking.flags & HIVEMIND)
- speaking.broadcast(src,trim(message))
- return
+ ..()
- ..(trim(message), speaking, verb)
-
-/mob/living/carbon/brain/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
+/mob/living/carbon/brain/handle_message_mode(message_mode, message, verb, speaking, used_radios)
..()
if(message_mode)
var/obj/item/device/mmi/R = container
- if (R.radio && R.radio.radio_enabled)
+ if(R.radio && R.radio.radio_enabled)
if(message_mode == "general")
message_mode = null
- return R.radio.talk_into(src,message,message_mode,verb,speaking)
+ return R.radio.talk_into(src, message, message_mode, verb, speaking)
else
to_chat(src, "Your radio is disabled.")
return 0
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index c0f0e59421..88b74579b1 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -3,29 +3,26 @@
var/datum/gender/T = gender_datums[get_visible_gender()]
- if (findtext(act, "-", 1, null))
+ if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
- if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
- act = copytext(act,1,length(act))
-
var/muzzled = is_muzzled()
//var/m_type = 1
for(var/obj/item/organ/O in src.organs)
for (var/obj/item/weapon/implant/I in O)
- if (I.implanted)
+ if(I.implanted)
I.trigger(act, src)
- if(src.stat == 2.0 && (act != "deathgasp"))
+ if(stat == DEAD && (act != "deathgasp"))
return
if(attempt_vr(src,"handle_emote_vr",list(act,m_type,message))) return //VOREStation Add - Custom Emote Handler
switch(act)
- if ("airguitar")
- if (!src.restrained())
+ if("airguitar")
+ if(!src.restrained())
message = "is strumming the air and headbanging like a safari chimp."
m_type = 1
@@ -39,7 +36,7 @@
var/M = null
if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
if(!M)
@@ -75,7 +72,7 @@
else
use_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg'
- if (param)
+ if(param)
message = "[display_msg] at [param]."
else
message = "[display_msg]."
@@ -103,142 +100,142 @@
message = "warbles."
m_type = 2
- if ("blink")
+ if("blink")
message = "blinks."
m_type = 1
- if ("blink_r")
+ if("blink_r")
message = "blinks rapidly."
m_type = 1
- if ("bow")
- if (!src.buckled)
+ if("bow")
+ if(!src.buckled)
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
+ if(param)
message = "bows to [param]."
else
message = "bows."
m_type = 1
- if ("custom")
+ if("custom")
var/input = sanitize(input("Choose an emote to display.") as text|null)
- if (!input)
+ if(!input)
return
var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable")
- if (input2 == "Visible")
+ if(input2 == "Visible")
m_type = 1
- else if (input2 == "Hearable")
- if (src.miming)
+ else if(input2 == "Hearable")
+ if(src.miming)
return
m_type = 2
else
alert("Unable to use this emote, must be either hearable or visible.")
return
- return custom_emote(m_type, message)
+ return custom_emote(m_type, input)
- if ("me")
+ if("me")
//if(silent && silent > 0 && findtext(message,"\"",1, null) > 0)
// return //This check does not work and I have no idea why, I'm leaving it in for reference.
- if (src.client)
- if (client.prefs.muted & MUTE_IC)
+ if(src.client)
+ if(client.prefs.muted & MUTE_IC)
to_chat(src, "You cannot send IC messages (muted).")
return
- if (stat)
+ if(stat)
return
if(!(message))
return
return custom_emote(m_type, message)
- if ("salute")
- if (!src.buckled)
+ if("salute")
+ if(!src.buckled)
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
+ if(param)
message = "salutes to [param]."
else
message = "salutes."
m_type = 1
- if ("choke")
+ if("choke")
if(miming)
message = "clutches [T.his] throat desperately!"
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "chokes!"
m_type = 2
else
message = "makes a strong noise."
m_type = 2
- if ("clap")
- if (!src.restrained())
+ if("clap")
+ if(!src.restrained())
message = "claps."
playsound(src.loc, 'sound/misc/clapping.ogg')
m_type = 2
if(miming)
m_type = 1
- if ("flap")
- if (!src.restrained())
+ if("flap")
+ if(!src.restrained())
message = "flaps [T.his] wings."
m_type = 2
if(miming)
m_type = 1
- if ("aflap")
- if (!src.restrained())
+ if("aflap")
+ if(!src.restrained())
message = "flaps [T.his] wings ANGRILY!"
m_type = 2
if(miming)
m_type = 1
- if ("drool")
+ if("drool")
message = "drools."
m_type = 1
- if ("eyebrow")
+ if("eyebrow")
message = "raises an eyebrow."
m_type = 1
- if ("chuckle")
+ if("chuckle")
if(miming)
message = "appears to chuckle."
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "chuckles."
m_type = 2
else
message = "makes a noise."
m_type = 2
- if ("twitch")
+ if("twitch")
message = "twitches."
m_type = 1
- if ("twitch_v")
+ if("twitch_v")
message = "twitches violently."
m_type = 1
- if ("faint")
+ if("faint")
message = "faints."
if(src.sleeping)
return //Can't faint while asleep
@@ -277,167 +274,167 @@
message = "makes a strong noise."
m_type = 2
- if ("frown")
+ if("frown")
message = "frowns."
m_type = 1
- if ("nod")
+ if("nod")
message = "nods."
m_type = 1
- if ("blush")
+ if("blush")
message = "blushes."
m_type = 1
- if ("wave")
+ if("wave")
message = "waves."
m_type = 1
- if ("gasp")
+ if("gasp")
if(miming)
message = "appears to be gasping!"
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "gasps!"
m_type = 2
else
message = "makes a weak noise."
m_type = 2
- if ("deathgasp")
+ if("deathgasp")
message = "[species.get_death_message()]"
m_type = 1
- if ("giggle")
+ if("giggle")
if(miming)
message = "giggles silently!"
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "giggles."
m_type = 2
else
message = "makes a noise."
m_type = 2
- if ("glare")
+ if("glare")
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
+ if(param)
message = "glares at [param]."
else
message = "glares."
- if ("stare")
+ if("stare")
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
+ if(param)
message = "stares at [param]."
else
message = "stares."
- if ("look")
+ if("look")
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
+ if(param)
message = "looks at [param]."
else
message = "looks."
m_type = 1
- if ("grin")
+ if("grin")
message = "grins."
m_type = 1
- if ("cry")
+ if("cry")
if(miming)
message = "cries."
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "cries."
m_type = 2
else
message = "makes a weak noise. [T.he] [get_visible_gender() == NEUTER ? "frown" : "frowns"]." // no good, non-unwieldy alternative to this ternary at the moment
m_type = 2
- if ("sigh")
+ if("sigh")
if(miming)
message = "sighs."
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "sighs."
m_type = 2
else
message = "makes a weak noise."
m_type = 2
- if ("laugh")
+ if("laugh")
if(miming)
message = "acts out a laugh."
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "laughs."
m_type = 2
else
message = "makes a noise."
m_type = 2
- if ("mumble")
+ if("mumble")
message = "mumbles!"
m_type = 2
if(miming)
m_type = 1
- if ("grumble")
+ if("grumble")
if(miming)
message = "grumbles!"
m_type = 1
- if (!muzzled)
+ if(!muzzled)
message = "grumbles!"
m_type = 2
else
message = "makes a noise."
m_type = 2
- if ("groan")
+ if("groan")
if(miming)
message = "appears to groan!"
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "groans!"
m_type = 2
else
message = "makes a loud noise."
m_type = 2
- if ("moan")
+ if("moan")
if(miming)
message = "appears to moan!"
m_type = 1
@@ -445,11 +442,11 @@
message = "moans!"
m_type = 2
- if ("johnny")
+ if("johnny")
var/M
- if (param)
+ if(param)
M = param
- if (!M)
+ if(!M)
param = null
else
if(miming)
@@ -459,27 +456,27 @@
message = "says, \"[M], please. He had a family.\" [src.name] takes a drag from a cigarette and blows his name out in smoke."
m_type = 2
- if ("point")
- if (!src.restrained())
+ if("point")
+ if(!src.restrained())
var/mob/M = null
- if (param)
+ if(param)
for (var/atom/A as mob|obj|turf|area in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
message = "points."
else
pointed(M)
- if (M)
+ if(M)
message = "points to [M]."
else
m_type = 1
- if ("raise")
- if (!src.restrained())
+ if("raise")
+ if(!src.restrained())
message = "raises a hand."
m_type = 1
@@ -487,35 +484,35 @@
message = "shakes [T.his] head."
m_type = 1
- if ("shrug")
+ if("shrug")
message = "shrugs."
m_type = 1
- if ("signal")
- if (!src.restrained())
+ if("signal")
+ if(!src.restrained())
var/t1 = round(text2num(param))
- if (isnum(t1))
- if (t1 <= 5 && (!src.r_hand || !src.l_hand))
+ if(isnum(t1))
+ if(t1 <= 5 && (!src.r_hand || !src.l_hand))
message = "raises [t1] finger\s."
- else if (t1 <= 10 && (!src.r_hand && !src.l_hand))
+ else if(t1 <= 10 && (!src.r_hand && !src.l_hand))
message = "raises [t1] finger\s."
m_type = 1
- if ("smile")
+ if("smile")
message = "smiles."
m_type = 1
- if ("shiver")
+ if("shiver")
message = "shivers."
m_type = 2
if(miming)
m_type = 1
- if ("pale")
+ if("pale")
message = "goes pale for a second."
m_type = 1
- if ("tremble")
+ if("tremble")
message = "trembles in fear!"
m_type = 1
@@ -550,48 +547,48 @@
message = "makes a strange noise."
m_type = 2
- if ("sniff")
+ if("sniff")
message = "sniffs."
m_type = 2
if(miming)
m_type = 1
- if ("snore")
- if (miming)
+ if("snore")
+ if(miming)
message = "sleeps soundly."
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "snores."
m_type = 2
else
message = "makes a noise."
m_type = 2
- if ("whimper")
- if (miming)
+ if("whimper")
+ if(miming)
message = "appears hurt."
m_type = 1
else
- if (!muzzled)
+ if(!muzzled)
message = "whimpers."
m_type = 2
else
message = "makes a weak noise."
m_type = 2
- if ("wink")
+ if("wink")
message = "winks."
m_type = 1
- if ("yawn")
- if (!muzzled)
+ if("yawn")
+ if(!muzzled)
message = "yawns."
m_type = 2
if(miming)
m_type = 1
- if ("collapse")
+ if("collapse")
Paralyse(2)
message = "collapses!"
m_type = 2
@@ -600,49 +597,49 @@
if("hug")
m_type = 1
- if (!src.restrained())
+ if(!src.restrained())
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(1, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (M == src)
+ if(M == src)
M = null
- if (M)
+ if(M)
message = "hugs [M]."
else
message = "hugs [T.himself]."
- if ("handshake")
+ if("handshake")
m_type = 1
- if (!src.restrained() && !src.r_hand)
+ if(!src.restrained() && !src.r_hand)
var/mob/living/M = null
- if (param)
+ if(param)
for (var/mob/living/A in view(1, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (M == src)
+ if(M == src)
M = null
- if (M)
- if (M.canmove && !M.r_hand && !M.restrained())
+ if(M)
+ if(M.canmove && !M.r_hand && !M.restrained())
message = "shakes hands with [M]."
else
message = "holds out [T.his] hand to [M]."
if("dap")
m_type = 1
- if (!src.restrained())
+ if(!src.restrained())
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(1, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (M)
+ if(M)
message = "gives daps to [M]."
else
message = "sadly can't find anybody to give daps to, and daps [T.himself]. Shameful."
@@ -737,16 +734,20 @@
else
message = "makes a light spitting noise, a poor attempt at a whistle."
- if ("help")
- to_chat(src, "blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, deathgasp, drool, eyebrow, fastsway/qwag, \
+ if("help")
+ to_chat(src, "blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, deathgasp, drool, eyebrow, fastsway/qwag, \
frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, laugh, look-(none)/mob, moan, mumble, nod, pale, point-atom, \
raise, salute, scream, sneeze, shake, shiver, shrug, sigh, signal-#1-10, slap-(none)/mob, smile, sneeze, sniff, snore, stare-(none)/mob, stopsway/swag, sway/wag, swish, tremble, twitch, \
- twitch_v, vomit, whimper, wink, yawn. Prometheans: squish Synthetics: beep, buzz, dwoop, yes, no, rcough, rsneeze, ping. Skrell: warble")
+ twitch_v, vomit, whimper, wink, yawn. Prometheans: squish Synthetics: beep, buzz, dwoop, yes, no, rcough, rsneeze, ping. Skrell: warble")
else
+<<<<<<< HEAD
to_chat(src, "Unusable emote '[act]'. Say *help or *vhelp for a list.") //VOREStation Edit, mention *vhelp for Virgo-specific emotes located in emote_vr.dm.
+=======
+ to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
- if (message)
+ if(message)
custom_emote(m_type,message)
/mob/living/carbon/human/verb/pose()
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index 1e5e549106..df9e6a331e 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -1,10 +1,13 @@
-/mob/living/carbon/human/say(var/message,var/whispering=0)
- var/alt_name = ""
+/mob/living/carbon/human/GetAltName()
if(name != GetVoice())
- alt_name = "(as [get_id_name("Unknown")])"
+ return " (as [get_id_name("Unknown")])"
+<<<<<<< HEAD
message = sanitize_or_reflect(message,src) //VOREStation Edit - Reflect too-long messages, within reason
..(message, alt_name = alt_name, whispering = whispering)
+=======
+ return ..()
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
@@ -47,18 +50,18 @@
return species.speech_bubble_appearance
return "normal"
-/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null)
-
+/mob/living/carbon/human/say_understands(var/mob/other, var/datum/language/speaking = null)
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
- return 1
+ return TRUE
if(species.can_understand(other))
- return 1
+ return TRUE
//These only pertain to common. Languages are handled by mob/say_understands()
- if (!speaking)
- if (istype(other, /mob/living/carbon/alien/diona))
+ if(!speaking)
+ if(istype(other, /mob/living/carbon/alien/diona))
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
+<<<<<<< HEAD
return 1
if (istype(other, /mob/living/silicon))
return 1
@@ -72,11 +75,19 @@
// if((other.universal_speak && !speaking) || src.universal_speak || src.universal_understand)
// return 1
// return 0
+=======
+ return TRUE
+ if(issilicon(other))
+ return TRUE
+ if(isbrain(other))
+ return TRUE
+ if(isslime(other))
+ return TRUE
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
return ..()
/mob/living/carbon/human/GetVoice()
-
var/voice_sub
if(istype(get_rig(),/obj/item/weapon/rig))
var/obj/item/weapon/rig/rig = get_rig()
@@ -113,30 +124,6 @@
/mob/living/carbon/human/proc/GetSpecialVoice()
return special_voice
-
-/*
- ***Deprecated***
- let this be handled at the hear_say or hear_radio proc
- This is left in for robot speaking when humans gain binary channel access until I get around to rewriting
- robot_talk() proc.
- There is no language handling build into it however there is at the /mob level so we accept the call
- for it but just ignore it.
-*/
-
-/mob/living/carbon/human/say_quote(var/message, var/datum/language/speaking = null)
- var/verb = "says"
- var/ending = copytext(message, length(message))
-
- if(speaking)
- verb = speaking.get_spoken_verb(ending)
- else
- if(ending == "!")
- verb=pick("exclaims","shouts","yells")
- else if(ending == "?")
- verb="asks"
-
- return verb
-
/mob/living/carbon/human/handle_speech_problems(var/list/message_data)
if(silent || (sdisabilities & MUTE))
message_data[1] = ""
@@ -152,59 +139,72 @@
else
. = ..(message_data)
-/mob/living/carbon/human/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
+/mob/living/carbon/human/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
switch(message_mode)
if("intercom")
- if(!src.restrained())
+ if(!restrained())
for(var/obj/item/device/radio/intercom/I in view(1))
- I.talk_into(src, message, null, verb, speaking)
+ I.talk_into(src, message_pieces, null, verb)
I.add_fingerprint(src)
used_radios += I
if("headset")
- if(l_ear && istype(l_ear,/obj/item/device/radio))
- var/obj/item/device/radio/R = l_ear
- R.talk_into(src,message,null,verb,speaking)
- used_radios += l_ear
- else if(r_ear && istype(r_ear,/obj/item/device/radio))
- var/obj/item/device/radio/R = r_ear
- R.talk_into(src,message,null,verb,speaking)
- used_radios += r_ear
- if("right ear")
- var/obj/item/device/radio/R
- var/has_radio = 0
- if(r_ear && istype(r_ear,/obj/item/device/radio))
- R = r_ear
- has_radio = 1
- if(r_hand && istype(r_hand, /obj/item/device/radio))
- R = r_hand
- has_radio = 1
- if(has_radio)
- R.talk_into(src,message,null,verb,speaking)
- used_radios += R
- if("left ear")
- var/obj/item/device/radio/R
- var/has_radio = 0
- if(l_ear && istype(l_ear,/obj/item/device/radio))
+ var/obj/item/device/radio/R = null
+ if(isradio(l_ear))
R = l_ear
- has_radio = 1
- if(l_hand && istype(l_hand,/obj/item/device/radio))
+ if(R.talk_into(src, message_pieces, null, verb))
+ used_radios += R
+ return
+
+ if(isradio(r_ear))
+ R = r_ear
+ if(R.talk_into(src, message_pieces, null, verb))
+ used_radios += R
+ return
+ if("right ear")
+ var/obj/item/device/radio/R = null
+ if(isradio(r_ear))
+ R = r_ear
+ if(isradio(r_hand))
+ R = r_hand
+ if(istype(R))
+ if(R.talk_into(src, message_pieces, null, verb))
+ used_radios += R
+ if("left ear")
+ var/obj/item/device/radio/R = null
+ if(isradio(l_ear))
+ R = l_ear
+ if(isradio(l_hand))
R = l_hand
- has_radio = 1
- if(has_radio)
- R.talk_into(src,message,null,verb,speaking)
- used_radios += R
+ if(istype(R))
+ if(R.talk_into(src, message_pieces, null, verb))
+ used_radios += R
else
if(message_mode)
- if(l_ear && istype(l_ear,/obj/item/device/radio))
- l_ear.talk_into(src,message, message_mode, verb, speaking)
- used_radios += l_ear
- else if(r_ear && istype(r_ear,/obj/item/device/radio))
- r_ear.talk_into(src,message, message_mode, verb, speaking)
- used_radios += r_ear
+ if(isradio(l_ear))
+ if(l_ear.talk_into(src, message_pieces, message_mode, verb))
+ used_radios += l_ear
+ return
+
+ if(isradio(r_ear))
+ if(r_ear.talk_into(src, message_pieces, message_mode, verb))
+ used_radios += r_ear
/mob/living/carbon/human/handle_speech_sound()
+ var/list/returns[2]
if(species.speech_sounds && prob(species.speech_chance))
- var/list/returns[2]
returns[1] = sound(pick(species.speech_sounds))
returns[2] = 50
- return ..()
+ return returns
+
+/mob/living/carbon/human/binarycheck()
+ . = FALSE
+ var/obj/item/device/radio/headset/R = null
+ if(istype(l_ear, /obj/item/device/radio/headset))
+ R = l_ear
+ if(R.translate_binary)
+ . = TRUE
+
+ if(istype(r_ear, /obj/item/device/radio/headset))
+ R = r_ear
+ if(R.translate_binary)
+ . = TRUE
diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm
index 3383e7bdfb..4e64d59d72 100644
--- a/code/modules/mob/living/carbon/human/species/station/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station.dm
@@ -532,10 +532,9 @@
genders = list(PLURAL)
/datum/species/diona/can_understand(var/mob/other)
- var/mob/living/carbon/alien/diona/D = other
- if(istype(D))
- return 1
- return 0
+ if(istype(other, /mob/living/carbon/alien/diona))
+ return TRUE
+ return FALSE
/datum/species/diona/equip_survival_gear(var/mob/living/carbon/human/H)
if(H.backbag == 1)
diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm
index 8a72f6ecf8..4809853f00 100644
--- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm
+++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm
@@ -86,11 +86,9 @@
return "alien [caste_name] ([alien_number])"
/datum/species/xenos/can_understand(var/mob/other)
-
- if(istype(other,/mob/living/carbon/alien/larva))
- return 1
-
- return 0
+ if(istype(other, /mob/living/carbon/alien/larva))
+ return TRUE
+ return FALSE
/datum/species/xenos/hug(var/mob/living/carbon/human/H,var/mob/living/target)
H.visible_message("[H] caresses [target] with its scythe-like arm.", \
diff --git a/code/modules/mob/living/carbon/metroid/death.dm b/code/modules/mob/living/carbon/metroid/death.dm
deleted file mode 100644
index d5510ac509..0000000000
--- a/code/modules/mob/living/carbon/metroid/death.dm
+++ /dev/null
@@ -1,22 +0,0 @@
-/mob/living/carbon/slime/death(gibbed)
-
- if(stat == DEAD) return
-
- if(!gibbed && is_adult)
- var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc, colour)
- M.rabid = 1
- M.Friends = Friends.Copy()
- step_away(M, src)
- is_adult = 0
- maxHealth = 150
- revive()
- if (!client) rabid = 1
- number = rand(1, 1000)
- name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
- return
-
- . = ..(gibbed, "seizes up and falls limp...")
- mood = null
- regenerate_icons()
-
- return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm
deleted file mode 100644
index 6fccaddb8f..0000000000
--- a/code/modules/mob/living/carbon/metroid/emote.dm
+++ /dev/null
@@ -1,99 +0,0 @@
-/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null)
-
- if (findtext(act, "-", 1, null))
- var/t1 = findtext(act, "-", 1, null)
- //param = copytext(act, t1 + 1, length(act) + 1)
- act = copytext(act, 1, t1)
-
- if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
- act = copytext(act,1,length(act))
-
- var/updateicon = 0
-
- switch(act) //Alphabetical please
- if ("me")
- if(silent)
- return
- if (src.client)
- if (client.prefs.muted & MUTE_IC)
- to_chat(src, "You cannot send IC messages (muted).")
- return
- if (stat)
- return
- if(!(message))
- return
- return custom_emote(m_type, message)
- if("bounce")
- message = "The [src.name] bounces in place."
- m_type = 1
-
- if ("custom")
- return custom_emote(m_type, message)
-
- if("jiggle")
- message = "The [src.name] jiggles!"
- m_type = 1
-
- if("light")
- message = "The [src.name] lights up for a bit, then stops."
- m_type = 1
-
- if("moan")
- message = "The [src.name] moans."
- m_type = 2
-
- if("shiver")
- message = "The [src.name] shivers."
- m_type = 2
-
- if("sway")
- message = "The [src.name] sways around dizzily."
- m_type = 1
-
- if("twitch")
- message = "The [src.name] twitches."
- m_type = 1
-
- if("vibrate")
- message = "The [src.name] vibrates!"
- m_type = 1
-
- if("nomood")
- mood = null
- updateicon = 1
-
- if("pout")
- mood = "pout"
- updateicon = 1
-
- if("sad")
- mood = "sad"
- updateicon = 1
-
- if("angry")
- mood = "angry"
- updateicon = 1
-
- if("frown")
- mood = "mischevous"
- updateicon = 1
-
- if("smile")
- mood = ":3"
- updateicon = 1
-
- if ("help") //This is an exception
- to_chat(src, "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate. You can also set your face with: \n\nnomood, pout, sad, angry, frown, smile")
-
- else
- to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
- if ((message && src.stat == 0))
- if (m_type & 1)
- for(var/mob/O in viewers(src, null))
- O.show_message(message, m_type)
- else
- for(var/mob/O in hearers(src, null))
- O.show_message(message, m_type)
- if(updateicon)
- regenerate_icons()
- return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/examine.dm b/code/modules/mob/living/carbon/metroid/examine.dm
deleted file mode 100644
index 9e96e3257d..0000000000
--- a/code/modules/mob/living/carbon/metroid/examine.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/mob/living/carbon/slime/examine(mob/user)
- ..(user)
- var/msg = ""
- if (src.stat == DEAD)
- msg += "It is limp and unresponsive.\n"
- else
- if (src.getBruteLoss())
- msg += ""
- if (src.getBruteLoss() < 40)
- msg += "It has some punctures in its flesh!"
- else
- msg += "It has severe punctures and tears in its flesh!"
- msg += "\n"
-
- switch(powerlevel)
-
- if(2 to 3)
- msg += "It is flickering gently with a little electrical activity.\n"
-
- if(4 to 5)
- msg += "It is glowing gently with moderate levels of electrical activity.\n"
-
- if(6 to 9)
- msg += "It is glowing brightly with high levels of electrical activity.\n"
-
- if(10)
- msg += "It is radiating with massive levels of electrical activity!\n"
-
- msg += "*---------*"
- to_chat(user,msg)
- return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/hud.dm b/code/modules/mob/living/carbon/metroid/hud.dm
deleted file mode 100644
index da6729c3dc..0000000000
--- a/code/modules/mob/living/carbon/metroid/hud.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/mob/living/carbon/slime/handle_regular_hud_updates()
- return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm
deleted file mode 100644
index 7643ea3d2e..0000000000
--- a/code/modules/mob/living/carbon/metroid/life.dm
+++ /dev/null
@@ -1,527 +0,0 @@
-/mob/living/carbon/slime/Life()
- set invisibility = 0
- set background = 1
-
- if (src.transforming)
- return
-
- ..()
-
- if(stat != DEAD)
- handle_nutrition()
-
- if (!client)
- handle_targets()
- if (!AIproc)
- spawn()
- handle_AI()
- handle_speech_and_mood()
-
-/mob/living/carbon/slime/handle_environment(datum/gas_mixture/environment)
- if(!environment)
- adjustToxLoss(rand(10,20))
- return
-
- //var/environment_heat_capacity = environment.heat_capacity()
- var/loc_temp = T0C
- if(istype(get_turf(src), /turf/space))
- //environment_heat_capacity = loc:heat_capacity
- var/turf/heat_turf = get_turf(src)
- loc_temp = heat_turf.temperature
- else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
- loc_temp = loc:air_contents.temperature
- else
- loc_temp = environment.temperature
-
- bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1)
-
- if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc
- if(bodytemperature <= hurt_temperature)
- if(bodytemperature <= die_temperature)
- adjustToxLoss(200)
- else
- // could be more fancy, but doesn't worth the complexity: when the slimes goes into a cold area
- // the damage is mostly determined by how fast its body cools
- adjustToxLoss(30)
-
- updatehealth()
-
- return //TODO: DEFERRED
-
-/mob/living/carbon/slime/proc/adjust_body_temperature(current, loc_temp, boost)
- var/temperature = current
- var/difference = abs(current-loc_temp) //get difference
- var/increments// = difference/10 //find how many increments apart they are
- if(difference > 50)
- increments = difference/5
- else
- increments = difference/10
- var/change = increments*boost // Get the amount to change by (x per increment)
- var/temp_change
- if(current < loc_temp)
- temperature = min(loc_temp, temperature+change)
- else if(current > loc_temp)
- temperature = max(loc_temp, temperature-change)
- temp_change = (temperature - current)
- return temp_change
-
-/mob/living/carbon/slime/handle_chemicals_in_body()
- chem_effects.Cut()
-
- if(touching) touching.metabolize()
- if(ingested) ingested.metabolize()
- if(bloodstr) bloodstr.metabolize()
-
- src.updatehealth()
-
- return //TODO: DEFERRED
-
-/mob/living/carbon/slime/handle_regular_status_updates()
-
- src.blinded = null
-
- health = getMaxHealth() - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
-
- if(health < 0 && stat != DEAD)
- death()
- return
-
- if (halloss)
- halloss = 0
-
- if(prob(30))
- adjustOxyLoss(-1)
- adjustToxLoss(-1)
- adjustFireLoss(-1)
- adjustCloneLoss(-1)
- adjustBruteLoss(-1)
-
- if (src.stat == DEAD)
- src.lying = 1
- src.blinded = 1
- else
- if (src.paralysis || src.stunned || src.weakened || (status_flags & FAKEDEATH)) //Stunned etc.
- if (src.stunned > 0)
- src.set_stat(CONSCIOUS)
- if (src.weakened > 0)
- src.lying = 0
- src.set_stat(CONSCIOUS)
- if (src.paralysis > 0)
- src.blinded = 0
- src.lying = 0
- src.set_stat(CONSCIOUS)
-
- else
- src.lying = 0
- src.set_stat(CONSCIOUS)
-
- if (src.stuttering) src.stuttering = 0
-
- if (src.eye_blind)
- SetBlinded(0)
- src.blinded = 1
-
- if (src.ear_deaf > 0) src.ear_deaf = 0
- if (src.ear_damage < 25)
- src.ear_damage = 0
-
- src.density = !( src.lying )
-
- if (src.sdisabilities & BLIND)
- src.blinded = 1
- if (src.sdisabilities & DEAF)
- src.ear_deaf = 1
-
- if (src.eye_blurry > 0)
- src.eye_blurry = 0
-
- if (src.druggy > 0)
- src.druggy = 0
-
- return 1
-
-/mob/living/carbon/slime/proc/handle_nutrition()
-
- if (prob(15))
- nutrition -= 1 + is_adult
-
- if(nutrition <= 0)
- nutrition = 0
- adjustToxLoss(rand(1,3))
- if (client && prob(5))
- to_chat(src, "You are starving!")
-
- else if (nutrition >= get_grow_nutrition() && amount_grown < 10)
- nutrition -= 20
- amount_grown++
-
-/mob/living/carbon/slime/proc/handle_targets()
- if(attacked > 50) attacked = 50 // Let's not get into absurdly long periods of rage
-
- if(attacked > 0)
- attacked--
-
- if(Discipline > 0)
-
- if(Discipline >= 5 && rabid)
- if(prob(60)) rabid = 0
-
- if(prob(10))
- Discipline--
-
- if(!canmove) return
-
- if(Victim) return // if it's eating someone already, continue eating!
-
- if(Target)
- --target_patience
- if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention
- target_patience = 0
- Target = null
-
- var/hungry = 0 // determines if the slime is hungry
-
- if (nutrition < get_starve_nutrition())
- hungry = 2
- else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
- hungry = 1
-
- if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
- if(Friends.len > 0 && prob(1))
- var/mob/nofriend = pick(Friends)
- if(nofriend && Friends[nofriend])
- Friends[nofriend] -= 1
- if (Friends[nofriend] <= 0)
- Friends[nofriend] = null
- Friends -= nofriend
- Friends -= null
-
- if(!Target)
- if(will_hunt(hungry) || attacked || rabid) // Only add to the list if we need to
- var/list/targets = list()
-
- for(var/mob/living/L in view(7,src))
-
- if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
- continue
-
- if(L in Friends) // No eating friends!
- continue
-
- if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
- targets += L // Possible target found!
-
- if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
- var/mob/living/carbon/human/H = L
- if(H.species.name == "Promethean")
- continue
-
- if(!L.canmove) // Only one slime can latch on at a time.
- var/notarget = 0
- for(var/mob/living/carbon/slime/M in view(1,L))
- if(M.Victim == L)
- notarget = 1
- if(notarget)
- continue
-
- targets += L // Possible target found!
-
- if(targets.len > 0)
- if(attacked || rabid || hungry == 2)
- Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care
- else
- for(var/mob/living/carbon/C in targets)
- if(ishuman(C) && !Discipline && prob(5))
- Target = C
- break
-
- if(isalien(C) || issmall(C) || isanimal(C))
- Target = C
- break
-
- if (Target)
- target_patience = rand(5,7)
- if (is_adult)
- target_patience += 3
-
- if(!Target) // If we have no target, we are wandering or following orders
- if (Leader)
- if (holding_still)
- holding_still = max(holding_still - 1, 0)
- else if(canmove && isturf(loc))
- step_to(src, Leader)
-
- else if(hungry)
- if (holding_still)
- holding_still = max(holding_still - 1 - hungry, 0)
- else if(canmove && isturf(loc) && prob(50))
- step(src, pick(cardinal))
-
- else
- if (holding_still)
- holding_still = max(holding_still - 1, 0)
- else if(canmove && isturf(loc) && prob(33))
- step(src, pick(cardinal))
-
-/mob/living/carbon/slime/proc/handle_AI() // the master AI process
-
- if(stat == DEAD || client || Victim) return // If we're dead or have a client, we don't need AI, if we're feeding, we continue feeding
- AIproc = 1
-
- if(amount_grown >= 10 && !Target)
- if(is_adult)
- Reproduce()
- else
- Evolve()
- AIproc = 0
- return
-
- if(Target) // We're chasing the target
- if(Target.stat == DEAD)
- Target = null
- AIproc = 0
- return
-
- for(var/mob/living/carbon/slime/M in view(1, Target))
- if(M.Victim == Target)
- Target = null
- AIproc = 0
- return
-
- if(Target.Adjacent(src))
- if(istype(Target, /mob/living/silicon)) // Glomp the silicons
- if(!Atkcool)
- a_intent = I_HURT
- UnarmedAttack(Target)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
- AIproc = 0
- return
-
- if(Target.client && !Target.lying && prob(60 + powerlevel * 4)) // Try to take down the target first
- if(!Atkcool)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
-
- a_intent = I_DISARM
- UnarmedAttack(Target)
-
- else
- if(!Atkcool)
- a_intent = I_GRAB
- UnarmedAttack(Target)
-
- else if(Target in view(7, src))
- step_to(src, Target)
-
- else
- Target = null
- AIproc = 0
- return
-
- else
- var/mob/living/carbon/slime/frenemy
- for (var/mob/living/carbon/slime/S in view(1, src))
- if (S != src)
- frenemy = S
- if (frenemy && prob(1))
- if (frenemy.colour == colour)
- a_intent = I_HELP
- else
- a_intent = I_HURT
- UnarmedAttack(frenemy)
-
- var/sleeptime = movement_delay()
- if(sleeptime <= 5) sleeptime = 5 // Maximum one action per half a second
- spawn (sleeptime)
- handle_AI()
- return
-
-/mob/living/carbon/slime/proc/handle_speech_and_mood()
- //Mood starts here
- var/newmood = ""
- a_intent = I_HELP
- if (rabid || attacked)
- newmood = "angry"
- a_intent = I_HURT
- else if (Target) newmood = "mischevous"
-
- if (!newmood)
- if (Discipline && prob(25))
- newmood = "pout"
- else if (prob(1))
- newmood = pick("sad", ":3", "pout")
-
- if ((mood == "sad" || mood == ":3" || mood == "pout") && !newmood)
- if (prob(75)) newmood = mood
-
- if (newmood != mood) // This is so we don't redraw them every time
- mood = newmood
- regenerate_icons()
-
- //Speech understanding starts here
- var/to_say
- if (speech_buffer.len > 0)
- var/who = speech_buffer[1] // Who said it?
- var/phrase = speech_buffer[2] // What did they say?
- if ((findtext(phrase, num2text(number)) || findtext(phrase, "slimes"))) // Talking to us
- if (findtext(phrase, "hello") || findtext(phrase, "hi"))
- to_say = pick("Hello...", "Hi...")
- else if (findtext(phrase, "follow"))
- if (Leader)
- if (Leader == who) // Already following him
- to_say = pick("Yes...", "Lead...", "Following...")
- else if (Friends[who] > Friends[Leader]) // VIVA
- Leader = who
- to_say = "Yes... I follow [who]..."
- else
- to_say = "No... I follow [Leader]..."
- else
- if (Friends[who] > 2)
- Leader = who
- to_say = "I follow..."
- else // Not friendly enough
- to_say = pick("No...", "I won't follow...")
- else if (findtext(phrase, "stop"))
- if (Victim) // We are asked to stop feeding
- if (Friends[who] > 4)
- Victim = null
- Target = null
- if (Friends[who] < 7)
- --Friends[who]
- to_say = "Grrr..." // I'm angry but I do it
- else
- to_say = "Fine..."
- else if (Target) // We are asked to stop chasing
- if (Friends[who] > 3)
- Target = null
- if (Friends[who] < 6)
- --Friends[who]
- to_say = "Grrr..." // I'm angry but I do it
- else
- to_say = "Fine..."
- else if (Leader) // We are asked to stop following
- if (Leader == who)
- to_say = "Yes... I'll stay..."
- Leader = null
- else
- if (Friends[who] > Friends[Leader])
- Leader = null
- to_say = "Yes... I'll stop..."
- else
- to_say = "No... I'll keep following..."
- else if (findtext(phrase, "stay"))
- if (Leader)
- if (Leader == who)
- holding_still = Friends[who] * 10
- to_say = "Yes... Staying..."
- else if (Friends[who] > Friends[Leader])
- holding_still = (Friends[who] - Friends[Leader]) * 10
- to_say = "Yes... Staying..."
- else
- to_say = "No... I'll keep following..."
- else
- if (Friends[who] > 2)
- holding_still = Friends[who] * 10
- to_say = "Yes... Staying..."
- else
- to_say = "No... I won't stay..."
- speech_buffer = list()
-
- //Speech starts here
- if (to_say)
- say (to_say)
- else if(prob(1))
- emote(pick("bounce","sway","light","vibrate","jiggle"))
- else
- var/t = 10
- var/slimes_near = -1 // Don't count myself
- var/dead_slimes = 0
- var/friends_near = list()
- for (var/mob/living/carbon/M in view(7,src))
- if (isslime(M))
- ++slimes_near
- if (M.stat == DEAD)
- ++dead_slimes
- if (M in Friends)
- t += 20
- friends_near += M
- if (nutrition < get_hunger_nutrition()) t += 10
- if (nutrition < get_starve_nutrition()) t += 10
- if (prob(2) && prob(t))
- var/phrases = list()
- if (Target) phrases += "[Target]... looks tasty..."
- if (nutrition < get_starve_nutrition())
- phrases += "So... hungry..."
- phrases += "Very... hungry..."
- phrases += "Need... food..."
- phrases += "Must... eat..."
- else if (nutrition < get_hunger_nutrition())
- phrases += "Hungry..."
- phrases += "Where is the food?"
- phrases += "I want to eat..."
- phrases += "Rawr..."
- phrases += "Blop..."
- phrases += "Blorble..."
- if (rabid || attacked)
- phrases += "Hrr..."
- phrases += "Nhuu..."
- phrases += "Unn..."
- if (mood == ":3")
- phrases += "Purr..."
- if (attacked)
- phrases += "Grrr..."
- if (getToxLoss() > 30)
- phrases += "Cold..."
- if (getToxLoss() > 60)
- phrases += "So... cold..."
- phrases += "Very... cold..."
- if (getToxLoss() > 90)
- phrases += "..."
- phrases += "C... c..."
- if (Victim)
- phrases += "Nom..."
- phrases += "Tasty..."
- if (powerlevel > 3) phrases += "Bzzz..."
- if (powerlevel > 5) phrases += "Zap..."
- if (powerlevel > 8) phrases += "Zap... Bzz..."
- if (mood == "sad") phrases += "Bored..."
- if (slimes_near) phrases += "Brother..."
- if (slimes_near > 1) phrases += "Brothers..."
- if (dead_slimes) phrases += "What happened?"
- if (!slimes_near)
- phrases += "Lonely..."
- for (var/M in friends_near)
- phrases += "[M]... friend..."
- if (nutrition < get_hunger_nutrition())
- phrases += "[M]... feed me..."
- say (pick(phrases))
-
-/mob/living/carbon/slime/proc/get_max_nutrition() // Can't go above it
- if (is_adult) return 1200
- else return 1000
-
-/mob/living/carbon/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat
- if (is_adult) return 1000
- else return 800
-
-/mob/living/carbon/slime/proc/get_hunger_nutrition() // Below it we will always eat
- if (is_adult) return 600
- else return 500
-
-/mob/living/carbon/slime/proc/get_starve_nutrition() // Below it we will eat before everything else
- if (is_adult) return 300
- else return 200
-
-/mob/living/carbon/slime/proc/will_hunt(var/hunger) // Check for being stopped from feeding and chasing
- if (hunger == 2 || rabid || attacked) return 1
- if (Leader) return 0
- if (holding_still) return 0
- if (hunger == 1 || prob(25))
- return 1
- return 0
-
-/mob/living/carbon/slime/slip() //Can't slip something without legs.
- return 0
diff --git a/code/modules/mob/living/carbon/metroid/login.dm b/code/modules/mob/living/carbon/metroid/login.dm
deleted file mode 100644
index 8ca29bf481..0000000000
--- a/code/modules/mob/living/carbon/metroid/login.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/mob/living/carbon/slime/Login()
- ..()
- update_hud()
- return
diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm
deleted file mode 100644
index a871d7e3ac..0000000000
--- a/code/modules/mob/living/carbon/metroid/metroid.dm
+++ /dev/null
@@ -1,384 +0,0 @@
-/mob/living/carbon/slime
- name = "baby slime"
- icon = 'icons/mob/slimes.dmi'
- icon_state = "grey baby slime"
- pass_flags = PASSTABLE
- var/is_adult = 0
- speak_emote = list("chirps")
-
- plane = MOB_PLANE
- layer = ABOVE_MOB_LAYER
- maxHealth = 150
- health = 150
- gender = NEUTER
-
- update_icon = 0
- nutrition = 700
-
- see_in_dark = 8
- update_slimes = 0
-
- // canstun and canweaken don't affect slimes because they ignore stun and weakened variables
- // for the sake of cleanliness, though, here they are.
- status_flags = CANPARALYSE|CANPUSH
-
- var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside
- var/mutation_chance = 30 // Chance of mutating, should be between 25 and 35
-
- var/powerlevel = 0 // 0-10 controls how much electricity they are generating
- var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
-
- var/number = 0 // Used to understand when someone is talking to it
-
- var/mob/living/Victim = null // the person the slime is currently feeding on
- var/mob/living/Target = null // AI variable - tells the slime to hunt this down
- var/mob/living/Leader = null // AI variable - tells the slime to follow this person
-
- var/attacked = 0 // Determines if it's been attacked recently. Can be any number, is a cooloff-ish variable
- var/rabid = 0 // If set to 1, the slime will attack and eat anything it comes in contact with
- var/holding_still = 0 // AI variable, cooloff-ish for how long it's going to stay in one place
- var/target_patience = 0 // AI variable, cooloff-ish for how long it's going to follow its target
-
- var/list/Friends = list() // A list of friends; they are not considered targets for feeding; passed down after splitting
-
- var/list/speech_buffer = list() // Last phrase said near it and person who said it
-
- var/mood = "" // To show its face
-
- var/AIproc = 0 // If it's 0, we need to launch an AI proc
- var/Atkcool = 0 // attack cooldown
- var/SStun = 0 // NPC stun variable. Used to calm them down when they are attacked while feeding, or they will immediately re-attach
- var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while. The part about freeze gun is a lie
-
- var/hurt_temperature = T0C-50 // slime keeps taking damage when its bodytemperature is below this
- var/die_temperature = 50 // slime dies instantly when its bodytemperature is below this
-
- ///////////TIME FOR SUBSPECIES
-
- var/colour = "grey"
- var/coretype = /obj/item/slime_extract/grey
- var/list/slime_mutation[4]
-
- var/core_removal_stage = 0 //For removing cores.
-
-/mob/living/carbon/slime/New(var/location, var/colour="grey")
-
- verbs += /mob/living/proc/ventcrawl
-
- src.colour = colour
- number = rand(1, 1000)
- name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
- real_name = name
- slime_mutation = mutation_table(colour)
- mutation_chance = rand(25, 35)
- var/sanitizedcolour = replacetext(colour, " ", "")
- coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
- regenerate_icons()
- ..(location)
-
-/mob/living/carbon/slime/movement_delay()
- if (bodytemperature >= 330.23) // 135 F
- return -1 // slimes become supercharged at high temperatures
-
- var/tally = 0
-
- var/health_deficiency = (getMaxHealth() - health)
- if(health_deficiency >= 30) tally += (health_deficiency / 25)
-
- if (bodytemperature < 183.222)
- tally += (283.222 - bodytemperature) / 10 * 1.75
-
- if(reagents)
- if(reagents.has_reagent("hyperzine")) // Hyperzine slows slimes down
- tally *= 2
-
- if(reagents.has_reagent("frostoil")) // Frostoil also makes them move VEEERRYYYYY slow
- tally *= 5
-
- if(health <= 0) // if damaged, the slime moves twice as slow
- tally *= 2
-
- return tally + config.slime_delay
-
-/mob/living/carbon/slime/Bump(atom/movable/AM as mob|obj, yes)
- if ((!(yes) || now_pushing))
- return
- now_pushing = 1
-
- if(isobj(AM) && !client && powerlevel > 0)
- var/probab = 10
- switch(powerlevel)
- if(1 to 2) probab = 20
- if(3 to 4) probab = 30
- if(5 to 6) probab = 40
- if(7 to 8) probab = 60
- if(9) probab = 70
- if(10) probab = 95
- if(prob(probab))
- if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
- if(nutrition <= get_hunger_nutrition() && !Atkcool)
- if (is_adult || prob(5))
- UnarmedAttack(AM)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
-
- if(ismob(AM))
- var/mob/tmob = AM
-
- if(is_adult)
- if(istype(tmob, /mob/living/carbon/human))
- if(prob(90))
- now_pushing = 0
- return
- else
- if(istype(tmob, /mob/living/carbon/human))
- now_pushing = 0
- return
-
- now_pushing = 0
-
- ..()
-
-/mob/living/carbon/slime/Process_Spacemove()
- return 2
-
-/mob/living/carbon/slime/Stat()
- ..()
-
- statpanel("Status")
- stat(null, "Health: [round((health / getMaxHealth()) * 100)]%")
- stat(null, "Intent: [a_intent]")
-
- if (client.statpanel == "Status")
- stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
- if(amount_grown >= 10)
- if(is_adult)
- stat(null, "You can reproduce!")
- else
- stat(null, "You can evolve!")
-
- stat(null,"Power Level: [powerlevel]")
-
-/mob/living/carbon/slime/adjustFireLoss(amount)
- ..(-abs(amount)) // Heals them
- return
-
-/mob/living/carbon/slime/bullet_act(var/obj/item/projectile/Proj)
- attacked += 10
- ..(Proj)
- return 0
-
-/mob/living/carbon/slime/emp_act(severity)
- powerlevel = 0 // oh no, the power!
- ..()
-
-/mob/living/carbon/slime/ex_act(severity)
- ..()
-
- var/b_loss = null
- var/f_loss = null
- switch (severity)
- if (1.0)
- qdel(src)
- return
-
- if (2.0)
-
- b_loss += 60
- f_loss += 60
-
-
- if(3.0)
- b_loss += 30
-
- adjustBruteLoss(b_loss)
- adjustFireLoss(f_loss)
-
- updatehealth()
-
-
-/mob/living/carbon/slime/u_equip(obj/item/W as obj)
- return
-
-/mob/living/carbon/slime/attack_ui(slot)
- return
-
-/mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M as mob)
-
- ..()
-
- if(Victim)
- if(Victim == M)
- if(prob(60))
- visible_message("[M] attempts to wrestle \the [name] off!")
- playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
-
- else
- visible_message(" [M] manages to wrestle \the [name] off!")
- playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
-
- if(prob(90) && !client)
- Discipline++
-
- SStun = 1
- spawn(rand(45,60))
- SStun = 0
-
- Victim = null
- anchored = 0
- step_away(src,M)
-
- return
-
- else
- if(prob(30))
- visible_message("[M] attempts to wrestle \the [name] off of [Victim]!")
- playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
-
- else
- visible_message(" [M] manages to wrestle \the [name] off of [Victim]!")
- playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
-
- if(prob(80) && !client)
- Discipline++
-
- if(!is_adult)
- if(Discipline == 1)
- attacked = 0
-
- SStun = 1
- spawn(rand(55,65))
- SStun = 0
-
- Victim = null
- anchored = 0
- step_away(src,M)
-
- return
-
- switch(M.a_intent)
-
- if (I_HELP)
- help_shake_act(M)
-
- if (I_GRAB)
- if (M == src || anchored)
- return
- var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src)
-
- M.put_in_active_hand(G)
-
- G.synch()
-
- LAssailant = M
-
- playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
- visible_message("[M] has grabbed [src] passively!")
-
- else
-
- var/damage = rand(1, 9)
-
- attacked += 10
- if (prob(90))
- if (HULK in M.mutations)
- damage += 5
- if(Victim || Target)
- Victim = null
- Target = null
- anchored = 0
- if(prob(80) && !client)
- Discipline++
- spawn(0)
- step_away(src,M,15)
- sleep(3)
- step_away(src,M,15)
-
- playsound(loc, "punch", 25, 1, -1)
- visible_message("[M] has punched [src]!", \
- "[M] has punched [src]!")
-
- adjustBruteLoss(damage)
- updatehealth()
- else
- playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
- visible_message("[M] has attempted to punch [src]!")
- return
-
-/mob/living/carbon/slime/attackby(obj/item/W, mob/user)
- if(W.force > 0)
- attacked += 10
- if(prob(25))
- to_chat(user, "[W] passes right through [src]!")
- return
- if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
- Discipline = 0
- if(W.force >= 3)
- if(is_adult)
- if(prob(5 + round(W.force/2)))
- if(Victim || Target)
- if(prob(80) && !client)
- Discipline++
-
- Victim = null
- Target = null
- anchored = 0
-
- SStun = 1
- spawn(rand(5,20))
- SStun = 0
-
- spawn(0)
- if(user)
- canmove = 0
- step_away(src, user)
- if(prob(25 + W.force))
- sleep(2)
- if(user)
- step_away(src, user)
- canmove = 1
-
- else
- if(prob(10 + W.force*2))
- if(Victim || Target)
- if(prob(80) && !client)
- Discipline++
- if(Discipline == 1)
- attacked = 0
- SStun = 1
- spawn(rand(5,20))
- SStun = 0
-
- Victim = null
- Target = null
- anchored = 0
-
- spawn(0)
- if(user)
- canmove = 0
- step_away(src, user)
- if(prob(25 + W.force*4))
- sleep(2)
- if(user)
- step_away(src, user)
- canmove = 1
- ..()
-
-/mob/living/carbon/slime/restrained()
- return 0
-
-/mob/living/carbon/slime/var/co2overloadtime = null
-/mob/living/carbon/slime/var/temperature_resistance = T0C+75
-
-/mob/living/carbon/slime/toggle_throw_mode()
- return
-
-/mob/living/carbon/slime/proc/gain_nutrition(var/amount)
- nutrition += amount
- if(prob(amount * 2)) // Gain around one level per 50 nutrition
- powerlevel++
- if(powerlevel > 10)
- powerlevel = 10
- adjustToxLoss(-10)
- nutrition = max(nutrition, get_max_nutrition())
diff --git a/code/modules/mob/living/carbon/metroid/say.dm b/code/modules/mob/living/carbon/metroid/say.dm
deleted file mode 100644
index 7c7ad76240..0000000000
--- a/code/modules/mob/living/carbon/metroid/say.dm
+++ /dev/null
@@ -1,39 +0,0 @@
-/mob/living/carbon/slime/say(var/message)
-
- message = sanitize(message)
-
- var/verb = say_quote(message)
-
- if(copytext(message,1,2) == "*")
- return emote(copytext(message,2))
-
- return ..(message, null, verb)
-
-/mob/living/carbon/slime/say_quote(var/text)
- var/ending = copytext(text, length(text))
-
- if (ending == "?")
- return "asks";
- else if (ending == "!")
- return "cries";
-
- return "chirps";
-
-/mob/living/carbon/slime/say_understands(var/other)
- if (istype(other, /mob/living/carbon/slime))
- return 1
- return ..()
-
-/mob/living/carbon/slime/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
- if (speaker in Friends)
- speech_buffer = list()
- speech_buffer.Add(speaker)
- speech_buffer.Add(lowertext(html_decode(message)))
- ..()
-
-/mob/living/carbon/slime/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
- if (speaker in Friends)
- speech_buffer = list()
- speech_buffer.Add(speaker)
- speech_buffer.Add(lowertext(html_decode(message)))
- ..()
diff --git a/code/modules/mob/living/carbon/metroid/subtypes.dm b/code/modules/mob/living/carbon/metroid/subtypes.dm
deleted file mode 100644
index 6aa75990ac..0000000000
--- a/code/modules/mob/living/carbon/metroid/subtypes.dm
+++ /dev/null
@@ -1,79 +0,0 @@
-/mob/living/carbon/slime/proc/mutation_table(var/colour)
- var/list/slime_mutation[4]
- switch(colour)
- //Tier 1
- if("grey")
- slime_mutation[1] = "orange"
- slime_mutation[2] = "metal"
- slime_mutation[3] = "blue"
- slime_mutation[4] = "purple"
- //Tier 2
- if("purple")
- slime_mutation[1] = "dark purple"
- slime_mutation[2] = "dark blue"
- slime_mutation[3] = "green"
- slime_mutation[4] = "green"
- if("metal")
- slime_mutation[1] = "silver"
- slime_mutation[2] = "yellow"
- slime_mutation[3] = "gold"
- slime_mutation[4] = "gold"
- if("orange")
- slime_mutation[1] = "dark purple"
- slime_mutation[2] = "yellow"
- slime_mutation[3] = "red"
- slime_mutation[4] = "red"
- if("blue")
- slime_mutation[1] = "dark blue"
- slime_mutation[2] = "silver"
- slime_mutation[3] = "pink"
- slime_mutation[4] = "pink"
- //Tier 3
- if("dark blue")
- slime_mutation[1] = "purple"
- slime_mutation[2] = "purple"
- slime_mutation[3] = "blue"
- slime_mutation[4] = "blue"
- if("dark purple")
- slime_mutation[1] = "purple"
- slime_mutation[2] = "purple"
- slime_mutation[3] = "orange"
- slime_mutation[4] = "orange"
- if("yellow")
- slime_mutation[1] = "metal"
- slime_mutation[2] = "metal"
- slime_mutation[3] = "orange"
- slime_mutation[4] = "orange"
- if("silver")
- slime_mutation[1] = "metal"
- slime_mutation[2] = "metal"
- slime_mutation[3] = "blue"
- slime_mutation[4] = "blue"
- //Tier 4
- if("pink")
- slime_mutation[1] = "pink"
- slime_mutation[2] = "pink"
- slime_mutation[3] = "light pink"
- slime_mutation[4] = "light pink"
- if("red")
- slime_mutation[1] = "red"
- slime_mutation[2] = "red"
- slime_mutation[3] = "oil"
- slime_mutation[4] = "oil"
- if("gold")
- slime_mutation[1] = "gold"
- slime_mutation[2] = "gold"
- slime_mutation[3] = "adamantine"
- slime_mutation[4] = "adamantine"
- if("green")
- slime_mutation[1] = "green"
- slime_mutation[2] = "green"
- slime_mutation[3] = "black"
- slime_mutation[4] = "black"
- // Tier 5
- else
- slime_mutation[1] = colour
- slime_mutation[2] = colour
- slime_mutation[3] = colour
- slime_mutation[4] = colour
- return(slime_mutation)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/metroid/update_icons.dm b/code/modules/mob/living/carbon/metroid/update_icons.dm
deleted file mode 100644
index 847dcaeb18..0000000000
--- a/code/modules/mob/living/carbon/metroid/update_icons.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-/mob/living/carbon/slime/regenerate_icons()
- if (stat == DEAD)
- icon_state = "[colour] baby slime dead"
- else
- icon_state = "[colour] [is_adult ? "adult" : "baby"] slime[Victim ? "" : " eat"]"
- overlays.len = 0
- if (mood)
- overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
- ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/default_language.dm b/code/modules/mob/living/default_language.dm
index 94b08207b8..eefe4929f9 100644
--- a/code/modules/mob/living/default_language.dm
+++ b/code/modules/mob/living/default_language.dm
@@ -10,7 +10,7 @@
return 0
if(language == GLOB.all_languages[src.species_language])
- to_chat(src, "You will now speak your standard default language, [language], if you do not specify a language when speaking.")
+ to_chat(src, "You will now speak your standard default language, [language ? language : "common"], if you do not specify a language when speaking.")
else if (language)
if(language && !can_speak(language))
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index f980601d39..e3693533a8 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -70,34 +70,23 @@ proc/get_radio_key_from_channel(var/channel)
return key
/mob/living/proc/binarycheck()
+ return FALSE
- if (istype(src, /mob/living/silicon/pai))
- return
+/mob/proc/get_default_language()
+ return null
- if (!ishuman(src))
- return
-
- var/mob/living/carbon/human/H = src
- if (H.l_ear || H.r_ear)
- var/obj/item/device/radio/headset/dongle
- if(istype(H.l_ear,/obj/item/device/radio/headset))
- dongle = H.l_ear
- else
- dongle = H.r_ear
- if(!istype(dongle)) return
- if(dongle.translate_binary) return 1
-
-/mob/living/proc/get_default_language()
+/mob/living/get_default_language()
return default_language
//Takes a list of the form list(message, verb, whispering) and modifies it as needed
//Returns 1 if a speech problem was applied, 0 otherwise
/mob/living/proc/handle_speech_problems(var/list/message_data)
- var/message = message_data[1]
+ var/list/message_pieces = message_data[1]
var/verb = message_data[2]
var/whispering = message_data[3]
. = 0
+<<<<<<< HEAD
if((HULK in mutations) && health >= 25 && length(message))
message = "[uppertext(message)]!!!"
verb = pick("yells","roars","hollers")
@@ -119,13 +108,35 @@ proc/get_radio_key_from_channel(var/channel)
//VOREStation Edit End
message_data[1] = message
+=======
+ // Technically this rerolls the verb for as many say pieces as there are. _shrug_
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking && (S.speaking.flags & NO_STUTTER || S.speaking.flags & SIGNLANG))
+ continue
+
+ if((HULK in mutations) && health >= 25 && length(S.message))
+ S.message = "[uppertext(S.message)]!!!"
+ verb = pick("yells","roars","hollers")
+ whispering = 0
+ . = 1
+ if(slurring)
+ S.message = slur(S.message)
+ verb = pick("slobbers","slurs")
+ . = 1
+ if(stuttering)
+ S.message = stutter(S.message)
+ verb = pick("stammers","stutters")
+ . = 1
+
+ message_data[1] = message_pieces
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
message_data[2] = verb
message_data[3] = whispering
-/mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
+/mob/living/proc/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
if(message_mode == "intercom")
for(var/obj/item/device/radio/intercom/I in view(1, null))
- I.talk_into(src, message, verb, speaking)
+ I.talk_into(src, message_pieces, verb)
used_radios += I
return 0
@@ -136,13 +147,13 @@ proc/get_radio_key_from_channel(var/channel)
return returns
/mob/living/proc/get_speech_ending(verb, var/ending)
- if(ending=="!")
+ if(ending == "!")
return pick("exclaims","shouts","yells")
- if(ending=="?")
+ if(ending == "?")
return "asks"
return verb
-/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/whispering = 0)
+/mob/living/say(var/message, var/whispering = 0)
//If you're muted for IC chat
if(client)
if(message)
@@ -161,98 +172,81 @@ proc/get_radio_key_from_channel(var/channel)
var/message_mode = parse_message_mode(message, "headset")
//Maybe they are using say/whisper to do a quick emote, so do those
- switch(copytext(message,1,2))
- if("*") return emote(copytext(message,2))
- if("^") return custom_emote(1, copytext(message,2))
+ switch(copytext(message, 1, 2))
+ if("*") return emote(copytext(message, 2))
+ if("^") return custom_emote(1, copytext(message, 2))
//Parse the radio code and consume it
- if (message_mode)
- if (message_mode == "headset")
- message = copytext(message,2) //it would be really nice if the parse procs could do this for us.
- else if (message_mode == "whisper")
+ if(message_mode)
+ if(message_mode == "headset")
+ message = copytext(message, 2) //it would be really nice if the parse procs could do this for us.
+ else if(message_mode == "whisper")
whispering = 1
message_mode = null
- message = copytext(message,3)
+ message = copytext(message, 3)
else
- message = copytext(message,3)
+ message = copytext(message, 3)
//Clean up any remaining space on the left
message = trim_left(message)
//Parse the language code and consume it
- if(!speaking)
- speaking = parse_language(message)
-
- if(!speaking)
- speaking = get_default_language()
-
- if(!can_speak(speaking))
- speaking = GLOB.all_languages[LANGUAGE_GIBBERISH]
- var/babble_key = ",r"
- message = babble_key + message
-
- if(speaking == get_default_language())
- var/new_message = ",[speaking.key]"
- new_message += message
- message = new_message
-
- if(speaking)
- message = copytext(message,2+length(speaking.key))
-
- //HIVEMIND languages always send to all people with that language
- if(speaking && (speaking.flags & HIVEMIND))
- speaking.broadcast(src,trim(message))
+ var/list/message_pieces = parse_languages(message)
+ if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quark for dealing with hivemind/signlang languages.
+ var/datum/multilingual_say_piece/S = message_pieces // Yay for BYOND's hilariously broken typecasting for allowing us to do this.
+ S.speaking.broadcast(src, S.message)
return 1
- //Self explanatory.
- if(is_muzzled() && !(speaking && (speaking.flags & SIGNLANG)))
+ if(!LAZYLEN(message_pieces))
+ log_runtime(EXCEPTION("Message failed to generate pieces. [message] - [json_encode(message_pieces)]"))
+ return 0
+
+ // If you're muzzled, you can only speak sign language
+ // However, sign language is handled above.
+ if(is_muzzled())
to_chat(src, "You're muzzled and cannot speak!")
return
- //Clean up any remaining junk on the left like spaces.
- message = trim_left(message)
-
- //Autohiss handles auto-rolling tajaran R's and unathi S's/Z's
- message = handle_autohiss(message, speaking)
-
//Whisper vars
var/w_scramble_range = 5 //The range at which you get ***as*th**wi****
var/w_adverb //An adverb prepended to the verb in whispers
var/w_not_heard //The message for people in watching range
+ var/datum/multilingual_say_piece/first_piece = message_pieces[1]
+ var/verb = ""
//Handle language-specific verbs and adverb setup if necessary
if(!whispering) //Just doing normal 'say' (for now, may change below)
- verb = say_quote(message, speaking)
- else if(whispering && speaking.whisper_verb) //Language has defined whisper verb
- verb = speaking.whisper_verb
+ verb = say_quote(message, first_piece.speaking)
+ else if(whispering && first_piece.speaking.whisper_verb) //Language has defined whisper verb
+ verb = first_piece.speaking.whisper_verb
w_not_heard = "[verb] something"
else //Whispering but language has no whisper verb, use say verb
w_adverb = pick("quietly", "softly")
- verb = speaking.speech_verb
- w_not_heard = "[speaking.speech_verb] something [w_adverb]"
+ verb = first_piece.speaking.speech_verb
+ w_not_heard = "[first_piece.speaking.speech_verb] something [w_adverb]"
//For speech disorders (hulk, slurring, stuttering)
- if(!(speaking && (speaking.flags & NO_STUTTER || speaking.flags & SIGNLANG)))
- var/list/message_data = list(message, verb, whispering)
- if(handle_speech_problems(message_data))
- message = message_data[1]
- whispering = message_data[3]
+ var/list/message_data = list(message_pieces, verb, whispering)
+ if(handle_speech_problems(message_data))
+ message_pieces = message_data[1]
+ whispering = message_data[3]
- if(verb != message_data[2]) //They changed our verb
- if(whispering)
- w_adverb = pick("quietly", "softly")
- verb = message_data[2]
+ if(verb != message_data[2]) //They changed our verb
+ if(whispering)
+ w_adverb = pick("quietly", "softly")
+ verb = message_data[2]
//Whisper may have adverbs, add those if one was set
- if(w_adverb) verb = "[verb] [w_adverb]"
+ if(w_adverb)
+ verb = "[verb] [w_adverb]"
//If something nulled or emptied the message, forget it
- if(!message || message == "")
+ if(!LAZYLEN(message_pieces))
return 0
//Radio message handling
- var/list/obj/item/used_radios = new
- if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, whispering))
+ var/list/used_radios = list()
+ if(handle_message_mode(message_mode, message_pieces, verb, used_radios, whispering))
return 1
//For languages with actual speech sounds
@@ -268,16 +262,19 @@ proc/get_radio_key_from_channel(var/channel)
if(used_radios.len)
italics = 1
message_range = 1
- if(speaking)
- message_range = speaking.get_talkinto_msg_range(message)
+
+ if(first_piece.speaking)
+ message_range = first_piece.speaking.get_talkinto_msg_range(message)
var/msg
- if(!speaking || !(speaking.flags & NO_TALK_MSG))
- msg = "\The [src] talks into \the [used_radios[1]]"
- for(var/mob/living/M in hearers(5, src))
- if((M != src) && msg)
+ if(!first_piece.speaking || !(first_piece.speaking.flags & NO_TALK_MSG))
+ msg = "[src] talks into [used_radios[1]]"
+
+ if(msg)
+ for(var/mob/living/M in hearers(5, src) - src)
M.show_message(msg)
- if (speech_sound)
- sound_vol *= 0.5
+
+ if(speech_sound)
+ sound_vol *= 0.5
//Set vars if we're still whispering by this point
if(whispering)
@@ -285,6 +282,7 @@ proc/get_radio_key_from_channel(var/channel)
message_range = 1
sound_vol *= 0.5
+<<<<<<< HEAD
//VOREStation edit - allows for custom say verbs, overriding all other say-verb types- e.g. "says loudly" instead of "shouts"
//You'll still stammer if injured or slur if drunk, but it won't have those specific words
var/ending = copytext(message, length(message))
@@ -308,6 +306,13 @@ proc/get_radio_key_from_channel(var/channel)
if (speaking.flags & NONVERBAL)
if (prob(30))
src.custom_emote(1, "[pick(speaking.signlang_verb)].")
+=======
+ //Handle nonverbal languages here
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking.flags & NONVERBAL)
+ if(prob(30))
+ custom_emote(1, "[pick(S.speaking.signlang_verb)].")
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
//These will contain the main receivers of the message
var/list/listening = list()
@@ -318,12 +323,12 @@ proc/get_radio_key_from_channel(var/channel)
if(T)
//Air is too thin to carry sound at all, contact speech only
var/datum/gas_mixture/environment = T.return_air()
- var/pressure = (environment)? environment.return_pressure() : 0
+ var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE)
message_range = 1
//Air is nearing minimum levels, make text italics as a hint, and muffle sound
- if (pressure < ONE_ATMOSPHERE*0.4)
+ if(pressure < ONE_ATMOSPHERE * 0.4)
italics = 1
sound_vol *= 0.5
@@ -376,16 +381,16 @@ proc/get_radio_key_from_channel(var/channel)
var/image/I1 = listening[M] || speech_bubble
images_to_clients[I1] |= M.client
M << I1
- M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
+ M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol)
if(whispering) //Don't even bother with these unless whispering
if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range
if(M.client)
var/image/I2 = listening[M] || speech_bubble
images_to_clients[I2] |= M.client
M << I2
- M.hear_say(stars(message), verb, speaking, alt_name, italics, src, speech_sound, sound_vol*0.2)
+ M.hear_say(stars_all(message_pieces), verb, italics, src, speech_sound, sound_vol*0.2)
if(dst > w_scramble_range && dst <= world.view) //Inside whisper 'visible' range
- M.show_message("[src.name] [w_not_heard].", 2)
+ M.show_message("[name] [w_not_heard].", 2)
//Object message delivery
for(var/obj/O in listening_obj)
@@ -393,7 +398,7 @@ proc/get_radio_key_from_channel(var/channel)
if(O && src) //If we still exist, when the spawn processes
var/dst = get_dist(get_turf(O),get_turf(src))
if(dst <= message_range)
- O.hear_talk(src, message, verb, speaking)
+ O.hear_talk(src, message_pieces, verb)
//Remove all those images. At least it's just ONE spawn this time.
spawn(30)
@@ -410,7 +415,7 @@ proc/get_radio_key_from_channel(var/channel)
if(message_mode)
message = "([message_mode == "headset" ? "Common" : capitalize(message_mode)]) [message]" //Adds radio keys used if available
if(whispering)
- log_whisper(message,src)
+ log_whisper(message, src)
else
log_say(message, src)
return 1
@@ -438,8 +443,41 @@ proc/get_radio_key_from_channel(var/channel)
/obj/effect/speech_bubble
var/mob/parent
-/mob/living/proc/GetVoice()
+/mob/proc/GetVoice()
return name
+/mob/living/emote(var/act, var/type, var/message) //emote code is terrible, this is so that anything that isn't
+ if(stat) //already snowflaked to shit can call the parent and handle emoting sanely
+ return FALSE
+
+ if(..(act, type, message))
+ return TRUE
+
+ if(act && type && message)
+ log_emote(message, src)
+
+ for(var/mob/M in dead_mob_list)
+ if(!M.client)
+ continue
+
+ if(isnewplayer(M))
+ continue
+
+ if(isobserver(M) && M.is_preference_enabled(/datum/client_preference/ghost_sight))
+ M.show_message(message)
+
+ switch(type)
+ if(1) // Visible
+ visible_message(message)
+ return TRUE
+ if(2) // Audible
+ audible_message(message)
+ return TRUE
+ else
+ if(act == "help")
+ return // Mobs handle this individually
+ to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
+
+
/mob/proc/speech_bubble_appearance()
return "normal"
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 4a5e3182d8..fa59ebf5c8 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -837,6 +837,69 @@ var/list/ai_verbs_default = list(
// If that is ever fixed please update this proc.
return TRUE
+
+/mob/living/silicon/ai/handle_track(message, verb = "says", mob/speaker = null, speaker_name, hard_to_hear)
+ if(hard_to_hear)
+ return
+
+ var/jobname // the mob's "job"
+ var/mob/living/carbon/human/impersonating //The crew member being impersonated, if any.
+ var/changed_voice
+
+ if(ishuman(speaker))
+ var/mob/living/carbon/human/H = speaker
+
+ if(H.wear_mask && istype(H.wear_mask,/obj/item/clothing/mask/gas/voice))
+ changed_voice = 1
+ var/list/impersonated = new()
+ var/mob/living/carbon/human/I = impersonated[speaker_name]
+
+ if(!I)
+ for(var/mob/living/carbon/human/M in mob_list)
+ if(M.real_name == speaker_name)
+ I = M
+ impersonated[speaker_name] = I
+ break
+
+ // If I's display name is currently different from the voice name and using an agent ID then don't impersonate
+ // as this would allow the AI to track I and realize the mismatch.
+ if(I && !(I.name != speaker_name && I.wear_id && istype(I.wear_id,/obj/item/weapon/card/id/syndicate)))
+ impersonating = I
+ jobname = impersonating.get_assignment()
+ else
+ jobname = "Unknown"
+ else
+ jobname = H.get_assignment()
+
+ else if(iscarbon(speaker)) // Nonhuman carbon mob
+ jobname = "No id"
+ else if(isAI(speaker))
+ jobname = "AI"
+ else if(isrobot(speaker))
+ jobname = "Cyborg"
+ else if(istype(speaker, /mob/living/silicon/pai))
+ jobname = "Personal AI"
+ else
+ jobname = "Unknown"
+
+ var/track = ""
+ if(changed_voice)
+ if(impersonating)
+ track = "[speaker_name] ([jobname])"
+ else
+ track = "[speaker_name] ([jobname])"
+ else
+ track = "[speaker_name] ([jobname])"
+
+ return track
+
+/mob/living/silicon/ai/proc/relay_speech(mob/living/M, list/message_pieces, verb)
+ var/message = combine_message(message_pieces, verb, M)
+ var/name_used = M.GetVoice()
+ //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
+ var/rendered = "Relayed Speech: [name_used] [message]"
+ show_message(rendered, 2)
+
//Special subtype kept around for global announcements
/mob/living/silicon/ai/announcer/
is_dummy = 1
diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm
new file mode 100644
index 0000000000..ff3e340419
--- /dev/null
+++ b/code/modules/mob/living/silicon/emote.dm
@@ -0,0 +1,113 @@
+/mob/living/silicon/emote(var/act, var/m_type = 1,var/message = null)
+ var/param = null
+ if(findtext(act, "-", 1, null))
+ var/t1 = findtext(act, "-", 1, null)
+ param = copytext(act, t1 + 1, length(act) + 1)
+ act = copytext(act, 1, t1)
+
+ if(findtext(act, "s", -1) && !findtext(act, "_", -2))//Removes ending s's unless they are prefixed with a '_'
+ act = copytext(act, 1, length(act))
+
+ switch(act)
+ if("beep")
+ var/M = null
+ if(param)
+ for (var/mob/A in view(null, null))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] beeps at [param]."
+ else
+ message = "[src] beeps."
+ playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
+ m_type = 1
+
+ if("ping")
+ var/M = null
+ if(param)
+ for (var/mob/A in view(null, null))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] pings at [param]."
+ else
+ message = "[src] pings."
+ playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
+ m_type = 1
+
+ if("buzz")
+ var/M = null
+ if(param)
+ for (var/mob/A in view(null, null))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] buzzes at [param]."
+ else
+ message = "[src] buzzes."
+ playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ m_type = 1
+
+ if("yes", "ye")
+ var/M = null
+ if(param)
+ for (var/mob/A in view(null, null))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] emits an affirmative blip at [param]."
+ else
+ message = "[src] emits an affirmative blip."
+ playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
+ m_type = 1
+
+ if("dwoop")
+ var/M = null
+ if(param)
+ for (var/mob/A in view(null, null))
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] chirps happily at [param]"
+ else
+ message = "[src] chirps happily."
+ playsound(src.loc, 'sound/machines/dwoop.ogg', 50, 0)
+ m_type = 1
+
+ if("no")
+ var/M = null
+ if(param)
+ for (var/mob/A in view(null, null))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] emits a negative blip at [param]."
+ else
+ message = "[src] emits a negative blip."
+ playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
+ m_type = 1
+
+ ..(act, m_type, message)
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/pai/say.dm b/code/modules/mob/living/silicon/pai/say.dm
index 2c7bc900d6..4b18c42beb 100644
--- a/code/modules/mob/living/silicon/pai/say.dm
+++ b/code/modules/mob/living/silicon/pai/say.dm
@@ -1,5 +1,5 @@
-/mob/living/silicon/pai/say(var/msg)
+/mob/living/silicon/pai/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
if(silence_time)
to_chat(src, "Communication circuits remain uninitialized.")
else
- ..(msg)
\ No newline at end of file
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_say.dm b/code/modules/mob/living/silicon/robot/drone/drone_say.dm
index 76e104cfb2..5e8dd6dc74 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_say.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_say.dm
@@ -1,4 +1,4 @@
-/mob/living/silicon/robot/drone/say(var/message)
+/mob/living/silicon/robot/drone/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
if(local_transmit)
if (src.client)
if(client.prefs.muted & MUTE_IC)
@@ -36,4 +36,4 @@
if(M.client)
to_chat(M, "[src] transmits, \"[message]\"")
return 1
- return ..(message, 0)
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm
index 881f827929..4f2a23bce5 100644
--- a/code/modules/mob/living/silicon/robot/emote.dm
+++ b/code/modules/mob/living/silicon/robot/emote.dm
@@ -1,6 +1,6 @@
/mob/living/silicon/robot/emote(var/act,var/m_type=1,var/message = null)
var/param = null
- if (findtext(act, "-", 1, null))
+ if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
@@ -9,236 +9,124 @@
act = copytext(act,1,length(act))
switch(act)
- if ("me")
- if (src.client)
- if(client.prefs.muted & MUTE_IC)
- to_chat(src, "You cannot send IC messages (muted).")
- return
- if (stat)
- return
- if(!(message))
- return
- else
- return custom_emote(m_type, message)
-
- if ("custom")
- return custom_emote(m_type, message)
-
- if ("salute")
- if (!src.buckled)
+ if("salute")
+ if(!src.buckled)
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
- message = "salutes to [param]."
+ if(param)
+ message = "[src] salutes to [param]."
else
- message = "salutes."
+ message = "[src] salutes."
m_type = 1
- if ("bow")
- if (!src.buckled)
+ if("bow")
+ if(!src.buckled)
var/M = null
- if (param)
+ if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
- if (!M)
+ if(!M)
param = null
- if (param)
- message = "bows to [param]."
+ if(param)
+ message = "[src] bows to [param]."
else
- message = "bows."
+ message = "[src] bows."
m_type = 1
- if ("clap")
- if (!src.restrained())
- message = "claps."
+ if("clap")
+ if(!src.restrained())
+ message = "[src] claps."
m_type = 2
- if ("flap")
- if (!src.restrained())
- message = "flaps its wings."
+ if("flap")
+ if(!src.restrained())
+ message = "[src] flaps its wings."
m_type = 2
- if ("aflap")
- if (!src.restrained())
- message = "flaps its wings ANGRILY!"
+ if("aflap")
+ if(!src.restrained())
+ message = "[src] flaps its wings ANGRILY!"
m_type = 2
- if ("twitch")
- message = "twitches."
+ if("twitch")
+ message = "[src] twitches."
m_type = 1
- if ("twitch_v")
- message = "twitches violently."
+ if("twitch_v")
+ message = "[src] twitches violently."
m_type = 1
- if ("nod")
- message = "nods."
+ if("nod")
+ message = "[src] nods."
m_type = 1
- if ("deathgasp")
- message = "shudders violently for a moment, then becomes motionless, its eyes slowly darkening."
+ if("deathgasp")
+ message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening."
m_type = 1
- if ("glare")
- var/M = null
- if (param)
- for (var/mob/A in view(null, null))
- if (param == A.name)
- M = A
- break
- if (!M)
- param = null
-
- if (param)
- message = "glares at [param]."
- else
- message = "glares."
-
- if ("stare")
- var/M = null
- if (param)
- for (var/mob/A in view(null, null))
- if (param == A.name)
- M = A
- break
- if (!M)
- param = null
-
- if (param)
- message = "stares at [param]."
- else
- message = "stares."
-
- if ("look")
- var/M = null
- if (param)
- for (var/mob/A in view(null, null))
- if (param == A.name)
- M = A
- break
-
- if (!M)
- param = null
-
- if (param)
- message = "looks at [param]."
- else
- message = "looks."
- m_type = 1
-
- if("beep")
+ if("glare")
var/M = null
if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
if(!M)
param = null
- if (param)
- message = "beeps at [param]."
+ if(param)
+ message = "[src] glares at [param]."
else
- message = "beeps."
- playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
- m_type = 1
+ message = "[src] glares."
- if("ping")
+ if("stare")
var/M = null
if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
if(!M)
param = null
- if (param)
- message = "pings at [param]."
+ if(param)
+ message = "[src] stares at [param]."
else
- message = "pings."
- playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
- m_type = 1
+ message = "[src] stares."
- if("buzz")
+ if("look")
var/M = null
if(param)
for (var/mob/A in view(null, null))
- if (param == A.name)
+ if(param == A.name)
M = A
break
+
if(!M)
param = null
- if (param)
- message = "buzzes at [param]."
- else
- message = "buzzes."
- playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
- m_type = 1
-
- if("yes", "ye")
- var/M = null
if(param)
- for (var/mob/A in view(null, null))
- if (param == A.name)
- M = A
- break
- if(!M)
- param = null
-
- if (param)
- message = "emits an affirmative blip at [param]."
+ message = "[src] looks at [param]."
else
- message = "emits an affirmative blip."
- playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
- m_type = 1
-
- if("dwoop")
- var/M = null
- if(param)
- for (var/mob/A in view(null, null))
- M = A
- break
- if(!M)
- param = null
-
- if (param)
- message = "chirps happily at [param]"
- else
- message = "chirps happily."
- playsound(src.loc, 'sound/machines/dwoop.ogg', 50, 0)
- m_type = 1
-
-
- if("no")
- var/M = null
- if(param)
- for (var/mob/A in view(null, null))
- if (param == A.name)
- M = A
- break
- if(!M)
- param = null
-
- if (param)
- message = "emits a negative blip at [param]."
- else
- message = "emits a negative blip."
- playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
+ message = "[src] looks."
m_type = 1
if("law")
+<<<<<<< HEAD
if (istype(module,/obj/item/weapon/robot_module/robot/security) || istype(module,/obj/item/weapon/robot_module/robot/knine)) //VOREStation Add - K9
message = "shows its legal authorization barcode."
+=======
+ if(istype(module,/obj/item/weapon/robot_module/robot/security))
+ message = "[src] shows its legal authorization barcode."
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0)
m_type = 2
@@ -246,20 +134,20 @@
to_chat(src, "You are not THE LAW, pal.")
if("halt")
+<<<<<<< HEAD
if (istype(module,/obj/item/weapon/robot_module/robot/security) || istype(module,/obj/item/weapon/robot_module/robot/knine)) //VOREStation Add - K9
message = "'s speakers skreech, \"Halt! Security!\"."
+=======
+ if(istype(module,/obj/item/weapon/robot_module/robot/security))
+ message = "[src] 's speakers skreech, \"Halt! Security!\"."
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
playsound(src.loc, 'sound/voice/halt.ogg', 50, 0)
m_type = 2
else
to_chat(src, "You are not security.")
- if ("help")
+ if("help")
to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitch_s, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look, beep, ping, \nbuzz, law, halt, yes, dwoop, no")
- else
- to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
- if ((message && src.stat == 0))
- custom_emote(m_type,message)
-
- return
+ ..(act, m_type, message)
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm
index 0867fedff8..41df4c5146 100644
--- a/code/modules/mob/living/silicon/say.dm
+++ b/code/modules/mob/living/silicon/say.dm
@@ -1,10 +1,4 @@
-/mob/living/silicon/say(var/message, var/sanitize = 1, var/whispering = 0)
- return ..((sanitize ? sanitize(message) : message), whispering = whispering)
-
-/mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
- log_say(message, src)
-
-/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
+/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios)
..()
if(message_mode)
if(!is_component_functioning("radio"))
@@ -17,7 +11,7 @@
/mob/living/silicon/speech_bubble_appearance()
return "synthetic"
-/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
+/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios)
..()
if(message_mode == "department")
return holopad_talk(message, verb, speaking)
@@ -29,7 +23,7 @@
message_mode = null
return aiRadio.talk_into(src,message,message_mode,verb,speaking)
-/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
+/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios)
..()
if(message_mode)
if(message_mode == "general")
@@ -50,29 +44,24 @@
#define IS_ROBOT 2
#define IS_PAI 3
-/mob/living/silicon/say_understands(var/other,var/datum/language/speaking = null)
+/mob/living/silicon/say_understands(var/other, var/datum/language/speaking = null)
//These only pertain to common. Languages are handled by mob/say_understands()
- if (!speaking)
- if (istype(other, /mob/living/carbon))
- return 1
- if (istype(other, /mob/living/silicon))
- return 1
- if (istype(other, /mob/living/carbon/brain))
- return 1
+ if(!speaking)
+ if(iscarbon(other))
+ return TRUE
+ if(issilicon(other))
+ return TRUE
+ if(isbrain(other))
+ return TRUE
return ..()
//For holopads only. Usable by AI.
-/mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking)
-
- log_say("(HPAD) [message]",src)
-
- message = trim(message)
-
- if (!message)
- return
+/mob/living/silicon/ai/proc/holopad_talk(list/message_pieces, verb)
+ log_say("(HPAD) [multilingual_to_message(message_pieces)]",src)
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.masters[src])//If there is a hologram and its master is the user.
+<<<<<<< HEAD
//Human-like, sorta, heard by those who understand humans.
var/rendered_a
//Speech distorted, heard by those who do not understand AIs.
@@ -87,33 +76,29 @@
rendered_a = "[name] [verb], \"[message]\""
rendered_b = "[voice_name] [verb], \"[message_stars]\""
to_chat(src, "Holopad transmitted, [real_name] [verb], \"[message]\"") //The AI can "hear" its own message.
+=======
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
var/list/listeners = get_mobs_and_objs_in_view_fast(get_turf(T), world.view)
var/list/listening = listeners["mobs"]
var/list/listening_obj = listeners["objs"]
for(var/mob/M in listening)
- spawn(0)
- if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to.
- M.show_message(rendered_a, 2)
- else//If they do not.
- M.show_message(rendered_b, 2)
+ M.hear_holopad_talk(message_pieces, verb, src)
for(var/obj/O in listening_obj)
if(O == T) //Don't recieve your own speech
continue
- spawn(0)
- if(O && src) //If we still exist, when the spawn processes
- O.hear_talk(src, message, verb, speaking)
+ O.hear_talk(src, message_pieces, verb)
/*Radios "filter out" this conversation channel so we don't need to account for them.
This is another way of saying that we won't bother dealing with them.*/
+ to_chat(src, "Holopad transmitted, [real_name] [combine_message(message_pieces, verb, src)]")
else
to_chat(src, "No holopad connected.")
return 0
return 1
/mob/living/silicon/ai/proc/holopad_emote(var/message) //This is called when the AI uses the 'me' verb while using a holopad.
-
message = trim(message)
- if (!message)
+ if(!message)
return
var/obj/machinery/hologram/holopad/T = src.holo
@@ -147,11 +132,11 @@
return 1
/mob/living/silicon/ai/emote(var/act, var/type, var/message)
- var/obj/machinery/hologram/holopad/T = src.holo
+ var/obj/machinery/hologram/holopad/T = holo
if(T && T.masters[src]) //Is the AI using a holopad?
- src.holopad_emote(message)
+ . = holopad_emote(message)
else //Emote normally, then.
- ..()
+ . = ..()
#undef IS_AI
#undef IS_ROBOT
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 6a74eb41d5..9ad7179cca 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -193,7 +193,14 @@
//Silicon mob language procs
/mob/living/silicon/can_speak(datum/language/speaking)
- return universal_speak || (speaking in src.speech_synthesizer_langs) || (speaking.name == "Noise") //need speech synthesizer support to vocalize a language
+ if(universal_speak)
+ return TRUE
+ //need speech synthesizer support to vocalize a language
+ if(speaking in speech_synthesizer_langs)
+ return TRUE
+ if(speaking && speaking.flags & INNATE)
+ return TRUE
+ return FALSE
/mob/living/silicon/add_language(var/language, var/can_speak=1)
var/var/datum/language/added_language = GLOB.all_languages[language]
@@ -213,15 +220,11 @@
..(rem_language)
speech_synthesizer_langs -= removed_language
-/mob/living/silicon/check_languages()
- set name = "Check Known Languages"
- set category = "IC"
- set src = usr
-
- var/dat = "Known Languages
"
+/mob/living/silicon/check_lang_data()
+ . = ""
if(default_language)
- dat += "Current default language: [default_language] - reset
"
+ . += "Current default language: [default_language] - reset
"
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
@@ -232,10 +235,7 @@
default_str = " - set default"
var/synth = (L in speech_synthesizer_langs)
- dat += "[L.name] ([get_language_prefix()][L.key])[synth ? default_str : null]
Speech Synthesizer: [synth ? "YES" : "NOT SUPPORTED"]
[L.desc]
"
-
- src << browse(dat, "window=checklanguage")
- return
+ . += "[L.name] ([get_language_prefix()][L.key])[synth ? default_str : null]
Speech Synthesizer: [synth ? "YES" : "NOT SUPPORTED"]
[L.desc]
"
/mob/living/silicon/proc/toggle_sensor_mode()
var/sensor_type = input("Please select sensor type.", "Sensor Integration", null) in list("Security","Medical","Disable")
diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm
index c9030b0860..71e7736ebb 100644
--- a/code/modules/mob/living/simple_mob/simple_mob.dm
+++ b/code/modules/mob/living/simple_mob/simple_mob.dm
@@ -194,12 +194,6 @@
. = ..()
to_chat(src,"You are \the [src]. [player_msg]")
-
-/mob/living/simple_mob/emote(var/act, var/type, var/desc)
- if(act)
- ..(act, type, desc)
-
-
/mob/living/simple_mob/SelfMove(turf/n, direct)
var/turf/old_turf = get_turf(src)
var/old_dir = dir
@@ -264,14 +258,11 @@
update_icon()
-/mob/living/simple_mob/say(var/message,var/datum/language/language)
- var/verb = "says"
+/mob/living/simple_mob/say_quote(var/message, var/datum/language/speaking = null)
if(speak_emote.len)
- verb = pick(speak_emote)
-
- message = sanitize(message)
-
- ..(message, null, verb)
+ . = pick(speak_emote)
+ else if(speaking)
+ . = ..()
/mob/living/simple_mob/get_speech_ending(verb, var/ending)
return verb
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
index 6ea44df66d..e1f7535bf8 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
@@ -205,7 +205,7 @@
return
// This is awful but its literally say code.
-/mob/living/simple_mob/animal/borer/say(message)
+/mob/living/simple_mob/animal/borer/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
message = sanitize(message)
message = capitalize(message)
@@ -224,10 +224,11 @@
if(copytext(message, 1, 2) == "*")
return emote(copytext(message, 2))
- var/datum/language/L = parse_language(message)
- if(L && L.flags & HIVEMIND)
- L.broadcast(src,trim(copytext(message,3)), src.true_name)
- return
+ var/list/message_pieces = parse_languages(message)
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking && S.speaking.flags & HIVEMIND)
+ S.speaking.broadcast(src, trim(copytext(message, 3)), src.true_name)
+ return
if(!host)
if(chemicals >= 30)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm
index 4f117d485c..618efee6dc 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm
@@ -5,7 +5,7 @@
real_name = "host brain"
universal_understand = 1
-/mob/living/captive_brain/say(var/message)
+/mob/living/captive_brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
if (src.client)
if(client.prefs.muted & MUTE_IC)
@@ -31,7 +31,12 @@
else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
to_chat(M, "The captive mind of [src] whispers, \"[message]\"")
+/mob/living/captive_brain/me_verb(message as text)
+ to_chat(src, "You cannot emote as a captive mind.")
+ return
+
/mob/living/captive_brain/emote(var/message)
+ to_chat(src, "You cannot emote as a captive mind.")
return
/mob/living/captive_brain/process_resist()
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/pets/parrot.dm b/code/modules/mob/living/simple_mob/subtypes/animal/pets/parrot.dm
index dc611e3831..427c0fff9c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/pets/parrot.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/pets/parrot.dm
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
// Parrots can talk, and may repeat things it hears.
/mob/living/simple_mob/animal/passive/bird/parrot
name = "parrot"
@@ -249,4 +250,257 @@
if(holder.stat || !holder.say_list || !message || speaker == holder)
return
var/datum/say_list/S = holder.say_list
+=======
+// Parrots can talk, and may repeat things it hears.
+/mob/living/simple_mob/animal/passive/bird/parrot
+ name = "parrot"
+ description_info = "You can give it a headset by clicking on it with a headset. \
+ To remove it, click the bird while on grab intent."
+ has_langs = list("Galactic Common", "Bird")
+
+ ai_holder_type = /datum/ai_holder/simple_mob/passive/parrot
+
+ // A headset, so that talking parrots can yell at the crew over comms.
+ // If set to a type, on initialize it will be instantiated into that type.
+ var/obj/item/device/radio/headset/my_headset = null
+
+// Say list
+/datum/say_list/bird/poly
+ speak = list(
+ "Poly wanna cracker!",
+ "Check the singulo, you chucklefucks!",
+ "Wire the solars, you lazy bums!",
+ "WHO TOOK THE DAMN HARDSUITS?",
+ "OH GOD ITS FREE CALL THE SHUTTLE",
+ "Danger! Crystal hyperstructure instability!",
+ "CRYSTAL DELAMINATION IMMINENT.",
+ "Tweet tweet, I'm a Teshari.",
+ "Chitters.",
+ "Meteors have been detected on a collision course with the station!"
+ )
+
+// Lets the AI use headsets.
+// Player-controlled parrots will need to do it manually.
+/mob/living/simple_mob/animal/passive/bird/parrot/ISay(message)
+ if(my_headset && prob(50))
+ var/list/keys = list()
+ for(var/channel in my_headset.channels)
+ var/key = get_radio_key_from_channel(channel)
+ if(key)
+ keys += key
+ if(keys.len)
+ var/key_used = pick(keys)
+ return say("[key_used] [message]")
+ return say(message)
+
+// Ugly saycode so parrots can use their headsets.
+/mob/living/simple_mob/animal/passive/bird/parrot/handle_message_mode(message_mode, message, verb, speaking, used_radios)
+ ..()
+ if(message_mode)
+ if(my_headset && istype(my_headset, /obj/item/device/radio))
+ my_headset.talk_into(src, message, message_mode, verb, speaking)
+ used_radios += my_headset
+
+// Clicked on while holding an object.
+/mob/living/simple_mob/animal/passive/bird/parrot/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/device/radio/headset))
+ give_headset(I, user)
+ return
+ return ..()
+
+// Clicked on by empty hand.
+/mob/living/simple_mob/animal/passive/bird/parrot/attack_hand(mob/living/L)
+ if(L.a_intent == I_GRAB && my_headset)
+ remove_headset(L)
+ else
+ ..()
+
+
+/mob/living/simple_mob/animal/passive/bird/parrot/proc/give_headset(obj/item/device/radio/headset/new_headset, mob/living/user)
+ if(!istype(new_headset))
+ to_chat(user, span("warning", "\The [new_headset] isn't a headset."))
+ return
+ if(my_headset)
+ to_chat(user, span("warning", "\The [src] is already wearing \a [my_headset]."))
+ return
+ else
+ user.drop_item(new_headset)
+ my_headset = new_headset
+ new_headset.forceMove(src)
+ to_chat(user, span("warning", "You place \a [new_headset] on \the [src]. You monster."))
+ to_chat(src, span("notice", "\The [user] gives you \a [new_headset]. You should put it to good use immediately."))
+ return
+
+/mob/living/simple_mob/animal/passive/bird/parrot/proc/remove_headset(mob/living/user)
+ if(!my_headset)
+ to_chat(user, "\The [src] doesn't have a headset to remove, thankfully.")
+ else
+ ISay("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
+ my_headset.forceMove(get_turf(src))
+ user.put_in_hands(my_headset)
+ to_chat(user, span("notice", "You take away \the [src]'s [my_headset.name]. Finally."))
+ to_chat(src, span("warning", "\The [user] takes your [my_headset.name] away! How cruel!"))
+ my_headset = null
+
+/mob/living/simple_mob/animal/passive/bird/parrot/examine(mob/user)
+ ..()
+ if(my_headset)
+ to_chat(user, "It is wearing \a [my_headset].")
+
+/mob/living/simple_mob/animal/passive/bird/parrot/Initialize()
+ if(my_headset)
+ my_headset = new my_headset(src)
+ return ..()
+
+// Subtypes.
+
+// Best Bird
+/mob/living/simple_mob/animal/passive/bird/parrot/poly
+ name = "Poly"
+ desc = "It's a parrot. An expert on quantum cracker theory."
+ icon_state = "poly"
+ icon_rest = "poly-held"
+ icon_dead = "poly-dead"
+ tt_desc = "E Ara macao"
+ my_headset = /obj/item/device/radio/headset/headset_eng
+ say_list_type = /datum/say_list/bird/poly
+
+// Best Bird with best headset.
+/mob/living/simple_mob/animal/passive/bird/parrot/poly/ultimate
+ my_headset = /obj/item/device/radio/headset/omni
+
+/mob/living/simple_mob/animal/passive/bird/parrot/kea
+ name = "kea"
+ desc = "A species of parrot. On Earth, they are unique among other parrots for residing in alpine climates. \
+ They are known to be intelligent and curious, which has made some consider them a pest."
+ icon_state = "kea"
+ icon_rest = "kea-held"
+ icon_dead = "kea-dead"
+ tt_desc = "E Nestor notabilis"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/eclectus
+ name = "eclectus"
+ desc = "A species of parrot, this species features extreme sexual dimorphism in their plumage's colors. \
+ A male eclectus has emerald green plumage, where as a female eclectus has red and purple plumage."
+ icon_state = "eclectus"
+ icon_rest = "eclectus-held"
+ icon_dead = "eclectus-dead"
+ tt_desc = "E Eclectus roratus"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/eclectus/Initialize()
+ gender = pick(MALE, FEMALE)
+ if(gender == FEMALE)
+ icon_state = "eclectusf"
+ icon_rest = "eclectusf-held"
+ icon_dead = "eclectusf-dead"
+ return ..()
+
+/mob/living/simple_mob/animal/passive/bird/parrot/grey_parrot
+ name = "grey parrot"
+ desc = "A species of parrot. This one is predominantly grey, but has red tail feathers."
+ icon_state = "agrey"
+ icon_rest = "agrey-held"
+ icon_dead = "agrey-dead"
+ tt_desc = "E Psittacus erithacus"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/black_headed_caique
+ name = "black-headed caique"
+ desc = "A species of parrot, these birds have a distinct black color on their heads, distinguishing them from their relative Caiques."
+ icon_state = "bcaique"
+ icon_rest = "bcaique-held"
+ icon_dead = "bcaique-dead"
+ tt_desc = "E Pionites melanocephalus"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/white_caique
+ name = "white-bellied caique"
+ desc = "A species of parrot, they are also known as the Green-Thighed Parrot."
+ icon_state = "wcaique"
+ icon_rest = "wcaique-held"
+ icon_dead = "wcaique-dead"
+ tt_desc = "E Pionites leucogaster"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/budgerigar
+ name = "budgerigar"
+ desc = "A species of parrot, they are also known as the common parakeet, or in some circles, the budgie. \
+ This one is has its natural colors of green and yellow."
+ icon_state = "gbudge"
+ icon_rest = "gbudge-held"
+ icon_dead = "gbudge-dead"
+ tt_desc = "E Melopsittacus undulatus"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/budgerigar/blue
+ icon_state = "bbudge"
+ icon_rest = "bbudge-held"
+ icon_dead = "bbudge-dead"
+ desc = "A species of parrot, they are also known as the common parakeet, or in some circles, the budgie. \
+ This one has a mutation which altered its color to be blue instead of green and yellow."
+
+/mob/living/simple_mob/animal/passive/bird/parrot/budgerigar/bluegreen
+ icon_state = "bgbudge"
+ icon_rest = "bgbudge-held"
+ icon_dead = "bgbudge-dead"
+ desc = "A species of parrot, they are also known as the common parakeet, or in some circles, the budgie. \
+ This one has a mutation which altered its color to be a mix of blue and green."
+
+/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel
+ name = "cockatiel"
+ desc = "A species of parrot. This one has a highly visible crest."
+ icon_state = "tiel"
+ icon_rest = "tiel-held"
+ icon_dead = "tiel-dead"
+ tt_desc = "E Nymphicus hollandicus"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/white
+ icon_state = "wtiel"
+ icon_rest = "wtiel-held"
+ icon_dead = "wtiel-dead"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/yellowish
+ icon_state = "luttiel"
+ icon_rest = "luttiel-held"
+ icon_dead = "luttiel-dead"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/grey
+ icon_state = "blutiel" // idk why this is blu.
+ icon_rest = "blutiel-held"
+ icon_dead = "blutiel-dead"
+
+// This actually might be the yellow-crested cockatoo but idk.
+/mob/living/simple_mob/animal/passive/bird/parrot/sulphur_cockatoo
+ name = "sulphur-crested cockatoo"
+ desc = "A species of parrot. This one has an expressive yellow crest. Their underwing and tail feathers are also yellow."
+ icon_state = "too"
+ icon_rest = "too-held"
+ icon_dead = "too-dead"
+ tt_desc = "E Cacatua galerita"
+
+// This was originally called 'hooded_too', which might not mean the unbrella cockatoo but idk.
+/mob/living/simple_mob/animal/passive/bird/parrot/white_cockatoo
+ name = "white cockatoo"
+ desc = "A species of parrot. This one is also known as the Umbrella Cockatoo, due to the semicircular shape of its crest."
+ icon_state = "utoo"
+ icon_rest = "utoo-held"
+ icon_dead = "utoo-dead"
+ tt_desc = "E Cacatua alba"
+
+/mob/living/simple_mob/animal/passive/bird/parrot/pink_cockatoo
+ name = "pink cockatoo"
+ desc = "A species of parrot. This one is also known as Major Mitchell's cockatoo, \
+ in honor of a human surveyor and explorer who existed before humans fully explored their home planet."
+ icon_state = "mtoo"
+ icon_rest = "mtoo-held"
+ icon_dead = "mtoo-dead"
+ tt_desc = "E Lophochroa leadbeateri"
+
+
+// AI
+/datum/ai_holder/simple_mob/passive/parrot
+ speak_chance = 2
+ base_wander_delay = 8
+
+/datum/ai_holder/simple_mob/passive/parrot/on_hear_say(mob/living/speaker, message)
+ if(holder.stat || !holder.say_list || !message || speaker == holder)
+ return
+ var/datum/say_list/S = holder.say_list
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
S.speak |= message
\ No newline at end of file
diff --git a/code/modules/mob/living/voice/voice.dm b/code/modules/mob/living/voice/voice.dm
index 92270dc145..919e302bcf 100644
--- a/code/modules/mob/living/voice/voice.dm
+++ b/code/modules/mob/living/voice/voice.dm
@@ -104,7 +104,7 @@
// Proc: say()
// Parameters: 4 (generic say() arguments)
// Description: Adds a speech bubble to the communicator device, then calls ..() to do the real work.
-/mob/living/voice/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/whispering=0)
+/mob/living/voice/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
//Speech bubbles.
if(comm)
var/speech_bubble_test = say_test(message)
@@ -118,7 +118,7 @@
M << speech_bubble
src << speech_bubble
- ..(message, speaking, verb, alt_name, whispering) //mob/living/say() can do the actual talking.
+ ..() //mob/living/say() can do the actual talking.
// Proc: speech_bubble_appearance()
// Parameters: 0
@@ -126,15 +126,15 @@
/mob/living/voice/speech_bubble_appearance()
return "comm"
-/mob/living/voice/say_understands(var/other,var/datum/language/speaking = null)
+/mob/living/voice/say_understands(var/other, var/datum/language/speaking = null)
//These only pertain to common. Languages are handled by mob/say_understands()
- if (!speaking)
- if (istype(other, /mob/living/carbon))
- return 1
- if (istype(other, /mob/living/silicon))
- return 1
- if (istype(other, /mob/living/carbon/brain))
- return 1
+ if(!speaking)
+ if(iscarbon(other))
+ return TRUE
+ if(issilicon(other))
+ return TRUE
+ if(isbrain(other))
+ return TRUE
return ..()
/mob/living/voice/custom_emote(var/m_type=1,var/message = null,var/range=world.view)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 68ea573a72..d1d65ff21d 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1224,3 +1224,6 @@ mob/proc/yank_out_object()
selfimage.loc = src
return selfimage
+
+/mob/proc/GetAltName()
+ return ""
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 5450ced7ee..7c1034a77d 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -184,6 +184,12 @@ proc/getsensorlevel(A)
p++
return t
+/proc/stars_all(list/message_pieces, pr)
+ // eugh, we have to clone the list to avoid collateral damage due to the nature of these messages
+ . = list()
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ . += new /datum/multilingual_say_piece(S.speaking, stars(S.message))
+
proc/slur(phrase)
phrase = html_decode(phrase)
var/leng=length(phrase)
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index bfdc39b25e..81804d7119 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -605,7 +605,7 @@
return ready && ..()
// Prevents lobby players from seeing say, even with ghostears
-/mob/new_player/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
+/mob/new_player/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null)
return
// Prevents lobby players from seeing emotes, even with ghosteyes
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 25d506d91a..439e3c5314 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -1,4 +1,4 @@
-/mob/proc/say()
+/mob/proc/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
return
/mob/verb/whisper(message as text)
@@ -30,7 +30,7 @@
set_typing_indicator(FALSE)
if(use_me)
- usr.emote("me",usr.emote_type,message)
+ custom_emote(usr.emote_type, message)
else
usr.emote(message)
@@ -42,7 +42,7 @@
if(!client)
return // Clientless mobs shouldn't be trying to talk in deadchat.
- if(!src.client.holder)
+ if(!client.holder)
if(!config.dsay_allowed)
to_chat(src, "Deadchat is globally muted.")
return
@@ -55,55 +55,55 @@
say_dead_direct("[pick("complains","moans","whines","laments","blubbers")], \"[message]\"", src)
-/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null)
-
- if (src.stat == DEAD)
- return 1
+/mob/proc/say_understands(var/mob/other, var/datum/language/speaking = null)
+ if(stat == DEAD)
+ return TRUE
//Universal speak makes everything understandable, for obvious reasons.
- else if(src.universal_speak || src.universal_understand)
- return 1
+ else if(universal_speak || universal_understand)
+ return TRUE
//Languages are handled after.
- if (!speaking)
+ if(!speaking)
if(!other)
- return 1
+ return TRUE
if(other.universal_speak)
- return 1
+ return TRUE
if(isAI(src) && ispAI(other))
- return 1
- if (istype(other, src.type) || istype(src, other.type))
- return 1
- return 0
+ return TRUE
+ if(istype(other, type) || istype(src, other.type))
+ return TRUE
+ return FALSE
if(speaking.flags & INNATE)
- return 1
+ return TRUE
+
+ //non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
+ if(speaking.flags & NONVERBAL)
+ if(sdisabilities & BLIND || blinded)
+ return FALSE
+ if(!other || !(other in view(src)))
+ return FALSE
//Language check.
- for(var/datum/language/L in src.languages)
+ for(var/datum/language/L in languages)
if(speaking.name == L.name)
- return 1
+ return TRUE
- return 0
-
-/*
- ***Deprecated***
- let this be handled at the hear_say or hear_radio proc
- This is left in for robot speaking when humans gain binary channel access until I get around to rewriting
- robot_talk() proc.
- There is no language handling build into it however there is at the /mob level so we accept the call
- for it but just ignore it.
-*/
+ return FALSE
/mob/proc/say_quote(var/message, var/datum/language/speaking = null)
- var/verb = "says"
- var/ending = copytext(message, length(message))
- if(ending=="!")
- verb=pick("exclaims","shouts","yells")
- else if(ending=="?")
- verb="asks"
+ var/verb = "says"
+ var/ending = copytext(message, length(message))
- return verb
+ if(speaking)
+ verb = speaking.get_spoken_verb(ending)
+ else
+ if(ending == "!")
+ verb = pick("exclaims", "shouts", "yells")
+ else if(ending == "?")
+ verb = "asks"
+ return verb
/mob/proc/emote(var/act, var/type, var/message)
@@ -120,38 +120,123 @@
/mob/proc/say_test(var/text)
var/ending = copytext(text, length(text))
- if (ending == "?")
+ if(ending == "?")
return "1"
- else if (ending == "!")
+ else if(ending == "!")
return "2"
return "0"
//parses the message mode code (e.g. :h, :w) from text, such as that supplied to say.
//returns the message mode string or null for no message mode.
//standard mode is the mode returned for the special ';' radio code.
-/mob/proc/parse_message_mode(var/message, var/standard_mode="headset")
- if(length(message) >= 1 && copytext(message,1,2) == ";")
+/mob/proc/parse_message_mode(var/message, var/standard_mode = "headset")
+ if(length(message) >= 1 && copytext(message, 1, 2) == ";")
return standard_mode
if(length(message) >= 2)
- var/channel_prefix = copytext(message, 1 ,3)
+ var/channel_prefix = copytext(message, 1, 3)
return department_radio_keys[channel_prefix]
return null
-//parses the language code (e.g. :j) from text, such as that supplied to say.
-//returns the language object only if the code corresponds to a language that src can speak, otherwise null.
-/mob/proc/parse_language(var/message)
- var/prefix = copytext(message,1,2)
- // This is for audible emotes
- if(length(message) >= 1 && prefix == "!")
- return GLOB.all_languages["Noise"]
+/datum/multilingual_say_piece
+ var/datum/language/speaking = null
+ var/message = ""
- if(length(message) >= 2 && is_language_prefix(prefix))
- var/language_prefix = copytext(message, 2 ,3)
- var/datum/language/L = GLOB.language_keys[language_prefix]
- if (can_speak(L))
- return L
+/datum/multilingual_say_piece/New(datum/language/new_speaking, new_message)
+ . = ..()
+ speaking = new_speaking
+ if(new_message)
+ message = new_message
+
+/mob/proc/find_valid_prefixes(message)
+ var/list/prefixes = list() // [["Common", start, end], ["Gutter", start, end]]
+ for(var/i in 1 to length(message))
+ // This grabs trimmed 3 character substrings, to allow for up to 1 prefix and 1 letter language keys
+ var/selection = trim_right(lowertext(copytext(message, i, i + 2)))
+ // The first character in the selection will always be the prefix (if this is a valid language invocation)
+ var/prefix = copytext(selection, 1, 2)
+ var/language_key = copytext(selection, 2, 3)
+ if(is_language_prefix(prefix))
+ // Okay, we're definitely now trying to invoke a language (probably)
+ // This "[]" is probably unnecessary but BYOND will runtime if a number is used
+ var/datum/language/L = GLOB.language_keys["[language_key]"]
+ // It's kinda silly that we have to check L != null and this isn't done for us by can_speak (it runtimes instead), but w/e
+ if(L && can_speak(L))
+ // So we have a valid language invocation, and we can speak that language, let's make a piece for it
+ // This language will be the language until the next prefixes[] index, or the end of the message if there are none.
+ prefixes[++prefixes.len] = list(L, i, i + length(selection))
+ else if(L)
+ // We found a valid language, but they can't speak it. Let's make them speak gibberish instead.
+ prefixes[++prefixes.len] = list(GLOB.all_languages[LANGUAGE_GIBBERISH], i, i + length(selection))
+ continue
+ if(i == 1)
+ // This covers the case of "no prefixes in use."
+ prefixes[++prefixes.len] = list(get_default_language(), i, i)
+
+ return prefixes
+
+/mob/proc/strip_prefixes(message, mob/prefixer = null)
+ . = ""
+ var/last_index = 1
+ for(var/i in 1 to length(message))
+ var/selection = trim_right(lowertext(copytext(message, i, i + 2)))
+ // The first character in the selection will always be the prefix (if this is a valid language invocation)
+ var/prefix = copytext(selection, 1, 2)
+ var/language_key = copytext(selection, 2, 3)
+ if(is_language_prefix(prefix))
+ var/datum/language/L = GLOB.language_keys["[language_key]"]
+ if(L)
+ . += copytext(message, last_index, i)
+ last_index = i + 2
+ if(i + 1 > length(message))
+ . += copytext(message, last_index)
+
+// this returns a structured message with language sections
+// list(/datum/multilingual_say_piece(common, "hi"), /datum/multilingual_say_piece(farwa, "squik"), /datum/multilingual_say_piece(common, "meow!"))
+/mob/proc/parse_languages(message)
+ . = list()
+
+ // Noise language is a snowflake.
+ if(copytext(message, 1, 2) == "!" && length(message) > 1)
+ // Note that list() here is intended
+ // Returning a raw /datum/multilingual_say_piece is supported, but only for hivemind languages
+ // What we actually want is a normal say piece that's all noise lang
+ return list(new /datum/multilingual_say_piece(GLOB.all_languages["Noise"], trim(strip_prefixes(copytext(message, 2)))))
+
+ // Scan the message for prefixes
+ var/list/prefix_locations = find_valid_prefixes(message)
+ if(!LAZYLEN(prefix_locations)) // There are no prefixes... or at least, no _valid_ prefixes.
+ . += new /datum/multilingual_say_piece(get_default_language(), trim(strip_prefixes(message))) // So we'll just strip those pesky things and still make the message.
+
+ for(var/i in 1 to length(prefix_locations))
+ var/current = prefix_locations[i] // ["Common", start, end]
+
+ // There are a few things that will make us want to ignore all other languages in - namely, HIVEMIND languages.
+ var/datum/language/L = current[1]
+ if(L && (L.flags & HIVEMIND || L.flags & SIGNLANG))
+ return new /datum/multilingual_say_piece(L, trim(strip_prefixes(message)))
+
+ if(i + 1 > length(prefix_locations)) // We are out of lookaheads, that means the rest of the message is in cur lang
+ var/spoke_message = handle_autohiss(trim(copytext(message, current[3])), L)
+ . += new /datum/multilingual_say_piece(current[1], spoke_message)
else
- return GLOB.all_languages[LANGUAGE_GIBBERISH]
- return null
+ var/next = prefix_locations[i + 1] // We look ahead at the next message to see where we need to stop.
+ var/spoke_message = handle_autohiss(trim(copytext(message, current[3], next[2])), L)
+ . += new /datum/multilingual_say_piece(current[1], spoke_message)
+
+/* These are here purely because it would be hell to try to convert everything over to using the multi-lingual system at once */
+/proc/message_to_multilingual(message, datum/language/speaking = null)
+ . = list(new /datum/multilingual_say_piece(speaking, message))
+
+/proc/multilingual_to_message(list/message_pieces, var/requires_machine_understands = FALSE, var/with_capitalization = FALSE)
+ . = ""
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ var/message_to_append = S.message
+ if(S.speaking)
+ if(with_capitalization)
+ message_to_append = S.speaking.format_message_plain(S.message)
+ if(requires_machine_understands && !S.speaking.machine_understands)
+ message_to_append = S.speaking.scramble(S.message)
+ . += message_to_append + " "
+ . = trim_right(.)
diff --git a/code/modules/multiz/zshadow.dm b/code/modules/multiz/zshadow.dm
index 99b5314ade..eaa91e4a2b 100644
--- a/code/modules/multiz/zshadow.dm
+++ b/code/modules/multiz/zshadow.dm
@@ -41,12 +41,12 @@
return owner.examine(user, distance, infix, suffix)
// Relay some stuff they hear
-/mob/zshadow/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
+/mob/zshadow/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(speaker && speaker.z != src.z)
return // Only relay speech on our acutal z, otherwise we might relay sounds that were themselves relayed up!
if(isliving(owner))
verb += " from above"
- return owner.hear_say(message, verb, language, alt_name, italics, speaker, speech_sound, sound_vol)
+ return owner.hear_say(message, verb, language, italics, speaker, speech_sound, sound_vol)
/mob/zshadow/proc/sync_icon(var/mob/M)
name = M.name
diff --git a/code/modules/xenoarcheaology/finds/special.dm b/code/modules/xenoarcheaology/finds/special.dm
index d93e47a1dd..3ed9ce38e8 100644
--- a/code/modules/xenoarcheaology/finds/special.dm
+++ b/code/modules/xenoarcheaology/finds/special.dm
@@ -29,11 +29,11 @@
var/mob/living/M = src.loc
M.say(pick(heard_talk))
-/obj/item/clothing/mask/gas/poltergeist/hear_talk(mob/M as mob, text)
+/obj/item/clothing/mask/gas/poltergeist/hear_talk(mob/M, list/message_pieces, verb)
..()
if(heard_talk.len > max_stored_messages)
heard_talk.Remove(pick(heard_talk))
- heard_talk.Add(text)
+ heard_talk.Add(multilingual_to_message(message_pieces))
if(istype(src.loc, /mob/living) && world.time - last_twitch > 50)
last_twitch = world.time
@@ -116,7 +116,7 @@
else if(get_dist(W, src) > 10)
shadow_wights.Remove(wight_check_index)
-/obj/item/weapon/vampiric/hear_talk(mob/M as mob, text)
+/obj/item/weapon/vampiric/hear_talk(mob/M, list/message_pieces, verb)
..()
if(world.time - last_bloodcall >= bloodcall_interval && M in view(7, src))
bloodcall(M)
diff --git a/code/modules/xenobio2/mob/xeno procs.dm b/code/modules/xenobio2/mob/xeno procs.dm
index 4b05bbf2e9..0acdcba2e7 100644
--- a/code/modules/xenobio2/mob/xeno procs.dm
+++ b/code/modules/xenobio2/mob/xeno procs.dm
@@ -112,7 +112,11 @@ Divergence proc, used in mutation to make unique datums.
/mob/living/simple_mob/xeno/proc/RandomizeTraits()
return
+<<<<<<< HEAD
/mob/living/simple_mob/xeno/hear_say(var/message, var/verb = "says", var/datum/language/language, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
+=======
+/mob/living/simple_animal/xeno/hear_say(var/message, var/verb = "says", var/datum/language/language, var/italics = 0, var/mob/speaker = null)
+>>>>>>> 54a8a58... Saycode Overhaul -- Multilingualism (#6956)
if(traitdat.traits[TRAIT_XENO_CANLEARN])
/*
Until this gets sorted out to a functioning point, or waiting on Psi's saycode update.
@@ -128,7 +132,7 @@ Divergence proc, used in mutation to make unique datums.
*/
if(!(message in speak))
speech_buffer.Add(message)
- ..(message,verb,language,alt_name,italics,speaker)
+ ..(message,verb,language,italics,speaker)
/mob/living/simple_mob/xeno/proc/ProcessSpeechBuffer()
if(speech_buffer.len)
diff --git a/vorestation.dme b/vorestation.dme
index 7515d44cbd..7ee3eed2cc 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2373,7 +2373,6 @@
#include "code\modules\mob\living\carbon\alien\emote.dm"
#include "code\modules\mob\living\carbon\alien\life.dm"
#include "code\modules\mob\living\carbon\alien\progression.dm"
-#include "code\modules\mob\living\carbon\alien\say.dm"
#include "code\modules\mob\living\carbon\alien\update_icons.dm"
#include "code\modules\mob\living\carbon\alien\diona\diona.dm"
#include "code\modules\mob\living\carbon\alien\diona\diona_attacks.dm"
@@ -2490,6 +2489,7 @@
#include "code\modules\mob\living\carbon\metroid\subtypes.dm"
#include "code\modules\mob\living\carbon\metroid\update_icons.dm"
#include "code\modules\mob\living\silicon\death.dm"
+#include "code\modules\mob\living\silicon\emote.dm"
#include "code\modules\mob\living\silicon\laws.dm"
#include "code\modules\mob\living\silicon\login.dm"
#include "code\modules\mob\living\silicon\say.dm"