diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 6c41355d398..ceb9c873dfd 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -561,6 +561,16 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /mob/living/carbon/has_dna() return dna +/// Returns TRUE if the mob is allowed to mutate via its DNA, or FALSE if otherwise. +/// Only an organic Carbon with valid DNA may mutate; not robots, AIs, aliens, Ians, or other mobs. +/mob/proc/can_mutate() + return FALSE + +/mob/living/carbon/can_mutate() + if(!(mob_biotypes & MOB_ORGANIC)) + return FALSE + if(has_dna() && !HAS_TRAIT(src, TRAIT_GENELESS) && !HAS_TRAIT(src, TRAIT_BADDNA)) + return TRUE /// Sets the DNA of the mob to the given DNA. /mob/living/carbon/human/proc/hardset_dna(unique_identity, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations) diff --git a/code/datums/elements/organ_set_bonus.dm b/code/datums/elements/organ_set_bonus.dm index fb90c3f4640..290e9865798 100644 --- a/code/datums/elements/organ_set_bonus.dm +++ b/code/datums/elements/organ_set_bonus.dm @@ -6,17 +6,15 @@ /datum/element/organ_set_bonus element_flags = ELEMENT_BESPOKE argument_hash_start_idx = 2 - ///status effect type to apply/update! - var/bonus_type + /// Status Effect typepath to instantiate and apply to the mob. + var/datum/status_effect/organ_set_bonus/bonus_type /datum/element/organ_set_bonus/Attach(datum/target, bonus_type) . = ..() if(!isorgan(target)) return ELEMENT_INCOMPATIBLE - src.bonus_type = bonus_type - RegisterSignal(target, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_implanted)) RegisterSignal(target, COMSIG_ORGAN_REMOVED, PROC_REF(on_removed)) @@ -50,11 +48,15 @@ ///how many organs the carbon with this has in the set var/organs = 0 ///how many organs in the set you need to enable the bonus - var/organs_needed = 5 + var/organs_needed = 0 ///if the bonus is active var/bonus_active = FALSE var/bonus_activate_text = span_notice("??? DNA is deeply infused with you! You've learned how to make error reports!") var/bonus_deactivate_text = span_notice("Your DNA is no longer majority ???. You did make an issue report, right?") + /// Required mob bio-type. Also checks DNA validity it's set to MOB_ORGANIC. + var/required_biotype = MOB_ORGANIC + /// A Trait or list of Traits added to the mob upon bonus activation. + var/bonus_traits /datum/status_effect/organ_set_bonus/proc/set_organs(new_value) organs = new_value @@ -62,18 +64,36 @@ qdel(src) if(organs >= organs_needed) if(!bonus_active) - enable_bonus() + INVOKE_ASYNC(src, PROC_REF(enable_bonus)) else if(bonus_active) - disable_bonus() + INVOKE_ASYNC(src, PROC_REF(disable_bonus)) /datum/status_effect/organ_set_bonus/proc/enable_bonus() SHOULD_CALL_PARENT(TRUE) + if(required_biotype) + if(!(owner.mob_biotypes & required_biotype)) + return FALSE + if((required_biotype == MOB_ORGANIC) && !owner.can_mutate()) + return FALSE bonus_active = TRUE + if(bonus_traits) + if(islist(bonus_traits)) + for(var/trait in bonus_traits) + ADD_TRAIT(owner, trait, REF(src)) + else + ADD_TRAIT(owner, bonus_traits, REF(src)) if(bonus_activate_text) to_chat(owner, bonus_activate_text) + return TRUE /datum/status_effect/organ_set_bonus/proc/disable_bonus() SHOULD_CALL_PARENT(TRUE) bonus_active = FALSE + if(bonus_traits) + if(islist(bonus_traits)) + for(var/trait in bonus_traits) + REMOVE_TRAIT(owner, trait, REF(src)) + else + REMOVE_TRAIT(owner, bonus_traits, REF(src)) if(bonus_deactivate_text) to_chat(owner, bonus_deactivate_text) diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index b47b1bff7b4..4736ff0f490 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -38,7 +38,7 @@ return var/mob/living/carbon/human/H = L - if(!H.dna || HAS_TRAIT(H, TRAIT_GENELESS) || H.status_flags & GODMODE) + if(!H.can_mutate() || H.status_flags & GODMODE) return if(HAS_TRAIT(H, TRAIT_RADIMMUNE)) diff --git a/code/game/machinery/dna_infuser/dna_infuser.dm b/code/game/machinery/dna_infuser/dna_infuser.dm index 05be920a49d..3c1f5d74e30 100644 --- a/code/game/machinery/dna_infuser/dna_infuser.dm +++ b/code/game/machinery/dna_infuser/dna_infuser.dm @@ -127,11 +127,13 @@ // TODO: In the future, this should have more logic: // - Replace non-mutant organs before mutant ones. /obj/machinery/dna_infuser/proc/infuse_organ(mob/living/carbon/human/target) - if(!ishuman(target) || !infusing_into) + if(!ishuman(target)) return FALSE var/obj/item/organ/new_organ = pick_organ(target) if(!new_organ) return FALSE + // Valid organ successfully picked. + new_organ = new new_organ() if(!istype(new_organ, /obj/item/organ/internal/brain)) // Organ ISN'T brain, insert normally. new_organ.Insert(target, special = TRUE, drop_if_replaced = FALSE) @@ -148,14 +150,17 @@ return TRUE /// Picks a random mutated organ from the infuser entry which is also compatible with the target mob. -/// Tries to return a valid mutant organ if all of the following criteria are true: +/// Tries to return a typepath of a valid mutant organ if all of the following criteria are true: /// 1. Target must have a pre-existing organ in the same organ slot as the new organ; /// - or the new organ must be external. /// 2. Target's pre-existing organ must be organic / not robotic. /// 3. Target must not have the same/identical organ. /obj/machinery/dna_infuser/proc/pick_organ(mob/living/carbon/human/target) + if(!infusing_into) + return FALSE var/list/obj/item/organ/potential_new_organs = infusing_into.output_organs.Copy() - for(var/obj/item/organ/new_organ in infusing_into.output_organs) + // Remove organ typepaths from the list if they're incompatible with target. + for(var/obj/item/organ/new_organ as anything in infusing_into.output_organs) var/obj/item/organ/old_organ = target.getorganslot(initial(new_organ.slot)) if(old_organ) if((old_organ.type != new_organ) && (old_organ.status != ORGAN_ROBOTIC)) @@ -262,14 +267,14 @@ /// Verify that the occupant/target is organic, and has mutable DNA. /obj/machinery/dna_infuser/proc/is_valid_occupant(mob/living/carbon/human/human_target, mob/user) - // Invalid: Occupant isn't Human, isn't organic, lacks DNA / has TRAIT_GENELESS. - if(!ishuman(human_target) || !(human_target.mob_biotypes & MOB_ORGANIC) || !human_target.has_dna() || HAS_TRAIT(human_target, TRAIT_GENELESS)) - balloon_alert(user, "dna is missing!") - return FALSE // Invalid: DNA is too damaged to mutate anymore / has TRAIT_BADDNA. if(HAS_TRAIT(human_target, TRAIT_BADDNA)) balloon_alert(user, "dna is corrupted!") return FALSE + // Invalid: Occupant isn't Human, isn't organic, lacks DNA / has TRAIT_GENELESS. + if(!ishuman(human_target) || !human_target.can_mutate()) + balloon_alert(user, "dna is missing!") + return FALSE // Valid: Occupant is an organic Human who has undamaged and mutable DNA. return TRUE diff --git a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm index 3cc4fca59e6..0835ce5aa09 100644 --- a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm @@ -1,23 +1,15 @@ - #define CARP_ORGAN_COLOR "#4caee7" #define CARP_SCLERA_COLOR "#ffffff" #define CARP_PUPIL_COLOR "#00b1b1" - #define CARP_COLORS CARP_ORGAN_COLOR + CARP_SCLERA_COLOR + CARP_PUPIL_COLOR ///bonus of the carp: you can swim through space! /datum/status_effect/organ_set_bonus/carp + id = "organ_set_bonus_carp" organs_needed = 4 bonus_activate_text = span_notice("Carp DNA is deeply infused with you! You've learned how to propel yourself through space!") bonus_deactivate_text = span_notice("Your DNA is once again mostly yours, and so fades your ability to space-swim...") - -/datum/status_effect/organ_set_bonus/carp/enable_bonus() - . = ..() - ADD_TRAIT(owner, TRAIT_SPACEWALK, REF(src)) - -/datum/status_effect/organ_set_bonus/carp/disable_bonus() - . = ..() - REMOVE_TRAIT(owner, TRAIT_SPACEWALK, REF(src)) + bonus_traits = TRAIT_SPACEWALK ///Carp lungs! You can breathe in space! Oh... you can't breathe on the station, you need low oxygen environments. /// Inverts behavior of lungs. Bypasses suffocation due to space / lack of gas, but also allows Oxygen to suffocate. @@ -61,6 +53,8 @@ if(!ishuman(tongue_owner)) return var/mob/living/carbon/human/human_receiver = tongue_owner + if(!human_receiver.can_mutate()) + return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(tongue_owner, rec_species.no_equip_flags | ITEM_SLOT_MASK) var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) @@ -73,6 +67,8 @@ if(!ishuman(tongue_owner)) return var/mob/living/carbon/human/human_receiver = tongue_owner + if(!human_receiver.can_mutate()) + return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(tongue_owner, initial(rec_species.no_equip_flags)) var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) @@ -112,10 +108,7 @@ /obj/item/organ/internal/brain/carp/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) - -/obj/item/organ/internal/brain/carp/Insert(mob/living/carbon/reciever, special, drop_if_replaced, no_id_transfer) - AddElement(/datum/element/noticable_organ, "seem[reciever.p_s()] unable to stay still.") - return ..() + AddElement(/datum/element/noticable_organ, "seem%PRONOUN_S unable to stay still.") /obj/item/organ/internal/brain/carp/Insert(mob/living/carbon/brain_owner, special, drop_if_replaced, no_id_transfer) . = ..() @@ -125,7 +118,7 @@ //technically you could get around the mood issue by extracting and reimplanting the brain but it will be far easier to just go one z there and back /obj/item/organ/internal/brain/carp/Remove(mob/living/carbon/brain_owner, special, no_id_transfer) . = ..() - UnregisterSignal(brain_owner) + UnregisterSignal(brain_owner, COMSIG_MOVABLE_Z_CHANGED) deltimer(cooldown_timer) /obj/item/organ/internal/brain/carp/get_attacking_limb(mob/living/carbon/human/target) @@ -153,14 +146,10 @@ /obj/item/organ/internal/heart/carp/Initialize(mapload) . = ..() + AddElement(/datum/element/noticable_organ, "skin has small patches of scales growing on it.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) -/obj/item/organ/internal/heart/carp/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) - AddElement(/datum/element/noticable_organ, "[reciever.p_have()] small patches of scales growing on [reciever.p_their()] skin...") - return ..() - #undef CARP_ORGAN_COLOR #undef CARP_SCLERA_COLOR #undef CARP_PUPIL_COLOR - #undef CARP_COLORS diff --git a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm index e05e479524c..71bb89fdad4 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm @@ -1,5 +1,9 @@ +#define FLY_INFUSED_ORGAN_DESC "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." +#define FLY_INFUSED_ORGAN_ICON pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + ///bonus of the fly: you... are a flyperson now. sorry. /datum/status_effect/organ_set_bonus/fly + id = "organ_set_bonus_fly" organs_needed = 4 //there are actually 7 fly organs that count, but you only need 4 to go full-flyperson. Be careful! bonus_activate_text = null bonus_deactivate_text = null @@ -64,12 +68,12 @@ return ..() + /datum/language/buzzwords /obj/item/organ/internal/heart/fly - desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." + desc = FLY_INFUSED_ORGAN_DESC /obj/item/organ/internal/heart/fly/Initialize(mapload) . = ..() name = odd_organ_name() - icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + icon_state = FLY_INFUSED_ORGAN_ICON AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly) /obj/item/organ/internal/heart/fly/update_icon_state() @@ -77,31 +81,31 @@ return //don't set icon thank you /obj/item/organ/internal/lungs/fly - desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." + desc = FLY_INFUSED_ORGAN_DESC /obj/item/organ/internal/lungs/fly/Initialize(mapload) . = ..() name = odd_organ_name() - icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + icon_state = FLY_INFUSED_ORGAN_ICON AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly) /obj/item/organ/internal/liver/fly - desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." + desc = FLY_INFUSED_ORGAN_DESC alcohol_tolerance = 0.007 //flies eat vomit, so a lower alcohol tolerance is perfect! /obj/item/organ/internal/liver/fly/Initialize(mapload) . = ..() name = odd_organ_name() - icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + icon_state = FLY_INFUSED_ORGAN_ICON AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly) /obj/item/organ/internal/stomach/fly - desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." + desc = FLY_INFUSED_ORGAN_DESC /obj/item/organ/internal/stomach/fly/Initialize(mapload) . = ..() name = odd_organ_name() - icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + icon_state = FLY_INFUSED_ORGAN_ICON AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly) /obj/item/organ/internal/stomach/fly/after_eat(edible) @@ -117,28 +121,29 @@ return ..() /obj/item/organ/internal/appendix/fly - desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." + desc = FLY_INFUSED_ORGAN_DESC /obj/item/organ/internal/appendix/fly/Initialize(mapload) . = ..() name = odd_organ_name() - icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + icon_state = FLY_INFUSED_ORGAN_ICON AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly) /obj/item/organ/internal/appendix/fly/update_appearance(updates=ALL) return ..(updates & ~(UPDATE_NAME|UPDATE_ICON)) //don't set name or icon thank you - - //useless organs we throw in just to fuck with surgeons a bit more. they aren't part of a bonus, just the (absolute) state of flies /obj/item/organ/internal/fly - desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity." + desc = FLY_INFUSED_ORGAN_DESC visual = FALSE /obj/item/organ/internal/fly/Initialize(mapload) . = ..() name = odd_organ_name() - icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "spinner-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5") + icon_state = FLY_INFUSED_ORGAN_ICON /obj/item/organ/internal/fly/groin //appendix is the only groin organ so we gotta have one of these too lol zone = BODY_ZONE_PRECISE_GROIN + +#undef FLY_INFUSED_ORGAN_DESC +#undef FLY_INFUSED_ORGAN_ICON diff --git a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm index 04c48cfe9ac..0c7f482422c 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm @@ -1,4 +1,3 @@ - /obj/item/organ/internal/ears/fox name = "fox ears" icon = 'icons/obj/clothing/head/costume.dmi' @@ -10,16 +9,16 @@ //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION /* /obj/item/organ/internal/ears/fox/Insert(mob/living/carbon/human/ear_owner, special = 0, drop_if_replaced = TRUE) - ..() - if(istype(ear_owner)) + . = ..() + if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color ear_owner.dna.features["ears"] = ear_owner.dna.species.mutant_bodyparts["ears"] = "Fox" ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) ear_owner.update_body() /obj/item/organ/internal/ears/fox/Remove(mob/living/carbon/human/ear_owner, special = 0) - ..() - if(istype(ear_owner)) + . = ..() + if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color ear_owner.dna.species.mutant_bodyparts -= "ears" ear_owner.update_body() diff --git a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm index 48dd45c7985..66283804e77 100644 --- a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm @@ -1,23 +1,15 @@ - #define GOLIATH_ORGAN_COLOR "#875652" #define GOLIATH_SCLERA_COLOR "#ac0f32" #define GOLIATH_PUPIL_COLOR "#FF0000" - #define GOLIATH_COLORS GOLIATH_ORGAN_COLOR + GOLIATH_SCLERA_COLOR + GOLIATH_PUPIL_COLOR ///bonus of the goliath: you can swim through space! /datum/status_effect/organ_set_bonus/goliath + id = "organ_set_bonus_goliath" organs_needed = 4 bonus_activate_text = span_notice("goliath DNA is deeply infused with you! You can now endure walking on lava!") bonus_deactivate_text = span_notice("You feel your muscle mass shrink and the tendrils around your skin wither. Your Goliath DNA is mostly gone and so is your ability to survive lava.") - -/datum/status_effect/organ_set_bonus/goliath/enable_bonus() - . = ..() - ADD_TRAIT(owner, TRAIT_LAVA_IMMUNE, REF(src)) - -/datum/status_effect/organ_set_bonus/goliath/disable_bonus() - . = ..() - REMOVE_TRAIT(owner, TRAIT_LAVA_IMMUNE, REF(src)) + bonus_traits = TRAIT_LAVA_IMMUNE ///goliath eyes, simple night vision /obj/item/organ/internal/eyes/night_vision/goliath @@ -42,14 +34,6 @@ AddElement(/datum/element/noticable_organ, "eyes are blood red and stone-like.", BODY_ZONE_PRECISE_EYES) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) -/obj/item/organ/internal/eyes/night_vision/goliath/Insert(mob/living/carbon/eyes_owner, special, drop_if_replaced) - . = ..() - ADD_TRAIT(eyes_owner, TRAIT_UNNATURAL_RED_GLOWY_EYES, ORGAN_TRAIT) - -/obj/item/organ/internal/eyes/night_vision/goliath/Remove(mob/living/carbon/eyes_owner, special, drop_if_replaced) - REMOVE_TRAIT(eyes_owner, TRAIT_UNNATURAL_RED_GLOWY_EYES, ORGAN_TRAIT) - return ..() - ///goliath lungs! You can breathe lavaland air mix but can't breath pure O2 from a tank anymore. /obj/item/organ/internal/lungs/lavaland/goliath name = "mutated goliath-lungs" @@ -87,9 +71,10 @@ if(!ishuman(brain_owner)) return var/mob/living/carbon/human/human_receiver = brain_owner + if(!human_receiver.can_mutate()) + return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(brain_owner, rec_species.no_equip_flags | ITEM_SLOT_GLOVES) - hammer = new/obj/item/goliath_infuser_hammer brain_owner.put_in_hands(hammer) @@ -99,12 +84,13 @@ if(!ishuman(brain_owner)) return var/mob/living/carbon/human/human_receiver = brain_owner + if(!human_receiver.can_mutate()) + return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(brain_owner, initial(rec_species.no_equip_flags)) if(hammer) brain_owner.visible_message(span_warning("\The [hammer] disintegrates!")) QDEL_NULL(hammer) - return ..() /obj/item/goliath_infuser_hammer name = "tendril hammer" @@ -172,11 +158,11 @@ /obj/item/organ/internal/heart/goliath/Initialize(mapload) . = ..() + AddElement(/datum/element/noticable_organ, "skin has visible hard plates growing from within.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) AddElement(/datum/element/update_icon_blocker) -/obj/item/organ/internal/heart/goliath/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) - AddElement(/datum/element/noticable_organ, "skin [reciever.p_have()] visible hard plates growing from within.", BODY_ZONE_CHEST) - return ..() - +#undef GOLIATH_ORGAN_COLOR +#undef GOLIATH_SCLERA_COLOR +#undef GOLIATH_PUPIL_COLOR #undef GOLIATH_COLORS diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm index c7d2db6419f..805ae2290be 100644 --- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm @@ -13,7 +13,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... organs_needed = 3 bonus_activate_text = span_notice("Gondola DNA is deeply infused with you! You are the ultimate observer, uncaring of the environment around you...") bonus_deactivate_text = span_notice("Your DNA is no longer serene and gondola-like, and so you begin remembering that breathing is like, important...") - //bonus_traits = list(TRAIT_RESISTHEAT, TRAIT_RESISTCOLD, TRAIT_NOBREATH, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE) SKYRAT EDIT REMOVE ME!!! + bonus_traits = list(TRAIT_RESISTHEAT, TRAIT_RESISTCOLD, TRAIT_NOBREATH, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE) /// makes you a pacifist and turns most mobs neutral towards you /obj/item/organ/internal/heart/gondola diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index 414ca0b1622..d107bf42534 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -1,25 +1,15 @@ - #define RAT_ORGAN_COLOR "#646464" #define RAT_SCLERA_COLOR "#f0e055" #define RAT_PUPIL_COLOR "#000000" - #define RAT_COLORS RAT_ORGAN_COLOR + RAT_SCLERA_COLOR + RAT_PUPIL_COLOR ///bonus of the rat: you can ventcrawl! /datum/status_effect/organ_set_bonus/rat + id = "organ_set_bonus_rat" organs_needed = 4 bonus_activate_text = span_notice("Rodent DNA is deeply infused with you! You've learned how to traverse ventilation!") bonus_deactivate_text = span_notice("Your DNA is no longer majority rat, and so fades your ventilation skills...") - -/datum/status_effect/organ_set_bonus/rat/enable_bonus() - . = ..() - ADD_TRAIT(owner, TRAIT_VENTCRAWLER_NUDE, REF(src)) - -/datum/status_effect/organ_set_bonus/rat/disable_bonus() - . = ..() - REMOVE_TRAIT(owner, TRAIT_VENTCRAWLER_NUDE, REF(src)) - - + bonus_traits = TRAIT_VENTCRAWLER_NUDE ///way better night vision, super sensitive. lotta things work like this, huh? /obj/item/organ/internal/eyes/night_vision/rat @@ -42,8 +32,6 @@ AddElement(/datum/element/noticable_organ, "eyes have deep, shifty black pupils, surrounded by a sickening yellow sclera.", BODY_ZONE_PRECISE_EYES) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) - - ///increases hunger, disgust recovers quicker, expands what is defined as "food" /obj/item/organ/internal/stomach/rat name = "mutated rat-stomach" @@ -54,27 +42,29 @@ icon_state = "stomach" greyscale_config = /datum/greyscale_config/mutant_organ greyscale_colors = RAT_COLORS + /// Multiplier of [physiology.hunger_mod]. + var/hunger_mod = 10 /obj/item/organ/internal/stomach/rat/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) + AddElement(/datum/element/noticable_organ, "mouth is drooling excessively.", BODY_ZONE_PRECISE_MOUTH) -/obj/item/organ/internal/stomach/rat/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) - AddElement(/datum/element/noticable_organ, "salivate[reciever.p_s()] excessively.", BODY_ZONE_HEAD) - return ..() - -/obj/item/organ/internal/stomach/rat/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/internal/stomach/rat/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() - if(!ishuman(reciever)) + if(!ishuman(receiver)) + return + var/mob/living/carbon/human/human_holder = receiver + if(!human_holder.can_mutate()) return - var/mob/living/carbon/human/human_holder = reciever var/datum/species/species = human_holder.dna.species //mmm, cheese. doesn't especially like anything else species.liked_food = DAIRY //but a rat can eat anything without issue species.disliked_food = NONE species.toxic_food = NONE - human_holder.physiology.hunger_mod *= 10 + if(human_holder.physiology) + human_holder.physiology.hunger_mod *= hunger_mod RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) /obj/item/organ/internal/stomach/rat/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) @@ -88,15 +78,16 @@ if(!ishuman(stomach_owner)) return var/mob/living/carbon/human/human_holder = stomach_owner + if(!human_holder.can_mutate()) + return var/datum/species/species = human_holder.dna.species species.liked_food = initial(species.liked_food) species.disliked_food = initial(species.disliked_food) species.toxic_food = initial(species.toxic_food) - human_holder.physiology.hunger_mod /= 10 + if(human_holder.physiology) + human_holder.physiology.hunger_mod /= hunger_mod UnregisterSignal(stomach_owner, COMSIG_SPECIES_GAIN) - - /// makes you smaller, walk over tables, and take 1.5x damage /obj/item/organ/internal/heart/rat name = "mutated rat-heart" @@ -110,29 +101,30 @@ /obj/item/organ/internal/heart/rat/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) + AddElement(/datum/element/noticable_organ, "hunch%PRONOUN_ES over unnaturally!") -/obj/item/organ/internal/heart/rat/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) - AddElement(/datum/element/noticable_organ, "hunch[owner.p_es()] over unnaturally!") - return ..() - -/obj/item/organ/internal/heart/rat/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/internal/heart/rat/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() - if(!ishuman(reciever)) + if(!ishuman(receiver)) return - var/mob/living/carbon/human/human_reciever = reciever - human_reciever.dna.add_mutation(/datum/mutation/human/dwarfism) + var/mob/living/carbon/human/human_receiver = receiver + if(!human_receiver.can_mutate()) + return + human_receiver.dna.add_mutation(/datum/mutation/human/dwarfism) //but 1.5 damage - human_reciever.physiology.damage_resistance -= 50 + if(human_receiver.physiology) + human_receiver.physiology.damage_resistance -= 50 /obj/item/organ/internal/heart/rat/Remove(mob/living/carbon/heartless, special) . = ..() if(!ishuman(heartless)) return var/mob/living/carbon/human/human_heartless = heartless + if(!human_heartless.can_mutate()) + return human_heartless.dna.remove_mutation(/datum/mutation/human/dwarfism) - human_heartless.physiology.damage_resistance += 50 - - + if(human_heartless.physiology) + human_heartless.physiology.damage_resistance += 50 /// you occasionally squeak, and have some rat related verbal tics /obj/item/organ/internal/tongue/rat @@ -148,7 +140,7 @@ /obj/item/organ/internal/tongue/rat/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "teeth are oddly shaped and yellowing", BODY_ZONE_HEAD) + AddElement(/datum/element/noticable_organ, "teeth are oddly shaped and yellowing", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) /obj/item/organ/internal/tongue/rat/modify_speech(datum/source, list/speech_args) @@ -184,5 +176,4 @@ #undef RAT_ORGAN_COLOR #undef RAT_SCLERA_COLOR #undef RAT_PUPIL_COLOR - #undef RAT_COLORS diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index a0c6f4c65bb..42ccd090483 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -41,30 +41,30 @@ return attack_hand(user, modifiers) /obj/item/dnainjector/proc/inject(mob/living/carbon/target, mob/user) - if(target.has_dna() && !HAS_TRAIT(target, TRAIT_GENELESS) && !HAS_TRAIT(target, TRAIT_BADDNA)) - for(var/removed_mutation in remove_mutations) - target.dna.remove_mutation(removed_mutation) - for(var/added_mutation in add_mutations) - if(added_mutation == /datum/mutation/human/race) - message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(target)] with the [name] [span_danger("(MONKEY)")]") - if(target.dna.mutation_in_sequence(added_mutation)) - target.dna.activate_mutation(added_mutation) - else - target.dna.add_mutation(added_mutation, MUT_EXTRA) - if(fields) - if(fields["name"] && fields["UE"] && fields["blood_type"]) - target.real_name = fields["name"] - target.dna.unique_enzymes = fields["UE"] - target.name = target.real_name - target.dna.blood_type = fields["blood_type"] - if(fields["UI"]) //UI+UE - target.dna.unique_identity = merge_text(target.dna.unique_identity, fields["UI"]) - if(fields["UF"]) - target.dna.unique_features = merge_text(target.dna.unique_features, fields["UF"]) - if(fields["UI"] || fields["UF"]) - target.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) - return TRUE - return FALSE + if(!target.can_mutate()) + return FALSE + for(var/removed_mutation in remove_mutations) + target.dna.remove_mutation(removed_mutation) + for(var/added_mutation in add_mutations) + if(added_mutation == /datum/mutation/human/race) + message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(target)] with the [name] [span_danger("(MONKEY)")]") + if(target.dna.mutation_in_sequence(added_mutation)) + target.dna.activate_mutation(added_mutation) + else + target.dna.add_mutation(added_mutation, MUT_EXTRA) + if(fields) + if(fields["name"] && fields["UE"] && fields["blood_type"]) + target.real_name = fields["name"] + target.dna.unique_enzymes = fields["UE"] + target.name = target.real_name + target.dna.blood_type = fields["blood_type"] + if(fields["UI"]) //UI+UE + target.dna.unique_identity = merge_text(target.dna.unique_identity, fields["UI"]) + if(fields["UF"]) + target.dna.unique_features = merge_text(target.dna.unique_features, fields["UF"]) + if(fields["UI"] || fields["UF"]) + target.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) + return TRUE /obj/item/dnainjector/attack(mob/target, mob/user) if(!ISADVANCEDTOOLUSER(user)) @@ -105,52 +105,50 @@ if(target.stat == DEAD) //prevents dead people from having their DNA changed to_chat(user, span_notice("You can't modify [target]'s DNA while [target.p_theyre()] dead.")) return FALSE - - if(target.has_dna() && !(HAS_TRAIT(target, TRAIT_BADDNA))) - var/endtime = world.time + duration - for(var/mutation in remove_mutations) - if(mutation == /datum/mutation/human/race) - if(!ismonkey(target)) - continue - target = target.dna.remove_mutation(mutation) - else - target.dna.remove_mutation(mutation) - for(var/mutation in add_mutations) - if(target.dna.get_mutation(mutation)) - continue //Skip permanent mutations we already have. - if(mutation == /datum/mutation/human/race && !ismonkey(target)) - message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(target)] with the [name] [span_danger("(MONKEY)")]") - target = target.dna.add_mutation(mutation, MUT_OTHER, endtime) - else - target.dna.add_mutation(mutation, MUT_OTHER, endtime) - if(fields) - if(fields["name"] && fields["UE"] && fields["blood_type"]) - if(!target.dna.previous["name"]) - target.dna.previous["name"] = target.real_name - if(!target.dna.previous["UE"]) - target.dna.previous["UE"] = target.dna.unique_enzymes - if(!target.dna.previous["blood_type"]) - target.dna.previous["blood_type"] = target.dna.blood_type - target.real_name = fields["name"] - target.dna.unique_enzymes = fields["UE"] - target.name = target.real_name - target.dna.blood_type = fields["blood_type"] - target.dna.temporary_mutations[UE_CHANGED] = endtime - if(fields["UI"]) //UI+UE - if(!target.dna.previous["UI"]) - target.dna.previous["UI"] = target.dna.unique_identity - target.dna.unique_identity = merge_text(target.dna.unique_identity, fields["UI"]) - target.dna.temporary_mutations[UI_CHANGED] = endtime - if(fields["UF"]) //UI+UE - if(!target.dna.previous["UF"]) - target.dna.previous["UF"] = target.dna.unique_features - target.dna.unique_features = merge_text(target.dna.unique_features, fields["UF"]) - target.dna.temporary_mutations[UF_CHANGED] = endtime - if(fields["UI"] || fields["UF"]) - target.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) - return TRUE - else + if(!target.can_mutate()) return FALSE + var/endtime = world.time + duration + for(var/mutation in remove_mutations) + if(mutation == /datum/mutation/human/race) + if(!ismonkey(target)) + continue + target = target.dna.remove_mutation(mutation) + else + target.dna.remove_mutation(mutation) + for(var/mutation in add_mutations) + if(target.dna.get_mutation(mutation)) + continue //Skip permanent mutations we already have. + if(mutation == /datum/mutation/human/race && !ismonkey(target)) + message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(target)] with the [name] [span_danger("(MONKEY)")]") + target = target.dna.add_mutation(mutation, MUT_OTHER, endtime) + else + target.dna.add_mutation(mutation, MUT_OTHER, endtime) + if(fields) + if(fields["name"] && fields["UE"] && fields["blood_type"]) + if(!target.dna.previous["name"]) + target.dna.previous["name"] = target.real_name + if(!target.dna.previous["UE"]) + target.dna.previous["UE"] = target.dna.unique_enzymes + if(!target.dna.previous["blood_type"]) + target.dna.previous["blood_type"] = target.dna.blood_type + target.real_name = fields["name"] + target.dna.unique_enzymes = fields["UE"] + target.name = target.real_name + target.dna.blood_type = fields["blood_type"] + target.dna.temporary_mutations[UE_CHANGED] = endtime + if(fields["UI"]) //UI+UE + if(!target.dna.previous["UI"]) + target.dna.previous["UI"] = target.dna.unique_identity + target.dna.unique_identity = merge_text(target.dna.unique_identity, fields["UI"]) + target.dna.temporary_mutations[UI_CHANGED] = endtime + if(fields["UF"]) //UI+UE + if(!target.dna.previous["UF"]) + target.dna.previous["UF"] = target.dna.unique_features + target.dna.unique_features = merge_text(target.dna.unique_features, fields["UF"]) + target.dna.temporary_mutations[UF_CHANGED] = endtime + if(fields["UI"] || fields["UF"]) + target.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) + return TRUE /obj/item/dnainjector/timed/hulk name = "\improper DNA injector (Hulk)" @@ -171,24 +169,23 @@ var/crispr_charge = FALSE // Look for viruses, look at symptoms, if research and Dormant DNA Activator or Viral Evolutionary Acceleration, set to true /obj/item/dnainjector/activator/inject(mob/living/carbon/target, mob/user) - if(target.has_dna() && !HAS_TRAIT(target, TRAIT_GENELESS) && !HAS_TRAIT(target, TRAIT_BADDNA)) - for(var/mutation in add_mutations) - var/datum/mutation/human/added_mutation = mutation - if(istype(added_mutation, /datum/mutation/human)) - mutation = added_mutation.type - if(!target.dna.activate_mutation(added_mutation)) - if(doitanyway) - target.dna.add_mutation(added_mutation, MUT_EXTRA) - else if(research && target.client) - filled = TRUE - - for(var/datum/disease/advance/disease in target.diseases) - for(var/datum/symptom/symp in disease.symptoms) - if((symp.type == /datum/symptom/genetic_mutation) || (symp.type == /datum/symptom/viralevolution)) - crispr_charge = TRUE - log_combat(user, target, "[!doitanyway ? "failed to inject" : "injected"]", "[src] ([mutation])[crispr_charge ? " with CRISPR charge" : ""]") - return TRUE - return FALSE + if(!target.can_mutate()) + return FALSE + for(var/mutation in add_mutations) + var/datum/mutation/human/added_mutation = mutation + if(istype(added_mutation, /datum/mutation/human)) + mutation = added_mutation.type + if(!target.dna.activate_mutation(added_mutation)) + if(doitanyway) + target.dna.add_mutation(added_mutation, MUT_EXTRA) + else if(research && target.client) + filled = TRUE + for(var/datum/disease/advance/disease in target.diseases) + for(var/datum/symptom/symp in disease.symptoms) + if((symp.type == /datum/symptom/genetic_mutation) || (symp.type == /datum/symptom/viralevolution)) + crispr_charge = TRUE + log_combat(user, target, "[!doitanyway ? "failed to inject" : "injected"]", "[src] ([mutation])[crispr_charge ? " with CRISPR charge" : ""]") + return TRUE /// DNA INJECTORS diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 1b9ff451c83..0f76cfd2a2a 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -52,7 +52,7 @@ /datum/reagent/toxin/mutagen/expose_mob(mob/living/carbon/exposed_mob, methods=TOUCH, reac_volume) . = ..() - if(!exposed_mob.has_dna() || HAS_TRAIT(exposed_mob, TRAIT_GENELESS) || HAS_TRAIT(exposed_mob, TRAIT_BADDNA)) + if(!exposed_mob.can_mutate()) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if(((methods & VAPOR) && prob(min(33, reac_volume))) || (methods & (INGEST|PATCH|INJECT))) exposed_mob.random_mutate_unique_identity() diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index c46134c8c3e..6252cb3ade7 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -62,34 +62,35 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /* * Insert the organ into the select mob. * - * reciever - the mob who will get our organ + * receiver - the mob who will get our organ * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment * drop_if_replaced - if there's an organ in the slot already, whether we drop it afterwards */ -/obj/item/organ/proc/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) - if(!iscarbon(reciever) || owner == reciever) +/obj/item/organ/proc/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) + if(!iscarbon(receiver) || owner == receiver) return FALSE - var/obj/item/organ/replaced = reciever.getorganslot(slot) + var/obj/item/organ/replaced = receiver.getorganslot(slot) if(replaced) - replaced.Remove(reciever, special = TRUE) + replaced.Remove(receiver, special = TRUE) if(drop_if_replaced) - replaced.forceMove(get_turf(reciever)) + replaced.forceMove(get_turf(receiver)) else qdel(replaced) - reciever.internal_organs |= src - reciever.internal_organs_slot[slot] = src + receiver.internal_organs |= src + receiver.internal_organs_slot[slot] = src + owner = receiver - SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, reciever) - SEND_SIGNAL(reciever, COMSIG_CARBON_GAIN_ORGAN, src, special) - - owner = reciever moveToNullspace() RegisterSignal(owner, COMSIG_PARENT_EXAMINE, PROC_REF(on_owner_examine)) - update_organ_traits(reciever) + update_organ_traits(receiver) for(var/datum/action/action as anything in actions) - action.Grant(reciever) + action.Grant(receiver) + + SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, receiver) + SEND_SIGNAL(receiver, COMSIG_CARBON_GAIN_ORGAN, src, special) + return TRUE /* diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index b62ff383658..2f8d88d0c14 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -71,16 +71,16 @@ //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION /* /obj/item/organ/internal/ears/cat/Insert(mob/living/carbon/human/ear_owner, special = 0, drop_if_replaced = TRUE) - ..() - if(istype(ear_owner)) + . = ..() + if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color ear_owner.dna.features["ears"] = ear_owner.dna.species.mutant_bodyparts["ears"] = "Cat" ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) ear_owner.update_body() /obj/item/organ/internal/ears/cat/Remove(mob/living/carbon/human/ear_owner, special = 0) - ..() - if(istype(ear_owner)) + . = ..() + if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color ear_owner.dna.species.mutant_bodyparts -= "ears" ear_owner.update_body() diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm index 83c0ce9f3d9..ed9f8fee155 100644 --- a/code/modules/surgery/organs/external/_external_organs.dm +++ b/code/modules/surgery/organs/external/_external_organs.dm @@ -67,8 +67,8 @@ return ..() -/obj/item/organ/external/Insert(mob/living/carbon/reciever, special, drop_if_replaced) - var/obj/item/bodypart/limb = reciever.get_bodypart(deprecise_zone(zone)) +/obj/item/organ/external/Insert(mob/living/carbon/receiver, special, drop_if_replaced) + var/obj/item/bodypart/limb = receiver.get_bodypart(deprecise_zone(zone)) if(!limb) return FALSE @@ -80,12 +80,12 @@ if(bodypart_overlay.imprint_on_next_insertion) //We only want this set *once* - // SKYRAT EDIT - Customization - ORIGINAL: bodypart_overlay.set_appearance_from_name(reciever.dna.features[bodypart_overlay.feature_key]) - if(reciever.dna.features[bodypart_overlay.feature_key]) - bodypart_overlay.set_appearance_from_name(reciever.dna.features[bodypart_overlay.feature_key]) + // SKYRAT EDIT - Customization - ORIGINAL: bodypart_overlay.set_appearance_from_name(receiver.dna.features[bodypart_overlay.feature_key]) + if(receiver.dna.features[bodypart_overlay.feature_key]) + bodypart_overlay.set_appearance_from_name(receiver.dna.features[bodypart_overlay.feature_key]) else - bodypart_overlay.set_appearance_from_dna(reciever.dna) + bodypart_overlay.set_appearance_from_dna(receiver.dna) // SKYRAT EDIT END bodypart_overlay.imprint_on_next_insertion = FALSE @@ -93,9 +93,9 @@ add_to_limb(ownerlimb) if(external_bodytypes) - limb.synchronize_bodytypes(reciever) + limb.synchronize_bodytypes(receiver) - reciever.update_body_parts() + receiver.update_body_parts() /obj/item/organ/external/Remove(mob/living/carbon/organ_owner, special, moving) . = ..() @@ -273,11 +273,11 @@ ///Store our old datum here for if our antennae are healed var/original_sprite_datum -/obj/item/organ/external/antennae/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/antennae/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() - RegisterSignal(reciever, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_antennae)) - RegisterSignal(reciever, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_antennae)) + RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_antennae)) + RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_antennae)) /obj/item/organ/external/antennae/Remove(mob/living/carbon/organ_owner, special, moving) . = ..() diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 991af39e454..7b2d1da179d 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -17,19 +17,19 @@ ///The original owner of this tail var/original_owner //Yay, snowflake code! -/obj/item/organ/external/tail/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() if(.) - RegisterSignal(reciever, COMSIG_ORGAN_WAG_TAIL, PROC_REF(wag)) - original_owner ||= WEAKREF(reciever) + RegisterSignal(receiver, COMSIG_ORGAN_WAG_TAIL, PROC_REF(wag)) + original_owner ||= WEAKREF(receiver) - reciever.clear_mood_event("tail_lost") - reciever.clear_mood_event("tail_balance_lost") + receiver.clear_mood_event("tail_lost") + receiver.clear_mood_event("tail_balance_lost") - if(IS_WEAKREF_OF(reciever, original_owner)) - reciever.clear_mood_event("wrong_tail_regained") - else if(type in reciever.dna.species.external_organs) - reciever.add_mood_event("wrong_tail_regained", /datum/mood_event/tail_regained_wrong) + if(IS_WEAKREF_OF(receiver, original_owner)) + receiver.clear_mood_event("wrong_tail_regained") + else if(type in receiver.dna.species.external_organs) + receiver.add_mood_event("wrong_tail_regained", /datum/mood_event/tail_regained_wrong) /obj/item/organ/external/tail/Remove(mob/living/carbon/organ_owner, special, moving) if(wag_flags & WAG_WAGGING) diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index a1605f3d546..91eec796873 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -31,12 +31,12 @@ return TRUE // SKYRAT EDIT END -/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() if(isnull(fly)) fly = new - fly.Grant(reciever) + fly.Grant(receiver) /obj/item/organ/external/wings/functional/Remove(mob/living/carbon/organ_owner, special, moving) . = ..() diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index 7c9a10934cd..715a22061c2 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -14,12 +14,12 @@ ///Store our old datum here for if our burned wings are healed var/original_sprite_datum -/obj/item/organ/external/wings/moth/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/wings/moth/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() - RegisterSignal(reciever, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_wings)) - RegisterSignal(reciever, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_wings)) - RegisterSignal(reciever, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(update_float_move)) + RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_wings)) + RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_wings)) + RegisterSignal(receiver, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(update_float_move)) /obj/item/organ/external/wings/moth/Remove(mob/living/carbon/organ_owner, special, moving) . = ..() diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 9bb3f42543f..640937e8be1 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -14,9 +14,9 @@ STOP_PROCESSING(SSobj, src) return ..() -/obj/item/organ/internal/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) . = ..() - if(!.) + if(!. || !owner) return // internal_organs_slot must ALWAYS be ordered in the same way as organ_process_order diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 869e2049920..22c14726ad9 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -162,6 +162,7 @@ #include "objectives.dm" #include "orderable_items.dm" #include "operating_table.dm" +#include "organ_set_bonus.dm" #include "outfit_sanity.dm" #include "paintings.dm" #include "pills.dm" diff --git a/code/modules/unit_tests/organ_set_bonus.dm b/code/modules/unit_tests/organ_set_bonus.dm new file mode 100644 index 00000000000..17620f0a393 --- /dev/null +++ b/code/modules/unit_tests/organ_set_bonus.dm @@ -0,0 +1,86 @@ +/// Tests the "organ set bonus" Elements and Status Effects, which are for the DNA Infuser. +/// Ensures the developers properly change IDs to be unique. +/datum/unit_test/organ_set_bonus_id + +/datum/unit_test/organ_set_bonus_id/Run() + var/list/bonus_effects = typesof(/datum/status_effect/organ_set_bonus) + var/list/existing_ids = list() + for(var/datum/status_effect/organ_set_bonus/bonus_effect as anything in bonus_effects) + var/effect_id = initial(bonus_effect.id) + var/existing_status = (effect_id in existing_ids) + if(existing_status) + TEST_FAIL("The ID of [bonus_effect] was duplicated in another status effect.") + else + existing_ids += effect_id + +/datum/unit_test/organ_set_bonus_sanity/proc/check_status_type(mob/living/carbon/human/lab_rat, datum/status_effect/status_type) + for(var/datum/status_effect/present_effect as anything in lab_rat.status_effects) + if(istype(present_effect, status_type)) + return present_effect + +/// Tests the "organ set bonus" Elements and Status Effects, which are for the DNA Infuser. +/// Ensures that each Element and Status Effect gets properly added/removed from mobs. +/datum/unit_test/organ_set_bonus_sanity + +/datum/unit_test/organ_set_bonus_sanity/Run() + // Fetch the globally instantiated DNA Infuser entries. + for(var/datum/infuser_entry/infuser_entry as anything in GLOB.infuser_entries) + var/output_organs = infuser_entry.output_organs + // Human which will reiceve organs. + var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent) + lab_rat.dna.mutant_bodyparts["moth_antennae"] = list(MUTANT_INDEX_NAME = "Plain", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF"), MUTANT_INDEX_EMISSIVE_LIST = list(FALSE)) // SKYRAT EDIT - Customization + var/list/obj/item/organ/inserted_organs = list() + for(var/obj/item/organ/organ as anything in output_organs) + organ = new organ() + var/implant_ok = organ.Insert(lab_rat, special = TRUE, drop_if_replaced = FALSE) + if(!implant_ok) + TEST_FAIL("The organ \"[organ.type]\" for \"[infuser_entry.type]\" was not inserted in the mob when expected.") + continue + inserted_organs += organ + + var/total_inserted = length(inserted_organs) + + // Search for added Status Effect. + var/datum/status_effect/organ_set_bonus/added_status = check_status_type(lab_rat, /datum/status_effect/organ_set_bonus) + + // Threshold description implies an organ set bonus. + // Without it, we'll assume there isn't a Status Effect to look for. + var/has_threshold = (infuser_entry.threshold_desc != DNA_INFUSION_NO_THRESHOLD) + var/total_organs_needed = added_status ? added_status.organs_needed : 0 + var/total_organs = length(infuser_entry.output_organs) + + // Found a Status Effect but no threshold description. + if(!has_threshold && added_status) + TEST_FAIL("The threshold_desc variable for \"[infuser_entry.type]\" was an empty string when a description was expected.") + + // Since threshold_desc is filled-in, we expect the organ set bonus. + if(has_threshold) + if(!added_status) + TEST_FAIL("The \"/datum/status_effect/organ_set_bonus\" for \"[infuser_entry.type]\" was not added to the mob when expected.") + else if(!total_organs_needed) + TEST_FAIL("The \"needed_organs\" variable for \"[added_status.type]\" was 0 or null, when a positive number was expected.") + else if(total_organs_needed > total_organs) + TEST_FAIL("The \"output_organs\" list for \"[infuser_entry.type]\" had a length of \"[length(infuser_entry.output_organs)]\" when a minimum of at least [total_organs_needed] organs was specified in \"[added_status.type]\".") + else if(!added_status.bonus_active) + TEST_FAIL("The \"[added_status.type]\" bonus was not activated after inserting [total_inserted] of the [total_organs_needed] required organs in the mob, when it was expected.") + + // Nothing to do. + if(!total_inserted) + continue + + // Bonus of the Fly mutation swaps out all the organs, making it rather permanent. + // As a result, the inserted_organs list is un-usable by this point. + if(istype(infuser_entry, /datum/infuser_entry/fly)) + continue + + // Remove all the organs which were just added. + var/total_removed = 0 + for(var/obj/item/organ/test_organ as anything in inserted_organs) + test_organ.Remove(lab_rat, special = TRUE) + total_removed += 1 + + added_status = check_status_type(lab_rat, /datum/status_effect/organ_set_bonus) + + // Search for added Status Effect. + if(added_status && added_status.bonus_active) + TEST_FAIL("The \"[added_status.type]\" bonus was not deactivated after removing [total_removed] of the [total_organs_needed] required organs from the mob, when it was expected.") diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index 62dd75c293b..7893a755b2c 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -17,11 +17,11 @@ new /obj/item/circuit_component/bci_core, ), SHELL_CAPACITY_SMALL, starting_circuit = circuit) -/obj/item/organ/internal/cyberimp/bci/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/internal/cyberimp/bci/Insert(mob/living/carbon/receiver, special, drop_if_replaced) . = ..() // Organs are put in nullspace, but this breaks circuit interactions - forceMove(reciever) + forceMove(receiver) /obj/item/organ/internal/cyberimp/bci/say(message, bubble_type, list/spans, sanitize, datum/language/language, ignore_spam, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null) if (owner)