Worked Whisper into Say

It was annoying. And hard. But it's done.

For the most part anyway.
This commit is contained in:
Arokha Sieyes
2016-05-25 16:59:47 -04:00
parent 2aa0e29ae6
commit 4588498486
5 changed files with 104 additions and 192 deletions

View File

@@ -1,10 +1,10 @@
/mob/living/carbon/human/say(var/message)
/mob/living/carbon/human/say(var/message,var/whispering=0)
var/alt_name = ""
if(name != GetVoice())
alt_name = "(as [get_id_name("Unknown")])"
message = sanitize(message)
..(message, alt_name = alt_name)
..(message, alt_name = alt_name, whispering = whispering)
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
@@ -181,9 +181,6 @@
if(has_radio)
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))

View File

@@ -1,132 +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
usr << "\red Speech is currently admin-disabled."
return
message = sanitize(message)
log_whisper("[src.name]/[src.key] : [message]")
if (src.client)
if (src.client.prefs.muted & MUTE_IC)
src << "\red You cannot whisper (muted)."
return
if (src.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/verb="whispers")
if (is_muzzled())
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
var/adverb
if (speaking)
if (speaking.whisper_verb)
verb = speaking.whisper_verb
not_heard = "[verb] something"
else
adverb = pick("quietly", "softly")
verb = speaking.speech_verb
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
message = capitalize(trim(message))
//speech problems
if(!(speaking && (speaking.flags & NO_STUTTER)))
var/list/message_data = list(message, verb, 1)
if(handle_speech_problems(message_data))
message = message_data[1]
if(!message_data[3]) //if a speech problem like hulk forces someone to yell then everyone hears it
verb = message_data[2] //assume that if they are going to force not-whispering then they will set an appropriate verb too
message_range = world.view
else if(verb != message_data[2])
adverb = pick("quietly", "softly") //new verb given, so 'whisperize' it with an adverb
verb = message_data[2]
//consoldiate the adverb if we have one
if(adverb) verb = "[verb] [adverb]"
if(!message || message=="")
return
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.is_preference_enabled(/datum/client_preference/ghost_ears))
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, verb, 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/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) qdel(speech_bubble)
for(var/mob/M in listening)
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src)
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 << speech_bubble
M.hear_say(new_message, verb, speaking, alt_name, italics, src)
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

