Skip to content

Commit

Permalink
[MIRROR] Let's you talk through action figures, plushies, and toy mec…
Browse files Browse the repository at this point in the history
…hs with `.l` and `.r`. Also a big clean up of `say` because its support for non-mobs was lackluster. (#1320)

* 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)

* 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.

* Modular

---------

Co-authored-by: MrMelbert <[email protected]>
Co-authored-by: Mal <[email protected]>
  • Loading branch information
3 people authored and StealsThePRs committed Mar 7, 2024
1 parent f80121f commit 2a16e67
Show file tree
Hide file tree
Showing 36 changed files with 342 additions and 135 deletions.
6 changes: 3 additions & 3 deletions code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@
#define ZIMPACT_NO_SPIN (1<<2)

/// From mob/living/try_speak(): (message, ignore_spam, forced)
#define COMSIG_LIVING_TRY_SPEECH "living_vocal_speech"
/// Return if the mob can speak the message, regardless of any other signal returns or checks.
#define COMPONENT_CAN_ALWAYS_SPEAK (1<<0)
#define COMSIG_MOB_TRY_SPEECH "living_vocal_speech"
/// Return to skip can_speak check, IE, forcing success. Overrides below.
#define COMPONENT_IGNORE_CAN_SPEAK (1<<0)
/// Return if the mob cannot speak.
#define COMPONENT_CANNOT_SPEAK (1<<1)

Expand Down
4 changes: 3 additions & 1 deletion code/__DEFINES/dcs/signals/signals_object.dm
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,11 @@

// /obj/item/radio signals

///called from base of /obj/item/proc/talk_into(): (atom/movable/speaker, message, channel, list/spans, language, list/message_mods)
#define COMSIG_ITEM_TALK_INTO "item_talk_into"
///called from base of /obj/item/radio/proc/set_frequency(): (list/args)
#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency"
///called from base of /obj/item/radio/proc/talk_into(): (atom/movable/M, message, channel)
///called from base of /obj/item/radio/talk_into(): (atom/movable/M, message, channel)
#define COMSIG_RADIO_NEW_MESSAGE "radio_new_message"
///called from base of /obj/item/radio/proc/on_receive_messgae(): (list/data)
#define COMSIG_RADIO_RECEIVE_MESSAGE "radio_receive_message"
Expand Down
10 changes: 8 additions & 2 deletions code/__DEFINES/say.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@

#define MODE_MAFIA "mafia"

/// Applies singing characters to the message
#define MODE_SING "sing"

/// A custom say emote is being supplied [value = the emote]
#define MODE_CUSTOM_SAY_EMOTE "custom_say"

/// No message is following, just emote
#define MODE_CUSTOM_SAY_ERASE_INPUT "erase_input"
/// Message is being relayed through another object
#define MODE_RELAY "relayed"

//Spans. Robot speech, italics, etc. Applied in compose_message().
#define SPAN_ROBOT "robot"
Expand All @@ -79,8 +82,11 @@
#define SPAN_HELIUM "small"

//bitflag #defines for return value of the radio() proc.
/// Makes the message use italics
#define ITALICS (1<<0)
/// Reduces the range of the message to 1
#define REDUCE_RANGE (1<<1)
/// Stops any actual message from being sent
#define NOPASS (1<<2)

/// Range to hear normal messages
Expand Down
3 changes: 2 additions & 1 deletion code/datums/brain_damage/split_personality.dm
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@
to_chat(src, span_notice("As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality."))
to_chat(src, span_warning("<b>Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.</b>"))

/mob/living/split_personality/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/split_personality/try_speak(message, ignore_spam, forced, filterproof)
SHOULD_CALL_PARENT(FALSE)
to_chat(src, span_warning("You cannot speak, your other self is controlling your body!"))
return FALSE

