From be4c58986c8b79a2d57ae555e4beeb9992121847 Mon Sep 17 00:00:00 2001 From: nikothedude <59709059+nikothedude@users.noreply.github.com> Date: Sun, 17 May 2026 14:40:01 -0400 Subject: [PATCH] Allows cursekin to load a preference slot instead of simply changing species. (#5568) ## About The Pull Request Title. Adds a new preference option that allows you to designate a character slot as your lycan transformation. Does not transfer quirks and does not change the name. Additionally, allows peopel to use the lycan species as a prefs-only species for customization. ### Note This will likely transfer languages and a few other things, but nothing gamechanging. If the SAD does it (excluding quirks), this probably also does it. ## Why It's Good For The Game Adds for customization of the lycan form. Hair, Augments (NOT IMPLANTS). Even taur mode. ## Proof Of Testing
Screenshots/Videos image
## Changelog :cl: add: Cursekin can select a character slot to transform into rather than just siwtching species. /:cl: --- ...eenshot_humanoids__datum_species_lycan.png | Bin 1073 -> 1073 bytes .../species/lycans/_lycan_species.dm | 17 ++++- .../species/lycans/cursekin_prefs.dm | 20 ++++++ .../species/lycans/organs/lycan_brain.dm | 60 ++++++++++++++---- tgstation.dme | 1 + .../bubbers/cursekin.tsx | 12 ++++ 6 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 modular_zubbers/code/modules/customization/species/lycans/cursekin_prefs.dm create mode 100644 tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/cursekin.tsx diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lycan.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lycan.png index 6c6219f0e07e3d13ce9cfd93d04294ff35ee4685..3ac91e03901733b62715ca4b472d39291b3e8b76 100644 GIT binary patch delta 72 zcmdnUv5{kfzU@pQwq0WEbA;IR)Z|imSkx6HTLoBmim_`cORFhJGB7asa55Wc$eZdY cu`)6+F)-+=$?g_opDx74-s5PxG3O{V03k{aXaE2J delta 72 zcmdnUv5{kfzHNht>+JBrCNCE~HMtN2BXtGId^@XI;elGp(rOBl3=9koDjEhF@}@dU cEX=G-jLf=fvU4JW>fD{ycA6P%%sI*o0Hx^?9RL6T diff --git a/modular_zubbers/code/modules/customization/species/lycans/_lycan_species.dm b/modular_zubbers/code/modules/customization/species/lycans/_lycan_species.dm index 0eb445ea597..2a8f513f137 100644 --- a/modular_zubbers/code/modules/customization/species/lycans/_lycan_species.dm +++ b/modular_zubbers/code/modules/customization/species/lycans/_lycan_species.dm @@ -50,10 +50,12 @@ ) no_equip_flags = ITEM_SLOT_ICLOTHING | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_SUITSTORE | ITEM_SLOT_BACK | ITEM_SLOT_BELT | ITEM_SLOT_EARS | ITEM_SLOT_HEAD | ITEM_SLOT_MASK | ITEM_SLOT_EYES | ITEM_SLOT_BACK | ITEM_SLOT_NECK + always_customizable = TRUE + sort_bottom = TRUE /datum/species/lycan/prepare_human_for_preview(mob/living/carbon/human/lycan) var/main_color = "#362d23" - var/secondary_color = "#9c5852" + var/secondary_color = "#bb1607" var/tertiary_color = "#CCF6E2" lycan.dna.features["mcolor"] = main_color lycan.dna.features["mcolor2"] = secondary_color @@ -68,15 +70,24 @@ race = /datum/species/lycan /datum/species/lycan/get_species_description() - return list(placeholder_description) + return list("The transformed version of a Cursekin. Only available for customization of a Cursekin's transformed form.") /datum/species/lycan/get_species_lore() - return list(placeholder_lore) + return list("See Cursekin lore.") /datum/species/lycan/on_species_gain(mob/living/carbon/human/gainer, datum/species/old_species, pref_load, regenerate_icons = TRUE) . = ..() gainer.AddElement(/datum/element/inorganic_rejection) + gainer.dna.features["body_size"] = 2 + gainer.maptext_height = 32 * gainer.dna.features["body_size"] //Adjust runechat height + gainer.mob_size = MOB_SIZE_LARGE + gainer.dna.update_body_size() /datum/species/lycan/on_species_loss(mob/living/carbon/human/loser, datum/species/new_species, pref_load) . = ..() loser.RemoveElement(/datum/element/inorganic_rejection) + if(!loser.has_quirk(/datum/quirk/oversized)) + loser.dna.features["body_size"] = loser?.client?.prefs?.read_preference(/datum/preference/numeric/body_size) || 1 + loser.maptext_height = 32 * loser.dna.features["body_size"] + loser.mob_size = MOB_SIZE_HUMAN + loser.dna.update_body_size() diff --git a/modular_zubbers/code/modules/customization/species/lycans/cursekin_prefs.dm b/modular_zubbers/code/modules/customization/species/lycans/cursekin_prefs.dm new file mode 100644 index 00000000000..7859271a858 --- /dev/null +++ b/modular_zubbers/code/modules/customization/species/lycans/cursekin_prefs.dm @@ -0,0 +1,20 @@ +/datum/preference/numeric/cursekin_char_slot + category = PREFERENCE_CATEGORY_CHARACTER_BASICS + savefile_identifier = PREFERENCE_CHARACTER + savefile_key = "cursekin_char_slot" + can_randomize = FALSE + minimum = 0 + maximum = /datum/preferences::max_save_slots + +/datum/preference/numeric/cursekin_char_slot/has_relevant_feature(datum/preferences/preferences) + . = ..() + if (!.) + return FALSE + + return ispath(preferences.read_preference(/datum/preference/choiced/species), /datum/species/human/cursekin) + +/datum/preference/numeric/cursekin_char_slot/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return + +/datum/preference/numeric/cursekin_char_slot/create_default_value() + return 0 diff --git a/modular_zubbers/code/modules/customization/species/lycans/organs/lycan_brain.dm b/modular_zubbers/code/modules/customization/species/lycans/organs/lycan_brain.dm index 96432d0b572..107cab3d7e6 100644 --- a/modular_zubbers/code/modules/customization/species/lycans/organs/lycan_brain.dm +++ b/modular_zubbers/code/modules/customization/species/lycans/organs/lycan_brain.dm @@ -3,6 +3,23 @@ desc = "A larger than average, albeit slightly smoother brain. The hypothalamus seems larger than normal." // I read in a random medical artical that the hypothalamus controls aggression. actions_types = list(/datum/action/cooldown/spell/beast_form) var/list/removed_quirks = list() + var/last_slot + +/obj/item/organ/brain/lycan/on_mob_insert(mob/living/carbon/brain_owner, special, movement_flags) + . = ..() + + addtimer(CALLBACK(src, PROC_REF(try_getting_slot)), 0.1 SECONDS) + +// no remove. we want it to REMEMBER. + +/// A delayed getter for the current slot of the mob. Used because theres no easy way to access the client when a mob is spawend... +/obj/item/organ/brain/lycan/proc/try_getting_slot() + if (last_slot) + return + + var/client/target_client = owner?.client + if (!isnull(target_client)) + last_slot = target_client.prefs.savefile.get_entry("default_slot") /obj/item/organ/brain/lycan/proc/enter_beast_form() var/datum/species/human/cursekin/current_wolf = owner.dna.species @@ -15,12 +32,30 @@ removed_quirks += bad_quirk.type owner.remove_quirk(bad_quirk.type) owner.visible_message(span_warning("[owner] grows massive, their body quickly getting covered in fur!")) - owner.set_species(current_wolf.lycanthropy_species, TRUE, TRUE, FALSE) + var/client/target_client = owner.client + if (!isnull(target_client)) + var/name = owner.real_name + var/slot = target_client.prefs.read_preference(/datum/preference/numeric/cursekin_char_slot) + var/transfer = TRUE + if (isnull(last_slot)) + last_slot = target_client.prefs.savefile.get_entry("default_slot") + target_client.prefs.load_character(slot) + if (!ispath(target_client.prefs.read_preference(/datum.preference/choiced/species), current_wolf.lycanthropy_species)) + to_chat(owner, span_warning("Your selected slot is not a lycan! Defaulting to simply changing your species...")) + target_client.prefs.load_character(last_slot) + owner.set_species(current_wolf.lycanthropy_species, TRUE, TRUE, FALSE) + last_slot = null // allows for easier switching in later procs + transfer = FALSE + + if (transfer) + target_client.prefs.safe_transfer_prefs_to_with_damage(owner) + owner.real_name = name + owner.name = name + owner.dna.update_dna_identity() + + target_client.prefs.load_character(last_slot) + ADD_TRAIT(owner, TRAIT_BEAST_FORM, SPECIES_TRAIT) - owner.dna.features["body_size"] = 2 - owner.maptext_height = 32 * owner.dna.features["body_size"] //Adjust runechat height - owner.dna.update_body_size() - owner.mob_size = MOB_SIZE_LARGE playsound(owner, 'modular_zubbers/code/modules/customization/species/lycans/transform.ogg', 50) /obj/item/organ/brain/lycan/proc/leave_beast_form() @@ -28,13 +63,16 @@ if(isnull(current_wolf) && !HAS_TRAIT_FROM(owner, TRAIT_BEAST_FORM, SPECIES_TRAIT)) return owner.visible_message(span_warning("[owner] shrinks down, their fur receding!")) - owner.set_species(/datum/species/human/cursekin, TRUE, TRUE, FALSE) + + if (last_slot) + var/client/target_client = owner.client + if (!isnull(target_client)) + target_client.prefs.load_character(last_slot) + target_client.prefs.safe_transfer_prefs_to_with_damage(owner) + owner.dna.update_dna_identity() + else + owner.set_species(/datum/species/human/cursekin, TRUE, TRUE, FALSE) REMOVE_TRAIT(owner, TRAIT_BEAST_FORM, SPECIES_TRAIT) - if(!owner.has_quirk(/datum/quirk/oversized)) - owner.dna.features["body_size"] = owner?.client?.prefs ?owner?.client?.prefs?.read_preference(/datum/preference/numeric/body_size) : 1 - owner.maptext_height = 32 * owner.dna.features["body_size"] - owner.dna.update_body_size() - owner.mob_size = MOB_SIZE_HUMAN playsound(owner, 'modular_zubbers/code/modules/customization/species/lycans/transform.ogg', 50) if(removed_quirks) for(var/typepath in removed_quirks) diff --git a/tgstation.dme b/tgstation.dme index a61cca12cac..0a26d389a49 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -9502,6 +9502,7 @@ #include "modular_zubbers\code\modules\customization\species\lycans\_cursekin_species.dm" #include "modular_zubbers\code\modules\customization\species\lycans\_lycan_species.dm" #include "modular_zubbers\code\modules\customization\species\lycans\cursekin_blacklisted_quirks.dm" +#include "modular_zubbers\code\modules\customization\species\lycans\cursekin_prefs.dm" #include "modular_zubbers\code\modules\customization\species\lycans\lycan_verbs.dm" #include "modular_zubbers\code\modules\customization\species\lycans\bodyparts\lycan_bodyparts.dm" #include "modular_zubbers\code\modules\customization\species\lycans\organs\lycan_brain.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/cursekin.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/cursekin.tsx new file mode 100644 index 00000000000..d7fdc3d587a --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/cursekin.tsx @@ -0,0 +1,12 @@ +import { + type Feature, + FeatureNumberInput, +} from '../../base'; + +export const cursekin_char_slot: Feature = { + name: 'Lycan Character Slot', + description: + "The index of the character slot, from top to bottom, of the lycan character slot that will be used when you transform. \ + Does not use quirks, implants, or the set name. Set to a non-lycan slot to simply switch species instead of loading a slot.", + component: FeatureNumberInput, +};