@@ -82,21 +82,18 @@ proc/get_radio_key_from_channel(var/channel)
/mob/living/proc/get_default_language()
return default_language
/mob/living/proc/is_muzzled()
return 0
//Takes a list of the form list(message, verb, whispering) and modifies it as needed
//Returns 1 if a speech problem was applied, 0 otherwise
/mob/living/proc/handle_speech_problems(var/list/message_data)
var/message = message_data[1]
var/verb = message_data[2]
var/whispering = message_data[3]
. = 0
if((HULK in mutations) && health >= 25 && length(message))
message = "[uppertext(message)]!!!"
verb = pick("yells","roars","hollers")
message_data[3] = 0
whispering = 0
. = 1
if(slurring)
message = slur(message)
@@ -109,6 +106,7 @@ proc/get_radio_key_from_channel(var/channel)
message_data[1] = message
message_data[2] = verb
message_data[2] = whispering
/mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
if(message_mode == "intercom")
@@ -130,33 +128,42 @@ proc/get_radio_key_from_channel(var/channel)
return "asks"
return verb
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="")
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/whispering = 0)
//If you're muted for IC chat
if(client)
if(client.prefs.muted & MUTE_IC)
src << "\red You cannot speak in IC (Muted)."
if((client.prefs.muted & MUTE_IC) || say_disabled)
src << "<span class='warning'>You cannot speak in IC (Muted).</span>"
return
//Redirect to say_dead if talker is dead
if(stat)
if(stat == 2)
if(stat == DEAD)
return say_dead(message)
return
//Parse the mode
var/message_mode = parse_message_mode(message, "headset")
//Maybe they are using say/whisper to do a quick emote, so do those
switch(copytext(message,1,2))
if("*") return emote(copytext(message,2))
if("^") return custom_emote(1, copytext(message,2))
//parse the radio code and consume it
//Parse the radio code and consume it
if (message_mode)
if (message_mode == "headset")
message = copytext(message,2) //it would be really nice if the parse procs could do this for us.
else if (message_mode == "whisper")
whispering = 1
message_mode = null
message = copytext(message,3)
else
message = copytext(message,3)
//Clean up any remaining space on the left
message = trim_left(message)
//parse the language code and consume it
//Parse the language code and consume it
if(!speaking)
speaking = parse_language(message)
if(speaking)
@@ -164,43 +171,72 @@ proc/get_radio_key_from_channel(var/channel)
else
speaking = get_default_language()
// This is broadcast to all mobs with the language,
// irrespective of distance or anything else.
//HIVEMIND languages always send to all people with that language
if(speaking && (speaking.flags & HIVEMIND))
speaking.broadcast(src,trim(message))
return 1
verb = say_quote(message, speaking)
//Self explanatory.
if(is_muzzled())
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
return
//Clean up any remaining junk on the left like spaces.
message = trim_left(message)
//Autohiss handles auto-rolling tajaran R's and unathi S's/Z's
message = handle_autohiss(message, speaking)
//Whisper vars
var/w_scramble_range = 5 //The range at which you get ***as*th**wi****
var/w_adverb //An adverb prepended to the verb in whispers
var/w_not_heard //The message for people in watching range
//Handle language-specific verbs and adverb setup if necessary
if(!whispering) //Just doing normal 'say' (for now, may change below)
verb = say_quote(message, speaking)
else if(whispering && speaking.whisper_verb) //Language has defined whisper verb
verb = speaking.whisper_verb
w_not_heard = "[verb] something"
else //Whispering but language has no whisper verb, use say verb
w_adverb = pick("quietly", "softly")
verb = speaking.speech_verb
w_not_heard = "[speaking.speech_verb] something [w_adverb]"
//For speech disorders (hulk, slurring, stuttering)
if(!(speaking && (speaking.flags & NO_STUTTER)))
var/list/message_data = list(message, verb, 0)
var/list/message_data = list(message, verb, whispering)
if(handle_speech_problems(message_data))
message = message_data[1]
verb = message_data[2]
whispering = message_data[3]
if(verb != message_data[2]) //They changed our verb
if(whispering)
w_adverb = pick("quietly", "softly")
verb = message_data[2]
//Whisper may have adverbs, add those if one was set
if(w_adverb) verb = "[verb] [w_adverb]"
//If something nulled or emptied the message, forget it
if(!message || message == "")
return 0
//Radio message handling
var/list/obj/item/used_radios = new
if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name))
if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, whispering))
return 1
//For languages with actual speech sounds
var/list/handle_v = handle_speech_sound()
var/sound/speech_sound = handle_v[1]
var/sound_vol = handle_v[2]
var/italics = 0
//Default range and italics, may be overridden past here
var/message_range = world.view
var/italics = 0
//speaking into radios
//Speaking into radios
if(used_radios.len)
italics = 1
message_range = 1
@@ -215,9 +251,13 @@ proc/get_radio_key_from_channel(var/channel)
if (speech_sound)
sound_vol *= 0.5
var/turf/T = get_turf(src)
//Set vars if we're still whispering by this point
if(whispering)
italics = 1
message_range = 1
sound_vol *= 0.5
//handle nonverbal and sign languages here
//Handle nonverbal and sign languages here
if (speaking)
if (speaking.flags & NONVERBAL)
if (prob(30))
@@ -226,42 +266,64 @@ proc/get_radio_key_from_channel(var/channel)
if (speaking.flags & SIGNLANG)
return say_signlang(message, pick(speaking.signlang_verb), speaking)
//These will contain the main receivers of the message
var/list/listening = list()
var/list/listening_obj = list()
//Atmosphere calculations (speaker's side only, for now)
var/turf/T = get_turf(src)
if(T)
//make sure the air can transmit speech - speaker's side
//Air is too thin to carry sound at all, contact speech only
var/datum/gas_mixture/environment = T.return_air()
var/pressure = (environment)? environment.return_pressure() : 0
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
//Air is nearing minimum levels, make text italics as a hint, and muffle sound
if (pressure < ONE_ATMOSPHERE*0.4)
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
var/list/results = get_mobs_and_objs_in_view_fast(T, message_range)
//Obtain the mobs and objects in the message range
var/list/results = get_mobs_and_objs_in_view_fast(T, world.view)
listening = results["mobs"]
listening_obj = results["objs"]
else
return 1 //If we're in nullspace, then forget it.
//The 'post-say' static speech bubble
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) qdel(speech_bubble)
//Main 'say' and 'whisper' message delivery
for(var/mob/M in listening)
try
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
catch(var/exception/e)
log_debug("hear_say exception on mob - [e] in [e.file]:[e.line]")
spawn(0) //Using spawns to queue all the messages for AFTER this proc is done, and stop runtimes
if(M && src) //If we still exist, when the spawn processes
var/dst = get_dist(get_turf(M),get_turf(src))
if(dst <= message_range) //Inside normal message range, FYI -1 is "from self to self" range
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
if(whispering) //Don't even bother with these unless whispering
if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range
M << speech_bubble
M.hear_say(stars(message), verb, speaking, alt_name, italics, src, speech_sound, sound_vol*0.2)
if(dst > w_scramble_range && dst <= world.view) //Inside whisper 'visible' range
M.show_message("<span class='game say'><span class='name'>[src.name]</span> [w_not_heard].</span>", 2)
//Object message delivery
for(var/obj/O in listening_obj)
try
O.hear_talk(src, message, verb, speaking)
catch(var/exception/e)
log_debug("hear_talk exception on obj - [e] in [e.file]:[e.line]")
spawn(0)
if(O && src) //If we still exist, when the spawn processes
var/dst = get_dist(get_turf(O),get_turf(src))
if(dst <= message_range)
O.hear_talk(src, message, verb, speaking)
log_say("[name]/[key] : [message]")
//Log the message to file
log_say("[name]/[key][whispering ? " (W)" : ""]: [message]")
return 1
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)

