Saycode Overhaul -- Multilingualism (#6956)

* Port ParadiseSS13/Paradise#2100 - Saycode refactor

* Removed unused old carbon slimes code

* Port ParadiseSS13/Paradise#5099 - Saycode part 2

* Ported ParadiseSS13/Paradise#7170's /datum/browser Check Known Languages

* Port ParadiseSS13/Paradise#9240 - Get rid of alt_name in favor of GetAltName()

* Port ParadiseSS13/Paradise#10330 - You can now use multiple languages in one message

* Addressed Atermonera's review.

Translators now print the full message if they find any languages within the
message that the user doesn't understand, minus languages it cannot translate.

Additionally, the combine_message proc has been significantly simplified
by eliminating an ugly tree structure with the help of a little helper
proc.

The removal of the extra span inside each piece doesn't seem to have
visually changed the messages in any other way than changing where the
wordwrap happens, strangely enough. Must be something in IE's code being
picky about invisible elements. On the bright side, it splits *later*
than it did before, thus reducing the lines a message will take up by a
tiny amount.

Also, a bunch of things now have the 'filter_say' class from
PolarisSS13/Polaris#6998. Since span classes with no definition are
totally valid and just don't do anything, this PR does **not** depend on
that PR being merged first.

* Always gotta be one
This commit is contained in:
ShadowLarkens
2020-04-20 01:11:53 -07:00
committed by GitHub
parent 1ed5556b8f
commit 54a8a5823d
72 changed files with 1338 additions and 3284 deletions

View File

@@ -13,6 +13,8 @@
#define isitem(D) istype(D, /obj/item) #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 isairlock(A) istype(A, /obj/machinery/door/airlock)
#define isorgan(A) istype(A, /obj/item/organ/external) #define isorgan(A) istype(A, /obj/item/organ/external)

View File

@@ -368,3 +368,7 @@ var/global/list/##LIST_NAME = list();\
#define MOUSE_OPACITY_TRANSPARENT 0 #define MOUSE_OPACITY_TRANSPARENT 0
#define MOUSE_OPACITY_ICON 1 #define MOUSE_OPACITY_ICON 1
#define MOUSE_OPACITY_OPAQUE 2 #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

View File

@@ -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. /*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.*/ 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) /obj/machinery/hologram/holopad/hear_talk(mob/M, list/message_pieces, verb)
if(M) if(M && LAZYLEN(masters))
for(var/mob/living/silicon/ai/master in 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(masters[master] && M != master)
if(speaking) master.relay_speech(M, message_pieces, verb)
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 = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span></i>"
else
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
master.show_message(rendered, 2)
/obj/machinery/hologram/holopad/see_emote(mob/living/M, text) /obj/machinery/hologram/holopad/see_emote(mob/living/M, text)
if(M) if(M)

View File

@@ -71,7 +71,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],, signal.data["realname"], signal.data["vname"],,
signal.data["compression"], signal.data["level"], signal.frequency, signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"], signal.data["language"] ) signal.data["verb"])
/** #### - Simple Broadcast - #### **/ /** #### - Simple Broadcast - #### **/
@@ -97,7 +97,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency, signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"], signal.data["language"]) signal.data["verb"])
if(!message_delay) if(!message_delay)
message_delay = 1 message_delay = 1
@@ -165,7 +165,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency, signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], signal.data["language"]) signal.data["verb"])
else else
if(intercept) if(intercept)
Broadcast_Message(signal.data["connection"], signal.data["mob"], Broadcast_Message(signal.data["connection"], signal.data["mob"],
@@ -173,7 +173,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], signal.data["language"]) signal.data["verb"])
@@ -235,9 +235,9 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
**/ **/
/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M, /proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
var/vmask, var/vmessage, var/obj/item/device/radio/radio, var/vmask, var/list/vmessage_pieces, var/obj/item/device/radio/radio,
var/message, var/name, var/job, var/realname, var/vname, var/list/message_pieces, 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/data, var/compression, var/list/level, var/freq, var/verbage = "says")
/* ###### Prepare the radio connection ###### */ /* ###### Prepare the radio connection ###### */
@@ -300,7 +300,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
for (var/mob/R in receive) for (var/mob/R in receive)
/* --- Loop through the receivers and categorize them --- */ /* --- 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 continue
if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes. if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes.
@@ -317,10 +317,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Can understand the speech --- // --- Can understand the speech ---
if (!M || R.say_understands(M)) if(!M || R.say_understands(M))
// - Not human or wearing a voice mask - // - Not human or wearing a voice mask -
if (!M || !ishuman(M) || vmask) if(!M || !ishuman(M) || vmask)
heard_masked += R heard_masked += R
// - Human and not wearing voice mask - // - Human and not wearing voice mask -
@@ -331,7 +331,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
else else
// - The speaker has a prespecified "voice message" to display if not understood - // - The speaker has a prespecified "voice message" to display if not understood -
if (vmessage) if(vmessage_pieces)
heard_voice += R heard_voice += R
// - Just display a garbled message - // - Just display a garbled message -
@@ -340,7 +340,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* ###### Begin formatting and sending the message ###### */ /* ###### 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 --- */ /* --- Some miscellaneous variables to format the string output --- */
var/freq_text = get_frequency_name(display_freq) var/freq_text = get_frequency_name(display_freq)
@@ -356,12 +356,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Filter the message; place it in quotes apply a verb --- // --- Filter the message; place it in quotes apply a verb ---
var/quotedmsg = null var/quotedmsg = null
if(M) if(M)
quotedmsg = M.say_quote(message) quotedmsg = "[M.say_quote(multilingual_to_message(message_pieces))], \"[multilingual_to_message(message_pieces)]\""
else 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 --- // --- This following recording is intended for research and feedback in the use of department radio channels ---
@@ -402,44 +401,36 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
//End of research and feedback code. //End of research and feedback code.
/* ###### Send the message ###### */ /* ###### Send the message ###### */
/* --- Process all the mobs that heard a masked voice (understood) --- */ /* --- 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) 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) --- */ /* --- 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) 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) --- */ /* --- 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) 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) --- */ /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
// Displays garbled message (ie "f*c* **u, **i*er!") // Displays garbled message (ie "f*c* **u, **i*er!")
if(length(heard_garbled))
if (length(heard_garbled))
for (var/mob/R in 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 --- */ /* --- 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) 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 return 1
/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level) /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)
/* ###### Prepare the radio connection ###### */ /* ###### Prepare the radio connection ###### */
if(!M) if(!M)
@@ -519,7 +510,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Can understand the speech --- // --- Can understand the speech ---
if (R.say_understands(M)) if(R.say_understands(M))
heard_normal += R heard_normal += R
@@ -532,7 +523,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* ###### Begin formatting and sending the message ###### */ /* ###### 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 --- */ /* --- Some miscellaneous variables to format the string output --- */
var/part_a = "<span class='[frequency_span_class(display_freq)]'><span class='name'>" // goes in the actual output var/part_a = "<span class='[frequency_span_class(display_freq)]'><span class='name'>" // goes in the actual output
@@ -587,7 +578,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Process all the mobs that heard the voice normally (understood) --- */ /* --- 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]" var/rendered = "[part_a][source][part_b]\"[text]\"[part_c]"
for (var/mob/R in heard_normal) for (var/mob/R in heard_normal)
@@ -596,7 +587,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) --- */ /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
// Displays garbled message (ie "f*c* **u, **i*er!") // Displays garbled message (ie "f*c* **u, **i*er!")
if (length(heard_garbled)) if(length(heard_garbled))
var/quotedmsg = "\"[stars(text)]\"" var/quotedmsg = "\"[stars(text)]\""
var/rendered = "[part_a][source][part_b][quotedmsg][part_c]" var/rendered = "[part_a][source][part_b][quotedmsg][part_c]"
@@ -606,7 +597,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Complete gibberish. Usually happens when there's a compressed message --- */ /* --- 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/quotedmsg = "\"[Gibberish(text, compression + 50)]\""
var/rendered = "[part_a][Gibberish(source, compression + 50)][part_b][quotedmsg][part_c]" var/rendered = "[part_a][Gibberish(source, compression + 50)][part_b][quotedmsg][part_c]"

View File

@@ -574,7 +574,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
var/encryption = "null" // encryption key: ie "password" var/encryption = "null" // encryption key: ie "password"
var/salt = "null" // encryption salt: ie "123comsat" var/salt = "null" // encryption salt: ie "123comsat"
// would add up to md5("password123comsat") // would add up to md5("password123comsat")
var/language = "human"
var/obj/item/device/radio/headset/server_radio = null var/obj/item/device/radio/headset/server_radio = null
/obj/machinery/telecomms/server/New() /obj/machinery/telecomms/server/New()
@@ -615,12 +614,11 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
log.parameters["mobtype"] = signal.data["mobtype"] log.parameters["mobtype"] = signal.data["mobtype"]
log.parameters["job"] = signal.data["job"] log.parameters["job"] = signal.data["job"]
log.parameters["key"] = signal.data["key"] 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["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["name"] = signal.data["name"]
log.parameters["realname"] = signal.data["realname"] log.parameters["realname"] = signal.data["realname"]
log.parameters["language"] = signal.data["language"]
var/race = "unknown" var/race = "unknown"
if(ishuman(M)) if(ishuman(M))
@@ -649,7 +647,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// If the signal is still compressed, make the log entry gibberish // If the signal is still compressed, make the log entry gibberish
if(signal.data["compression"] > 0) 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["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50)
log.parameters["name"] = Gibberish(signal.data["name"], 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) log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50)

View File

@@ -119,134 +119,6 @@
melee_can_hit = 1 melee_can_hit = 1
return 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 = {"<html>
<head>
<style>
body {background:#000;color: #00ff00;font-family:"Courier",monospace;font-size:12px;}
#target {word-wrap: break-word;width:100%;padding-right:2px;}
#form {display:none;padding:0;margin:0;}
#input {background:#000;color: #00ff00;font-family:"Courier",monospace;border:none;padding:0;margin:0;width:90%;font-size:12px;}
</style>
<script type="text/javascript">
var text = "SGNL RCVD\\nTAG ANL :: STTS ACCPTD \\nINITSOC{buff:{128,0,NIL};p:'-zxf';stddev;inenc:'bin';outenc:'plain'}\\nSOD ->\\n0010101100101011001000000101010001101000011010010111001100100000011011010110000101100011011010000110100101101110011001010010000001101001011100110010000001100100011010010111001101100011011010000110000101110010011001110110010101100100001000000110100101101110011101000110111100100000011110010110111101110101011100100010000001100011011000010111001001100101001000000010101100101011000011010000101000101011001010110010000001000110011010010110011101101000011101000010000001110111011010010111010001101000001000000111010001101000011010010111001100100000011011010110000101100011011010000110100101101110011001010010110000100000011000010110111001100100001000000110011101110101011000010111001001100100001000000110100101110100001000000110011001110010011011110110110100100000011101000110100001100101001000000111001101101000011000010110110101100101001000000110111101100110001000000110010001100101011001100110010101100001011101000010000000101011001010110000110100001010001010110010101100100000010100110110010101110010011101100110010100100000011101000110100001101001011100110010000001101101011000010110001101101000011010010110111001100101001011000010000001100001011100110010000001111001011011110111010100100000011101110110111101110101011011000110010000100000011010000110000101110110011001010010000001100110011010010110011101101000011101000010000001101001011101000010000001100110011011110111001000100000011110010110111101110101001000000010101100101011\\n<- EOD\\nSOCFLUSH\\n";
var target_id = "target";
var form_id = "form";
var input_id = "input";
var delay=5;
var currentChar=0;
var inter;
var cur_el;
var maiden_el;
function type()
{
maiden_el = cur_el = document.getElementById(target_id);
if(cur_el && typeof(cur_el)!='undefined'){
inter = setInterval(function(){appendText(cur_el)},delay);
}
}
function appendText(el){
if(currentChar>text.length){
maiden_el.style.border = 'none';
clearInterval(inter);
var form = document.getElementById(form_id);
var input = document.getElementById(input_id);
if((form && typeof(form)!='undefined') && (input && typeof(input)!='undefined')){
form.style.display = 'block';
input.focus();
}
return;
}
var tchar = text.substr(currentChar, 1);
if(tchar=='\\n'){
el = cur_el = document.createElement('div');
maiden_el.appendChild(cur_el);
currentChar++;
return;
}
if(!el.firstChild){
var tNode=document.createTextNode(tchar);
el.appendChild(tNode);
}
else {
el.firstChild.nodeValue = el.firstChild.nodeValue+tchar
}
currentChar++;
}
function addSubmitEvent(form, input) {
input.onkeydown = function(e) {
e = e || window.event;
if (e.keyCode == 13) {
form.submit();
return false;
}
};
}
window.onload = function(){
var form = document.getElementById(form_id);
var input = document.getElementById(input_id);
if((!form || typeof(form)=='undefined') || (!input || typeof(input)=='undefined')){
return false;
}
addSubmitEvent(form,input);
type();
}
</script>
</head>
<body>
<div id="wrapper"><div id="target"></div>
<form id="form" name="form" action="byond://" method="get">
<label for="input">&gt;</label><input name="saminput" type="text" id="input" value="" />
<input type=\"hidden\" name=\"src\" value=\"\ref[src]\">
</form>
</div>
</body>
</html>
"}
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) /obj/mecha/combat/moved_inside(var/mob/living/carbon/human/H as mob)
if(..()) if(..())
if(H.client) if(H.client)
@@ -275,10 +147,3 @@
if(top_filter.get("close")) if(top_filter.get("close"))
am = null am = null
return 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
*/

View File

@@ -290,10 +290,9 @@
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits. /obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
return return
/obj/mecha/hear_talk(mob/M as mob, text) /obj/mecha/hear_talk(mob/M, list/message_pieces, verb)
if(M==occupant && radio.broadcasting) if(M == occupant && radio.broadcasting)
radio.talk_into(M, text) radio.talk_into(M, message_pieces)
return
//////////////////////////// ////////////////////////////
///// Action processing //// ///// Action processing ////

View File

@@ -220,30 +220,22 @@
..() ..()
// Proc: hear_talk() // 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 // Parameters: 3 (M - the mob the speech originated from,
// being used) // 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. // 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) for(var/obj/item/device/communicator/comm in communicating)
var/turf/T = get_turf(comm) var/turf/T = get_turf(comm)
if(!T) return if(!T) return
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0)
var/list/mobs_to_relay = in_range["mobs"] var/list/mobs_to_relay = in_range["mobs"]
for(var/mob/mob in mobs_to_relay) for(var/mob/mob in mobs_to_relay)
//Can whoever is hearing us understand? var/message = mob.combine_message(message_pieces, verb, M)
if(!mob.say_understands(M, speaking))
if(speaking)
text = speaking.scramble(text)
else
text = stars(text)
var/name_used = M.GetVoice() var/name_used = M.GetVoice()
var/rendered = null var/rendered = null
if(speaking) //Language being used rendered = "<span class='game say'>[bicon(src)] <span class='name'>[name_used]</span> [message]</span>"
rendered = "<span class='game say'>[bicon(src)] <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span>"
else
rendered = "<span class='game say'>[bicon(src)] <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span>"
mob.show_message(rendered, 2) mob.show_message(rendered, 2)
// Proc: show_message() // Proc: show_message()

View File

@@ -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!") 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) /obj/item/device/megaphone/proc/can_broadcast(var/mob/living/user)
if (user.client) if(user.client)
if(user.client.prefs.muted & MUTE_IC) if(user.client.prefs.muted & MUTE_IC)
to_chat(user, "<span class='warning'>You cannot speak in IC (muted).</span>") to_chat(user, "<span class='warning'>You cannot speak in IC (muted).</span>")
return 0 return FALSE
if(!(ishuman(user) || user.isSynthetic())) if(!(ishuman(user) || user.isSynthetic()))
to_chat(user, "<span class='warning'>You don't know how to use this!</span>") to_chat(user, "<span class='warning'>You don't know how to use this!</span>")
return 0 return FALSE
if(user.silent) if(user.silent)
return 0 return FALSE
if(spamcheck) if(spamcheck > world.time)
to_chat(user, "<span class='warning'>\The [src] needs to recharge!</span>") to_chat(user, "<span class='warning'>[src] needs to recharge!</span>")
return 0 return FALSE
return 1 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) /obj/item/device/megaphone/proc/do_broadcast(var/mob/living/user, var/message)
if ((src.loc == user && usr.stat == 0)) if(emagged)
if(emagged) if(insults)
if(insults) user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=3>\"[pick(insultmsg)]\"</FONT>")
user.audible_message("<B>[user]</B> broadcasts, <FONT size=3>\"[pick(insultmsg)]\"</FONT>") insults--
insults--
else
to_chat(user, "<span class='warning'>*BZZZZzzzzzt*</span>")
else else
user.audible_message("<B>[user]</B> broadcasts, <FONT size=3>\"[message]\"</FONT>") to_chat(user, "<span class='warning'>*BZZZZzzzzzt*</span>")
else
spamcheck = 1 user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=3>\"[message]\"</FONT>")
spawn(20)
spamcheck = 0
return
/obj/item/device/megaphone/attack_self(mob/living/user as mob)
if(!can_broadcast(user))
return
/obj/item/device/megaphone/attack_self(var/mob/living/user)
var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text) var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text)
if(!message) if(!message)
return return
message = capitalize(message) message = capitalize(message)
if(!can_broadcast(user))
return
spamcheck = world.time + 20
do_broadcast(user, message) do_broadcast(user, message)
/obj/item/device/megaphone/emag_act(var/remaining_charges, var/mob/user) /obj/item/device/megaphone/emag_act(var/remaining_charges, var/mob/user)
if(!emagged) if(!emagged)
to_chat(user, "<span class='warning'>You overload \the [src]'s voice synthesizer.</span>") to_chat(user, "<span class='warning'>You overload [src]'s voice synthesizer.</span>")
emagged = 1 emagged = TRUE
insults = rand(1, 3)//to prevent caps spam. insults = rand(1, 3)//to prevent caps spam.
return 1 return TRUE
/obj/item/device/megaphone/super /obj/item/device/megaphone/super
name = "gigaphone" name = "gigaphone"
@@ -130,41 +129,35 @@
broadcast_color = new_color broadcast_color = new_color
/obj/item/device/megaphone/super/do_broadcast(var/mob/living/user, var/message) /obj/item/device/megaphone/super/do_broadcast(var/mob/living/user, var/message)
if ((src.loc == user && usr.stat == 0)) if(emagged)
if(emagged) if(insults)
if(insults) user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[pick(insultmsg)]\"</FONT>")
user.audible_message("<B>[user]</B> broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[pick(insultmsg)]\"</FONT>") if(broadcast_size >= 11)
if(broadcast_size >= 11) var/turf/T = get_turf(user)
var/turf/T = get_turf(user) playsound(T, 'sound/items/AirHorn.ogg', 100, 1)
playsound(T, 'sound/items/AirHorn.ogg', 100, 1) for(var/mob/living/carbon/M in oviewers(4, T))
for(var/mob/living/carbon/M in oviewers(4, T)) if(M.get_ear_protection() >= 2)
if(M.get_ear_protection() >= 2) continue
continue M.sleeping = 0
M.sleeping = 0 M.stuttering += 20
M.stuttering += 20 M.ear_deaf += 30
M.ear_deaf += 30 M.Weaken(3)
M.Weaken(3) if(prob(30))
if(prob(30)) M.Stun(10)
M.Stun(10) M.Paralyse(4)
M.Paralyse(4) else
else M.make_jittery(50)
M.make_jittery(50) insults--
insults--
else
user.audible_message("<span class='critical'>*BZZZZzzzzzt*</span>")
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("<span class='warning'>\The [src] sparks violently!</span>")
spawn(30)
explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1)
qdel(src)
return
else else
user.audible_message("<B>[user]</B> broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[message]\"</FONT>") user.audible_message("<span class='critical'>*BZZZZzzzzzt*</span>")
if(prob(40) && insults <= 0)
spamcheck = 1 var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
spawn(20) s.set_up(2, 1, get_turf(user))
spamcheck = 0 s.start()
return user.visible_message("<span class='warning'>\The [src] sparks violently!</span>")
spawn(30)
explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1)
qdel(src)
return
else
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[message]\"</FONT>")

