From 1089da7fb13c53d8ea98befb6bf5d7ca5ac47168 Mon Sep 17 00:00:00 2001 From: Chinsky Date: Wed, 20 May 2015 02:59:19 +0300 Subject: [PATCH] Frankenstein edition: Limbs now store their own dna/species info. This allows transplanted limbs show up as they are, instead of conforming to mob. Vox-cat-monkey hybrids, rainbow skrells, go wild. Also changed rejection to cause infection instead of straight up organ damage - wouldn't want your newly acquired catpaws fracture out of blue. As a bonus, attacks are tracked per limb, so for example having kitty claws will give you the corresponding attack --- .../mob/living/carbon/human/appearance.dm | 2 + .../living/carbon/human/human_attackhand.dm | 7 +++- .../mob/living/carbon/human/update_icons.dm | 39 ++++++++++--------- code/modules/organs/organ.dm | 31 +++++++++------ code/modules/organs/organ_icon.dm | 34 ++++++++++------ code/modules/organs/robolimbs.dm | 1 + 6 files changed, 72 insertions(+), 42 deletions(-) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 52ba116d43..5f9527b93b 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -118,6 +118,7 @@ b_skin = blue force_update_limbs() + update_body() return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) @@ -127,6 +128,7 @@ s_tone = tone force_update_limbs() + update_body() return 1 /mob/living/carbon/human/proc/update_dna() diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 0deb593c84..3187ac7e02 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -176,8 +176,13 @@ miss_type = 2 // See what attack they use + var/possible_moves = list() var/datum/unarmed_attack/attack = null - for(var/datum/unarmed_attack/u_attack in H.species.unarmed_attacks) + for(var/part in list("l_hand","r_hand","l_foot","r_foot","head")) + var/obj/item/organ/external/E = H.get_organ(part) + possible_moves |= E.species.unarmed_attacks + + for(var/datum/unarmed_attack/u_attack in possible_moves) if(!u_attack.is_usable(H, src, hit_zone)) continue else diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 382ff909b3..8b13178adf 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -234,15 +234,13 @@ var/global/list/damage_icon_parts = list() var/hulk = (HULK in src.mutations) var/skeleton = (SKELETON in src.mutations) - var/g = (gender == FEMALE ? "f" : "m") - //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. //Create a new, blank icon for our mob to use. if(stand_icon) qdel(stand_icon) stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") - var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]" + var/icon_key = "" var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"] if(eyes) @@ -260,7 +258,12 @@ var/global/list/damage_icon_parts = list() icon_key += "3" else icon_key += "1" - + if(part) + icon_key += "[part.species.race_key]" + icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" + icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" + if(part.s_col) + icon_key += "[rgb(part.s_col[1],part.s_col[2],part.s_col[3])]" icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" var/icon/base_icon @@ -894,22 +897,22 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/proc/get_tail_icon() var/icon_key = "[species.race_key][r_skin][g_skin][b_skin]" - + var/icon/tail_icon = tail_icon_cache[icon_key] - if(!tail_icon) - + if(!tail_icon) + //generate a new one tail_icon = new/icon(icon = (species.tail_animation? species.tail_animation : 'icons/effects/species.dmi')) tail_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - + tail_icon_cache[icon_key] = tail_icon - + return tail_icon /mob/living/carbon/human/proc/set_tail_state(var/t_state) var/image/tail_overlay = overlays_standing[TAIL_LAYER] - + if(tail_overlay && species.tail_animation) tail_overlay.icon_state = t_state return tail_overlay @@ -919,30 +922,30 @@ var/global/list/damage_icon_parts = list() //Update this if the ability to flick() images or make looping animation start at the first frame is ever added. /mob/living/carbon/human/proc/animate_tail_once(var/update_icons=1) var/t_state = "[species.tail]_once" - + var/image/tail_overlay = overlays_standing[TAIL_LAYER] if(tail_overlay && tail_overlay.icon_state == t_state) return //let the existing animation finish - + tail_overlay = set_tail_state(t_state) if(tail_overlay) spawn(15) //check that the animation hasn't changed in the meantime if(overlays_standing[TAIL_LAYER] == tail_overlay && tail_overlay.icon_state == t_state) animate_tail_stop() - + if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_start(var/update_icons=1) set_tail_state("[species.tail]_slow[rand(0,9)]") - + if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_fast(var/update_icons=1) set_tail_state("[species.tail]_loop[rand(0,9)]") - + if(update_icons) update_icons() @@ -951,14 +954,14 @@ var/global/list/damage_icon_parts = list() set_tail_state("[species.tail]_idle[rand(0,9)]") else set_tail_state("[species.tail]_static") - - + + if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1) set_tail_state("[species.tail]_static") - + if(update_icons) update_icons() diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 0e4e9e35a8..9d40b8d650 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -23,6 +23,8 @@ var/list/organ_cache = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, // links chemical IDs to number of ticks for which they'll stay in the blood germ_level = 0 + var/datum/dna/dna + var/datum/species/species /obj/item/organ/proc/update_health() return @@ -34,6 +36,12 @@ var/list/organ_cache = list() max_damage = min_broken_damage * 2 if(istype(holder)) src.owner = holder + species = all_species["Human"] + if(holder.dna) + dna = holder.dna.Clone() + species = all_species[dna.species] + else + log_debug("[src] at [loc] spawned without a proper DNA.") var/mob/living/carbon/human/H = holder if(istype(H)) if(internal) @@ -42,10 +50,10 @@ var/list/organ_cache = list() if(E.internal_organs == null) E.internal_organs = list() E.internal_organs |= src - if(H.dna) + if(dna) if(!blood_DNA) blood_DNA = list() - blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + blood_DNA[dna.unique_enzymes] = dna.b_type if(internal) holder.internal_organs |= src @@ -123,24 +131,23 @@ 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(transplant_data) - if(!rejecting && prob(20) && owner.dna && blood_incompatible(transplant_data["blood_type"],owner.dna.b_type,owner.species,transplant_data["species"])) - rejecting = 1 + if(dna) + if(!rejecting) + if(blood_incompatible(dna.b_type, owner.dna.b_type, species, owner.species)) + rejecting = 1 else rejecting++ //Rejection severity increases over time. if(rejecting % 10 == 0) //Only fire every ten rejection ticks. switch(rejecting) if(1 to 50) - take_damage(1) + germ_level++ if(51 to 200) - owner.reagents.add_reagent("toxin", 1) - take_damage(1) + germ_level += rand(1,2) if(201 to 500) - take_damage(rand(2,3)) - owner.reagents.add_reagent("toxin", 2) + germ_level += rand(2,3) if(501 to INFINITY) - take_damage(4) - owner.reagents.add_reagent("toxin", rand(3,5)) + germ_level += rand(3,5) + owner.reagents.add_reagent("toxin", rand(1,2)) /obj/item/organ/proc/receive_chem(chemical as obj) return 0 diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 7036e7e725..d25ce2f5a2 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -17,11 +17,23 @@ var/global/list/limb_icon_cache = list() s_col = null if(status & ORGAN_ROBOT) return + if(species && human.species && species.name != human.species.name) + return if(!isnull(human.s_tone) && (human.species.flags & HAS_SKIN_TONE)) s_tone = human.s_tone if(human.species.flags & HAS_SKIN_COLOR) s_col = list(human.r_skin, human.g_skin, human.b_skin) +/obj/item/organ/external/proc/sync_colour_to_dna() + s_tone = null + s_col = null + if(status & ORGAN_ROBOT) + return + if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.flags & HAS_SKIN_TONE)) + s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) + if(species.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)) + /obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human) ..() var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] @@ -35,10 +47,10 @@ var/global/list/limb_icon_cache = list() ..() overlays.Cut() - if(owner.species.has_organ["eyes"]) + if(species.has_organ["eyes"]) var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] - if(owner.species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', owner.species.eyes) + if(species.eyes) + var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) if(eyes) eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD) else @@ -46,14 +58,14 @@ var/global/list/limb_icon_cache = list() mob_icon.Blend(eyes_icon, ICON_OVERLAY) overlays |= eyes_icon - if(owner.lip_style && (owner.species && (owner.species.flags & HAS_LIPS))) + if(owner.lip_style && (species && (species.flags & HAS_LIPS))) var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) 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 && (owner.species.name in facial_hair_style.species_allowed)) + if(facial_hair_style && facial_hair_style.species_allowed && (species.name 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), ICON_ADD) @@ -61,7 +73,7 @@ var/global/list/limb_icon_cache = list() if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && (owner.species.name in hair_style.species_allowed)) + if(hair_style && (species.name in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration) hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD) @@ -75,25 +87,25 @@ var/global/list/limb_icon_cache = list() if(force_icon) mob_icon = new /icon(force_icon, "[icon_name]") else - if(!owner) + if(!dna) mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]") else if(gendered_icon) - if(owner.gender == FEMALE) + if(dna.GetUIState(DNA_UI_GENDER)) gender = "f" else gender = "m" if(skeletal) mob_icon = new /icon('icons/mob/human_races/r_skeleton.dmi', "[icon_name][gender ? "_[gender]" : ""]") - else if ((status & ORGAN_ROBOT) && !(owner.species && owner.species.flags & IS_SYNTHETIC)) + else if ((status & ORGAN_ROBOT) && !(species && species.flags & IS_SYNTHETIC)) mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]") else if (status & ORGAN_MUTATED) - mob_icon = new /icon(owner.species.deform, "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(species.deform, "[icon_name][gender ? "_[gender]" : ""]") else - mob_icon = new /icon(owner.species.icobase, "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(species.icobase, "[icon_name][gender ? "_[gender]" : ""]") if(status & ORGAN_DEAD) mob_icon.ColorTone(rgb(10,50,0)) diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 8d19d60b49..bb2d571f5d 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -7,6 +7,7 @@ var/global/datum/robolimb/basic_robolimb for(var/limb_type in typesof(/datum/robolimb)) var/datum/robolimb/R = new limb_type() all_robolimbs[R.company] = R + world << "Adding [R.company] as [R], [R.type]" if(!R.unavailable_at_chargen) chargen_robolimbs[R.company] = R