From e902125c5e4d2136ac7e7e8e5bce25a410890d6f Mon Sep 17 00:00:00 2001 From: CHOMPStation2StaffMirrorBot <94713762+CHOMPStation2StaffMirrorBot@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:13:01 -0700 Subject: [PATCH] [MIRROR] DNA Clone Fix (#10580) Co-authored-by: Will <7099514+Willburd@users.noreply.github.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> --- .github/workflows/render_nanomaps.yml | 1 + code/__defines/species_languages.dm | 1 + code/game/dna/dna2_helpers.dm | 4 +- code/game/machinery/bioprinter.dm | 8 +- .../food/kitchen/cooking_machines/fryer.dm | 2 +- code/modules/mob/living/butchering.dm | 2 - .../mob/living/carbon/human/appearance.dm | 7 +- code/modules/mob/living/carbon/human/human.dm | 2 +- .../human/species/species_shapeshift.dm | 2 +- .../human/species/xenomorphs/alien_species.dm | 2 +- .../mob/living/carbon/human/update_icons.dm | 4 +- code/modules/organs/data.dm | 103 ++++++++++++++++++ code/modules/organs/organ.dm | 29 +++-- code/modules/organs/organ_external.dm | 28 +++-- code/modules/organs/organ_icon.dm | 79 ++++++-------- code/modules/organs/subtypes/seromi.dm | 8 -- code/modules/organs/subtypes/standard.dm | 2 +- code/modules/organs/subtypes/xenos.dm | 11 -- code/modules/research/prosfab_designs.dm | 15 +-- .../code/modules/organs/organ_icon.dm | 26 ++--- vorestation.dme | 1 + 21 files changed, 199 insertions(+), 138 deletions(-) create mode 100644 code/modules/organs/data.dm delete mode 100644 code/modules/organs/subtypes/seromi.dm diff --git a/.github/workflows/render_nanomaps.yml b/.github/workflows/render_nanomaps.yml index b46fa5bbd7..05594d7f59 100644 --- a/.github/workflows/render_nanomaps.yml +++ b/.github/workflows/render_nanomaps.yml @@ -40,6 +40,7 @@ jobs: ${{ runner.os }}-spacemandmm- - name: Install Tools run: | + sudo apt update bash tools/ci/install_spaceman_dmm.sh dmm-tools sudo apt install -y imagemagick - name: Ensure +x on github-actions directory diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index e11b0a3dec..9b7647917c 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -12,6 +12,7 @@ #define NO_INFECT 0x400 // Don't allow infections in limbs or organs, similar to IS_PLANT, without other strings. #define NO_DEFIB 0x800 // Don't allow them to be defibbed #define NO_DNA 0x1000 // Cannot have mutations or have their dna changed by genetics/radiation/genome-stolen. +#define THICK_SKIN 0x2000 // Needles have a chain to fail when attempted to be used on them. // unused: 0x8000 - higher than this will overflow // Species EMP vuln for carbons diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 03057dd174..1932f65be8 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -302,12 +302,10 @@ else return 0 -//VOREStation Add /mob/living/carbon/human/proc/force_update_organs() for(var/obj/item/organ/O as anything in organs + internal_organs) - O.species = species + O.data.setup_from_species(species) species.post_spawn_special(src) -//VOREStation Add End // Used below, simple injection modifier. /proc/probinj(var/pr, var/inj) diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index d67f33c431..c46da76bcc 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -254,7 +254,7 @@ O.status |= ORGAN_CUT_AWAY var/mob/living/carbon/human/C = loaded_dna["donor"] O.set_dna(C.dna) - O.species = C.species + O.data.setup_from_species(C.species) var/malfunctioned = FALSE @@ -264,7 +264,7 @@ var/new_species = pick(possible_species) if(!GLOB.all_species[new_species]) new_species = SPECIES_HUMAN - O.species = GLOB.all_species[new_species] + O.data.setup_from_species(GLOB.all_species[new_species]) if(istype(O, /obj/item/organ/external) && !malfunctioned) var/obj/item/organ/external/E = O @@ -273,9 +273,9 @@ O.pixel_x = rand(-6.0, 6) O.pixel_y = rand(-6.0, 6) - if(O.species) + if(O.data) // This is a very hacky way of doing of what organ/New() does if it has an owner - O.w_class = max(O.w_class + mob_size_difference(O.species.mob_size, MOB_MEDIUM), 1) + O.w_class = max(O.w_class + mob_size_difference(O.data.get_species_mob_size(), MOB_MEDIUM), 1) return O // END GENERIC PRINTER diff --git a/code/modules/food/kitchen/cooking_machines/fryer.dm b/code/modules/food/kitchen/cooking_machines/fryer.dm index 5a73b1e768..a56f4c0cd5 100644 --- a/code/modules/food/kitchen/cooking_machines/fryer.dm +++ b/code/modules/food/kitchen/cooking_machines/fryer.dm @@ -209,7 +209,7 @@ if(ishuman(victim) && user.zone_sel.selecting != BP_GROIN && user.zone_sel.selecting != BP_TORSO) var/mob/living/carbon/human/H = victim E = H.get_organ(user.zone_sel.selecting) - if(!E || E.species.flags & NO_PAIN) + if(!E || E.data.get_species_flags() & NO_PAIN) nopain = 2 else if(E.robotic >= ORGAN_ROBOT) nopain = 1 diff --git a/code/modules/mob/living/butchering.dm b/code/modules/mob/living/butchering.dm index aa1381eaf4..22ab08c48b 100644 --- a/code/modules/mob/living/butchering.dm +++ b/code/modules/mob/living/butchering.dm @@ -62,8 +62,6 @@ var/mob/living/simple_mob/SM = src if(SM.limb_icon) neworg.force_icon = SM.limb_icon - neworg.force_icon_key = SM.limb_icon_key - organs |= neworg organs -= path diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 085f72501b..7290601a61 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -172,8 +172,7 @@ /mob/living/carbon/human/proc/update_dna() check_dna() dna.ready_dna(src) - for(var/obj/item/organ/O in organs) - qdel_swap(O.dna, dna.Clone()) // Update all of those because apparently they're separate, and icons won't update properly + sync_organ_dna(dna) /mob/living/carbon/human/proc/generate_valid_species(var/check_whitelist = 1, var/list/whitelist = list(), var/list/blacklist = list()) var/list/valid_species = new() @@ -198,7 +197,7 @@ var/use_species = species.get_bodytype(src) var/obj/item/organ/external/head/H = get_organ(BP_HEAD) - if(H) use_species = H.species.get_bodytype(src) + if(H) use_species = H.data.get_species_bodytype(src) var/list/valid_hairstyles = new() for(var/hairstyle in hair_styles_list) @@ -224,7 +223,7 @@ var/use_species = species.get_bodytype(src) var/obj/item/organ/external/head/H = get_organ(BP_HEAD) - if(H) use_species = H.species.get_bodytype(src) + if(H) use_species = H.data.get_species_bodytype(src) var/list/valid_facial_hairstyles = new() for(var/facialhairstyle in facial_hair_styles_list) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index aac3f5fc43..ad6d632598 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1432,7 +1432,7 @@ else if (affecting.robotic >= ORGAN_LIFELIKE) . = 0 fail_msg = "Your needle refuses to penetrate more than a short distance..." - else if (affecting.thick_skin && prob(70 - round(affecting.brute_dam + affecting.burn_dam / 2))) // Allows transplanted limbs with thick skin to maintain their resistance. + else if ((species.flags & THICK_SKIN) && prob(70 - round(affecting.brute_dam + affecting.burn_dam / 2))) // Allows transplanted limbs with thick skin to maintain their resistance. . = 0 fail_msg = "Your needle fails to penetrate \the [affecting]'s thick hide..." else diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm index 544018818e..128131fcc9 100644 --- a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm +++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm @@ -276,7 +276,7 @@ var/list/wrapped_species_by_ref = list() for(var/limb in organs_by_name) var/obj/item/organ/external/O = organs_by_name[limb] if(limb_exists[O.organ_tag]) - O.species = GLOB.all_species[new_species] + O.data.setup_from_species(GLOB.all_species[new_species]) O.wounds = wounds_by_limb[O.organ_tag] // sync the organ's damage with its wounds O.update_damages() diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index 62513ddcdf..e59d021f63 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -24,7 +24,7 @@ cold_level_2 = -1 cold_level_3 = -1 - flags = NO_DNA | NO_SLEEVE | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT | NO_INFECT | NO_DEFIB + flags = NO_DNA | NO_SLEEVE | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT | NO_INFECT | NO_DEFIB | THICK_SKIN spawn_flags = SPECIES_IS_RESTRICTED reagent_tag = IS_XENOS diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 8a2e6b23e7..0eb5813f03 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -226,8 +226,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //see UpdateDamageIcon() continue if(part) wholeicontransparent &&= part.transparent //VORESTATION EDIT: transparent instead of nonsolid - icon_key += "[part.species.get_race_key(part.owner)]" - icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" + icon_key += "[part.data.get_species_race_key(part.owner)]" + icon_key += "[part.data.body_gender]" icon_key += "[part.s_tone]" if(part.s_col && part.s_col.len >= 3) icon_key += "[rgb(part.s_col[1],part.s_col[2],part.s_col[3])]" diff --git a/code/modules/organs/data.dm b/code/modules/organs/data.dm new file mode 100644 index 0000000000..7b617ab5bd --- /dev/null +++ b/code/modules/organs/data.dm @@ -0,0 +1,103 @@ +// Data written to each organ on creation for appearance and blood, this WAS originally done by sending the full dna datum. +// However sending the whole dna datum through Clone() is extremely expensive, and a memory leak if its a hardref instead. +/datum/organ_data + VAR_PRIVATE/datum/weakref/species + // Species currently uses a cache system, if the species datum deletes, these are used as fallbacks for the last obtained state from the species datum + // In the future, transforming species need to be refactored to not need this, as it's the only thing holding it back from proper isolation. + + // Species + VAR_PRIVATE/cached_species_vars = list() + + // Dna + var/unique_enzymes + var/b_type + var/body_gender + var/digitigrade + var/skin_tone + var/list/skin_color + var/list/hair_color + +/datum/organ_data/proc/setup_from_dna(var/datum/dna/dna) + SHOULD_NOT_OVERRIDE(TRUE) + // Prosfab uses default dna to get vars, lets respect that still + var/self_clear = FALSE + if(!dna) + dna = new() + dna.ResetUI() + self_clear = TRUE + + // Setup cached dna data, as storing the entire DNA cloned is horrifically laggy + unique_enzymes = dna.unique_enzymes + body_gender = dna.GetUIState(DNA_UI_GENDER) + if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE))) + skin_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) + skin_color = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B)) + hair_color = list(dna.GetUIValue(DNA_UI_HAIR_R), dna.GetUIValue(DNA_UI_HAIR_G), dna.GetUIValue(DNA_UI_HAIR_B)) + digitigrade = dna.digitigrade + + // Cleanup for synthfab default dna + if(self_clear) + qdel(dna) + +/datum/organ_data/proc/setup_from_species(var/datum/species/S) // This needs a full rework, but can't be done unless all of transformating species code is refactored + SHOULD_NOT_OVERRIDE(TRUE) + species = WEAKREF(S) + +// All accessed vars need to be cached during read. +// Get data from species, if this fails use cached data +#define SETUP_SPECIES_CHECK(p,x)\ +var/datum/species/SP = species?.resolve();\ +if(SP)\ + cached_species_vars[p] = x;\ +return cached_species_vars[p]; + + +/datum/organ_data/proc/get_species_name() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("name",SP.name) + +/datum/organ_data/proc/get_species_race_key(var/owner) + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("race_key",SP.get_race_key(owner)) + +/datum/organ_data/proc/get_species_bodytype(var/mob/living/carbon/human/H) + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("bodytype",SP.get_bodytype(H)) + +/datum/organ_data/proc/get_species_icobase(var/mob/living/carbon/human/H, var/get_deform) + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("icobase",SP.get_icobase(H,get_deform)) + +/datum/organ_data/proc/get_species_flags() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("flags",SP.flags) + +/datum/organ_data/proc/get_species_appearance_flags() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("appearance_flags",SP.appearance_flags) + +/datum/organ_data/proc/get_species_health_hud_intensity() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("health_hud_intensity",SP.health_hud_intensity) + +/datum/organ_data/proc/get_species_color_mult() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("color_mult",SP.color_mult) + +/datum/organ_data/proc/get_species_mob_size() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("mob_size",SP.mob_size) + +/datum/organ_data/proc/get_species_flesh_colour(var/owner) + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("flesh_colour",SP.get_flesh_colour(owner) || "#C80000") + +/datum/organ_data/proc/get_species_blood_colour(var/owner) + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("blood_colour",SP.get_blood_colour(owner) || "#C80000") + +/datum/organ_data/proc/get_species_icodigi() + SHOULD_NOT_OVERRIDE(TRUE) + SETUP_SPECIES_CHECK("icodigi",SP.icodigi) + +#undef SETUP_SPECIES_CHECK diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index e0baa420f9..69f3cd1245 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -23,8 +23,7 @@ var/list/organ_cache = list() var/list/transplant_data // Transplant match data. var/list/autopsy_data = list() // Trauma data for forensics. var/list/trace_chemicals = list() // Traces of chemicals in the organ. - var/datum/dna/dna // Original DNA. - var/datum/species/species // Original species. + var/datum/organ_data/data = new() // Stores data for appearance and investigation // Damage vars. var/min_bruised_damage = 10 // Damage before considered bruised @@ -54,8 +53,7 @@ var/list/organ_cache = list() if(transplant_data) transplant_data.Cut() if(autopsy_data) autopsy_data.Cut() if(trace_chemicals) trace_chemicals.Cut() - QDEL_NULL(dna) - species = null + QDEL_NULL(data) return ..() @@ -91,10 +89,11 @@ var/list/organ_cache = list() max_damage = min_broken_damage * 2 if(iscarbon(owner)) var/mob/living/carbon/C = owner - species = GLOB.all_species[SPECIES_HUMAN] + if(!C.species) + data.setup_from_species(GLOB.all_species[SPECIES_HUMAN]) if(owner.dna) - qdel_swap(dna, C.dna.Clone()) - species = C.species + data.setup_from_dna(C.dna) + data.setup_from_species(C.species) else log_debug("[src] at [loc] spawned without a proper DNA.") var/mob/living/carbon/human/H = C @@ -105,12 +104,12 @@ var/list/organ_cache = list() if(E.internal_organs == null) E.internal_organs = list() E.internal_organs |= src - if(dna) + if(data) if(!blood_DNA) blood_DNA = list() - blood_DNA[dna.unique_enzymes] = dna.b_type + blood_DNA[data.unique_enzymes] = data.b_type else - species = GLOB.all_species["Human"] + data.setup_from_species(GLOB.all_species["Human"]) handle_organ_mod_special() @@ -131,10 +130,10 @@ var/list/organ_cache = list() /obj/item/organ/proc/set_dna(var/datum/dna/new_dna) if(new_dna) - qdel_swap(dna, new_dna.Clone()) + data.setup_from_dna(new_dna) if(blood_DNA) blood_DNA.Cut() - blood_DNA[dna.unique_enzymes] = dna.b_type + blood_DNA[data.unique_enzymes] = data.b_type /obj/item/organ/proc/die() if(robotic < ORGAN_ROBOT) @@ -259,9 +258,9 @@ var/list/organ_cache = list() /obj/item/organ/proc/handle_rejection() // Process unsuitable transplants. TODO: consider some kind of // immunosuppressant that changes transplant data to make it match. - if(dna && can_reject) + if(data && can_reject) if(!rejecting) - if(blood_incompatible(dna.b_type, owner.dna.b_type, species.name, owner.species.name)) //VOREStation Edit - Process species by name. + if(blood_incompatible(data.b_type, owner.dna.b_type, data.get_species_name(), owner.species.name)) //VOREStation Edit - Process species by name. rejecting = 1 else rejecting++ //Rejection severity increases over time. @@ -519,7 +518,7 @@ var/list/organ_cache = list() qdel(src) /obj/item/organ/proc/organ_can_feel_pain() - if(species.flags & NO_PAIN) + if(data.get_species_flags() & NO_PAIN) return 0 if(status & ORGAN_DESTROYED) return 0 diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 0d0e6bc410..5d06adda82 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -31,8 +31,6 @@ var/burn_dam = 0 // Actual current burn damage. var/last_dam = -1 // used in healing/processing calculations. var/spread_dam = 0 - var/thick_skin = 0 // If a needle has a chance to fail to penetrate. - // Appearance vars. var/nonsolid // Snowflake warning, reee. Used for slime limbs. var/transparent // As above, so below. Used for transparent limbs. @@ -41,7 +39,6 @@ var/icon_position = 0 // Used in mob overlay layering calculations. var/model // Used when caching robolimb icons. var/force_icon // Used to force override of species-specific limb icons (for prosthetics). Also used for any limbs chopped from a simple mob, and then attached to humans. - var/force_icon_key // Used to force the override of the icon-key generated using the species. Must be used in tandem with the above. var/icon/mob_icon // Cached icon for use in mob overlays. var/gendered_icon = 0 // Whether or not the icon state appends a gender. var/s_tone // Skin tone. @@ -257,7 +254,8 @@ /obj/item/organ/external/LateInitialize() . = ..() - get_icon() + if(!QDELETED(src)) + get_icon() /obj/item/organ/external/replaced(var/mob/living/carbon/human/target) owner = target @@ -595,13 +593,15 @@ This function completely restores a damaged organ to perfect condition. //moved this before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return) //Possibly trigger an internal wound, too. var/local_damage = brute_dam + burn_dam + damage - if((damage > 15) && (type != BURN) && (local_damage > 30) && prob(damage) && (robotic < ORGAN_ROBOT) && !(species.flags & NO_BLOOD)) + if((damage > 15) && (type != BURN) && (local_damage > 30) && prob(damage) && (robotic < ORGAN_ROBOT) && !(data.get_species_flags() & NO_BLOOD)) var/datum/wound/internal_bleeding/I = new (min(damage - 15, 15)) wounds += I owner.custom_pain("Something ruptures inside of your [name]. You get the feeling you'll need more than just a bandage to fix it.", 15, TRUE) to_chat(owner, span_bolddanger(span_massive("OH GOD! Something just tore in your [name]!"))) //Let's make this CLEAR that an artery was severed. This was vague enough that most players didn't realize they had IB. - if((damage > 5 || damage + burn_dam >= 15) && type == BURN && (robotic < ORGAN_ROBOT) && !(species.flags & NO_BLOOD)) +//Burn damage can cause fluid loss due to blistering and cook-off + + if((damage > 5 || damage + burn_dam >= 15) && type == BURN && (robotic < ORGAN_ROBOT) && !(data.get_species_flags() & NO_BLOOD)) var/fluid_loss = 0.1 * (damage/(owner.getMaxHealth() - CONFIG_GET(number/health_threshold_dead))) * owner.species.blood_volume*(1 - owner.species.blood_level_fatal) //CHOMPedit reduce fluid loss 4-fold so lasers dont suck your blood owner.remove_blood(fluid_loss) // first check whether we can widen an existing wound @@ -787,8 +787,7 @@ Note that amputating the affected organ does in fact remove the infection from t //Updating wounds. Handles wound natural I had some free spachealing, internal bleedings and infections /obj/item/organ/external/proc/update_wounds() - - if((robotic >= ORGAN_ROBOT) || (species.flags & UNDEAD)) //Robotic and dead limbs don't heal or get worse. + if((robotic >= ORGAN_ROBOT) || (data.get_species_flags() & UNDEAD)) //Robotic and dead limbs don't heal or get worse. for(var/datum/wound/W in wounds) //Repaired wounds disappear though if(W.damage <= 0) //and they disappear right away wounds -= W //TODO: robot wounds for robot limbs @@ -959,8 +958,8 @@ Note that amputating the affected organ does in fact remove the infection from t var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed(). var/obj/item/organ/external/parent_organ = parent - var/use_flesh_colour = species?.get_flesh_colour(owner) ? species.get_flesh_colour(owner) : "#C80000" - var/use_blood_colour = species?.get_blood_colour(owner) ? species.get_blood_colour(owner) : "#C80000" + var/use_flesh_colour = data.get_species_flesh_colour(owner) + var/use_blood_colour = data.get_species_blood_colour(owner) removed(null, ignore_children) victim?.traumatic_shock += 60 @@ -1013,10 +1012,9 @@ Note that amputating the affected organ does in fact remove the infection from t gore = new /obj/effect/decal/cleanable/blood/gibs/robot(droploc) else gore = new /obj/effect/decal/cleanable/blood/gibs(droploc) - if(species) - gore.fleshcolor = use_flesh_colour - gore.basecolor = use_blood_colour - gore.update_icon() + gore.fleshcolor = use_flesh_colour + gore.basecolor = use_blood_colour + gore.update_icon() gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) @@ -1205,7 +1203,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(company) model = company var/datum/robolimb/R = all_robolimbs[company] - if(!R || (species && (species.name in R.species_cannot_use))) + if(!R || (data.get_species_name() in R.species_cannot_use)) R = basic_robolimb if(R) force_icon = R.icon diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 95cb3624a5..d98b9c7692 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -22,7 +22,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) if(human.synth_color) s_col = list(human.r_synth, human.g_synth, human.b_synth) return - if(species && human.species && species.name != human.species.name) + if(human.species && data.get_species_name() != human.species.name) return if(!isnull(human.s_tone) && (human.species.appearance_flags & HAS_SKIN_TONE)) s_tone = human.s_tone @@ -38,11 +38,11 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) var/datum/robolimb/franchise = all_robolimbs[model] if(!(franchise && franchise.skin_tone) && !(franchise && franchise.skin_color)) return - if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.appearance_flags & HAS_SKIN_TONE)) - s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) - if(species.appearance_flags & HAS_SKIN_COLOR) - s_col = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B)) - h_col = list(dna.GetUIValue(DNA_UI_HAIR_R),dna.GetUIValue(DNA_UI_HAIR_G),dna.GetUIValue(DNA_UI_HAIR_B)) + if(!isnull(data.skin_tone) && (data.get_species_appearance_flags() & HAS_SKIN_TONE)) + s_tone = data.skin_tone + if(data.get_species_appearance_flags() & HAS_SKIN_COLOR) + s_col = data.skin_color.Copy() + h_col = data.hair_color.Copy() /obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human) ..() @@ -56,7 +56,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) //Facial hair if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (species.get_bodytype(owner) in facial_hair_style.species_allowed)) + if(facial_hair_style && facial_hair_style.species_allowed && (data.get_species_bodytype(owner) in facial_hair_style.species_allowed)) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), facial_hair_style.color_blend_mode) @@ -69,7 +69,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) if(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR)) if(!(hair_style.flags & HAIR_VERY_SHORT)) hair_style = hair_styles_list["Short Hair"] - if(hair_style && (species.get_bodytype(owner) in hair_style.species_allowed)) + if(hair_style && (data.get_species_bodytype(owner) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) @@ -89,8 +89,8 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) var/check_digi = istype(src,/obj/item/organ/external/leg) || istype(src,/obj/item/organ/external/foot) if(owner) digitigrade = check_digi && owner.digitigrade - else if(dna) - digitigrade = check_digi && dna.digitigrade + else if(data) + digitigrade = check_digi && data.digitigrade for(var/M in markings) if (!markings[M]["on"]) @@ -124,22 +124,19 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) var/should_apply_transparency = FALSE - if(!force_icon_key) - icon_cache_key = "[icon_name]_[species ? species.get_bodytype() : SPECIES_HUMAN]" //VOREStation Edit - else - icon_cache_key = "[icon_name]_[force_icon_key]" + icon_cache_key = "[icon_name]_[data.get_species_bodytype(owner)]" if(force_icon) mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]") else - if(!dna) + if(!data) mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_[gender]" : ""]") else if(!gendered_icon) gender = null else - if(dna.GetUIState(DNA_UI_GENDER)) + if(data.body_gender) gender = "f" else gender = "m" @@ -155,7 +152,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) should_apply_transparency = TRUE else //Use digi icon if digitigrade, otherwise use regular icon. Ternary operator is based. - mob_icon = new /icon(digitigrade ? species.icodigi : species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(digitigrade ? data.get_species_icodigi() : data.get_species_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") should_apply_transparency = TRUE apply_colouration(mob_icon) @@ -173,12 +170,11 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" - //if(!GLOB.limb_icon_cache[cache_key]) //ChompEDIT START - var/icon/I = icon(species.get_icobase(owner), "[icon_name]_[body_hair]") - I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit - mob_icon.Blend(I, ICON_OVERLAY) - GLOB.limb_icon_cache[cache_key] = I - //ChompEDIT END + if(!GLOB.limb_icon_cache[cache_key]) + var/icon/I = icon(data.get_species_icobase(owner), "[icon_name]_[body_hair]") + I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit + GLOB.limb_icon_cache[cache_key] = I + mob_icon.Blend(GLOB.limb_icon_cache[cache_key], ICON_OVERLAY) // VOREStation edit start if(nail_polish) @@ -206,12 +202,11 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" - //if(!GLOB.limb_icon_cache[cache_key]) //ChompEDIT START - var/icon/I = icon(species.get_icobase(owner), "[icon_name]_[body_hair]") - I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit - mob_icon.Blend(I, ICON_OVERLAY) - GLOB.limb_icon_cache[cache_key] = I - //ChompEDIT END + if(!GLOB.limb_icon_cache[cache_key]) + var/icon/I = icon(data.get_species_icobase(owner), "[icon_name]_[body_hair]") + I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit + GLOB.limb_icon_cache[cache_key] = I + mob_icon.Blend(GLOB.limb_icon_cache[cache_key], ICON_OVERLAY) // VOREStation edit ends here if (transparent && !istype(src,/obj/item/organ/external/head) && can_apply_transparency && should_apply_transparency) //VORESTATION EDIT: transparent instead of nonsolid @@ -223,12 +218,9 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) /obj/item/organ/external/proc/apply_colouration(var/icon/applying) - if(transparent) //VOREStation edit + if(transparent) applying.MapColors("#4D4D4D","#969696","#1C1C1C", "#000000") - if(species && species.get_bodytype(owner) != SPECIES_HUMAN) - applying.SetIntensity(1) // Unathi, Taj and Skrell have -very- dark base icons. VOREStation edit fixes this and brings the number back to 1 - else - applying.SetIntensity(1) //VOREStation edit to make Prometheans not look like shit with mob coloring. + applying.SetIntensity(1) else if(status & ORGAN_DEAD) icon_cache_key += "_dead" @@ -242,14 +234,12 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) applying.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) icon_cache_key += "_tone_[s_tone]" else if(s_col && s_col.len >= 3) - //VOREStation Edit - Support for species.color_mult - if(species && species.color_mult) + if(data.get_species_color_mult()) applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_MULTIPLY) icon_cache_key += "_color_[s_col[1]]_[s_col[2]]_[s_col[3]]_[ICON_MULTIPLY]" else applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) icon_cache_key += "_color_[s_col[1]]_[s_col[2]]_[s_col[3]]_[ICON_ADD]" - //VOREStation Edit End return applying @@ -280,14 +270,15 @@ var/list/robot_hud_colours = list("#CFCFCF","#AFAFAF","#8F8F8F","#6F6F6F","#4F4F // This looks convoluted, but it's this way to avoid icon proc calls. if(!hud_damage_image) var/cache_key = "dambase-[icon_cache_key]" - if(!icon_cache_key || !GLOB.limb_icon_cache[cache_key]) //CHOMPNote - this isn't manipulated after the fact, so we leave it. - GLOB.limb_icon_cache[cache_key] = icon(get_icon(), null, SOUTH) //ChompEDIT - var/image/temp = image(GLOB.limb_icon_cache[cache_key]) //ChompEDIT - if((robotic < ORGAN_ROBOT) && species) + if(!icon_cache_key || !GLOB.limb_icon_cache[cache_key]) + GLOB.limb_icon_cache[cache_key] = icon(get_icon(), null, SOUTH) + var/image/temp = image(GLOB.limb_icon_cache[cache_key]) + if((robotic < ORGAN_ROBOT)) // Calculate the required colour matrix. - var/r = 0.30 * species.health_hud_intensity - var/g = 0.59 * species.health_hud_intensity - var/b = 0.11 * species.health_hud_intensity + var/int = data.get_species_health_hud_intensity() + var/r = 0.30 * int + var/g = 0.59 * int + var/b = 0.11 * int temp.color = list(r, r, r, g, g, g, b, b, b) else if(model) var/datum/robolimb/R = all_robolimbs[model] diff --git a/code/modules/organs/subtypes/seromi.dm b/code/modules/organs/subtypes/seromi.dm deleted file mode 100644 index 97d34f5d43..0000000000 --- a/code/modules/organs/subtypes/seromi.dm +++ /dev/null @@ -1,8 +0,0 @@ -/obj/item/organ/external/foot/seromi - //body_hair = "feathers" //TESHARI TEMPORARY REMOVAL -/obj/item/organ/external/foot/right/seromi - //body_hair = "feathers" //TESHARI TEMPORARY REMOVAL -/obj/item/organ/external/hand/seromi - //body_hair = "feathers" //TESHARI TEMPORARY REMOVAL -/obj/item/organ/external/hand/right/seromi - //body_hair = "feathers" //TESHARI TEMPORARY REMOVAL diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 49c749ebec..6f4cf9d070 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -389,7 +389,7 @@ icon_cache_key += "[eye_icon]" //Lip color/icon - if(owner.lip_style && (species && (species.appearance_flags & HAS_LIPS))) + if(owner.lip_style && (data.get_species_appearance_flags() & HAS_LIPS)) var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") add_overlay(lip_icon) mob_icon.Blend(lip_icon, ICON_OVERLAY) diff --git a/code/modules/organs/subtypes/xenos.dm b/code/modules/organs/subtypes/xenos.dm index c9746d1f76..4ddeb32ba0 100644 --- a/code/modules/organs/subtypes/xenos.dm +++ b/code/modules/organs/subtypes/xenos.dm @@ -155,72 +155,61 @@ /obj/item/organ/external/chest/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 - thick_skin = TRUE /obj/item/organ/external/groin/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 encased = TRUE - thick_skin = TRUE /obj/item/organ/external/arm/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/arm/right/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/leg/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/leg/right/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/foot/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/foot/right/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/hand/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/hand/right/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 stapled_nerves = TRUE encased = TRUE - thick_skin = TRUE /obj/item/organ/external/head/unseverable/xeno cannot_gib = 1 cannot_amputate = 1 - thick_skin = TRUE eye_icon = "blank_eyes" diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm index 11e0235cdc..7d51164e4f 100644 --- a/code/modules/research/prosfab_designs.dm +++ b/code/modules/research/prosfab_designs.dm @@ -21,15 +21,12 @@ manf = manf.species_alternates[prosfab.species] if(!prosfab.species || (prosfab.species in manf.species_cannot_use)) // Fabricator ensures the manufacturer can make parts for the species we're set to. - O.species = GLOB.all_species["[manf.suggested_species]"] + O.data.setup_from_species(GLOB.all_species["[manf.suggested_species]"]) else - O.species = GLOB.all_species[prosfab.species] + O.data.setup_from_species(GLOB.all_species[prosfab.species]) else - O.species = GLOB.all_species["Human"] + O.data.setup_from_species(GLOB.all_species["Human"]) O.robotize(prosfab.manufacturer) - qdel_swap(O.dna, new/datum/dna()) //Uuughhhh... why do I have to do this? - O.dna.ResetUI() - O.dna.ResetSE() return O return ..() @@ -60,15 +57,13 @@ EO.remove_rejuv() for(var/obj/item/organ/external/O in H.organs) - O.species = GLOB.all_species[newspecies] + O.data.setup_from_species(GLOB.all_species[newspecies]) if(!(O.organ_tag in manf.parts)) // Make sure we're using an actually present icon. manf = all_robolimbs["Unbranded"] O.robotize(manf.company) - qdel_swap(O.dna, new/datum/dna()) - O.dna.ResetUI() - O.dna.ResetSE() + O.data.setup_from_dna() // Skincolor weirdness. O.s_col[1] = 255 // CHOMP Edit diff --git a/modular_chomp/code/modules/organs/organ_icon.dm b/modular_chomp/code/modules/organs/organ_icon.dm index aa97c3d657..0f7207e9ac 100644 --- a/modular_chomp/code/modules/organs/organ_icon.dm +++ b/modular_chomp/code/modules/organs/organ_icon.dm @@ -8,8 +8,8 @@ var/check_digi = istype(src,/obj/item/organ/external/leg) || istype(src,/obj/item/organ/external/foot) if(owner) digitigrade = check_digi && owner.digitigrade - else if(dna) - digitigrade = check_digi && dna.digitigrade + else if(data) + digitigrade = check_digi && data.digitigrade var/should_apply_transparency = FALSE @@ -18,22 +18,19 @@ if(owner && owner.gender == FEMALE) gender = "f" - if(!force_icon_key) - icon_cache_key = "[icon_name]_[species ? species.get_bodytype() : SPECIES_HUMAN]" //VOREStation Edit - else - icon_cache_key = "[icon_name]_[force_icon_key]" + icon_cache_key = "[icon_name]_[data.get_species_bodytype(owner)]" if(force_icon && !skip_forced_icon) mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]") else - if(!dna) + if(!data) mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_[gender]" : ""]") else if(!gendered_icon) gender = null else - if(dna.GetUIState(DNA_UI_GENDER)) + if(data.body_gender) gender = "f" else gender = "m" @@ -50,7 +47,7 @@ should_apply_transparency = TRUE else //Use digi icon if digitigrade, otherwise use regular icon. Ternary operator is based. - mob_icon = new /icon(digitigrade ? species.icodigi : species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(digitigrade ? data.get_species_icodigi() : data.get_species_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") should_apply_transparency = TRUE apply_colouration(mob_icon) @@ -77,12 +74,11 @@ icon_cache_key += "[M][markings[M]["color"]]" if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" - //if(!GLOB.limb_icon_cache[cache_key]) //icon cache tweak start - var/icon/I = icon(species.get_icobase(owner), "[icon_name]_[body_hair]") - I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit - mob_icon.Blend(I, ICON_OVERLAY) - GLOB.limb_icon_cache[cache_key] = I - //icon cache tweak end + if(!GLOB.limb_icon_cache[cache_key]) + var/icon/I = icon(data.get_species_icobase(owner), "[icon_name]_[body_hair]") + I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit + GLOB.limb_icon_cache[cache_key] = I + mob_icon.Blend(GLOB.limb_icon_cache[cache_key], ICON_OVERLAY) // VOREStation edit start if(nail_polish && !(force_icon && !skip_forced_icon)) diff --git a/vorestation.dme b/vorestation.dme index 721163dca1..823e3a73b2 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -3869,6 +3869,7 @@ #include "code\modules\nifsoft\software\14_commlink.dm" #include "code\modules\nifsoft\software\15_misc.dm" #include "code\modules\organs\blood.dm" +#include "code\modules\organs\data.dm" #include "code\modules\organs\misc.dm" #include "code\modules\organs\organ.dm" #include "code\modules\organs\organ_external.dm"