View File

@@ -43,15 +43,17 @@
to_chat(user, "The following channels are available:") to_chat(user, "The following channels are available:")
to_chat(user, radio_desc) to_chat(user, radio_desc)
/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, message, channel) /obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, list/message_pieces, channel)
if (channel == "special") if(channel == "special")
if (translate_binary) if(translate_binary)
var/datum/language/binary = GLOB.all_languages["Robot Talk"] var/datum/language/binary = GLOB.all_languages["Robot Talk"]
binary.broadcast(M, message) binary.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
if (translate_hive) return RADIO_CONNECTION_NON_SUBSPACE
if(translate_hive)
var/datum/language/hivemind = GLOB.all_languages["Hivemind"] var/datum/language/hivemind = GLOB.all_languages["Hivemind"]
hivemind.broadcast(M, message) hivemind.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
return null return RADIO_CONNECTION_NON_SUBSPACE
return RADIO_CONNECTION_FAIL
return ..() return ..()

View File

@@ -169,7 +169,7 @@ var/global/list/default_medbay_channels = list(
return can_admin_interact() return can_admin_interact()
/obj/item/device/radio/proc/text_wires() /obj/item/device/radio/proc/text_wires()
if (b_stat) if(b_stat)
return wires.GetInteractWindow() return wires.GetInteractWindow()
return return
@@ -197,31 +197,31 @@ var/global/list/default_medbay_channels = list(
return TRUE return TRUE
usr.set_machine(src) usr.set_machine(src)
if (href_list["track"]) if(href_list["track"])
var/mob/target = locate(href_list["track"]) var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"]) var/mob/living/silicon/ai/A = locate(href_list["track2"])
if(A && target) if(A && target)
A.ai_actual_track(target) A.ai_actual_track(target)
. = 1 . = 1
else if (href_list["freq"]) else if(href_list["freq"])
var/new_frequency = (frequency + text2num(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) new_frequency = sanitize_frequency(new_frequency)
set_frequency(new_frequency) set_frequency(new_frequency)
if(hidden_uplink) if(hidden_uplink)
if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
usr << browse(null, "window=radio") usr << browse(null, "window=radio")
. = 1 . = 1
else if (href_list["talk"]) else if(href_list["talk"])
ToggleBroadcast() ToggleBroadcast()
. = 1 . = 1
else if (href_list["listen"]) else if(href_list["listen"])
var/chan_name = href_list["ch_name"] var/chan_name = href_list["ch_name"]
if (!chan_name) if(!chan_name)
ToggleReception() ToggleReception()
else else
if (channels[chan_name] & FREQ_LISTENING) if(channels[chan_name] & FREQ_LISTENING)
channels[chan_name] &= ~FREQ_LISTENING channels[chan_name] &= ~FREQ_LISTENING
else else
channels[chan_name] |= FREQ_LISTENING channels[chan_name] |= FREQ_LISTENING
@@ -240,46 +240,46 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT /obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT
var/datum/radio_frequency/connection = null var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0) if(channel && channels && channels.len > 0)
if (channel == "department") if(channel == "department")
//to_world("DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"") //to_world("DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"")
channel = channels[1] channel = channels[1]
connection = secure_radio_connections[channel] connection = secure_radio_connections[channel]
else else
connection = radio_connection connection = radio_connection
channel = null channel = null
if (!istype(connection)) if(!istype(connection))
return return
var/static/mob/living/silicon/ai/announcer/A = new /mob/living/silicon/ai/announcer(src, null, null, 1) var/static/mob/living/silicon/ai/announcer/A = new /mob/living/silicon/ai/announcer(src, null, null, 1)
A.SetName(from) A.SetName(from)
Broadcast_Message(connection, A, Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src, 0, "*garbled automated announcement*", src,
message, from, "Automated Announcement", from, "synthesized voice", message_to_multilingual(message), from, "Automated Announcement", from, "synthesized voice",
4, 0, list(0), connection.frequency, "states") 4, 0, list(0), connection.frequency, "states")
// Interprets the message mode when talking into a radio, possibly returning a connection datum // 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 a channel isn't specified, send to common.
if(!message_mode || message_mode == "headset") if(!message_mode || message_mode == "headset")
return radio_connection return radio_connection
// Otherwise, if a channel is specified, look for it. // Otherwise, if a channel is specified, look for it.
if(channels && channels.len > 0) if(channels && channels.len > 0)
if (message_mode == "department") // Department radio shortcut if(message_mode == "department") // Department radio shortcut
message_mode = channels[1] 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] return secure_radio_connections[message_mode]
// If we were to send to a channel we don't have, drop it. // 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) /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 if(!on)
return FALSE // the device has to be on
// Fix for permacell radios, but kinda eh about actually fixing them. // Fix for permacell radios, but kinda eh about actually fixing them.
if(!M || !message) return FALSE if(!M || !message_pieces)
return FALSE
if(speaking && (speaking.flags & (SIGNLANG|NONVERBAL))) return FALSE
if(istype(M)) M.trigger_aiming(TARGET_CAN_RADIO) if(istype(M)) M.trigger_aiming(TARGET_CAN_RADIO)
@@ -303,10 +303,17 @@ var/global/list/default_medbay_channels = list(
*/ */
//#### Grab the connection datum ####// //#### Grab the connection datum ####//
var/datum/radio_frequency/connection = handle_message_mode(M, message, channel) var/message_mode = handle_message_mode(M, message_pieces, channel)
if (!istype(connection)) 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 return FALSE
var/datum/radio_frequency/connection = message_mode
var/turf/position = get_turf(src) var/turf/position = get_turf(src)
//#### Tagging the signal with all appropriate identity values ####// //#### Tagging the signal with all appropriate identity values ####//
@@ -323,24 +330,24 @@ var/global/list/default_medbay_channels = list(
var/jobname // the mob's "job" var/jobname // the mob's "job"
// --- Human: use their actual job --- // --- Human: use their actual job ---
if (ishuman(M)) if(ishuman(M))
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
jobname = H.get_assignment() jobname = H.get_assignment()
// --- Carbon Nonhuman --- // --- Carbon Nonhuman ---
else if (iscarbon(M)) // Nonhuman carbon mob else if(iscarbon(M)) // Nonhuman carbon mob
jobname = "No id" jobname = "No id"
// --- AI --- // --- AI ---
else if (isAI(M)) else if(isAI(M))
jobname = "AI" jobname = "AI"
// --- Cyborg --- // --- Cyborg ---
else if (isrobot(M)) else if(isrobot(M))
jobname = "Cyborg" jobname = "Cyborg"
// --- Personal AI (pAI) --- // --- Personal AI (pAI) ---
else if (istype(M, /mob/living/silicon/pai)) else if(istype(M, /mob/living/silicon/pai))
jobname = "Personal AI" jobname = "Personal AI"
// --- Unidentifiable mob --- // --- Unidentifiable mob ---
@@ -351,7 +358,7 @@ var/global/list/default_medbay_channels = list(
// --- Modifications to the mob's identity --- // --- Modifications to the mob's identity ---
// The mob is disguising their identity: // The mob is disguising their identity:
if (ishuman(M) && M.GetVoice() != real_name) if(ishuman(M) && M.GetVoice() != real_name)
displayname = M.GetVoice() displayname = M.GetVoice()
jobname = "Unknown" jobname = "Unknown"
voicemask = 1 voicemask = 1
@@ -390,7 +397,7 @@ var/global/list/default_medbay_channels = list(
// Other tags: // Other tags:
"compression" = rand(45,50), // compressed radio signal "compression" = rand(45,50), // compressed radio signal
"message" = message, // the actual sent message "message" = message_pieces, // the actual sent message
"connection" = connection, // the radio connection to use "connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission "radio" = src, // stores the radio used for transmission
"slow" = 0, // how much to sleep() before broadcasting - simulates net lag "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
@@ -399,7 +406,6 @@ var/global/list/default_medbay_channels = list(
"server" = null, // the last server to log this signal "server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = position.z, // The source's z level "level" = position.z, // The source's z level
"language" = speaking,
"verb" = verb "verb" = verb
) )
signal.frequency = connection.frequency // Quick frequency set signal.frequency = connection.frequency // Quick frequency set
@@ -421,8 +427,8 @@ var/global/list/default_medbay_channels = list(
to_chat(loc, "<span class='warning'>\The [src] pings as it falls back to local radio transmission.</span>") to_chat(loc, "<span class='warning'>\The [src] pings as it falls back to local radio transmission.</span>")
subspace_transmission = FALSE subspace_transmission = FALSE
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message, displayname, jobname, real_name, M.voice_name, src, message_pieces, displayname, jobname, real_name, M.voice_name,
signal.transmission_method, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb,speaking) signal.transmission_method, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb)
/* ###### Intercoms and station-bounced radios ###### */ /* ###### Intercoms and station-bounced radios ###### */
@@ -452,7 +458,7 @@ var/global/list/default_medbay_channels = list(
"vmask" = voicemask, // 1 if the mob is using a voice gas mas "vmask" = voicemask, // 1 if the mob is using a voice gas mas
"compression" = 0, // uncompressed radio signal "compression" = 0, // uncompressed radio signal
"message" = message, // the actual sent message "message" = message_pieces, // the actual sent message
"connection" = connection, // the radio connection to use "connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission "radio" = src, // stores the radio used for transmission
"slow" = 0, "slow" = 0,
@@ -461,7 +467,6 @@ var/global/list/default_medbay_channels = list(
"server" = null, "server" = null,
"reject" = 0, "reject" = 0,
"level" = position.z, "level" = position.z,
"language" = speaking,
"verb" = verb "verb" = verb
) )
signal.frequency = connection.frequency // Quick frequency set signal.frequency = connection.frequency // Quick frequency set
@@ -482,20 +487,20 @@ var/global/list/default_medbay_channels = list(
//THIS IS TEMPORARY. YEAH RIGHT //THIS IS TEMPORARY. YEAH RIGHT
if(!connection) return FALSE //~Carn if(!connection) return FALSE //~Carn
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message, displayname, jobname, real_name, M.voice_name, src, message_pieces, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb,speaking) filter_type, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency, verb)
/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null) /obj/item/device/radio/hear_talk(mob/M, list/message_pieces, verb)
if (broadcasting) if(broadcasting)
if(get_dist(src, M) <= canhear_range) if(get_dist(src, M) <= canhear_range)
talk_into(M, msg,null,verb,speaking) talk_into(M, message_pieces, null, verb)
/* /*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message) /obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
if ((R.frequency == frequency && message)) if((R.frequency == frequency && message))
return TRUE return TRUE
else if else if
@@ -510,7 +515,7 @@ var/global/list/default_medbay_channels = list(
// what the range is in which mobs will hear the radio // what the range is in which mobs will hear the radio
// returns: -1 if can't receive, range otherwise // returns: -1 if can't receive, range otherwise
if (wires.IsIndexCut(WIRE_RECEIVE)) if(wires.IsIndexCut(WIRE_RECEIVE))
return -1 return -1
if(!listening) if(!listening)
return -1 return -1
@@ -526,20 +531,20 @@ var/global/list/default_medbay_channels = list(
if(freq in CENT_FREQS) if(freq in CENT_FREQS)
if(!(src.centComm))//Checks to see if it's allowed on that frequency, based on the encryption keys if(!(src.centComm))//Checks to see if it's allowed on that frequency, based on the encryption keys
return -1 return -1
if (!on) if(!on)
return -1 return -1
if (!freq) //recieved on main frequency if(!freq) //recieved on main frequency
if (!listening) if(!listening)
return -1 return -1
else else
var/accept = (freq==frequency && listening) var/accept = (freq==frequency && listening)
if (!accept) if(!accept)
for (var/ch_name in channels) for (var/ch_name in channels)
var/datum/radio_frequency/RF = secure_radio_connections[ch_name] 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 accept = 1
break break
if (!accept) if(!accept)
return -1 return -1
return canhear_range return canhear_range
@@ -552,8 +557,8 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/examine(mob/user) /obj/item/device/radio/examine(mob/user)
. = ..() . = ..()
if ((in_range(src, user) || loc == user)) if((in_range(src, user) || loc == user))
if (b_stat) if(b_stat)
user.show_message("<span class='notice'>\The [src] can be attached and modified!</span>") user.show_message("<span class='notice'>\The [src] can be attached and modified!</span>")
else else
user.show_message("<span class='notice'>\The [src] can not be modified or attached!</span>") user.show_message("<span class='notice'>\The [src] can not be modified or attached!</span>")
@@ -562,11 +567,11 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob) /obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob)
..() ..()
user.set_machine(src) user.set_machine(src)
if (!W.is_screwdriver()) if(!W.is_screwdriver())
return return
b_stat = !( b_stat ) b_stat = !( b_stat )
if(!istype(src, /obj/item/device/radio/beacon)) if(!istype(src, /obj/item/device/radio/beacon))
if (b_stat) if(b_stat)
user.show_message("<span class='notice'>\The [src] can now be attached and modified!</span>") user.show_message("<span class='notice'>\The [src] can now be attached and modified!</span>")
else else
user.show_message("<span class='notice'>\The [src] can no longer be modified or attached!</span>") user.show_message("<span class='notice'>\The [src] can no longer be modified or attached!</span>")
@@ -606,7 +611,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/borg/talk_into() /obj/item/device/radio/borg/talk_into()
. = ..() . = ..()
if (isrobot(src.loc)) if(isrobot(src.loc))
var/mob/living/silicon/robot/R = src.loc var/mob/living/silicon/robot/R = src.loc
var/datum/robot_component/C = R.components["radio"] var/datum/robot_component/C = R.components["radio"]
R.cell_use_power(C.active_usage) R.cell_use_power(C.active_usage)
@@ -614,7 +619,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob) /obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..() // ..()
user.set_machine(src) 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 return
if(W.is_screwdriver()) if(W.is_screwdriver())
@@ -688,7 +693,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/borg/Topic(href, href_list) /obj/item/device/radio/borg/Topic(href, href_list)
if(..()) if(..())
return TRUE return TRUE
if (href_list["mode"]) if(href_list["mode"])
var/enable_subspace_transmission = text2num(href_list["mode"]) var/enable_subspace_transmission = text2num(href_list["mode"])
if(enable_subspace_transmission != subspace_transmission) if(enable_subspace_transmission != subspace_transmission)
subspace_transmission = !subspace_transmission subspace_transmission = !subspace_transmission
@@ -702,7 +707,7 @@ var/global/list/default_medbay_channels = list(
else else
recalculateChannels() recalculateChannels()
. = 1 . = 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"]) var/do_shut_up = text2num(href_list["shutup"])
if(do_shut_up != shut_up) if(do_shut_up != shut_up)
shut_up = !shut_up shut_up = !shut_up

View File

@@ -126,10 +126,7 @@
linkedmonitor.unpair(src) linkedmonitor.unpair(src)
linkedmonitor = null 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 /obj/item/device/bug_monitor
name = "mobile camera pod monitor" name = "mobile camera pod monitor"
desc = "A portable camera console designed to work with mobile camera pods." desc = "A portable camera console designed to work with mobile camera pods."
@@ -208,10 +205,7 @@
return return
return 1 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 /obj/item/device/bug_monitor/spy
name = "\improper PDA" name = "\improper PDA"
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge." desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."

View File

@@ -86,15 +86,10 @@
update_icon() 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(mytape && recording)
mytape.record_speech("[M.name] [verb], \"[msg]\"")
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]\"")
/obj/item/device/taperecorder/see_emote(mob/M as mob, text, var/emote_type) /obj/item/device/taperecorder/see_emote(mob/M as mob, text, var/emote_type)

View File

@@ -33,8 +33,8 @@
icon_state = "[initial(icon_state)]" icon_state = "[initial(icon_state)]"
to_chat(user, "<span class='notice'>You disable \the [src].</span>") to_chat(user, "<span class='notice'>You disable \the [src].</span>")
/obj/item/device/universal_translator/hear_talk(var/mob/speaker, var/message, var/vrb, var/datum/language/language) /obj/item/device/universal_translator/hear_talk(mob/M, list/message_pieces, verb)
if(!listening || !istype(speaker)) if(!listening || !istype(M))
return return
//Show the "I heard something" animation. //Show the "I heard something" animation.
@@ -46,34 +46,38 @@
return return
var/mob/living/L = loc 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) // Using two for loops kinda sucks, but I think it's more efficient
return //Borgs were causing runtimes when passing language=null // 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)) var/new_message = ""
return //Not gonna translate sign language
if (!language.machine_understands) for(var/datum/multilingual_say_piece/S in message_pieces)
return //Any other languages that it can't translate. 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)) new_message += (S.message + " ")
return //Can't see the screen, don't get the message
if (audio && ((L.sdisabilities & DEAF) || L.ear_deaf)) if(!L.say_understands(null, langset))
return //Can't hear the translation, don't get the message new_message = langset.scramble(new_message)
//Only translate if they can't understand, otherwise pointlessly spammy to_chat(L, "<span class='filter_say'><i><b>[src]</b> translates, </i>\"<span class='[langset.colour]'>[new_message]</span>\"</span>")
//I'll just assume they don't look at the screen in that case
//They don't understand the spoken language we're translating FROM /obj/item/device/universal_translator/proc/user_understands(mob/M, mob/living/L, list/message_pieces)
if(!L.say_understands(speaker,language)) for(var/datum/multilingual_say_piece/S in message_pieces)
//They understand the output language if(S.speaking && !L.say_understands(M, S.speaking))
if(L.say_understands(null,langset)) return FALSE
to_chat(L, "<i><b>[src]</b> translates, </i>\"<span class='[langset.colour]'>[message]</span>\"") return TRUE
//They don't understand the output language
else
to_chat(L, "<i><b>[src]</b> translates, </i>\"<span class='[langset.colour]'>[langset.scramble(message)]</span>\"")
//Let's try an ear-worn version //Let's try an ear-worn version
/obj/item/device/universal_translator/ear /obj/item/device/universal_translator/ear

View File

@@ -38,9 +38,9 @@
radio.icon_state = src.icon_state radio.icon_state = src.icon_state
update_icon() update_icon()
/obj/item/device/tvcamera/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null) /obj/item/device/tvcamera/hear_talk(mob/M, list/message_pieces, verb)
radio.hear_talk(M,msg,verb,speaking) radio.hear_talk(M, message_pieces, verb)
..() . = ..()
/obj/item/device/tvcamera/attack_self(mob/user) /obj/item/device/tvcamera/attack_self(mob/user)
add_fingerprint(user) add_fingerprint(user)

View File

@@ -227,7 +227,8 @@ Implant Specifics:<BR>"}
<b>Integrity:</b> Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} <b>Integrity:</b> Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."}
return dat 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) hear(msg)
return return

View File

@@ -162,9 +162,9 @@
/obj/proc/hides_under_flooring() /obj/proc/hides_under_flooring()
return 0 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) if(talking_atom)
talking_atom.catchMessage(text, M) talking_atom.catchMessage(multilingual_to_message(message_pieces), M)
/* /*
var/mob/mo = locate(/mob) in src var/mob/mo = locate(/mob) in src
if(mo) if(mo)

View File

@@ -155,11 +155,11 @@
master.receive_signal() master.receive_signal()
return 1 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) if(a_right)
a_right.hear_talk(M,msg,verb,speaking) a_right.hear_talk(M, message_pieces, verb)
if(a_left) 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 /obj/item/device/assembly_holder/timer_igniter
name = "timer-igniter assembly" name = "timer-igniter assembly"

View File

@@ -7,7 +7,8 @@
var/listening = 0 var/listening = 0
var/recorded //the activation message 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) if(listening)
recorded = msg recorded = msg
listening = 0 listening = 0

View File

@@ -527,13 +527,15 @@
listening_objects -= src listening_objects -= src
return ..() 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 var/translated = FALSE
if(M && msg) if(M && msg)
if(speaking) for(var/datum/multilingual_say_piece/S in message_pieces)
if(!speaking.machine_understands) // S.speaking && here is not redundant, it's preventing `S.speaking = null` from flagging
msg = speaking.scramble(msg) // as a translation, when it is not.
if(!istype(speaking, /datum/language/common)) if(S.speaking && !istype(S.speaking, /datum/language/common))
translated = TRUE translated = TRUE
set_pin_data(IC_OUTPUT, 1, M.GetVoice()) set_pin_data(IC_OUTPUT, 1, M.GetVoice())
set_pin_data(IC_OUTPUT, 2, msg) set_pin_data(IC_OUTPUT, 2, msg)
@@ -577,25 +579,41 @@
var/datum/language/newlang = GLOB.all_languages[lang] var/datum/language/newlang = GLOB.all_languages[lang]
my_langs |= newlang 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 var/translated = FALSE
if(M && msg) if(M && msg)
if(speaking) for(var/datum/multilingual_say_piece/S in message_pieces)
if(!((speaking.flags & NONVERBAL) || (speaking.flags & SIGNLANG))) if(S.speaking)
translated = TRUE if(!((S.speaking.flags & NONVERBAL) || (S.speaking.flags & SIGNLANG)))
msg = speaking.scramble(msg, my_langs) translated = TRUE
msg = stars(msg)
break
set_pin_data(IC_OUTPUT, 1, M.GetVoice()) set_pin_data(IC_OUTPUT, 1, M.GetVoice())
set_pin_data(IC_OUTPUT, 2, msg) set_pin_data(IC_OUTPUT, 2, msg)
push_data() push_data()
if(!translated) if(!translated)
activate_pin(1) activate_pin(1)
if(translated) else
activate_pin(2) activate_pin(2)
/obj/item/integrated_circuit/input/microphone/sign/hear_signlang(text, verb, datum/language/speaking, mob/M as mob) /obj/item/integrated_circuit/input/microphone/sign/hear_signlang(text, verb, datum/language/speaking, mob/M as mob)
hear_talk(M, text, verb, speaking) var/translated = FALSE
return 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 /obj/item/integrated_circuit/input/sensor
name = "sensor" name = "sensor"

View File

@@ -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) 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, "<font color='red'>You cannot talk in deadchat (muted).</font>")
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) if(!message)
return 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, "<font color='red'>You cannot talk in deadchat (muted).</font>")
return
. = say_dead(message)
/mob/observer/dead/me_verb(message as text)
if(!message)
return return
log_ghostemote(message, src) log_ghostemote(message, src)
if(src.client) if(client)
if(message) if(message)
client.handle_spam_prevention(MUTE_DEADCHAT) client.handle_spam_prevention(MUTE_DEADCHAT)
if(src.client.prefs.muted & MUTE_DEADCHAT) if(client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<font color='red'>You cannot emote in deadchat (muted).</font>") to_chat(src, "<font color='red'>You cannot emote in deadchat (muted).</font>")
return return
. = src.emote_dead(message) . = emote_dead(message)
/* /mob/observer/dead/handle_track(message, verb = "says", mob/speaker = null, speaker_name, hard_to_hear)
for (var/mob/M in hearers(null, null)) return "[speaker_name] ([ghost_follow_link(speaker, src)])"
if (!M.stat)
if(M.job == "Chaplain") /mob/observer/dead/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
if (prob (49)) var/speaker_name = ..()
M.show_message("<span class='game'><i>You hear muffled speech... but nothing is there...</i></span>", 2) //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(prob(20)) if(speaker && (speaker_name != speaker.real_name) && !isAI(speaker))
playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) speaker_name = "[speaker.real_name] ([speaker_name])"
else return speaker_name
M.show_message("<span class='game'><i>You hear muffled speech... you can almost make out some words...</i></span>", 2)
// M.show_message("<span class='game'><i>[stutter(message)]</i></span>", 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("<span class='game'><i>You hear muffled speech... but nothing is there...</i></span>", 2)
if(prob(20))
playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1)
else
M.show_message("<span class='game'><i>You hear muffled speech... you can almost make out some words...</i></span>", 2)
// M.show_message("<span class='game'><i>[stutter(message)]</i></span>", 2)
playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1)
*/

