diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm index 86ecb31fc79..20f32f85a37 100644 --- a/code/__DEFINES/genetics.dm +++ b/code/__DEFINES/genetics.dm @@ -75,6 +75,7 @@ #define TR_KEEPSE 32 // changelings shouldn't edit the DNA's SE when turning into a monkey #define TR_DEFAULTMSG 64 #define TR_KEEPSRC 128 +#define TR_KEEPORGANS 256 //Organ stuff, It's here because "Genetics" is the most relevant file for organs #define ORGAN_ORGANIC 1 diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index 10c6399b17e..63b22f7004e 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -212,11 +212,6 @@ check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_ALIVE|AB_CHECK_INSIDE /datum/action/item_action/CheckRemoval(mob/living/user) - if(iscarbon(user)) - var/mob/living/carbon/C = user - if(target in C.internal_organs) - return 0 - return !(target in user) /datum/action/item_action/hands_free diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 34ac5085c27..45f8ddab2f6 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -252,15 +252,17 @@ body += "" body += "" body += "" - if(ishuman(D)) + if(iscarbon(D)) body += "" - body += "" - body += "" + body += "" body += "" - body += "" + if(ishuman(D)) body += "" + body += "" + body += "" body += "" body += "" + body += "" body += "" body += "" if(isobj(D)) @@ -700,6 +702,17 @@ body if("left") A.dir = turn(A.dir, 45) href_list["datumrefresh"] = href_list["rotatedatum"] + else if(href_list["editorgans"]) + if(!check_rights(0)) return + + var/mob/living/carbon/C = locate(href_list["editorgans"]) + if(!istype(C)) + usr << "This can only be done to instances of type /mob/living/carbon" + return + + manipulate_organs(C) + href_list["datumrefresh"] = href_list["editorgans"] + else if(href_list["makehuman"]) if(!check_rights(R_SPAWN)) return @@ -773,9 +786,9 @@ body else if(href_list["makeai"]) if(!check_rights(R_SPAWN)) return - var/mob/living/carbon/human/H = locate(href_list["makeai"]) + var/mob/living/carbon/H = locate(href_list["makeai"]) if(!istype(H)) - usr << "This can only be done to instances of type /mob/living/carbon/human" + usr << "This can only be done to instances of type /mob/living/carbon" return if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 93fd9239761..69e66e43351 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -94,7 +94,7 @@ /datum/disease/transformation/jungle_fever/do_disease_transformation(mob/living/carbon/affected_mob) if(!ismonkey(affected_mob)) ticker.mode.add_monkey(affected_mob.mind) - affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) /datum/disease/transformation/jungle_fever/stage_act() ..() diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c21d96be8a3..12be3beba8f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1161,7 +1161,7 @@ sleep(0) //because deleting of virus is doing throught spawn(0) log_admin("[key_name(usr)] attempting to humanize [key_name(current)]") message_admins("[key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") - H = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) + H = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) if(H) src = H.mind diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm index a24fbc63aff..b517e417d93 100644 --- a/code/datums/mutations.dm +++ b/code/datums/mutations.dm @@ -334,7 +334,7 @@ /datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner) if(..()) return - . = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + . = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) /datum/mutation/human/race/gain_indication(mob/living/carbon/human/owner) return @@ -345,7 +345,7 @@ /datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner) if(..()) return - . = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + . = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) /datum/mutation/human/stealth diff --git a/code/game/gamemodes/changeling/powers/headcrab.dm b/code/game/gamemodes/changeling/powers/headcrab.dm index 79ff7f9b11e..0f4b1f855ca 100644 --- a/code/game/gamemodes/changeling/powers/headcrab.dm +++ b/code/game/gamemodes/changeling/powers/headcrab.dm @@ -7,10 +7,17 @@ /obj/effect/proc_holder/changeling/headcrab/sting_action(mob/user) var/datum/mind/M = user.mind + var/list/organs = user.getorganszone("head") + user.getorganszone("eyes") + + for(var/obj/item/organ/internal/I in organs) + I.Remove(user, 1) + explosion(get_turf(user),0,0,2,0,silent=1) var/turf = get_turf(user) spawn(5) // So it's not killed in explosion var/mob/living/simple_animal/hostile/headcrab/crab = new(turf) + for(var/obj/item/organ/internal/I in organs) + I.loc = crab crab.origin = M if(M) M.transfer_to(crab) diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index 999aaf47bed..3d8916e6b66 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -26,7 +26,7 @@ user << "We transform our appearance." user.dna = chosen_dna - user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPSRC),chosen_dna.real_name) + user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSRC),chosen_dna.real_name) changeling.purchasedpowers -= src feedback_add_details("changeling_powers","LFT") diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index 310b470ff28..2ce8470c19c 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -12,9 +12,9 @@ return 0 user << "Our genes cry out!" - user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPSE | TR_KEEPSRC) + user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSE | TR_KEEPSRC) // Human-form power now handled in monkeyize() feedback_add_details("changeling_powers","LF") .=1 - qdel(user) + qdel(user) \ No newline at end of file diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm index 2be31698d51..c3a71b8f485 100644 --- a/code/game/objects/items/body_egg.dm +++ b/code/game/objects/items/body_egg.dm @@ -1,58 +1,49 @@ -/obj/item/body_egg - name = "generic egg" +/obj/item/organ/internal/body_egg + name = "body egg" desc = "All slimy and yuck." - icon = 'icons/mob/alien.dmi' - icon_state = "larva0_dead" - var/mob/living/affected_mob + icon_state = "innards" + origin_tech = "biotech=5" + zone = "chest" + slot = "parasite_egg" -/obj/item/body_egg/New() - if(istype(loc, /mob/living)) - affected_mob = loc - affected_mob.status_flags |= XENO_HOST - SSobj.processing |= src - if(istype(affected_mob,/mob/living/carbon)) - var/mob/living/carbon/H = affected_mob - H.med_hud_set_status() - spawn(0) - AddInfectionImages(affected_mob) - else - qdel(src) +/obj/item/organ/internal/body_egg/New(loc) + if(iscarbon(loc)) + src.Insert(loc) + return ..() -/obj/item/body_egg/Destroy() - if(affected_mob) - affected_mob.status_flags &= ~(XENO_HOST) - if(istype(affected_mob,/mob/living/carbon)) - var/mob/living/carbon/H = affected_mob - H.med_hud_set_status() +/obj/item/organ/internal/body_egg/Insert(var/mob/living/carbon/M, special = 0) + ..() + owner.status_flags |= XENO_HOST + SSobj.processing |= src + owner.med_hud_set_status() + spawn(0) + AddInfectionImages(owner) + +/obj/item/organ/internal/body_egg/Remove(var/mob/living/carbon/M, special = 0) + SSobj.processing.Remove(src) + if(owner) + owner.status_flags &= ~(XENO_HOST) + owner.med_hud_set_status() spawn(0) - RemoveInfectionImages(affected_mob) - affected_mob = null + RemoveInfectionImages(owner) ..() -/obj/item/body_egg/process() - if(!affected_mob) return - if(loc != affected_mob) - affected_mob.status_flags &= ~(XENO_HOST) - SSobj.processing.Remove(src) - if(istype(affected_mob,/mob/living/carbon)) - var/mob/living/carbon/H = affected_mob - H.med_hud_set_status() - spawn(0) - RemoveInfectionImages(affected_mob) - affected_mob = null +/obj/item/organ/internal/body_egg/process() + if(!owner) return + if(!(src in owner.internal_organs)) + Remove(owner) return - egg_process() -/obj/item/body_egg/proc/egg_process() +/obj/item/organ/internal/body_egg/proc/egg_process() return -/obj/item/body_egg/proc/RefreshInfectionImage() +/obj/item/organ/internal/body_egg/proc/RefreshInfectionImage() RemoveInfectionImages() AddInfectionImages() -/obj/item/body_egg/proc/AddInfectionImages() +/obj/item/organ/internal/body_egg/proc/AddInfectionImages() return -/obj/item/body_egg/proc/RemoveInfectionImages() +/obj/item/organ/internal/body_egg/proc/RemoveInfectionImages() return \ No newline at end of file diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index d7497060491..8844b5c5be4 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -400,6 +400,7 @@ var/list/TYPES_SHORTCUTS = list( /obj/machinery/portable_atmospherics = "PORT_ATMOS", /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack = "MECHA_MISSILE_RACK", /obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP", + /obj/item/organ/internal = "ORGAN_INT", ) var/global/list/g_fancy_list_of_types = null diff --git a/code/modules/admin/verbs/manipulate_organs.dm b/code/modules/admin/verbs/manipulate_organs.dm new file mode 100644 index 00000000000..99dfeadd05b --- /dev/null +++ b/code/modules/admin/verbs/manipulate_organs.dm @@ -0,0 +1,55 @@ +/client/proc/manipulate_organs(mob/living/carbon/C in world) + set name = "Manipulate Organs" + set category = "Debug" + var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add organ", "add implant", "drop organ/implant", "remove organ/implant", "cancel") + + var/list/organs = list() + switch(operation) + if("add organ") + for(var/path in typesof(/obj/item/organ/internal) - /obj/item/organ/internal) + var/dat = replacetext("[path]", "/obj/item/organ/internal/", ":") + organs[dat] = path + + var/obj/item/organ/internal/organ = input("Select organ type:", "Organ Manipulation", null) in organs + organ = organs[organ] + organ = new organ + organ.Insert(C) + + if("add implant") + for(var/path in typesof(/obj/item/weapon/implant) - /obj/item/weapon/implant) + var/dat = replacetext("[path]", "/obj/item/weapon/implant/", ":") + organs[dat] = path + + var/obj/item/weapon/implant/organ = input("Select implant type:", "Organ Manipulation", null) in organs + organ = organs[organ] + organ = new organ + organ.implant(C) + + if("drop organ/implant", "remove organ/implant") + for(var/obj/item/organ/internal/I in C.internal_organs) + organs["[I] ([I.type])"] = I + + for(var/obj/item/weapon/implant/I in C) + organs["[I] ([I.type])"] = I + + var/obj/item/organ = input("Select organ/implant:", "Organ Manipulation", null) in organs + organ = organs[organ] + if(!organ) return + var/obj/item/organ/internal/O + var/obj/item/weapon/implant/I + + if(isorgan(organ)) + O = organ + O.Remove(C) + else + I = organ + I.removed(C) + + organ.loc = get_turf(C) + + if(operation == "remove organ/implant") + qdel(organ) + else if(I) // Put the implant in case. + var/obj/item/weapon/implantcase/case = new(get_turf(C)) + case.imp = I + I.loc = case \ No newline at end of file diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index d947599c6d5..5152ab29436 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -159,6 +159,8 @@ var/intercom_range_display_status = 0 src.verbs += /client/proc/print_pointers src.verbs += /client/proc/count_movable_instances src.verbs += /client/proc/cmd_show_at_list + src.verbs += /client/proc/cmd_show_at_list + src.verbs += /client/proc/manipulate_organs //src.verbs += /client/proc/cmd_admin_rejuvenate feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 04ab010bc33..f96c94af11a 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -190,7 +190,7 @@ Des: Gives the client of the alien an image on each infected mob. if (client) for (var/mob/living/C in mob_list) if(C.status_flags & XENO_HOST) - var/obj/item/body_egg/alien_embryo/A = locate() in C + var/obj/item/organ/internal/body_egg/alien_embryo/A = locate() in C var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]") client.images += I return diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 0f742d02a10..b62a11e5153 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -2,55 +2,53 @@ // It functions almost identically (see code/datums/diseases/alien_embryo.dm) var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds -/obj/item/body_egg/alien_embryo +/obj/item/organ/internal/body_egg/alien_embryo name = "alien embryo" + icon = 'icons/mob/alien.dmi' + icon_state = "larva0_dead" var/stage = 0 -/obj/item/body_egg/alien_embryo/egg_process() +/obj/item/organ/internal/body_egg/alien_embryo/on_life() + switch(stage) + if(2, 3) + if(prob(1)) + owner.emote("sneeze") + if(prob(1)) + owner.emote("cough") + if(prob(1)) + owner << "Your throat feels sore." + if(prob(1)) + owner << "Mucous runs down the back of your throat." + if(4) + if(prob(1)) + owner.emote("sneeze") + if(prob(1)) + owner.emote("cough") + if(prob(2)) + owner << "Your muscles ache." + if(prob(20)) + owner.take_organ_damage(1) + if(prob(2)) + owner << "Your stomach hurts." + if(prob(20)) + owner.adjustToxLoss(1) + if(5) + owner << "You feel something tearing its way out of your stomach..." + owner.adjustToxLoss(10) + +/obj/item/organ/internal/body_egg/alien_embryo/egg_process() if(stage < 5 && prob(3)) stage++ spawn(0) RefreshInfectionImage() - switch(stage) - if(2, 3) - if(affected_mob == DEAD) - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - affected_mob << "Your throat feels sore." - if(prob(1)) - affected_mob << "Mucous runs down the back of your throat." - if(4) - if(affected_mob == DEAD) - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(2)) - affected_mob << "Your muscles ache." - if(prob(20)) - affected_mob.take_organ_damage(1) - if(prob(2)) - affected_mob << "Your stomach hurts." - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - if(5) - if(affected_mob != DEAD) - affected_mob << "You feel something tearing its way out of your stomach..." - affected_mob.adjustToxLoss(10) - affected_mob.updatehealth() - if(prob(50)) - AttemptGrow() + if(stage == 5 && prob(50)) + AttemptGrow() -/obj/item/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success = 1) +/obj/item/organ/internal/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success = 1) + if(!owner) return var/list/candidates = get_candidates(BE_ALIEN, ALIEN_AFK_BRACKET) var/client/C = null @@ -61,55 +59,47 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds if(candidates.len) C = pick(candidates) - else if(affected_mob.client) - C = affected_mob.client + else if(owner.client) + C = owner.client else stage = 4 // Let's try again later. return - if(affected_mob.lying) - affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie") + if(owner.lying) + owner.overlays += image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_lie") else - affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand") + owner.overlays += image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_stand") spawn(6) - var/location = get_turf(affected_mob) - if(!location) - location = affected_mob.loc - var/mob/living/carbon/alien/larva/new_xeno = new(location) + var/atom/xeno_loc = owner + if(!gib_on_success) + xeno_loc = get_turf(xeno_loc) + + var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc) new_xeno.key = C.key new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention if(gib_on_success) - affected_mob.gib() - if(istype(new_xeno.loc,/mob/living/carbon)) - var/mob/living/carbon/digester = new_xeno.loc - digester.stomach_contents += new_xeno + owner.stomach_contents += new_xeno + owner.gib() qdel(src) -/*---------------------------------------- -Proc: RefreshInfectionImage() -Des: Removes the current icons located in the infected mob adds the current stage -----------------------------------------*/ -/obj/item/body_egg/alien_embryo/RefreshInfectionImage() - RemoveInfectionImages() - AddInfectionImages() /*---------------------------------------- Proc: AddInfectionImages(C) Des: Adds the infection image to all aliens for this embryo ----------------------------------------*/ -/obj/item/body_egg/alien_embryo/AddInfectionImages() +/obj/item/organ/internal/body_egg/alien_embryo/AddInfectionImages() for(var/mob/living/carbon/alien/alien in player_list) if(alien.client) - var/I = image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "infected[stage]") + var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]") alien.client.images += I /*---------------------------------------- Proc: RemoveInfectionImage(C) Des: Removes all images from the mob infected by this embryo ----------------------------------------*/ -/obj/item/body_egg/alien_embryo/RemoveInfectionImages() +/obj/item/organ/internal/body_egg/alien_embryo/RemoveInfectionImages() for(var/mob/living/carbon/alien/alien in player_list) if(alien.client) for(var/image/I in alien.client.images) - if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == affected_mob) + if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner) qdel(I) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 7763954c786..bfca0c02171 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -116,7 +116,7 @@ var/const/MAX_ACTIVE_TIME = 400 if(loc == L) return 0 if(stat != CONSCIOUS) return 0 - if(locate(/obj/item/body_egg/alien_embryo) in L) return 0 + if(locate(/obj/item/organ/internal/body_egg/alien_embryo) in L) return 0 if(!sterile) L.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage L.visible_message("[src] leaps at [L]'s face!", \ @@ -176,8 +176,7 @@ var/const/MAX_ACTIVE_TIME = 400 icon_state = "[initial(icon_state)]_impregnated" if(!target.getlimb(/obj/item/organ/limb/robot/chest) && !(target.status_flags & XENO_HOST)) - new /obj/item/body_egg/alien_embryo(target) - + new /obj/item/organ/internal/body_egg/alien_embryo(target) if(iscorgi(target)) var/mob/living/simple_animal/pet/dog/corgi/C = target diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index c301a6a8d04..5df89ec19ae 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -9,7 +9,7 @@ throw_speed = 3 throw_range = 5 layer = 4.1 - origin_tech = "biotech=3" + origin_tech = "biotech=4" attack_verb = list("attacked", "slapped", "whacked") var/mob/living/carbon/brain/brainmob = null diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index af0c7205b31..70d3d476103 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -172,7 +172,7 @@ if(blocked <= 0) return 0 var/obj/item/organ/limb/organ = null - if(isorgan(def_zone)) + if(islimb(def_zone)) organ = def_zone else if(!def_zone) def_zone = ran_zone(def_zone) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 06944984cf5..8ed71d82690 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -11,7 +11,7 @@ emp_act var/organnum = 0 if(def_zone) - if(isorgan(def_zone)) + if(islimb(def_zone)) return checkarmor(def_zone, type) var/obj/item/organ/limb/affecting = get_organ(ran_zone(def_zone)) return checkarmor(affecting, type) @@ -469,4 +469,4 @@ emp_act L.take_damage(I.w_class*I.embedded_impact_pain_multiplier) visible_message("\the [I.name] embeds itself in [src]'s [L.getDisplayName()]!","\the [I.name] embeds itself in your [L.getDisplayName()]!") return - return ..() + return ..() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 0e90a523120..d24c1a42450 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1101,7 +1101,7 @@ if(blocked <= 0) return 0 var/obj/item/organ/limb/organ = null - if(isorgan(def_zone)) + if(islimb(def_zone)) organ = def_zone else if(!def_zone) def_zone = ran_zone(def_zone) diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index 2fe08fe36ed..587e686d67d 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -21,13 +21,15 @@ var/datum/mind/origin var/egg_lain = 0 -/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/human/victim) - var/obj/item/body_egg/changeling_egg/egg = new(victim) +/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/victim) + var/obj/item/organ/internal/body_egg/changeling_egg/egg = new(victim) + egg.Insert(victim) if(origin) - egg.owner = origin + egg.origin = origin else if(mind) // Let's make this a feature - egg.owner = mind - victim.internal_organs += egg + egg.origin = mind + for(var/obj/item/organ/internal/I in src) + I.loc = egg visible_message("[src] lays an egg in a [victim].") egg_lain = 1 @@ -35,9 +37,10 @@ if(egg_lain) target.attack_animal(src) return - if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(H.stat == DEAD) + if(iscarbon(target) && !ismonkey(target)) + // Changeling egg can survive in aliens! + var/mob/living/carbon/C = target + if(C.stat == DEAD) Infect(target) src << "With your egg laid you feel your death rapidly approaching, time to die..." spawn(100) @@ -48,32 +51,36 @@ -/obj/item/body_egg/changeling_egg +/obj/item/organ/internal/body_egg/changeling_egg name = "changeling egg" - desc = "Twitching and disgusting" - var/datum/mind/owner + desc = "Twitching and disgusting." + origin_tech = "biotech=7" // You need to be really lucky to obtain it. + var/datum/mind/origin var/time - var/used -/obj/item/body_egg/changeling_egg/egg_process() - //Changeling eggs grow in dead people +/obj/item/organ/internal/body_egg/changeling_egg/egg_process() + // Changeling eggs grow in dead people time++ if(time >= EGG_INCUBATION_TIME) Pop() + Remove(owner) + qdel(src) -/obj/item/body_egg/changeling_egg/proc/Pop() - if(!used) - var/mob/living/carbon/monkey/M = new(affected_mob.loc) - if(owner) - owner.transfer_to(M) - if(owner.changeling) - owner.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) - M.key = owner.key - if(ishuman(affected_mob)) - var/mob/living/carbon/human/H = affected_mob - H.internal_organs.Remove(src) - affected_mob.gib() - used = 1 - qdel(src) +/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop() + var/mob/living/carbon/monkey/M = new(owner) + owner.stomach_contents += M + + for(var/obj/item/organ/internal/I in src) + I.Insert(M, 1) + + if(!origin && owner.mind) + origin = owner.mind + + if(origin) + origin.transfer_to(M) + if(origin.changeling) + origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) + M.key = origin.key + owner.gib() #undef EGG_INCUBATION_TIME diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 62fb5c75178..316eff9795e 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -125,7 +125,7 @@ return 1 return 0 -/proc/isorgan(A) +/proc/islimb(A) if(istype(A, /obj/item/organ/limb)) return 1 return 0 diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 45fe320ce0c..d645bf4a6ef 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -3,15 +3,18 @@ return //Handle items on mob - //first implants + //first implants & organs var/list/implants = list() + var/list/int_organs = list() + if (tr_flags & TR_KEEPIMPLANTS) for(var/obj/item/weapon/implant/W in src) implants += W - if(tr_flags & TR_KEEPITEMS) - for(var/obj/item/W in (src.contents-implants)) - unEquip(W) + if (tr_flags & TR_KEEPORGANS) + for(var/obj/item/organ/internal/I in internal_organs) + int_organs += I + I.Remove(src, 1) //Make mob invisible and spawn animation regenerate_icons() @@ -70,6 +73,14 @@ I.loc = O I.implanted = O + //re-add organs to new mob + if(tr_flags & TR_KEEPORGANS) + for(var/obj/item/organ/internal/I in O.internal_organs) + qdel(I) + + for(var/obj/item/organ/internal/I in int_organs) + I.Insert(O, 1) + //transfer mind and delete old mob if(mind) mind.transfer_to(O) @@ -98,12 +109,19 @@ return //Handle items on mob - //first implants + //first implants & organs var/list/implants = list() + var/list/int_organs = list() + if (tr_flags & TR_KEEPIMPLANTS) for(var/obj/item/weapon/implant/W in src) implants += W + if (tr_flags & TR_KEEPORGANS) + for(var/obj/item/organ/internal/I in internal_organs) + int_organs += I + I.Remove(src, 1) + //now the rest if (tr_flags & TR_KEEPITEMS) for(var/obj/item/W in (src.contents-implants)) @@ -187,6 +205,13 @@ I.implanted = O O.sec_hud_set_implants() + if(tr_flags & TR_KEEPORGANS) + for(var/obj/item/organ/internal/I in O.internal_organs) + qdel(I) + + for(var/obj/item/organ/internal/I in int_organs) + I.Insert(O, 1) + if(mind) mind.transfer_to(O) O.a_intent = "help" diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index 6b4feb8749e..b3ab5a6379c 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -3,6 +3,7 @@ steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/extract_implant, /datum/surgery_step/close) species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list("chest") + requires_organic_bodypart = 0 //extract implant diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 3cdfda38de5..ab814cbf9df 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -26,12 +26,12 @@ M.sight |= sight_flags /obj/item/organ/internal/cyberimp/eyes/Remove(var/mob/living/carbon/M, var/special = 0) - ..() M.sight ^= sight_flags - if(istype(owner,/mob/living/carbon/human) && eye_color) + if(istype(M,/mob/living/carbon/human) && eye_color) var/mob/living/carbon/human/HMN = owner HMN.eye_color = old_eye_color HMN.regenerate_icons() + ..() /obj/item/organ/internal/cyberimp/eyes/on_life() ..() @@ -88,11 +88,11 @@ M.permanent_huds |= H /obj/item/organ/internal/cyberimp/eyes/hud/Remove(var/mob/living/carbon/M, var/special = 0) - ..() if(HUD_type) var/datum/atom_hud/H = huds[HUD_type] M.permanent_huds ^= H H.remove_hud_from(M) + ..() /obj/item/organ/internal/cyberimp/eyes/hud/medical name = "Medical HUD implant" diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index ee26bab3a0d..b904d93f9e3 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -114,9 +114,9 @@ r_hand_obj.flags ^= NODROP /obj/item/organ/internal/cyberimp/brain/anti_drop/Remove(var/mob/living/carbon/M, special = 0) - ..() if(active) ui_action_click() + ..() /obj/item/organ/internal/cyberimp/brain/anti_stun @@ -167,8 +167,6 @@ /obj/item/organ/internal/cyberimp/chest/nutriment/on_life() if(synthesizing) return - if(owner.stat == DEAD) - return if(owner.nutrition <= hunger_threshold) synthesizing = 1 diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm index 151aed42fca..18b4185ea52 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -27,4 +27,7 @@ mob/proc/getlimb() return mob/living/carbon/human/getlimb(typepath) - return (locate(typepath) in organs) \ No newline at end of file + return (locate(typepath) in organs) + +proc/isorgan(atom/A) + return istype(A, /obj/item/organ/internal) \ No newline at end of file diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index d41710296c9..af2b5d1a7ca 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -1,21 +1,31 @@ /obj/item/organ/internal + origin_tech = "biotech=2" var/zone = "chest" var/slot var/vital = 0 var/organ_action_name = null /obj/item/organ/internal/proc/Insert(var/mob/living/carbon/M, special = 0) + if(!iscarbon(M)) + return + + var/obj/item/organ/internal/replaced = M.getorganslot(slot) + if(replaced) + replaced.Remove(M, special = 1) + + owner = M - M.internal_organs += src + M.internal_organs |= src loc = null if(organ_action_name) action_button_name = organ_action_name /obj/item/organ/internal/proc/Remove(var/mob/living/carbon/M, special = 0) owner = null - M.internal_organs -= src - if(vital && !special) - M.death() + if(M) + M.internal_organs -= src + if(vital && !special) + M.death() if(organ_action_name) action_button_name = null @@ -23,6 +33,11 @@ /obj/item/organ/internal/proc/on_life() return +/obj/item/organ/internal/Destroy() + if(owner) + Remove(owner, 1) + ..() + //Looking for brains? //Try code/modules/mob/living/carbon/brain/brain_item.dm @@ -33,6 +48,7 @@ icon_state = "heart-on" zone = "chest" slot = "heart" + origin_tech = "biotech=3" vital = 1 var/beating = 1 @@ -42,6 +58,16 @@ else icon_state = "heart-off" +/obj/item/organ/internal/heart/Insert(var/mob/living/carbon/M, special = 0) + ..() + beating = 1 + update_icon() + +/obj/item/organ/internal/heart/Remove(var/mob/living/carbon/M, special = 0) + ..() + spawn(120) + beating = 0 + update_icon() /obj/item/organ/internal/appendix diff --git a/code/modules/surgery/xenomorph_removal.dm b/code/modules/surgery/xenomorph_removal.dm index 8528c349179..97cabb6d003 100644 --- a/code/modules/surgery/xenomorph_removal.dm +++ b/code/modules/surgery/xenomorph_removal.dm @@ -23,7 +23,7 @@ return 1 /datum/surgery_step/xenomorph_removal/proc/remove_xeno(mob/user, mob/living/carbon/target) - var/obj/item/body_egg/alien_embryo/A = locate() in target.contents + var/obj/item/organ/internal/body_egg/alien_embryo/A = target.getorgan(/obj/item/organ/internal/body_egg/alien_embryo) if(A) user << "You found an unknown alien organism in [target]'s chest!" if(A.stage < 4) @@ -33,12 +33,13 @@ if(prob(10)) A.AttemptGrow() + A.Remove(target) A.loc = get_turf(target) return 1 /datum/surgery_step/xenomorph_removal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/obj/item/body_egg/alien_embryo/A = locate() in target.contents + var/obj/item/organ/internal/body_egg/alien_embryo/A = target.getorgan(/obj/item/organ/internal/body_egg/alien_embryo) if(A) if(prob(50)) A.AttemptGrow(0) diff --git a/tgstation.dme b/tgstation.dme index 9aad023590f..f5124222594 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -838,6 +838,7 @@ #include "code\modules\admin\verbs\fps.dm" #include "code\modules\admin\verbs\getlogs.dm" #include "code\modules\admin\verbs\machine_upgrade.dm" +#include "code\modules\admin\verbs\manipulate_organs.dm" #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" #include "code\modules\admin\verbs\modifyvariables.dm"