Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions code/datums/bodypart_overlays/mutant_bodypart_overlay.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@
stack_trace("adding a [parent.type] to a [receiver.type] when it shouldn't be!")

if(imprint_on_next_insertion) //We only want this set *once*
var/feature_name = receiver.dna.features[feature_key] || receiver.dna.species.mutant_organs[parent.type]
/* DOPPLER EDIT START - Uses special_feature_key from modular instead of normal feature_keys */
var/dna_feature_key = special_feature_key || feature_key
var/feature_name = receiver.dna.features[dna_feature_key] || receiver.dna.species.mutant_organs[parent.type] // originally: var/feature_name = receiver.dna.features[feature_key] || receiver.dna.species.mutant_organs[parent.type]
/* DOPPLER EDIT END */
if (isnull(feature_name))
stack_trace("[type] has no default feature name for organ [parent.type]!")
// DOPPLER REMOVAL (stack_trace works off of mutant part assumptions that aren't compatible with our own mutant part system) - stack_trace("[type] has no default feature name for organ [parent.type]!")
feature_name = get_consistent_feature_entry(get_global_feature_list()) //fallback to something
set_appearance_from_name(feature_name)
imprint_on_next_insertion = FALSE
Expand Down
2 changes: 2 additions & 0 deletions code/modules/mob/living/carbon/human/dummy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/proc/create_consistent_human_dna(mob/living/carbon/human/target)
target.dna.features[FEATURE_MUTANT_COLOR] = COLOR_VIBRANT_LIME
target.dna.features[FEATURE_ETHEREAL_COLOR] = COLOR_WHITE
/* DOPPLER REMOVAL START - Removes applying ALL consistent features just because they exist
for(var/feature_key in SSaccessories.feature_list)
target.dna.features[feature_key] = get_consistent_feature_entry(SSaccessories.feature_list[feature_key])
DOPPLER REMOVAL END */
// DOPPLER ADDITION START - Fix tri color features in dummies
target.dna.features[FEATURE_EARS_COLORS] = DEFAULT_MATRIXED_FEATURE_COLORS
target.dna.features[FEATURE_MARKINGS_COLORS] = DEFAULT_MATRIXED_FEATURE_COLORS
Expand Down
10 changes: 9 additions & 1 deletion code/modules/surgery/organs/external/tails.dm
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,17 @@
if(!tail_spine_key)
return

/* DOPPLER ADDITION START - Fixes tail spines throwing runtimes when spawning humanoid mobs/corpses with tails
* The tail spines overlay is dependent on the owner's DNA, which may not be set yet.
* If the owner doesn't have a valid DNA, don't insert the tail spines overlay.*/
var/obj/item/organ/spines/owner_spines = bodypart.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES)
var/feature_name = bodypart.owner.dna.features[FEATURE_SPINES] || bodypart.owner.dna.species.mutant_organs[owner_spines?.type]
if(!feature_name || feature_name == SPRITE_ACCESSORY_NONE)
return
/* DOPPLER ADDITION END */
tail_spines_overlay = new
tail_spines_overlay.tail_spine_key = tail_spine_key
var/feature_name = bodypart.owner.dna.features[FEATURE_SPINES] //tail spines don't live in DNA, but share feature names with regular spines
//DOPPLER REMOVAL: var/feature_name = bodypart.owner.dna.features[FEATURE_SPINES] //tail spines don't live in DNA, but share feature names with regular spines
tail_spines_overlay.set_appearance_from_name(feature_name)
bodypart.add_bodypart_overlay(tail_spines_overlay)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,14 @@
/datum/bodypart_overlay/mutant/proc/get_feature_key_for_overlay()
return sprite_datum?.key || feature_key

/// Returns the DNA feature which controls whether an organ type's overlay is present.
/proc/get_bodypart_overlay_dna_feature_key_from_type(obj/item/organ/organ_type)
if(isnull(organ_type))
return null
var/datum/bodypart_overlay/mutant/overlay_type = initial(organ_type.bodypart_overlay)
if(isnull(overlay_type))
return null
return initial(overlay_type.special_feature_key) || initial(overlay_type.feature_key)

#undef MAX_MATRIXED_COLORS
#undef ALPHA_OPAQUE
46 changes: 34 additions & 12 deletions modular_doppler/modular_customization/preferences/tail.dm
Original file line number Diff line number Diff line change
@@ -1,31 +1,52 @@
/datum/dna
/// This variable is read by the regenerate_organs() proc to know what organ subtype to give
var/tail_type = NO_VARIATION
/// Null until a tail choice is applied, NO_VARIATION for an explicit opt-out, or a tail category to generate.
var/tail_type

/datum/species/regenerate_organs(mob/living/carbon/target, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE, replace_missing = TRUE)
. = ..()
if(target == null)
return
return ..()

