<commit_before>GLOBAL_LIST_INIT(department_radio_prefixes, list(":", "."))

GLOBAL_LIST_INIT(department_radio_keys, list(
	// Location
	"r" = "right hand",
	"l" = "left hand",
	"i" = "intercom",

	// Department
	"h" = "department",
	"c" = "Command",
	"n" = "Science",
	"m" = "Medical",
	"e" = "Engineering",
	"s" = "Security",
	"u" = "Supply",
	"v" = "Service",

	// Faction
	"t" = "Syndicate",
	"y" = "Centcom",

	// Species
	"b" = "binary",
	"g" = "changeling",
	"a" = "alientalk",

	// Admin
	"p" = "admin",
	"d" = "deadmin",

	// Misc
	"o" = "AI Private", // AI Upload channel
	"x" = "cords",		// vocal cords, used by Voice of God


	//kinda localization -- rastaf0
	//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
	// Location
	"" = "right hand",
	"" = "left hand",
	"" = "intercom",

	// Department
	"" = "department",
	"" = "Command",
	"" = "Science",
	"" = "Medical",
	"" = "Engineering",
	"" = "Security",
	"" = "Supply",
	"" = "Service",

	// Faction
	"" = "Syndicate",
	"" = "Centcom",

	// Species
	"" = "binary",
	"" = "changeling",
	"" = "alientalk",

	// Admin
	"" = "admin",
	"" = "deadmin",

	// Misc
	"" = "AI Private",
	"" = "cords"
))

/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null)
	var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
	var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)

	var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)

	if(sanitize)
		message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
	if(!message || message == "")
		return

	var/message_mode = get_message_mode(message)
	var/original_message = message
	var/in_critical = InCritical()

	if(one_character_prefix[message_mode])
		message = copytext(message, 2)
	else if(message_mode)
		message = copytext(message, 3)
	if(findtext(message, " ", 1, 2))
		message = copytext(message, 2)

	if(message_mode == "admin")
		if(client)
			client.cmd_admin_say(message)
		return

	if(message_mode == "deadmin")
		if(client)
			client.dsay(message)
		return

	if(stat == DEAD)
		say_dead(original_message)
		return

	if(check_emote(original_message) || !can_speak_basic(original_message))
		return

	if(in_critical)
		if(!(crit_allowed_modes[message_mode]))
			return
	else if(stat == UNCONSCIOUS)
		if(!(unconscious_allowed_modes[message_mode]))
			return

	// language comma detection.
	var/datum/language/message_language = get_message_language(message)
	if(message_language)
		// No, you cannot speak in xenocommon just because you know the key
		if(can_speak_in_language(message_language))
			language = message_language
		message = copytext(message, 3)

		// Trim the space if they said ",0 I LOVE LANGUAGES"
		if(findtext(message, " ", 1, 2))
			message = copytext(message, 2)

	if(!language)
		language = get_default_language()

	// Detection of language needs to be before inherent channels, because
	// AIs use inherent channels for the holopad. Most inherent channels
	// ignore the language argument however.

	if(handle_inherent_channels(message, message_mode, language)) //Hiveminds, binary chat & holopad.
		return

	if(!can_speak_vocal(message))
		to_chat(src, "<span class='warning'>You find yourself unable to speak!</span>")
		return

	var/message_range = 7

	var/succumbed = FALSE

	if(message_mode == MODE_WHISPER)
		message_range = 1
		spans |= SPAN_ITALICS
		log_whisper("[src.name]/[src.key] : [message]")
		if(in_critical)
			var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
			// If we cut our message short, abruptly end it with a-..
			var/message_len = length(message)
			message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
			message = Ellipsis(message, 10, 1)
			message_mode = MODE_WHISPER_CRIT
			succumbed = TRUE
	else
		log_say("[name]/[key] : [message]")

	message = treat_message(message)
	if(!message)
		return

	spans += get_spans()

	if(language)
		var/datum/language/L = GLOB.language_datums[language]
		if(!istype(L))
			L = new language
			GLOB.language_datums[language] = L

		spans |= L.spans

	//Log what we've said with an associated timestamp, using the list's len for safety/to prevent overwriting messages
	log_message(message, INDIVIDUAL_SAY_LOG)

	var/radio_return = radio(message, message_mode, spans)
	if(radio_return & ITALICS)
		spans |= SPAN_ITALICS
	if(radio_return & REDUCE_RANGE)
		message_range = 1<commit_msg>Fixes languages being understood over radio<commit_after>GLOBAL_LIST_INIT(department_radio_prefixes, list(":", "."))

