Whispering Refactor (#12755)

This commit is contained in:
Geeves
2021-12-27 23:44:57 +02:00
committed by GitHub
parent 4d3c06d78a
commit 1df88da53d
25 changed files with 160 additions and 217 deletions

View File

@@ -5,7 +5,7 @@
/mob/statue_mob/send_emote()
to_chat(src, "You are unable to move while trapped as a statue.")
/mob/statue_mob/say()
/mob/statue_mob/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
to_chat(src, "You are unable to speak while trapped as a statue.")
/obj/structure/closet/statue
@@ -192,4 +192,4 @@
dump_contents()
visible_message("<span class='warning'>\The [src] shatters!</span>")
qdel(src)
qdel(src)

View File

@@ -1,4 +1,4 @@
/mob/abstract/observer/say(var/message)
/mob/abstract/observer/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if (!message)
return

View File

@@ -156,10 +156,12 @@
/datum/language/proc/check_special_condition(var/mob/other)
return 1
/datum/language/proc/get_spoken_verb(var/msg_end, var/pre_end, var/singing = FALSE)
/datum/language/proc/get_spoken_verb(var/msg_end, var/pre_end, var/singing = FALSE, var/whisper = FALSE)
var/chosen_verb = speech_verb
if(singing)
return pick(sing_verb)
if(whisper)
return pick(whisper_verb)
switch(msg_end)
if("!")
if(pre_end == "!" || pre_end == "?")

View File

@@ -161,10 +161,8 @@
return
return attack_hand(user)
/mob/living/bot/say(var/message)
var/verb = "beeps"
..(message, null, verb)
/mob/living/bot/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
..(message, null, "beeps")
/mob/living/bot/Collide(atom/A)
if(on && botcard && istype(A, /obj/machinery/door))

View File

@@ -1,15 +1,14 @@
//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/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if (silent)
return
if(!(container && istype(container, /obj/item/device/mmi)))
return //No MMI, can't speak, bucko./N
else
var/datum/language/speaking = parse_language(message)
speaking = parse_language(message)
if(speaking)
message = copytext(message, 2+length(speaking.key))
var/verb = "says"
var/ending = copytext(message, length(message))
var/pre_ending = copytext(message, length(message) - 1, length(message))
if (speaking)

View File

@@ -109,12 +109,12 @@
for it but just ignore it.
*/
/mob/living/carbon/human/say_quote(var/message, var/datum/language/speaking = null, var/singing = FALSE)
/mob/living/carbon/human/say_quote(var/message, var/datum/language/speaking = null, var/singing = FALSE, var/whisper = FALSE)
var/ending = copytext(message, length(message))
var/pre_ending = copytext(message, length(message) - 1, length(message))
if(speaking)
. = speaking.get_spoken_verb(ending, pre_ending, singing)
. = speaking.get_spoken_verb(ending, pre_ending, singing, whisper)
else
. = ..()
@@ -163,7 +163,7 @@
/mob/living/carbon/human/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, successful_radio)
if(paralysis || InStasis())
whisper_say(message, speaking, alt_name)
whisper(message, speaking)
return TRUE
switch(message_mode)
if("intercom")
@@ -218,8 +218,8 @@
if(R.talk_into(src,message,null,verb,speaking))
successful_radio += R
if("whisper")
whisper_say(message, speaking, alt_name)
return 1
whisper(message, speaking)
return TRUE
else if(message_mode)
var/obj/item/device/radio/R = get_radio()
if(R)

View File