View File

@@ -1,29 +1,15 @@
/mob/proc/say()
return
/mob/verb/whisper()
/mob/verb/whisper(message as text)
set name = "Whisper"
set category = "IC"
return
usr.say(message,whispering=1)
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
if(say_disabled) //This is here to try to identify lag problems
usr << "\red Speech is currently admin-disabled."
return
//Let's try to make users fix their errors - we try to detect single, out-of-place letters and 'unintended' words
/*
var/first_letter = copytext(message,1,2)
if((copytext(message,2,3) == " " && first_letter != "I" && first_letter != "A" && first_letter != ";") || cmptext(copytext(message,1,5), "say ") || cmptext(copytext(message,1,4), "me ") || cmptext(copytext(message,1,6), "looc ") || cmptext(copytext(message,1,5), "ooc ") || cmptext(copytext(message,2,6), "say "))
var/response = alert(usr, "Do you really want to say this using the *say* verb?\n\n[message]\n", "Confirm your message", "Yes", "Edit message", "No")
if(response == "Edit message")
message = input(usr, "Please edit your message carefully:", "Edit message", message)
if(!message)
return
else if(response == "No")
return
*/
set_typing_indicator(0)
usr.say(message)
@@ -62,7 +48,7 @@
/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null)
if (src.stat == 2) //Dead
if (src.stat == DEAD)
return 1
//Universal speak makes everything understandable, for obvious reasons.

View File

@@ -1380,7 +1380,6 @@
#include "code\modules\mob\living\carbon\human\stripping.dm"
#include "code\modules\mob\living\carbon\human\unarmed_attack.dm"
#include "code\modules\mob\living\carbon\human\update_icons.dm"
#include "code\modules\mob\living\carbon\human\whisper.dm"
#include "code\modules\mob\living\carbon\human\species\species.dm"
#include "code\modules\mob\living\carbon\human\species\species_attack.dm"
#include "code\modules\mob\living\carbon\human\species\species_getters.dm"