diff --git a/code/__defines/talksounds.dm b/code/__defines/talksounds.dm index fdd08d759e..6c7a312afa 100644 --- a/code/__defines/talksounds.dm +++ b/code/__defines/talksounds.dm @@ -33,7 +33,7 @@ var/list/talk_sound_map = rlist( GLOB.goon_speak_pugg_sound, GLOB.goon_speak_roach_sound, GLOB.goon_speak_skelly_sound, - // xeno_speak_sound // Does not exist on virgo + GLOB.xeno_speak_sound // Does not exist on virgo ) ) diff --git a/code/_global_vars/lists/misc.dm b/code/_global_vars/lists/misc.dm index 7fbe4c74f1..0e5e8b4ee3 100644 --- a/code/_global_vars/lists/misc.dm +++ b/code/_global_vars/lists/misc.dm @@ -10,6 +10,8 @@ GLOBAL_LIST_EMPTY(tagger_locations) GLOBAL_LIST_INIT(char_directory_tags, list("Pred", "Pred-Pref", "Prey", "Prey-Pref", "Switch", "Non-Vore", "Unset")) GLOBAL_LIST_INIT(char_directory_erptags, list("Dominant", "Dom-Pref", "Submissive", "Sub-Pref", "Switch", "No ERP", "Unset")) +GLOBAL_LIST_INIT(char_directory_sexualitytags, list("Straight", "Bisexual", "Pansexual", "Gay", "Lesbian", "Asexual", "Demisexual", "Flexible", "Other", "Unset")) +GLOBAL_LIST_INIT(char_directory_gendertags, list("Male", "Female", "Feminine", "Masculine", "Nonbinary", "Trans Man", "Trans Woman", "Other", "Flexible", "Ungendered", "Unset")) GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes GLOBAL_LIST_INIT(uplink_locations, list("PDA", "Headset", "None")) diff --git a/code/datums/mind_vr.dm b/code/datums/mind_vr.dm index a6758ca229..21f0fda7b5 100644 --- a/code/datums/mind_vr.dm +++ b/code/datums/mind_vr.dm @@ -5,6 +5,9 @@ var/directory_erptag var/directory_ad var/vore_prey_eaten = 0 + var/vantag_preference = VANTAG_NONE + var/directory_gendertag + var/directory_sexualitytag /mob/living/mind_initialize() . = ..() @@ -13,3 +16,6 @@ mind.directory_tag = client.prefs.directory_tag mind.directory_erptag = client.prefs.directory_erptag mind.directory_ad = client.prefs.directory_ad + mind.vantag_preference = client.prefs.vantag_preference + mind.directory_gendertag = client.prefs.directory_gendertag + mind.directory_sexualitytag = client.prefs.directory_sexualitytag diff --git a/code/game/objects/items/devices/body_snatcher_vr.dm b/code/game/objects/items/devices/body_snatcher_vr.dm index eeb3a651ed..fec5fe3a38 100644 --- a/code/game/objects/items/devices/body_snatcher_vr.dm +++ b/code/game/objects/items/devices/body_snatcher_vr.dm @@ -28,19 +28,16 @@ to_chat(user,span_danger("The target's mind is too complex to be affected!")) return - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.resleeve_lock && user.ckey != H.resleeve_lock) - to_chat(src, span_danger("[H] cannot be impersonated!")) - return - if(M.stat == DEAD) //Are they dead? to_chat(user,span_warning("A warning pops up on the device, informing you that [M] is dead, and, as such, the mind transfer can not be done.")) return var/choice = tgui_alert(user,"This will swap your mind with the target's mind. This will result in them controlling your body, and you controlling their body. Continue?","Confirmation",list("Continue","Cancel")) if(choice == "Continue" && user.get_active_hand() == src && user.Adjacent(M)) - + if(M.ckey && !M.client) + log_and_message_admins("attempted to body swap with [key_name(M)] while they were SSD!") + else + log_and_message_admins("attempted to body swap with [key_name(M)].") user.visible_message(span_warning("[user] pushes the device up their forehead and [M]'s head, the device beginning to let out a series of light beeps!"),span_notice("You begin swap minds with [M]!")) if(do_after(user,35 SECONDS,M)) if(user.mind && M.mind && M.stat != DEAD && user.stat != DEAD) @@ -51,6 +48,12 @@ var/target_ooc_notes = M.ooc_notes var/target_likes = M.ooc_notes_likes var/target_dislikes = M.ooc_notes_dislikes + var/target_favs = M.ooc_notes_favs + var/target_maybes = M.ooc_notes_maybes + var/target_style = M.ooc_notes_style + var/user_favs = user.ooc_notes_favs + var/user_maybes = user.ooc_notes_maybes + var/user_style = user.ooc_notes_style var/user_ooc_notes = user.ooc_notes var/user_likes = user.ooc_notes_likes var/user_dislikes = user.ooc_notes_dislikes @@ -67,6 +70,20 @@ M.ooc_notes = user_ooc_notes //Let's keep their OOC notes over to their new body. M.ooc_notes_likes = user_likes M.ooc_notes_dislikes = user_dislikes + M.ooc_notes_favs = user_favs + M.ooc_notes_maybes = user_maybes + M.ooc_notes_style = user_style + user.ooc_notes_favs = target_favs + user.ooc_notes_maybes = target_maybes + user.ooc_notes_style = target_style + if(M.tf_mob_holder == user) + M.tf_mob_holder = null + else + M.tf_mob_holder = user + if(user.tf_mob_holder == M) + user.tf_mob_holder = null + else + user.tf_mob_holder = M user.ooc_notes = target_ooc_notes user.ooc_notes_likes = target_likes user.ooc_notes_dislikes = target_dislikes diff --git a/code/game/objects/items/devices/scanners/sleevemate.dm b/code/game/objects/items/devices/scanners/sleevemate.dm index 2a7962f24f..5d13bb9923 100644 --- a/code/game/objects/items/devices/scanners/sleevemate.dm +++ b/code/game/objects/items/devices/scanners/sleevemate.dm @@ -18,8 +18,11 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob var/datum/mind/stored_mind var/ooc_notes = null //For holding prefs + var/ooc_notes_favs = null var/ooc_notes_likes = null + var/ooc_notes_maybes = null var/ooc_notes_dislikes = null + var/ooc_notes_style = FALSE // Resleeving database this machine interacts with. Blank for default database // Needs a matching /datum/transcore_db with key defined in code @@ -45,6 +48,9 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob ooc_notes = M.ooc_notes ooc_notes_likes = M.ooc_notes_likes ooc_notes_dislikes = M.ooc_notes_dislikes + ooc_notes_favs = M.ooc_notes_favs + ooc_notes_maybes = M.ooc_notes_maybes + ooc_notes_style = M.ooc_notes_style stored_mind = M.mind M.ghostize() stored_mind.current = null @@ -56,6 +62,9 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob M.ooc_notes = ooc_notes M.ooc_notes_likes = ooc_notes_likes M.ooc_notes_dislikes = ooc_notes_dislikes + M.ooc_notes_favs = ooc_notes_favs + M.ooc_notes_maybes = ooc_notes_maybes + M.ooc_notes_style = ooc_notes_style clear_mind() diff --git a/code/game/sound.dm b/code/game/sound.dm index 63266b2939..17bb6aac20 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -308,6 +308,7 @@ 'sound/effects/mech/powerloader_step2.ogg') return soundin + //Are these even used? //Yes GLOBAL_LIST_INIT(keyboard_sound, list('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg')) GLOBAL_LIST_INIT(bodyfall_sound, list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg')) @@ -328,6 +329,11 @@ GLOBAL_LIST_INIT(goon_speak_pugg_sound, list('sound/talksounds/goon/pugg.ogg', ' GLOBAL_LIST_INIT(goon_speak_roach_sound, list('sound/talksounds/goon/roach.ogg', 'sound/talksounds/goon/roach_ask.ogg', 'sound/talksounds/goon/roach_exclaim.ogg')) GLOBAL_LIST_INIT(goon_speak_skelly_sound, list('sound/talksounds/goon/skelly.ogg', 'sound/talksounds/goon/skelly_ask.ogg', 'sound/talksounds/goon/skelly_exclaim.ogg')) +GLOBAL_LIST_INIT(wf_speak_lure_sound, list ('sound/talksounds/wf/lure_1.ogg', 'sound/talksounds/wf/lure_2.ogg', 'sound/talksounds/wf/lure_3.ogg', 'sound/talksounds/wf/lure_4.ogg', 'sound/talksounds/wf/lure_5.ogg')) +GLOBAL_LIST_INIT(wf_speak_lyst_sound, list ('sound/talksounds/wf/lyst_1.ogg', 'sound/talksounds/wf/lyst_2.ogg', 'sound/talksounds/wf/lyst_3.ogg', 'sound/talksounds/wf/lyst_4.ogg', 'sound/talksounds/wf/lyst_5.ogg', 'sound/talksounds/wf/lyst_6.ogg')) +GLOBAL_LIST_INIT(wf_speak_void_sound, list ('sound/talksounds/wf/void_1.ogg', 'sound/talksounds/wf/void_2.ogg', 'sound/talksounds/wf/void_3.ogg')) +GLOBAL_LIST_INIT(wf_speak_vomva_sound, list ('sound/talksounds/wf/vomva_1.ogg', 'sound/talksounds/wf/vomva_2.ogg', 'sound/talksounds/wf/vomva_3.ogg', 'sound/talksounds/wf/vomva_4.ogg')) +GLOBAL_LIST_INIT(xeno_speak_sound, list('sound/talksounds/xeno/xenotalk.ogg', 'sound/talksounds/xeno/xenotalk2.ogg', 'sound/talksounds/xeno/xenotalk3.ogg')) #define canine_sounds list("cough" = null, "sneeze" = null, "scream" = list('sound/voice/scream/canine/wolf_scream.ogg', 'sound/voice/scream/canine/wolf_scream2.ogg', 'sound/voice/scream/canine/wolf_scream3.ogg', 'sound/voice/scream/canine/wolf_scream4.ogg', 'sound/voice/scream/canine/wolf_scream5.ogg', 'sound/voice/scream/canine/wolf_scream6.ogg'), "pain" = list('sound/voice/pain/canine/wolf_pain.ogg', 'sound/voice/pain/canine/wolf_pain2.ogg', 'sound/voice/pain/canine/wolf_pain3.ogg', 'sound/voice/pain/canine/wolf_pain4.ogg'), "gasp" = list('sound/voice/gasp/canine/wolf_gasp.ogg'), "death" = list('sound/voice/death/canine/wolf_death1.ogg', 'sound/voice/death/canine/wolf_death2.ogg', 'sound/voice/death/canine/wolf_death3.ogg', 'sound/voice/death/canine/wolf_death4.ogg', 'sound/voice/death/canine/wolf_death5.ogg')) #define feline_sounds list("cough" = null, "sneeze" = null, "scream" = list('sound/voice/scream/feline/feline_scream.ogg'), "pain" = list('sound/voice/pain/feline/feline_pain.ogg'), "gasp" = list('sound/voice/gasp/feline/feline_gasp.ogg'), "death" = list('sound/voice/death/feline/feline_death.ogg')) diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 3027a2f041..2cc80ea3d2 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -62,10 +62,11 @@ . += "
" . += span_bold("Biological Sex:") + " [gender2text(pref.biological_gender)]
" . += span_bold("Pronouns:") + " [genders_to_pronoun_set[pref.identifying_gender]]
" - . += span_bold("Age:") + " [pref.read_preference(/datum/preference/numeric/human/age)] Birthday: [pref.read_preference(/datum/preference/numeric/human/bday_month)]/[pref.read_preference(/datum/preference/numeric/human/bday_day)] - Announce?: [pref.read_preference(/datum/preference/toggle/human/bday_announce) ? "Yes" : "No"]
" + . += span_bold("Age:") + " [pref.read_preference(/datum/preference/numeric/human/age)] Birthday: [pref.read_preference(/datum/preference/numeric/human/bday_month)]/[pref.read_preference(/datum/preference/numeric/human/bday_day)] - Announce?: [pref.read_preference(/datum/preference/toggle/human/bday_announce) ? "Yes" : "Disabled"]
" . += span_bold("Spawn Point:") + " [pref.read_preference(/datum/preference/choiced/living/spawnpoint)]
" if(CONFIG_GET(flag/allow_metadata)) - . += span_bold("OOC Notes: EditLikesDislikes") + "
" + . += span_bold("OOC Notes: EditFavsLikesMaybesDislikes") + "
" + . += "Detailed field or short list system? [pref.read_preference(/datum/preference/toggle/living/ooc_notes_style) ? "Lists" : "Fields"]

" . = jointext(.,null) /datum/category_item/player_setup_item/general/basic/OnTopic(var/href,var/list/href_list, var/mob/user) @@ -202,6 +203,21 @@ if(new_metadata == "!clear") new_metadata = "" pref.update_preference_by_type(/datum/preference/text/living/ooc_notes_dislikes, new_metadata) + else if(href_list["edit_ooc_note_favs"]) + var/new_metadata = strip_html_simple(tgui_input_text(user, "Enter any information you'd like others to see relating to your FAVOURITE roleplay preferences. This will not be saved permanently unless you click save in the Character Setup panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(pref.read_preference(/datum/preference/text/living/ooc_notes_favs)), multiline = TRUE, prevent_enter = TRUE)) + if(new_metadata && CanUseTopic(user)) + if(new_metadata == "!clear") + new_metadata = "" + pref.update_preference_by_type(/datum/preference/text/living/ooc_notes_favs, new_metadata) + else if(href_list["edit_ooc_note_maybes"]) + var/new_metadata = strip_html_simple(tgui_input_text(user, "Enter any information you'd like others to see relating to your MAYBE roleplay preferences. This will not be saved permanently unless you click save in the Character Setup panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(pref.read_preference(/datum/preference/text/living/ooc_notes_maybes)), multiline = TRUE, prevent_enter = TRUE)) + if(new_metadata && CanUseTopic(user)) + if(new_metadata == "!clear") + new_metadata = "" + pref.update_preference_by_type(/datum/preference/text/living/ooc_notes_maybes, new_metadata) + else if(href_list["edit_ooc_note_style"]) + pref.update_preference_by_type(/datum/preference/toggle/living/ooc_notes_style, !pref.read_preference(/datum/preference/toggle/living/ooc_notes_style)) + return TOPIC_REFRESH return ..() /datum/category_item/player_setup_item/general/basic/proc/get_genders() diff --git a/code/modules/client/preference_setup/vore/02_size.dm b/code/modules/client/preference_setup/vore/02_size.dm index acc41101cd..46f3fc0420 100644 --- a/code/modules/client/preference_setup/vore/02_size.dm +++ b/code/modules/client/preference_setup/vore/02_size.dm @@ -33,6 +33,7 @@ pref.voice_sound = save_data["voice_sound"] pref.custom_speech_bubble = save_data["custom_speech_bubble"] pref.custom_footstep = save_data["custom_footstep"] + pref.species_sound = save_data["species_sound"] /datum/category_item/player_setup_item/vore/size/save_character(list/save_data) save_data["size_multiplier"] = pref.size_multiplier @@ -45,6 +46,7 @@ save_data["voice_sound"] = pref.voice_sound save_data["custom_speech_bubble"] = pref.custom_speech_bubble save_data["custom_footstep"] = pref.custom_footstep + save_data["species_sound"] = pref.species_sound /datum/category_item/player_setup_item/vore/size/sanitize_character() pref.weight_vr = sanitize_integer(pref.weight_vr, WEIGHT_MIN, WEIGHT_MAX, initial(pref.weight_vr)) @@ -53,13 +55,16 @@ pref.fuzzy = sanitize_integer(pref.fuzzy, 0, 1, initial(pref.fuzzy)) pref.offset_override = sanitize_integer(pref.offset_override, 0, 1, initial(pref.offset_override)) if(pref.voice_freq != 0) - pref.voice_freq = sanitize_integer(pref.voice_freq, MIN_VOICE_FREQ, MAX_VOICE_FREQ, initial(pref.fuzzy)) + pref.voice_freq = sanitize_integer(pref.voice_freq, MIN_VOICE_FREQ, MAX_VOICE_FREQ, initial(pref.voice_freq)) if(pref.size_multiplier == null || pref.size_multiplier < RESIZE_TINY || pref.size_multiplier > RESIZE_HUGE) pref.size_multiplier = initial(pref.size_multiplier) if(!(pref.custom_speech_bubble in GLOB.selectable_speech_bubbles)) pref.custom_speech_bubble = "default" if(!(pref.custom_footstep)) pref.custom_footstep = "Default" + // var/datum/species/selected_species = GLOB.all_species[pref.species] + if(!(pref.species_sound)) + pref.species_sound = "Unset" /datum/category_item/player_setup_item/vore/size/copy_to_mob(var/mob/living/carbon/human/character) character.weight = pref.weight_vr @@ -69,6 +74,7 @@ character.offset_override = pref.offset_override character.voice_freq = pref.voice_freq character.resize(pref.size_multiplier, animate = FALSE, ignore_prefs = TRUE) + if(!pref.voice_sound) character.voice_sounds_list = GLOB.talk_sound else @@ -81,12 +87,23 @@ . += span_bold("Scale:") + " [round(pref.size_multiplier*100)]%
" . += span_bold("Scaled Appearance:") + " [pref.fuzzy ? "Fuzzy" : "Sharp"]
" . += span_bold("Scaling Center:") + " [pref.offset_override ? "Odd" : "Even"]
" + . += "
" + . += span_bold("Mob Speech/Noise Customization") + "" + . += "
" . += span_bold("Voice Frequency:") + " [pref.voice_freq]
" . += span_bold("Voice Sounds:") + " [pref.voice_sound]
" . += "Test Selected Voice
" . += span_bold("Custom Speech Bubble:") + " [pref.custom_speech_bubble]
" . += span_bold("Custom Footstep Sounds:") + "[pref.custom_footstep]
" . += "
" + . += span_bold("Species Sounds:") + " [pref.species_sound]
" + . += "Test Cough Sounds
" + . += "Test Sneeze Sounds
" + . += "Test Scream Sounds
" + . += "Test Pain Sounds
" + . += "Test Gasp Sounds
" + . += "Test Death Sounds
" + . += "
" . += span_bold("Relative Weight:") + " [pref.weight_vr]
" . += span_bold("Weight Gain Rate:") + " [pref.weight_gain]
" . += span_bold("Weight Loss Rate:") + " [pref.weight_loss]
" @@ -152,7 +169,7 @@ return choice = preset_voice_freqs[choice] if(choice == 0) - pref.voice_freq = choice + pref.voice_freq = 42500 return TOPIC_REFRESH else if(choice == 1) choice = tgui_input_number(user, "Choose your character's voice frequency, ranging from [MIN_VOICE_FREQ] to [MAX_VOICE_FREQ]", "Custom Voice Frequency", null, MAX_VOICE_FREQ, MIN_VOICE_FREQ) @@ -178,10 +195,13 @@ "goon speak pug", "goon speak pugg", "goon speak roach", - "goon speak skelly") + "goon speak skelly", + "xeno speak") var/choice = tgui_input_list(user, "Which set of sounds would you like to use for your character's speech sounds?", "Voice Sounds", possible_voice_types) - if(!choice) - pref.voice_sound = "beep-boop" + if(!pref.voice_sound) + pref.voice_sound = "goon speak 1" + else if(!choice) + return TOPIC_REFRESH else pref.voice_sound = choice return TOPIC_REFRESH @@ -231,11 +251,110 @@ S = sound(pick(GLOB.goon_speak_roach_sound)) if("goon speak skelly") S = sound(pick(GLOB.goon_speak_skelly_sound)) + if("xeno speak") + S = sound(pick(GLOB.xeno_speak_sound)) if(S) S.frequency = pick(pref.voice_freq) S.volume = 50 SEND_SOUND(user, S) - + else if(href_list["species_sound_options"]) // You shouldn't be able to see this option if you don't have the option to select a custom icon base, so we don't need to re-check for safety here. + var/list/possible_species_sound_types = species_sound_map + var/choice = tgui_input_list(user, "Which set of sounds would you like to use for your character's species sounds? (Cough, Sneeze, Scream, Pain, Gasp, Death)", "Species Sounds", possible_species_sound_types) + if(!choice) + return TOPIC_REFRESH // No choice? Don't reset our selection + else + pref.species_sound = choice + return TOPIC_REFRESH + else if(href_list["cough_test"]) + var/sound/S + var/ourpref = pref.species_sound + var/oursound = get_species_sound(ourpref)["cough"] + S = sound(pick(oursound)) + if(pref.species_sound == "Unset") + oursound = get_species_sound(select_default_species_sound(pref))["cough"] + S = sound(pick(oursound)) + if(pref.species_sound == "None" || oursound == null) + to_chat(user, span_warning("This set does not have cough sounds!")) + return TOPIC_REFRESH + S.frequency = pick(pref.voice_freq) + S.volume = 20 + SEND_SOUND(user, S) + return TOPIC_REFRESH + else if(href_list["sneeze_test"]) + var/sound/S + var/ourpref = pref.species_sound + var/oursound = get_species_sound(ourpref)["sneeze"] + S = sound(pick(oursound)) + if(pref.species_sound == "Unset") + oursound = get_species_sound(select_default_species_sound(pref))["sneeze"] + S = sound(pick(oursound)) + if(pref.species_sound == "None" || oursound == null) + to_chat(user, span_warning("This set does not have sneeze sounds!")) + return TOPIC_REFRESH + S.frequency = pick(pref.voice_freq) + S.volume = 20 + SEND_SOUND(user, S) + return TOPIC_REFRESH + else if(href_list["scream_test"]) + var/sound/S + var/ourpref = pref.species_sound + var/oursound = get_species_sound(ourpref)["scream"] + S = sound(pick(oursound)) + if(pref.species_sound == "Unset") + oursound = get_species_sound(select_default_species_sound(pref))["scream"] + S = sound(pick(oursound)) + if(pref.species_sound == "None" || oursound == null) + to_chat(user, span_warning("This set does not have scream sounds!")) + return TOPIC_REFRESH + S.frequency = pick(pref.voice_freq) + S.volume = 20 + SEND_SOUND(user, S) + return TOPIC_REFRESH + else if(href_list["pain_test"]) + var/sound/S + var/ourpref = pref.species_sound + var/oursound = get_species_sound(ourpref)["pain"] + S = sound(pick(oursound)) + if(pref.species_sound == "Unset") + oursound = get_species_sound(select_default_species_sound(pref))["pain"] + S = sound(pick(oursound)) + if(pref.species_sound == "None" || oursound == null) + to_chat(user, span_warning("This set does not have pain sounds!")) + return TOPIC_REFRESH + S.frequency = pick(pref.voice_freq) + S.volume = 20 + SEND_SOUND(user, S) + return TOPIC_REFRESH + else if(href_list["gasp_test"]) + var/sound/S + var/ourpref = pref.species_sound + var/oursound = get_species_sound(ourpref)["gasp"] + S = sound(pick(oursound)) + if(pref.species_sound == "Unset") + oursound = get_species_sound(select_default_species_sound(pref))["gasp"] + S = sound(pick(oursound)) + if(pref.species_sound == "None" || oursound == null) + to_chat(user, span_warning("This set does not have gasp sounds!")) + return TOPIC_REFRESH + S.frequency = pick(pref.voice_freq) + S.volume = 20 + SEND_SOUND(user, S) + return TOPIC_REFRESH + else if(href_list["death_test"]) + var/sound/S + var/ourpref = pref.species_sound + var/oursound = get_species_sound(ourpref)["death"] + S = sound(pick(oursound)) + if(pref.species_sound == "Unset") + oursound = get_species_sound(select_default_species_sound(pref))["death"] + S = sound(pick(oursound)) + if(pref.species_sound == "None" || oursound == null) + to_chat(user, span_warning("This set does not have death sounds!")) + return TOPIC_REFRESH + S.frequency = pick(pref.voice_freq) + S.volume = 20 + SEND_SOUND(user, S) + return TOPIC_REFRESH return ..(); #undef WEIGHT_CHANGE_MIN diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm index c15eb7c519..1efa93c186 100644 --- a/code/modules/client/preference_setup/vore/07_traits.dm +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -564,7 +564,7 @@ var/global/list/valid_bloodreagents = list("default",REAGENT_ID_IRON,REAGENT_ID_ for(var/T in pref.pos_traits + pref.neu_traits + pref.neg_traits) points_left -= GLOB.traits_costs[T] - var/traits_left = pref.max_traits - (pref.pos_traits.len + pref.neg_traits.len) + var/traits_left = pref.max_traits - pref.pos_traits.len // CHOMPEdit: Only positive traits have a slot limit, to prevent broken builds var/message = "Select a trait to learn more." if(mode != NEUTRAL_MODE) diff --git a/code/modules/client/preference_setup/vore/09_misc.dm b/code/modules/client/preference_setup/vore/09_misc.dm index 90b3546eee..d68b659602 100644 --- a/code/modules/client/preference_setup/vore/09_misc.dm +++ b/code/modules/client/preference_setup/vore/09_misc.dm @@ -5,6 +5,8 @@ /datum/category_item/player_setup_item/vore/misc/load_character(list/save_data) pref.show_in_directory = save_data["show_in_directory"] pref.directory_tag = save_data["directory_tag"] + pref.directory_gendertag = save_data["directory_gendertag"] + pref.directory_sexualitytag = save_data["directory_sexualitytag"] pref.directory_erptag = save_data["directory_erptag"] pref.directory_ad = save_data["directory_ad"] pref.sensorpref = save_data["sensorpref"] @@ -15,6 +17,8 @@ /datum/category_item/player_setup_item/vore/misc/save_character(list/save_data) save_data["show_in_directory"] = pref.show_in_directory save_data["directory_tag"] = pref.directory_tag + save_data["directory_gendertag"] = pref.directory_gendertag + save_data["directory_sexualitytag"] = pref.directory_sexualitytag save_data["directory_erptag"] = pref.directory_erptag save_data["directory_ad"] = pref.directory_ad save_data["sensorpref"] = pref.sensorpref @@ -33,6 +37,8 @@ /datum/category_item/player_setup_item/vore/misc/sanitize_character() pref.show_in_directory = sanitize_integer(pref.show_in_directory, 0, 1, initial(pref.show_in_directory)) pref.directory_tag = sanitize_inlist(pref.directory_tag, GLOB.char_directory_tags, initial(pref.directory_tag)) + pref.directory_gendertag = sanitize_inlist(pref.directory_gendertag, GLOB.char_directory_gendertags, initial(pref.directory_gendertag)) + pref.directory_sexualitytag = sanitize_inlist(pref.directory_sexualitytag, GLOB.char_directory_sexualitytags, initial(pref.directory_sexualitytag)) pref.directory_erptag = sanitize_inlist(pref.directory_erptag, GLOB.char_directory_erptags, initial(pref.directory_erptag)) pref.sensorpref = sanitize_integer(pref.sensorpref, 1, GLOB.sensorpreflist.len, initial(pref.sensorpref)) pref.capture_crystal = sanitize_integer(pref.capture_crystal, 0, 1, initial(pref.capture_crystal)) @@ -43,6 +49,8 @@ . += "
" . += span_bold("Appear in Character Directory:") + " [pref.show_in_directory ? "Yes" : "No"]
" . += span_bold("Character Directory Vore Tag:") + " [pref.directory_tag]
" + . += span_bold("Character Directory Gender:") + " [pref.directory_gendertag]
" + . += span_bold("Character Directory Sexuality:") + " [pref.directory_sexualitytag]
" . += span_bold("Character Directory ERP Tag:") + " [pref.directory_erptag]
" . += span_bold("Character Directory Advertisement:") + " Set Directory Ad
" . += span_bold("Suit Sensors Preference:") + " [GLOB.sensorpreflist[pref.sensorpref]]
" @@ -62,6 +70,18 @@ return pref.directory_tag = new_tag return TOPIC_REFRESH + else if(href_list["directory_gendertag"]) + var/new_gendertag = tgui_input_list(user, "Pick a new Gender tag for the character directory. This is YOUR gender, not what you prefer.", "Character Gender Tag", GLOB.char_directory_gendertags, pref.directory_gendertag) + if(!new_gendertag) + return + pref.directory_gendertag = new_gendertag + return TOPIC_REFRESH + else if(href_list["directory_sexualitytag"]) + var/new_sexualitytag = tgui_input_list(user, "Pick a new Sexuality/Orientation tag for the character directory", "Character Sexuality/Orientation Tag", GLOB.char_directory_sexualitytags, pref.directory_sexualitytag) + if(!new_sexualitytag) + return + pref.directory_sexualitytag = new_sexualitytag + return TOPIC_REFRESH else if(href_list["directory_erptag"]) var/new_erptag = tgui_input_list(user, "Pick a new ERP tag for the character directory", "Character ERP Tag", GLOB.char_directory_erptags, pref.directory_erptag) if(!new_erptag) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index cf77959927..61620146ea 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -613,6 +613,9 @@ var/list/preferences_datums = list() character.ooc_notes = read_preference(/datum/preference/text/living/ooc_notes) character.ooc_notes_dislikes = read_preference(/datum/preference/text/living/ooc_notes_dislikes) character.ooc_notes_likes = read_preference(/datum/preference/text/living/ooc_notes_likes) + character.ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs) + character.ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes) + character.ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style) character.weight = weight_vr character.weight_gain = weight_gain diff --git a/code/modules/client/preferences/types/character/general/01_basic.dm b/code/modules/client/preferences/types/character/general/01_basic.dm index e2a9652954..d466b39b90 100644 --- a/code/modules/client/preferences/types/character/general/01_basic.dm +++ b/code/modules/client/preferences/types/character/general/01_basic.dm @@ -115,7 +115,6 @@ target.ooc_notes_dislikes = value return -// CHOMP specific, but added here not to forget /datum/preference/toggle/living/ooc_notes_style category = PREFERENCE_CATEGORY_MANUALLY_RENDERED savefile_key = "OOC_Notes_System" @@ -124,7 +123,7 @@ can_randomize = FALSE /datum/preference/toggle/living/ooc_notes_style/apply_to_living(mob/living/target, value) - // target.ooc_notes_style // Not available on virgo + target.ooc_notes_style = value return /datum/preference/text/living/ooc_notes_maybes @@ -135,7 +134,7 @@ can_randomize = FALSE /datum/preference/text/living/ooc_notes_maybes/apply_to_living(mob/living/target, value) - // target.ooc_notes_maybes = value // Not available on virgo + target.ooc_notes_maybes = value return /datum/preference/text/living/ooc_notes_favs @@ -146,7 +145,7 @@ can_randomize = FALSE /datum/preference/text/living/ooc_notes_favs/apply_to_living(mob/living/target, value) - // target.ooc_notes_favs = value // Not available on virgo + target.ooc_notes_favs = value return /datum/preference/toggle/human/name_is_always_random diff --git a/code/modules/client/preferences/types/game/misc.dm b/code/modules/client/preferences/types/game/misc.dm index 85e6d47c3e..dd36250210 100644 --- a/code/modules/client/preferences/types/game/misc.dm +++ b/code/modules/client/preferences/types/game/misc.dm @@ -106,3 +106,13 @@ /datum/preference/text/lastchangelog/is_accessible(datum/preferences/preferences) ..() return FALSE + +/datum/preference/toggle/random_emote_pitch + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "EMOTE_VARY" + savefile_identifier = PREFERENCE_PLAYER + +/datum/preference/toggle/autotranscore + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "AUTOTRANSCORE" + savefile_identifier = PREFERENCE_PLAYER diff --git a/code/modules/client/preferences_vr.dm b/code/modules/client/preferences_vr.dm index c3a8d182bc..fdb793a1d7 100644 --- a/code/modules/client/preferences_vr.dm +++ b/code/modules/client/preferences_vr.dm @@ -2,6 +2,8 @@ var/show_in_directory = 1 //Show in Character Directory var/directory_tag = "Unset" //Sorting tag to use in character directory var/directory_erptag = "Unset" //ditto, but for non-vore scenes + var/directory_gendertag = "Unset" // Gender stuff! + var/directory_sexualitytag = "Unset" // Sexuality! var/directory_ad = "" //Advertisement stuff to show in character directory. var/sensorpref = 5 //Set character's suit sensor level var/capture_crystal = 1 //Whether or not someone is able to be caught with capture crystals diff --git a/code/modules/client/verbs/character_directory.dm b/code/modules/client/verbs/character_directory.dm index 0d9cab006c..4352fd0af4 100644 --- a/code/modules/client/verbs/character_directory.dm +++ b/code/modules/client/verbs/character_directory.dm @@ -34,10 +34,16 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) data["personalVisibility"] = user.mind.show_in_directory data["personalTag"] = user.mind.directory_tag || "Unset" data["personalErpTag"] = user.mind.directory_erptag || "Unset" + data["personalEventTag"] = GLOB.vantag_choices_list[user.mind.vantag_preference] + data["personalGenderTag"] = user.mind.directory_gendertag || "Unset" + data["personalSexualityTag"] = user.mind.directory_sexualitytag || "Unset" else if (user?.client?.prefs) data["personalVisibility"] = user.client.prefs.show_in_directory data["personalTag"] = user.client.prefs.directory_tag || "Unset" data["personalErpTag"] = user.client.prefs.directory_erptag || "Unset" + data["personalEventTag"] = GLOB.vantag_choices_list[user.client.prefs.vantag_preference] + data["personalGenderTag"] = user.client.prefs.directory_gendertag || "Unset" + data["personalSexualityTag"] = user.client.prefs.directory_sexualitytag || "Unset" return data @@ -55,6 +61,14 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) var/name = null var/species = null var/ooc_notes = null + var/ooc_notes_favs = null + var/ooc_notes_likes = null + var/ooc_notes_maybes = null + var/ooc_notes_dislikes = null + var/ooc_notes_style = null + var/gendertag = null + var/sexualitytag = null + var/eventtag = GLOB.vantag_choices_list[VANTAG_NONE] var/flavor_text = null var/tag var/erptag @@ -63,35 +77,67 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) tag = C.mob.mind.directory_tag || "Unset" erptag = C.mob.mind.directory_erptag || "Unset" character_ad = C.mob.mind.directory_ad + gendertag = C.mob.mind.directory_gendertag || "Unset" + sexualitytag = C.mob.mind.directory_sexualitytag || "Unset" + eventtag = GLOB.vantag_choices_list[C.mob.mind.vantag_preference] else tag = C.prefs.directory_tag || "Unset" erptag = C.prefs.directory_erptag || "Unset" character_ad = C.prefs.directory_ad + gendertag = C.prefs.directory_gendertag || "Unset" + sexualitytag = C.prefs.directory_sexualitytag || "Unset" + eventtag = GLOB.vantag_choices_list[C.prefs.vantag_preference] if(ishuman(C.mob)) var/mob/living/carbon/human/H = C.mob - //if(data_core && GLOB.data_core.general) - // if(!find_general_record("name", H.real_name)) - // if(!find_record("name", H.real_name, data_core.hidden_general)) - // continue - name = H.real_name + var/strangername = H.real_name + if(GLOB.data_core && GLOB.data_core.general) + if(!find_general_record("name", H.real_name)) + if(!find_record("name", H.real_name, GLOB.data_core.hidden_general)) + strangername = "unknown" + name = strangername species = "[H.custom_species ? H.custom_species : H.species.name]" ooc_notes = H.ooc_notes - if(H.ooc_notes_likes) - ooc_notes += "\n\nLIKES\n\n[H.ooc_notes_likes]" - if(H.ooc_notes_dislikes) - ooc_notes += "\n\nDISLIKES\n\n[H.ooc_notes_dislikes]" - flavor_text = H.flavor_texts["general"] + if(H.ooc_notes_style && (H.ooc_notes_favs || H.ooc_notes_likes || H.ooc_notes_maybes || H.ooc_notes_dislikes)) + ooc_notes = H.ooc_notes + "\n\n" + ooc_notes_favs = H.ooc_notes_favs + ooc_notes_likes = H.ooc_notes_likes + ooc_notes_maybes = H.ooc_notes_maybes + ooc_notes_dislikes = H.ooc_notes_dislikes + ooc_notes_style = H.ooc_notes_style + else + if(H.ooc_notes_favs) + ooc_notes += "\n\nFAVOURITES\n\n[H.ooc_notes_favs]" + if(H.ooc_notes_likes) + ooc_notes += "\n\nLIKES\n\n[H.ooc_notes_likes]" + if(H.ooc_notes_maybes) + ooc_notes += "\n\nMAYBES\n\n[H.ooc_notes_maybes]" + if(H.ooc_notes_dislikes) + ooc_notes += "\n\nDISLIKES\n\n[H.ooc_notes_dislikes]" + if(LAZYLEN(H.flavor_texts)) + flavor_text = H.flavor_texts["general"] if(isAI(C.mob)) var/mob/living/silicon/ai/A = C.mob name = A.name species = "Artificial Intelligence" ooc_notes = A.ooc_notes - if(A.ooc_notes_likes) - ooc_notes += "\n\nLIKES\n\n[A.ooc_notes_likes]" - if(A.ooc_notes_dislikes) - ooc_notes += "\n\nDISLIKES\n\n[A.ooc_notes_dislikes]" + if(A.ooc_notes_style && (A.ooc_notes_favs || A.ooc_notes_likes || A.ooc_notes_maybes || A.ooc_notes_dislikes)) + ooc_notes = A.ooc_notes + "\n\n" + ooc_notes_favs = A.ooc_notes_favs + ooc_notes_likes = A.ooc_notes_likes + ooc_notes_maybes = A.ooc_notes_maybes + ooc_notes_dislikes = A.ooc_notes_dislikes + ooc_notes_style = A.ooc_notes_style + else + if(A.ooc_notes_favs) + ooc_notes += "\n\nFAVOURITES\n\n[A.ooc_notes_favs]" + if(A.ooc_notes_likes) + ooc_notes += "\n\nLIKES\n\n[A.ooc_notes_likes]" + if(A.ooc_notes_maybes) + ooc_notes += "\n\nMAYBES\n\n[A.ooc_notes_maybes]" + if(A.ooc_notes_dislikes) + ooc_notes += "\n\nDISLIKES\n\n[A.ooc_notes_dislikes]" flavor_text = null // No flavor text for AIs :c @@ -102,10 +148,22 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) name = R.name species = "[R.modtype] [R.braintype]" ooc_notes = R.ooc_notes - if(R.ooc_notes_likes) - ooc_notes += "\n\nLIKES\n\n[R.ooc_notes_likes]" - if(R.ooc_notes_dislikes) - ooc_notes += "\n\nDISLIKES\n\n[R.ooc_notes_dislikes]" + if(R.ooc_notes_style && (R.ooc_notes_favs || R.ooc_notes_likes || R.ooc_notes_maybes || R.ooc_notes_dislikes)) + ooc_notes = R.ooc_notes + "\n\n" + ooc_notes_favs = R.ooc_notes_favs + ooc_notes_likes = R.ooc_notes_likes + ooc_notes_maybes = R.ooc_notes_maybes + ooc_notes_dislikes = R.ooc_notes_dislikes + ooc_notes_style = R.ooc_notes_style + else + if(R.ooc_notes_favs) + ooc_notes += "\n\nFAVOURITES\n\n[R.ooc_notes_favs]" + if(R.ooc_notes_likes) + ooc_notes += "\n\nLIKES\n\n[R.ooc_notes_likes]" + if(R.ooc_notes_maybes) + ooc_notes += "\n\nMAYBES\n\n[R.ooc_notes_maybes]" + if(R.ooc_notes_dislikes) + ooc_notes += "\n\nDISLIKES\n\n[R.ooc_notes_dislikes]" flavor_text = R.flavor_text @@ -114,23 +172,45 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) name = P.name species = "pAI" ooc_notes = P.ooc_notes - if(P.ooc_notes_likes) - ooc_notes += "\n\nLIKES\n\n[P.ooc_notes_likes]" - if(P.ooc_notes_dislikes) - ooc_notes += "\n\nDISLIKES\n\n[P.ooc_notes_dislikes]" - + if(P.ooc_notes_style && (P.ooc_notes_favs || P.ooc_notes_likes || P.ooc_notes_maybes || P.ooc_notes_dislikes)) + ooc_notes = P.ooc_notes + "\n\n" + ooc_notes_favs = P.ooc_notes_favs + ooc_notes_likes = P.ooc_notes_likes + ooc_notes_maybes = P.ooc_notes_maybes + ooc_notes_dislikes = P.ooc_notes_dislikes + ooc_notes_style = P.ooc_notes_style + else + if(P.ooc_notes_favs) + ooc_notes += "\n\nFAVOURITES\n\n[P.ooc_notes_favs]" + if(P.ooc_notes_likes) + ooc_notes += "\n\nLIKES\n\n[P.ooc_notes_likes]" + if(P.ooc_notes_maybes) + ooc_notes += "\n\nMAYBES\n\n[P.ooc_notes_maybes]" + if(P.ooc_notes_dislikes) + ooc_notes += "\n\nDISLIKES\n\n[P.ooc_notes_dislikes]" flavor_text = P.flavor_text if(isanimal(C.mob)) var/mob/living/simple_mob/S = C.mob name = S.name - species = initial(S.name) + species = S.character_directory_species() ooc_notes = S.ooc_notes - if(S.ooc_notes_likes) - ooc_notes += "\n\nLIKES\n\n[S.ooc_notes_likes]" - if(S.ooc_notes_dislikes) - ooc_notes += "\n\nDISLIKES\n\n[S.ooc_notes_dislikes]" - + if(S.ooc_notes_style && (S.ooc_notes_favs || S.ooc_notes_likes || S.ooc_notes_maybes || S.ooc_notes_dislikes)) + ooc_notes = S.ooc_notes + "\n\n" + ooc_notes_favs = S.ooc_notes_favs + ooc_notes_likes = S.ooc_notes_likes + ooc_notes_maybes = S.ooc_notes_maybes + ooc_notes_dislikes = S.ooc_notes_dislikes + ooc_notes_style = S.ooc_notes_style + else + if(S.ooc_notes_favs) + ooc_notes += "\n\nFAVOURITES\n\n[S.ooc_notes_favs]" + if(S.ooc_notes_likes) + ooc_notes += "\n\nLIKES\n\n[S.ooc_notes_likes]" + if(S.ooc_notes_maybes) + ooc_notes += "\n\nMAYBES\n\n[S.ooc_notes_maybes]" + if(S.ooc_notes_dislikes) + ooc_notes += "\n\nDISLIKES\n\n[S.ooc_notes_dislikes]" flavor_text = S.desc // It's okay if we fail to find OOC notes and flavor text @@ -141,6 +221,14 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) directory_mobs.Add(list(list( "name" = name, "species" = species, + "ooc_notes_favs" = ooc_notes_favs, + "ooc_notes_likes" = ooc_notes_likes, + "ooc_notes_maybes" = ooc_notes_maybes, + "ooc_notes_dislikes" = ooc_notes_dislikes, + "ooc_notes_style" = ooc_notes_style, + "gendertag" = gendertag, + "sexualitytag" = sexualitytag, + "eventtag" = eventtag, "ooc_notes" = ooc_notes, "tag" = tag, "erptag" = erptag, @@ -203,6 +291,24 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) if(isnull(new_ad)) return return set_for_mind_or_prefs(user, action, new_ad, can_set_prefs, can_set_mind) + if("setGenderTag") + var/list/new_gendertag = tgui_input_list(usr, "Pick a new Gender tag for the character directory. This is YOUR gender, not what you prefer.", "Character Gender Tag", GLOB.char_directory_gendertags) + if(!new_gendertag) + return + return set_for_mind_or_prefs(user, action, new_gendertag, can_set_prefs, can_set_mind) + if("setSexualityTag") + var/list/new_sexualitytag = tgui_input_list(usr, "Pick a new Sexuality/Orientation tag for the character directory", "Character Sexuality/Orientation Tag", GLOB.char_directory_sexualitytags) + if(!new_sexualitytag) + return + return set_for_mind_or_prefs(user, action, new_sexualitytag, can_set_prefs, can_set_mind) + if("setEventTag") + var/list/names_list = list() + for(var/C in GLOB.vantag_choices_list) + names_list[GLOB.vantag_choices_list[C]] = C + var/list/new_eventtag = tgui_input_list(usr, "Pick your preference for event involvement", "Event Preference Tag", usr?.client?.prefs?.vantag_preference, names_list) + if(!new_eventtag) + return + return set_for_mind_or_prefs(user, action, names_list[new_eventtag], can_set_prefs, can_set_mind) /datum/character_directory/proc/set_for_mind_or_prefs(mob/user, action, new_value, can_set_prefs, can_set_mind) can_set_prefs &&= !!user.client.prefs @@ -235,3 +341,18 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) if (can_set_mind) user.mind.directory_ad = new_value return TRUE + if ("setEventTag") + if (can_set_prefs) + user.client.prefs.vantag_preference = new_value + if (can_set_mind) + user.mind.vantag_preference = new_value + if ("setGenderTag") + if (can_set_prefs) + user.client.prefs.directory_gendertag = new_value + if (can_set_mind) + user.mind.directory_gendertag = new_value + if ("setSexualityTag") + if (can_set_prefs) + user.client.prefs.directory_sexualitytag = new_value + if (can_set_mind) + user.mind.directory_sexualitytag = new_value diff --git a/code/modules/emotes/emote_define.dm b/code/modules/emotes/emote_define.dm index 38c4868a22..ba035b627f 100644 --- a/code/modules/emotes/emote_define.dm +++ b/code/modules/emotes/emote_define.dm @@ -189,7 +189,11 @@ var/global/list/emotes_by_key if(islist(sound_to_play) && length(sound_to_play)) sound_to_play = pick(sound_to_play) if(sound_to_play) - playsound(user.loc, sound_to_play, use_sound["vol"], sound_vary, frequency = null, preference = sound_preferences) //VOREStation Add - Preference + if(istype(user, /mob)) + var/mob/u = user + playsound(user.loc, sound_to_play, use_sound["vol"], u.read_preference(/datum/preference/toggle/random_emote_pitch) && sound_vary, extrarange = use_sound["exr"], frequency = u.voice_freq, preference = sound_preferences, volume_channel = use_sound["volchannel"]) + else + playsound(user.loc, sound_to_play, use_sound["vol"], sound_vary, extrarange = use_sound["exr"], frequency = null, preference = sound_preferences, volume_channel = use_sound["volchannel"]) /decl/emote/proc/mob_can_use(var/mob/user) return istype(user) && user.stat != DEAD && (type in user.get_available_emotes()) diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index ce911762b9..c8de7e1223 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -520,6 +520,9 @@ ooc_notes = AI.ooc_notes ooc_notes_likes = AI.ooc_notes_likes ooc_notes_dislikes = AI.ooc_notes_dislikes + ooc_notes_favs = AI.ooc_notes_favs + ooc_notes_maybes = AI.ooc_notes_maybes + ooc_notes_style = AI.ooc_notes_style to_chat(src, span_notice("You feel a tingle in your circuits as your systems interface with \the [initial(src.name)].")) if(AI.idcard.GetAccess()) botcard.access |= AI.idcard.GetAccess() @@ -531,6 +534,9 @@ AI.ooc_notes = ooc_notes AI.ooc_notes_likes = ooc_notes_likes AI.ooc_notes_dislikes = ooc_notes_dislikes + AI.ooc_notes_favs = ooc_notes_favs + AI.ooc_notes_maybes = ooc_notes_maybes + AI.ooc_notes_style = ooc_notes_style paicard.forceMove(src.loc) paicard = null name = initial(name) diff --git a/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm b/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm index 8ab66fa08a..512d4d44d8 100644 --- a/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm +++ b/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm @@ -378,6 +378,9 @@ blob.ooc_notes = ooc_notes blob.ooc_notes_likes = ooc_notes_likes blob.ooc_notes_dislikes = ooc_notes_dislikes + blob.ooc_notes_favs = ooc_notes_favs + blob.ooc_notes_maybes = ooc_notes_maybes + blob.ooc_notes_style = ooc_notes_style blob.transforming = FALSE blob.name = name blob.real_name = real_name @@ -467,6 +470,9 @@ ooc_notes = blob.ooc_notes // Updating notes incase they change them in blob form. ooc_notes_likes = blob.ooc_notes_likes ooc_notes_dislikes = blob.ooc_notes_dislikes + ooc_notes_favs = blob.ooc_notes_favs + ooc_notes_maybes = blob.ooc_notes_maybes + ooc_notes_style = blob.ooc_notes_style transforming = FALSE blob.name = "Promethean Blob" var/obj/item/hat = blob.hat diff --git a/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm b/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm index daa2c399c6..0f91d6df4b 100644 --- a/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm +++ b/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm @@ -475,6 +475,9 @@ blob.ooc_notes = ooc_notes blob.ooc_notes_likes = ooc_notes_likes blob.ooc_notes_dislikes = ooc_notes_dislikes + blob.ooc_notes_favs = ooc_notes_favs + blob.ooc_notes_maybes = ooc_notes_maybes + blob.ooc_notes_style = ooc_notes_style temporary_form = blob var/obj/item/radio/R = null if(isradio(l_ear)) @@ -602,6 +605,9 @@ ooc_notes = blob.ooc_notes // Lets give the protean any updated notes from blob form. ooc_notes_likes = blob.ooc_notes_likes ooc_notes_dislikes = blob.ooc_notes_dislikes + ooc_notes_favs = blob.ooc_notes_favs + ooc_notes_maybes = blob.ooc_notes_maybes + ooc_notes_style = blob.ooc_notes_style temporary_form = null //Transfer vore organs diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 8263274955..67006c76ab 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1433,6 +1433,36 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() struggle_anim_taur = FALSE update_vore_tail_sprite() +/mob/living/carbon/human/proc/GetAppearanceFromPrefs(var/flavourtext, var/oocnotes) + /* Jank code that effectively creates the client's mob from save, then copies its appearance to our current mob. + Intended to be used with shapeshifter species so we don't reset their organs in doing so.*/ + if(client.prefs) + var/mob/living/carbon/human/dummy/mannequin/Dummy = get_mannequin(client.ckey) + client.prefs.copy_to(Dummy) + //Important, since some sprites only work for specific species + /* Probably not needed anymore since impersonate_bodytype no longer exists + if(Dummy.species.base_species == "Promethean") + impersonate_bodytype = "Human" + else + impersonate_bodytype = Dummy.species.base_species + */ + custom_species = Dummy.custom_species + var/list/traits = dna.species_traits.Copy() + dna = Dummy.dna.Clone() + dna.species_traits.Cut() + dna.species_traits = traits.Copy() + UpdateAppearance() + icon = Dummy.icon + if(flavourtext) + flavor_texts = client.prefs.flavor_texts.Copy() + if(oocnotes) + ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes) + ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes) + ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes) + ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs) + ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes) + ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style) + //Human Overlays Indexes///////// #undef MUTATIONS_LAYER #undef SKIN_LAYER diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 4fd58a9a29..1895a3fbb7 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1477,3 +1477,39 @@ drop.invisibility = 0 //else // come up with drips for other mobs someday + +/mob/living/proc/set_metainfo_favs(var/mob/user, var/reopen = TRUE) + if(user != src) + return + var/new_metadata = strip_html_simple(tgui_input_text(user, "Enter any information you'd like others to see relating to your FAVOURITE roleplay preferences. This will not be saved permanently unless you click save in the OOC notes panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(ooc_notes_favs), multiline = TRUE, prevent_enter = TRUE)) + if(new_metadata && CanUseTopic(user)) + if(new_metadata == "!clear") + new_metadata = "" + ooc_notes_favs = new_metadata + client.prefs.update_preference_by_type(/datum/preference/text/living/ooc_notes_favs, new_metadata) + to_chat(user, span_filter_notice("OOC note favs have been updated. Don't forget to save!")) + log_admin("[key_name(user)] updated their OOC note favs mid-round.") + if(reopen) + ooc_notes_window(user) + +/mob/living/proc/set_metainfo_maybes(var/mob/user, var/reopen = TRUE) + if(user != src) + return + var/new_metadata = strip_html_simple(tgui_input_text(user, "Enter any information you'd like others to see relating to your MAYBE roleplay preferences. This will not be saved permanently unless you click save in the OOC notes panel! Type \"!clear\" to empty.", "Game Preference" , html_decode(ooc_notes_maybes), multiline = TRUE, prevent_enter = TRUE)) + if(new_metadata && CanUseTopic(user)) + if(new_metadata == "!clear") + new_metadata = "" + ooc_notes_maybes = new_metadata + client.prefs.update_preference_by_type(/datum/preference/text/living/ooc_notes_maybes, new_metadata) + to_chat(user, span_filter_notice("OOC note maybes have been updated. Don't forget to save!")) + log_admin("[key_name(user)] updated their OOC note maybes mid-round.") + if(reopen) + ooc_notes_window(user) + +/mob/living/proc/set_metainfo_ooc_style(var/mob/user, var/reopen = TRUE) + if(user != src) + return + ooc_notes_style = !ooc_notes_style + client.prefs.update_preference_by_type(/datum/preference/toggle/living/ooc_notes_style, ooc_notes_style) + if(reopen) + ooc_notes_window(user) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index c4344676f8..d9b4106bcf 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -112,3 +112,7 @@ var/mob/living/tf_form // Shapeshifter shenanigans var/tf_form_ckey + + var/ooc_notes_favs = null + var/ooc_notes_maybes = null + var/ooc_notes_style = FALSE diff --git a/code/modules/mob/living/living_vr.dm b/code/modules/mob/living/living_vr.dm index 1eb3684979..8bc8c2b365 100644 --- a/code/modules/mob/living/living_vr.dm +++ b/code/modules/mob/living/living_vr.dm @@ -91,11 +91,49 @@ if(!ooc_notes) return var/msg = ooc_notes - if(ooc_notes_likes) - msg += "

