Adds cardboard IDs to the game: The broke man's agent ID. (#76682)

## About The Pull Request
This PR adds a new craftable item to the game that, in a way, works
somewhat like ID cards, as in it gives the wearer an identity of some
sort, and that can be modified similardly to the agent ID, but...

It doesn't provide access.
It doesn't trick security bots and turrets.
It doesn't work with chameleon masks.
It doesn't have a bank account.
It doesn't fit inside wallets or PDAs.
It doesn't show a trim (it's just cosmetic) on the security HUD.
It doesn't look like an ID card.

(It does however, synergizes well with sign language and face-covering
mask, but in the face of all the things id doesn't do, should I change
that? idk)

Basically, it's not an ID, it's just a piece of cardboard with name and
job written on it.

![aww](https://github.com/tgstation/tgstation/assets/42542238/b33ddb38-a11d-41d9-8085-2c719a2c4d48)

![(null)scrnshot1](https://github.com/tgstation/tgstation/assets/42542238/00a53379-70f6-4105-9cca-cff75d0e4144)

## Why It's Good For The Game
Often, player shenanigeans rely on ID cards with gimmicky names and jobs
to advertise themselves or provide a (feeble) disguise for it.
The idea is to provide players a cheap tool for their tomfoolery, that
doesn't get much in the way of balance. Compared to actual IDs,
cardboard IDs' only advantage is the fact they're more easily
produceable.

Also this PR converts a bit of snowflakey code into signals, and fixes
the name part in hallucination messages being shown "Unknown" while the
speaker is wearing a mask but also an ID.

## Changelog

🆑
add: Added cardboard IDs to the game. They can be crafted with a
cardboard sheet and wirecutters and modified with a writing tool. While
worn, these will modify the visible name of the wearer just like actual
IDs, though they aren't real IDs and won't work as such.
/🆑
This commit is contained in:
Ghom
2023-07-10 17:45:34 +01:00
committed by GitHub
parent 315a0b5bfa
commit 3b44a8b15c
18 changed files with 245 additions and 62 deletions
@@ -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()
+2 -2
View File
@@ -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.
@@ -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
@@ -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])"
@@ -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")])"
@@ -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
+1 -1
View File
@@ -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
+4 -1
View File
@@ -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 = "<a href='?src=[REF(src)];track=[html_encode(namepart)]'>"
var/jobpart = "Unknown"
+9 -8
View File
@@ -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