Expand Down
4 changes: 2 additions & 2 deletions code/datums/components/blob_minion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
RegisterSignal(parent, COMSIG_ATOM_FIRE_ACT, PROC_REF(on_burned))
RegisterSignal(parent, COMSIG_ATOM_TRIED_PASS, PROC_REF(on_attempted_pass))
RegisterSignal(parent, COMSIG_MOVABLE_SPACEMOVE, PROC_REF(on_space_move))
RegisterSignal(parent, COMSIG_LIVING_TRY_SPEECH, PROC_REF(on_try_speech))
RegisterSignal(parent, COMSIG_MOB_TRY_SPEECH, PROC_REF(on_try_speech))
RegisterSignal(parent, COMSIG_MOB_CHANGED_TYPE, PROC_REF(on_transformed))
living_parent.update_appearance(UPDATE_ICON)
GLOB.blob_telepathy_mobs |= parent
Expand All @@ -73,7 +73,7 @@
COMSIG_ATOM_FIRE_ACT,
COMSIG_ATOM_TRIED_PASS,
COMSIG_ATOM_UPDATE_ICON,
COMSIG_LIVING_TRY_SPEECH,
COMSIG_MOB_TRY_SPEECH,
COMSIG_MOB_CHANGED_TYPE,
COMSIG_MOB_GET_STATUS_TAB_ITEMS,
COMSIG_MOB_MIND_INITIALIZED,
Expand Down
6 changes: 3 additions & 3 deletions code/datums/components/chuunibyou.dm
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@
. = ..()
RegisterSignal(parent, COMSIG_MOB_SPELL_PROJECTILE, PROC_REF(on_spell_projectile))
RegisterSignal(parent, COMSIG_MOB_PRE_INVOCATION, PROC_REF(on_pre_invocation))
RegisterSignal(parent, COMSIG_LIVING_TRY_SPEECH, PROC_REF(on_try_speech))
RegisterSignal(parent, COMSIG_MOB_TRY_SPEECH, PROC_REF(on_try_speech))
RegisterSignal(parent, COMSIG_MOB_AFTER_SPELL_CAST, PROC_REF(on_after_spell_cast))

/datum/component/chuunibyou/UnregisterFromParent()
. = ..()
UnregisterSignal(parent, list(
COMSIG_MOB_SPELL_PROJECTILE,
COMSIG_MOB_PRE_INVOCATION,
COMSIG_LIVING_TRY_SPEECH,
COMSIG_MOB_TRY_SPEECH,
COMSIG_MOB_AFTER_SPELL_CAST,
))

Expand All @@ -63,7 +63,7 @@
SIGNAL_HANDLER

if(casting_spell)
return COMPONENT_CAN_ALWAYS_SPEAK
return COMPONENT_IGNORE_CAN_SPEAK

///signal sent when the parent casts a spell that has a projectile
/datum/component/chuunibyou/proc/on_spell_projectile(mob/living/source, datum/action/cooldown/spell/spell, atom/cast_on, obj/projectile/to_fire)
Expand Down
1 change: 1 addition & 0 deletions code/datums/components/marionette.dm
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
language = language,
forced = "[source]'s marionette",
saymode = saymode,
message_mods = list(MODE_RELAY = TRUE),
)
speech_args[SPEECH_RANGE] = WHISPER_RANGE

