diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index c334ed1e9b..b98431c253 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -224,6 +224,7 @@ // /mob/living/carbon signals #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) +#define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE) // /mob/living/simple_animal/hostile signals #define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" @@ -289,6 +290,9 @@ #define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) #define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) #define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) +#define COMSIG_HUMAN_PREFS_COPIED_TO "human_prefs_copied_to" //from datum/preferences/copy_to(): (datum/preferences, icon_updates, roundstart_checks) +#define COMSIG_HUMAN_HARDSET_DNA "human_hardset_dna" //from mob/living/carbon/human/hardset_dna(): (ui, se, newreal_name, newblood_type, datum/species, newfeatures) +#define COMSIG_HUMAN_ON_RANDOMIZE "humman_on_randomize" //from base of proc/randomize_human() // /datum/species signals #define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 4ae30838e4..ffc1bcc6b7 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -107,38 +107,6 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) if(!src.holder) return message_admins("[key_name_admin(usr)] manually reloaded mentors") -//Flavor Text -/mob/proc/set_flavor() - set name = "Set Flavor Text" - set desc = "Sets an extended description of your character's features." - set category = "IC" - - var/new_flavor = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", flavor_text, MAX_FAVOR_LEN, TRUE) - if(!isnull(new_flavor)) - flavor_text = html_decode(new_flavor) - to_chat(src, "Your flavor text has been updated.") - -//Flavor Text -/mob/proc/set_flavor_2() - set name = "Set Temporary Flavor Text" - set desc = "Sets a description of your character's current appearance. Use this for emotions, poses etc." - set category = "IC" - - var/new_flavor = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", flavor_text_2, MAX_FAVOR_LEN, TRUE) - if(!isnull(new_flavor)) - flavor_text_2 = html_decode(new_flavor) - to_chat(src, "Your temporary flavor text has been updated.") - -/mob/proc/print_flavor_text(flavor,temp = FALSE) - if(!flavor) - return - // We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown. - var/msg = html_decode(replacetext(flavor, "\n", " ")) - if(length_char(msg) <= 40) - return "[html_encode(msg)]" - else - return "[html_encode(copytext_char(msg, 1, 37))]... More..." - //LOOC toggles /client/verb/listen_looc() set name = "Show/Hide LOOC" diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 2f4dba9c38..2973a44a68 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -51,10 +51,11 @@ if(ishuman(destination)) var/mob/living/carbon/human/H = destination H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA - destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text if(transfer_SE) destination.dna.struc_enzymes = struc_enzymes + SEND_SIGNAL(destination, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, src, transfer_SE) + /datum/dna/proc/copy_dna(datum/dna/new_dna) new_dna.unique_enzymes = unique_enzymes new_dna.struc_enzymes = struc_enzymes @@ -284,7 +285,6 @@ if(newfeatures) dna.features = newfeatures - flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text if(mrace) var/datum/species/newrace = new mrace.type @@ -306,6 +306,8 @@ dna.struc_enzymes = se domutcheck() + SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, se, newreal_name, newblood_type, mrace, newfeatures) + if(mrace || newfeatures || ui) update_body() update_hair() diff --git a/code/datums/elements/flavor_text.dm b/code/datums/elements/flavor_text.dm new file mode 100644 index 0000000000..54729d5f83 --- /dev/null +++ b/code/datums/elements/flavor_text.dm @@ -0,0 +1,146 @@ +GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code + +/datum/element/flavor_text + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 3 + var/flavor_name = "Flavor Text" + var/list/texts_by_atom = list() + var/addendum = "This can also be used for OOC notes and preferences!" + var/always_show = FALSE + var/max_len = MAX_FAVOR_LEN + var/can_edit = TRUE + +/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FAVOR_LEN, _always_show = FALSE, _edit = TRUE) + . = ..() + + if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) //no reason why this shouldn't work on atoms too. + return ELEMENT_INCOMPATIBLE + + if(_max_len) + max_len = _max_len + texts_by_atom[target] = copytext(text, 1, max_len) + if(_name) + flavor_name = _name + if(!isnull(addendum)) + addendum = _addendum + always_show = _always_show + can_edit = _edit + + RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/show_flavor) + + if(can_edit && ismob(target)) //but only mobs receive the proc/verb for the time being + var/mob/M = target + LAZYOR(GLOB.mobs_with_editable_flavor_text[M], src) + M.verbs |= /mob/proc/manage_flavor_tests + +/datum/element/flavor_text/Detach(atom/A) + . = ..() + UnregisterSignal(A, COMSIG_PARENT_EXAMINE) + texts_by_atom -= A + if(can_edit && ismob(A)) + var/mob/M = A + LAZYREMOVE(GLOB.mobs_with_editable_flavor_text[M], src) + if(!GLOB.mobs_with_editable_flavor_text[M]) + GLOB.mobs_with_editable_flavor_text -= M + M.verbs -= /mob/proc/manage_flavor_tests + +/datum/element/flavor_text/proc/show_flavor(atom/target, mob/user, list/examine_list) + if(!always_show && isliving(target)) + var/mob/living/L = target + var/unknown = L.get_visible_name() == "Unknown" + if(!unknown && iscarbon(target)) + var/mob/living/carbon/C = L + unknown = (C.wear_mask && (C.wear_mask.flags_inv & HIDEFACE)) || (C.head && (C.head.flags_inv & HIDEFACE)) + if(unknown) + if(!("...?" in examine_list)) //can't think of anything better in case of multiple flavor texts. + examine_list += "...?" + return + var/text = texts_by_atom[target] + if(!text) + return + var/msg = replacetext(text, "\n", " ") + if(length_char(msg) <= 40) + examine_list += "[html_encode(msg)]" + else + examine_list += "[html_encode(copytext_char(msg, 1, 37))]... More..." + +/datum/element/flavor_text/Topic(href, href_list) + . = ..() + if(.) + return + if(href_list["show_flavor"]) + var/atom/target = locate(href_list["show_flavor"]) + var/text = texts_by_atom[target] + if(text) + usr << browse("[target.name][replacetext(texts_by_atom[target], "\n", "
")]
", "window=[target.name];size=500x200") + onclose(usr, "[target.name]") + return TRUE + +/mob/proc/manage_flavor_tests() + set name = "Manage Flavor Texts" + set desc = "Used to manage your various flavor texts." + set category = "IC" + + var/list/L = GLOB.mobs_with_editable_flavor_text[src] + + if(length(L) == 1) + var/datum/element/flavor_text/F = L[1] + F.set_flavor(src) + return + + var/list/choices = list() + + for(var/i in L) + var/datum/element/flavor_text/F = i + choices[F.flavor_name] = F + + var/chosen = input(src, "Which flavor text would you like to modify?") as null|anything in choices + if(!chosen) + return + var/datum/element/flavor_text/F = choices[chosen] + F.set_flavor(src) + +/datum/element/flavor_text/proc/set_flavor(mob/user) + if(!(user in texts_by_atom)) + return FALSE + + var/lower_name = lowertext(flavor_name) + var/new_text = stripped_multiline_input(user, "Set the [lower_name] displayed on 'examine'. [addendum]", flavor_name, texts_by_atom[usr], max_len, TRUE) + if(!isnull(new_text) && (user in texts_by_atom)) + texts_by_atom[user] = html_decode(new_text) + to_chat(src, "Your [lower_name] has been updated.") + return TRUE + return FALSE + +//subtypes with additional hooks for DNA and preferences. +/datum/element/flavor_text/carbon + +/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FAVOR_LEN, _always_show = FALSE, _edit = TRUE) + if(!iscarbon(target)) + return ELEMENT_INCOMPATIBLE + . = ..() + if(. == ELEMENT_INCOMPATIBLE) + return + RegisterSignal(target, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, .proc/update_dna_flavor_text) + if(ishuman(target)) + RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text) + RegisterSignal(target, COMSIG_HUMAN_HARDSET_DNA, .proc/update_dna_flavor_text) + RegisterSignal(target, COMSIG_HUMAN_ON_RANDOMIZE, .proc/unset_flavor) + +/datum/element/flavor_text/carbon/Detach(mob/living/carbon/C) + . = ..() + UnregisterSignal(C, list(COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, COMSIG_HUMAN_PREFS_COPIED_TO, COMSIG_HUMAN_HARDSET_DNA, COMSIG_HUMAN_ON_RANDOMIZE)) + +/datum/element/flavor_text/carbon/proc/update_dna_flavor_text(mob/living/carbon/C) + texts_by_atom[C] = C.dna.features["flavor_text"] + +/datum/element/flavor_text/carbon/proc/update_prefs_flavor_text(mob/living/carbon/human/H, datum/preferences/P, icon_updates = TRUE, roundstart_checks = TRUE) + texts_by_atom[H] = P.features["flavor_text"] + +/datum/element/flavor_text/carbon/set_flavor(mob/living/carbon/user) + . = ..() + if(. && user.dna) + user.dna.features["flavor_text"] = texts_by_atom[user] + +/datum/element/flavor_text/carbon/proc/unset_flavor(mob/living/carbon/user) + texts_by_atom[user] = "" diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 9784aa7cd1..4d1cb1a7de 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -40,6 +40,9 @@ H.dna.features["insect_wings"] = pick(GLOB.insect_wings_list) H.dna.features["deco_wings"] = pick(GLOB.deco_wings_list) H.dna.features["insect_fluff"] = pick(GLOB.insect_fluffs_list) + H.dna.features["flavor_text"] = "" //Oh no. + + SEND_SIGNAL(H, COMSIG_HUMAN_ON_RANDOMIZE) H.update_body() H.update_hair() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index a9cf45744e..a9deba070a 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -2429,6 +2429,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) else character.Digitigrade_Leg_Swap(TRUE) + SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks) + //let's be sure the character updates if(icon_updates) character.update_body() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index fec82b357f..cb21534d25 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -25,15 +25,10 @@ var/list/obscured = check_obscured_slots() var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE)) - if(ishuman(src)) //user just returned, y'know, the user's own species. dumb. - var/mob/living/carbon/human/H = src - var/datum/species/pref_species = H.dna.species - if(get_visible_name() == "Unknown") // same as flavor text, but hey it works. - . += "You can't make out what species they are." - else if(skipface) - . += "You can't make out what species they are." - else - . += "[t_He] [t_is] a [H.dna.custom_species ? H.dna.custom_species : pref_species.name]!" + if(skipface || get_visible_name() == "Unknown") + . += "You can't make out what species they are." + else + . += "[t_He] [t_is] a [dna.custom_species ? dna.custom_species : dna.species.name]!" //uniform if(w_uniform && !(SLOT_W_UNIFORM in obscured)) @@ -389,18 +384,8 @@ else if(isobserver(user) && traitstring) . += "Traits: [traitstring]" - //No flavor text unless the face can be seen. Prevents certain metagaming with impersonation. - var/invisible_man = skipface || get_visible_name() == "Unknown" - if(invisible_man) - . += "...?" - else - var/flavor = print_flavor_text(flavor_text) - if(flavor) - . += flavor - var/temp_flavor = print_flavor_text(flavor_text_2,TRUE) - if(temp_flavor) - . += temp_flavor - SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) + SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) //This also handles flavor texts now + . += "*---------*" /mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects! diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index a2b93a7279..1b57796250 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -9,8 +9,6 @@ verbs += /mob/living/proc/mob_sleep verbs += /mob/living/proc/lay_down verbs += /mob/living/carbon/human/proc/underwear_toggle //fwee - verbs += /mob/proc/set_flavor - verbs += /mob/proc/set_flavor_2 //initialize limbs first create_bodyparts() @@ -40,6 +38,8 @@ . = ..() if(!CONFIG_GET(flag/disable_human_mood)) AddComponent(/datum/component/mood) + AddElement(/datum/element/flavor_text/carbon) + AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!") /mob/living/carbon/human/Destroy() QDEL_NULL(physiology) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 1f766d5f95..5225534cee 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -503,14 +503,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) unset_machine() src << browse(null, t1) - if(href_list["flavor_more"]) - usr << browse(text("[][]", name, replacetext(flavor_text, "\n", "
")), text("window=[];size=500x200", name)) - onclose(usr, "[name]") - - if(href_list["flavor2_more"]) - usr << browse(text("[][]", name, replacetext(flavor_text_2, "\n", "
")), text("window=[];size=500x200", name)) - onclose(usr, "[name]") - if(href_list["refresh"]) if(machine && in_range(src, usr)) show_inv(machine) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 059fed3d5c..f638281f27 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -125,6 +125,3 @@ var/siliconaccesstoggle = FALSE var/voluntary_ghosted = FALSE //whether or not they voluntarily ghosted. - - var/flavor_text = "" - var/flavor_text_2 = "" //version of the above that only lasts for the current round. diff --git a/modular_citadel/code/modules/client/preferences.dm b/modular_citadel/code/modules/client/preferences.dm index 8b0ba2dd43..f1dbe31d02 100644 --- a/modular_citadel/code/modules/client/preferences.dm +++ b/modular_citadel/code/modules/client/preferences.dm @@ -49,6 +49,5 @@ /datum/preferences/copy_to(mob/living/carbon/human/character, icon_updates = 1) ..() character.give_genitals(TRUE) - character.flavor_text = features["flavor_text"] //Let's update their flavor_text at least initially if(icon_updates) character.update_genitals() diff --git a/tgstation.dme b/tgstation.dme index cd0e1a333d..9abd2527b8 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -498,6 +498,7 @@ #include "code\datums\elements\dusts_on_leaving_area.dm" #include "code\datums\elements\earhealing.dm" #include "code\datums\elements\firestacker.dm" +#include "code\datums\elements\flavor_text.dm" #include "code\datums\elements\ghost_role_eligibility.dm" #include "code\datums\elements\mob_holder.dm" #include "code\datums\elements\swimming.dm"