Saycode refactor/improvements

- Refactored multiple bits of saycode to be less eyeburning code
 - Radios now properly report special channel messages (binary, hivemind)
 - Animals with no speak list no longer show unfiltered messages to
   everyone.

 - Fun part:
   - Improves handling of headsets for the two ear system.
     - The right headset will now be talked into if the left headset
       reports that it is unable to send the message on the chosen
       channel/mode.
     - This means that instead of having to swap headsets around, wearing
       a headset on either ear will grant you access to all of it's
       channels.
     - The left headset will take priority, which really only affects when
       it's set to a non-standard frequency.
This commit is contained in:
Tigercat2000
2016-07-18 19:17:11 -07:00
parent a28ae804b9
commit 9f8ba253c9
12 changed files with 174 additions and 160 deletions

View File

@@ -1,51 +1,54 @@
// At minimum every mob has a hear_say proc.
/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)
/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(!client)
return
return 0
if(speaker && !speaker.client && istype(src,/mob/dead/observer) && client.prefs.toggles & CHAT_GHOSTEARS && !speaker in view(src))
if(isobserver(src) && client.prefs.toggles & CHAT_GHOSTEARS)
if(speaker && !speaker.client && !(speaker in view(src)))
//Does the speaker have a client? It's either random stuff that observers won't care about (Experiment 97B says, 'EHEHEHEHEHEHEHE')
//Or someone snoring. So we make it where they won't hear it.
return
return 0
//make sure the air can transmit speech - hearer's side
var/turf/T = get_turf(src)
if((T) && (!(istype(src, /mob/dead/observer)))) //Ghosts can hear even in vacuum.
if(T && !isobserver(src))
var/datum/gas_mixture/environment = T.return_air()
var/pressure = (environment)? environment.return_pressure() : 0
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
return
return 0
if(pressure < ONE_ATMOSPHERE*0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = 1
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
sound_vol *= 0.5
if(sleeping || stat == 1)
if(sleeping || stat == UNCONSCIOUS)
hear_sleep(message)
return
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(!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
if(sdisabilities & BLIND || blinded) //blind people can't see dumbass
message = stars(message)
if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
if(!say_understands(speaker,language))
if(istype(speaker,/mob/living/simple_animal))
var/mob/living/simple_animal/S = speaker
if(S.speak.len)
message = pick(S.speak)
else
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
if(language)
message = language.scramble(message)
else
message = stars(message)
message = stars(message)
else
if(language)
message = language.scramble(message)
else
message = stars(message)
var/speaker_name = speaker.name
if(istype(speaker, /mob/living/carbon/human))
if(ishuman(speaker))
var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice()
@@ -53,7 +56,7 @@
message = "<i>[message]</i>"
var/track = null
if(istype(src, /mob/dead/observer))
if(isobserver(src))
if(italics && client.prefs.toggles & CHAT_GHOSTRADIO)
return
if(speaker_name != speaker.real_name && speaker.real_name)
@@ -78,12 +81,11 @@
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(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)
if(!client)
return
if(sleeping || stat==1) //If unconscious or sleeping
if(sleeping || stat == DEAD) //If unconscious or sleeping
hear_sleep(message)
return
@@ -93,25 +95,27 @@
//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)))
if(sdisabilities & BLIND || blinded) //blind people can't see dumbass
message = stars(message)
if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
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
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
if(language)
message = language.scramble(message)
else
message = stars(message)
return
else
if(language)
message = language.scramble(message)
else
message = stars(message)
if(hard_to_hear)
message = stars(message)
if(hard_to_hear)
message = stars(message)
var/speaker_name = "unknown"
if(speaker)

View File

@@ -165,7 +165,7 @@
return list(wear_mask, back, l_hand, r_hand)
/mob/proc/get_id_card()
for(var/obj/item/I in src.get_all_slots())
for(var/obj/item/I in get_all_slots())
. = I.GetID()
if(.)
break

View File

@@ -38,8 +38,7 @@
say(temp)
winset(client, "input", "text=[null]")
/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null)
/mob/living/carbon/human/say_understands(var/mob/other, var/datum/language/speaking = null)
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
return 1
@@ -51,21 +50,15 @@
if(istype(other, /mob/living/simple_animal/diona))
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
return 1
if(istype(other, /mob/living/silicon))
if(issilicon(other))
return 1
if(istype(other, /mob/living/simple_animal/bot))
if(isbot(other))
return 1
if(istype(other, /mob/living/carbon/brain))
if(isbrain(other))
return 1
if(istype(other, /mob/living/carbon/slime))
if(isslime(other))
return 1
//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 ..()
/mob/living/carbon/human/proc/HasVoiceChanger()
@@ -148,7 +141,7 @@
if(prob(braindam))
message = uppertext(message)
verb = "yells loudly"
if(locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs)
message = "<span class='sans'>[message]</span>"
@@ -166,57 +159,70 @@
used_radios += I
if("headset")
if(l_ear && istype(l_ear,/obj/item/device/radio))
var/obj/item/device/radio/R = l_ear
R.talk_into(src,message,null,verb,speaking)
used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio))
var/obj/item/device/radio/R = r_ear
R.talk_into(src,message,null,verb,speaking)
used_radios += r_ear
var/obj/item/device/radio/R = null
if(isradio(l_ear))
R = l_ear
if(R.talk_into(src, message, null, verb, speaking))
used_radios += R
return
if(isradio(r_ear))
R = r_ear
if(R.talk_into(src, message, null, verb, speaking))
used_radios += R
return
if("right ear")
var/obj/item/device/radio/R
var/has_radio = 0
if(r_ear && istype(r_ear,/obj/item/device/radio))
if(isradio(r_ear))
R = r_ear
has_radio = 1
if(r_hand && istype(r_hand, /obj/item/device/radio))
else if(isradio(r_hand))
R = r_hand
has_radio = 1
if(has_radio)
R.talk_into(src,message,null,verb,speaking)
used_radios += R
if(R)
if(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))
if(isradio(l_ear))
R = l_ear
has_radio = 1
if(l_hand && istype(l_hand,/obj/item/device/radio))
else if(isradio(l_hand))
R = l_hand
has_radio = 1
if(has_radio)
R.talk_into(src,message,null,verb,speaking)
used_radios += R
if(R)
if(R.talk_into(src, message, null, verb, speaking))
used_radios += R
if("whisper")
whisper_say(message, speaking, alt_name)
return 1
else
if(message_mode)
if(l_ear && istype(l_ear,/obj/item/device/radio))
l_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio))
r_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += r_ear
if(isradio(l_ear))
if(l_ear.talk_into(src, message, message_mode, verb, speaking))
used_radios += l_ear
return
if(isradio(r_ear))
if(r_ear.talk_into(src, message, message_mode, verb, speaking))
used_radios += r_ear
return
/mob/living/carbon/human/handle_speech_sound()
var/list/returns[2]
if(species.speech_sounds && prob(species.speech_chance))
returns[1] = sound(pick(species.speech_sounds))
returns[2] = 50
return returns
return returns
/mob/living/carbon/human/binarycheck()
. = FALSE
var/obj/item/device/radio/headset/R
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