LIKES

[ooc_notes_likes]" - if(ooc_notes_dislikes) - msg += "

DISLIKES

[ooc_notes_dislikes]" - to_chat(user, span_chatexport("[src]'s Metainfo:
[msg]")) + if(ooc_notes_style && (ooc_notes_favs || ooc_notes_likes || ooc_notes_maybes || ooc_notes_dislikes) && !user.client?.prefs?.read_preference(/datum/preference/toggle/vchat_enable)) // Oldchat hates proper formatting + msg += "

" + msg += "" + if(ooc_notes_favs) + msg += "" + if(ooc_notes_likes) + msg += "" + if(ooc_notes_maybes) + msg += "" + if(ooc_notes_dislikes) + msg += "" + msg += "" + if(ooc_notes_favs) + msg += "" + if(ooc_notes_likes) + msg += "" + if(ooc_notes_maybes) + msg += "" + if(ooc_notes_dislikes) + msg += "" + msg += "
\t[span_blue("FAVOURITES")]\t[span_green("LIKES")]\t[span_yellow("MAYBES")]\t[span_red("DISLIKES")]
" + for(var/line in splittext(ooc_notes_favs, "\n")) + msg += "\t[line]\n" + msg += "" + for(var/line in splittext(ooc_notes_likes, "\n")) + msg += "\t[line]\n" + msg += "" + for(var/line in splittext(ooc_notes_maybes, "\n")) + msg += "\t[line]\n" + msg += "" + for(var/line in splittext(ooc_notes_dislikes, "\n")) + msg += "\t[line]\n" + msg += "
" + else + if(ooc_notes_favs) + msg += "