View File

@@ -1,54 +1,96 @@
// At minimum every mob has a hear_say proc. // 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 = "<span class='message body'>[piece]</span>"
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) 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') //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. //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 //make sure the air can transmit speech - hearer's side
var/turf/T = get_turf(src) 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/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) 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 italics = 1
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact 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 var/speaker_name = speaker.name
if(istype(speaker, /mob/living/carbon/human)) if(ishuman(speaker))
var/mob/living/carbon/human/H = speaker var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice() 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) if(italics)
message = "<i>[message]</i>" message = "<i>[message]</i>"
message = encode_html_emphasis(message) message = encode_html_emphasis(message)
var/track = null var/track = null
if(istype(src, /mob/observer/dead)) if(isobserver(src))
if(italics && is_preference_enabled(/datum/client_preference/ghost_radio)) if(italics && is_preference_enabled(/datum/client_preference/ghost_radio))
return return
if(speaker_name != speaker.real_name && speaker.real_name) if(speaker_name != speaker.real_name && speaker.real_name)
@@ -58,31 +100,27 @@
message = "<b>[message]</b>" message = "<b>[message]</b>"
if(is_deaf()) 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)
if(speaker == src) to_chat(src, "<span class='filter_say'><span class='warning'>You cannot hear yourself speak!</span></span>")
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>") else
else to_chat(src, "<span class='filter_say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] makes a noise, possibly speech, but you cannot hear them.</span>")
to_chat(src, "<span class='name'>[speaker_name]</span>[alt_name] talks but you cannot hear.")
else else
var/message_to_send = null var/message_to_send = null
if(language) message_to_send = "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][message]</span>"
message_to_send = "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][language.format_message(message, verb)]</span>" if(check_mentioned(multilingual_to_message(message_pieces)) && is_preference_enabled(/datum/client_preference/check_mention))
else
message_to_send = "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][verb], <span class='message'><span class='body'>\"[message]\"</span></span></span>"
if(check_mentioned(message) && is_preference_enabled(/datum/client_preference/check_mention))
message_to_send = "<font size='3'><b>[message_to_send]</b></font>" message_to_send = "<font size='3'><b>[message_to_send]</b></font>"
on_hear_say(message_to_send) on_hear_say(message_to_send)
if (speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z)) if(speech_sound && (get_dist(speaker, src) <= world.view && z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src) var/turf/source = speaker ? get_turf(speaker) : get_turf(src)
src.playsound_local(source, speech_sound, sound_vol, 1) 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). // 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. 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) /mob/proc/on_hear_say(var/message)
to_chat(src, message) to_chat(src, message)
@@ -124,114 +162,25 @@
return tagged_message 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) if(!client)
return 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) hear_sleep(message)
return return
var/track = null var/speaker_name = handle_speaker_name(speaker, vname, hard_to_hear)
var/track = handle_track(message, verb, speaker, speaker_name, hard_to_hear)
//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 = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[impersonating]'>[speaker_name] ([jobname])</a>"
else
track = "[speaker_name] ([jobname])"
else
track = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[speaker]'>[speaker_name] ([jobname])</a>"
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)])"
message = encode_html_emphasis(message) message = encode_html_emphasis(message)
var/formatted
if(language)
formatted = "[language.format_message_radio(message, verb)][part_c]"
else
formatted = "[verb], <span class=\"body\">\"[message]\"</span>[part_c]"
if((sdisabilities & DEAF) || ear_deaf) if((sdisabilities & DEAF) || ear_deaf)
if(prob(20)) if(prob(20))
to_chat(src, "<span class='warning'>You feel your headset vibrate but can hear nothing from it!</span>") to_chat(src, "<span class='warning'>You feel your headset vibrate but can hear nothing from it!</span>")
else 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() /proc/say_timestamp()
return "<span class='say_quote'>\[[stationtime2text()]\]</span>" return "<span class='say_quote'>\[[stationtime2text()]\]</span>"
@@ -296,9 +245,40 @@
heardword = copytext(heardword,2) heardword = copytext(heardword,2)
if(copytext(heardword,-1) in punctuation) if(copytext(heardword,-1) in punctuation)
heardword = copytext(heardword,1,length(heardword)) heardword = copytext(heardword,1,length(heardword))
heard = "<span class = 'game_say'>...You hear something about...[heardword]</span>" heard = "<span class='game say'>...You hear something about...[heardword]</span>"
else else
heard = "<span class = 'game_say'>...<i>You almost hear someone talking</i>...</span>" heard = "<span class='game say'>...<i>You almost hear someone talking</i>...</span>"
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 = "<span class='game say'><span class='name'>[name]</span> [message]</span>"
to_chat(src, rendered)

View File

@@ -5,12 +5,6 @@
key = "" key = ""
flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER
/datum/language/noise/format_message(message, verb)
return "<span class='message'><span class='[colour]'>[message]</span></span>"
/datum/language/noise/format_message_plain(message, verb)
return message
/datum/language/noise/format_message_radio(message, verb) /datum/language/noise/format_message_radio(message, verb)
return "<span class='[colour]'>[message]</span>" return "<span class='[colour]'>[message]</span>"
@@ -143,6 +137,17 @@
var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands
return (hands || !iscarbon(speaker)) 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 // Silly language for those times when you try to talk a languague you normally can't
/datum/language/gibberish /datum/language/gibberish
name = LANGUAGE_GIBBERISH name = LANGUAGE_GIBBERISH

View File

@@ -113,13 +113,13 @@
return scrambled_text return scrambled_text
/datum/language/proc/format_message(message, verb) /datum/language/proc/format_message(message, verb)
return "[verb], <span class='message'><span class='[colour]'>\"[capitalize(message)]\"</span></span>" return "<span class='message'><span class='[colour]'>[message]</span></span>"
/datum/language/proc/format_message_plain(message, verb) /datum/language/proc/format_message_plain(message, verb)
return "[verb], \"[capitalize(message)]\"" return "[capitalize(message)]"
/datum/language/proc/format_message_radio(message, verb) /datum/language/proc/format_message_radio(message, verb)
return "[verb], <span class='[colour]'>\"[capitalize(message)]\"</span>" return "<span class='[colour]'>[capitalize(message)]</span>"
/datum/language/proc/get_talkinto_msg_range(message) /datum/language/proc/get_talkinto_msg_range(message)
// if you yell, you'll be heard from two tiles over instead of one // if you yell, you'll be heard from two tiles over instead of one
@@ -129,7 +129,7 @@
log_say("(HIVE) [message]", speaker) log_say("(HIVE) [message]", speaker)
if(!speaker_mask) speaker_mask = speaker.name 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) for(var/mob/player in player_list)
player.hear_broadcast(src, speaker, speaker_mask, message) player.hear_broadcast(src, speaker, speaker_mask, message)
@@ -233,36 +233,36 @@
return prefix in config.language_prefixes return prefix in config.language_prefixes
//TBD //TBD
/mob/proc/check_lang_data()
. = ""
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
. += "<b>[L.name] ([get_language_prefix()][L.key])</b><br/>[L.desc]<br/><br/>"
/mob/living/check_lang_data()
. = ""
if(default_language)
. += "Current default language: [default_language] - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/><br/>"
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
if(L == default_language)
. += "<b>[L.name] ([get_language_prefix()][L.key])</b> - default - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/>[L.desc]<br/><br/>"
else if (can_speak(L))
. += "<b>[L.name] ([get_language_prefix()][L.key])</b> - <a href='byond://?src=\ref[src];default_lang=\ref[L]'>set default</a><br/>[L.desc]<br/><br/>"
else
. += "<b>[L.name] ([get_language_prefix()][L.key])</b> - cannot speak!<br/>[L.desc]<br/><br/>"
/mob/verb/check_languages() /mob/verb/check_languages()
set name = "Check Known Languages" set name = "Check Known Languages"
set category = "IC" set category = "IC"
set src = usr set src = usr
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>" var/datum/browser/popup = new(src, "checklanguage", "Known Languages", 420, 470)
popup.set_content(check_lang_data())
for(var/datum/language/L in languages) popup.open()
if(!(L.flags & NONGLOBAL))
dat += "<b>[L.name] ([get_language_prefix()][L.key])</b><br/>[L.desc]<br/><br/>"
src << browse(dat, "window=checklanguage")
return
/mob/living/check_languages()
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
if(default_language)
dat += "Current default language: [default_language] - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/><br/>"
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
if(L == default_language)
dat += "<b>[L.name] ([get_language_prefix()][L.key])</b> - default - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/>[L.desc]<br/><br/>"
else if (can_speak(L))
dat += "<b>[L.name] ([get_language_prefix()][L.key])</b> - <a href='byond://?src=\ref[src];default_lang=\ref[L]'>set default</a><br/>[L.desc]<br/><br/>"
else
dat += "<b>[L.name] ([get_language_prefix()][L.key])</b> - cannot speak!<br/>[L.desc]<br/><br/>"
src << browse(dat, "window=checklanguage")
/mob/living/Topic(href, href_list) /mob/living/Topic(href, href_list)
if(href_list["default_lang"]) if(href_list["default_lang"])