@@ -803,8 +803,7 @@
"is pulling themselves apart!")
/datum/species/diona/can_understand(var/mob/other)
var/mob/living/simple_animal/diona/D = other
if(istype(D))
if(istype(other, /mob/living/simple_animal/diona))
return 1
return 0

View File

@@ -29,7 +29,7 @@ var/list/department_radio_keys = list(
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":Z" = "Service", "#Z" = "Service", ".Z" = "Service",
":P" = "AI Private", "#P" = "AI Private", ".P" = "AI Private",
":-" = "Special Ops", "#-" = "Special Ops", ".-" = "Special Ops"
":-" = "Special Ops", "#-" = "Special Ops", ".-" = "Special Ops"
)
@@ -48,22 +48,7 @@ proc/get_radio_key_from_channel(var/channel)
return key
/mob/living/proc/binarycheck()
if(istype(src, /mob/living/silicon/pai))
return
if(!ishuman(src))
return
var/mob/living/carbon/human/H = src
if(H.l_ear || H.r_ear)
var/obj/item/device/radio/headset/dongle
if(istype(H.l_ear,/obj/item/device/radio/headset))
dongle = H.l_ear
else
dongle = H.r_ear
if(!istype(dongle)) return
if(dongle.translate_binary) return 1
return FALSE
/mob/living/proc/get_default_language()
return default_language
@@ -123,27 +108,27 @@ proc/get_radio_key_from_channel(var/channel)
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb = "says", var/alt_name="")
if(client)
if(client.prefs.muted & MUTE_IC)
to_chat(src, "\red You cannot speak in IC (Muted).")
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
return
message = trim_strip_html_properly(message)
if(stat)
if(stat == 2)
if(stat == DEAD)
return say_dead(message)
return
var/message_mode = parse_message_mode(message, "headset")
if(copytext(message,1,2) == "*")
return emote(copytext(message,2))
if(copytext(message, 1, 2) == "*")
return emote(copytext(message, 2))
//parse the radio code and consume it
if(message_mode)
if(message_mode == "headset")
message = copytext(message,2) //it would be really nice if the parse procs could do this for us.
message = copytext(message, 2) //it would be really nice if the parse procs could do this for us.
else
message = copytext(message,3)
message = copytext(message, 3)
message = trim_left(message)
@@ -184,7 +169,7 @@ proc/get_radio_key_from_channel(var/channel)
if(!message || message == "")
return 0
var/list/obj/item/used_radios = new
var/list/used_radios = new
if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name))
return 1
@@ -204,11 +189,14 @@ proc/get_radio_key_from_channel(var/channel)
var/msg
if(!speaking || !(speaking.flags & NO_TALK_MSG))
msg = "<span class='notice'>\The [src] talks into \the [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)
if(speech_sound)
sound_vol *= 0.5
if(speech_sound)
sound_vol *= 0.5
var/turf/T = get_turf(src)
@@ -216,7 +204,7 @@ proc/get_radio_key_from_channel(var/channel)
if(speaking)
if(speaking.flags & NONVERBAL)
if(prob(30))
src.custom_emote(1, "[pick(speaking.signlang_verb)].")
custom_emote(1, "[pick(speaking.signlang_verb)].")
if(speaking.flags & SIGNLANG)
return say_signlang(message, pick(speaking.signlang_verb), speaking)
@@ -227,11 +215,11 @@ proc/get_radio_key_from_channel(var/channel)
if(T)
//make sure the air can transmit speech - speaker's side
var/datum/gas_mixture/environment = T.return_air()
var/pressure = (environment)? environment.return_pressure() : 0
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE)
message_range = 1
if(pressure < ONE_ATMOSPHERE*0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = 1
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
@@ -239,26 +227,26 @@ proc/get_radio_key_from_channel(var/channel)
var/list/hearturfs = list()
for(var/I in hear)
if(istype(I, /mob/))
if(ismob(I))
var/mob/M = I
listening += M
hearturfs += M.locs[1]
hearturfs += get_turf(M)
for(var/obj/O in M.contents)
listening_obj |= O
else if(istype(I, /obj/))
if(isobj(I))
var/obj/O = I
hearturfs += O.locs[1]
hearturfs += get_turf(O)
listening_obj |= O
for(var/mob/M in player_list)
if(!M.client)
continue //skip monkeys and leavers
if(istype(M, /mob/new_player))
if(isnewplayer(M))
continue
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS) && src.client) // src.client is so that ghosts don't have to listen to mice
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS) && client) // client is so that ghosts don't have to listen to mice
listening |= M
continue
if(M.loc && M.locs[1] in hearturfs)
if(get_turf(M) in hearturfs)
listening |= M
var/list/speech_bubble_recipients = list()
@@ -354,7 +342,7 @@ proc/get_radio_key_from_channel(var/channel)
return
if(stat)
if(stat == 2)
if(stat == DEAD)
return say_dead(message)
return
@@ -380,7 +368,7 @@ proc/get_radio_key_from_channel(var/channel)
verb = "[speaking.speech_verb] [adverb]"
not_heard = "[speaking.speech_verb] something [adverb]"
else
not_heard = "[verb] something" //TODO get rid of the null language and just prevent speech if language is null
not_heard = "[verb] something"
message = trim(message)
@@ -391,11 +379,12 @@ proc/get_radio_key_from_channel(var/channel)
speech_problem_flag = handle_s[3]
if(verb == "yells loudly")
verb = "slurs emphatically"
else if(speech_problem_flag)
var/adverb = pick("quietly", "softly")
verb = "[verb] [adverb]"
if(!message || message=="")
if(!message)
return
var/atom/whisper_loc = get_whisper_loc()
@@ -412,7 +401,7 @@ proc/get_radio_key_from_channel(var/channel)
//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))
if(isliving(C))
listening += C
//pass on the message to objects that can hear us.
@@ -452,11 +441,11 @@ proc/get_radio_key_from_channel(var/channel)
flick_overlay(I, speech_bubble_recipients, 30)
if(watching.len)
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
var/rendered = "<span class='game say'><span class='name'>[name]</span> [not_heard].</span>"
for(var/mob/M in watching)
M.show_message(rendered, 2)
log_whisper("[src.name]/[src.key] : [message]")
log_whisper("[name]/[key] : [message]")
return 1
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())