[span_blue("FAVOURITES")]
[ooc_notes_favs]" + if(ooc_notes_likes) + msg += "

[span_green("LIKES")]
[ooc_notes_likes]" + if(ooc_notes_maybes) + msg += "

[span_yellow("MAYBES")]
[ooc_notes_maybes]" + if(ooc_notes_dislikes) + msg += "

[span_red("DISLIKES")]
[ooc_notes_dislikes]" + to_chat(user, span_chatexport("[src]'s Metainfo:
[msg]")) /mob/living/verb/set_custom_link() set name = "Set Custom Link" diff --git a/code/modules/mob/living/ooc_notes.dm b/code/modules/mob/living/ooc_notes.dm index 58db82d046..bf824c6648 100644 --- a/code/modules/mob/living/ooc_notes.dm +++ b/code/modules/mob/living/ooc_notes.dm @@ -3,14 +3,27 @@ return //I tried to get it to accept things like emojis and all that, but, it wouldn't do! It would be cool if it did. var/notes = replacetext(html_decode(src.ooc_notes), "\n", "
") + var/favs = replacetext(html_decode(src.ooc_notes_favs), "\n", "
") var/likes = replacetext(html_decode(src.ooc_notes_likes), "\n", "
") + var/maybes = replacetext(html_decode(src.ooc_notes_maybes), "\n", "
") var/dislikes = replacetext(html_decode(src.ooc_notes_dislikes), "\n", "
") + var/style = src.ooc_notes_style var/dat = {" "} @@ -44,8 +75,21 @@ Print to chat - "} + if(user == src) + if(style) + dat += {" + + Lists + + "} + else + dat += {" + + Fields + + "} + dat += {""} if(user == src) dat += {" @@ -59,12 +103,36 @@ dat += {"
-

[notes]

+
+

[notes]

+
+
"} + if(style) + dat += {"
"} + if(favs || user == src) + dat += "
" + span_bold("
Favourites
") + "
" + if(user == src) + dat += {" + + +
+ Edit +
+ "} + if(favs) + dat += {" +
+

[favs]

+
"} + + if(style) + dat += {"
"} + dat += {"
"} if(likes || user == src) - dat += {"
Likes
"} + dat += "
" + span_bold("
Likes
") + "
" if(user == src) dat += {" @@ -77,12 +145,36 @@ if(likes) dat += {"
-

[likes]

+

[likes]

"} - if(dislikes || user == src) + + if(style) + dat += {""} + dat += {"
"} + if(maybes || user == src) + dat += "
" + span_bold("
Maybes
") + "
" + if(user == src) dat += {" -
-
Dislikes
"} +
+ +
+ Edit +
+ "} + + if(maybes) + dat += {" +
+

[maybes]

+
+ "} + + + if(style) + dat += {"
"} + dat += {"
"} + if(dislikes || user == src) + dat += "
" + span_bold("
Dislikes
") + "
" if(user == src) dat += {" @@ -95,11 +187,13 @@ if(dislikes) dat += {"
-

[dislikes]

+

[dislikes]

- - "} + if(style) + dat += {""} + dat+= {" + "} var/key = "ooc_notes[src.real_name]" //Generate a unique key so we can make unique clones of windows, that way we can have more than one if(src.ckey) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ed921e905f..178d5eeff3 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -218,6 +218,9 @@ var/list/ai_verbs_default = list( ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes) ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes) ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes) + ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs) + ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes) + ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style) private_notes = client.prefs.read_preference(/datum/preference/text/living/private_notes) if (malf && !(mind in malf.current_antagonists)) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 11d45ff662..90ba3909ef 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -155,6 +155,9 @@ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes) ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes) ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes) + ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs) + ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes) + ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style) private_notes = client.prefs.read_preference(/datum/preference/text/living/private_notes) src << sound('sound/effects/pai_login.ogg', volume = 75) //VOREStation Add diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index d2494f6a98..4f2c11c5d1 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -411,6 +411,9 @@ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes) ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes) ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes) + ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs) + ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes) + ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style) private_notes = client.prefs.read_preference(/datum/preference/text/living/private_notes) custom_link = client.prefs.custom_link diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm index dd452c44f9..8a884d782b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm @@ -15,9 +15,16 @@ var/pred_ooc_notes var/pred_ooc_likes var/pred_ooc_dislikes + var/pred_ooc_favs + var/pred_ooc_maybes + var/pred_ooc_style + var/prey_ooc_favs + var/prey_ooc_maybes + var/prey_ooc_style var/prey_ooc_notes var/prey_ooc_likes var/prey_ooc_dislikes + var/was_mob /mob/living/dominated_brain/Initialize(mapload, var/mob/living/pred, preyname, var/mob/living/prey) prey_name = preyname @@ -112,6 +119,9 @@ prey_goes_here.ooc_notes = prey_ooc_notes prey_goes_here.ooc_notes_likes = prey_ooc_likes prey_goes_here.ooc_notes_dislikes = prey_ooc_dislikes + prey_goes_here.ooc_notes_favs = prey_ooc_favs + prey_goes_here.ooc_notes_maybes = prey_ooc_maybes + prey_goes_here.ooc_notes_style = prey_ooc_style add_verb(prey_goes_here, /mob/living/dominated_brain/proc/cease_this_foolishness) @@ -128,6 +138,9 @@ prey_goes_here.ooc_notes = prey_ooc_notes prey_goes_here.ooc_notes_likes = prey_ooc_likes prey_goes_here.ooc_notes_dislikes = prey_ooc_dislikes + prey_goes_here.ooc_notes_favs = prey_ooc_favs + prey_goes_here.ooc_notes_maybes = prey_ooc_maybes + prey_goes_here.ooc_notes_style = prey_ooc_style /////////////////// @@ -140,6 +153,9 @@ pred_body.ooc_notes = pred_ooc_notes pred_body.ooc_notes_likes = pred_ooc_likes pred_body.ooc_notes_dislikes = pred_ooc_dislikes + pred_body.ooc_notes_favs = pred_ooc_favs + pred_body.ooc_notes_maybes = pred_ooc_maybes + pred_body.ooc_notes_style = pred_ooc_style log_and_message_admins("is now controlled by [pred_body.ckey]. They were restored to control through prey domination, and had been controlled by [prey_ckey].", pred_body) pred_body.absorb_langs() pred_body.prey_controlled = FALSE @@ -173,6 +189,7 @@ set category = "Abilities.Vore" set name = "Dominate Predator" set desc = "Connect to and dominate the brain of your predator." + var/is_mob = FALSE // - tracks if character is a non player mob TODO: Add var/mob/living/pred var/mob/living/prey = src @@ -196,9 +213,6 @@ to_chat(prey, span_warning("[pred] is unable to be dominated.")) return - if(!pred.ckey) - to_chat(prey, span_notice("\The [pred] isn't able to be dominated.")) - return if(isrobot(pred) && jobban_isbanned(prey, JOB_CYBORG)) to_chat(prey, span_warning("Forces beyond your comprehension forbid you from taking control of [pred].")) return @@ -212,11 +226,21 @@ return to_chat(prey, span_notice("You attempt to exert your control over \the [pred]...")) log_admin("[key_name_admin(prey)] attempted to take over [pred].") - if(tgui_alert(pred, "\The [prey] has elected to attempt to take control of you. Is this something you will allow to happen?", "Allow Prey Domination",list("No","Yes")) != "Yes") - to_chat(prey, span_warning("\The [pred] declined your request for control.")) - return - if(tgui_alert(pred, "Are you sure? If you should decide to revoke this, you will have the ability to do so in your 'Abilities' tab.", "Allow Prey Domination",list("No","Yes")) != "Yes") - return + + if(pred.ckey) //check if body is assigned to another player currently + if(tgui_alert(pred, "\The [prey] has elected to attempt to take control of you. Is this something you will allow to happen?", "Allow Prey Domination",list("No","Yes")) != "Yes") + to_chat(prey, span_warning("\The [pred] declined your request for control.")) + return + if(tgui_alert(pred, "Are you sure? If you should decide to revoke this, you will have the ability to do so in your 'Abilities' tab.", "Allow Prey Domination",list("No","Yes")) != "Yes") + return + else if(!pred.client && ("original_player" in pred.vars)) //check if the body belonged to a player and give proper log about it while preparing it + log_and_message_admins("[key_name_admin(prey)] is taking control over [pred] while they are out of their body.") + pred.ckey="DOMPLY[rand(100000,999999)]" + is_mob = TRUE + else //at this point we end up with a mob + pred.ckey = "DOMMOB[rand(100000,999999)]" //this is cursed, but it does work and is cleaned up after + is_mob = TRUE + to_chat(pred, span_warning("You can feel the will of another overwriting your own, control of your body being sapped away from you...")) to_chat(prey, span_warning("You can feel the will of your host diminishing as you exert your will over them!")) if(!do_after(prey, 10 SECONDS, exclusive = TRUE)) @@ -241,6 +265,12 @@ pred_brain.prey_ooc_notes = prey.ooc_notes pred_brain.prey_ooc_likes = prey.ooc_notes_likes pred_brain.prey_ooc_dislikes = prey.ooc_notes_dislikes + pred_brain.prey_ooc_favs = prey.ooc_notes_favs + pred_brain.prey_ooc_maybes = prey.ooc_notes_maybes + pred_brain.prey_ooc_style = prey.ooc_notes_style + pred_brain.pred_ooc_favs = pred.ooc_notes_favs + pred_brain.pred_ooc_maybes = pred.ooc_notes_maybes + pred_brain.pred_ooc_style = pred.ooc_notes_style pred_brain.pred_ooc_notes = pred.ooc_notes pred_brain.pred_ooc_likes = pred.ooc_notes_likes pred_brain.pred_ooc_dislikes = pred.ooc_notes_dislikes @@ -256,6 +286,9 @@ pred.ooc_notes = pred_brain.prey_ooc_notes pred.ooc_notes_likes = pred_brain.prey_ooc_likes pred.ooc_notes_dislikes = pred_brain.prey_ooc_dislikes + pred.ooc_notes_favs = pred_brain.prey_ooc_favs + pred.ooc_notes_maybes = pred_brain.prey_ooc_maybes + pred.ooc_notes_style = pred_brain.prey_ooc_style add_verb(pred, /mob/proc/release_predator) @@ -268,6 +301,9 @@ if(delete_source) qdel(prey) + if(is_mob == 1) + pred_brain.was_mob = TRUE + /mob/proc/release_predator() set category = "Abilities.Vore" set name = "Restore Control" @@ -279,7 +315,12 @@ if(db.ckey == db.pred_ckey) to_chat(src, span_notice("You ease off of your control, releasing \the [db].")) to_chat(db, span_notice("You feel the alien presence fade, and restore control of your body to you of their own will...")) - db.restore_control() + if(db.was_mob) + db.pred_ckey = null + db.ckey = null + db.restore_control() + else + db.restore_control() return else continue @@ -317,6 +358,14 @@ possible_mobs |= L else continue + var/obj/item/grab/G = src.get_active_hand() + if(istype(G)) + var/mob/living/L = G.affecting + if(istype(L) && L.allow_mind_transfer) + if(G.state != GRAB_NECK) + possible_mobs |= "~~[L.name]~~ (reinforce grab first)" + else + possible_mobs |= L if(!possible_mobs) to_chat(src, span_warning("There are no valid targets inside of you.")) return @@ -324,6 +373,9 @@ if(!input) return var/mob/living/M = input + if(!istype(M)) + to_chat(src, span_warning("You must have a tighter grip to dominate this creature.")) + return if(!M.allow_mind_transfer) //check if the dominated mob pref is enabled to_chat(src, span_warning("[M] is unable to be dominated.")) return @@ -340,11 +392,13 @@ to_chat(M, span_warning("You can feel the will of another pulling you away from your body...")) to_chat(src, span_warning("You can feel the will of your prey diminishing as you gather them!")) + if(istype(G) && M == G.affecting) + src.visible_message(span_danger("[src] seems to be doing something to [M], resulting in [M]'s body looking increasingly drowsy with every passing moment!")) if(!do_after(src, 10 SECONDS, exclusive = TRUE)) to_chat(M, span_notice("The alien presence fades, and you are left along in your body...")) to_chat(src, span_notice("Your attempt to gather [M]'s mind has been interrupted.")) return - if(!isbelly(M.loc)) + if(!isbelly(M.loc) && !(istype(G) && M == G.affecting && G.state == GRAB_NECK)) //CHOMPEdit - Let dominate prey work on grabbed people to_chat(M, span_notice("The alien presence fades, and you are left along in your body...")) to_chat(src, span_notice("Your attempt to gather [M]'s mind has been interrupted.")) return @@ -364,6 +418,12 @@ db.ooc_notes = M.ooc_notes db.ooc_notes_likes = M.ooc_notes_likes db.ooc_notes_dislikes = M.ooc_notes_dislikes + db.ooc_notes_favs = M.ooc_notes_favs + db.ooc_notes_maybes = M.ooc_notes_maybes + db.ooc_notes_style = M.ooc_notes_style + db.prey_ooc_favs = M.ooc_notes_favs + db.prey_ooc_maybes = M.ooc_notes_maybes + db.prey_ooc_style = M.ooc_notes_style db.prey_ooc_likes = M.ooc_notes_likes db.prey_ooc_dislikes = M.ooc_notes_dislikes add_verb(db, /mob/living/dominated_brain/proc/cease_this_foolishness) @@ -374,6 +434,8 @@ log_admin("[db] ([db.ckey]) has agreed to [src]'s dominate prey attempt, and so no longer occupies their original body.") to_chat(src, span_notice("You feel your mind expanded as [M] is incorporated into you.")) to_chat(M, span_warning("Your mind is gathered into \the [src], becoming part of them...")) + if(istype(G) && M == G.affecting) + visible_message(span_danger("[src] seems to finish whatever they were doing to [M].")) /mob/living/dominated_brain/proc/cease_this_foolishness() set category = "Abilities.Vore" @@ -472,6 +534,12 @@ pred_brain.prey_ooc_notes = prey.ooc_notes pred_brain.prey_ooc_likes = prey.ooc_notes_likes pred_brain.prey_ooc_dislikes = prey.ooc_notes_dislikes + pred_brain.prey_ooc_favs = prey.ooc_notes_favs + pred_brain.prey_ooc_maybes = prey.ooc_notes_maybes + pred_brain.prey_ooc_style = prey.ooc_notes_style + pred_brain.pred_ooc_favs = pred.ooc_notes_favs + pred_brain.pred_ooc_maybes = pred.ooc_notes_maybes + pred_brain.pred_ooc_style = pred.ooc_notes_style pred_brain.pred_ooc_notes = pred.ooc_notes pred_brain.pred_ooc_likes = pred.ooc_notes_likes pred_brain.pred_ooc_dislikes = pred.ooc_notes_dislikes @@ -486,6 +554,9 @@ pred.ooc_notes = pred_brain.prey_ooc_notes pred.ooc_notes_likes = pred_brain.prey_ooc_likes pred.ooc_notes_dislikes = pred_brain.prey_ooc_dislikes + pred.ooc_notes_favs = pred_brain.prey_ooc_favs + pred.ooc_notes_maybes = pred_brain.prey_ooc_maybes + pred.ooc_notes_style = pred_brain.prey_ooc_style add_verb(pred, /mob/proc/release_predator) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm index 55172c2697..8720272b8c 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm @@ -22,11 +22,9 @@ ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes) ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes) ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes) - /* Not implemented on virgo ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs) ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes) ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style) - */ private_notes = client.prefs.read_preference(/datum/preference/text/living/private_notes) digestable = client.prefs_vr.digestable devourable = client.prefs_vr.devourable diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm index 231eac0829..d89ef0d789 100644 --- a/code/modules/nifsoft/software/13_soulcatcher.dm +++ b/code/modules/nifsoft/software/13_soulcatcher.dm @@ -259,11 +259,9 @@ brainmob.ooc_notes = H.ooc_notes brainmob.ooc_notes_likes = H.ooc_notes_likes brainmob.ooc_notes_dislikes = H.ooc_notes_dislikes - /* Not implemented on virgo brainmob.ooc_notes_favs = H.ooc_notes_favs brainmob.ooc_notes_maybes = H.ooc_notes_maybes brainmob.ooc_notes_style = H.ooc_notes_style - */ brainmob.timeofhostdeath = H.timeofdeath SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it. diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 41d777262c..02a4cebeb8 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -111,6 +111,9 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain) brainmob.ooc_notes = H.ooc_notes brainmob.ooc_notes_likes = H.ooc_notes_likes brainmob.ooc_notes_dislikes = H.ooc_notes_dislikes + brainmob.ooc_notes_favs = H.ooc_notes_favs + brainmob.ooc_notes_maybes = H.ooc_notes_maybes + brainmob.ooc_notes_style = H.ooc_notes_style // Copy modifiers. for(var/datum/modifier/M in H.modifiers) diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 14fd45b968..97d8420337 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -113,6 +113,8 @@ for(var/atom/movable/A in affecting) if(istype(A,/obj/effect/abstract)) // Flashlight's lights are not physical objects continue + if(A.is_incorporeal()) + continue if(!A.anchored) if(A.loc == src.loc) // prevents the object from being affected if it's not currently here. step(A,movedir) diff --git a/code/modules/resleeving/infocore_records.dm b/code/modules/resleeving/infocore_records.dm index 1c3491c6a8..f4b97ffb49 100644 --- a/code/modules/resleeving/infocore_records.dm +++ b/code/modules/resleeving/infocore_records.dm @@ -26,6 +26,9 @@ var/mind_oocnotes = "" var/mind_ooclikes = "" var/mind_oocdislikes = "" + var/mind_oocfavs = "" + var/mind_oocmaybes = "" + var/mind_oocstyle = FALSE var/nif_path var/nif_durability var/list/nif_software @@ -61,6 +64,9 @@ nif_software = nifsofts nif_savedata = M.nif.save_data.Copy() + if(istype(M,/mob) && !M.read_preference(/datum/preference/toggle/autotranscore)) + do_notify = FALSE + last_update = world.time if(add_to_db) @@ -81,6 +87,9 @@ var/body_oocnotes var/body_ooclikes var/body_oocdislikes + var/body_oocfavs + var/body_oocmaybes + var/body_oocstyle var/list/limb_data = list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO) var/list/organ_data = list(O_HEART, O_EYES, O_LUNGS, O_BRAIN) var/list/genetic_modifiers = list() @@ -114,11 +123,13 @@ //Person OOCly doesn't want people impersonating them locked = ckeylock + //Prevent people from printing restricted and whitelisted species var/datum/species/S = GLOB.all_species["[M.dna.species]"] if(S) + toocomplex = (S.spawn_flags & SPECIES_IS_WHITELISTED) || (S.spawn_flags & SPECIES_IS_RESTRICTED) // Force ckey locking if species is whitelisted - if((S.spawn_flags & SPECIES_IS_WHITELISTED) || (S.spawn_flags & SPECIES_IS_RESTRICTED)) - locked = TRUE + //if((S.spawn_flags & SPECIES_IS_WHITELISTED) || (S.spawn_flags & SPECIES_IS_RESTRICTED)) + //locked = TRUE //General stuff about them synthetic = M.isSynthetic() diff --git a/code/modules/resleeving/machines.dm b/code/modules/resleeving/machines.dm index a02a0a92f7..11d80753d8 100644 --- a/code/modules/resleeving/machines.dm +++ b/code/modules/resleeving/machines.dm @@ -125,6 +125,9 @@ H.ooc_notes = current_project.body_oocnotes H.ooc_notes_likes = current_project.body_ooclikes H.ooc_notes_dislikes = current_project.body_oocdislikes + H.ooc_notes_favs = current_project.body_oocfavs + H.ooc_notes_maybes = current_project.body_oocmaybes + H.ooc_notes_style = current_project.body_oocstyle H.flavor_texts = current_project.mydna.flavor.Copy() H.resize(current_project.sizemult, FALSE) H.appearance_flags = current_project.aflags @@ -599,6 +602,9 @@ occupant.ooc_notes = MR.mind_oocnotes occupant.ooc_notes_likes = MR.mind_ooclikes occupant.ooc_notes_dislikes = MR.mind_oocdislikes + occupant.ooc_notes_favs = MR.mind_oocfavs + occupant.ooc_notes_maybes = MR.mind_oocmaybes + occupant.ooc_notes_style = MR.mind_oocstyle occupant.apply_vore_prefs() //Cheap hack for now to give them SOME bellies. if(MR.one_time) diff --git a/code/modules/resleeving/sleevecard.dm b/code/modules/resleeving/sleevecard.dm index d0d4bf665c..a3be102f50 100644 --- a/code/modules/resleeving/sleevecard.dm +++ b/code/modules/resleeving/sleevecard.dm @@ -46,6 +46,9 @@ infomorph.ooc_notes = MR.mind_oocnotes infomorph.ooc_notes_likes = MR.mind_ooclikes infomorph.ooc_notes_dislikes = MR.mind_oocdislikes + infomorph.ooc_notes_favs = MR.mind_oocfavs + infomorph.ooc_notes_maybes = MR.mind_oocmaybes + infomorph.ooc_notes_style = MR.mind_oocstyle infomorph.apply_vore_prefs() //Cheap hack for now to give them SOME bellies. //Don't set 'real_name' because then we get a nice (as sleevecard) thing. diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index bfacf6a692..39585f8236 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -1100,7 +1100,6 @@ save_ooc_panel(usr) if(href_list["print_ooc_notes_chat"]) print_ooc_notes_chat(usr) - /* Not implemented on virgo if(href_list["edit_ooc_note_favs"]) if(usr == src) set_metainfo_favs(usr) @@ -1109,7 +1108,6 @@ set_metainfo_maybes(usr) if(href_list["set_metainfo_ooc_style"]) set_metainfo_ooc_style(usr) - */ if(href_list["save_private_notes"]) if(usr == src) save_private_notes(usr) diff --git a/code/modules/vore/eating/soulcatcher.dm b/code/modules/vore/eating/soulcatcher.dm index 7251f97100..9fe9cdb5e8 100644 --- a/code/modules/vore/eating/soulcatcher.dm +++ b/code/modules/vore/eating/soulcatcher.dm @@ -168,11 +168,9 @@ brainmob.ooc_notes = L.ooc_notes brainmob.ooc_notes_likes = L.ooc_notes_likes brainmob.ooc_notes_dislikes = L.ooc_notes_dislikes - /* Not implemented on virgo brainmob.ooc_notes_favs = L.ooc_notes_favs brainmob.ooc_notes_maybes = L.ooc_notes_maybes brainmob.ooc_notes_style = L.ooc_notes_style - */ brainmob.timeofhostdeath = L.timeofdeath if(ishuman(L)) SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it. diff --git a/sound/talksounds/wf/lure_1.ogg b/sound/talksounds/wf/lure_1.ogg new file mode 100644 index 0000000000..8a71133ba6 Binary files /dev/null and b/sound/talksounds/wf/lure_1.ogg differ diff --git a/sound/talksounds/wf/lure_2.ogg b/sound/talksounds/wf/lure_2.ogg new file mode 100644 index 0000000000..646787e6ba Binary files /dev/null and b/sound/talksounds/wf/lure_2.ogg differ diff --git a/sound/talksounds/wf/lure_3.ogg b/sound/talksounds/wf/lure_3.ogg new file mode 100644 index 0000000000..9506a5f671 Binary files /dev/null and b/sound/talksounds/wf/lure_3.ogg differ diff --git a/sound/talksounds/wf/lure_4.ogg b/sound/talksounds/wf/lure_4.ogg new file mode 100644 index 0000000000..1e2225a60f Binary files /dev/null and b/sound/talksounds/wf/lure_4.ogg differ diff --git a/sound/talksounds/wf/lure_5.ogg b/sound/talksounds/wf/lure_5.ogg new file mode 100644 index 0000000000..2ff7d186c2 Binary files /dev/null and b/sound/talksounds/wf/lure_5.ogg differ diff --git a/sound/talksounds/wf/lyst_1.ogg b/sound/talksounds/wf/lyst_1.ogg new file mode 100644 index 0000000000..eb5c49d2b8 Binary files /dev/null and b/sound/talksounds/wf/lyst_1.ogg differ diff --git a/sound/talksounds/wf/lyst_2.ogg b/sound/talksounds/wf/lyst_2.ogg new file mode 100644 index 0000000000..031ee39e8d Binary files /dev/null and b/sound/talksounds/wf/lyst_2.ogg differ diff --git a/sound/talksounds/wf/lyst_3.ogg b/sound/talksounds/wf/lyst_3.ogg new file mode 100644 index 0000000000..ec165d6c51 Binary files /dev/null and b/sound/talksounds/wf/lyst_3.ogg differ diff --git a/sound/talksounds/wf/lyst_4.ogg b/sound/talksounds/wf/lyst_4.ogg new file mode 100644 index 0000000000..e7124ff96c Binary files /dev/null and b/sound/talksounds/wf/lyst_4.ogg differ diff --git a/sound/talksounds/wf/lyst_5.ogg b/sound/talksounds/wf/lyst_5.ogg new file mode 100644 index 0000000000..a86f568650 Binary files /dev/null and b/sound/talksounds/wf/lyst_5.ogg differ diff --git a/sound/talksounds/wf/lyst_6.ogg b/sound/talksounds/wf/lyst_6.ogg new file mode 100644 index 0000000000..7fb22060dc Binary files /dev/null and b/sound/talksounds/wf/lyst_6.ogg differ diff --git a/sound/talksounds/wf/void_1.ogg b/sound/talksounds/wf/void_1.ogg new file mode 100644 index 0000000000..049ce155b4 Binary files /dev/null and b/sound/talksounds/wf/void_1.ogg differ diff --git a/sound/talksounds/wf/void_2.ogg b/sound/talksounds/wf/void_2.ogg new file mode 100644 index 0000000000..639bcc89b3 Binary files /dev/null and b/sound/talksounds/wf/void_2.ogg differ diff --git a/sound/talksounds/wf/void_3.ogg b/sound/talksounds/wf/void_3.ogg new file mode 100644 index 0000000000..8beda78a7d Binary files /dev/null and b/sound/talksounds/wf/void_3.ogg differ diff --git a/sound/talksounds/wf/vomva_1.ogg b/sound/talksounds/wf/vomva_1.ogg new file mode 100644 index 0000000000..128dd43c60 Binary files /dev/null and b/sound/talksounds/wf/vomva_1.ogg differ diff --git a/sound/talksounds/wf/vomva_2.ogg b/sound/talksounds/wf/vomva_2.ogg new file mode 100644 index 0000000000..e3aeb7c10e Binary files /dev/null and b/sound/talksounds/wf/vomva_2.ogg differ diff --git a/sound/talksounds/wf/vomva_3.ogg b/sound/talksounds/wf/vomva_3.ogg new file mode 100644 index 0000000000..25b9587d62 Binary files /dev/null and b/sound/talksounds/wf/vomva_3.ogg differ diff --git a/sound/talksounds/wf/vomva_4.ogg b/sound/talksounds/wf/vomva_4.ogg new file mode 100644 index 0000000000..f9e6bd2838 Binary files /dev/null and b/sound/talksounds/wf/vomva_4.ogg differ diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory.tsx deleted file mode 100644 index b9a9d6b5c2..0000000000 --- a/tgui/packages/tgui/interfaces/CharacterDirectory.tsx +++ /dev/null @@ -1,311 +0,0 @@ -import { type ReactNode, useState } from 'react'; -import { useBackend } from 'tgui/backend'; -import { Window } from 'tgui/layouts'; -import { - Box, - Button, - Icon, - LabeledList, - Section, - Stack, - Table, -} from 'tgui-core/components'; -import type { BooleanLike } from 'tgui-core/react'; - -const getTagColor = (tag: string) => { - switch (tag) { - case 'Unset': - return 'label'; - case 'Pred': - return 'red'; - case 'Pred-Pref': - return 'orange'; - case 'Prey': - return 'blue'; - case 'Prey-Pref': - return 'green'; - case 'Switch': - return 'yellow'; - case 'Non-Vore': - return 'black'; - } -}; - -type Data = { - personalVisibility: BooleanLike; - personalTag: string; - personalErpTag: string; - directory: character[]; -}; - -type character = { - name: string; - species: string; - ooc_notes: string; - tag: string; - erptag: string; - character_ad: string; - flavor_text: string; -}; - -export const CharacterDirectory = (props) => { - const { act, data } = useBackend(); - const { personalVisibility, personalTag, personalErpTag } = data; - - const [overlay, setOverlay] = useState(null); - const [overwritePrefs, setOverwritePrefs] = useState(false); - - function handleOverlay(value: character | null) { - setOverlay(value); - } - - return ( - - - {(overlay && ( - - )) || ( - <> -
- - - Save to current preferences slot:  - - - - - - - } - > - - - - - - - - - - - - - - -
- - - )} -
-
- ); -}; - -const ViewCharacter = (props) => { - return ( -
props.onOverlay(null)}> - Back - - } - > -
- {props.overlay.species} -
-
- - {props.overlay.tag} - -
-
- {props.overlay.erptag} -
-
- - {props.overlay.character_ad || 'Unset.'} - -
-
- - {props.overlay.ooc_notes || 'Unset.'} - -
-
- - {props.overlay.flavor_text || 'Unset.'} - -
-
- ); -}; - -const CharacterDirectoryList = (props) => { - const { act, data } = useBackend(); - - const { directory } = data; - - const [sortId, setSortId] = useState('name'); - const [sortOrder, setSortOrder] = useState('name'); - - function handleSortId(value: string) { - setSortId(value); - } - function handleSortOrder(value: string) { - setSortOrder(value); - } - - return ( -
act('refresh')}> - Refresh - - } - > -
- - - Name - - - Species - - - Vore Tag - - - ERP Tag - - - View - - - {directory - .sort((a, b) => { - const i = sortOrder ? 1 : -1; - return a[sortId].localeCompare(b[sortId]) * i; - }) - .map((character, i) => ( - - {character.name} - {character.species} - {character.tag} - {character.erptag} - - - - - ))} -
- - ); -}; - -const SortButton = (props: { - id: string; - sortId: string; - sortOrder: string; - onSortId: Function; - onSortOrder: Function; - children: ReactNode | string; -}) => { - const { id, children } = props; - - // Hey, same keys mean same data~ - - return ( - - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx new file mode 100644 index 0000000000..b7cb1ecb9f --- /dev/null +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx @@ -0,0 +1,135 @@ +import { useState } from 'react'; +import { useBackend } from 'tgui/backend'; +import { Button, Section, Table } from 'tgui-core/components'; + +import { SortButton } from './CharacterDirectorySortButton'; +import { getTagColor } from './constants'; +import type { mobEntry } from './types'; + +export const CharacterDirectoryList = (props: { + directory: mobEntry[]; + onOverlay: Function; +}) => { + const { act } = useBackend(); + + const { onOverlay, directory } = props; + + const [sortId, setSortId] = useState('name'); + const [sortOrder, setSortOrder] = useState('name'); + + function handleSortId(value: string) { + setSortId(value); + } + + function handleSortOrder(value: string) { + setSortOrder(value); + } + + return ( +
act('refresh')}> + Refresh + + } + > + + + + Name + + + Species + + + Vore Tag + + + Gender + + + Sexuality + + + ERP Tag + + + Event Pref + + + View + + + {directory + .sort((a, b) => { + const i = sortOrder ? 1 : -1; + return a[sortId].localeCompare(b[sortId]) * i; + }) + .map((character, i) => ( + + {character.name} + {character.species} + {character.tag} + {character.gendertag} + {character.sexualitytag} + {character.erptag} + {character.eventtag} + + + + + ))} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectorySortButton.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectorySortButton.tsx new file mode 100644 index 0000000000..24d369b515 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectorySortButton.tsx @@ -0,0 +1,36 @@ +import { Button, Icon, Table } from 'tgui-core/components'; + +export const SortButton = (props: { + id: string; + sortId: string; + sortOrder: string; + onSortOrder: Function; + onSortId: Function; + children: React.JSX.Element | string; +}) => { + const { id, sortId, sortOrder, onSortOrder, onSortId, children } = props; + + // Hey, same keys mean same data~ + + return ( + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx new file mode 100644 index 0000000000..6cfbb172db --- /dev/null +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx @@ -0,0 +1,113 @@ +import { Box, Button, Section, Table } from 'tgui-core/components'; + +import { getTagColor } from './constants'; +import type { mobEntry } from './types'; + +export const ViewCharacter = (props: { + overlay: mobEntry; + onOverlay: Function; +}) => { + const { overlay, onOverlay } = props; + + return ( +
onOverlay(null)}> + Back + + } + > +
+ {overlay.species} +
+
+ + {overlay.tag} + +
+
+ {overlay.gendertag} +
+
+ {overlay.sexualitytag} +
+
+ {overlay.erptag} +
+
+ {overlay.eventtag} +
+
+ + {overlay.character_ad || 'Unset.'} + +
+
+ + {overlay.ooc_notes || 'Unset.'} + {overlay.ooc_notes_style && + (overlay.ooc_notes_favs || + overlay.ooc_notes_likes || + overlay.ooc_notes_maybes || + overlay.ooc_notes_dislikes) ? ( + + + {overlay.ooc_notes_favs ? ( + FAVOURITES + ) : ( + '' + )} + {overlay.ooc_notes_likes ? LIKES : ''} + {overlay.ooc_notes_maybes ? ( + MAYBES + ) : ( + '' + )} + {overlay.ooc_notes_dislikes ? ( + DISLIKES + ) : ( + '' + )} + + + +
+
+
+ + {overlay.ooc_notes_favs ? ( + {overlay.ooc_notes_favs} + ) : ( + '' + )} + {overlay.ooc_notes_likes ? ( + {overlay.ooc_notes_likes} + ) : ( + '' + )} + {overlay.ooc_notes_maybes ? ( + {overlay.ooc_notes_maybes} + ) : ( + '' + )} + {overlay.ooc_notes_dislikes ? ( + {overlay.ooc_notes_dislikes} + ) : ( + '' + )} + +
+ ) : ( + '' + )} +
+
+
+ + {overlay.flavor_text || 'Unset.'} + +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/constants.ts b/tgui/packages/tgui/interfaces/CharacterDirectory/constants.ts new file mode 100644 index 0000000000..d7b99dabf8 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/constants.ts @@ -0,0 +1,18 @@ +export const getTagColor = (tag: string) => { + switch (tag) { + case 'Unset': + return 'label'; + case 'Pred': + return 'red'; + case 'Pred-Pref': + return 'orange'; + case 'Prey': + return 'blue'; + case 'Prey-Pref': + return 'green'; + case 'Switch': + return 'yellow'; + case 'Non-Vore': + return 'black'; + } +}; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx new file mode 100644 index 0000000000..291df29c38 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx @@ -0,0 +1,142 @@ +import { useState } from 'react'; +import { useBackend } from 'tgui/backend'; +import { Window } from 'tgui/layouts'; +import { Box, Button, LabeledList, Section, Stack } from 'tgui-core/components'; + +import { CharacterDirectoryList } from './CharacterDirectoryList'; +import { ViewCharacter } from './CharacterDirectoryViewCharacter'; +import type { Data, mobEntry } from './types'; + +export const CharacterDirectory = (props) => { + const { act, data } = useBackend(); + + const { + personalVisibility, + personalTag, + personalGenderTag, + personalSexualityTag, + personalErpTag, + personalEventTag, + directory, + } = data; + + const [overlay, setOverlay] = useState(null); + const [overwritePrefs, setOverwritePrefs] = useState(false); + + function handleOverlay(value: mobEntry) { + setOverlay(value); + } + + return ( + + + {(overlay && ( + + )) || ( + <> +
+ + + Save to current preferences slot:  + + + + + + + } + > + + + + + + + + + + + + + + + + + + + + + + + +
+ + + )} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts b/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts new file mode 100644 index 0000000000..407ef60216 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts @@ -0,0 +1,29 @@ +import type { BooleanLike } from 'tgui-core/react'; + +export type Data = { + personalVisibility: BooleanLike; + personalTag: string; + personalErpTag: string; + personalEventTag: string; + personalGenderTag: string; + personalSexualityTag: string; + directory: mobEntry[]; +}; + +export type mobEntry = { + name: string; + species: string; + ooc_notes_favs: string; + ooc_notes_likes: string; + ooc_notes_maybes: string; + ooc_notes_dislikes: string; + ooc_notes_style: BooleanLike; + gendertag: string; + sexualitytag: string; + eventtag: string; + ooc_notes: string; + tag: string; + erptag: string; + character_ad: string; + flavor_text: string; +};