View File

@@ -94,6 +94,10 @@
key = "l" key = "l"
flags = WHITELISTED | SIGNLANG | NO_STUTTER | NONVERBAL 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 /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. var/list/allowed_species = list(SPECIES_TAJ, SPECIES_TESHARI) // Need a tail and ears and such to use this.
if(iscarbon(speaker)) if(iscarbon(speaker))

View File

@@ -6,7 +6,7 @@
#define AUTOHISS_NUM 3 #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 return message // no autohiss at this level
/mob/living/carbon/human/handle_autohiss(message, datum/language/L) /mob/living/carbon/human/handle_autohiss(message, datum/language/L)

View File

@@ -144,12 +144,8 @@
/mob/living/bot/attack_ai(var/mob/user) /mob/living/bot/attack_ai(var/mob/user)
return attack_hand(user) return attack_hand(user)
/mob/living/bot/say(var/message) /mob/living/bot/say_quote(var/message, var/datum/language/speaking = null)
var/verb = "beeps" return "beeps"
message = sanitize(message)
..(message, null, verb)
/mob/living/bot/speech_bubble_appearance() /mob/living/bot/speech_bubble_appearance()
return "machine" return "machine"

View File

@@ -1,5 +1,4 @@
/mob/living/carbon/alien /mob/living/carbon/alien
name = "alien" name = "alien"
desc = "What IS that?" desc = "What IS that?"
icon = 'icons/mob/alien.dmi' icon = 'icons/mob/alien.dmi'
@@ -53,3 +52,22 @@
/mob/living/carbon/alien/cannot_use_vents() /mob/living/carbon/alien/cannot_use_vents()
return 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

View File

@@ -1,6 +1,5 @@
/mob/living/carbon/alien/diona/say_understands(var/mob/other,var/datum/language/speaking = null) /mob/living/carbon/alien/diona/say_understands(var/mob/other, var/datum/language/speaking = null)
if(ishuman(other) && !speaking)
if (istype(other, /mob/living/carbon/human) && !speaking)
if(languages.len >= 2) // They have sucked down some blood. if(languages.len >= 2) // They have sucked down some blood.
return 1 return TRUE
return ..() return ..()

View File

@@ -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 var/param = null
if (findtext(act, "-", 1, null)) if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null) var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1) param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1) 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/muzzled = is_muzzled()
switch(act) switch(act)
if ("me")
if(silent)
return
if (src.client)
if (client.prefs.muted & MUTE_IC)
to_chat(src, "<font color='red'>You cannot send IC messages (muted).</font>")
return
if (stat)
return
if(!(message))
return
return custom_emote(m_type, message)
if ("custom")
return custom_emote(m_type, message)
if("sign") if("sign")
if (!src.restrained()) if(!restrained())
message = text("<B>The alien</B> signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) var/num = null
m_type = 1 if(text2num(param))
if ("burp") num = "the number [text2num(param)]"
if (!muzzled) if(num)
message = "<B>[src]</B> signs [num]."
m_type = 1
if("burp")
if(!muzzled)
message = "<B>[src]</B> burps." message = "<B>[src]</B> burps."
m_type = 2 m_type = 2
if("deathgasp") if("deathgasp")
message = "<B>The [src.name]</B> lets out a waning guttural screech, green blood bubbling from its maw." message = "<B>[src]</B> lets out a waning guttural screech, green blood bubbling from its maw."
m_type = 2 m_type = 2
if("scratch") if("scratch")
if (!src.restrained()) if(!restrained())
message = "<B>The [src.name]</B> scratches." message = "<B>[src]</B> scratches."
m_type = 1 m_type = 1
if("whimper") if("whimper")
if (!muzzled) if(!muzzled)
message = "<B>The [src.name]</B> whimpers." message = "<B>[src]</B> whimpers."
m_type = 2 m_type = 2
if("tail") if("tail")
message = "<B>The [src.name]</B> waves its tail." message = "<B>[src]</B> waves its tail."
m_type = 1 m_type = 1
if("gasp") if("gasp")
message = "<B>The [src.name]</B> gasps." message = "<B>[src]</B> gasps."
m_type = 2 m_type = 2
if("shiver") if("shiver")
message = "<B>The [src.name]</B> shivers." message = "<B>[src]</B> shivers."
m_type = 2 m_type = 2
if("drool") if("drool")
message = "<B>The [src.name]</B> drools." message = "<B>[src]</B> drools."
m_type = 1 m_type = 1
if("scretch") if("scretch")
if (!muzzled) if(!muzzled)
message = "<B>The [src.name]</B> scretches." message = "<B>[src]</B> scretches."
m_type = 2 m_type = 2
if("choke") if("choke")
message = "<B>The [src.name]</B> chokes." message = "<B>[src]</B> chokes."
m_type = 2 m_type = 2
if("moan") if("moan")
message = "<B>The [src.name]</B> moans!" message = "<B>[src]</B> moans!"
m_type = 2 m_type = 2
if("nod") if("nod")
message = "<B>The [src.name]</B> nods its head." message = "<B>[src]</B> nods its head."
m_type = 1 m_type = 1
// if("sit") // if("sit")
// message = "<B>The [src.name]</B> sits down." //Larvan can't sit down, /N // message = "<B>[src]</B> sits down." //Larvan can't sit down, /N
// m_type = 1 // m_type = 1
if("sway") if("sway")
message = "<B>The [src.name]</B> sways around dizzily." message = "<B>[src]</B> sways around dizzily."
m_type = 1 m_type = 1
if("sulk") if("sulk")
message = "<B>The [src.name]</B> sulks down sadly." message = "<B>[src]</B> sulks down sadly."
m_type = 1 m_type = 1
if("twitch") if("twitch")
message = "<B>The [src.name]</B> twitches." message = "<B>[src]</B> twitches."
m_type = 1 m_type = 1
if("twitch_v") if("twitch_v")
message = "<B>The [src.name]</B> twitches violently." message = "<B>[src]</B> twitches violently."
m_type = 1 m_type = 1
if("dance") if("dance")
if (!src.restrained()) if(!restrained())
message = "<B>The [src.name]</B> dances around happily." message = "<B>[src]</B> dances around happily."
m_type = 1 m_type = 1
if("roll") if("roll")
if (!src.restrained()) if(!restrained())
message = "<B>The [src.name]</B> rolls." message = "<B>[src]</B> rolls."
m_type = 1 m_type = 1
if("shake") if("shake")
message = "<B>The [src.name]</B> shakes its head." message = "<B>[src]</B> shakes its head."
m_type = 1 m_type = 1
if("gnarl") if("gnarl")
if (!muzzled) if(!muzzled)
message = "<B>The [src.name]</B> gnarls and shows its teeth.." message = "<B>[src]</B> gnarls and shows its teeth.."
m_type = 2 m_type = 2
if("jump") if("jump")
message = "<B>The [src.name]</B> jumps!" message = "<B>[src]</B> jumps!"
m_type = 1 m_type = 1
if("hiss_") if("hiss_")
message = "<B>The [src.name]</B> hisses softly." message = "<B>[src]</B> hisses softly."
m_type = 1 m_type = 1
if("collapse") if("collapse")
Paralyse(2) Paralyse(2)
message = text("<B>[]</B> collapses!", src) message = "<B>[src]</B> collapses!"
m_type = 2 m_type = 2
if("chirp") if("chirp")
message = "<B>The [src.name]</B> chirps!" message = "<B>[src]</B> chirps!"
playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) playsound(loc, 'sound/misc/nymphchirp.ogg', 50, 0)
m_type = 2 m_type = 2
if("help") 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") to_chat(src, "<span class='filter_say'>burp, chirp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper</span>")
else
to_chat(src, "Invalid Emote: [act]") if(!stat)
if ((message && src.stat == 0)) ..(act, m_type, message)
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

View File

@@ -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, "<font color='red'>You cannot speak in IC (Muted).</font>")
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)

View File

@@ -17,36 +17,19 @@
/mob/living/carbon/brain/Destroy() /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(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 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. ghostize() //Ghostize checks for key so nothing else is necessary.
return ..() return ..()
/mob/living/carbon/brain/say_understands(var/other)//Goddamn is this hackish, but this say code is so odd /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(istype(container, /obj/item/device/mmi))
if(!(container && istype(container, /obj/item/device/mmi))) if(issilicon(other))
return 0 return TRUE
else if(ishuman(other))
return 1 return TRUE
if (istype(other, /mob/living/silicon/decoy)) if(isslime(other))
if(!(container && istype(container, /obj/item/device/mmi))) return TRUE
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
return ..() return ..()
/mob/living/carbon/brain/update_canmove() /mob/living/carbon/brain/update_canmove()

View File

@@ -2,79 +2,46 @@
if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes
return return
if (findtext(act, "-", 1, null)) if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null) var/t1 = findtext(act, "-", 1, null)
act = copytext(act, 1, t1) act = copytext(act, 1, t1)
if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' if(stat == DEAD)
act = copytext(act,1,length(act))
if(src.stat == DEAD)
return return
switch(act) switch(act)
if ("me") if("alarm")
if(silent)
return
if (src.client)
if (client.prefs.muted & MUTE_IC)
to_chat(src, "<font color='red'>You cannot send IC messages (muted).</font>")
return
if (stat)
return
if(!(message))
return
return custom_emote(m_type, message)
if ("custom")
return custom_emote(m_type, message)
if ("alarm")
to_chat(src, "You sound an alarm.") to_chat(src, "You sound an alarm.")
message = "<B>[src]</B> sounds an alarm." message = "<B>[src]</B> sounds an alarm."
m_type = 2 m_type = 2
if ("alert") if("alert")
to_chat(src, "You let out a distressed noise.") to_chat(src, "You let out a distressed noise.")
message = "<B>[src]</B> lets out a distressed noise." message = "<B>[src]</B> lets out a distressed noise."
m_type = 2 m_type = 2
if ("notice") if("notice")
to_chat(src, "You play a loud tone.") to_chat(src, "You play a loud tone.")
message = "<B>[src]</B> plays a loud tone." message = "<B>[src]</B> plays a loud tone."
m_type = 2 m_type = 2
if ("flash") if("flash")
message = "The lights on <B>[src]</B> flash quickly." message = "The lights on <B>[src]</B> flash quickly."
m_type = 1 m_type = 1
if ("blink") if("blink")
message = "<B>[src]</B> blinks." message = "<B>[src]</B> blinks."
m_type = 1 m_type = 1
if ("whistle") if("whistle")
to_chat(src, "You whistle.") to_chat(src, "You whistle.")
message = "<B>[src]</B> whistles." message = "<B>[src]</B> whistles."
m_type = 2 m_type = 2
if ("beep") if("beep")
to_chat(src, "You beep.") to_chat(src, "You beep.")
message = "<B>[src]</B> beeps." message = "<B>[src]</B> beeps."
m_type = 2 m_type = 2
if ("boop") if("boop")
to_chat(src, "You boop.") to_chat(src, "You boop.")
message = "<B>[src]</B> boops." message = "<B>[src]</B> boops."
m_type = 2 m_type = 2
if ("help") if("help")
to_chat(src, "alarm,alert,notice,flash,blink,whistle,beep,boop") to_chat(src, "<span class='filter_say'>alarm, alert, notice, flash, blink, whistle, beep, boop</span>")
else
to_chat(src, "<font color='blue'>Unusable emote '[act]'. Say *help for a list.</font>")
if (message) if(!stat)
log_emote(message, src) ..(act, m_type, message)
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)

View File

@@ -1,6 +1,6 @@
//TODO: Convert this over for languages. //TODO: Convert this over for languages.
/mob/living/carbon/brain/say(var/message) /mob/living/carbon/brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
if (silent) if(silent)
return return
message = sanitize(message) message = sanitize(message)
@@ -8,39 +8,22 @@
if(!(container && container.can_speak)) if(!(container && container.can_speak))
return //Certain objects can speak, like MMIs. Most others cannot. -Q return //Certain objects can speak, like MMIs. Most others cannot. -Q
else else
var/datum/language/speaking = parse_language(message) if(prob(emp_damage * 4))
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(10))//10% chance to drop the message entirely if(prob(10))//10% chance to drop the message entirely
return return
else else
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher 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)
/mob/living/carbon/brain/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..() ..()
if(message_mode) if(message_mode)
var/obj/item/device/mmi/R = container 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") if(message_mode == "general")
message_mode = null 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 else
to_chat(src, "<span class='danger'>Your radio is disabled.</span>") to_chat(src, "<span class='danger'>Your radio is disabled.</span>")
return 0 return 0

View File

