Let's you talk through action figures, plushies, and toy mechs with .l and .r. Also a big clean up of say because its support for non-mobs was lackluster. (#81848)

This commit is contained in:
MrMelbert
2024-03-07 09:21:12 -07:00
committed by GitHub
parent 0733065c4e
commit 47dc38fee2
34 changed files with 316 additions and 133 deletions
+13 -1
View File
@@ -286,7 +286,19 @@ GLOBAL_LIST_EMPTY(blob_nodes)
blob_points = clamp(blob_points + points, 0, max_blob_points)
hud_used.blobpwrdisplay.maptext = MAPTEXT("<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#e36600'>[round(blob_points)]</font></div>")
/mob/camera/blob/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/mob/camera/blob/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if (!message)
return
@@ -113,7 +113,19 @@ the new instance inside the host to be updated to the template's stats.
for(var/datum/disease_ability/ability in purchased_abilities)
. += span_notice("[ability.name]")
/mob/camera/disease/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/mob/camera/disease/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if(!message)
return
if(sanitize)
+1 -1
View File
@@ -35,7 +35,7 @@
/obj/item/assembly/voice/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
. = ..()
if(message_mods[WHISPER_MODE]) //Too quiet lad
if(message_mods[WHISPER_MODE] || message_mods[MODE_RELAY]) //Too quiet lad
return FALSE
if(speaker == src)
return FALSE
+13 -2
View File
@@ -9,7 +9,19 @@
mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]]
return message
/mob/dead/observer/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/mob/dead/observer/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
message = trim(message) //trim now and sanitize after checking for special admin radio keys
var/list/filter_result = CAN_BYPASS_FILTER(src) ? null : is_ooc_filtered(message)
@@ -27,7 +39,6 @@
if(!message)
return
var/list/message_mods = list()
message = get_message_mods(message, message_mods)
if(client?.holder && (message_mods[RADIO_EXTENSION] == MODE_ADMIN || message_mods[RADIO_EXTENSION] == MODE_DEADMIN || (message_mods[RADIO_EXTENSION] == MODE_PUPPET && mind?.current)))
message = trim_left(copytext_char(message, length(message_mods[RADIO_KEY]) + 2))
@@ -47,12 +47,11 @@
/mob/living/basic/migo/proc/update_dodge_chance(health_ratio)
dodge_prob = LERP(50, 10, health_ratio)
/mob/living/basic/migo/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
..()
if(stat)
/mob/living/basic/migo/send_speech(message_raw, message_range, obj/source, bubble_type, list/spans, datum/language/message_language, list/message_mods, forced, tts_message, list/tts_filter)
. = ..()
if(stat != CONSCIOUS)
return
var/chosen_sound = pick(migo_sounds)
playsound(src, chosen_sound, 50, TRUE)
playsound(src, pick(migo_sounds), 50, TRUE)
/mob/living/basic/migo/Life(seconds_per_tick = SSMOBS_DT, times_fired)
..()
@@ -168,7 +168,19 @@
essencecolor = "#1D2953" //oh jeez you're dying
hud_used.healths.maptext = MAPTEXT("<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='[essencecolor]'>[essence]E</font></div>")
/mob/living/basic/revenant/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/mob/living/basic/revenant/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if(!message)
return
@@ -54,7 +54,7 @@
/mob/living/basic/statue/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_UNOBSERVANT, INNATE_TRAIT)
add_traits(list(TRAIT_MUTE, TRAIT_UNOBSERVANT), INNATE_TRAIT)
AddComponent(/datum/component/unobserved_actor, unobserved_flags = NO_OBSERVED_MOVEMENT | NO_OBSERVED_ATTACKS)
var/static/list/innate_actions = list(
@@ -69,14 +69,8 @@
/mob/living/basic/statue/med_hud_set_status()
return //we're a statue we're invincible
/mob/living/basic/statue/can_speak(allow_mimes = FALSE)
return FALSE // We're a statue, of course we can't talk.
// Cannot talk
/mob/living/basic/statue/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
return
// Turn to dust when gibbed
/mob/living/basic/statue/gib()
+21 -10
View File
@@ -1,14 +1,25 @@
/mob/living/brain/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterpoof = null, message_range = 7, datum/saymode/saymode = null)
if(!(container && istype(container, /obj/item/mmi)))
return //No MMI, can't speak, bucko./N
else
if(prob(emp_damage*4))
if(prob(10))//10% chane to drop the message entirely
return
else
message = Gibberish(message, emp_damage >= 12)//scrambles the message, gets worse when emp_damage is higher
/mob/living/brain/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if(prob(emp_damage * 4))
if(prob(10)) //10% chance to drop the message entirely
return
message = Gibberish(message, emp_damage >= 12)//scrambles the message, gets worse when emp_damage is higher
..()
return ..()
/mob/living/brain/can_speak(allow_mimes)
return istype(container, /obj/item/mmi) && ..()
/mob/living/brain/radio(message, list/message_mods = list(), list/spans, language)
if(message_mods[MODE_HEADSET] && istype(container, /obj/item/mmi))
@@ -1,6 +1,18 @@
/mob/living/carbon/human/say(message, bubble_type, list/spans, sanitize, datum/language/language, ignore_spam, forced, filterproof, message_range, datum/saymode/saymode)
/mob/living/carbon/human/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if(!HAS_TRAIT(src, TRAIT_SPEAKS_CLEARLY))
var/static/regex/tongueless_lower = new("\[gdntke]+", "g")
var/static/regex/tongueless_upper = new("\[GDNTKE]+", "g")
+17 -37
View File
@@ -94,13 +94,24 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
return new_msg
/mob/living/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/mob/living/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if(sanitize)
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message || message == "")
return
var/list/message_mods = list()
var/original_message = message
message = get_message_mods(message, message_mods)
saymode = SSradio.saymodes[message_mods[RADIO_KEY]]
@@ -206,7 +217,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
message = "[randomnote] [message] [randomnote]"
spans |= SPAN_SINGING
if(LAZYACCESS(message_mods,WHISPER_MODE)) // whisper away
if(message_mods[WHISPER_MODE]) // whisper away
spans |= SPAN_ITALICS
if(!message)
@@ -222,6 +233,9 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
return
var/radio_return = radio(message, message_mods, spans, language)//roughly 27% of living/say()'s total cost
if(radio_return & NOPASS)
return TRUE
if(radio_return & ITALICS)
spans |= SPAN_ITALICS
if(radio_return & REDUCE_RANGE)
@@ -229,8 +243,6 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
if(!message_mods[WHISPER_MODE])
message_mods[WHISPER_MODE] = MODE_WHISPER
message_mods[SAY_MOD_VERB] = say_mod(message, message_mods)
if(radio_return & NOPASS)
return TRUE
//No screams in space, unless you're next to someone.
var/turf/T = get_turf(src)
@@ -426,38 +438,6 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
/mob/proc/binarycheck()
return FALSE
/mob/living/try_speak(message, ignore_spam = FALSE, forced = null, filterproof = FALSE)
if(!..())
return FALSE
var/sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_TRY_SPEECH, message, ignore_spam, forced)
if(sigreturn & COMPONENT_CAN_ALWAYS_SPEAK)
return TRUE
if(sigreturn & COMPONENT_CANNOT_SPEAK)
return FALSE
if(!can_speak())
if(HAS_MIND_TRAIT(src, TRAIT_MIMING))
to_chat(src, span_green("Your vow of silence prevents you from speaking!"))
else
to_chat(src, span_warning("You find yourself unable to speak!"))
return FALSE
return TRUE
/mob/living/can_speak(allow_mimes = FALSE)
if(!allow_mimes && HAS_MIND_TRAIT(src, TRAIT_MIMING))
return FALSE
if(HAS_TRAIT(src, TRAIT_MUTE))
return FALSE
if(is_muzzled())
return FALSE
return TRUE
/**
* Treats the passed message with things that may modify speech (stuttering, slurring etc).
*
+14 -2
View File
@@ -1,5 +1,17 @@
/mob/living/silicon/ai/say(message, bubble_type,list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
if(parent && istype(parent) && parent.stat != DEAD) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
/mob/living/silicon/ai/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if(istype(parent) && parent.stat != DEAD) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
return parent.say(arglist(args))
return ..()
@@ -56,11 +56,8 @@
M.take_damage(50, BRUTE, MELEE, 1)
//Elites can't talk (normally)!
/mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
if(can_talk)
. = ..()
return TRUE
return FALSE
/mob/living/simple_animal/hostile/asteroid/elite/can_speak(allow_mimes)
return can_talk && ..()
/*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup.
While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/
@@ -63,9 +63,11 @@
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost()
icon_state = "herald_ghost"
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/mob/living/simple_animal/hostile/asteroid/elite/herald/send_speech(message_raw, message_range, obj/source, bubble_type, list/spans, datum/language/message_language, list/message_mods, forced, tts_message, list/tts_filter)
. = ..()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
if(stat != CONSCIOUS)
return
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
/datum/action/innate/elite_attack/herald_trishot
name = "Triple Shot"
+23 -4
View File
@@ -52,9 +52,6 @@
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)
@@ -88,9 +85,31 @@
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()
var/sigreturn = SEND_SIGNAL(src, COMSIG_MOB_TRY_SPEECH, message, ignore_spam, forced)
if(sigreturn & COMPONENT_IGNORE_CAN_SPEAK)
return TRUE
if(sigreturn & COMPONENT_CANNOT_SPEAK)
return FALSE
if(!..()) // the can_speak check
if(HAS_MIND_TRAIT(src, TRAIT_MIMING))
to_chat(src, span_green("Your vow of silence prevents you from speaking!"))
else
to_chat(src, span_warning("You find yourself unable to speak!"))
return FALSE
return TRUE
/mob/can_speak(allow_mimes = FALSE)
if(!allow_mimes && HAS_MIND_TRAIT(src, TRAIT_MIMING))
return FALSE
if(is_muzzled())
return FALSE
return ..()
///Speak as a dead person (ghost etc)
/mob/proc/say_dead(message)
var/name = real_name
+3 -7
View File
@@ -194,13 +194,9 @@
return
/obj/item/bodypart/head/talk_into(mob/holder, message, channel, spans, datum/language/language, list/message_mods)
var/mob/headholder = holder
if(istype(headholder))
headholder.log_talk(message, LOG_SAY, tag = "beheaded talk")
say(message, language, sanitize = FALSE)
return NOPASS
/obj/item/bodypart/head/Initialize(mapload)
. = ..()
AddElement(/datum/element/toy_talk)
/obj/item/bodypart/head/GetVoice()
return "The head of [real_name]"
+2 -2
View File
@@ -289,8 +289,8 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
GLOB.vending_machines_to_restock -= src
return ..()
/obj/machinery/vending/can_speak()
return !shut_up
/obj/machinery/vending/can_speak(allow_mimes)
return is_operational && !shut_up && ..()
/obj/machinery/vending/emp_act(severity)
. = ..()
@@ -20,16 +20,29 @@
new /obj/item/circuit_component/bci_core,
), SHELL_CAPACITY_SMALL, starting_circuit = circuit)
/obj/item/organ/internal/cyberimp/bci/say(message, bubble_type, list/spans, sanitize, datum/language/language, ignore_spam, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
/obj/item/organ/internal/cyberimp/bci/say(
message,
bubble_type,
list/spans = list(),
sanitize = TRUE,
datum/language/language,
ignore_spam = FALSE,
forced,
filterproof = FALSE,
message_range = 7,
datum/saymode/saymode,
list/message_mods = list(),
)
if (owner)
// Otherwise say_dead will be called.
// It's intentional that a circuit for a dead person does not speak from the shell.
if (owner.stat == DEAD)
return
owner.say(message, forced = "circuit speech")
else
return ..()
forced = "circuit speech"
return owner.say(arglist(args))
return ..()
/obj/item/organ/internal/cyberimp/bci/proc/action_comp_registered(datum/source, obj/item/circuit_component/equipment_action/action_comp)
SIGNAL_HANDLER