GLOBAL_LIST_INIT(department_radio_keys, list(
	// Location
	"r" = "right hand",
	"l" = "left hand",
	"i" = "intercom",

	// Department
	"h" = "department",
	"c" = "Command",
	"n" = "Science",
	"m" = "Medical",
	"e" = "Engineering",
	"s" = "Security",
	"u" = "Supply",
	"v" = "Service",

	// Faction
	"t" = "Syndicate",
	"y" = "Centcom",

	// Species
	"b" = "binary",
	"g" = "changeling",
	"a" = "alientalk",

	// Admin
	"p" = "admin",
	"d" = "deadmin",

	// Misc
	"o" = "AI Private", // AI Upload channel
	"x" = "cords",		// vocal cords, used by Voice of God


	//kinda localization -- rastaf0
	//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
	// Location
	"" = "right hand",
	"" = "left hand",
	"" = "intercom",

	// Department
	"" = "department",
	"" = "Command",
	"" = "Science",
	"" = "Medical",
	"" = "Engineering",
	"" = "Security",
	"" = "Supply",
	"" = "Service",

	// Faction
	"" = "Syndicate",
	"" = "Centcom",

	// Species
	"" = "binary",
	"" = "changeling",
	"" = "alientalk",

	// Admin
	"" = "admin",
	"" = "deadmin",

	// Misc
	"" = "AI Private",
	"" = "cords"
))

/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null)
	var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
	var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)

	var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)

	if(sanitize)
		message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
	if(!message || message == "")
		return

	var/message_mode = get_message_mode(message)
	var/original_message = message
	var/in_critical = InCritical()

	if(one_character_prefix[message_mode])
		message = copytext(message, 2)
	else if(message_mode)
		message = copytext(message, 3)
	if(findtext(message, " ", 1, 2))
		message = copytext(message, 2)

	if(message_mode == "admin")
		if(client)
			client.cmd_admin_say(message)
		return

	if(message_mode == "deadmin")
		if(client)
			client.dsay(message)
		return

	if(stat == DEAD)
		say_dead(original_message)
		return

	if(check_emote(original_message) || !can_speak_basic(original_message))
		return

	if(in_critical)
		if(!(crit_allowed_modes[message_mode]))
			return
	else if(stat == UNCONSCIOUS)
		if(!(unconscious_allowed_modes[message_mode]))
			return

	// language comma detection.
	var/datum/language/message_language = get_message_language(message)
	if(message_language)
		// No, you cannot speak in xenocommon just because you know the key
		if(can_speak_in_language(message_language))
			language = message_language
		message = copytext(message, 3)

		// Trim the space if they said ",0 I LOVE LANGUAGES"
		if(findtext(message, " ", 1, 2))
			message = copytext(message, 2)

	if(!language)
		language = get_default_language()

	// Detection of language needs to be before inherent channels, because
	// AIs use inherent channels for the holopad. Most inherent channels
	// ignore the language argument however.

	if(handle_inherent_channels(message, message_mode, language)) //Hiveminds, binary chat & holopad.
		return

	if(!can_speak_vocal(message))
		to_chat(src, "<span class='warning'>You find yourself unable to speak!</span>")
		return

	var/message_range = 7

	var/succumbed = FALSE

	if(message_mode == MODE_WHISPER)
		message_range = 1
		spans |= SPAN_ITALICS
		log_whisper("[src.name]/[src.key] : [message]")
		if(in_critical)
			var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
			// If we cut our message short, abruptly end it with a-..
			var/message_len = length(message)
			message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
			message = Ellipsis(message, 10, 1)
			message_mode = MODE_WHISPER_CRIT
			succumbed = TRUE
	else
		log_say("[name]/[key] : [message]")

	message = treat_message(message)
	if(!message)
		return

	spans += get_spans()

	if(language)
		var/datum/language/L = GLOB.language_datums[language]
		if(!istype(L))
			L = new language
			GLOB.language_datums[language] = L

		spans |= L.spans

	//Log what we've said with an associated timestamp, using the list's len for safety/to prevent overwriting messages
	log_message(message, INDIVIDUAL_SAY_LOG)

	var/radio_return = radio(message, message_mode, spans, language)
	if(radio_return & ITALICS)
		spans |= SPAN_ITALICS
	if(radio_return & REDUCE_RANGE)
		message_range = 1
{'fraction_non_alphanumeric': 0.14984742807323453, 'fraction_numerical': 0.005013077593722755, 'mean_word_length': 4.205331820760068, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5154683', 'n_tokens_mistral': 3655, 'n_tokens_neox': 3348, 'n_words': 747}