// The normal organ code will not add a tail while its DNA feature is set to "None".
// Read which feature the species' tail overlay uses directly from its type, then set that feature to the species default before calling the normal organ code below.
// Without this, generic mobs without player preferences will not get a tail when their species should.
var/use_species_default_tail = FALSE
if(isnull(target.dna.tail_type)) // always false when the target has prefs
var/obj/item/organ/species_tail_type = get_mutant_organ_type_for_slot(ORGAN_SLOT_EXTERNAL_TAIL)
if(species_tail_type) // always false when a species doesn't normally have a tail
var/default_tail_appearance = mutant_organs[species_tail_type]
var/tail_feature_key = get_bodypart_overlay_dna_feature_key_from_type(species_tail_type)
if(tail_feature_key && default_tail_appearance)
target.dna.features[tail_feature_key] = default_tail_appearance
use_species_default_tail = TRUE

. = ..()
// The parent has now handled the species' usual tail. The customization branches below are only for player-prefs tail choices, including an explicit preference to have no tail.
if(use_species_default_tail)
return .

if(!ishuman(target))
return

if(can_regenerate_mutant_feature(FEATURE_TAIL_LIZARD) && target.dna.features[FEATURE_TAIL_LIZARD] != /datum/sprite_accessory/blank::name)
// Because we both have None & Null as possible values we check target.dna.features twice. First for null, then afterwards for "None"
// can_regenerate_mutant_feature() is used to prevent giving mutant parts to species on GLOB.species_blacklist_no_mutant
if(target.dna.features[FEATURE_TAIL_LIZARD] && can_regenerate_mutant_feature(FEATURE_TAIL_LIZARD) && target.dna.features[FEATURE_TAIL_LIZARD] != /datum/sprite_accessory/blank::name)
var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/tail/lizard)
replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED)
return .
else if(can_regenerate_mutant_feature(FEATURE_TAIL_CAT) && target.dna.features[FEATURE_TAIL_CAT] != /datum/sprite_accessory/blank::name)
else if(target.dna.features[FEATURE_TAIL_CAT] && can_regenerate_mutant_feature(FEATURE_TAIL_CAT) && target.dna.features[FEATURE_TAIL_CAT] != /datum/sprite_accessory/blank::name)
var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/tail/cat)
replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED)
return .
else if(can_regenerate_mutant_feature(FEATURE_TAIL_MONKEY) && target.dna.features[FEATURE_TAIL_MONKEY] != /datum/sprite_accessory/blank::name)
else if(target.dna.features[FEATURE_TAIL_MONKEY] && can_regenerate_mutant_feature(FEATURE_TAIL_MONKEY) && target.dna.features[FEATURE_TAIL_MONKEY] != /datum/sprite_accessory/blank::name)
var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/tail/monkey)
replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED)
return .
else if(can_regenerate_mutant_feature(FEATURE_TAIL_FISH) && target.dna.features[FEATURE_TAIL_FISH] != /datum/sprite_accessory/blank::name)
else if(target.dna.features[FEATURE_TAIL_FISH] && can_regenerate_mutant_feature(FEATURE_TAIL_FISH) && target.dna.features[FEATURE_TAIL_FISH] != /datum/sprite_accessory/blank::name)
var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/tail/fish)
replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED)
return .
else if((can_regenerate_mutant_feature(FEATURE_TAIL_OTHER) && target.dna.features[FEATURE_TAIL_OTHER] != /datum/sprite_accessory/blank::name) && (target.dna.tail_type != NO_VARIATION))
else if((target.dna.features[FEATURE_TAIL_OTHER] && can_regenerate_mutant_feature(FEATURE_TAIL_OTHER) && target.dna.features[FEATURE_TAIL_OTHER] != /datum/sprite_accessory/blank::name) && (target.dna.tail_type && target.dna.tail_type != NO_VARIATION))
var/obj/item/organ/organ_path = text2path("/obj/item/organ/tail/[target.dna.tail_type]")
var/obj/item/organ/replacement = SSwardrobe.provide_type(organ_path)
replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED)
Expand Down Expand Up @@ -715,8 +736,9 @@
feature_key_sprite = "tail"

/datum/bodypart_overlay/mutant/tail/color_images(list/image/overlays, layer, obj/item/bodypart/limb)
if((sprite_datum.color_src == USE_ONE_COLOR) && length(limb.owner?.dna.features[FEATURE_TAIL_COLORS]))
draw_color = limb.owner?.dna.features[FEATURE_TAIL_COLORS][1]
else
draw_color = limb.owner?.dna.features[FEATURE_TAIL_COLORS]
var/list/tail_colors = limb.owner?.dna.features[FEATURE_TAIL_COLORS]
// Preference colors override the tail's inherited limb color. Generic mobs do not have this
// preference data, so retaining draw_color makes their native tail match their mutant color.
if(length(tail_colors))
draw_color = sprite_datum.color_src == USE_ONE_COLOR ? tail_colors[1] : tail_colors
return ..()
Loading