diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index dc4d5a25ea0..07954aab2f5 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -104,3 +104,8 @@ #define MOVABLE_SAY_QUOTE_MESSAGE 1 #define MOVABLE_SAY_QUOTE_MESSAGE_SPANS 2 #define MOVABLE_SAY_QUOTE_MESSAGE_MODS 3 + +/// Sent from /atom/movable/proc/compose_message() after the name part: (list/stored_name, visible_name) +#define COMSIG_MOVABLE_MESSAGE_GET_NAME_PART "movable_message_get_name_part" + ///The index of the name part + #define NAME_PART_INDEX 1 diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index f72e47db97a..d73b5e5daf0 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -131,6 +131,13 @@ ///from /mob/living/carbon/human/proc/force_say(): () #define COMSIG_HUMAN_FORCESAY "human_forcesay" +///from /mob/living/carbon/human/get_visible_name(), not sent if the mob has TRAIT_UNKNOWN: (identity) +#define COMSIG_HUMAN_GET_VISIBLE_NAME "human_get_visible_name" + //Index for the name of the face + #define VISIBLE_NAME_FACE 1 + //Index for the name of the id + #define VISIBLE_NAME_ID 2 + // Mob transformation signals ///Called when a human turns into a monkey, from /mob/living/carbon/proc/finish_monkeyize() #define COMSIG_HUMAN_MONKEYIZE "human_monkeyize" diff --git a/code/datums/components/crafting/misc.dm b/code/datums/components/crafting/misc.dm index dd850874d68..264ff981565 100644 --- a/code/datums/components/crafting/misc.dm +++ b/code/datums/components/crafting/misc.dm @@ -34,3 +34,13 @@ ) tool_paths = list(/obj/item/stamp/head/captain) category = CAT_MISC + +/datum/crafting_recipe/cardboard_id + name = "Cardboard ID Card" + tool_behaviors = list(TOOL_WIRECUTTER) + result = /obj/item/card/cardboard + time = 4 SECONDS + reqs = list( + /obj/item/stack/sheet/cardboard = 1, + ) + category = CAT_MISC diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index c4821a30523..ddaf61f3095 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -28,14 +28,28 @@ name = "card" desc = "Does card things." icon = 'icons/obj/card.dmi' + inhand_icon_state = "card-id" + lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' w_class = WEIGHT_CLASS_TINY - - var/list/files = list() + /// Cached icon that has been built for this card. Intended to be displayed in chat. Cardboards IDs and actual IDs use it. + var/icon/cached_flat_icon /obj/item/card/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] begins to swipe [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")) return BRUTELOSS +/obj/item/card/update_overlays() + . = ..() + cached_flat_icon = null + +/// If no cached_flat_icon exists, this proc creates it and crops it. This proc then returns the cached_flat_icon. Intended for use displaying ID card icons in chat. +/obj/item/card/proc/get_cached_flat_icon() + if(!cached_flat_icon) + cached_flat_icon = getFlatIcon(src) + cached_flat_icon.Crop(ID_ICON_BORDERS) + return cached_flat_icon + /* * ID CARDS */ @@ -45,17 +59,11 @@ name = "retro identification card" desc = "A card used to provide ID and determine access across the station." icon_state = "card_grey" - inhand_icon_state = "card-id" worn_icon_state = "nothing" - lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' slot_flags = ITEM_SLOT_ID armor_type = /datum/armor/card_id resistance_flags = FIRE_PROOF | ACID_PROOF - /// Cached icon that has been built for this card. Intended for use in chat. - var/icon/cached_flat_icon - /// The name registered on the card (for example: Dr Bryan See) var/registered_name = null /// Linked bank account. @@ -136,18 +144,6 @@ . = ..() . += list("[icon2html(get_cached_flat_icon(), user, extra_classes = "bigicon")]") -/obj/item/card/id/update_overlays() - . = ..() - - cached_flat_icon = null - -/// If no cached_flat_icon exists, this proc creates it and crops it. This proc then returns the cached_flat_icon. Intended only for use displaying ID card icons in chat. -/obj/item/card/id/proc/get_cached_flat_icon() - if(!cached_flat_icon) - cached_flat_icon = getFlatIcon(src) - cached_flat_icon.Crop(ID_ICON_BORDERS) - return cached_flat_icon - /obj/item/card/id/get_examine_string(mob/user, thats = FALSE) return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" @@ -1194,8 +1190,6 @@ desc = "You are a number, you are not a free man." icon_state = "card_prisoner" inhand_icon_state = "orange-id" - lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' registered_name = "Scum" registered_age = null trim = /datum/id_trim/job/prisoner @@ -1648,3 +1642,159 @@ #undef INTERN_THRESHOLD_FALLBACK_HOURS #undef ID_ICON_BORDERS #undef HOLOPAY_PROJECTION_INTERVAL + +#define INDEX_NAME_COLOR 1 +#define INDEX_ASSIGNMENT_COLOR 2 +#define INDEX_TRIM_COLOR 3 + +/** + * A fake ID card any silly-willy can craft with wirecutters, cardboard and a writing utensil + * Beside the gimmick of changing the visible name when worn, they do nothing. They cannot have an account. + * They don't fit in PDAs nor wallets, They have no access. They won't trick securitrons. They won't work with chameleon masks. + * Etcetera etcetera. Furthermore, talking, or getting examined on will pretty much give it away. + */ +/obj/item/card/cardboard + name = "cardboard identification card" + desc = "A card used to provice ID and det- Heeeey, wait a second, this is just a piece of cut cardboard!" + icon_state = "cardboard_id" + inhand_icon_state = "cardboard-id" + worn_icon_state = "nothing" + resistance_flags = FLAMMABLE + slot_flags = ITEM_SLOT_ID + ///The "name" of the "owner" of this "ID" + var/scribbled_name + ///The assignment written on this card. + var/scribbled_assignment + ///An icon state used as trim. + var/scribbled_trim + ///The colors for each of the above variables, for when overlays are updated. + var/details_colors = list("#000000", "#000000", "#000000") + +/obj/item/card/cardboard/equipped(mob/user, slot, initial = FALSE) + . = ..() + if(slot == ITEM_SLOT_ID) + RegisterSignal(user, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(return_visible_name)) + RegisterSignal(user, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, PROC_REF(return_message_name_part)) + +/obj/item/card/cardboard/dropped(mob/user, silent = FALSE) + . = ..() + UnregisterSignal(user, list(COMSIG_HUMAN_GET_VISIBLE_NAME, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART)) + +/obj/item/card/cardboard/proc/return_visible_name(mob/living/carbon/human/source, list/identity) + SIGNAL_HANDLER + identity[VISIBLE_NAME_ID] = scribbled_name + +/obj/item/card/cardboard/proc/return_message_name_part(mob/living/carbon/human/source, list/stored_name, visible_name) + SIGNAL_HANDLER + if(visible_name) + return + var/voice_name = source.GetVoice() + if(source.name != voice_name) + voice_name += " (as [scribbled_name])" + stored_name[NAME_PART_INDEX] = voice_name + +/obj/item/card/cardboard/attackby(obj/item/item, mob/living/user, params) + if(user.can_write(item, TRUE)) + INVOKE_ASYNC(src, PROC_REF(modify_card), user, item) + return TRUE + return ..() + +///Lets the user write a name, assignment or trim on the card, or reset it. Only the name is important for the component. +/obj/item/card/cardboard/proc/modify_card(mob/living/user, obj/item/item) + if(!user.mind) + return + var/popup_input = tgui_input_list(user, "What To Change", "Cardboard ID", list("Name", "Assignment", "Trim", "Reset")) + if(!after_input_check(user, item, popup_input)) + return + switch(popup_input) + if("Name") + var/input_name = tgui_input_text(user, "What name would you like to put on this card?", "Cardboard card name", scribbled_name || (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN) + input_name = sanitize_name(input_name, allow_numbers = TRUE) + if(!after_input_check(user, item, input_name, scribbled_name)) + return + scribbled_name = input_name + var/list/details = item.get_writing_implement_details() + details_colors[INDEX_NAME_COLOR] = details["color"] || "#000000" + if("Assignment") + var/input_assignment = tgui_input_text(user, "What assignment would you like to put on this card?", "Cardboard card job ssignment", scribbled_assignment || "Assistant", MAX_NAME_LEN) + if(!after_input_check(user, item, input_assignment, scribbled_assignment)) + return + scribbled_assignment = input_assignment + var/list/details = item.get_writing_implement_details() + details_colors[INDEX_ASSIGNMENT_COLOR] = details["color"] || "#000000" + if("Trim") + var/static/list/possible_trims + if(!possible_trims) + possible_trims = list() + for(var/trim_path in typesof(/datum/id_trim)) + var/datum/id_trim/trim = SSid_access.trim_singletons_by_path[trim_path] + if(trim?.trim_state && trim.assignment) + possible_trims |= replacetext(trim.trim_state, "trim_", "") + sortTim(possible_trims, GLOBAL_PROC_REF(cmp_typepaths_asc)) + var/input_trim = tgui_input_list(user, "Select trim to apply to your card.\nNote: This will not grant any trim accesses.", "Forge Trim", possible_trims) + if(!input_trim || !after_input_check(user, item, input_trim, scribbled_trim)) + return + scribbled_trim = "cardboard_[input_trim]" + var/list/details = item.get_writing_implement_details() + details_colors[INDEX_TRIM_COLOR] = details["color"] || "#000000" + if("Reset") + scribbled_name = null + scribbled_assignment = null + scribbled_trim = null + details_colors = list("#000000", "#000000", "#000000") + + update_appearance() + +///Checks that the conditions to be able to modify the cardboard card are still present after user input calls. +/obj/item/card/cardboard/proc/after_input_check(mob/living/user, obj/item/item, input, value) + if(!input || (value && input == value)) + return FALSE + if(QDELETED(user) || QDELETED(item) || QDELETED(src) || user.incapacitated() || !user.is_holding(item) || !user.CanReach(src) || !user.can_write(item)) + return FALSE + return TRUE + +/obj/item/card/cardboard/attack_self(mob/user) + if(!Adjacent(user)) + return + user.visible_message(span_notice("[user] shows you: [icon2html(src, viewers(user))] [name]."), span_notice("You show \the [name].")) + add_fingerprint(user) + +/obj/item/card/cardboard/update_name() + . = ..() + if(!scribbled_name) + name = initial(name) + return + name = "[scribbled_name]'s ID Card ([scribbled_assignment])" + +/obj/item/card/cardboard/update_overlays() + . = ..() + if(scribbled_name) + var/mutable_appearance/name_overlay = mutable_appearance(icon, "cardboard_name") + name_overlay.color = details_colors[INDEX_NAME_COLOR] + . += name_overlay + if(scribbled_assignment) + var/mutable_appearance/assignment_overlay = mutable_appearance(icon, "cardboard_assignment") + assignment_overlay.color = details_colors[INDEX_ASSIGNMENT_COLOR] + . += assignment_overlay + if(scribbled_trim) + var/mutable_appearance/frame_overlay = mutable_appearance(icon, "cardboard_frame") + frame_overlay.color = details_colors[INDEX_TRIM_COLOR] + . += frame_overlay + var/mutable_appearance/trim_overlay = mutable_appearance(icon, scribbled_trim) + trim_overlay.color = details_colors[INDEX_TRIM_COLOR] + . += trim_overlay + +/obj/item/card/cardboard/get_id_examine_strings(mob/user) + . = ..() + . += list("[icon2html(get_cached_flat_icon(), user, extra_classes = "bigicon")]") + +/obj/item/card/cardboard/get_examine_string(mob/user, thats = FALSE) + return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" + +/obj/item/card/cardboard/examine(mob/user) + . = ..() + . += span_notice("You could use a pen or crayon to forge a name, assignment or trim.") + +#undef INDEX_NAME_COLOR +#undef INDEX_ASSIGNMENT_COLOR +#undef INDEX_TRIM_COLOR diff --git a/code/game/objects/items/emags.dm b/code/game/objects/items/emags.dm index 84eb1d50139..56da7757c0a 100644 --- a/code/game/objects/items/emags.dm +++ b/code/game/objects/items/emags.dm @@ -11,9 +11,6 @@ desc = "It's a card with a magnetic strip attached to some circuitry." name = "cryptographic sequencer" icon_state = "emag" - inhand_icon_state = "card-id" - lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' item_flags = NO_MAT_REDEMPTION | NOBLUDGEON slot_flags = ITEM_SLOT_ID worn_icon_state = "emag" @@ -40,11 +37,8 @@ desc = "It's a card with a magnetic strip attached to some circuitry. Closer inspection shows that this card is a poorly made replica, with a \"Donk Co.\" logo stamped on the back." name = "cryptographic sequencer" icon_state = "emag" - inhand_icon_state = "card-id" slot_flags = ITEM_SLOT_ID worn_icon_state = "emag" - lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' /obj/item/card/emagfake/attack_self(mob/user) //for assistants with balls of plasteel if(Adjacent(user)) diff --git a/code/game/say.dm b/code/game/say.dm index 1a5c6525741..528c81c656d 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -104,7 +104,7 @@ GLOBAL_LIST_INIT(freqtospan, list( if(voice && found_client) INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), src, html_decode(tts_message_to_use), message_language, voice, filter.Join(","), listened, message_range = range, pitch = pitch, silicon = tts_silicon_voice_effect) -/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), face_name = FALSE, visible_name = FALSE) +/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), visible_name = FALSE) //This proc uses [] because it is faster than continually appending strings. Thanks BYOND. //Basic span var/spanpart1 = "" @@ -113,13 +113,11 @@ GLOBAL_LIST_INIT(freqtospan, list( //Radio freq/name display var/freqpart = radio_freq ? "\[[get_radio_name(radio_freq)]\] " : "" //Speaker name - var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]" - if(face_name && ishuman(speaker)) - var/mob/living/carbon/human/H = speaker - namepart = "[H.get_face_name()]" //So "fake" speaking like in hallucinations does not give the speaker away if disguised - else if(visible_name && ishuman(speaker)) - var/mob/living/carbon/human/human_speaker = speaker - namepart = "[human_speaker.get_visible_name()]" //For if the message can be seen but not heard, shows "speaker"'s visible identity (like when using sign language) + var/namepart + var/list/stored_name = list(null) + SEND_SIGNAL(speaker, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, stored_name, visible_name) + namepart = stored_name[NAME_PART_INDEX] || "[speaker.GetVoice()]" + //End name span. var/endspanpart = "" @@ -236,8 +234,6 @@ GLOBAL_LIST_INIT(freqtospan, list( /atom/movable/proc/GetVoice() return "[src]" //Returns the atom's name, prepended with 'The' if it's not a proper noun -/atom/movable/proc/get_alt_name() - //HACKY VIRTUALSPEAKER STUFF BEYOND THIS POINT //these exist mostly to deal with the AIs hrefs and job stuff. diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm index 064b77cb518..f8bef933790 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm @@ -94,13 +94,18 @@ if(ishuman(loc)) var/mob/living/carbon/human/wearer = loc new /obj/effect/temp_visual/dir_setting/ninja/cloak(get_turf(wearer), wearer.dir) - wearer.name_override = disguise.name + RegisterSignal(wearer, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(return_disguise_name)) wearer.icon = disguise.icon wearer.icon_state = disguise.icon_state wearer.cut_overlays() wearer.add_overlay(disguise.overlays) wearer.update_held_items() +/obj/item/clothing/suit/armor/abductor/vest/proc/return_disguise_name(mob/living/carbon/human/source, list/identity) + SIGNAL_HANDLER + identity[VISIBLE_NAME_FACE] = disguise.name + identity[VISIBLE_NAME_ID] = "" + /obj/item/clothing/suit/armor/abductor/vest/proc/DeactivateStealth() if(!stealth_active) return @@ -108,7 +113,7 @@ if(ishuman(loc)) var/mob/living/carbon/human/wearer = loc new /obj/effect/temp_visual/dir_setting/ninja(get_turf(wearer), wearer.dir) - wearer.name_override = null + UnregisterSignal(wearer, COMSIG_HUMAN_GET_VISIBLE_NAME) wearer.cut_overlays() wearer.regenerate_icons() diff --git a/code/modules/hallucination/fake_chat.dm b/code/modules/hallucination/fake_chat.dm index 47a99d2088b..049a337c110 100644 --- a/code/modules/hallucination/fake_chat.dm +++ b/code/modules/hallucination/fake_chat.dm @@ -34,7 +34,7 @@ humans += crew_mind.current if(humans.len) speaker = pick(humans) - + if(!speaker) return @@ -87,7 +87,7 @@ hallucinator.create_chat_message(speaker, understood_language, chosen, spans) // And actually show them the message, for real. - var/message = hallucinator.compose_message(speaker, understood_language, chosen, is_radio ? "[FREQ_COMMON]" : null, spans, face_name = TRUE) + var/message = hallucinator.compose_message(speaker, understood_language, chosen, is_radio ? "[FREQ_COMMON]" : null, spans, visible_name = TRUE) to_chat(hallucinator, message) // Then clean up. diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 26b070dc5c6..36dcc80fa12 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -61,8 +61,6 @@ var/special_voice = "" // For changing our voice. Used by a symptom. - var/name_override //For temporary visible name changes - var/datum/physiology/physiology var/list/datum/bioware/biowares diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index f61d19ff318..805dc01249a 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -58,12 +58,14 @@ //repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a separate proc as it'll be useful elsewhere /mob/living/carbon/human/get_visible_name() - var/face_name = get_face_name("") - var/id_name = get_id_name("") if(HAS_TRAIT(src, TRAIT_UNKNOWN)) return "Unknown" - if(name_override) - return name_override + var/list/identity = list(null, null) + SEND_SIGNAL(src, COMSIG_HUMAN_GET_VISIBLE_NAME, identity) + var/signal_face = LAZYACCESS(identity, VISIBLE_NAME_FACE) + var/signal_id = LAZYACCESS(identity, VISIBLE_NAME_ID) + var/face_name = !isnull(signal_face) ? signal_face : get_face_name("") + var/id_name = !isnull(signal_id) ? signal_id : get_id_name("") if(face_name) if(id_name && (id_name != face_name)) return "[face_name] (as [id_name])" diff --git a/code/modules/mob/living/carbon/human/human_say.dm b/code/modules/mob/living/carbon/human/human_say.dm index 7089e5ed048..27298f466dd 100644 --- a/code/modules/mob/living/carbon/human/human_say.dm +++ b/code/modules/mob/living/carbon/human/human_say.dm @@ -82,7 +82,3 @@ return ITALICS | REDUCE_RANGE return FALSE - -/mob/living/carbon/human/get_alt_name() - if(name != GetVoice()) - return " (as [get_id_name("Unknown")])" diff --git a/code/modules/mob/living/carbon/human/init_signals.dm b/code/modules/mob/living/carbon/human/init_signals.dm index 44a377c2b3d..9a4a55bb7ac 100644 --- a/code/modules/mob/living/carbon/human/init_signals.dm +++ b/code/modules/mob/living/carbon/human/init_signals.dm @@ -3,6 +3,7 @@ RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_UNKNOWN), SIGNAL_REMOVETRAIT(TRAIT_UNKNOWN)), PROC_REF(on_unknown_trait)) RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_DWARF), SIGNAL_REMOVETRAIT(TRAIT_DWARF)), PROC_REF(on_dwarf_trait)) + RegisterSignal(src, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, PROC_REF(get_name_part)) /// Gaining or losing [TRAIT_UNKNOWN] updates our name and our sechud /mob/living/carbon/human/proc/on_unknown_trait(datum/source) @@ -22,3 +23,18 @@ passtable_on(src, TRAIT_DWARF) else passtable_off(src, TRAIT_DWARF) + +///From compose_message(). Snowflake code converted into its own signal proc +/mob/living/carbon/human/proc/get_name_part(datum/source, list/stored_name, visible_name) + SIGNAL_HANDLER + /** + * For if the message can be seen but not heard, shows our visible identity (like when using sign language) + * Also used by hallucinations, so it doesn't give source's identity away. + */ + if(visible_name) + stored_name[NAME_PART_INDEX] = get_visible_name() + return + var/voice_name = GetVoice() + if(name != voice_name) + voice_name += " (as [get_id_name("Unknown")])" + stored_name[NAME_PART_INDEX] = voice_name diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 62a3f10f6b8..5c06bc69e39 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -288,7 +288,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) if(HAS_TRAIT(speaker, TRAIT_SIGN_LANG)) //Checks if speaker is using sign language - deaf_message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods, FALSE, TRUE) + deaf_message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods, TRUE) if(speaker != src) if(!radio_freq) //I'm about 90% sure there's a way to make this less cluttered diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 4fa56abf9b2..c0f093c38c6 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -893,7 +893,10 @@ var/treated_message = source.say_quote(raw_translation, spans, message_mods) var/start = "Relayed Speech: " - var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]" + var/namepart + var/list/stored_name = list(null) + SEND_SIGNAL(speaker, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, stored_name, FALSE) + namepart = stored_name[NAME_PART_INDEX] || "[speaker.GetVoice()]" var/hrefpart = "" var/jobpart = "Unknown" diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 9e1e3ecf138..5e2ef600a67 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1234,10 +1234,16 @@ * Proc that returns TRUE if the mob can write using the writing_instrument, FALSE otherwise. * * This proc a side effect, outputting a message to the mob's chat with a reason if it returns FALSE. + * Unless silent_if_not_writing_tool is TRUE. In that case it'll be silent if it isn't a writing implement/tool/instrument w/e. */ -/mob/proc/can_write(obj/item/writing_instrument) - if(!istype(writing_instrument)) - to_chat(src, span_warning("You can't write with the [writing_instrument]!")) +/mob/proc/can_write(obj/item/writing_instrument, silent_if_not_writing_tool = FALSE) + if(!writing_instrument) + return FALSE + + var/pen_info = writing_instrument.get_writing_implement_details() + if(!pen_info || (pen_info["interaction_mode"] != MODE_WRITING)) + if(!silent_if_not_writing_tool) + to_chat(src, span_warning("You can't write with the [writing_instrument]!")) return FALSE if(HAS_MIND_TRAIT(src, TRAIT_MIMING) && !istype(writing_instrument, /obj/item/toy/crayon/mime)) @@ -1252,11 +1258,6 @@ to_chat(src, span_warning("It's too dark in here to write anything!")) return FALSE - var/pen_info = writing_instrument.get_writing_implement_details() - if(!pen_info || (pen_info["interaction_mode"] != MODE_WRITING)) - to_chat(src, span_warning("You can't write with the [writing_instrument]!")) - return FALSE - if(has_gravity()) return TRUE diff --git a/icons/mob/inhands/equipment/idcards_lefthand.dmi b/icons/mob/inhands/equipment/idcards_lefthand.dmi index 53b40584e7b..90b96bd4d47 100644 Binary files a/icons/mob/inhands/equipment/idcards_lefthand.dmi and b/icons/mob/inhands/equipment/idcards_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/idcards_righthand.dmi b/icons/mob/inhands/equipment/idcards_righthand.dmi index 19a6f77c283..a4b0ec4bb74 100644 Binary files a/icons/mob/inhands/equipment/idcards_righthand.dmi and b/icons/mob/inhands/equipment/idcards_righthand.dmi differ diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index 95a5504f18c..a5c4e828301 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