@@ -1,159 +0,0 @@
//Lallander was here
/mob/living/carbon/human/whisper(message as text)
var/alt_name = ""
if(say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='warning'>Speech is currently admin-disabled.</span>")
return
message = sanitize(message)
if (client && client.handle_spam_prevention(message,MUTE_IC))
return
if (src.stat == 2)
return src.say_dead(message)
if (src.stat)
return
if(name != GetVoice())
alt_name = "(as [get_id_name("Unknown")])"
//parse the language code and consume it
var/datum/language/speaking = parse_language(message)
if (speaking)
message = copytext(message,2+length(speaking.key))
whisper_say(message, speaking, alt_name)
//This is used by both the whisper verb and human/say() to handle whispering
/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/whisper_text = "whispers")
if (istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
var/message_range = 1
var/eavesdropping_range = 2
var/watching_range = 5
var/italics = 1
var/not_heard //the message displayed to people who could not hear the whispering
if(speaking)
if(speaking.whisper_verb)
whisper_text = pick(speaking.whisper_verb)
not_heard = "[whisper_text] something"
else
var/adverb = pick("quietly", "softly")
whisper_text = "[speaking.speech_verb] [adverb]"
not_heard = "[speaking.speech_verb] something [adverb]"
else
not_heard = "[whisper_text] something"
message = capitalize(trim(message))
if(speech_problem_flag)
var/list/handle_r = handle_speech_problems(message)
message = handle_r[1]
whisper_text = handle_r[2]
var/adverb = pick("quietly", "softly")
whisper_text = "[whisper_text] [adverb]"
speech_problem_flag = handle_r[3]
if(!message || message=="")
return
log_whisper("[key_name(src)] : ([get_lang_name(speaking)]) [message]",ckey=key_name(src))
//looks like this only appears in whisper. Should it be elsewhere as well? Maybe handle_speech_problems?
var/voice_sub
if(istype(back,/obj/item/rig))
var/obj/item/rig/rig = back
// todo: fix this shit
if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
voice_sub = rig.speech.voice_holder.voice
else
for(var/obj/item/gear in list(wear_mask,wear_suit,head))
if(!gear)
continue
var/obj/item/voice_changer/changer = locate() in gear
if(changer && changer.active && changer.voice)
voice_sub = changer.voice
if(voice_sub == "Unknown")
if(copytext(message, 1, 2) != "*")
var/list/temp_message = text2list(message, " ")
var/list/pick_list = list()
for(var/i = 1, i <= temp_message.len, i++)
pick_list += i
for(var/i=1, i <= abs(temp_message.len/3), i++)
var/H = pick(pick_list)
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
temp_message[H] = ninjaspeak(temp_message[H])
pick_list -= H
message = jointext(temp_message, " ")
message = replacetext(message, "o", "¤")
message = replacetext(message, "p", "ž")
message = replacetext(message, "l", "£")
message = replacetext(message, "s", "§")
message = replacetext(message, "u", "µ")
message = replacetext(message, "b", "ß")
var/list/listening = hearers(message_range, src)
listening |= src
//ghosts
for (var/mob/M in dead_mob_list) //does this include players who joined as observers as well?
if (!(M.client))
continue
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
listening |= M
//Pass whispers on to anything inside the immediate listeners.
for(var/mob/L in listening)
for(var/mob/C in L.contents)
if(istype(C,/mob/living))
listening += C
//pass on the message to objects that can hear us.
for (var/obj/O in view(message_range, src))
spawn (0)
if (O)
O.hear_talk(src, message, whisper_text, speaking)
var/list/eavesdropping = hearers(eavesdropping_range, src)
eavesdropping -= src
eavesdropping -= listening
var/list/watching = hearers(watching_range, src)
watching -= src
watching -= listening
watching -= eavesdropping
//now mobs
var/list/listening_clients = list() // The clients we're going to show the speech bubble to.
for(var/mob/M in listening)
M.hear_say(message, whisper_text, speaking, alt_name, italics, src)
if (M.client)
listening_clients += 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.
for(var/mob/M in eavesdropping)
M.hear_say(new_message, whisper_text, speaking, alt_name, italics, src)
if (M.client)
listening_clients += M.client
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image(get_talk_bubble(),src,"h[speech_bubble_test]")
INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, speech_bubble, listening_clients, 30)
if (watching.len)
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
for (var/mob/M in watching)
M.show_message(rendered, 2)

View File

@@ -1,6 +1,5 @@
/mob/living/carbon/slime/say(var/message)
var/verb = say_quote(message)
/mob/living/carbon/slime/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
verb = say_quote(message)
if(copytext(message,1,2) == "*")
return emote(copytext(message,2))

View File

@@ -103,7 +103,7 @@ var/controlling
qdel(src)
// When a meme speaks, it speaks through its host
/mob/living/parasite/meme/say(message as text)
/mob/living/parasite/meme/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(dormant)
to_chat(src, "<span class='notice'>You are dormant! </span>")
return

View File

@@ -3,7 +3,7 @@
real_name = "host brain"
universal_understand = 1
/mob/living/parasite/captive_brain/say(var/message)
/mob/living/parasite/captive_brain/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(istype(src.loc,/mob/living/parasite/meme))
if (!message)

View File