@@ -3,28 +3,25 @@
var/datum/gender/T = gender_datums[get_visible_gender()] 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) var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1) param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1) 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/muzzled = is_muzzled()
//var/m_type = 1 //var/m_type = 1
for(var/obj/item/organ/O in src.organs) for(var/obj/item/organ/O in src.organs)
for (var/obj/item/weapon/implant/I in O) for (var/obj/item/weapon/implant/I in O)
if (I.implanted) if(I.implanted)
I.trigger(act, src) I.trigger(act, src)
if(src.stat == 2.0 && (act != "deathgasp")) if(stat == DEAD && (act != "deathgasp"))
return return
switch(act) switch(act)
if ("airguitar") if("airguitar")
if (!src.restrained()) if(!src.restrained())
message = "is strumming the air and headbanging like a safari chimp." message = "is strumming the air and headbanging like a safari chimp."
m_type = 1 m_type = 1
@@ -38,7 +35,7 @@
var/M = null var/M = null
if(param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if(!M) if(!M)
@@ -74,7 +71,7 @@
else else
use_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg' use_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg'
if (param) if(param)
message = "[display_msg] at [param]." message = "[display_msg] at [param]."
else else
message = "[display_msg]." message = "[display_msg]."
@@ -101,142 +98,142 @@
message = "warbles." message = "warbles."
m_type = 2 m_type = 2
if ("blink") if("blink")
message = "blinks." message = "blinks."
m_type = 1 m_type = 1
if ("blink_r") if("blink_r")
message = "blinks rapidly." message = "blinks rapidly."
m_type = 1 m_type = 1
if ("bow") if("bow")
if (!src.buckled) if(!src.buckled)
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "bows to [param]." message = "bows to [param]."
else else
message = "bows." message = "bows."
m_type = 1 m_type = 1
if ("custom") if("custom")
var/input = sanitize(input("Choose an emote to display.") as text|null) var/input = sanitize(input("Choose an emote to display.") as text|null)
if (!input) if(!input)
return return
var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable")
if (input2 == "Visible") if(input2 == "Visible")
m_type = 1 m_type = 1
else if (input2 == "Hearable") else if(input2 == "Hearable")
if (src.miming) if(src.miming)
return return
m_type = 2 m_type = 2
else else
alert("Unable to use this emote, must be either hearable or visible.") alert("Unable to use this emote, must be either hearable or visible.")
return 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) //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. // return //This check does not work and I have no idea why, I'm leaving it in for reference.
if (src.client) if(src.client)
if (client.prefs.muted & MUTE_IC) if(client.prefs.muted & MUTE_IC)
to_chat(src, "<font color='red'>You cannot send IC messages (muted).</font>") to_chat(src, "<font color='red'>You cannot send IC messages (muted).</font>")
return return
if (stat) if(stat)
return return
if(!(message)) if(!(message))
return return
return custom_emote(m_type, message) return custom_emote(m_type, message)
if ("salute") if("salute")
if (!src.buckled) if(!src.buckled)
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "salutes to [param]." message = "salutes to [param]."
else else
message = "salutes." message = "salutes."
m_type = 1 m_type = 1
if ("choke") if("choke")
if(miming) if(miming)
message = "clutches [T.his] throat desperately!" message = "clutches [T.his] throat desperately!"
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "chokes!" message = "chokes!"
m_type = 2 m_type = 2
else else
message = "makes a strong noise." message = "makes a strong noise."
m_type = 2 m_type = 2
if ("clap") if("clap")
if (!src.restrained()) if(!src.restrained())
message = "claps." message = "claps."
playsound(src.loc, 'sound/misc/clapping.ogg') playsound(src.loc, 'sound/misc/clapping.ogg')
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("flap") if("flap")
if (!src.restrained()) if(!src.restrained())
message = "flaps [T.his] wings." message = "flaps [T.his] wings."
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("aflap") if("aflap")
if (!src.restrained()) if(!src.restrained())
message = "flaps [T.his] wings ANGRILY!" message = "flaps [T.his] wings ANGRILY!"
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("drool") if("drool")
message = "drools." message = "drools."
m_type = 1 m_type = 1
if ("eyebrow") if("eyebrow")
message = "raises an eyebrow." message = "raises an eyebrow."
m_type = 1 m_type = 1
if ("chuckle") if("chuckle")
if(miming) if(miming)
message = "appears to chuckle." message = "appears to chuckle."
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "chuckles." message = "chuckles."
m_type = 2 m_type = 2
else else
message = "makes a noise." message = "makes a noise."
m_type = 2 m_type = 2
if ("twitch") if("twitch")
message = "twitches." message = "twitches."
m_type = 1 m_type = 1
if ("twitch_v") if("twitch_v")
message = "twitches violently." message = "twitches violently."
m_type = 1 m_type = 1
if ("faint") if("faint")
message = "faints." message = "faints."
if(src.sleeping) if(src.sleeping)
return //Can't faint while asleep return //Can't faint while asleep
@@ -275,167 +272,167 @@
message = "makes a strong noise." message = "makes a strong noise."
m_type = 2 m_type = 2
if ("frown") if("frown")
message = "frowns." message = "frowns."
m_type = 1 m_type = 1
if ("nod") if("nod")
message = "nods." message = "nods."
m_type = 1 m_type = 1
if ("blush") if("blush")
message = "blushes." message = "blushes."
m_type = 1 m_type = 1
if ("wave") if("wave")
message = "waves." message = "waves."
m_type = 1 m_type = 1
if ("gasp") if("gasp")
if(miming) if(miming)
message = "appears to be gasping!" message = "appears to be gasping!"
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "gasps!" message = "gasps!"
m_type = 2 m_type = 2
else else
message = "makes a weak noise." message = "makes a weak noise."
m_type = 2 m_type = 2
if ("deathgasp") if("deathgasp")
message = "[species.get_death_message()]" message = "[species.get_death_message()]"
m_type = 1 m_type = 1
if ("giggle") if("giggle")
if(miming) if(miming)
message = "giggles silently!" message = "giggles silently!"
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "giggles." message = "giggles."
m_type = 2 m_type = 2
else else
message = "makes a noise." message = "makes a noise."
m_type = 2 m_type = 2
if ("glare") if("glare")
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "glares at [param]." message = "glares at [param]."
else else
message = "glares." message = "glares."
if ("stare") if("stare")
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "stares at [param]." message = "stares at [param]."
else else
message = "stares." message = "stares."
if ("look") if("look")
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "looks at [param]." message = "looks at [param]."
else else
message = "looks." message = "looks."
m_type = 1 m_type = 1
if ("grin") if("grin")
message = "grins." message = "grins."
m_type = 1 m_type = 1
if ("cry") if("cry")
if(miming) if(miming)
message = "cries." message = "cries."
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "cries." message = "cries."
m_type = 2 m_type = 2
else 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 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 m_type = 2
if ("sigh") if("sigh")
if(miming) if(miming)
message = "sighs." message = "sighs."
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "sighs." message = "sighs."
m_type = 2 m_type = 2
else else
message = "makes a weak noise." message = "makes a weak noise."
m_type = 2 m_type = 2
if ("laugh") if("laugh")
if(miming) if(miming)
message = "acts out a laugh." message = "acts out a laugh."
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "laughs." message = "laughs."
m_type = 2 m_type = 2
else else
message = "makes a noise." message = "makes a noise."
m_type = 2 m_type = 2
if ("mumble") if("mumble")
message = "mumbles!" message = "mumbles!"
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("grumble") if("grumble")
if(miming) if(miming)
message = "grumbles!" message = "grumbles!"
m_type = 1 m_type = 1
if (!muzzled) if(!muzzled)
message = "grumbles!" message = "grumbles!"
m_type = 2 m_type = 2
else else
message = "makes a noise." message = "makes a noise."
m_type = 2 m_type = 2
if ("groan") if("groan")
if(miming) if(miming)
message = "appears to groan!" message = "appears to groan!"
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "groans!" message = "groans!"
m_type = 2 m_type = 2
else else
message = "makes a loud noise." message = "makes a loud noise."
m_type = 2 m_type = 2
if ("moan") if("moan")
if(miming) if(miming)
message = "appears to moan!" message = "appears to moan!"
m_type = 1 m_type = 1
@@ -443,11 +440,11 @@
message = "moans!" message = "moans!"
m_type = 2 m_type = 2
if ("johnny") if("johnny")
var/M var/M
if (param) if(param)
M = param M = param
if (!M) if(!M)
param = null param = null
else else
if(miming) if(miming)
@@ -457,27 +454,27 @@
message = "says, \"[M], please. He had a family.\" [src.name] takes a drag from a cigarette and blows his name out in smoke." 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 m_type = 2
if ("point") if("point")
if (!src.restrained()) if(!src.restrained())
var/mob/M = null var/mob/M = null
if (param) if(param)
for (var/atom/A as mob|obj|turf|area in view(null, null)) for (var/atom/A as mob|obj|turf|area in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
message = "points." message = "points."
else else
pointed(M) pointed(M)
if (M) if(M)
message = "points to [M]." message = "points to [M]."
else else
m_type = 1 m_type = 1
if ("raise") if("raise")
if (!src.restrained()) if(!src.restrained())
message = "raises a hand." message = "raises a hand."
m_type = 1 m_type = 1
@@ -485,35 +482,35 @@
message = "shakes [T.his] head." message = "shakes [T.his] head."
m_type = 1 m_type = 1
if ("shrug") if("shrug")
message = "shrugs." message = "shrugs."
m_type = 1 m_type = 1
if ("signal") if("signal")
if (!src.restrained()) if(!src.restrained())
var/t1 = round(text2num(param)) var/t1 = round(text2num(param))
if (isnum(t1)) if(isnum(t1))
if (t1 <= 5 && (!src.r_hand || !src.l_hand)) if(t1 <= 5 && (!src.r_hand || !src.l_hand))
message = "raises [t1] finger\s." 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." message = "raises [t1] finger\s."
m_type = 1 m_type = 1
if ("smile") if("smile")
message = "smiles." message = "smiles."
m_type = 1 m_type = 1
if ("shiver") if("shiver")
message = "shivers." message = "shivers."
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("pale") if("pale")
message = "goes pale for a second." message = "goes pale for a second."
m_type = 1 m_type = 1
if ("tremble") if("tremble")
message = "trembles in fear!" message = "trembles in fear!"
m_type = 1 m_type = 1
@@ -548,48 +545,48 @@
message = "makes a strange noise." message = "makes a strange noise."
m_type = 2 m_type = 2
if ("sniff") if("sniff")
message = "sniffs." message = "sniffs."
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("snore") if("snore")
if (miming) if(miming)
message = "sleeps soundly." message = "sleeps soundly."
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "snores." message = "snores."
m_type = 2 m_type = 2
else else
message = "makes a noise." message = "makes a noise."
m_type = 2 m_type = 2
if ("whimper") if("whimper")
if (miming) if(miming)
message = "appears hurt." message = "appears hurt."
m_type = 1 m_type = 1
else else
if (!muzzled) if(!muzzled)
message = "whimpers." message = "whimpers."
m_type = 2 m_type = 2
else else
message = "makes a weak noise." message = "makes a weak noise."
m_type = 2 m_type = 2
if ("wink") if("wink")
message = "winks." message = "winks."
m_type = 1 m_type = 1
if ("yawn") if("yawn")
if (!muzzled) if(!muzzled)
message = "yawns." message = "yawns."
m_type = 2 m_type = 2
if(miming) if(miming)
m_type = 1 m_type = 1
if ("collapse") if("collapse")
Paralyse(2) Paralyse(2)
message = "collapses!" message = "collapses!"
m_type = 2 m_type = 2
@@ -598,49 +595,49 @@
if("hug") if("hug")
m_type = 1 m_type = 1
if (!src.restrained()) if(!src.restrained())
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(1, null)) for (var/mob/A in view(1, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (M == src) if(M == src)
M = null M = null
if (M) if(M)
message = "hugs [M]." message = "hugs [M]."
else else
message = "hugs [T.himself]." message = "hugs [T.himself]."
if ("handshake") if("handshake")
m_type = 1 m_type = 1
if (!src.restrained() && !src.r_hand) if(!src.restrained() && !src.r_hand)
var/mob/living/M = null var/mob/living/M = null
if (param) if(param)
for (var/mob/living/A in view(1, null)) for (var/mob/living/A in view(1, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (M == src) if(M == src)
M = null M = null
if (M) if(M)
if (M.canmove && !M.r_hand && !M.restrained()) if(M.canmove && !M.r_hand && !M.restrained())
message = "shakes hands with [M]." message = "shakes hands with [M]."
else else
message = "holds out [T.his] hand to [M]." message = "holds out [T.his] hand to [M]."
if("dap") if("dap")
m_type = 1 m_type = 1
if (!src.restrained()) if(!src.restrained())
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(1, null)) for (var/mob/A in view(1, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (M) if(M)
message = "gives daps to [M]." message = "gives daps to [M]."
else else
message = "sadly can't find anybody to give daps to, and daps [T.himself]. Shameful." message = "sadly can't find anybody to give daps to, and daps [T.himself]. Shameful."
@@ -735,16 +732,16 @@
else else
message = "makes a light spitting noise, a poor attempt at a whistle." message = "makes a light spitting noise, a poor attempt at a whistle."
if ("help") 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, \ to_chat(src, "<span class='filter_say'>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, \ 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, \ 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</span>")
else else
to_chat(src, "<font color='blue'>Unusable emote '[act]'. Say *help for a list.</font>") to_chat(src, "<span class='filter_say'><font color='blue'>Unusable emote '[act]'. Say *help for a list.</font></span>")
if (message) if(message)
custom_emote(m_type,message) custom_emote(m_type,message)
/mob/living/carbon/human/verb/pose() /mob/living/carbon/human/verb/pose()

View File

@@ -1,10 +1,8 @@
/mob/living/carbon/human/say(var/message,var/whispering=0) /mob/living/carbon/human/GetAltName()
var/alt_name = ""
if(name != GetVoice()) if(name != GetVoice())
alt_name = "(as [get_id_name("Unknown")])" return " (as [get_id_name("Unknown")])"
message = sanitize(message) return ..()
..(message, alt_name = alt_name, whispering = whispering)
/mob/living/carbon/human/proc/forcesay(list/append) /mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS) if(stat == CONSCIOUS)
@@ -47,36 +45,28 @@
return species.speech_bubble_appearance return species.speech_bubble_appearance
return "normal" 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. if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
return 1 return TRUE
if(species.can_understand(other)) if(species.can_understand(other))
return 1 return TRUE
//These only pertain to common. Languages are handled by mob/say_understands() //These only pertain to common. Languages are handled by mob/say_understands()
if (!speaking) if(!speaking)
if (istype(other, /mob/living/carbon/alien/diona)) if(istype(other, /mob/living/carbon/alien/diona))
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now. if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
return 1 return TRUE
if (istype(other, /mob/living/silicon)) if(issilicon(other))
return 1 return TRUE
if (istype(other, /mob/living/carbon/brain)) if(isbrain(other))
return 1 return TRUE
if (istype(other, /mob/living/simple_mob/slime)) if(isslime(other))
return 1 return TRUE
//This is already covered by mob/say_understands()
//if (istype(other, /mob/living/simple_animal))
// if((other.universal_speak && !speaking) || src.universal_speak || src.universal_understand)
// return 1
// return 0
return ..() return ..()
/mob/living/carbon/human/GetVoice() /mob/living/carbon/human/GetVoice()
var/voice_sub var/voice_sub
if(istype(get_rig(),/obj/item/weapon/rig)) if(istype(get_rig(),/obj/item/weapon/rig))
var/obj/item/weapon/rig/rig = get_rig() var/obj/item/weapon/rig/rig = get_rig()
@@ -113,30 +103,6 @@
/mob/living/carbon/human/proc/GetSpecialVoice() /mob/living/carbon/human/proc/GetSpecialVoice()
return special_voice 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) /mob/living/carbon/human/handle_speech_problems(var/list/message_data)
if(silent || (sdisabilities & MUTE)) if(silent || (sdisabilities & MUTE))
message_data[1] = "" message_data[1] = ""
@@ -152,59 +118,72 @@
else else
. = ..(message_data) . = ..(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) switch(message_mode)
if("intercom") if("intercom")
if(!src.restrained()) if(!restrained())
for(var/obj/item/device/radio/intercom/I in view(1)) 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) I.add_fingerprint(src)
used_radios += I used_radios += I
if("headset") if("headset")
if(l_ear && istype(l_ear,/obj/item/device/radio)) var/obj/item/device/radio/R = null
var/obj/item/device/radio/R = l_ear if(isradio(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))
R = l_ear R = l_ear
has_radio = 1 if(R.talk_into(src, message_pieces, null, verb))
if(l_hand && istype(l_hand,/obj/item/device/radio)) 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 R = l_hand
has_radio = 1 if(istype(R))
if(has_radio) if(R.talk_into(src, message_pieces, null, verb))
R.talk_into(src,message,null,verb,speaking) used_radios += R
used_radios += R
else else
if(message_mode) if(message_mode)
if(l_ear && istype(l_ear,/obj/item/device/radio)) if(isradio(l_ear))
l_ear.talk_into(src,message, message_mode, verb, speaking) if(l_ear.talk_into(src, message_pieces, message_mode, verb))
used_radios += l_ear used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio)) return
r_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += r_ear 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() /mob/living/carbon/human/handle_speech_sound()
var/list/returns[2]
if(species.speech_sounds && prob(species.speech_chance)) if(species.speech_sounds && prob(species.speech_chance))
var/list/returns[2]
returns[1] = sound(pick(species.speech_sounds)) returns[1] = sound(pick(species.speech_sounds))
returns[2] = 50 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

View File

@@ -532,10 +532,9 @@
genders = list(PLURAL) genders = list(PLURAL)
/datum/species/diona/can_understand(var/mob/other) /datum/species/diona/can_understand(var/mob/other)
var/mob/living/carbon/alien/diona/D = other if(istype(other, /mob/living/carbon/alien/diona))
if(istype(D)) return TRUE
return 1 return FALSE
return 0
/datum/species/diona/equip_survival_gear(var/mob/living/carbon/human/H) /datum/species/diona/equip_survival_gear(var/mob/living/carbon/human/H)
if(H.backbag == 1) if(H.backbag == 1)

View File