Expand Down
8 changes: 4 additions & 4 deletions code/datums/components/sign_language.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
carbon_parent.verb_yell = "emphatically signs"
carbon_parent.bubble_icon = "signlang"
RegisterSignal(carbon_parent, COMSIG_CARBON_GAIN_ORGAN, PROC_REF(on_added_organ))
RegisterSignal(carbon_parent, COMSIG_LIVING_TRY_SPEECH, PROC_REF(on_try_speech))
RegisterSignal(carbon_parent, COMSIG_MOB_TRY_SPEECH, PROC_REF(on_try_speech))
RegisterSignal(carbon_parent, COMSIG_LIVING_TREAT_MESSAGE, PROC_REF(on_treat_living_message))
RegisterSignal(carbon_parent, COMSIG_MOVABLE_USING_RADIO, PROC_REF(on_using_radio))
RegisterSignal(carbon_parent, COMSIG_MOVABLE_SAY_QUOTE, PROC_REF(on_say_quote))
Expand All @@ -106,7 +106,7 @@
carbon_parent.bubble_icon = initial(carbon_parent.bubble_icon)
UnregisterSignal(carbon_parent, list(
COMSIG_CARBON_GAIN_ORGAN,
COMSIG_LIVING_TRY_SPEECH,
COMSIG_MOB_TRY_SPEECH,
COMSIG_LIVING_TREAT_MESSAGE,
COMSIG_MOVABLE_USING_RADIO,
COMSIG_MOVABLE_SAY_QUOTE,
Expand All @@ -125,7 +125,7 @@
var/obj/item/organ/internal/tongue/new_tongue = new_organ
new_tongue.temp_say_mod = "signs"

/// Signal proc for [COMSIG_LIVING_TRY_SPEECH]
/// Signal proc for [COMSIG_MOB_TRY_SPEECH]
/// Sign languagers can always speak regardless of they're mute (as long as they're not mimes)
/datum/component/sign_language/proc/on_try_speech(mob/living/source, message, ignore_spam, forced)
SIGNAL_HANDLER
Expand Down Expand Up @@ -158,7 +158,7 @@

// Assuming none of the above fail, sign language users can speak
// regardless of being muzzled or mute toxin'd or whatever.
return COMPONENT_CAN_ALWAYS_SPEAK
return COMPONENT_IGNORE_CAN_SPEAK

/// Checks to see what state this person is in and if they are able to sign or not.
/datum/component/sign_language/proc/check_signables_state()
Expand Down
28 changes: 28 additions & 0 deletions code/datums/elements/toy_talk.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Allows people to talk via the item with .l or .r
*
* Be sure to override [/atom/movable/proc/GetVoice] if you want the item's "voice" to not default to itself
*/
/datum/element/toy_talk

/datum/element/toy_talk/Attach(datum/target)
. = ..()
if(!isitem(target))
return ELEMENT_INCOMPATIBLE

RegisterSignal(target, COMSIG_ITEM_TALK_INTO, PROC_REF(do_talk))

/datum/element/toy_talk/Detach(datum/source, ...)
. = ..()
UnregisterSignal(source, COMSIG_ITEM_TALK_INTO)

/datum/element/toy_talk/proc/do_talk(obj/item/source, mob/speaker, message, channel, list/spans, language, list/message_mods)
SIGNAL_HANDLER

if(!ismob(speaker) || message_mods[MODE_HEADSET] || message_mods[MODE_RELAY])
return NONE

message_mods[MODE_RELAY] = TRUE // Redundant (given NOPASS) but covers our bases
speaker.log_talk(message, LOG_SAY, tag = "toy talk ([source])")
source.say(message, language = language, sanitize = FALSE, message_mods = list(MODE_RELAY = TRUE))
return NOPASS
19 changes: 17 additions & 2 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,23 @@
playsound(src, block_sound, BLOCK_SOUND_VOLUME, vary = TRUE)
return TRUE

/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language, list/message_mods)
return ITALICS | REDUCE_RANGE
/**
* Handles someone talking INTO an item
*
* Commonly used by someone holding it and using .r or .l
* Also used by radios
*
* * speaker - the atom that is doing the talking
* * message - the message being spoken
* * channel - the channel the message is being spoken on, only really used for radios
* * spans - the spans of the message
* * language - the language the message is in
* * message_mods - any message mods that should be applied to the message
*
* Return a flag that modifies the original message
*/
/obj/item/proc/talk_into(atom/movable/speaker, message, channel, list/spans, datum/language/language, list/message_mods)
return SEND_SIGNAL(src, COMSIG_ITEM_TALK_INTO, speaker, message, channel, spans, language, message_mods) || (ITALICS|REDUCE_RANGE)

/// Called when a mob drops an item.
/obj/item/proc/dropped(mob/user, silent = FALSE)
Expand Down
22 changes: 17 additions & 5 deletions code/game/objects/items/devices/radio/radio.dm
Original file line number Diff line number Diff line change
Expand Up @@ -262,17 +262,29 @@

/obj/item/radio/talk_into(atom/movable/talking_movable, message, channel, list/spans, datum/language/language, list/message_mods)
if(SEND_SIGNAL(talking_movable, COMSIG_MOVABLE_USING_RADIO, src) & COMPONENT_CANNOT_USE_RADIO)
return
return NONE
if(SEND_SIGNAL(src, COMSIG_RADIO_NEW_MESSAGE, talking_movable, message, channel) & COMPONENT_CANNOT_USE_RADIO)
return
return NONE

if(!spans)
spans = list(talking_movable.speech_span)
if(!language)
language = talking_movable.get_selected_language()
INVOKE_ASYNC(src, PROC_REF(talk_into_impl), talking_movable, message, channel, spans.Copy(), language, message_mods)
INVOKE_ASYNC(src, PROC_REF(talk_into_impl), talking_movable, message, channel, LAZYLISTDUPLICATE(spans), language, LAZYLISTDUPLICATE(message_mods))
return ITALICS | REDUCE_RANGE

/**
* Handles talking into the radio
*
* Unlike most speech related procs, spans and message_mods are not guaranteed to be lists
*
* * talking_movable - the atom that is talking
* * message - the message to be spoken
* * channel - the channel to be spoken on
* * spans - the spans to be used, lazylist
* * language - the language to be spoken in. (Should) never be null
* * message_mods - the message mods to be used, lazylist
*/
/obj/item/radio/proc/talk_into_impl(atom/movable/talking_movable, message, channel, list/spans, datum/language/language, list/message_mods)
if(!on)
return // the device has to be on
Expand Down Expand Up @@ -358,9 +370,9 @@

/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
. = ..()
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range)
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range || message_mods[MODE_RELAY])
return
var/filtered_mods = list()
var/list/filtered_mods = list()

