mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-12 15:45:25 +01:00
Multilingualism
This commit adjusts the speech parsing system to allow for an infinite number of languages to be present in the same message. You can transition freely between any language you are able to speak simply by putting it's language key in the middle of the sentence. Honestly, this was a massive pain in the ass, and there's probably still broken stuff, even though I've spent around 8 hours testing and refining this.
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
|
||||
. = src.emote_dead(message)
|
||||
|
||||
/mob/dead/observer/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
|
||||
/mob/dead/observer/handle_track(var/message, var/verb = "says", var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
|
||||
return "[speaker_name] ([ghost_follow_link(follow_target, ghost=src)])"
|
||||
|
||||
/mob/dead/observer/handle_speaker_name(var/mob/speaker = null, var/vname, var/hard_to_hear)
|
||||
|
||||
@@ -1,6 +1,53 @@
|
||||
// At minimum every mob has a hear_say proc.
|
||||
|
||||
/mob/proc/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)
|
||||
/mob/proc/combine_message(var/list/message_pieces, var/verb, var/mob/speaker, always_stars = 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
|
||||
|
||||
if(SP.speaking && SP.speaking.flags & INNATE) // Fucking snowflake noise lang
|
||||
return SP.speaking.format_message(piece)
|
||||
|
||||
if(iteration_count == 1)
|
||||
piece = capitalize(piece)
|
||||
|
||||
if(SP.speaking)
|
||||
if(!say_understands(speaker, SP.speaking))
|
||||
if(isanimal(speaker))
|
||||
var/mob/living/simple_animal/S = speaker
|
||||
if(LAZYLEN(S.speak))
|
||||
piece = pick(S.speak)
|
||||
else
|
||||
piece = stars(piece)
|
||||
else
|
||||
piece = SP.speaking.scramble(piece)
|
||||
if(always_stars)
|
||||
piece = stars(piece)
|
||||
piece = SP.speaking.format_message(piece)
|
||||
else
|
||||
if(!say_understands(speaker, null))
|
||||
piece = stars(piece)
|
||||
if(isanimal(speaker))
|
||||
var/mob/living/simple_animal/S = speaker
|
||||
if(LAZYLEN(S.speak))
|
||||
piece = pick(S.speak)
|
||||
if(always_stars)
|
||||
piece = stars(piece)
|
||||
piece = "<span class='message'><span class='body'>[piece]</span></span>"
|
||||
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/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)
|
||||
return 0
|
||||
|
||||
@@ -23,35 +70,18 @@
|
||||
sound_vol *= 0.5
|
||||
|
||||
if(sleeping || stat == UNCONSCIOUS)
|
||||
hear_sleep(message)
|
||||
hear_sleep(message_pieces)
|
||||
return 0
|
||||
|
||||
//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(!has_vision(information_only = TRUE)) //blind people can't see dumbass
|
||||
message = stars(message)
|
||||
|
||||
if(!speaker || !(speaker in view(src)))
|
||||
message = stars(message)
|
||||
|
||||
if(!say_understands(speaker, language))
|
||||
if(isanimal(speaker))
|
||||
var/mob/living/simple_animal/S = speaker
|
||||
if(S.speak.len)
|
||||
message = pick(S.speak)
|
||||
else
|
||||
message = stars(message)
|
||||
else
|
||||
if(language)
|
||||
message = language.scramble(message)
|
||||
else
|
||||
message = stars(message)
|
||||
|
||||
var/speaker_name = speaker.name
|
||||
if(ishuman(speaker))
|
||||
var/mob/living/carbon/human/H = speaker
|
||||
speaker_name = H.GetVoice()
|
||||
|
||||
var/message = combine_message(message_pieces, verb, speaker)
|
||||
if(message == "")
|
||||
return
|
||||
|
||||
if(italics)
|
||||
message = "<i>[message]</i>"
|
||||
|
||||
@@ -66,74 +96,47 @@
|
||||
message = "<b>[message]</b>"
|
||||
|
||||
if(!can_hear())
|
||||
if(!language || !(language.flags & INNATE)) // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set
|
||||
if(speaker == src)
|
||||
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>")
|
||||
else
|
||||
to_chat(src, "<span class='name'>[speaker_name]</span>[speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
|
||||
else
|
||||
if(language)
|
||||
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][language.format_message(message, verb)]</span>")
|
||||
// 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(!language || !(language.flags & INNATE))
|
||||
if(speaker == src)
|
||||
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>")
|
||||
else
|
||||
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][verb], <span class='message'><span class='body'>\"[message]\"</span></span></span>")
|
||||
to_chat(src, "<span class='name'>[speaker_name]</span>[speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
|
||||
else
|
||||
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][message]</span>")
|
||||
if(speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
|
||||
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
|
||||
src.playsound_local(source, speech_sound, sound_vol, 1)
|
||||
|
||||
|
||||
/mob/proc/hear_radio(var/message, var/verb = "says", var/datum/language/language = null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname = "", var/atom/follow_target)
|
||||
/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target)
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(sleeping || stat == UNCONSCIOUS) //If unconscious or sleeping
|
||||
hear_sleep(message)
|
||||
hear_sleep(multilingual_to_message(message_pieces))
|
||||
return
|
||||
|
||||
var/message = combine_message(message_pieces, verb, speaker, always_stars = hard_to_hear)
|
||||
if(message == "")
|
||||
return
|
||||
|
||||
var/track = null
|
||||
if(!follow_target)
|
||||
follow_target = speaker
|
||||
|
||||
//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(!has_vision(information_only=TRUE)) //blind people can't see dumbass
|
||||
message = stars(message)
|
||||
|
||||
if(!speaker || !(speaker in view(src)))
|
||||
message = stars(message)
|
||||
|
||||
if(!say_understands(speaker, language))
|
||||
if(isanimal(speaker))
|
||||
var/mob/living/simple_animal/S = speaker
|
||||
if(S.speak && S.speak.len)
|
||||
message = pick(S.speak)
|
||||
else
|
||||
return
|
||||
else
|
||||
if(language)
|
||||
message = language.scramble(message)
|
||||
else
|
||||
message = stars(message)
|
||||
|
||||
if(hard_to_hear)
|
||||
message = stars(message)
|
||||
|
||||
var/speaker_name = handle_speaker_name(speaker, vname, hard_to_hear)
|
||||
track = handle_track(message, verb, language, speaker, speaker_name, follow_target, hard_to_hear)
|
||||
track = handle_track(message, verb, speaker, speaker_name, follow_target, hard_to_hear)
|
||||
|
||||
var/formatted
|
||||
if(language)
|
||||
formatted = language.format_message_radio(message, verb)
|
||||
else
|
||||
formatted = "[verb], <span class=\"body\">\"[message]\"</span>"
|
||||
if(!can_hear())
|
||||
if(prob(20))
|
||||
to_chat(src, "<span class='warning'>You feel your headset vibrate but can hear nothing from it!</span>")
|
||||
else if(track)
|
||||
to_chat(src, "[part_a][track][part_b][formatted]</span></span>")
|
||||
to_chat(src, "[part_a][track][part_b][message]</span></span>")
|
||||
else
|
||||
to_chat(src, "[part_a][speaker_name][part_b][formatted]</span></span>")
|
||||
to_chat(src, "[part_a][speaker_name][part_b][message]</span></span>")
|
||||
|
||||
/mob/proc/handle_speaker_name(var/mob/speaker = null, var/vname, var/hard_to_hear)
|
||||
/mob/proc/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
|
||||
var/speaker_name = "unknown"
|
||||
if(speaker)
|
||||
speaker_name = speaker.name
|
||||
@@ -146,26 +149,10 @@
|
||||
|
||||
return speaker_name
|
||||
|
||||
/mob/proc/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
|
||||
/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
|
||||
return
|
||||
|
||||
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(say_understands(speaker, language))
|
||||
message = "<B>[src]</B> [verb], \"[message]\""
|
||||
else
|
||||
message = "<B>[src]</B> [verb]."
|
||||
|
||||
if(src.status_flags & PASSEMOTES)
|
||||
for(var/obj/item/holder/H in src.contents)
|
||||
H.show_message(message)
|
||||
for(var/mob/living/M in src.contents)
|
||||
M.show_message(message)
|
||||
src.show_message(message)
|
||||
|
||||
/mob/proc/hear_sleep(var/message)
|
||||
/mob/proc/hear_sleep(message)
|
||||
var/heard = ""
|
||||
if(prob(15))
|
||||
message = strip_html_properly(message)
|
||||
@@ -177,9 +164,19 @@
|
||||
heardword = copytext(heardword,2)
|
||||
if(copytext(heardword,-1) in punctuation)
|
||||
heardword = copytext(heardword,1,lentext(heardword))
|
||||
heard = "<span class = 'game_say'>...You hear something about...[heardword]</span>"
|
||||
heard = "<span class='game say'>...<i>You hear something about<i>... '[heardword]'...</span>"
|
||||
|
||||
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)
|
||||
|
||||
/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)
|
||||
@@ -11,7 +11,6 @@
|
||||
var/ask_verb = "asks" // Used when sentence ends in a ?
|
||||
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
|
||||
var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead.
|
||||
var/signlang_verb = list() // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
|
||||
var/colour = "body" // CSS style to use for strings in this language.
|
||||
var/key = "x" // Character used to speak in language eg. :o for Unathi.
|
||||
var/flags = 0 // Various language flags.
|
||||
@@ -85,11 +84,11 @@
|
||||
|
||||
return scrambled_text
|
||||
|
||||
/datum/language/proc/format_message(message, verb)
|
||||
return "[verb], <span class='message'><span class='[colour]'>\"[capitalize(message)]\"</span></span>"
|
||||
/datum/language/proc/format_message(message)
|
||||
return "<span class='message'><span class='[colour]'>[message]</span></span>"
|
||||
|
||||
/datum/language/proc/format_message_radio(message, verb)
|
||||
return "[verb], <span class='[colour]'>\"[capitalize(message)]\"</span>"
|
||||
/datum/language/proc/format_message_radio(message)
|
||||
return "<span class='[colour]'>[message]</span>"
|
||||
|
||||
/datum/language/proc/get_talkinto_msg_range(message)
|
||||
// if you yell, you'll be heard from two tiles over instead of one
|
||||
@@ -103,11 +102,11 @@
|
||||
|
||||
if(!speaker_mask)
|
||||
speaker_mask = speaker.name
|
||||
var/msg = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> [format_message(message, get_spoken_verb(message))]</span></i>"
|
||||
var/msg = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> [get_spoken_verb(message)], [format_message(message)]</span></i>"
|
||||
|
||||
for(var/mob/player in GLOB.player_list)
|
||||
if(istype(player,/mob/dead) && follow)
|
||||
var/msg_dead = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> ([ghost_follow_link(speaker, ghost=player)]) [format_message(message, get_spoken_verb(message))]</span></i>"
|
||||
var/msg_dead = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> ([ghost_follow_link(speaker, ghost=player)]) [get_spoken_verb(message)], [format_message(message)]</span></i>"
|
||||
to_chat(player, msg_dead)
|
||||
continue
|
||||
|
||||
@@ -135,10 +134,10 @@
|
||||
key = ""
|
||||
flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER
|
||||
|
||||
/datum/language/noise/format_message(message, verb)
|
||||
/datum/language/noise/format_message(message)
|
||||
return "<span class='message'><span class='[colour]'>[message]</span></span>"
|
||||
|
||||
/datum/language/noise/format_message_radio(message, verb)
|
||||
/datum/language/noise/format_message_radio(message)
|
||||
return "<span class='[colour]'>[message]</span>"
|
||||
|
||||
/datum/language/noise/get_talkinto_msg_range(message)
|
||||
@@ -635,10 +634,9 @@
|
||||
|
||||
// Language handling.
|
||||
/mob/proc/add_language(language)
|
||||
|
||||
var/datum/language/new_language = GLOB.all_languages[language]
|
||||
|
||||
if(!istype(new_language) || new_language in languages)
|
||||
if(!istype(new_language) || (new_language in languages))
|
||||
return FALSE
|
||||
|
||||
languages |= new_language
|
||||
@@ -657,8 +655,7 @@
|
||||
|
||||
// Can we speak this language, as opposed to just understanding it?
|
||||
/mob/proc/can_speak_language(datum/language/speaking)
|
||||
|
||||
return (universal_speak || (speaking && speaking.flags & INNATE) || speaking in languages)
|
||||
return universal_speak || (speaking && speaking.flags & INNATE) || (speaking in languages)
|
||||
|
||||
//TBD
|
||||
/mob/proc/check_lang_data()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/proc/handle_autohiss(message, datum/language/L)
|
||||
/mob/proc/handle_autohiss(message, datum/language/L)
|
||||
return message // no autohiss at this level
|
||||
|
||||
/mob/living/carbon/human/handle_autohiss(message, datum/language/L)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
to_chat(usr, "<span class='warning'>You cannot speak, as your internal speaker is turned off.</span>")
|
||||
. = FALSE
|
||||
|
||||
/mob/living/carbon/brain/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
|
||||
/mob/living/carbon/brain/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios)
|
||||
switch(message_mode)
|
||||
if("headset")
|
||||
var/radio_worked = 0 // If any of the radios our brainmob could use functioned, this is set true so that we don't use any others
|
||||
@@ -39,12 +39,12 @@
|
||||
if(!radio_worked && c.mecha)
|
||||
var/obj/mecha/metalgear = c.mecha
|
||||
if(metalgear.radio)
|
||||
radio_worked = metalgear.radio.talk_into(src, message, message_mode, verb, speaking)
|
||||
radio_worked = metalgear.radio.talk_into(src, message_pieces, message_mode, verb)
|
||||
|
||||
else if(!radio_worked && c.radio)
|
||||
radio_worked = c.radio.talk_into(src, message, message_mode, verb, speaking)
|
||||
radio_worked = c.radio.talk_into(src, message_pieces, message_mode, verb)
|
||||
return radio_worked
|
||||
if("whisper")
|
||||
whisper_say(message, speaking)
|
||||
whisper_say(message_pieces)
|
||||
return 1
|
||||
else return 0
|
||||
|
||||
@@ -233,7 +233,6 @@
|
||||
var/obj/item/organ/external/picked = pick(parts)
|
||||
if(picked.receive_damage(brute, burn, sharp, updating_health))
|
||||
UpdateDamageIcon()
|
||||
speech_problem_flag = 1
|
||||
|
||||
|
||||
//Heal MANY external organs, in random order
|
||||
@@ -256,7 +255,6 @@
|
||||
|
||||
if(updating_health)
|
||||
updatehealth("heal overall damage")
|
||||
speech_problem_flag = 1
|
||||
if(update)
|
||||
UpdateDamageIcon()
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ var/global/default_martial_art = new/datum/martial_art
|
||||
|
||||
var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life()
|
||||
|
||||
var/speech_problem_flag = 0
|
||||
|
||||
var/datum/personal_crafting/handcrafting
|
||||
|
||||
var/datum/martial_art/martial_art = null
|
||||
|
||||
@@ -580,14 +580,14 @@
|
||||
return FALSE
|
||||
saveVoice()
|
||||
|
||||
/mob/living/carbon/human/interactive/hear_say(message, verb = "says", datum/language/language = null, italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
|
||||
/mob/living/carbon/human/interactive/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
|
||||
if(!istype(speaker, /mob/living/carbon/human/interactive))
|
||||
knownStrings |= html_decode(message)
|
||||
knownStrings |= html_decode(multilingual_to_message(message_pieces))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/interactive/hear_radio(message, verb = "says", datum/language/language=null, part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target)
|
||||
/mob/living/carbon/human/interactive/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target)
|
||||
if(!istype(speaker, /mob/living/carbon/human/interactive))
|
||||
knownStrings |= html_decode(message)
|
||||
knownStrings |= html_decode(multilingual_to_message(message_pieces))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/interactive/proc/doProcess()
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
drop_item()
|
||||
emote("cough")
|
||||
if(disabilities & TOURETTES)
|
||||
speech_problem_flag = 1
|
||||
if((prob(10) && paralysis <= 1))
|
||||
Stun(10)
|
||||
switch(rand(1, 3))
|
||||
@@ -86,12 +85,10 @@
|
||||
animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y), time = 1)
|
||||
|
||||
if(disabilities & NERVOUS)
|
||||
speech_problem_flag = 1
|
||||
if(prob(10))
|
||||
Stuttering(10)
|
||||
|
||||
if(getBrainLoss() >= 60 && stat != DEAD)
|
||||
speech_problem_flag = 1
|
||||
if(prob(3))
|
||||
var/list/s1 = list("IM A [pick("PONY","LIZARD","taJaran","kitty","Vulpakin","drASK","BIRDIE","voxxie","race car","combat meCH","SPESSSHIP")] [pick("NEEEEEEIIIIIIIIIGH","sKREEEEEE","MEOW","NYA~","rawr","Barkbark","Hissssss","vROOOOOM","pewpew","choo Choo")]!",
|
||||
"without oxigen blob don't evoluate?",
|
||||
@@ -158,7 +155,6 @@
|
||||
if(!gene.block)
|
||||
continue
|
||||
if(gene.is_active(src))
|
||||
speech_problem_flag = 1
|
||||
gene.OnMobLife(src)
|
||||
if(!ignore_gene_stability && gene_stability < GENETIC_DAMAGE_STAGE_1)
|
||||
var/instability = DEFAULT_GENE_STABILITY - gene_stability
|
||||
@@ -741,7 +737,6 @@
|
||||
stat = UNCONSCIOUS
|
||||
|
||||
else if(sleeping)
|
||||
speech_problem_flag = 1
|
||||
|
||||
stat = UNCONSCIOUS
|
||||
|
||||
@@ -1003,29 +998,6 @@
|
||||
This proc below is only called when those HUD elements need to change as determined by the mobs hud_updateflag.
|
||||
*/
|
||||
|
||||
|
||||
/mob/living/carbon/human/handle_silent()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return silent
|
||||
|
||||
/mob/living/carbon/human/handle_slurring()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return slurring
|
||||
|
||||
/mob/living/carbon/human/handle_stunned()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return stunned
|
||||
|
||||
/mob/living/carbon/human/handle_stuttering()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return stuttering
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/can_heartattack()
|
||||
if(NO_BLOOD in dna.species.species_traits)
|
||||
return FALSE
|
||||
|
||||
@@ -107,65 +107,58 @@
|
||||
/mob/living/carbon/human/proc/GetSpecialVoice()
|
||||
return special_voice
|
||||
|
||||
/mob/living/carbon/human/handle_speech_problems(var/message, var/verb)
|
||||
var/list/returns[3]
|
||||
var/speech_problem_flag = 0
|
||||
/mob/living/carbon/human/handle_speech_problems(list/message_pieces, var/verb)
|
||||
var/span = ""
|
||||
if(mind)
|
||||
span = mind.speech_span
|
||||
|
||||
if(silent || (disabilities & MUTE))
|
||||
message = ""
|
||||
speech_problem_flag = 1
|
||||
if((COMIC in mutations) \
|
||||
|| (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \
|
||||
|| istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown))
|
||||
span = "sans"
|
||||
|
||||
var/list/parent = ..()
|
||||
verb = parent["verb"]
|
||||
|
||||
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
|
||||
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
|
||||
if(hoers.voicechange)
|
||||
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
|
||||
verb = pick("whinnies","neighs", "says")
|
||||
speech_problem_flag = 1
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
if(S.speaking && S.speaking.flags & NO_STUTTER)
|
||||
continue
|
||||
|
||||
if(dna)
|
||||
for(var/datum/dna/gene/gene in dna_genes)
|
||||
if(!gene.block)
|
||||
continue
|
||||
if(gene.is_active(src))
|
||||
message = gene.OnSay(src,message)
|
||||
speech_problem_flag = 1
|
||||
if(silent || (disabilities & MUTE))
|
||||
S.message = ""
|
||||
|
||||
if(message != "")
|
||||
var/list/parent = ..()
|
||||
message = parent[1]
|
||||
verb = parent[2]
|
||||
if(parent[3])
|
||||
speech_problem_flag = 1
|
||||
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
|
||||
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
|
||||
if(hoers.voicechange)
|
||||
S.message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
|
||||
verb = pick("whinnies", "neighs", "says")
|
||||
|
||||
if(dna)
|
||||
for(var/datum/dna/gene/gene in dna_genes)
|
||||
if(!gene.block)
|
||||
continue
|
||||
if(gene.is_active(src))
|
||||
S.message = gene.OnSay(src, S.message)
|
||||
|
||||
var/braindam = getBrainLoss()
|
||||
if(braindam >= 60)
|
||||
speech_problem_flag = 1
|
||||
if(prob(braindam/4))
|
||||
message = stutter(message)
|
||||
if(prob(braindam / 4))
|
||||
S.message = stutter(S.message)
|
||||
verb = "gibbers"
|
||||
if(prob(braindam))
|
||||
message = uppertext(message)
|
||||
S.message = uppertext(S.message)
|
||||
verb = "yells loudly"
|
||||
|
||||
if((COMIC in mutations) || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) || istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown))
|
||||
span = "sans"
|
||||
if(span)
|
||||
S.message = "<span class='[span]'>[S.message]</span>"
|
||||
return list("verb" = verb)
|
||||
|
||||
if(span)
|
||||
message = "<span class='[span]'>[message]</span>"
|
||||
returns[1] = message
|
||||
returns[2] = verb
|
||||
returns[3] = speech_problem_flag
|
||||
return returns
|
||||
|
||||
/mob/living/carbon/human/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
|
||||
/mob/living/carbon/human/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios)
|
||||
switch(message_mode)
|
||||
if("intercom")
|
||||
for(var/obj/item/radio/intercom/I in view(1, src))
|
||||
spawn(0)
|
||||
I.talk_into(src, message, null, verb, speaking)
|
||||
I.talk_into(src, message_pieces, null, verb)
|
||||
used_radios += I
|
||||
|
||||
if("headset")
|
||||
@@ -173,13 +166,13 @@
|
||||
if(isradio(l_ear))
|
||||
R = l_ear
|
||||
used_radios += R
|
||||
if(R.talk_into(src, message, null, verb, speaking))
|
||||
if(R.talk_into(src, message_pieces, null, verb))
|
||||
return
|
||||
|
||||
if(isradio(r_ear))
|
||||
R = r_ear
|
||||
used_radios += R
|
||||
if(R.talk_into(src, message, null, verb, speaking))
|
||||
if(R.talk_into(src, message_pieces, null, verb))
|
||||
return
|
||||
|
||||
if("right ear")
|
||||
@@ -190,7 +183,7 @@
|
||||
R = r_hand
|
||||
if(R)
|
||||
used_radios += R
|
||||
R.talk_into(src, message, null, verb, speaking)
|
||||
R.talk_into(src, message_pieces, null, verb)
|
||||
|
||||
if("left ear")
|
||||
var/obj/item/radio/R
|
||||
@@ -200,21 +193,21 @@
|
||||
R = l_hand
|
||||
if(R)
|
||||
used_radios += R
|
||||
R.talk_into(src, message, null, verb, speaking)
|
||||
R.talk_into(src, message_pieces, null, verb)
|
||||
|
||||
if("whisper")
|
||||
whisper_say(message, speaking)
|
||||
whisper_say(message_pieces)
|
||||
return 1
|
||||
else
|
||||
if(message_mode)
|
||||
if(isradio(l_ear))
|
||||
used_radios += l_ear
|
||||
if(l_ear.talk_into(src, message, message_mode, verb, speaking))
|
||||
if(l_ear.talk_into(src, message_pieces, message_mode, verb))
|
||||
return
|
||||
|
||||
if(isradio(r_ear))
|
||||
used_radios += r_ear
|
||||
if(r_ear.talk_into(src, message, message_mode, verb, speaking))
|
||||
if(r_ear.talk_into(src, message_pieces, message_mode, verb))
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/handle_speech_sound()
|
||||
|
||||
@@ -3,19 +3,11 @@
|
||||
message = trim_strip_html_properly(message) //bit of duplicate code, acceptable because the workaround would be annoying
|
||||
|
||||
//parse the language code and consume it
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if(speaking)
|
||||
message = copytext(message, 2 + length(speaking.key))
|
||||
else
|
||||
speaking = get_default_language()
|
||||
|
||||
// This is broadcast to all mobs with the language,
|
||||
// irrespective of distance or anything else.
|
||||
if(speaking && (speaking.flags & HIVEMIND))
|
||||
speaking.broadcast(src,trim(message))
|
||||
var/list/message_pieces = parse_languages(message)
|
||||
if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages
|
||||
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
|
||||
S.speaking.broadcast(src, S.message)
|
||||
return 1
|
||||
|
||||
message = trim_left(message)
|
||||
message = handle_autohiss(message, speaking)
|
||||
|
||||
whisper_say(message, speaking)
|
||||
whisper_say(message, message_pieces)
|
||||
@@ -14,16 +14,16 @@
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/slime/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)
|
||||
/mob/living/carbon/slime/hear_say(list/message_pieces, var/verb = "says", 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)))
|
||||
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/slime/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="", var/atom/follow_target)
|
||||
/mob/living/carbon/slime/hear_radio(list/message_pieces, var/verb="says", var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="", var/atom/follow_target)
|
||||
if(speaker in Friends)
|
||||
speech_buffer = list()
|
||||
speech_buffer.Add(speaker)
|
||||
speech_buffer.Add(lowertext(html_decode(message)))
|
||||
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
|
||||
..()
|
||||
|
||||
+80
-122
@@ -54,51 +54,48 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
/mob/living/proc/binarycheck()
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/get_default_language()
|
||||
/mob/proc/get_default_language()
|
||||
return null
|
||||
|
||||
/mob/living/get_default_language()
|
||||
return default_language
|
||||
|
||||
/mob/living/proc/handle_speech_problems(var/message, var/verb)
|
||||
var/list/returns[3]
|
||||
var/speech_problem_flag = 0
|
||||
/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb)
|
||||
var/robot = isSynthetic()
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
if(S.speaking && S.speaking.flags & NO_STUTTER)
|
||||
continue
|
||||
|
||||
if((HULK in mutations) && health >= 25)
|
||||
S.message = "[uppertext(S.message)]!!!"
|
||||
verb = pick("yells", "roars", "hollers")
|
||||
|
||||
if((HULK in mutations) && health >= 25 && length(message))
|
||||
message = "[uppertext(message)]!!!"
|
||||
verb = pick("yells","roars","hollers")
|
||||
speech_problem_flag = 1
|
||||
if(slurring)
|
||||
if(robot)
|
||||
S.message = slur(S.message, list("@", "!", "#", "$", "%", "&", "?"))
|
||||
else
|
||||
S.message = slur(S.message)
|
||||
verb = "slurs"
|
||||
|
||||
if(slurring)
|
||||
if(robot)
|
||||
message = slur(message, list("@", "!", "#", "$", "%", "&", "?"))
|
||||
else
|
||||
message = slur(message)
|
||||
verb = "slurs"
|
||||
speech_problem_flag = 1
|
||||
if(stuttering)
|
||||
if(robot)
|
||||
message = robostutter(message)
|
||||
else
|
||||
message = stutter(message)
|
||||
verb = "stammers"
|
||||
speech_problem_flag = 1
|
||||
if(cultslurring)
|
||||
message = cultslur(message)
|
||||
verb = "slurs"
|
||||
speech_problem_flag = 1
|
||||
if(!IsVocal())
|
||||
message = ""
|
||||
speech_problem_flag = 1
|
||||
if(stuttering)
|
||||
if(robot)
|
||||
S.message = robostutter(S.message)
|
||||
else
|
||||
S.message = stutter(S.message)
|
||||
verb = "stammers"
|
||||
|
||||
returns[1] = message
|
||||
returns[2] = verb
|
||||
returns[3] = speech_problem_flag
|
||||
return returns
|
||||
if(cultslurring)
|
||||
S.message = cultslur(S.message)
|
||||
verb = "slurs"
|
||||
|
||||
/mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios)
|
||||
if(!IsVocal())
|
||||
S.message = ""
|
||||
return list("verb" = verb)
|
||||
|
||||
/mob/living/proc/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
|
||||
switch(message_mode)
|
||||
if("whisper") //all mobs can whisper by default
|
||||
whisper_say(message, speaking)
|
||||
whisper_say(message_pieces)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -109,7 +106,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
return returns
|
||||
|
||||
|
||||
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
|
||||
/mob/living/say(var/message, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
|
||||
@@ -138,19 +135,17 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
message = trim_left(message)
|
||||
|
||||
//parse the language code and consume it
|
||||
if(!speaking)
|
||||
speaking = parse_language(message)
|
||||
if(speaking)
|
||||
message = copytext(message, 2 + length(speaking.key))
|
||||
else
|
||||
speaking = get_default_language()
|
||||
|
||||
// This is broadcast to all mobs with the language,
|
||||
// irrespective of distance or anything else.
|
||||
if(speaking && (speaking.flags & HIVEMIND))
|
||||
speaking.broadcast(src,trim(message))
|
||||
var/list/message_pieces = parse_languages(message)
|
||||
if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages
|
||||
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
|
||||
S.speaking.broadcast(src, S.message)
|
||||
return 1
|
||||
|
||||
|
||||
if(!LAZYLEN(message_pieces))
|
||||
log_runtime(EXCEPTION("Message failed to generate pieces. [message] - [json_encode(message_pieces)]"))
|
||||
return 0
|
||||
|
||||
if(message_mode == "cords")
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
@@ -160,7 +155,8 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
V.speak_with(message) //words come before actions
|
||||
return 1
|
||||
|
||||
verb = say_quote(message, speaking)
|
||||
var/datum/multilingual_say_piece/first_piece = message_pieces[1]
|
||||
verb = say_quote(message, first_piece.speaking)
|
||||
|
||||
if(is_muzzled())
|
||||
var/obj/item/clothing/mask/muzzle/G = wear_mask
|
||||
@@ -168,25 +164,19 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
|
||||
return
|
||||
else if(G.mute == MUZZLE_MUTE_MUFFLE)
|
||||
message = muffledspeech(message)
|
||||
muffledspeech_all(message_pieces)
|
||||
verb = "mumbles"
|
||||
|
||||
message = trim_left(message)
|
||||
if(!ignore_speech_problems)
|
||||
var/list/hsp = handle_speech_problems(message_pieces, verb)
|
||||
verb = hsp["verb"]
|
||||
|
||||
message = handle_autohiss(message, speaking)
|
||||
|
||||
if(!ignore_speech_problems && (speaking && !(speaking.flags & NO_STUTTER)))
|
||||
var/list/handle_s = handle_speech_problems(message, verb)
|
||||
message = handle_s[1]
|
||||
verb = handle_s[2]
|
||||
|
||||
if(!message || message == "")
|
||||
return 0
|
||||
|
||||
var/list/used_radios = list()
|
||||
if(handle_message_mode(message_mode, message, verb, speaking, used_radios))
|
||||
if(handle_message_mode(message_mode, message_pieces, verb, used_radios))
|
||||
return 1
|
||||
|
||||
|
||||
var/list/handle_v = handle_speech_sound()
|
||||
var/sound/speech_sound = handle_v[1]
|
||||
var/sound_vol = handle_v[2]
|
||||
@@ -198,11 +188,12 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
if(used_radios.len)
|
||||
italics = 1
|
||||
message_range = 1
|
||||
if(speaking)
|
||||
message_range = speaking.get_talkinto_msg_range(message)
|
||||
if(first_piece.speaking)
|
||||
message_range = first_piece.speaking.get_talkinto_msg_range(message)
|
||||
|
||||
var/msg
|
||||
if(!speaking || !(speaking.flags & NO_TALK_MSG))
|
||||
msg = "<span class='notice'>\The [src] talks into \the [used_radios[1]]</span>"
|
||||
if(!first_piece.speaking || !(first_piece.speaking.flags & NO_TALK_MSG))
|
||||
msg = "<span class='notice'>[src] talks into [used_radios[1]]</span>"
|
||||
|
||||
if(msg)
|
||||
for(var/mob/living/M in hearers(5, src) - src)
|
||||
@@ -213,16 +204,6 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
//handle nonverbal and sign languages here
|
||||
if(speaking)
|
||||
if(speaking.flags & NONVERBAL)
|
||||
if(prob(30))
|
||||
custom_emote(1, "[pick(speaking.signlang_verb)].")
|
||||
|
||||
if(speaking.flags & SIGNLANG)
|
||||
return say_signlang(message, pick(speaking.signlang_verb), speaking)
|
||||
|
||||
var/list/listening = list()
|
||||
var/list/listening_obj = list()
|
||||
|
||||
@@ -268,7 +249,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
var/speech_bubble_test = say_test(message)
|
||||
|
||||
for(var/mob/M in listening)
|
||||
M.hear_say(message, verb, speaking, italics, src, speech_sound, sound_vol)
|
||||
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol)
|
||||
if(M.client)
|
||||
speech_bubble_recipients.Add(M.client)
|
||||
spawn(0)
|
||||
@@ -281,19 +262,13 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
for(var/obj/O in listening_obj)
|
||||
spawn(0)
|
||||
if(O) //It's possible that it could be deleted in the meantime.
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
O.hear_talk(src, message_pieces, verb)
|
||||
|
||||
//Log of what we've said, plain message, no spans or junk
|
||||
say_log += message
|
||||
|
||||
log_say(message, src)
|
||||
return 1
|
||||
|
||||
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.hear_signlang(message, verb, language, src)
|
||||
return 1
|
||||
|
||||
/obj/effect/speech_bubble
|
||||
var/mob/parent
|
||||
|
||||
@@ -338,28 +313,19 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
message = trim_strip_html_properly(message)
|
||||
|
||||
//parse the language code and consume it
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if(speaking)
|
||||
message = copytext(message, 2 + length(speaking.key))
|
||||
else
|
||||
speaking = get_default_language()
|
||||
|
||||
// This is broadcast to all mobs with the language,
|
||||
// irrespective of distance or anything else.
|
||||
if(speaking && (speaking.flags & HIVEMIND))
|
||||
speaking.broadcast(src,trim(message))
|
||||
var/list/message_pieces = parse_languages(message)
|
||||
if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages
|
||||
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
|
||||
S.speaking.broadcast(src, S.message)
|
||||
return 1
|
||||
|
||||
message = trim_left(message)
|
||||
message = handle_autohiss(message, speaking)
|
||||
|
||||
whisper_say(message, speaking)
|
||||
whisper_say(message_pieces)
|
||||
|
||||
// for weird circumstances where you're inside an atom that is also you, like pai's
|
||||
/mob/living/proc/get_whisper_loc()
|
||||
return src
|
||||
|
||||
/mob/living/proc/whisper_say(var/message, var/datum/language/speaking = null, var/verb="whispers")
|
||||
/mob/living/proc/whisper_say(list/message_pieces, verb = "whispers")
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
|
||||
@@ -367,7 +333,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
|
||||
if(stat)
|
||||
if(stat == DEAD)
|
||||
return say_dead(message)
|
||||
return say_dead(message_pieces)
|
||||
return
|
||||
|
||||
if(is_muzzled())
|
||||
@@ -382,37 +348,29 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
var/watching_range = 5
|
||||
var/italics = 1
|
||||
var/adverb_added = FALSE
|
||||
|
||||
var/not_heard //the message displayed to people who could not hear the whispering
|
||||
if(speaking)
|
||||
if(speaking.whisper_verb)
|
||||
verb = speaking.whisper_verb
|
||||
|
||||
var/datum/multilingual_say_piece/first_piece = message_pieces[1]
|
||||
if(first_piece.speaking)
|
||||
if(first_piece.speaking.whisper_verb)
|
||||
verb = first_piece.speaking.whisper_verb
|
||||
not_heard = "[verb] something"
|
||||
else
|
||||
var/adverb = pick("quietly", "softly")
|
||||
adverb_added = TRUE
|
||||
verb = "[speaking.speech_verb] [adverb]"
|
||||
not_heard = "[speaking.speech_verb] something [adverb]"
|
||||
verb = "[first_piece.speaking.speech_verb] [adverb]"
|
||||
not_heard = "[first_piece.speaking.speech_verb] something [adverb]"
|
||||
else
|
||||
not_heard = "[verb] something"
|
||||
|
||||
message = trim(message)
|
||||
|
||||
var/speech_problem_flag = 0
|
||||
var/list/handle_s = handle_speech_problems(message, verb)
|
||||
message = handle_s[1]
|
||||
verb = handle_s[2]
|
||||
speech_problem_flag = handle_s[3]
|
||||
var/list/hsp = handle_speech_problems(message_pieces, verb)
|
||||
verb = hsp["verb"]
|
||||
if(verb == "yells loudly")
|
||||
verb = "slurs emphatically"
|
||||
|
||||
else if(speech_problem_flag && !adverb_added)
|
||||
else if(!adverb_added)
|
||||
var/adverb = pick("quietly", "softly")
|
||||
verb = "[verb] [adverb]"
|
||||
|
||||
if(!message)
|
||||
return
|
||||
|
||||
var/atom/whisper_loc = get_whisper_loc()
|
||||
var/list/listening = hear(message_range, whisper_loc)
|
||||
listening |= src
|
||||
@@ -450,7 +408,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
for(var/obj/O in view(message_range, whisper_loc))
|
||||
spawn(0)
|
||||
if(O)
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
O.hear_talk(src, message_pieces, verb)
|
||||
|
||||
var/list/eavesdropping = hearers(eavesdropping_range, whisper_loc)
|
||||
eavesdropping -= src
|
||||
@@ -463,17 +421,17 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
|
||||
//now mobs
|
||||
var/list/speech_bubble_recipients = list()
|
||||
var/speech_bubble_test = say_test(message)
|
||||
var/speech_bubble_test = say_test(multilingual_to_message(message_pieces))
|
||||
|
||||
for(var/mob/M in listening)
|
||||
M.hear_say(message, verb, speaking, italics, src)
|
||||
M.hear_say(message_pieces, verb, italics, src)
|
||||
if(M.client)
|
||||
speech_bubble_recipients.Add(M.client)
|
||||
|
||||
if(eavesdropping.len)
|
||||
var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
|
||||
stars_all(message_pieces) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
|
||||
for(var/mob/M in eavesdropping)
|
||||
M.hear_say(new_message, verb, speaking, italics, src)
|
||||
M.hear_say(message_pieces, verb, italics, src)
|
||||
if(M.client)
|
||||
speech_bubble_recipients.Add(M.client)
|
||||
|
||||
@@ -487,7 +445,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
for(var/mob/M in watching)
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
log_whisper(message, src)
|
||||
log_whisper(multilingual_to_message(message_pieces), src)
|
||||
return 1
|
||||
|
||||
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
|
||||
|
||||
@@ -1184,19 +1184,11 @@ var/list/ai_verbs_default = list(
|
||||
var/list/viewscale = getviewsize(client.view)
|
||||
return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5)
|
||||
|
||||
/mob/living/silicon/ai/proc/relay_speech(mob/living/M, text, verb, datum/language/speaking)
|
||||
if(!say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad.
|
||||
if(speaking)
|
||||
text = speaking.scramble(text)
|
||||
else
|
||||
text = stars(text)
|
||||
/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
|
||||
if(speaking)
|
||||
rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span></i>"
|
||||
else
|
||||
rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
|
||||
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [message]</span></i>"
|
||||
show_message(rendered, 2)
|
||||
|
||||
/mob/living/silicon/ai/proc/malfhacked(obj/machinery/power/apc/apc)
|
||||
|
||||
@@ -141,6 +141,6 @@
|
||||
acceleration = !acceleration
|
||||
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
|
||||
|
||||
/mob/camera/aiEye/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)
|
||||
/mob/camera/aiEye/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
|
||||
if(relay_speech)
|
||||
ai.relay_speech(speaker, message, verb, language)
|
||||
ai.relay_speech(speaker, message_pieces, verb)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
|
||||
/mob/living/silicon/ai/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
|
||||
/mob/living/silicon/ai/handle_track(var/message, var/verb = "says", var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
|
||||
if(hard_to_hear)
|
||||
return
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
ventcrawler = 2
|
||||
magpulse = 1
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
default_language = "Drone"
|
||||
|
||||
// We need to keep track of a few module items so we don't need to do list operations
|
||||
// every time we need them. These get set in New() after the module is chosen.
|
||||
@@ -38,7 +37,6 @@
|
||||
|
||||
|
||||
/mob/living/silicon/robot/drone/New()
|
||||
|
||||
..()
|
||||
|
||||
remove_language("Robot Talk")
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/mob/living/silicon/robot/drone/say(var/message, var/datum/language/speaking = null)
|
||||
/mob/living/silicon/robot/drone/say(var/message)
|
||||
if(copytext(message, 1, 2) == "*")
|
||||
return emote(copytext(message, 2))
|
||||
|
||||
if(!speaking)
|
||||
speaking = parse_language(message)
|
||||
if(!speaking)
|
||||
speaking = istype(get_default_language(), /datum/language) ? get_default_language() : GLOB.all_languages[get_default_language()]
|
||||
message = speaking.key + " " + message; // Prepend key to prevent the message from getting trimmed
|
||||
if(speaking)
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/drone/whisper_say(var/message, var/datum/language/speaking = null, var/verb="whispers")
|
||||
say(message) //drones do not get to whisper, only speak normally
|
||||
return 1
|
||||
/mob/living/silicon/robot/drone/whisper_say(list/message_pieces)
|
||||
say(multilingual_to_message(message_pieces)) //drones do not get to whisper, only speak normally
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/robot/drone/get_default_language()
|
||||
if(default_language)
|
||||
return default_language
|
||||
return GLOB.all_languages["Drone"]
|
||||
@@ -1,9 +1,9 @@
|
||||
/mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios)
|
||||
log_say(message, src)
|
||||
/mob/living/silicon/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
|
||||
log_say(multilingual_to_message(message_pieces), src)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios)
|
||||
/mob/living/silicon/robot/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
|
||||
if(..())
|
||||
return 1
|
||||
if(message_mode)
|
||||
@@ -13,14 +13,14 @@
|
||||
return 0
|
||||
if(message_mode == "general")
|
||||
message_mode = null
|
||||
return radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
return radio.talk_into(src,message_pieces,message_mode,verb)
|
||||
|
||||
/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios)
|
||||
/mob/living/silicon/ai/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
|
||||
if(..())
|
||||
return 1
|
||||
if(message_mode == "department")
|
||||
used_radios += aiRadio
|
||||
return holopad_talk(message, verb, speaking)
|
||||
return holopad_talk(message_pieces, verb)
|
||||
else if(message_mode)
|
||||
used_radios += aiRadio
|
||||
if(aiRadio.disabledAi || aiRestorePowerRoutine || stat)
|
||||
@@ -28,19 +28,19 @@
|
||||
return 0
|
||||
if(message_mode == "general")
|
||||
message_mode = null
|
||||
return aiRadio.talk_into(src,message,message_mode,verb,speaking)
|
||||
return aiRadio.talk_into(src, message_pieces, message_mode, verb)
|
||||
|
||||
/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios)
|
||||
/mob/living/silicon/pai/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
|
||||
if(..())
|
||||
return 1
|
||||
else if(message_mode == "whisper")
|
||||
whisper_say(message, speaking)
|
||||
whisper_say(message_pieces)
|
||||
return 1
|
||||
else if(message_mode)
|
||||
if(message_mode == "general")
|
||||
message_mode = null
|
||||
used_radios += radio
|
||||
return radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
return radio.talk_into(src, message_pieces, message_mode, verb)
|
||||
|
||||
/mob/living/silicon/say_quote(var/text)
|
||||
var/ending = copytext(text, length(text))
|
||||
@@ -70,41 +70,14 @@
|
||||
return ..()
|
||||
|
||||
//For holopads only. Usable by AI.
|
||||
/mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking)
|
||||
log_say("(HPAD) [message]", src)
|
||||
|
||||
message = trim(message)
|
||||
|
||||
if(!message)
|
||||
return
|
||||
/mob/living/silicon/ai/proc/holopad_talk(list/message_pieces, verb)
|
||||
log_say("(HPAD) [multilingual_to_message(message_pieces)]", src)
|
||||
|
||||
var/obj/machinery/hologram/holopad/T = current
|
||||
if(istype(T) && T.masters[src])
|
||||
|
||||
//Human-like, sorta, heard by those who understand humans.
|
||||
var/rendered_a
|
||||
//Speach 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.
|
||||
|
||||
|
||||
for(var/mob/M in hearers(T.loc))//The location is the object, default distance.
|
||||
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)
|
||||
/*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.*/
|
||||
M.hear_holopad_talk(message_pieces, verb, src)
|
||||
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
|
||||
to_chat(src, "No holopad connected.")
|
||||
return
|
||||
|
||||
@@ -704,21 +704,21 @@
|
||||
available_channels = list(":e")
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/parrot/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
|
||||
/mob/living/simple_animal/parrot/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios)
|
||||
if(message_mode && istype(ears))
|
||||
ears.talk_into(src, message, message_mode, verb, speaking)
|
||||
ears.talk_into(src, message_pieces, message_mode, verb)
|
||||
used_radios += ears
|
||||
|
||||
/mob/living/simple_animal/parrot/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null)
|
||||
/mob/living/simple_animal/parrot/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null)
|
||||
if(speaker != src && prob(50))
|
||||
parrot_hear(html_decode(message))
|
||||
parrot_hear(html_decode(multilingual_to_message(message_pieces)))
|
||||
..()
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/atom/follow_target)
|
||||
/mob/living/simple_animal/parrot/hear_radio(list/message_pieces, var/verb="says", var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/atom/follow_target)
|
||||
if(speaker != src && prob(50))
|
||||
parrot_hear(html_decode(message))
|
||||
parrot_hear(html_decode(multilingual_to_message(message_pieces)))
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
. = !(disabilities & DEAF)
|
||||
|
||||
// Whether the mob is able to see
|
||||
// `information_only` is for stuff that's purely informational - like understanding nonverbal languages, or blindness overlays
|
||||
// `information_only` is for stuff that's purely informational - like blindness overlays
|
||||
// This flag exists because certain things like angel statues expect this to be false for dead people
|
||||
/mob/living/has_vision(information_only = FALSE)
|
||||
return (information_only && stat == DEAD) || !(eye_blind || (disabilities & BLIND) || stat)
|
||||
|
||||
@@ -177,6 +177,10 @@
|
||||
p++
|
||||
return t
|
||||
|
||||
/proc/stars_all(list/message_pieces, pr)
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
S.message = stars(S.message, pr)
|
||||
|
||||
/proc/slur(phrase, var/list/slurletters = ("'"))//use a different list as an input if you want to make robots slur with $#@%! characters
|
||||
phrase = html_decode(phrase)
|
||||
var/leng=lentext(phrase)
|
||||
@@ -266,6 +270,11 @@
|
||||
|
||||
return returntext
|
||||
|
||||
/proc/Gibberish_all(list/message_pieces, p)
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
S.message = Gibberish(S.message, p)
|
||||
|
||||
|
||||
proc/muffledspeech(phrase)
|
||||
phrase = html_decode(phrase)
|
||||
var/leng=lentext(phrase)
|
||||
@@ -284,6 +293,10 @@ proc/muffledspeech(phrase)
|
||||
counter-=1
|
||||
return newphrase
|
||||
|
||||
/proc/muffledspeech_all(list/message_pieces)
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
S.message = muffledspeech(S.message)
|
||||
|
||||
|
||||
/proc/shake_camera(mob/M, duration, strength=1)
|
||||
if(!M || !M.client || M.shakecamera)
|
||||
|
||||
+72
-12
@@ -132,17 +132,77 @@
|
||||
|
||||
return null
|
||||
|
||||
//parses the language code (e.g. :j) from text, such as that supplied to say.
|
||||
//returns the language object only if the code corresponds to a language that src can speak, otherwise null.
|
||||
/mob/proc/parse_language(var/message)
|
||||
var/prefix = copytext(message, 1, 2)
|
||||
if(length(message) >= 1 && prefix == "!")
|
||||
return GLOB.all_languages["Noise"]
|
||||
/datum/multilingual_say_piece
|
||||
var/datum/language/speaking = null
|
||||
var/message = ""
|
||||
|
||||
if(length(message) >= 2)
|
||||
var/language_prefix = trim_right(lowertext(copytext(message, 1 ,4)))
|
||||
var/datum/language/L = GLOB.language_keys[language_prefix]
|
||||
if(can_speak_language(L))
|
||||
return L
|
||||
/datum/multilingual_say_piece/New(datum/language/new_speaking, new_message)
|
||||
. = ..()
|
||||
speaking = new_speaking
|
||||
if(new_message)
|
||||
message = new_message
|
||||
|
||||
return null
|
||||
/mob/proc/find_valid_prefixes(message)
|
||||
var/list/prefixes = list() // [["Common", start, end], ["Gutter", start, end]]
|
||||
for(var/i in 1 to length(message))
|
||||
var/selection = trim_right(lowertext(copytext(message, i, i + 3)))
|
||||
var/datum/language/L = GLOB.language_keys[selection]
|
||||
if(L != null && can_speak_language(L)) // What the fuck... remove the L != null check if you ever find out what the fuck is adding `null` to the languages list on absolutely random mobs... seriously what the hell...
|
||||
prefixes[++prefixes.len] = list(L, i, i + length(selection))
|
||||
else if(!L && i == 1)
|
||||
prefixes[++prefixes.len] = list(get_default_language(), i, i)
|
||||
else
|
||||
return prefixes
|
||||
|
||||
/proc/strip_prefixes(message)
|
||||
. = ""
|
||||
var/last_index = 1
|
||||
for(var/i in 1 to length(message))
|
||||
var/selection = trim_right(lowertext(copytext(message, i, i + 3)))
|
||||
var/datum/language/L = GLOB.language_keys[selection]
|
||||
if(L)
|
||||
. += copytext(message, last_index, i)
|
||||
last_index = i + 3
|
||||
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)
|
||||
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", keypos]
|
||||
|
||||
// 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)
|
||||
. = new /datum/multilingual_say_piece(L, trim(strip_prefixes(message)))
|
||||
break
|
||||
|
||||
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
|
||||
var/next = prefix_locations[i + 1] // We look ahead at the next message to see where we need to stop.
|
||||
var/spoke_message = handle_autohiss(trim(copytext(message, current[3], next[2])), L)
|
||||
. += new /datum/multilingual_say_piece(current[1], spoke_message)
|
||||
|
||||
/* These are here purely because it would be hell to try to convert everything over to using the multi-lingual system at once */
|
||||
/proc/message_to_multilingual(message, datum/language/speaking = null)
|
||||
. = list(new /datum/multilingual_say_piece(speaking, message))
|
||||
|
||||
/proc/multilingual_to_message(list/message_pieces)
|
||||
. = ""
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
. += S.message + " "
|
||||
. = trim_right(.)
|
||||
Reference in New Issue
Block a user