@@ -86,11 +86,9 @@
return "alien [caste_name] ([alien_number])" return "alien [caste_name] ([alien_number])"
/datum/species/xenos/can_understand(var/mob/other) /datum/species/xenos/can_understand(var/mob/other)
if(istype(other, /mob/living/carbon/alien/larva))
if(istype(other,/mob/living/carbon/alien/larva)) return TRUE
return 1 return FALSE
return 0
/datum/species/xenos/hug(var/mob/living/carbon/human/H,var/mob/living/target) /datum/species/xenos/hug(var/mob/living/carbon/human/H,var/mob/living/target)
H.visible_message("<span class='notice'>[H] caresses [target] with its scythe-like arm.</span>", \ H.visible_message("<span class='notice'>[H] caresses [target] with its scythe-like arm.</span>", \

View File

@@ -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

View File

@@ -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, "<font color='red'>You cannot send IC messages (muted).</font>")
return
if (stat)
return
if(!(message))
return
return custom_emote(m_type, message)
if("bounce")
message = "<B>The [src.name]</B> bounces in place."
m_type = 1
if ("custom")
return custom_emote(m_type, message)
if("jiggle")
message = "<B>The [src.name]</B> jiggles!"
m_type = 1
if("light")
message = "<B>The [src.name]</B> lights up for a bit, then stops."
m_type = 1
if("moan")
message = "<B>The [src.name]</B> moans."
m_type = 2
if("shiver")
message = "<B>The [src.name]</B> shivers."
m_type = 2
if("sway")
message = "<B>The [src.name]</B> sways around dizzily."
m_type = 1
if("twitch")
message = "<B>The [src.name]</B> twitches."
m_type = 1
if("vibrate")
message = "<B>The [src.name]</B> 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, "<font color='blue'>Unusable emote '[act]'. Say *help for a list.</font>")
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

View File

@@ -1,31 +0,0 @@
/mob/living/carbon/slime/examine(mob/user)
..(user)
var/msg = ""
if (src.stat == DEAD)
msg += "<span class='deadsay'>It is limp and unresponsive.</span>\n"
else
if (src.getBruteLoss())
msg += "<span class='warning'>"
if (src.getBruteLoss() < 40)
msg += "It has some punctures in its flesh!"
else
msg += "<B>It has severe punctures and tears in its flesh!</B>"
msg += "</span>\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 += "<span class='warning'>It is glowing brightly with high levels of electrical activity.</span>\n"
if(10)
msg += "<span class='warning'><B>It is radiating with massive levels of electrical activity!</B></span>\n"
msg += "*---------*"
to_chat(user,msg)
return

View File

@@ -1,2 +0,0 @@
/mob/living/carbon/slime/handle_regular_hud_updates()
return

View File

@@ -1,392 +0,0 @@
/obj/item/slime_extract
name = "slime extract"
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
icon = 'icons/mob/slimes.dmi'
icon_state = "grey slime extract"
force = 1.0
w_class = ITEMSIZE_TINY
throwforce = 0
throw_speed = 3
throw_range = 6
origin_tech = list(TECH_BIO = 4)
var/uses = 1 // uses before it goes inert
var/enhanced = 0 //has it been enhanced before?
flags = OPENCONTAINER
/*
/obj/item/slime_extract/attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/slimesteroid2))
if(enhanced == 1)
to_chat(user, "<span class='warning'> This extract has already been enhanced!</span>")
return ..()
if(Uses == 0)
to_chat(user, "<span class='warning'> You can't enhance a used extract!</span>")
return ..()
to_chat(user, "You apply the enhancer. It now has triple the amount of uses.")
Uses = 3
enhanced = 1
qdel(O)
*/
/obj/item/slime_extract/New()
..()
create_reagents(5)
// reagents.add_reagent("slimejelly", 30)
/obj/item/slime_extract/grey
name = "grey slime extract"
icon_state = "grey slime extract"
/obj/item/slime_extract/gold
name = "gold slime extract"
icon_state = "gold slime extract"
/obj/item/slime_extract/silver
name = "silver slime extract"
icon_state = "silver slime extract"
/obj/item/slime_extract/metal
name = "metal slime extract"
icon_state = "metal slime extract"
/obj/item/slime_extract/purple
name = "purple slime extract"
icon_state = "purple slime extract"
/obj/item/slime_extract/dark_purple
name = "dark purple slime extract"
icon_state = "dark purple slime extract"
/obj/item/slime_extract/orange
name = "orange slime extract"
icon_state = "orange slime extract"
/obj/item/slime_extract/yellow
name = "yellow slime extract"
icon_state = "yellow slime extract"
/obj/item/slime_extract/red
name = "red slime extract"
icon_state = "red slime extract"
/obj/item/slime_extract/blue
name = "blue slime extract"
icon_state = "blue slime extract"
/obj/item/slime_extract/dark_blue
name = "dark blue slime extract"
icon_state = "dark blue slime extract"
/obj/item/slime_extract/pink
name = "pink slime extract"
icon_state = "pink slime extract"
/obj/item/slime_extract/green
name = "green slime extract"
icon_state = "green slime extract"
/obj/item/slime_extract/lightpink
name = "light pink slime extract"
icon_state = "light pink slime extract"
/obj/item/slime_extract/black
name = "black slime extract"
icon_state = "black slime extract"
/obj/item/slime_extract/oil
name = "oil slime extract"
icon_state = "oil slime extract"
/obj/item/slime_extract/adamantine
name = "adamantine slime extract"
icon_state = "adamantine slime extract"
/obj/item/slime_extract/bluespace
name = "bluespace slime extract"
icon_state = "bluespace slime extract"
/obj/item/slime_extract/pyrite
name = "pyrite slime extract"
icon_state = "pyrite slime extract"
/obj/item/slime_extract/cerulean
name = "cerulean slime extract"
icon_state = "cerulean slime extract"
/obj/item/slime_extract/sepia
name = "sepia slime extract"
icon_state = "sepia slime extract"
/obj/item/slime_extract/rainbow
name = "rainbow slime extract"
icon_state = "rainbow slime extract"
/obj/item/slimepotion
icon = 'icons/obj/chemical.dmi'
////Pet Slime Creation///
/*
/obj/item/slimepotion/docility
name = "docility potion"
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
icon_state = "bottle19"
/obj/item/slimepotion/docility/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
to_chat(user, "<span class='warning'> The potion only works on slimes!</span>")
return ..()
// if(M.is_adult) //Can't tame adults
// to_chat(user, "<span class='warning'> Only baby slimes can be tamed!</span>")
// return..()
if(M.stat)
to_chat(user, "<span class='warning'> The slime is dead!</span>")
return..()
if(M.mind)
to_chat(user, "<span class='warning'> The slime resists!</span>")
return ..()
var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
pet.icon_state = "[M.colour] [M.is_adult ? "adult" : "baby"] slime"
pet.icon_living = "[M.colour] [M.is_adult ? "adult" : "baby"] slime"
pet.icon_dead = "[M.colour] [M.is_adult ? "adult" : "baby"] slime dead"
pet.colour = "[M.colour]"
to_chat(user, "You feed the slime the potion, removing it's powers and calming it.")
qdel(M)
var/newname = sanitize(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN)
if (!newname)
newname = "pet slime"
pet.name = newname
pet.real_name = newname
qdel(src)
/obj/item/slimepotion/stabilizer
name = "slime stabilizer"
desc = "A potent chemical mix that will reduce the chance of a slime mutating."
icon_state = "potcyan"
/obj/item/slimepotion/stabilizer/attack(mob/living/carbon/slime/M, mob/user)
if(!isslime(M))
to_chat(user, "<span class='warning'>The stabilizer only works on slimes!</span>")
return ..()
if(M.stat)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
if(M.mutation_chance == 0)
to_chat(user, "<span class='warning'>The slime already has no chance of mutating!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the stabilizer. It is now less likely to mutate.</span>")
M.mutation_chance = Clamp(M.mutation_chance-15,0,100)
qdel(src)
/obj/item/weapon/slimepotion2
name = "advanced docility potion"
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
to_chat(user, "<span class='warning'> The potion only works on slimes!</span>")
return ..()
if(M.stat)
to_chat(user, "<span class='warning'> The slime is dead!</span>")
return..()
if(M.mind)
to_chat(user, "<span class='warning'> The slime resists!</span>")
return ..()
var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc)
pet.icon_state = "[M.colour] adult slime"
pet.icon_living = "[M.colour] adult slime"
pet.icon_dead = "[M.colour] baby slime dead"
pet.colour = "[M.colour]"
to_chat(user, "You feed the slime the potion, removing it's powers and calming it.")
qdel(M)
var/newname = sanitize(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN)
if (!newname)
newname = "pet slime"
pet.name = newname
pet.real_name = newname
qdel(src)
/obj/item/slimesteroid
name = "slime steroid"
desc = "A potent chemical mix that will cause a slime to generate more extract."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
to_chat(user, "<span class='warning'> The steroid only works on baby slimes!</span>")
return ..()
if(M.is_adult) //Can't tame adults
to_chat(user, "<span class='warning'> Only baby slimes can use the steroid!</span>")
return..()
if(M.stat)
to_chat(user, "<span class='warning'> The slime is dead!</span>")
return..()
if(M.cores == 3)
to_chat(user, "<span class='warning'> The slime already has the maximum amount of extract!</span>")
return..()
to_chat(user, "You feed the slime the steroid. It now has triple the amount of extract.")
M.cores = 3
qdel(src)
/obj/item/slimesteroid2
name = "extract enhancer"
desc = "A potent chemical mix that will give a slime extract three uses."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle17"
/*afterattack(obj/target, mob/user , flag)
if(istype(target, /obj/item/slime_extract))
if(target.enhanced == 1)
to_chat(user, "<span class='warning'> This extract has already been enhanced!</span>")
return ..()
if(target.Uses == 0)
to_chat(user, "<span class='warning'> You can't enhance a used extract!</span>")
return ..()
to_chat(user, "You apply the enhancer. It now has triple the amount of uses.")
target.Uses = 3
target.enahnced = 1
qdel(src)*/
*/
/obj/effect/golemrune
anchored = 1
desc = "a strange rune used to create golems. It glows when spirits are nearby."
name = "rune"
icon = 'icons/obj/rune.dmi'
icon_state = "golem"
unacidable = 1
layer = TURF_LAYER
New()
..()
START_PROCESSING(SSobj, src)
process()
var/mob/observer/dead/ghost
for(var/mob/observer/dead/O in src.loc)
if(!O.client) continue
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
ghost = O
break
if(ghost)
icon_state = "golem2"
else
icon_state = "golem"
attack_hand(mob/living/user as mob)
var/mob/observer/dead/ghost
for(var/mob/observer/dead/O in src.loc)
if(!O.client) continue
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
ghost = O
break
if(!ghost)
to_chat(user, "The rune fizzles uselessly. There is no spirit nearby.")
return
var/mob/living/carbon/human/G = new(src.loc)
G.set_species("Golem")
G.key = ghost.key
to_chat(G, "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost.")
qdel(src)
proc/announce_to_ghosts()
for(var/mob/observer/dead/G in player_list)
if(G.client)
var/area/A = get_area(src)
if(A)
to_chat(G, "Golem rune created in [A.name].")
/mob/living/carbon/slime/has_eyes()
return 0
//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
/*
// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
/obj/item/slime_core
name = "slime extract"
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
icon = 'icons/mob/slimes.dmi'
icon_state = "slime extract"
force = 1.0
w_class = ITEMSIZE_TINY
throwforce = 1.0
throw_speed = 2
throw_range = 6
origin_tech = list(TECH_BIO = 4)
var/POWERFLAG = 0 // sshhhhhhh
var/Flush = 30
var/Uses = 5 // uses before it goes inert
/obj/item/slime_core/New()
..()
create_reagents(100)
POWERFLAG = rand(1,10)
Uses = rand(7, 25)
//flags |= NOREACT
/*
spawn()
Life()
proc/Life()
while(src)
sleep(25)
Flush--
if(Flush <= 0)
reagents.clear_reagents()
Flush = 30
*/
/obj/item/weapon/reagent_containers/food/snacks/egg/slime
name = "slime egg"
desc = "A small, gelatinous egg."
icon = 'icons/mob/mob.dmi'
icon_state = "slime egg-growing"
bitesize = 12
origin_tech = list(TECH_BIO = 4)
var/grown = 0
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/Initialize()
. = ..()
reagents.add_reagent("nutriment", 4)
reagents.add_reagent("slimejelly", 1)
addtimer(CALLBACK(src, ./proc/Grow), rand(120 SECONDS, 150 SECONDS))
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
grown = 1
icon_state = "slime egg-grown"
START_PROCESSING(SSobj, src)
return
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
STOP_PROCESSING(SSobj, src)
var/turf/T = get_turf(src)
src.visible_message("<span class='warning'> The [name] pulsates and quivers!</span>")
spawn(rand(50,100))
src.visible_message("<span class='warning'> The [name] bursts open!</span>")
new/mob/living/carbon/slime(T)
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
var/turf/location = get_turf(src)
var/datum/gas_mixture/environment = location.return_air()
if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
src.Hatch()
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype( W, /obj/item/weapon/pen/crayon ))
return
else
..()
*/

View File

@@ -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, "<span class='danger'>You are starving!</span>")
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

View File

@@ -1,4 +0,0 @@
/mob/living/carbon/slime/Login()
..()
update_hud()
return

View File

@@ -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("<span class='warning'>[M] attempts to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
else
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off!</span>")
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("<span class='warning'>[M] attempts to wrestle \the [name] off of [Victim]!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
else
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off of [Victim]!</span>")
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("<span class='warning'>[M] has grabbed [src] passively!</span>")
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("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='danger'>[M] has punched [src]!</span>")
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>")
return
/mob/living/carbon/slime/attackby(obj/item/W, mob/user)
if(W.force > 0)
attacked += 10
if(prob(25))
to_chat(user, "<span class='danger'>[W] passes right through [src]!</span>")
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())

View File

@@ -1,169 +0,0 @@
/mob/living/carbon/slime/proc/Wrap(var/mob/living/M) // This is a proc for the clicks
if (Victim == M || src == M)
Feedstop()
return
if (Victim)
to_chat(src, "I am already feeding...")
return
var t = invalidFeedTarget(M)
if (t)
to_chat(src,t)
return
Feedon(M)
/mob/living/carbon/slime/proc/invalidFeedTarget(var/mob/living/M)
if (!M || !istype(M))
return "This subject is incomparable..."
if (istype(M, /mob/living/carbon/slime)) // No cannibalism... yet
return "I cannot feed on other slimes..."
if (!Adjacent(M))
return "This subject is too far away..."
if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.getMaxHealth() * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
return "This subject does not have an edible life energy..."
for(var/mob/living/carbon/slime/met in view())
if(met.Victim == M && met != src)
return "The [met.name] is already feeding on this subject..."
return 0
/mob/living/carbon/slime/proc/Feedon(var/mob/living/M)
Victim = M
loc = M.loc
canmove = 0
anchored = 1
regenerate_icons()
while(Victim && !invalidFeedTarget(M) && stat != 2)
canmove = 0
if(Adjacent(M))
UpdateFeed(M)
if(istype(M, /mob/living/carbon))
Victim.adjustCloneLoss(rand(5,6))
Victim.adjustToxLoss(rand(1,2))
if(Victim.health <= 0)
Victim.adjustToxLoss(rand(2,4))
else if(istype(M, /mob/living/simple_animal))
Victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
else
to_chat(src, "<span class='warning'>[pick("This subject is incompatable", "This subject does not have a life energy", "This subject is empty", "I am not satisified", "I can not feed from this subject", "I do not feel nourished", "This subject is not food")]...</span>")
Feedstop()
break
if(prob(15) && M.client && istype(M, /mob/living/carbon))
var/painMes = pick("You can feel your body becoming weak!", "You feel like you're about to die!", "You feel every part of your body screaming in agony!", "A low, rolling pain passes through your body!", "Your body feels as if it's falling apart!", "You feel extremely weak!", "A sharp, deep pain bathes every inch of your body!")
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.custom_pain(painMes, 100)
else if (istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if (C.can_feel_pain())
to_chat(M, "<span class='danger'>[painMes]</span>")
gain_nutrition(rand(20,25))
adjustOxyLoss(-10) //Heal yourself
adjustBruteLoss(-10)
adjustFireLoss(-10)
adjustCloneLoss(-10)
updatehealth()
if(Victim)
Victim.updatehealth()
sleep(30) // Deal damage every 3 seconds
else
break
canmove = 1
anchored = 0
if(M && invalidFeedTarget(M)) // This means that the slime drained the victim
if(!client)
if(Victim && !rabid && !attacked && Victim.LAssailant && Victim.LAssailant != Victim && prob(50))
if(!(Victim.LAssailant in Friends))
Friends[Victim.LAssailant] = 1
else
++Friends[Victim.LAssailant]
else
to_chat(src, "<span class='notice'>This subject does not have a strong enough life energy anymore...</span>")
Victim = null
/mob/living/carbon/slime/proc/Feedstop()
if(Victim)
if(Victim.client)
to_chat(Victim, "[src] has let go of your head!")
Victim = null
/mob/living/carbon/slime/proc/UpdateFeed(var/mob/M)
if(Victim)
if(Victim == M)
loc = M.loc // simple "attach to head" effect!
/mob/living/carbon/slime/verb/Evolve()
set category = "Slime"
set desc = "This will let you evolve from baby to adult slime."
if(stat)
to_chat(src, "<span class='notice'>I must be conscious to do this...</span>")
return
if(!is_adult)
if(amount_grown >= 10)
is_adult = 1
maxHealth = 200
amount_grown = 0
regenerate_icons()
name = text("[colour] [is_adult ? "adult" : "baby"] slime ([number])")
else
to_chat(src, "<span class='notice'>I am not ready to evolve yet...</span>")
else
to_chat(src, "<span class='notice'>I have already evolved...</span>")
/mob/living/carbon/slime/verb/Reproduce()
set category = "Slime"
set desc = "This will make you split into four Slimes."
if(stat)
to_chat(src, "<span class='notice'>I must be conscious to do this...</span>")
return
if(is_adult)
if(amount_grown >= 10)
if(stat)
to_chat(src, "<span class='notice'>I must be conscious to do this...</span>")
return
var/list/babies = list()
var/new_nutrition = round(nutrition * 0.9)
var/new_powerlevel = round(powerlevel / 4)
for(var/i = 1, i <= 4, i++)
var/t = colour
if(prob(mutation_chance))
t = slime_mutation[rand(1,4)]
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc, t)
if(ckey) M.nutrition = new_nutrition //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature!
M.powerlevel = new_powerlevel
if(i != 1) step_away(M, src)
M.Friends = Friends.Copy()
babies += M
feedback_add_details("slime_babies_born","slimebirth_[replacetext(M.colour," ","_")]")
var/mob/living/carbon/slime/new_slime = pick(babies)
new_slime.universal_speak = universal_speak
if(src.mind)
src.mind.transfer_to(new_slime)
else
new_slime.key = src.key
qdel(src)
else
to_chat(src, "<span class='notice'>I am not ready to reproduce yet...</span>")
else
to_chat(src, "<span class='notice'>I am not old enough to reproduce yet...</span>")

View File

@@ -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)))
..()

View File

@@ -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)

View File

@@ -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]")
..()

View File

@@ -10,7 +10,7 @@
return 0 return 0
if(language == GLOB.all_languages[src.species_language]) if(language == GLOB.all_languages[src.species_language])
to_chat(src, "<span class='notice'>You will now speak your standard default language, [language], if you do not specify a language when speaking.</span>") to_chat(src, "<span class='notice'>You will now speak your standard default language, [language ? language : "common"], if you do not specify a language when speaking.</span>")
else if (language) else if (language)
if(language && !can_speak(language)) if(language && !can_speak(language))

View File

