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"