mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-09 16:33:50 +00:00
* Allows custom say emote (prefix*words) prefixes to be uppercase. (#74940) ## About The Pull Request Title. Removes a lowertext() call that forced custom say emotes to be lowercase.  ## Why It's Good For The Game 1. I fail to see a reason as to why custom say emotes must be forced to be lowercase. It was brought up that this breaks the formatting of normal say prefixes, but I would counter by saying this _isn't_ a normal prefix. In effect, it's more of an emote, and people can already make differently-cased prefixes by just emoting. 2. Radio emotes (; blah blah blah*) use this system, however, due to the fact that the way a radio emote is used is to make the entire emote a prefix (nothing is put after the *), the entire thing is always forced lowercase. Allowing radio emotes to be uppercase (and, to an extent, prefixes) simply increases the amount of fluidity in what people can say, and improves the control players have over their characters actions by unlocking more aspects of the english language. ## Changelog 🆑 add: Say emote prefixes are no longer forced to be lowercase. This includes radio emotes! /🆑 * Allows custom say emote (prefix*words) prefixes to be uppercase. --------- Co-authored-by: nikothedude <59709059+nikothedude@users.noreply.github.com> Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
229 lines
8.8 KiB
Plaintext
229 lines
8.8 KiB
Plaintext
//Speech verbs.
|
|
|
|
///what clients use to speak. when you type a message into the chat bar in say mode, this is the first thing that goes off serverside.
|
|
/mob/verb/say_verb(message as text)
|
|
set name = "Say"
|
|
set category = "IC"
|
|
set instant = TRUE
|
|
|
|
if(GLOB.say_disabled) //This is here to try to identify lag problems
|
|
to_chat(usr, span_danger("Speech is currently admin-disabled."))
|
|
return
|
|
|
|
//queue this message because verbs are scheduled to process after SendMaps in the tick and speech is pretty expensive when it happens.
|
|
//by queuing this for next tick the mc can compensate for its cost instead of having speech delay the start of the next tick
|
|
if(message)
|
|
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, TYPE_PROC_REF(/atom/movable, say), message), SSspeech_controller)
|
|
|
|
///Whisper verb
|
|
/mob/verb/whisper_verb(message as text)
|
|
set name = "Whisper"
|
|
set category = "IC"
|
|
set instant = TRUE
|
|
|
|
if(GLOB.say_disabled) //This is here to try to identify lag problems
|
|
to_chat(usr, span_danger("Speech is currently admin-disabled."))
|
|
return
|
|
|
|
if(message)
|
|
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, TYPE_PROC_REF(/mob, whisper), message), SSspeech_controller)
|
|
|
|
/**
|
|
* Whisper a message.
|
|
*
|
|
* Basic level implementation just speaks the message, nothing else.
|
|
*/
|
|
/mob/proc/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced, filterproof)
|
|
if(!message)
|
|
return
|
|
say(message, language = language)
|
|
|
|
///The me emote verb
|
|
/mob/verb/me_verb(message as text)
|
|
set name = "Me"
|
|
set category = "IC"
|
|
|
|
if(GLOB.say_disabled) //This is here to try to identify lag problems
|
|
to_chat(usr, span_danger("Speech is currently admin-disabled."))
|
|
return
|
|
|
|
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
|
|
|
|
QUEUE_OR_CALL_VERB_FOR(VERB_CALLBACK(src, TYPE_PROC_REF(/mob, emote), "me", 1, message, TRUE), SSspeech_controller)
|
|
|
|
/mob/try_speak(message, ignore_spam = FALSE, forced = null, filterproof = FALSE)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
if(!..())
|
|
return FALSE
|
|
var/list/filter_result
|
|
var/list/soft_filter_result
|
|
if(client && !forced && !filterproof)
|
|
//The filter doesn't act on the sanitized message, but the raw message.
|
|
filter_result = CAN_BYPASS_FILTER(src) ? null : is_ic_filtered(message)
|
|
if(!filter_result)
|
|
soft_filter_result = CAN_BYPASS_FILTER(src) ? null : is_soft_ic_filtered(message)
|
|
|
|
if(filter_result && !filterproof)
|
|
//The filter warning message shows the sanitized message though.
|
|
to_chat(src, span_warning("That message contained a word prohibited in IC chat! Consider reviewing the server rules."))
|
|
to_chat(src, span_warning("\"[message]\""))
|
|
REPORT_CHAT_FILTER_TO_USER(src, filter_result)
|
|
log_filter("IC", message, filter_result)
|
|
SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match))
|
|
return FALSE
|
|
|
|
if(soft_filter_result && !filterproof)
|
|
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
|
|
SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
|
|
log_filter("Soft IC", message, filter_result)
|
|
return FALSE
|
|
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
|
|
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
|
|
SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
|
|
log_filter("Soft IC (Passed)", message, filter_result)
|
|
|
|
if(client && !(ignore_spam || forced))
|
|
if(client.prefs.muted & MUTE_IC)
|
|
to_chat(src, span_danger("You cannot speak IC (muted)."))
|
|
return FALSE
|
|
if(client.handle_spam_prevention(message, MUTE_IC))
|
|
return FALSE
|
|
// Including can_speak() here would ignore COMPONENT_CAN_ALWAYS_SPEAK in /mob/living/try_speak()
|
|
return TRUE
|
|
|
|
///Speak as a dead person (ghost etc)
|
|
/mob/proc/say_dead(message)
|
|
var/name = real_name
|
|
var/alt_name = ""
|
|
|
|
if(GLOB.say_disabled) //This is here to try to identify lag problems
|
|
to_chat(usr, span_danger("Speech is currently admin-disabled."))
|
|
return
|
|
|
|
//SKYRAT EDIT ADDITION
|
|
if(!GLOB.dchat_allowed && !check_rights(R_ADMIN, FALSE))
|
|
to_chat(src, "<span class='danger'>Dead chat is currently muted.</span>")
|
|
return
|
|
//SKYRAT EDIT END
|
|
|
|
var/jb = is_banned_from(ckey, "Deadchat")
|
|
if(QDELETED(src))
|
|
return
|
|
|
|
if(jb)
|
|
to_chat(src, span_danger("You have been banned from deadchat."))
|
|
return
|
|
|
|
if (src.client)
|
|
if(src.client.prefs.muted & MUTE_DEADCHAT)
|
|
to_chat(src, span_danger("You cannot talk in deadchat (muted)."))
|
|
return
|
|
|
|
if(SSlag_switch.measures[SLOWMODE_SAY] && !HAS_TRAIT(src, TRAIT_BYPASS_MEASURES) && src == usr)
|
|
if(!COOLDOWN_FINISHED(client, say_slowmode))
|
|
to_chat(src, span_warning("Message not sent due to slowmode. Please wait [SSlag_switch.slowmode_cooldown/10] seconds between messages.\n\"[message]\""))
|
|
return
|
|
COOLDOWN_START(client, say_slowmode, SSlag_switch.slowmode_cooldown)
|
|
|
|
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
|
|
return
|
|
|
|
var/mob/dead/observer/O = src
|
|
if(isobserver(src) && O.deadchat_name)
|
|
name = "[O.deadchat_name]"
|
|
else
|
|
if(mind?.name)
|
|
name = "[mind.name]"
|
|
else
|
|
name = real_name
|
|
if(name != real_name)
|
|
alt_name = " (died as [real_name])"
|
|
|
|
var/spanned = say_quote(say_emphasis(message))
|
|
var/source = "<span class='game'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name]"
|
|
var/rendered = " <span class='message'>[emoji_parse(spanned)]</span></span>"
|
|
log_talk(message, LOG_SAY, tag="DEAD")
|
|
if(SEND_SIGNAL(src, COMSIG_MOB_DEADSAY, message) & MOB_DEADSAY_SIGNAL_INTERCEPT)
|
|
return
|
|
var/displayed_key = key
|
|
if(client?.holder?.fakekey)
|
|
displayed_key = null
|
|
deadchat_broadcast(rendered, source, follow_target = src, speaker_key = displayed_key)
|
|
|
|
///Check if this message is an emote
|
|
/mob/proc/check_emote(message, forced)
|
|
if(message[1] == "*")
|
|
emote(copytext(message, length(message[1]) + 1), intentional = !forced)
|
|
return TRUE
|
|
|
|
///Check if the mob has a hivemind channel
|
|
/mob/proc/hivecheck()
|
|
return FALSE
|
|
|
|
///The amount of items we are looking for in the message
|
|
#define MESSAGE_MODS_LENGTH 6
|
|
|
|
/mob/proc/check_for_custom_say_emote(message, list/mods)
|
|
var/customsaypos = findtext(message, "*")
|
|
if(!customsaypos)
|
|
return message
|
|
if (is_banned_from(ckey, "Emote"))
|
|
return copytext(message, customsaypos + 1)
|
|
mods[MODE_CUSTOM_SAY_EMOTE] = copytext_char(message, 1, customsaypos)
|
|
message = copytext(message, customsaypos + 1)
|
|
if (!message)
|
|
mods[MODE_CUSTOM_SAY_ERASE_INPUT] = TRUE
|
|
message = "an interesting thing to say"
|
|
return message
|
|
/**
|
|
* Extracts and cleans message of any extenstions at the begining of the message
|
|
* Inserts the info into the passed list, returns the cleaned message
|
|
*
|
|
* Result can be
|
|
* * SAY_MODE (Things like aliens, channels that aren't channels)
|
|
* * MODE_WHISPER (Quiet speech)
|
|
* * MODE_SING (Singing)
|
|
* * MODE_HEADSET (Common radio channel)
|
|
* * RADIO_EXTENSION the extension we're using (lots of values here)
|
|
* * RADIO_KEY the radio key we're using, to make some things easier later (lots of values here)
|
|
* * LANGUAGE_EXTENSION the language we're trying to use (lots of values here)
|
|
*/
|
|
/mob/proc/get_message_mods(message, list/mods)
|
|
for(var/I in 1 to MESSAGE_MODS_LENGTH)
|
|
// Prevents "...text" from being read as a radio message
|
|
if (length(message) > 1 && message[2] == message[1])
|
|
continue
|
|
|
|
var/key = message[1]
|
|
var/chop_to = 2 //By default we just take off the first char
|
|
if(key == "#" && !mods[WHISPER_MODE])
|
|
mods[WHISPER_MODE] = MODE_WHISPER
|
|
else if(key == "%" && !mods[MODE_SING])
|
|
mods[MODE_SING] = TRUE
|
|
else if(key == ";" && !mods[MODE_HEADSET])
|
|
if(stat == CONSCIOUS) //necessary indentation so it gets stripped of the semicolon anyway.
|
|
mods[MODE_HEADSET] = TRUE
|
|
else if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION])
|
|
mods[RADIO_KEY] = lowertext(message[1 + length(key)])
|
|
mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]]
|
|
chop_to = length(key) + 2
|
|
else if(key == "," && !mods[LANGUAGE_EXTENSION])
|
|
for(var/ld in GLOB.all_languages)
|
|
var/datum/language/LD = ld
|
|
if(initial(LD.key) == message[1 + length(message[1])])
|
|
// No, you cannot speak in xenocommon just because you know the key
|
|
if(!can_speak_language(LD))
|
|
return message
|
|
mods[LANGUAGE_EXTENSION] = LD
|
|
chop_to = length(key) + length(initial(LD.key)) + 1
|
|
if(!mods[LANGUAGE_EXTENSION])
|
|
return message
|
|
else
|
|
return message
|
|
message = trim_left(copytext_char(message, chop_to))
|
|
if(!message)
|
|
return
|
|
return message
|
|
|
|
#undef MESSAGE_MODS_LENGTH
|