@@ -68,56 +68,49 @@ proc/get_radio_key_from_channel(var/channel)
return key return key
/mob/living/proc/binarycheck() /mob/living/proc/binarycheck()
return FALSE
if (istype(src, /mob/living/silicon/pai)) /mob/proc/get_default_language()
return return null
if (!ishuman(src)) /mob/living/get_default_language()
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()
return default_language return default_language
//Takes a list of the form list(message, verb, whispering) and modifies it as needed //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 //Returns 1 if a speech problem was applied, 0 otherwise
/mob/living/proc/handle_speech_problems(var/list/message_data) /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/verb = message_data[2]
var/whispering = message_data[3] var/whispering = message_data[3]
. = 0 . = 0
if((HULK in mutations) && health >= 25 && length(message)) // Technically this rerolls the verb for as many say pieces as there are. _shrug_
message = "[uppertext(message)]!!!" for(var/datum/multilingual_say_piece/S in message_pieces)
verb = pick("yells","roars","hollers") if(S.speaking && (S.speaking.flags & NO_STUTTER || S.speaking.flags & SIGNLANG))
whispering = 0 continue
. = 1
if(slurring)
message = slur(message)
verb = pick("slobbers","slurs")
. = 1
if(stuttering)
message = stutter(message)
verb = pick("stammers","stutters")
. = 1
message_data[1] = message 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
message_data[2] = verb message_data[2] = verb
message_data[3] = whispering 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") if(message_mode == "intercom")
for(var/obj/item/device/radio/intercom/I in view(1, null)) 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 used_radios += I
return 0 return 0
@@ -128,13 +121,13 @@ proc/get_radio_key_from_channel(var/channel)
return returns return returns
/mob/living/proc/get_speech_ending(verb, var/ending) /mob/living/proc/get_speech_ending(verb, var/ending)
if(ending=="!") if(ending == "!")
return pick("exclaims","shouts","yells") return pick("exclaims","shouts","yells")
if(ending=="?") if(ending == "?")
return "asks" return "asks"
return verb 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 you're muted for IC chat
if(client) if(client)
if(message) if(message)
@@ -153,98 +146,81 @@ proc/get_radio_key_from_channel(var/channel)
var/message_mode = parse_message_mode(message, "headset") var/message_mode = parse_message_mode(message, "headset")
//Maybe they are using say/whisper to do a quick emote, so do those //Maybe they are using say/whisper to do a quick emote, so do those
switch(copytext(message,1,2)) switch(copytext(message, 1, 2))
if("*") return emote(copytext(message,2)) if("*") return emote(copytext(message, 2))
if("^") return custom_emote(1, copytext(message,2)) if("^") return custom_emote(1, copytext(message, 2))
//Parse the radio code and consume it //Parse the radio code and consume it
if (message_mode) if(message_mode)
if (message_mode == "headset") if(message_mode == "headset")
message = copytext(message,2) //it would be really nice if the parse procs could do this for us. message = copytext(message, 2) //it would be really nice if the parse procs could do this for us.
else if (message_mode == "whisper") else if(message_mode == "whisper")
whispering = 1 whispering = 1
message_mode = null message_mode = null
message = copytext(message,3) message = copytext(message, 3)
else else
message = copytext(message,3) message = copytext(message, 3)
//Clean up any remaining space on the left //Clean up any remaining space on the left
message = trim_left(message) message = trim_left(message)
//Parse the language code and consume it //Parse the language code and consume it
if(!speaking) var/list/message_pieces = parse_languages(message)
speaking = parse_language(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.
if(!speaking) S.speaking.broadcast(src, S.message)
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))
return 1 return 1
//Self explanatory. if(!LAZYLEN(message_pieces))
if(is_muzzled() && !(speaking && (speaking.flags & SIGNLANG))) 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, "<span class='danger'>You're muzzled and cannot speak!</span>") to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return 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 //Whisper vars
var/w_scramble_range = 5 //The range at which you get ***as*th**wi**** 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_adverb //An adverb prepended to the verb in whispers
var/w_not_heard //The message for people in watching range 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 //Handle language-specific verbs and adverb setup if necessary
if(!whispering) //Just doing normal 'say' (for now, may change below) if(!whispering) //Just doing normal 'say' (for now, may change below)
verb = say_quote(message, speaking) verb = say_quote(message, first_piece.speaking)
else if(whispering && speaking.whisper_verb) //Language has defined whisper verb else if(whispering && first_piece.speaking.whisper_verb) //Language has defined whisper verb
verb = speaking.whisper_verb verb = first_piece.speaking.whisper_verb
w_not_heard = "[verb] something" w_not_heard = "[verb] something"
else //Whispering but language has no whisper verb, use say verb else //Whispering but language has no whisper verb, use say verb
w_adverb = pick("quietly", "softly") w_adverb = pick("quietly", "softly")
verb = speaking.speech_verb verb = first_piece.speaking.speech_verb
w_not_heard = "[speaking.speech_verb] something [w_adverb]" w_not_heard = "[first_piece.speaking.speech_verb] something [w_adverb]"
//For speech disorders (hulk, slurring, stuttering) //For speech disorders (hulk, slurring, stuttering)
if(!(speaking && (speaking.flags & NO_STUTTER || speaking.flags & SIGNLANG))) var/list/message_data = list(message_pieces, verb, whispering)
var/list/message_data = list(message, verb, whispering) if(handle_speech_problems(message_data))
if(handle_speech_problems(message_data)) message_pieces = message_data[1]
message = message_data[1] whispering = message_data[3]
whispering = message_data[3]
if(verb != message_data[2]) //They changed our verb if(verb != message_data[2]) //They changed our verb
if(whispering) if(whispering)
w_adverb = pick("quietly", "softly") w_adverb = pick("quietly", "softly")
verb = message_data[2] verb = message_data[2]
//Whisper may have adverbs, add those if one was set //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 something nulled or emptied the message, forget it
if(!message || message == "") if(!LAZYLEN(message_pieces))
return 0 return 0
//Radio message handling //Radio message handling
var/list/obj/item/used_radios = new var/list/used_radios = list()
if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, whispering)) if(handle_message_mode(message_mode, message_pieces, verb, used_radios, whispering))
return 1 return 1
//For languages with actual speech sounds //For languages with actual speech sounds
@@ -260,16 +236,19 @@ proc/get_radio_key_from_channel(var/channel)
if(used_radios.len) if(used_radios.len)
italics = 1 italics = 1
message_range = 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 var/msg
if(!speaking || !(speaking.flags & NO_TALK_MSG)) if(!first_piece.speaking || !(first_piece.speaking.flags & NO_TALK_MSG))
msg = "<span class='notice'>\The [src] talks into \the [used_radios[1]]</span>" msg = "<span class='notice'>[src] talks into [used_radios[1]]</span>"
for(var/mob/living/M in hearers(5, src))
if((M != src) && msg) if(msg)
for(var/mob/living/M in hearers(5, src) - src)
M.show_message(msg) 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 //Set vars if we're still whispering by this point
if(whispering) if(whispering)
@@ -277,15 +256,11 @@ proc/get_radio_key_from_channel(var/channel)
message_range = 1 message_range = 1
sound_vol *= 0.5 sound_vol *= 0.5
//Handle nonverbal and sign languages here //Handle nonverbal languages here
if (speaking) for(var/datum/multilingual_say_piece/S in message_pieces)
if (speaking.flags & SIGNLANG) if(S.speaking.flags & NONVERBAL)
log_say("(SIGN) [message]", src) if(prob(30))
return say_signlang(message, pick(speaking.signlang_verb), speaking) custom_emote(1, "[pick(S.speaking.signlang_verb)].")
if (speaking.flags & NONVERBAL)
if (prob(30))
src.custom_emote(1, "[pick(speaking.signlang_verb)].")
//These will contain the main receivers of the message //These will contain the main receivers of the message
var/list/listening = list() var/list/listening = list()
@@ -296,12 +271,12 @@ proc/get_radio_key_from_channel(var/channel)
if(T) if(T)
//Air is too thin to carry sound at all, contact speech only //Air is too thin to carry sound at all, contact speech only
var/datum/gas_mixture/environment = T.return_air() 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) if(pressure < SOUND_MINIMUM_PRESSURE)
message_range = 1 message_range = 1
//Air is nearing minimum levels, make text italics as a hint, and muffle sound //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 italics = 1
sound_vol *= 0.5 sound_vol *= 0.5
@@ -347,16 +322,16 @@ proc/get_radio_key_from_channel(var/channel)
var/image/I1 = listening[M] || speech_bubble var/image/I1 = listening[M] || speech_bubble
images_to_clients[I1] |= M.client images_to_clients[I1] |= M.client
M << I1 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(whispering) //Don't even bother with these unless whispering
if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range
if(M.client) if(M.client)
var/image/I2 = listening[M] || speech_bubble var/image/I2 = listening[M] || speech_bubble
images_to_clients[I2] |= M.client images_to_clients[I2] |= M.client
M << I2 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 if(dst > w_scramble_range && dst <= world.view) //Inside whisper 'visible' range
M.show_message("<span class='game say'><span class='name'>[src.name]</span> [w_not_heard].</span>", 2) M.show_message("<span class='game say'><span class='name'>[name]</span> [w_not_heard].</span>", 2)
//Object message delivery //Object message delivery
for(var/obj/O in listening_obj) for(var/obj/O in listening_obj)
@@ -364,7 +339,7 @@ proc/get_radio_key_from_channel(var/channel)
if(O && src) //If we still exist, when the spawn processes if(O && src) //If we still exist, when the spawn processes
var/dst = get_dist(get_turf(O),get_turf(src)) var/dst = get_dist(get_turf(O),get_turf(src))
if(dst <= message_range) 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. //Remove all those images. At least it's just ONE spawn this time.
spawn(30) spawn(30)
@@ -379,7 +354,7 @@ proc/get_radio_key_from_channel(var/channel)
//Log the message to file //Log the message to file
if(whispering) if(whispering)
log_whisper(message,src) log_whisper(message, src)
else else
log_say(message, src) log_say(message, src)
return 1 return 1
@@ -407,8 +382,41 @@ proc/get_radio_key_from_channel(var/channel)
/obj/effect/speech_bubble /obj/effect/speech_bubble
var/mob/parent var/mob/parent
/mob/living/proc/GetVoice() /mob/proc/GetVoice()
return name 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, "<span class='warning'>Unusable emote '[act]'. Say *help for a list.</span>")
/mob/proc/speech_bubble_appearance() /mob/proc/speech_bubble_appearance()
return "normal" return "normal"

View File

@@ -824,6 +824,69 @@ var/list/ai_verbs_default = list(
// If that is ever fixed please update this proc. // If that is ever fixed please update this proc.
return TRUE 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 = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[impersonating]'>[speaker_name] ([jobname])</a>"
else
track = "[speaker_name] ([jobname])"
else
track = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[speaker]'>[speaker_name] ([jobname])</a>"
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 = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [message]</span></i>"
show_message(rendered, 2)
//Special subtype kept around for global announcements //Special subtype kept around for global announcements
/mob/living/silicon/ai/announcer/ /mob/living/silicon/ai/announcer/
is_dummy = 1 is_dummy = 1

View File

@@ -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 = "<b>[src]</b> beeps at [param]."
else
message = "<b>[src]</b> 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 = "<b>[src]</b> pings at [param]."
else
message = "<b>[src]</b> 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 = "<b>[src]</b> buzzes at [param]."
else
message = "<b>[src]</b> 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 = "<b>[src]</b> emits an affirmative blip at [param]."
else
message = "<b>[src]</b> 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 = "<b>[src]</b> chirps happily at [param]"
else
message = "<b>[src]</b> 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 = "<b>[src]</b> emits a negative blip at [param]."
else
message = "<b>[src]</b> emits a negative blip."
playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
m_type = 1
..(act, m_type, message)

View File

@@ -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) if(silence_time)
to_chat(src, "<font color=green>Communication circuits remain uninitialized.</font>") to_chat(src, "<font color=green>Communication circuits remain uninitialized.</font>")
else else
..(msg) ..()

View File

@@ -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(local_transmit)
if (src.client) if (src.client)
if(client.prefs.muted & MUTE_IC) if(client.prefs.muted & MUTE_IC)
@@ -36,4 +36,4 @@
if(M.client) if(M.client)
to_chat(M, "<b>[src]</b> transmits, \"[message]\"") to_chat(M, "<b>[src]</b> transmits, \"[message]\"")
return 1 return 1
return ..(message, 0) return ..()

View File

@@ -1,6 +1,6 @@
/mob/living/silicon/robot/emote(var/act,var/m_type=1,var/message = null) /mob/living/silicon/robot/emote(var/act,var/m_type=1,var/message = null)
var/param = null var/param = null
if (findtext(act, "-", 1, null)) if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null) var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1) param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1) act = copytext(act, 1, t1)
@@ -9,236 +9,119 @@
act = copytext(act,1,length(act)) act = copytext(act,1,length(act))
switch(act) switch(act)
if ("me") if("salute")
if (src.client) if(!src.buckled)
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)
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "salutes to [param]." message = "<b>[src]</b> salutes to [param]."
else else
message = "salutes." message = "<b>[src]</b> salutes."
m_type = 1 m_type = 1
if ("bow") if("bow")
if (!src.buckled) if(!src.buckled)
var/M = null var/M = null
if (param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if (!M) if(!M)
param = null param = null
if (param) if(param)
message = "bows to [param]." message = "<b>[src]</b> bows to [param]."
else else
message = "bows." message = "<b>[src]</b> bows."
m_type = 1 m_type = 1
if ("clap") if("clap")
if (!src.restrained()) if(!src.restrained())
message = "claps." message = "<b>[src]</b> claps."
m_type = 2 m_type = 2
if ("flap") if("flap")
if (!src.restrained()) if(!src.restrained())
message = "flaps its wings." message = "<b>[src]</b> flaps its wings."
m_type = 2 m_type = 2
if ("aflap") if("aflap")
if (!src.restrained()) if(!src.restrained())
message = "flaps its wings ANGRILY!" message = "<b>[src]</b> flaps its wings ANGRILY!"
m_type = 2 m_type = 2
if ("twitch") if("twitch")
message = "twitches." message = "<b>[src]</b> twitches."
m_type = 1 m_type = 1
if ("twitch_v") if("twitch_v")
message = "twitches violently." message = "<b>[src]</b> twitches violently."
m_type = 1 m_type = 1
if ("nod") if("nod")
message = "nods." message = "<b>[src]</b> nods."
m_type = 1 m_type = 1
if ("deathgasp") if("deathgasp")
message = "shudders violently for a moment, then becomes motionless, its eyes slowly darkening." message = "<b>[src]</b> shudders violently for a moment, then becomes motionless, its eyes slowly darkening."
m_type = 1 m_type = 1
if ("glare") 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")
var/M = null var/M = null
if(param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if(!M) if(!M)
param = null param = null
if (param) if(param)
message = "beeps at [param]." message = "<b>[src]</b> glares at [param]."
else else
message = "beeps." message = "<b>[src]</b> glares."
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
m_type = 1
if("ping") if("stare")
var/M = null var/M = null
if(param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if(!M) if(!M)
param = null param = null
if (param) if(param)
message = "pings at [param]." message = "<b>[src]</b> stares at [param]."
else else
message = "pings." message = "<b>[src]</b> stares."
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
m_type = 1
if("buzz") if("look")
var/M = null var/M = null
if(param) if(param)
for (var/mob/A in view(null, null)) for (var/mob/A in view(null, null))
if (param == A.name) if(param == A.name)
M = A M = A
break break
if(!M) if(!M)
param = null 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) if(param)
for (var/mob/A in view(null, null)) message = "<b>[src]</b> looks at [param]."
if (param == A.name)
M = A
break
if(!M)
param = null
if (param)
message = "emits an affirmative blip at [param]."
else else
message = "emits an affirmative blip." message = "<b>[src]</b> looks."
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)
m_type = 1 m_type = 1
if("law") if("law")
if (istype(module,/obj/item/weapon/robot_module/robot/security)) if(istype(module,/obj/item/weapon/robot_module/robot/security))
message = "shows its legal authorization barcode." message = "<b>[src]</b> shows its legal authorization barcode."
playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0) playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0)
m_type = 2 m_type = 2
@@ -246,20 +129,15 @@
to_chat(src, "You are not THE LAW, pal.") to_chat(src, "You are not THE LAW, pal.")
if("halt") if("halt")
if (istype(module,/obj/item/weapon/robot_module/robot/security)) if(istype(module,/obj/item/weapon/robot_module/robot/security))
message = "<B>'s</B> speakers skreech, \"Halt! Security!\"." message = "<b>[src]</b> <B>'s</B> speakers skreech, \"Halt! Security!\"."
playsound(src.loc, 'sound/voice/halt.ogg', 50, 0) playsound(src.loc, 'sound/voice/halt.ogg', 50, 0)
m_type = 2 m_type = 2
else else
to_chat(src, "You are not security.") 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") 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, "<font color='blue'>Unusable emote '[act]'. Say *help for a list.</font>")
if ((message && src.stat == 0)) ..(act, m_type, message)
custom_emote(m_type,message)
return

View File

