From 687b44df37558a2b6b72c3c6f5f6112340806c11 Mon Sep 17 00:00:00 2001 From: The Sharkening <95130227+StrangeWeirdKitten@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:26:21 -0800 Subject: [PATCH 01/16] Seamless Heels Quirk (#2994) ## About The Pull Request Adds a "Seamless Heels" quirk that's neutral. You spawn with heels you can't take off. (More items TBD) ## Why It's Good For The Game Something for those who like to be a robot or something with heels. But also I wanted this for a long time, and I bent reality to my whims. ## Proof Of Testing - Heels being removed from you removes the quirk - Color picker works - quirk works - we test things on prod - merp merp meow meow squeak squeak ## Changelog :cl: add: Seamless heels quirk /:cl: --- .../subsystem/processing/quirks.dm | 1 + .../datums/quirks/neutral_quirks/entombed.dm | 12 +++-- .../quirks/neutral_quirks/seamless_clothes.dm | 53 +++++++++++++++++++ tgstation.dme | 1 + .../bubbers/seamless_clothes.tsx | 6 +++ 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 modular_zubbers/code/datums/quirks/neutral_quirks/seamless_clothes.dm create mode 100644 tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/seamless_clothes.tsx diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm index ee1cc3737c4..7bdf0f24cd6 100644 --- a/code/controllers/subsystem/processing/quirks.dm +++ b/code/controllers/subsystem/processing/quirks.dm @@ -44,6 +44,7 @@ GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list( list(/datum/quirk/featherweight, /datum/quirk/oversized), list(/datum/quirk/overweight, /datum/quirk/obese), list(/datum/quirk/dominant_aura, /datum/quirk/well_trained), + list(/datum/quirk/equipping/entombed, /datum/quirk/equipping/seamless_clothes), list(/datum/quirk/equipping/entombed, /datum/quirk/badback), //BUBBER EDIT ADDITION END )) diff --git a/modular_zubbers/code/datums/quirks/neutral_quirks/entombed.dm b/modular_zubbers/code/datums/quirks/neutral_quirks/entombed.dm index caa19427537..d506bf1fef4 100644 --- a/modular_zubbers/code/datums/quirks/neutral_quirks/entombed.dm +++ b/modular_zubbers/code/datums/quirks/neutral_quirks/entombed.dm @@ -175,7 +175,8 @@ return "Civilian" /datum/preference/choiced/entombed_skin/is_accessible(datum/preferences/preferences) - if (!..()) + . = ..() + if(!.) return FALSE return "Entombed" in preferences.all_quirks @@ -191,7 +192,8 @@ maximum_value_length = 48 /datum/preference/text/entombed_mod_name/is_accessible(datum/preferences/preferences) - if (!..()) + . = ..() + if(!.) return FALSE return "Entombed" in preferences.all_quirks @@ -216,7 +218,8 @@ can_randomize = FALSE /datum/preference/text/entombed_mod_desc/is_accessible(datum/preferences/preferences) - if (!..()) + . = ..() + if(!.) return FALSE return "Entombed" in preferences.all_quirks @@ -242,7 +245,8 @@ maximum_value_length = 16 /datum/preference/text/entombed_mod_prefix/is_accessible(datum/preferences/preferences) - if (!..()) + . = ..() + if(!.) return FALSE return "Entombed" in preferences.all_quirks diff --git a/modular_zubbers/code/datums/quirks/neutral_quirks/seamless_clothes.dm b/modular_zubbers/code/datums/quirks/neutral_quirks/seamless_clothes.dm new file mode 100644 index 00000000000..2ad7ecb7f19 --- /dev/null +++ b/modular_zubbers/code/datums/quirks/neutral_quirks/seamless_clothes.dm @@ -0,0 +1,53 @@ +/datum/quirk/equipping/seamless_clothes + name = "Seamless Heels" + desc = "You come with heels stuck on you. Whether it be a freak accident or part of your design, you can't take them off." + medical_record_text = "Subject appears to have clothing attire fused to their body." + value = 0 + icon = FA_ICON_TSHIRT + gain_text = span_notice("You feel things stick to your body.") + lose_text = span_notice("You feel things loose their grip on your body.") + quirk_flags = QUIRK_HIDE_FROM_SCAN + forced_items = list(/obj/item/clothing/shoes/fancy_heels = list(ITEM_SLOT_FEET)) + var/prefix = "seamless" + var/obj/item/clothing/shoes/shoes + +/datum/quirk/equipping/seamless_clothes/on_equip_item(obj/item/equipped, success) + shoes = equipped + +/datum/quirk/equipping/seamless_clothes/post_add() // Quirks init on round start ready up before client does. + if(!istype(shoes, /obj/item/clothing/shoes/fancy_heels)) + CRASH("Type mismatch on [src] during on_equip_item. Tried to equip [shoes]") + shoes.name = "[prefix] [initial(shoes.name)]" + shoes.desc = "A pair of heels which refuse to come off your feet." + shoes.greyscale_colors = quirk_holder.client.prefs.read_preference(/datum/preference/color/seamless_shoe_color) + shoes.resistance_flags = ACID_PROOF | FIRE_PROOF + shoes.update_greyscale() + ADD_TRAIT(shoes, TRAIT_NODROP, CLOTHING_TRAIT) + RegisterSignal(shoes, COMSIG_ITEM_DROPPED, PROC_REF(remove_quirk)) + +/datum/quirk/equipping/seamless_clothes/remove() + if(isnull(shoes)) + return + UnregisterSignal(shoes, COMSIG_ITEM_DROPPED) + QDEL_NULL(shoes) + +/datum/quirk/equipping/seamless_clothes/proc/remove_quirk() + SIGNAL_HANDLER + qdel(src) + +/datum/quirk_constant_data/seamless_clothes + associated_typepath = /datum/quirk/equipping/seamless_clothes + customization_options = list( + /datum/preference/color/seamless_shoe_color + ) + +/datum/preference/color/seamless_shoe_color + savefile_key = "seamless_shoe_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + +/datum/preference/color/seamless_shoe_color/create_default_value() + return "#e7e7e7" + +/datum/preference/color/seamless_shoe_color/apply_to_human(mob/living/carbon/human/target, value) + return diff --git a/tgstation.dme b/tgstation.dme index fbc75d71648..ef168cb13d0 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -8739,6 +8739,7 @@ #include "modular_zubbers\code\datums\quirks\neutral_quirks\lungs.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\oversized_quirk.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\pet_owner.dm" +#include "modular_zubbers\code\datums\quirks\neutral_quirks\seamless_clothes.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\waddle.dm" #include "modular_zubbers\code\datums\quirks\positive_quirks\dominant_aura.dm" #include "modular_zubbers\code\datums\quirks\positive_quirks\empath_override.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/seamless_clothes.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/seamless_clothes.tsx new file mode 100644 index 00000000000..ac33c2a28a3 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/seamless_clothes.tsx @@ -0,0 +1,6 @@ +import { Feature, FeatureColorInput } from '../../base'; + +export const seamless_shoe_color: Feature = { + name: 'Shoe Color', + component: FeatureColorInput, +}; From f7673e827e01e25a58fc8da68a607626f77d2bb0 Mon Sep 17 00:00:00 2001 From: The Sharkening <95130227+StrangeWeirdKitten@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:26:44 -0800 Subject: [PATCH 02/16] nameless quirk (#2989) ## About The Pull Request Adds the nameless quirk with the option to have a prefix. Without a prefix, you will spawn is as your [job] #[number]. If you don't have a job or prefix, you have some random prefixes I threw together that it chooses from. ## Why It's Good For The Game Adds an option for characters to spawn in as a random number. Adds to the bubber roleplay experience. You can be mass produced or something. ## Proof Of Testing ![image](https://github.com/user-attachments/assets/ca41a8cf-151a-42df-9df0-0fd2a8f91466) ## Changelog :cl: add: Nameless Quirk /:cl: --- .../datums/quirks/neutral_quirks/nameless.dm | 63 +++++++++++++++++++ tgstation.dme | 1 + .../bubbers/nameless.tsx | 8 +++ 3 files changed, 72 insertions(+) create mode 100644 modular_zubbers/code/datums/quirks/neutral_quirks/nameless.dm create mode 100644 tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/nameless.tsx diff --git a/modular_zubbers/code/datums/quirks/neutral_quirks/nameless.dm b/modular_zubbers/code/datums/quirks/neutral_quirks/nameless.dm new file mode 100644 index 00000000000..fc58e26b91d --- /dev/null +++ b/modular_zubbers/code/datums/quirks/neutral_quirks/nameless.dm @@ -0,0 +1,63 @@ +/datum/quirk/nameless + name = "Nameless" + desc = "You don't have a name. You are known only as a number." + medical_record_text = "Subject lacks a name in records." + value = 0 + icon = FA_ICON_USER_NINJA + gain_text = span_notice("You feel your name slip away.") + lose_text = span_notice("You spontaniously remember your full name!") + quirk_flags = QUIRK_HIDE_FROM_SCAN + var/character_name + var/new_name + +/datum/preference/text/nameless_quirk_option + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "nameless_quirk_name" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + maximum_value_length = 20 + +/// Some sanity to ensure you can't have " #1000" as your name. +/datum/preference/text/nameless_quirk_option/is_valid(value) + if(isnull(value)) + return TRUE + return !isnull(permissive_sanitize_name(value)) + +/datum/preference/text/nameless_quirk_option/serialize(input) + return htmlrendertext(input) + +/datum/preference/text/nameless_quirk_option/deserialize(input, datum/preferences/preferences) + return htmlrendertext(input) + +/datum/preference/text/nameless_quirk_option/apply_to_human(mob/living/carbon/human/target, value) + return + +/datum/quirk_constant_data/nameless + associated_typepath = /datum/quirk/nameless + customization_options = list( + /datum/preference/text/nameless_quirk_option + ) + +/datum/quirk/nameless/add(client/client_source) + character_name = client_source?.prefs.read_preference(/datum/preference/name/real_name) + new_name = generate_name() + quirk_holder.fully_replace_character_name(character_name, new_name) + +/datum/quirk/nameless/remove() + quirk_holder.fully_replace_character_name(new_name, character_name) + +/datum/quirk/nameless/proc/generate_name() + + var/prefix = quirk_holder.client?.prefs.read_preference(/datum/preference/text/nameless_quirk_option) + var/job + var/number = pick(rand(1000, 9999)) + + if(prefix) + job = prefix + else + job = isnull(quirk_holder.job) ? pick("Alpha", "Beta", "Delta", "Echo", "Zulu", "Omega") : quirk_holder.job + + return "[job] #[number]" + + + diff --git a/tgstation.dme b/tgstation.dme index ef168cb13d0..31c11e6e580 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -8737,6 +8737,7 @@ #include "modular_zubbers\code\datums\quirks\neutral_quirks\hungry.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\hydrophilic.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\lungs.dm" +#include "modular_zubbers\code\datums\quirks\neutral_quirks\nameless.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\oversized_quirk.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\pet_owner.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\seamless_clothes.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/nameless.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/nameless.tsx new file mode 100644 index 00000000000..d8b519a14c1 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/nameless.tsx @@ -0,0 +1,8 @@ +import { Feature, FeatureShortTextInput } from '../../base'; + +export const nameless_quirk_name: Feature = { + name: 'Prefix Name', + description: + 'Example: (Prefix) #1334. Leave blank to default to job title. Minimum 3 characters.', + component: FeatureShortTextInput, +}; From 48b239687902da16e20ae2d5c6b58b9726d1bac1 Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Tue, 25 Feb 2025 23:26:45 +0100 Subject: [PATCH 03/16] Automatic changelog for PR #2994 [ci skip] --- html/changelogs/AutoChangeLog-pr-2994.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2994.yml diff --git a/html/changelogs/AutoChangeLog-pr-2994.yml b/html/changelogs/AutoChangeLog-pr-2994.yml new file mode 100644 index 00000000000..37c2db1d973 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2994.yml @@ -0,0 +1,4 @@ +author: "StrangeWeirdKitten" +delete-after: True +changes: + - rscadd: "Seamless heels quirk" \ No newline at end of file From f710b3f46bf8ec7b0e1a4cdac3c500213dfc8bbc Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Tue, 25 Feb 2025 23:27:09 +0100 Subject: [PATCH 04/16] Automatic changelog for PR #2989 [ci skip] --- html/changelogs/AutoChangeLog-pr-2989.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2989.yml diff --git a/html/changelogs/AutoChangeLog-pr-2989.yml b/html/changelogs/AutoChangeLog-pr-2989.yml new file mode 100644 index 00000000000..2ae5086a912 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2989.yml @@ -0,0 +1,4 @@ +author: "StrangeWeirdKitten" +delete-after: True +changes: + - rscadd: "Nameless Quirk" \ No newline at end of file From 5dec4dfee31513981791c73b5a371b3990f7504e Mon Sep 17 00:00:00 2001 From: ABoxFaux <116041393+ABoxFaux@users.noreply.github.com> Date: Tue, 25 Feb 2025 22:56:40 +0000 Subject: [PATCH 05/16] Allows the size collar to work for teshari and vox primalis (#3090) ## About The Pull Request This makes the size collar item from the lustwish vendor modify Teshari & Vox Primalis size (Both of which have bodysize restrictions). It has the same restriction as before (infinidorms/interlink areas) and does NOT affect NIF Polymorph or the Character Creation bodysize slider. ## Why It's Good For The Game More ERP options regarding size stuff for birds. It's unlinked to the main course of the game and shouldn't affect that - teshari and vox primalis deserve to be the big bird (or small bird) for scenes in areas where it can't get them an advantage (the size collar only works in dorms areas. ## Proof Of Testing Compiled and tested on a localhost, large bird image provided below
Screenshots/Videos ![collar1](https://github.com/user-attachments/assets/3010a967-19e1-4399-b87a-28f3df1fd56b)
## Changelog :cl: code: Teshari and Vox primalis can now use size collars in dorms/interlink areas. /:cl: --------- Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com> --- .../modular_items/lewd_items/code/lewd_items/size_items.dm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/size_items.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/size_items.dm index 95bfa297c59..d50cf6342ff 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/size_items.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/size_items.dm @@ -116,13 +116,20 @@ if(!human_parent || !size_to_apply || (human_parent.dna.features["body_size"] == size_to_apply)) return FALSE + if(isteshari(human_parent) || isvoxprimalis(human_parent)) // We check if the human_parent is a Vox Primalis or Teshari & temporarily disable the bodysize restriction + human_parent.dna.species.body_size_restricted = FALSE + human_parent.dna.features["body_size"] = size_to_apply human_parent.maptext_height = 32 * human_parent.dna.features["body_size"] human_parent.dna.update_body_size() return TRUE /datum/component/temporary_size/Destroy(force, silent) + var/mob/living/carbon/human/human_parent = parent apply_size(original_size) + + if(isteshari(human_parent) || isvoxprimalis(human_parent)) // We reapply it on destroy if they were + human_parent.dna.species.body_size_restricted = TRUE UnregisterSignal(parent, COMSIG_ENTER_AREA) return ..() From 6a0b7e38f9c3aa95b5802f6288e0ec10b870c1a0 Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Tue, 25 Feb 2025 23:57:07 +0100 Subject: [PATCH 06/16] Automatic changelog for PR #3090 [ci skip] --- html/changelogs/AutoChangeLog-pr-3090.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3090.yml diff --git a/html/changelogs/AutoChangeLog-pr-3090.yml b/html/changelogs/AutoChangeLog-pr-3090.yml new file mode 100644 index 00000000000..f4589b06ee1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3090.yml @@ -0,0 +1,4 @@ +author: "ABoxFaux" +delete-after: True +changes: + - code_imp: "Teshari and Vox primalis can now use size collars in dorms/interlink areas." \ No newline at end of file From a9dc2855673691b65d1042c0b7331648978357be Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 25 Feb 2025 17:57:24 -0500 Subject: [PATCH 07/16] (MODULAR) Intern Ghoul Plushie (#3150) ## About The Pull Request Adds a plushie of my CentCom character, Intern John. (It's supposed to look scrungly and fucked up) ![image](https://github.com/user-attachments/assets/0d950401-5f12-4d66-bc13-6593418017b4) ## Why It's Good For The Game More plushies are arguably a good thing. ## Proof Of Testing It should work. ## Changelog :cl: add: added the intern ghoul plushie to both in game and the loadouts /:cl: --- .../code/game/objects/items/plushes.dm | 9 +++++++++ .../code/modules/loadout/categories/toys.dm | 4 ++++ modular_zubbers/icons/obj/toys/plushes.dmi | Bin 53639 -> 54031 bytes 3 files changed, 13 insertions(+) diff --git a/modular_zubbers/code/game/objects/items/plushes.dm b/modular_zubbers/code/game/objects/items/plushes.dm index e0256dd6341..40cbf750995 100644 --- a/modular_zubbers/code/game/objects/items/plushes.dm +++ b/modular_zubbers/code/game/objects/items/plushes.dm @@ -244,3 +244,12 @@ gender = FEMALE squeak_override = list('modular_zubbers/sound/emotes/arf.ogg' = 1) +// xPokee's plush +/obj/item/toy/plush/ghoul + name = "intern ghoul plushie" + desc = "Even the marketable plushie of this thing is utterly terrifying. At least it's cuddly..." + icon = 'modular_zubbers/icons/obj/toys/plushes.dmi' + icon_state = "johnghoul" + attack_verb_continuous = list("ghouls") + attack_verb_simple = list("ghoul") + squeak_override = list('modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh.ogg' = 1) diff --git a/modular_zubbers/code/modules/loadout/categories/toys.dm b/modular_zubbers/code/modules/loadout/categories/toys.dm index fb9246e6b23..a43073757fd 100644 --- a/modular_zubbers/code/modules/loadout/categories/toys.dm +++ b/modular_zubbers/code/modules/loadout/categories/toys.dm @@ -86,3 +86,7 @@ /datum/loadout_item/toys/androiddog name = "Android Dog Plushie" item_path = /obj/item/toy/plush/androiddog + +/datum/loadout_item/toys/ghoul + name = "Intern Ghoul Plushie" + item_path = /obj/item/toy/plush/ghoul diff --git a/modular_zubbers/icons/obj/toys/plushes.dmi b/modular_zubbers/icons/obj/toys/plushes.dmi index 8a2679cd87d3432af449dd9e06f976bdd7d5c284..d3b9e66e7bfd4657e069c67416352442e3505d62 100644 GIT binary patch delta 15321 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

MecT2}V>A{M< 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%0Dam)5`r&~l@GF;rNOihbU;kof{f^yBL*(ekY&Jq z*z}}6L*L>LI^}o_&CY`6CIK2jc%POEFxxWR)T_M#Z^1A&u0mE8?ta;N$qxq)pUi0B zyZVt4x#~--7m(()p_f|2Pq+=@!IN+(g!lWji>S6It$;wr;8^E_>SAGrdQTI4hZXw0 z_1iX2qjq&?+uN|I<5~1hgBpXKG1|qLn8ctp?mnn7+dD^o^!!jzQ4+DzDc^kFEXqRO zrrJahu==9!kVvnclv-NBKufFa(2Bc&c) zSu=S;M9_G+|36|#hoW2od#Ms0IuGJfc2w_5ul3R$KbYR$;OF;2esgjj+9%pECE8J# znjX7QJeq;JFybO~4b?e(3yVzHML>{w;#0qq{Y`5K2lie{9MkXWbLkuiMS@{1`IsiKb!!~hPO(qpIuZPzD0c)h1{tEmGXRb!Xy2>P#;loZ|X(#LWphUf@%#Vmf^Oy^ox zj&u9%W!FVb>sMR0!+f2Ui`Rd|nGB!wyQZ8+EN)ktPZhSfR8|?Vimw7anO(1N`mm(b zQy3c@TM!~AZ~`+@g&b$F4camx#ic{RAa~gSnrErq^`3IkD8mo$^ zm_M5)0S;z&=jXd<7R5i+_8cgLaXrxUV7aYqUv48)(os_cWw8Em*bFN_D&*`PYv^>2f*TGYy1kHihBlw9rw& zL{Yj+>Z*UKtSpfm3z*2ZY)+r-gas&y#e1Hs9dwei)q|D`&^)vILA7{kGwF&IR934y zElu4XEtg2*QX2vlY3Vy2mu^&RSF4E08g~$Y*+VMXzSO*nZZ}R0kH9rmP3U?nY^8Sd zoQ**XXwk%)@LaR{s&8}ZNfrf(2m)6oR400~#RJ`Doljb)@CO6s&HdV;>jdomwS>zg z>M%572*`v1sP8W%dV)V_%xr=kNs|~WIn1JL%z~uaK`0Y;C5x68BJ;)4SBnx#&CrIsv(-Ne zy8YCJI5;y1BmCu3T%a8XVb^g_q51JYfdQ-Z1RiTsJ^30Tt(B%}PB}hX;^8O1t(=&j zVAO?MXnk>ZUM;||^VoCe`^K}-E+o$b<>j!dN&NqI36+Q7k5!LnS9N8t0Jn%xlj1Tn zFZF44J}-fDzS`>caRCQWQHPJ5f?}}H^2>jCgk7150%<<=YYv0xDq$H4l|9KB&I~Xx uoc~+z5hUCSm_NrGC(N2blp+*#cmtFp;+uN8&33^+FDWrO(F$RG-~R(KTFz4d delta 14926 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 M#pT7SMGOP~4|~H|PXGV_ From a18d3d9db6f572581f79fb07580a2dea90d545e7 Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Tue, 25 Feb 2025 23:57:57 +0100 Subject: [PATCH 08/16] Automatic changelog for PR #3150 [ci skip] --- html/changelogs/AutoChangeLog-pr-3150.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3150.yml diff --git a/html/changelogs/AutoChangeLog-pr-3150.yml b/html/changelogs/AutoChangeLog-pr-3150.yml new file mode 100644 index 00000000000..4173087eb56 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3150.yml @@ -0,0 +1,4 @@ +author: "xPokee" +delete-after: True +changes: + - rscadd: "added the intern ghoul plushie to both in game and the loadouts" \ No newline at end of file From f863a9f544bcd5e6c6c78d6fe7dcdc58981bb399 Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Tue, 25 Feb 2025 23:22:04 +0000 Subject: [PATCH 09/16] Bubberstation automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-2989.yml | 4 ---- html/changelogs/AutoChangeLog-pr-2994.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3090.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3132.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3150.yml | 4 ---- html/changelogs/archive/2025-02.yml | 12 ++++++++++++ 6 files changed, 12 insertions(+), 20 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-2989.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-2994.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3090.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3132.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3150.yml diff --git a/html/changelogs/AutoChangeLog-pr-2989.yml b/html/changelogs/AutoChangeLog-pr-2989.yml deleted file mode 100644 index 2ae5086a912..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2989.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "StrangeWeirdKitten" -delete-after: True -changes: - - rscadd: "Nameless Quirk" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2994.yml b/html/changelogs/AutoChangeLog-pr-2994.yml deleted file mode 100644 index 37c2db1d973..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2994.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "StrangeWeirdKitten" -delete-after: True -changes: - - rscadd: "Seamless heels quirk" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3090.yml b/html/changelogs/AutoChangeLog-pr-3090.yml deleted file mode 100644 index f4589b06ee1..00000000000 --- a/html/changelogs/AutoChangeLog-pr-3090.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ABoxFaux" -delete-after: True -changes: - - code_imp: "Teshari and Vox primalis can now use size collars in dorms/interlink areas." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3132.yml b/html/changelogs/AutoChangeLog-pr-3132.yml deleted file mode 100644 index 44a38d61561..00000000000 --- a/html/changelogs/AutoChangeLog-pr-3132.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Alecksohs" -delete-after: True -changes: - - code_imp: "Vendors are now aware of sprite refits and will inform you if any are available." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3150.yml b/html/changelogs/AutoChangeLog-pr-3150.yml deleted file mode 100644 index 4173087eb56..00000000000 --- a/html/changelogs/AutoChangeLog-pr-3150.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "xPokee" -delete-after: True -changes: - - rscadd: "added the intern ghoul plushie to both in game and the loadouts" \ No newline at end of file diff --git a/html/changelogs/archive/2025-02.yml b/html/changelogs/archive/2025-02.yml index ea0a093544e..042db93c167 100644 --- a/html/changelogs/archive/2025-02.yml +++ b/html/changelogs/archive/2025-02.yml @@ -211,3 +211,15 @@ - rscadd: Nurse costume suit now in loadout and medical vendor SpooksAnno: - rscadd: The ability to grab parts and cells as a borg. +2025-02-25: + ABoxFaux: + - code_imp: Teshari and Vox primalis can now use size collars in dorms/interlink + areas. + Alecksohs: + - code_imp: Vendors are now aware of sprite refits and will inform you if any are + available. + StrangeWeirdKitten: + - rscadd: Seamless heels quirk + - rscadd: Nameless Quirk + xPokee: + - rscadd: added the intern ghoul plushie to both in game and the loadouts From 18999e3b3e02f1faa4b8682c3e4650606283cac6 Mon Sep 17 00:00:00 2001 From: nikothedude <59709059+nikothedude@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:24:25 -0500 Subject: [PATCH 10/16] Venom quirk (#2988) ## About The Pull Request Adds a quirk that lets you bite people to inject them with venom. Doesnt work against armor or thick clothing. Has a small delay to prevent in-combat use from being super effective - though you can still down them and force them to stay still. I've tried to balance it so that it's worthy of being in this weird-ass tg quirk dimension where positive quirks have to be mid as hell, but it's probably still overtuned. ## Why It's Good For The Game A lot of people in-game canonically have venom glands, and would love a quirk like this. ## Proof Of Testing