View File

@@ -53,13 +53,12 @@
say_dead_direct("[pick("complains", "moans", "whines", "laments", "blubbers", "salts")], <span class='message'>\"[message]\"</span>", src)
/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null)
if(src.stat == 2) //Dead
/mob/proc/say_understands(var/mob/other, var/datum/language/speaking = null)
if(stat == DEAD)
return 1
//Universal speak makes everything understandable, for obvious reasons.
else if(src.universal_speak || src.universal_understand)
if(universal_speak || universal_understand)
return 1
//Languages are handled after.
@@ -78,7 +77,7 @@
return 1
//Language check.
for(var/datum/language/L in src.languages)
for(var/datum/language/L in languages)
if(speaking.name == L.name)
return 1
@@ -92,9 +91,9 @@
if(speaking)
verb = speaking.get_spoken_verb(ending)
else
if(ending=="!")
verb = pick("exclaims","shouts","yells")
else if(ending=="?")
if(ending == "!")
verb = pick("exclaims", "shouts", "yells")
else if(ending == "?")
verb = "asks"
return verb
@@ -123,8 +122,8 @@
//parses the message mode code (e.g. :h, :w) from text, such as that supplied to say.
//returns the message mode string or null for no message mode.
//standard mode is the mode returned for the special ';' radio code.
/mob/proc/parse_message_mode(var/message, var/standard_mode="headset")
if(length(message) >= 1 && copytext(message,1,2) == ";")
/mob/proc/parse_message_mode(var/message, var/standard_mode = "headset")
if(length(message) >= 1 && copytext(message, 1, 2) == ";")
return standard_mode
if(length(message) >= 2)
@@ -136,7 +135,7 @@
//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)
var/prefix = copytext(message, 1, 2)
if(length(message) >= 1 && prefix == "!")
return all_languages["Noise"]