@@ -1,10 +1,4 @@
/mob/living/silicon/say(var/message, var/sanitize = 1, var/whispering = 0) /mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios)
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)
..() ..()
if(message_mode) if(message_mode)
if(!is_component_functioning("radio")) if(!is_component_functioning("radio"))
@@ -17,7 +11,7 @@
/mob/living/silicon/speech_bubble_appearance() /mob/living/silicon/speech_bubble_appearance()
return "synthetic" 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") if(message_mode == "department")
return holopad_talk(message, verb, speaking) return holopad_talk(message, verb, speaking)
@@ -29,7 +23,7 @@
message_mode = null message_mode = null
return aiRadio.talk_into(src,message,message_mode,verb,speaking) 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)
if(message_mode == "general") if(message_mode == "general")
@@ -50,71 +44,44 @@
#define IS_ROBOT 2 #define IS_ROBOT 2
#define IS_PAI 3 #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() //These only pertain to common. Languages are handled by mob/say_understands()
if (!speaking) if(!speaking)
if (istype(other, /mob/living/carbon)) if(iscarbon(other))
return 1 return TRUE
if (istype(other, /mob/living/silicon)) if(issilicon(other))
return 1 return TRUE
if (istype(other, /mob/living/carbon/brain)) if(isbrain(other))
return 1 return TRUE
return ..() return ..()
//For holopads only. Usable by AI. //For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking) /mob/living/silicon/ai/proc/holopad_talk(list/message_pieces, verb)
log_say("(HPAD) [multilingual_to_message(message_pieces)]",src)
log_say("(HPAD) [message]",src)
message = trim(message)
if (!message)
return
var/obj/machinery/hologram/holopad/T = src.holo var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.masters[src])//If there is a hologram and its master is the user. if(T && T.masters[src])//If there is a hologram and its master is the user.
//Human-like, sorta, heard by those who understand humans.
var/rendered_a
//Speech distorted, heard by those who do not understand AIs.
var/message_stars = stars(message)
var/rendered_b
if(speaking)
rendered_a = "<span class='game say'><span class='name'>[name]</span> [speaking.format_message(message, verb)]</span>"
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [speaking.format_message(message_stars, verb)]</span>"
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [speaking.format_message(message, verb)]</span></i>") //The AI can "hear" its own message.
else
rendered_a = "<span class='game say'><span class='name'>[name]</span> [verb], <span class='message'>\"[message]\"</span></span>"
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [verb], <span class='message'>\"[message_stars]\"</span></span>"
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>") //The AI can "hear" its own message.
var/list/listeners = get_mobs_and_objs_in_view_fast(get_turf(T), world.view) var/list/listeners = get_mobs_and_objs_in_view_fast(get_turf(T), world.view)
var/list/listening = listeners["mobs"] var/list/listening = listeners["mobs"]
var/list/listening_obj = listeners["objs"] var/list/listening_obj = listeners["objs"]
for(var/mob/M in listening) for(var/mob/M in listening)
spawn(0) M.hear_holopad_talk(message_pieces, verb, src)
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)
for(var/obj/O in listening_obj) for(var/obj/O in listening_obj)
if(O == T) //Don't recieve your own speech if(O == T) //Don't recieve your own speech
continue continue
spawn(0) O.hear_talk(src, message_pieces, verb)
if(O && src) //If we still exist, when the spawn processes
O.hear_talk(src, message, verb, speaking)
/*Radios "filter out" this conversation channel so we don't need to account for them. /*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.*/ This is another way of saying that we won't bother dealing with them.*/
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [combine_message(message_pieces, verb, src)]</span></i>")
else else
to_chat(src, "No holopad connected.") to_chat(src, "No holopad connected.")
return 0 return 0
return 1 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. /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) message = trim(message)
if (!message) if(!message)
return return
var/obj/machinery/hologram/holopad/T = src.holo var/obj/machinery/hologram/holopad/T = src.holo
@@ -147,11 +114,11 @@
return 1 return 1
/mob/living/silicon/ai/emote(var/act, var/type, var/message) /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? if(T && T.masters[src]) //Is the AI using a holopad?
src.holopad_emote(message) . = holopad_emote(message)
else //Emote normally, then. else //Emote normally, then.
..() . = ..()
#undef IS_AI #undef IS_AI
#undef IS_ROBOT #undef IS_ROBOT

View File

@@ -193,7 +193,14 @@
//Silicon mob language procs //Silicon mob language procs
/mob/living/silicon/can_speak(datum/language/speaking) /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) /mob/living/silicon/add_language(var/language, var/can_speak=1)
var/var/datum/language/added_language = GLOB.all_languages[language] var/var/datum/language/added_language = GLOB.all_languages[language]
@@ -213,15 +220,11 @@
..(rem_language) ..(rem_language)
speech_synthesizer_langs -= removed_language speech_synthesizer_langs -= removed_language
/mob/living/silicon/check_languages() /mob/living/silicon/check_lang_data()
set name = "Check Known Languages" . = ""
set category = "IC"
set src = usr
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
if(default_language) if(default_language)
dat += "Current default language: [default_language] - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/><br/>" . += "Current default language: [default_language] - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br><br>"
for(var/datum/language/L in languages) for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL)) if(!(L.flags & NONGLOBAL))
@@ -232,10 +235,7 @@
default_str = " - <a href='byond://?src=\ref[src];default_lang=\ref[L]'>set default</a>" default_str = " - <a href='byond://?src=\ref[src];default_lang=\ref[L]'>set default</a>"
var/synth = (L in speech_synthesizer_langs) var/synth = (L in speech_synthesizer_langs)
dat += "<b>[L.name] ([get_language_prefix()][L.key])</b>[synth ? default_str : null]<br/>Speech Synthesizer: <i>[synth ? "YES" : "NOT SUPPORTED"]</i><br/>[L.desc]<br/><br/>" . += "<b>[L.name] ([get_language_prefix()][L.key])</b>[synth ? default_str : null]<br>Speech Synthesizer: <i>[synth ? "YES" : "NOT SUPPORTED"]</i><br>[L.desc]<br><br>"
src << browse(dat, "window=checklanguage")
return
/mob/living/silicon/proc/toggle_sensor_mode() /mob/living/silicon/proc/toggle_sensor_mode()
var/sensor_type = input("Please select sensor type.", "Sensor Integration", null) in list("Security","Medical","Disable") var/sensor_type = input("Please select sensor type.", "Sensor Integration", null) in list("Security","Medical","Disable")

View File

@@ -194,12 +194,6 @@
. = ..() . = ..()
to_chat(src,"<b>You are \the [src].</b> [player_msg]") to_chat(src,"<b>You are \the [src].</b> [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) /mob/living/simple_mob/SelfMove(turf/n, direct)
var/turf/old_turf = get_turf(src) var/turf/old_turf = get_turf(src)
var/old_dir = dir var/old_dir = dir
@@ -264,14 +258,11 @@
update_icon() update_icon()
/mob/living/simple_mob/say(var/message,var/datum/language/language) /mob/living/simple_mob/say_quote(var/message, var/datum/language/speaking = null)
var/verb = "says"
if(speak_emote.len) if(speak_emote.len)
verb = pick(speak_emote) . = pick(speak_emote)
else if(speaking)
message = sanitize(message) . = ..()
..(message, null, verb)
/mob/living/simple_mob/get_speech_ending(verb, var/ending) /mob/living/simple_mob/get_speech_ending(verb, var/ending)
return verb return verb

View File

@@ -205,7 +205,7 @@
return return
// This is awful but its literally say code. // 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 = sanitize(message)
message = capitalize(message) message = capitalize(message)
@@ -224,10 +224,11 @@
if(copytext(message, 1, 2) == "*") if(copytext(message, 1, 2) == "*")
return emote(copytext(message, 2)) return emote(copytext(message, 2))
var/datum/language/L = parse_language(message) var/list/message_pieces = parse_languages(message)
if(L && L.flags & HIVEMIND) for(var/datum/multilingual_say_piece/S in message_pieces)
L.broadcast(src,trim(copytext(message,3)), src.true_name) if(S.speaking && S.speaking.flags & HIVEMIND)
return S.speaking.broadcast(src, trim(copytext(message, 3)), src.true_name)
return
if(!host) if(!host)
if(chemicals >= 30) if(chemicals >= 30)

View File

@@ -5,7 +5,7 @@
real_name = "host brain" real_name = "host brain"
universal_understand = 1 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 (src.client)
if(client.prefs.muted & MUTE_IC) if(client.prefs.muted & MUTE_IC)
@@ -31,7 +31,12 @@
else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
to_chat(M, "The captive mind of [src] whispers, \"[message]\"") to_chat(M, "The captive mind of [src] whispers, \"[message]\"")
/mob/living/captive_brain/me_verb(message as text)
to_chat(src, "<span class='danger'>You cannot emote as a captive mind.</span>")
return
/mob/living/captive_brain/emote(var/message) /mob/living/captive_brain/emote(var/message)
to_chat(src, "<span class='danger'>You cannot emote as a captive mind.</span>")
return return
/mob/living/captive_brain/process_resist() /mob/living/captive_brain/process_resist()

View File

@@ -41,7 +41,7 @@
return say(message) return say(message)
// Ugly saycode so parrots can use their headsets. // 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, alt_name) /mob/living/simple_mob/animal/passive/bird/parrot/handle_message_mode(message_mode, message, verb, speaking, used_radios)
..() ..()
if(message_mode) if(message_mode)
if(my_headset && istype(my_headset, /obj/item/device/radio)) if(my_headset && istype(my_headset, /obj/item/device/radio))

View File

@@ -104,7 +104,7 @@
// Proc: say() // Proc: say()
// Parameters: 4 (generic say() arguments) // Parameters: 4 (generic say() arguments)
// Description: Adds a speech bubble to the communicator device, then calls ..() to do the real work. // 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. //Speech bubbles.
if(comm) if(comm)
var/speech_bubble_test = say_test(message) var/speech_bubble_test = say_test(message)
@@ -117,7 +117,7 @@
M << speech_bubble M << speech_bubble
src << 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() // Proc: speech_bubble_appearance()
// Parameters: 0 // Parameters: 0
@@ -125,15 +125,15 @@
/mob/living/voice/speech_bubble_appearance() /mob/living/voice/speech_bubble_appearance()
return "comm" 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() //These only pertain to common. Languages are handled by mob/say_understands()
if (!speaking) if(!speaking)
if (istype(other, /mob/living/carbon)) if(iscarbon(other))
return 1 return TRUE
if (istype(other, /mob/living/silicon)) if(issilicon(other))
return 1 return TRUE
if (istype(other, /mob/living/carbon/brain)) if(isbrain(other))
return 1 return TRUE
return ..() return ..()
/mob/living/voice/custom_emote(var/m_type=1,var/message = null,var/range=world.view) /mob/living/voice/custom_emote(var/m_type=1,var/message = null,var/range=world.view)

View File

@@ -1217,3 +1217,6 @@ mob/proc/yank_out_object()
selfimage.loc = src selfimage.loc = src
return selfimage return selfimage
/mob/proc/GetAltName()
return ""

View File

@@ -184,6 +184,12 @@ proc/getsensorlevel(A)
p++ p++
return t 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) proc/slur(phrase)
phrase = html_decode(phrase) phrase = html_decode(phrase)
var/leng=length(phrase) var/leng=length(phrase)

View File

@@ -581,7 +581,7 @@
return ready && ..() return ready && ..()
// Prevents lobby players from seeing say, even with ghostears // 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 return
// Prevents lobby players from seeing emotes, even with ghosteyes // Prevents lobby players from seeing emotes, even with ghosteyes

View File

@@ -1,4 +1,4 @@
/mob/proc/say() /mob/proc/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
return return
/mob/verb/whisper(message as text) /mob/verb/whisper(message as text)
@@ -26,7 +26,7 @@
set_typing_indicator(FALSE) set_typing_indicator(FALSE)
if(use_me) if(use_me)
usr.emote("me",usr.emote_type,message) custom_emote(usr.emote_type, message)
else else
usr.emote(message) usr.emote(message)
@@ -38,7 +38,7 @@
if(!client) if(!client)
return // Clientless mobs shouldn't be trying to talk in deadchat. return // Clientless mobs shouldn't be trying to talk in deadchat.
if(!src.client.holder) if(!client.holder)
if(!config.dsay_allowed) if(!config.dsay_allowed)
to_chat(src, "<span class='danger'>Deadchat is globally muted.</span>") to_chat(src, "<span class='danger'>Deadchat is globally muted.</span>")
return return
@@ -51,55 +51,55 @@
say_dead_direct("[pick("complains","moans","whines","laments","blubbers")], <span class='message'>\"[message]\"</span>", src) say_dead_direct("[pick("complains","moans","whines","laments","blubbers")], <span class='message'>\"[message]\"</span>", src)
/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null) /mob/proc/say_understands(var/mob/other, var/datum/language/speaking = null)
if(stat == DEAD)
if (src.stat == DEAD) return TRUE
return 1
//Universal speak makes everything understandable, for obvious reasons. //Universal speak makes everything understandable, for obvious reasons.
else if(src.universal_speak || src.universal_understand) else if(universal_speak || universal_understand)
return 1 return TRUE
//Languages are handled after. //Languages are handled after.
if (!speaking) if(!speaking)
if(!other) if(!other)
return 1 return TRUE
if(other.universal_speak) if(other.universal_speak)
return 1 return TRUE
if(isAI(src) && ispAI(other)) if(isAI(src) && ispAI(other))
return 1 return TRUE
if (istype(other, src.type) || istype(src, other.type)) if(istype(other, type) || istype(src, other.type))
return 1 return TRUE
return 0 return FALSE
if(speaking.flags & INNATE) 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. //Language check.
for(var/datum/language/L in src.languages) for(var/datum/language/L in languages)
if(speaking.name == L.name) if(speaking.name == L.name)
return 1 return TRUE
return 0 return FALSE
/*
***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/proc/say_quote(var/message, var/datum/language/speaking = null) /mob/proc/say_quote(var/message, var/datum/language/speaking = null)
var/verb = "says" var/verb = "says"
var/ending = copytext(message, length(message)) var/ending = copytext(message, length(message))
if(ending=="!")
verb=pick("exclaims","shouts","yells")
else if(ending=="?")
verb="asks"
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) /mob/proc/emote(var/act, var/type, var/message)
@@ -116,38 +116,123 @@
/mob/proc/say_test(var/text) /mob/proc/say_test(var/text)
var/ending = copytext(text, length(text)) var/ending = copytext(text, length(text))
if (ending == "?") if(ending == "?")
return "1" return "1"
else if (ending == "!") else if(ending == "!")
return "2" return "2"
return "0" return "0"
//parses the message mode code (e.g. :h, :w) from text, such as that supplied to say. //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. //returns the message mode string or null for no message mode.
//standard mode is the mode returned for the special ';' radio code. //standard mode is the mode returned for the special ';' radio code.
/mob/proc/parse_message_mode(var/message, var/standard_mode="headset") /mob/proc/parse_message_mode(var/message, var/standard_mode = "headset")
if(length(message) >= 1 && copytext(message,1,2) == ";") if(length(message) >= 1 && copytext(message, 1, 2) == ";")
return standard_mode return standard_mode
if(length(message) >= 2) 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 department_radio_keys[channel_prefix]
return null return null
//parses the language code (e.g. :j) from text, such as that supplied to say. /datum/multilingual_say_piece
//returns the language object only if the code corresponds to a language that src can speak, otherwise null. var/datum/language/speaking = null
/mob/proc/parse_language(var/message) var/message = ""
var/prefix = copytext(message,1,2)
// This is for audible emotes
if(length(message) >= 1 && prefix == "!")
return GLOB.all_languages["Noise"]
if(length(message) >= 2 && is_language_prefix(prefix)) /datum/multilingual_say_piece/New(datum/language/new_speaking, new_message)
var/language_prefix = copytext(message, 2 ,3) . = ..()
var/datum/language/L = GLOB.language_keys[language_prefix] speaking = new_speaking
if (can_speak(L)) if(new_message)
return L 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 else
return GLOB.all_languages[LANGUAGE_GIBBERISH] var/next = prefix_locations[i + 1] // We look ahead at the next message to see where we need to stop.
return null 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(.)

View File

@@ -41,12 +41,12 @@
return owner.examine(user, distance, infix, suffix) return owner.examine(user, distance, infix, suffix)
// Relay some stuff they hear // 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) if(speaker && speaker.z != src.z)
return // Only relay speech on our acutal z, otherwise we might relay sounds that were themselves relayed up! return // Only relay speech on our acutal z, otherwise we might relay sounds that were themselves relayed up!
if(isliving(owner)) if(isliving(owner))
verb += " from above" 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) /mob/zshadow/proc/sync_icon(var/mob/M)
name = M.name name = M.name

View File

@@ -29,11 +29,11 @@
var/mob/living/M = src.loc var/mob/living/M = src.loc
M.say(pick(heard_talk)) 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) if(heard_talk.len > max_stored_messages)
heard_talk.Remove(pick(heard_talk)) 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) if(istype(src.loc, /mob/living) && world.time - last_twitch > 50)
last_twitch = world.time last_twitch = world.time
@@ -116,7 +116,7 @@
else if(get_dist(W, src) > 10) else if(get_dist(W, src) > 10)
shadow_wights.Remove(wight_check_index) 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)) if(world.time - last_bloodcall >= bloodcall_interval && M in view(7, src))
bloodcall(M) bloodcall(M)

View File

@@ -112,7 +112,7 @@ Divergence proc, used in mutation to make unique datums.
/mob/living/simple_animal/xeno/proc/RandomizeTraits() /mob/living/simple_animal/xeno/proc/RandomizeTraits()
return return
/mob/living/simple_animal/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)
if(traitdat.traits[TRAIT_XENO_CANLEARN]) if(traitdat.traits[TRAIT_XENO_CANLEARN])
/* /*
Until this gets sorted out to a functioning point, or waiting on Psi's saycode update. Until this gets sorted out to a functioning point, or waiting on Psi's saycode update.
@@ -128,7 +128,7 @@ Divergence proc, used in mutation to make unique datums.
*/ */
if(!(message in speak)) if(!(message in speak))
speech_buffer.Add(message) speech_buffer.Add(message)
..(message,verb,language,alt_name,italics,speaker) ..(message,verb,language,italics,speaker)
/mob/living/simple_animal/xeno/proc/ProcessSpeechBuffer() /mob/living/simple_animal/xeno/proc/ProcessSpeechBuffer()
if(speech_buffer.len) if(speech_buffer.len)

View File

@@ -2064,7 +2064,6 @@
#include "code\modules\mob\living\carbon\alien\emote.dm" #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\life.dm"
#include "code\modules\mob\living\carbon\alien\progression.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\update_icons.dm"
#include "code\modules\mob\living\carbon\alien\diona\diona.dm" #include "code\modules\mob\living\carbon\alien\diona\diona.dm"
#include "code\modules\mob\living\carbon\alien\diona\diona_attacks.dm" #include "code\modules\mob\living\carbon\alien\diona\diona_attacks.dm"
@@ -2136,6 +2135,7 @@
#include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_species.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_species.dm"
#include "code\modules\mob\living\carbon\human\species\xenomorphs\xenomorphs.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\xenomorphs.dm"
#include "code\modules\mob\living\silicon\death.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\laws.dm"
#include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\login.dm"
#include "code\modules\mob\living\silicon\say.dm" #include "code\modules\mob\living\silicon\say.dm"