Screenshots/Videos https://github.com/user-attachments/assets/5c531e74-b1f3-44e7-95c4-42188ec9f272
## Changelog :cl: add: Quirk; venemous bite. Allows you to bite people and inject them with a venom, or medicine, of your choosing. /:cl: --------- Co-authored-by: The Sharkening <95130227+StrangeWeirdKitten@users.noreply.github.com> Co-authored-by: zeroisthebiggay <43571008+zeroisthebiggay@users.noreply.github.com> Co-authored-by: nevimer <77420409+nevimer@users.noreply.github.com> --- .../venemous_bite/venomous_bite.dm | 145 ++++++++++++++++++ .../venemous_bite/venomous_bite_quirk.dm | 84 ++++++++++ .../mob/actions/quirks/venomous_bite.dmi | Bin 0 -> 270 bytes tgstation.dme | 2 + .../bubbers/venomous_bite.tsx | 7 + 5 files changed, 238 insertions(+) create mode 100644 modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite.dm create mode 100644 modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite_quirk.dm create mode 100644 modular_zubbers/icons/mob/actions/quirks/venomous_bite.dmi create mode 100644 tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/venomous_bite.tsx diff --git a/modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite.dm b/modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite.dm new file mode 100644 index 00000000000..8016ffc1a9b --- /dev/null +++ b/modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite.dm @@ -0,0 +1,145 @@ +#define VENOMOUS_BITE_DAMAGE 5 +#define VENOMOUS_BITE_WOUND_CHANCE 20 +#define VENOMOUS_BITE_WOUND_BONUS 40 + +/datum/action/cooldown/mob_cooldown/venomous_bite + name = "Inject Venom" + desc = "Sink your fangs into another and inject them with your venom. Ineffective against those wearing armor." + + button_icon = 'modular_zubbers/icons/mob/actions/quirks/venomous_bite.dmi' + button_icon_state = "venom" + + ranged_mousepointer = 'icons/effects/mouse_pointers/supplypod_pickturf.dmi' + + check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED | AB_CHECK_HANDS_BLOCKED // cant use it if cuffed + + /// The reagent we will inject. + var/datum/reagent/reagent_typepath + /// How much of [reagent_typepath] we will inject. + var/to_inject = 0 + +/datum/action/cooldown/mob_cooldown/venomous_bite/New(Target, original, datum/reagent/our_reagent, quantity_override = null) + . = ..() + + set_reagent(our_reagent, quantity_override) + +/datum/action/cooldown/mob_cooldown/venomous_bite/proc/set_reagent(datum/reagent/new_reagent, quantity_override = null, cooldown_override = null) + reagent_typepath = new_reagent + + var/list/reagent_spec = /datum/preference/choiced/venomous_bite_venom::venomous_bite_choice_specs[new_reagent] + if (isnum(quantity_override)) + to_inject = quantity_override + else + to_inject = reagent_spec[1] + + if (isnum(cooldown_override)) + cooldown_time = cooldown_override + else + cooldown_time = reagent_spec[2] + +/datum/action/cooldown/mob_cooldown/venomous_bite/set_click_ability(mob/on_who) + . = ..() + if (!.) + return + + owner.visible_message("[owner] bares [owner.p_their()] fangs...", span_warning("You bare your fangs...")) + +/datum/action/cooldown/mob_cooldown/venomous_bite/Activate(atom/target_atom) + if (!isliving(target_atom)) + return FALSE + if (iscarbon(owner)) + var/mob/living/carbon/carbon_holder = owner + if (carbon_holder.is_mouth_covered()) + owner.balloon_alert(owner, "mouth covered!") + return FALSE + + if (!owner.Adjacent(target_atom)) + owner.balloon_alert(owner, "too far!") + return FALSE + + if (target_atom == owner) + owner.balloon_alert(owner, "can't bite yourself!") + return FALSE + + owner.visible_message(span_warning("[owner] starts to bite [target_atom]!"), span_warning("You start to bite [target_atom]!"), ignored_mobs = target_atom) + to_chat(target_atom, span_userdanger("[owner] starts to bite you!")) + owner.balloon_alert_to_viewers("biting...") + var/result = do_after(owner, 0.5 SECONDS, target_atom, IGNORE_HELD_ITEM) + if (!result) + return FALSE + + . = ..() + + var/penetrated = try_bite(target_atom) + if (penetrated) + inject(target_atom) + return TRUE + +/// Does NOT inject reagents; represents the initial bite. Can end in your teeth being broken by armor. Dumbass. +/datum/action/cooldown/mob_cooldown/venomous_bite/proc/try_bite(mob/living/target) + var/target_zone = check_zone(owner.zone_selected) + var/armor = target.run_armor_check(target_zone, MELEE) + var/obj/item/bodypart/part = target.get_bodypart(target_zone) + + var/text = "[owner] sinks [owner.p_their()] teeth into [target]'s [target.parse_zone_with_bodypart(target_zone)]!" + var/self_message = "You sink your teeth into [target]'s [target.parse_zone_with_bodypart(target_zone)]!" + var/victim_message = "[owner] sinks [owner.p_their()] teeth into your [target.parse_zone_with_bodypart(target_zone)]!" + + var/covered = FALSE + if (ishuman(target)) + var/mob/living/carbon/human/human_target = target + for (var/obj/item/clothing/iter_clothing as anything in human_target.get_clothing_on_part(part)) + if (iter_clothing.clothing_flags & THICKMATERIAL) + covered = TRUE + + text = "[owner] tries to bite [target], but breaks [owner.p_their()] teeth on [target]'s clothing! Ouch!" + self_message = "You try to bite [target], but you break your teeth on [target.p_their()] clothing! Ouch!" + victim_message = "[owner] tries to bite you, but breaks [owner.p_their()] teeth on your clothing! Ouch!" + + owner.emote("scream") + if (isliving(owner)) + var/mob/living/living_owner = owner + living_owner.apply_damage(1, BRUTE, BODY_ZONE_HEAD) + + break + + owner.visible_message(span_warning(text), span_warning(self_message), ignored_mobs = list(target)) + to_chat(target, span_userdanger(victim_message)) + + owner.do_attack_animation(target, ATTACK_EFFECT_BITE) + playsound(owner, 'sound/items/weapons/bite.ogg', 60, TRUE) + if (covered) + return FALSE + var/wound_bonus = 0 + if (prob(VENOMOUS_BITE_WOUND_CHANCE)) + wound_bonus = VENOMOUS_BITE_WOUND_BONUS + target.apply_damage(VENOMOUS_BITE_DAMAGE, BRUTE, target_zone, armor, wound_bonus = wound_bonus, sharpness = SHARP_POINTY) + if (iscarbon(owner)) + var/mob/living/carbon/carbon_owner = owner + for (var/datum/disease/our_disease as anything in carbon_owner.diseases) + if (our_disease.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS || our_disease.spread_flags & DISEASE_SPREAD_CONTACT_SKIN) + target.ContactContractDisease(our_disease, target_zone) + + if (iscarbon(target)) + var/mob/living/carbon/carbon_target = target + for (var/datum/disease/their_disease as anything in carbon_target.diseases) + if (their_disease.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS || their_disease.spread_flags & DISEASE_SPREAD_CONTACT_SKIN) + carbon_owner.ContactContractDisease(their_disease, target_zone) + + return TRUE + +/datum/action/cooldown/mob_cooldown/venomous_bite/proc/inject(mob/living/target) + var/target_zone = check_zone(owner.zone_selected) + if (!target.try_inject(owner, target_zone)) + return FALSE + var/temp + if (ishuman(owner)) + var/mob/living/carbon/human/human_holder = owner + temp = human_holder.coretemperature + target.reagents.add_reagent(reagent_typepath, to_inject, reagtemp = temp) + + return TRUE + +#undef VENOMOUS_BITE_DAMAGE +#undef VENOMOUS_BITE_WOUND_BONUS +#undef VENOMOUS_BITE_WOUND_CHANCE diff --git a/modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite_quirk.dm b/modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite_quirk.dm new file mode 100644 index 00000000000..86d169e8ec4 --- /dev/null +++ b/modular_zubbers/code/datums/quirks/positive_quirks/venemous_bite/venomous_bite_quirk.dm @@ -0,0 +1,84 @@ +/datum/quirk/venomous_bite + name = "Venomous Bite" + desc = "You have a venom gland, and can bite people to inject them with a toxin of your choosing." + icon = FA_ICON_TEETH_OPEN + value = 8 + gain_text = span_notice("You feel a venom gland in the back of your throat.") + lose_text = span_warning("Your venom gland vanishes.") + medical_record_text = "Patient possesses a venom gland." + +/datum/quirk/venomous_bite/add(client/client_source) + var/datum/reagent/reagent = text2path(client_source?.prefs?.read_preference(/datum/preference/choiced/venomous_bite_venom)) + + var/mob/living/carbon/human/human_holder = quirk_holder + var/datum/action/cooldown/mob_cooldown/venomous_bite/action = new /datum/action/cooldown/mob_cooldown/venomous_bite(human_holder, our_reagent = reagent) + action.Grant(human_holder) + +/datum/quirk/venomous_bite/remove() + var/datum/action/cooldown/mob_cooldown/venomous_bite/action = locate(/datum/action/cooldown/mob_cooldown/venomous_bite) in quirk_holder.actions + action.Remove() + + return ..() + +/datum/quirk_constant_data/venomous_bite + associated_typepath = /datum/quirk/venomous_bite + customization_options = list(/datum/preference/choiced/venomous_bite_venom) + +/datum/preference/choiced/venomous_bite_venom + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "venomous_bite_venom" + savefile_identifier = PREFERENCE_CHARACTER + /// Format: (reagent typepath -> list(amount to inject per bite, cooldown)) + var/static/list/venomous_bite_choice_specs = list( + /datum/reagent/toxin = list(5, 80 SECONDS), + /datum/reagent/toxin/venom = list(5, 180 SECONDS), + /datum/reagent/toxin/carpotoxin = list(5, 60 SECONDS), // less powerful than toxin + // drugs + /datum/reagent/drug/space_drugs = list(5, 60 SECONDS), + /datum/reagent/toxin/mindbreaker = list(5, 60 SECONDS), + // erp stuff + /datum/reagent/drug/aphrodisiac/crocin = list(5, 2 SECONDS), + /datum/reagent/drug/aphrodisiac/crocin/hexacrocin = list(5, 5 SECONDS), + /datum/reagent/drug/aphrodisiac/succubus_milk = list(5, 2 SECONDS), + /datum/reagent/drug/aphrodisiac/incubus_draft = list(5, 2 SECONDS), +) + + +/datum/preference/choiced/venomous_bite_venom/init_possible_values() + var/list/choices = list() + for (var/entry in venomous_bite_choice_specs) + choices += "[entry]" + + return choices + +/datum/preference/choiced/venomous_bite_venom/create_default_value() + return "/datum/reagent/toxin" + +/datum/preference/choiced/venomous_bite_venom/compile_constant_data() + var/list/data = ..() + + var/list/titles = list() + + for (var/datum/reagent/entry as anything in venomous_bite_choice_specs) + var/list/specs = venomous_bite_choice_specs[entry] + + var/inject = specs[1] + var/cooldown = specs[2] + + var/name = entry::name + + titles["[entry]"] = "[name] ([inject]u, [cooldown / 10] second cooldown)" + + data[CHOICED_PREFERENCE_DISPLAY_NAMES] = titles + + return data + +/datum/preference/choiced/venomous_bite_venom/is_accessible(datum/preferences/preferences) + . = ..() + if (!.) + return FALSE + + return "Venomous Bite" in preferences.all_quirks + +/datum/preference/choiced/venomous_bite_venom/apply_to_human(mob/living/carbon/human/target, value) + return diff --git a/modular_zubbers/icons/mob/actions/quirks/venomous_bite.dmi b/modular_zubbers/icons/mob/actions/quirks/venomous_bite.dmi new file mode 100644 index 0000000000000000000000000000000000000000..45761c4335fe37b6c77d4a432fcd9bb4668c34f0 GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$ef*T!CNi6cTrZ*(R#|8W2c zGL{7S1v5B2yO9RuWLAYll(?i8Cl_TFlw{`TF)&oj2@WeLD*gT?xZva0CtBXRTIbH3 z58e=JaMAd|Bc1a;nkN~GdU|(Q7zY_&Huh4O^JvnMNg)csD|Jlu?ZZ2}ja4_VkT_xf zB_Q#>8M%BxR5;{V)e;shy{bV~E7m Date: Wed, 26 Feb 2025 16:24:53 +0100 Subject: [PATCH 11/16] Automatic changelog for PR #2988 [ci skip] --- html/changelogs/AutoChangeLog-pr-2988.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2988.yml diff --git a/html/changelogs/AutoChangeLog-pr-2988.yml b/html/changelogs/AutoChangeLog-pr-2988.yml new file mode 100644 index 00000000000..0df73cdfded --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2988.yml @@ -0,0 +1,4 @@ +author: "nikothedude" +delete-after: True +changes: + - rscadd: "Quirk; venemous bite. Allows you to bite people and inject them with a venom, or medicine, of your choosing." \ No newline at end of file From 3af681b307054ca425167e5dba1ab41edc6b5b2b Mon Sep 17 00:00:00 2001 From: The Sharkening <95130227+StrangeWeirdKitten@users.noreply.github.com> Date: Wed, 26 Feb 2025 09:11:50 -0800 Subject: [PATCH 12/16] Hypnotic Quirk (#3163) ## About The Pull Request Adds a new quirk: Hypnotic. If you have ERP prefs on and hypnosis prefs on, all this does is give you an examine text. ## Why It's Good For The Game More quirks are fun, especially for flavor. ## Proof Of Testing ![image](https://github.com/user-attachments/assets/18c06f92-5e82-42d9-85cb-d44a499445ce) ![image](https://github.com/user-attachments/assets/674e1bb4-a4e0-489b-b731-0540245a204d) ## Changelog :cl: add: Hypnotic Quirk /:cl: --- code/__DEFINES/~~bubber_defines/span.dm | 1 + .../datums/quirks/neutral_quirks/hypnotic.dm | 99 +++++++++++++++++++ tgstation.dme | 1 + .../bubbers/hypnotic_quirk.tsx | 14 +++ 4 files changed, 115 insertions(+) create mode 100644 modular_zubbers/code/datums/quirks/neutral_quirks/hypnotic.dm create mode 100644 tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/hypnotic_quirk.tsx diff --git a/code/__DEFINES/~~bubber_defines/span.dm b/code/__DEFINES/~~bubber_defines/span.dm index ae88cc47010..37a8e8fcf66 100644 --- a/code/__DEFINES/~~bubber_defines/span.dm +++ b/code/__DEFINES/~~bubber_defines/span.dm @@ -4,3 +4,4 @@ #define span_velvet(str) ("" + str + "") #define vote_font(str) ("" + str + "") +#define span_yellow_flashy(str) ("" + str + "") diff --git a/modular_zubbers/code/datums/quirks/neutral_quirks/hypnotic.dm b/modular_zubbers/code/datums/quirks/neutral_quirks/hypnotic.dm new file mode 100644 index 00000000000..9a8ee52dfc3 --- /dev/null +++ b/modular_zubbers/code/datums/quirks/neutral_quirks/hypnotic.dm @@ -0,0 +1,99 @@ +/datum/quirk/hypnotic + name = "Hypnotic" + desc = "You are extremely captivating to people who might be suspectable to fall into a stupor" + icon = FA_ICON_FACE_GRIN_HEARTS + value = 0 + quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_HIDE_FROM_SCAN + gain_text = "Your presence grows richer." + lose_text = "Your potent presence dulls." + medical_record_text = "Patient shows signs of a far richer presence then normal." + erp_quirk = TRUE + var/hypnotic_text + var/hypnotic_color + +/datum/quirk/hypnotic/add(client/client_source) + RegisterSignal(quirk_holder, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + +/datum/quirk/hypnotic/post_add() + hypnotic_text = quirk_holder.client.prefs.read_preference(/datum/preference/text/hypnotic_text) + hypnotic_color = quirk_holder.client.prefs.read_preference(/datum/preference/choiced/hypnotic_span) + +/datum/quirk/hypnotic/remove() + UnregisterSignal(quirk_holder, COMSIG_ATOM_EXAMINE) + +/datum/quirk/hypnotic/proc/on_examine(atom/source, mob/user, list/examine_list) + SIGNAL_HANDLER + + var/mob/living/examinee = source + if(!istype(user)) + return + if(!(examinee.client.prefs.read_preference(/datum/preference/toggle/erp/hypnosis))) + return + if(user.stat == DEAD) + return + if(isnull(hypnotic_color)) + return + examine_list += pick_color() + +/datum/quirk/hypnotic/proc/pick_color() + var/choice + switch(hypnotic_color) + if("Hypnophrase") + choice = "hypnophrase" + if("Velvet") + choice = "velvet" + if("Yellow Flashy") + choice = "glossy" + if("Pink") + choice = "pink" + if("Cult") + choice = "cult" + + return "[isnull(hypnotic_text) ? "Their eyes are enticing to stare at." : hypnotic_text]" + +/datum/quirk_constant_data/hypnotic + associated_typepath = /datum/quirk/hypnotic + customization_options = list( + /datum/preference/text/hypnotic_text, + /datum/preference/choiced/hypnotic_span, + ) + +/datum/preference/text/hypnotic_text + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "hypnotic_quirk_text" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + maximum_value_length = 100 + +/datum/preference/text/hypnotic_text/serialize(input) + return htmlrendertext(input) + +/datum/preference/text/hypnotic_text/deserialize(input, datum/preferences/preferences) + return htmlrendertext(input) + +/datum/preference/choiced/hypnotic_span + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "flashy_text" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + +/datum/preference/choiced/hypnotic_span/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return + +/datum/preference/text/hypnotic_text/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return + +/datum/preference/text/hypnotic_text/create_default_value() + return "Their eyes are inciticing to stare at." + +/datum/preference/choiced/hypnotic_span/create_default_value() + return "Hypnophrase" + +/datum/preference/choiced/hypnotic_span/init_possible_values() + return list( + "Hypnophrase", + "Velvet", + "Yellow Flashy", + "Pink", + "Cult", + ) diff --git a/tgstation.dme b/tgstation.dme index c41dde28d7e..14e0361c19b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -8736,6 +8736,7 @@ #include "modular_zubbers\code\datums\quirks\neutral_quirks\food.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\hungry.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\hydrophilic.dm" +#include "modular_zubbers\code\datums\quirks\neutral_quirks\hypnotic.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\lungs.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\nameless.dm" #include "modular_zubbers\code\datums\quirks\neutral_quirks\oversized_quirk.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/hypnotic_quirk.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/hypnotic_quirk.tsx new file mode 100644 index 00000000000..05b48e9f2dd --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/hypnotic_quirk.tsx @@ -0,0 +1,14 @@ +import { Feature, FeatureChoiced, FeatureShortTextInput } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; + +export const hypnotic_quirk_text: Feature = { + name: 'Hypnotic Text Examine', + description: + 'The examine text portrayed from your character. Use third person (Their, He, She, etc)', + component: FeatureShortTextInput, +}; + +export const flashy_text: FeatureChoiced = { + name: 'Text Color Selection', + component: FeatureDropdownInput, +}; From 1137cbdf03c50ab8a21b66eb83beadcc2db6e6ff Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Wed, 26 Feb 2025 18:12:15 +0100 Subject: [PATCH 13/16] Automatic changelog for PR #3163 [ci skip] --- html/changelogs/AutoChangeLog-pr-3163.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3163.yml diff --git a/html/changelogs/AutoChangeLog-pr-3163.yml b/html/changelogs/AutoChangeLog-pr-3163.yml new file mode 100644 index 00000000000..476bb22332d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3163.yml @@ -0,0 +1,4 @@ +author: "StrangeWeirdKitten" +delete-after: True +changes: + - rscadd: "Hypnotic Quirk" \ No newline at end of file From 6e8b24264d39a7440b9644ecca640d33f8c7f72a Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Wed, 26 Feb 2025 23:23:35 +0000 Subject: [PATCH 14/16] Bubberstation automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-2988.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3163.yml | 4 ---- html/changelogs/archive/2025-02.yml | 6 ++++++ 3 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-2988.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3163.yml diff --git a/html/changelogs/AutoChangeLog-pr-2988.yml b/html/changelogs/AutoChangeLog-pr-2988.yml deleted file mode 100644 index 0df73cdfded..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2988.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "nikothedude" -delete-after: True -changes: - - rscadd: "Quirk; venemous bite. Allows you to bite people and inject them with a venom, or medicine, of your choosing." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3163.yml b/html/changelogs/AutoChangeLog-pr-3163.yml deleted file mode 100644 index 476bb22332d..00000000000 --- a/html/changelogs/AutoChangeLog-pr-3163.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "StrangeWeirdKitten" -delete-after: True -changes: - - rscadd: "Hypnotic Quirk" \ No newline at end of file diff --git a/html/changelogs/archive/2025-02.yml b/html/changelogs/archive/2025-02.yml index 042db93c167..1d2c6419907 100644 --- a/html/changelogs/archive/2025-02.yml +++ b/html/changelogs/archive/2025-02.yml @@ -223,3 +223,9 @@ - rscadd: Nameless Quirk xPokee: - rscadd: added the intern ghoul plushie to both in game and the loadouts +2025-02-26: + StrangeWeirdKitten: + - rscadd: Hypnotic Quirk + nikothedude: + - rscadd: Quirk; venemous bite. Allows you to bite people and inject them with a + venom, or medicine, of your choosing. From 76878341e02cd186b2d29ab7a58a6e951d6cd35a Mon Sep 17 00:00:00 2001 From: Roxy <75404941+TealSeer@users.noreply.github.com> Date: Wed, 26 Feb 2025 21:29:43 -0500 Subject: [PATCH 15/16] Fix SAD not transferring wounds (#3167) ## About The Pull Request Add code to `/datum/component/damage_tracker/human` to keep track of wounds and reapply them as needed. ## Why It's Good For The Game Fixes #3162 ## Proof Of Testing I tested with both the permanent limp quirk and breaking one of my arms with force and both wounds stayed after using the SAD ## Changelog :cl: fix: fixed the SAD deleting wounds /:cl: --- .../code/datums/components/damage_tracker.dm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modular_skyrat/master_files/code/datums/components/damage_tracker.dm b/modular_skyrat/master_files/code/datums/components/damage_tracker.dm index f35cc531f9a..83dade56eda 100644 --- a/modular_skyrat/master_files/code/datums/components/damage_tracker.dm +++ b/modular_skyrat/master_files/code/datums/components/damage_tracker.dm @@ -76,6 +76,9 @@ /// What brain traumas does the owner currently have? var/list/trauma_list = list() + /// What wounds does the owner currently have? + var/list/wound_list = list() + /datum/component/damage_tracker/human/update_damage_values() . = ..() var/mob/living/carbon/human/human_parent = parent @@ -86,6 +89,12 @@ if(length(current_trauma_list)) trauma_list = current_trauma_list.Copy() + for(var/obj/item/bodypart/limb as anything in human_parent.get_wounded_bodyparts()) + for(var/datum/wound/limb_wound as anything in limb.wounds) + if(!islist(wound_list[limb.type])) + wound_list[limb.type] = list() + wound_list[limb.type] |= limb_wound.type + heart_damage = human_parent.check_organ_damage(/obj/item/organ/internal/heart) liver_damage = human_parent.check_organ_damage(/obj/item/organ/internal/liver) lung_damage = human_parent.check_organ_damage(/obj/item/organ/internal/lungs) @@ -121,6 +130,14 @@ human_brain.gain_trauma(trauma_to_add) + for(var/obj/item/bodypart/limb_type as anything in wound_list) + var/obj/item/bodypart/limb_instance = locate(limb_type) in human_parent.bodyparts + if(!limb_instance) + continue + for(var/datum/wound/wound_type as anything in wound_list[limb_type]) + var/datum/wound/new_wound = new wound_type() + new_wound.apply_wound(limb_instance, TRUE) + return TRUE /datum/component/damage_tracker/human/Initialize(...) From 0877b4b31d34e137e63fcbc121cb858f88255971 Mon Sep 17 00:00:00 2001 From: Bubberbot <151680451+Bubberbot@users.noreply.github.com> Date: Thu, 27 Feb 2025 03:30:08 +0100 Subject: [PATCH 16/16] Automatic changelog for PR #3167 [ci skip] --- html/changelogs/AutoChangeLog-pr-3167.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3167.yml diff --git a/html/changelogs/AutoChangeLog-pr-3167.yml b/html/changelogs/AutoChangeLog-pr-3167.yml new file mode 100644 index 00000000000..1f2308b8e80 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3167.yml @@ -0,0 +1,4 @@ +author: "TealSeer" +delete-after: True +changes: + - bugfix: "fixed the SAD deleting wounds" \ No newline at end of file