Files
Bubberstation/code/__HELPERS/pronouns.dm
MrMelbert 7c0973ccf4 Refactors names and voices / potted plants no longer conceal voice (just appearance) / honorifics show on examine (#92781)
## About The Pull Request

Closes #92778
Closes #86829

<img width="347" height="39" alt="image"
src="https://github.com/user-attachments/assets/c50bd1ff-8c00-47a7-a31a-617fae2adc5b"
/>

1. Splits `TRAIT_UNKNOWN` into `TRAIT_UNKNOWN_APPEARANCE` and
`TRAIT_UNKNOWN_VOICE`

2. Renames some stuff like `getvoice` and `getspecialvoice`

3. Gets rid some crummy signals around `get_visible_name` and
`get_voice`

4. Heads now apply the disfigured trait when relevant (rather than
snowflake checking for damage amount)

5. Ling voice refactored into using special voice (it was only used by a
viro symptom anyways; I don't anticipate this overlap being problematic)

6. Mask voice changer refactored into a trait

## Why It's Good For The Game

Potted plants shouldn't have magical voice concealing powers -
especially not over radio, but not over in person either. It's a damn
plant

So I addressed this by refactoring our face and voice system. Overall
things should be a lot cleaner and easier to use.

## Changelog

🆑 Melbert
refactor: Refactored a lot of code relating to human face and voice, ie,
what shows up in examine and in say. Report anything odd when examining
people, with ID cards, when talking over radio, or when disguised
refcator: Refactored how you get disfigured when your head's super
damaged
refactor: Refactored ling mimic voice and traitor voice changer
del: Potted plants no longer hide voice. They still hide appearance,
though
qol: Honorifics now show in examine / in world, rather than only when
speaking.
/🆑
2025-09-12 17:11:06 +02:00

580 lines
12 KiB
Plaintext

#define GET_TARGET_PRONOUN(target, pronoun, gender) call(target, ALL_PRONOUNS[pronoun])(gender)
//pronoun procs, for getting pronouns without using the text macros that only work in certain positions
//datums don't have gender, but most of their subtypes do!
/datum/proc/p_they(temp_gender)
return "it"
/datum/proc/p_They(temp_gender)
return capitalize(p_they(temp_gender))
/datum/proc/p_their(temp_gender)
return "its"
/datum/proc/p_Their(temp_gender)
return capitalize(p_their(temp_gender))
/datum/proc/p_theirs(temp_gender)
return "its"
/datum/proc/p_Theirs(temp_gender)
return capitalize(p_theirs(temp_gender))
/datum/proc/p_them(temp_gender)
return "it"
/datum/proc/p_Them(temp_gender)
return capitalize(p_them(temp_gender))
/datum/proc/p_have(temp_gender)
return "has"
/datum/proc/p_are(temp_gender)
return "is"
/datum/proc/p_were(temp_gender)
return "was"
/datum/proc/p_do(temp_gender)
return "does"
/datum/proc/p_theyve(temp_gender)
return p_they(temp_gender) + "'" + copytext_char(p_have(temp_gender), 3)
/datum/proc/p_Theyve(temp_gender)
return p_They(temp_gender) + "'" + copytext_char(p_have(temp_gender), 3)
/datum/proc/p_theyre(temp_gender)
return p_they(temp_gender) + "'" + copytext_char(p_are(temp_gender), 2)
/datum/proc/p_Theyre(temp_gender)
return p_They(temp_gender) + "'" + copytext_char(p_are(temp_gender), 2)
/datum/proc/p_s(temp_gender) //is this a descriptive proc name, or what?
return "s"
/datum/proc/p_es(temp_gender)
return "es"
/datum/proc/p_themselves(temp_gender)
return "itself"
/datum/proc/plural_s(pluralize)
switch(copytext_char(pluralize, -2))
if ("ss")
return "es"
if ("sh")
return "es"
if ("ch")
return "es"
else
switch(copytext_char(pluralize, -1))
if("s", "x", "z")
return "es"
else
return "s"
/// A proc to replace pronouns in a string with the appropriate pronouns for a target atom.
/// Uses associative list access from a __DEFINE list, since associative access is slightly
/// faster
/datum/proc/REPLACE_PRONOUNS(target_string, atom/targeted_atom, targeted_gender = null)
/// If someone specifies targeted_gender we choose that,
/// otherwise we go off the gender of our object
var/gender
if(targeted_gender)
if(!istext(targeted_gender) || !(targeted_gender in list(MALE, FEMALE, PLURAL, NEUTER)))
stack_trace("REPLACE_PRONOUNS called with improper parameters.")
return
gender = targeted_gender
else
gender = targeted_atom.get_visible_gender()
///The pronouns are ordered by their length to avoid %PRONOUN_Theyve being translated to "Heve" instead of "He's", for example
var/regex/pronoun_regex = regex("%PRONOUN(_(theirs|Theirs|theyve|Theyve|theyre|Theyre|their|Their|they|They|them|Them|have|were|are|do|es|s))")
while(pronoun_regex.Find(target_string))
target_string = pronoun_regex.Replace(target_string, GET_TARGET_PRONOUN(targeted_atom, pronoun_regex.match, gender))
return target_string
//like clients, which do have gender.
/client/p_they(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "she"
if(MALE)
return "he"
else
return "they"
/client/p_their(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "her"
if(MALE)
return "his"
else
return "their"
/client/p_theirs(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "hers"
if(MALE)
return "his"
else
return "theirs"
/client/p_them(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "her"
if(MALE)
return "him"
else
return "them"
/client/p_have(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL || temp_gender == NEUTER)
return "have"
return "has"
/client/p_are(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL || temp_gender == NEUTER)
return "are"
return "is"
/client/p_were(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL || temp_gender == NEUTER)
return "were"
return "was"
/client/p_do(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL || temp_gender == NEUTER)
return "do"
return "does"
/client/p_s(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL && temp_gender != NEUTER)
return "s"
/client/p_es(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL && temp_gender != NEUTER)
return "es"
/client/p_themselves(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "herself"
if(MALE)
return "himself"
if(PLURAL)
return "themselves"
else
return "itself"
//mobs(and atoms but atoms don't really matter write your own proc overrides) also have gender!
/mob/p_they(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "she"
if(MALE)
return "he"
if(PLURAL)
return "they"
else
return "it"
/mob/p_their(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "her"
if(MALE)
return "his"
if(PLURAL)
return "their"
else
return "its"
/mob/p_theirs(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "hers"
if(MALE)
return "his"
if(PLURAL)
return "theirs"
else
return "its"
/mob/p_them(capitalized, temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "her"
if(MALE)
return "him"
if(PLURAL)
return "them"
else
return "it"
/mob/p_have(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "have"
return "has"
/mob/p_are(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "are"
return "is"
/mob/p_were(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "were"
return "was"
/mob/p_do(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "do"
return "does"
/mob/p_s(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL)
return "s"
/mob/p_es(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL)
return "es"
/mob/p_themselves(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "herself"
if(MALE)
return "himself"
if(PLURAL)
return "themselves"
else
return "itself"
//Pronoun procs for objects
/atom/p_they(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "she"
if(MALE)
return "he"
if(PLURAL)
return "they"
else
return "it"
/atom/p_their(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "her"
if(MALE)
return "his"
if(PLURAL)
return "their"
else
return "its"
/atom/p_theirs(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "hers"
if(MALE)
return "his"
if(PLURAL)
return "theirs"
else
return "its"
/atom/p_them(capitalized, temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "her"
if(MALE)
return "him"
if(PLURAL)
return "them"
else
return "it"
/atom/p_have(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "have"
return "has"
/atom/p_are(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "are"
return "is"
/atom/p_were(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "were"
return "was"
/atom/p_do(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "do"
return "does"
/atom/p_s(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL)
return "s"
/atom/p_es(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL)
return "es"
/atom/p_themselves(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "herself"
if(MALE)
return "himself"
if(PLURAL)
return "themselves"
else
return "itself"
/// Reports what gender this atom appears to be
/atom/proc/get_visible_gender()
return gender
/mob/living/carbon/human/get_visible_gender()
if(HAS_TRAIT(src, TRAIT_UNKNOWN_APPEARANCE))
return PLURAL
// If both face and uniform are hidden, can't assess gender
if(obscured_slots & (HIDEFACE|HIDEJUMPSUIT) == (HIDEFACE|HIDEJUMPSUIT))
return PLURAL
return gender
//humans need special handling, because they can have their gender hidden
/mob/living/carbon/human/p_they(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_their(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_theirs(capitalized, temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_them(capitalized, temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_have(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_are(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_were(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_do(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_s(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_es(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
/mob/living/carbon/human/p_themselves(temp_gender)
temp_gender ||= get_visible_gender()
return ..()
//clothing need special handling due to pairs of items, ie gloves vs a singular glove, shoes, ect.
/obj/item/clothing/p_they(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "they"
return "it"
/obj/item/clothing/p_their(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "their"
return "its"
/obj/item/clothing/p_theirs(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "theirs"
return "its"
/obj/item/clothing/p_them(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "them"
return "it"
/obj/item/clothing/p_have(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "have"
return "has"
/obj/item/clothing/p_are(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "are"
return "is"
/obj/item/clothing/p_were(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "were"
return "was"
/obj/item/clothing/p_do(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender == PLURAL)
return "do"
return "does"
/obj/item/clothing/p_s(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL)
return "s"
/obj/item/clothing/p_es(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL)
return "es"
/obj/item/clothing/p_themselves(temp_gender)
if(!temp_gender)
temp_gender = gender
switch(temp_gender)
if(FEMALE)
return "herself"
if(MALE)
return "himself"
if(PLURAL)
return "themselves"
else
return "itself"
/datum/mind/p_they(temp_gender)
return current?.p_they(temp_gender) || ..()
/datum/mind/p_their(temp_gender)
return current?.p_their(temp_gender) || ..()
/datum/mind/p_theirs(temp_gender)
return current?.p_theirs(temp_gender) || ..()
/datum/mind/p_them(capitalized, temp_gender)
return current?.p_them(capitalized, temp_gender) || ..()
/datum/mind/p_have(temp_gender)
return current?.p_have(temp_gender) || ..()
/datum/mind/p_are(temp_gender)
return current?.p_are(temp_gender) || ..()
/datum/mind/p_were(temp_gender)
return current?.p_were(temp_gender) || ..()
/datum/mind/p_do(temp_gender)
return current?.p_do(temp_gender) || ..()
/datum/mind/p_s(temp_gender)
return current?.p_s(temp_gender) || ..()
/datum/mind/p_es(temp_gender)
return current?.p_es(temp_gender) || ..()
/datum/mind/p_themselves(temp_gender)
return current?.p_themselves(temp_gender) || ..()