@@ -130,6 +130,9 @@ proc/get_radio_key_from_channel(var/channel)
used_radios += I
if(I.talk_into(src, message, verb, speaking))
successful_radio += I
if(message_mode == "whisper")
whisper(message, speaking)
return TRUE
return 0
/mob/living/proc/handle_speech_sound()
@@ -153,7 +156,7 @@ proc/get_radio_key_from_channel(var/channel)
return FONT_SIZE_LARGE
return null
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR)
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(stat)
if(stat == DEAD)
return say_dead(message)
@@ -177,13 +180,15 @@ proc/get_radio_key_from_channel(var/channel)
message = trim(message)
message = formalize_text(message)
var/had_speaking = !!speaking
//parse the language code and consume it
if(!speaking || speaking.always_parse_language)
speaking = parse_language(message)
if(speaking)
message = copytext(message,2+length(speaking.key))
else
speaking = get_default_language()
if(!had_speaking)
if(speaking)
message = copytext(message,2+length(speaking.key))
else
speaking = get_default_language()
if(speaking)
var/list/speech_mod = speaking.handle_message_mode(message_mode)
@@ -205,7 +210,7 @@ proc/get_radio_key_from_channel(var/channel)
speaking.broadcast(src,trim(message))
return 1
verb = say_quote(message, speaking, is_singing)
verb = say_quote(message, speaking, is_singing, whisper)
if(is_muzzled())
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
@@ -269,6 +274,10 @@ proc/get_radio_key_from_channel(var/channel)
var/list/listening_obj = list()
var/turf/T = get_turf(src)
if(whisper)
message_range = 1
italics = TRUE
if(T)
if(!speaking || !(speaking.flags & PRESSUREPROOF))
//make sure the air can transmit speech - speaker's side
@@ -305,7 +314,11 @@ proc/get_radio_key_from_channel(var/channel)
if(mind)
mind.last_words = message
log_say("[key_name(src)] : ([get_lang_name(speaking)]) [message]",ckey=key_name(src))
if(whisper)
log_whisper("[key_name(src)] : ([get_lang_name(speaking)]) [message]",ckey=key_name(src))
else
log_say("[key_name(src)] : ([get_lang_name(speaking)]) [message]",ckey=key_name(src))
return 1
/mob/living/proc/do_animate_chat(var/message, var/datum/language/language, var/small, var/list/show_to, var/duration)

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/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(silence_time)
to_chat(src, "<font color=green>Communication circuits remain uninitialized.</font>")
else
..(msg)
return
return ..()

View File

@@ -1,6 +1,3 @@
/mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
log_say("[key_name(src)] : [message]",ckey=key_name(src))
/mob/living/silicon/robot/handle_speech_problems(var/message, var/verb, var/message_mode)
var/speech_problem_flag = FALSE
//Handle gibberish when components are damaged
@@ -24,21 +21,27 @@
return returns
/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode == "whisper")
whisper(message, speaking)
return TRUE
if(message_mode)
if(!is_component_functioning("radio"))
to_chat(src, SPAN_WARNING("Your radio isn't functional at this time."))
return 0
if(message_mode == "general")
message_mode = null
log_say("[key_name(src)] : [message]",ckey=key_name(src))
return common_radio.talk_into(src, message, message_mode, verb, speaking)
/mob/living/silicon/robot/drone/handle_message_mode()
return null
/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode == "whisper")
whisper(message, speaking)
return TRUE
if(message_mode == "department")
log_say("[key_name(src)] : [message]",ckey=key_name(src))
return holopad_talk(message, verb, speaking)
else if(message_mode)
if(ai_radio.disabledAi || ai_restore_power_routine || stat)
@@ -46,16 +49,24 @@
return FALSE
if(message_mode == "general")
message_mode = null
log_say("[key_name(src)] : [message]",ckey=key_name(src))
return ai_radio.talk_into(src, message, message_mode, verb, speaking)
/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode)
if(message_mode == "whisper")
whisper(message, speaking)
return TRUE
if(message_mode == "general")
message_mode = null
log_say("[key_name(src)] : [message]",ckey=key_name(src))
return radio.talk_into(src, message, message_mode, verb, speaking)
/mob/living/silicon/say_quote(var/text)
/mob/living/silicon/say_quote(var/text, var/datum/language/speaking = null, var/singing = FALSE, var/whisper = FALSE)
if(singing)
return "sings"
if(whisper)
return "whispers"
var/ending = copytext(text, length(text))
if(ending == "?")
return speak_query

View File

@@ -6,7 +6,7 @@
var/datum/progressbar/resist_bar
var/resist_start_time = 0
/mob/living/captive_brain/say(var/message)
/mob/living/captive_brain/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(istype(src.loc,/mob/living/simple_animal/borer))
if(!message)
return

View File

@@ -1,4 +1,4 @@
/mob/living/simple_animal/borer/say(var/message)
/mob/living/simple_animal/borer/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
message = capitalize(message)
if(!message)

View File

@@ -318,6 +318,9 @@
/mob/living/simple_animal/spiderbot/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
switch(message_mode)
if("whisper")
whisper(message, speaking)
return TRUE
if("headset")
radio.talk_into(src, message, null, verb, speaking)
used_radios += radio
@@ -347,4 +350,4 @@
/mob/living/simple_animal/spiderbot/ai/Initialize()
. = ..()
internal_id.access = get_all_station_access()
internal_id.access = get_all_station_access()

View File