if (message_mods[MODE_SING])
filtered_mods[MODE_SING] = message_mods[MODE_SING]
Expand Down
3 changes: 3 additions & 0 deletions code/game/objects/items/devices/taperecorder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@

/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list(), message_range)
. = ..()
if(message_mods[MODE_RELAY])
return

if(mytape && recording)
mytape.timestamp += mytape.used_capacity
mytape.storedinfo += "\[[time2text(mytape.used_capacity,"mm:ss")]\] [raw_message]"
Expand Down
1 change: 1 addition & 0 deletions code/game/objects/items/plushes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
. = ..()
AddComponent(/datum/component/squeak, squeak_override)
AddElement(/datum/element/bed_tuckable, mapload, 6, -5, 90)
AddElement(/datum/element/toy_talk)

//have we decided if Pinocchio goes in the blue or pink aisle yet?
if(gender == NEUTER)
Expand Down
9 changes: 3 additions & 6 deletions code/game/objects/items/toy_mechs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
/obj/item/toy/mecha/Initialize(mapload)
. = ..()
AddElement(/datum/element/series, /obj/item/toy/mecha, "Mini-Mecha action figures")
AddElement(/datum/element/toy_talk)
combat_health = max_combat_health
switch(special_attack_type)
if(SPECIAL_ATTACK_DAMAGE)
Expand Down Expand Up @@ -263,12 +264,8 @@
if(wins || losses)
. += span_notice("This toy has [wins] wins, and [losses] losses.")

/**
* Override the say proc if they're mute
*/
/obj/item/toy/mecha/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(!quiet)
. = ..()
/obj/item/toy/mecha/can_speak(allow_mimes)
return !quiet && ..()

/**
* The 'master' proc of the mech battle. Processes the entire battle's events and makes sure it start and finishes correctly.
Expand Down
11 changes: 4 additions & 7 deletions code/game/objects/items/toys.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,7 @@
/obj/item/toy/figure/Initialize(mapload)
. = ..()
desc = "A \"Space Life\" brand [src]."
AddElement(/datum/element/toy_talk)

/obj/item/toy/figure/attack_self(mob/user as mob)
if(cooldown <= world.time)
Expand Down Expand Up @@ -1245,13 +1246,9 @@
to_chat(user, span_notice("You name the dummy as \"[doll_name]\"."))
name = "[initial(name)] - [doll_name]"

/obj/item/toy/dummy/talk_into(atom/movable/A, message, channel, list/spans, datum/language/language, list/message_mods)
var/mob/M = A
if (istype(M))
M.log_talk(message, LOG_SAY, tag="dummy toy")

say(message, language, sanitize = FALSE)
return NOPASS
/obj/item/toy/dummy/Initialize(mapload)
. = ..()
AddElement(/datum/element/toy_talk)

/obj/item/toy/dummy/GetVoice()
return doll_name
Expand Down
Loading

0 comments on commit 2a16e67

Please sign in to comment.