@@ -694,12 +694,11 @@
available_channels = list(":e")
. = ..()
/mob/living/simple_animal/parrot/say(var/message)
/mob/living/simple_animal/parrot/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(stat)
return
var/verb = "says"
if(speak_emote.len)
verb = pick(speak_emote)

View File

@@ -210,7 +210,7 @@
heard_dying_message = 0
to_chat(src, "<span class='notice'>The soothing echoes of life reinvigorate you.</span>")
/mob/living/simple_animal/shade/bluespace/say(var/message)
/mob/living/simple_animal/shade/bluespace/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(!possessive)
var/list/words_in_memory = dd_text2List(last_message_heard, " ")
var/list/words_in_message = dd_text2List(message, " ")

View File

@@ -754,8 +754,7 @@
/mob/living/simple_animal/proc/reset_sound_time()
sound_time = TRUE
/mob/living/simple_animal/say(var/message)
var/verb = "says"
/mob/living/simple_animal/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(speak_emote.len)
verb = pick(speak_emote)

View File

@@ -0,0 +1,75 @@
/mob/living/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
if(say_disabled)
to_chat(usr, SPAN_WARNING("Speech is currently admin-disabled."))
return
message = sanitize(message)
message = formalize_text(message)
set_typing_indicator(0)
if(client.handle_spam_prevention(message, MUTE_IC))
return
whisper(message)
/mob/living/proc/whisper(var/message, var/datum/language/speaking)
if(is_muzzled())
to_chat(src, SPAN_DANGER("You're muzzled and cannot speak!"))
return
speaking = speaking ? speaking : parse_language(message)
var/message_range = 1
var/eavesdropping_range = 2
var/watching_range = 5
var/whisper_text = "whispers"
var/not_heard = "[whisper_text] something"
if(speaking)
if(speaking.whisper_verb)
whisper_text = pick(speaking.whisper_verb)
not_heard = "[whisper_text] something"
else
var/adverb = pick("quietly", "softly")
whisper_text = "[speaking.speech_verb] [adverb]"
not_heard = "[speaking.speech_verb] something [adverb]"
var/list/listening = list(src)
//ghosts
for(var/mob/M in dead_mob_list)
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
listening |= M
//Pass whispers on to anything inside the immediate listeners.
for(var/mob/L in listening)
for(var/mob/living/C in L.contents)
listening += C
var/list/eavesdropping = list()
var/list/watching = list()
var/list/all_in_range = hearers(watching_range, src)
for(var/mob/M as anything in all_in_range)
if(get_dist(src, M) <= message_range)
listening |= M
else if(get_dist(src, M) <= eavesdropping_range)
eavesdropping += M
else if(get_dist(src, M) <= watching_range)
watching += M
if(length(eavesdropping))
var/new_message = stars(message)
for(var/mob/M in eavesdropping)
M.hear_say(new_message, "whispers", speaking, "", TRUE, src)
if(length(watching))
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
for (var/mob/M in watching)
M.show_message(rendered, 2)
say(message, speaking, whisper_text, whisper = TRUE)

View File

@@ -1,9 +1,4 @@
/mob/proc/say()
return
/mob/verb/whisper()
set name = "Whisper"
set category = "IC"
/mob/proc/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
return
/mob/verb/say_verb(message as text)
@@ -11,7 +6,7 @@
set category = "IC"
if(say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='warning'>Speech is currently admin-disabled.</span>")
to_chat(usr, SPAN_WARNING("Speech is currently admin-disabled."))
return
message = sanitize(message)
@@ -101,10 +96,12 @@
for it but just ignore it.
*/
/mob/proc/say_quote(var/message, var/datum/language/speaking = null, var/singing = FALSE)
/mob/proc/say_quote(var/message, var/datum/language/speaking = null, var/singing = FALSE, var/whisper = FALSE)
. = "says"
if(singing)
return "sings"
if(whisper)
return "whispers"
var/ending = copytext(message, length(message))
var/pre_ending = copytext(message, length(message) - 1, length(message))
if(ending == "!")

View File

@@ -58,7 +58,7 @@
if(body.stat == DEAD) // Body is dead, and won't get a life tick.
body.handle_shared_dreaming()
/mob/living/brain_ghost/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="")
/mob/living/brain_ghost/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
if(!istype(body) || body.stat!=UNCONSCIOUS)
return
if(prob(20)) // 1/5 chance to mumble out anything you say in the dream.

View File

@@ -262,7 +262,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
return 0
return 1
/spell/proc/invocation(mob/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount
/spell/proc/invocation(mob/living/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount
switch(invocation_type)
if(SpI_SHOUT)
@@ -353,4 +353,4 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
if(!user || (!(spell_flags & (STATALLOWED|GHOSTCAST)) && user.stat != originalstat) || !(user.loc == Location))
return 0
return 1
return 1