diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index a8026f752b..62438ac7c1 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -143,11 +143,11 @@
#define CUSTOM_SKINTONE 24 //adds a "_g" suffix to bodypart overlays icon states if a custom skintone is used.
#define HORNCOLOR 25
#define WINGCOLOR 26
-#define CAN_SCAR 27 // If this species can be scarred (fleshy)
-
+#define ROBOTIC_LIMBS 27 //has robotic limbs that render like organic ones
+#define CAN_SCAR 28 // If this species can be scarred (fleshy)
/// Used for determining which wounds are applicable to this species.
-#define HAS_FLESH 28 /// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD)
-#define HAS_BONE 29 /// if we have bones (can suffer bone wounds)
+#define HAS_FLESH 29 /// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD)
+#define HAS_BONE 30 /// if we have bones (can suffer bone wounds)
//organ slots
#define ORGAN_SLOT_BRAIN "brain"
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 55be13834d..66f741b2c7 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -76,6 +76,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismush(A) (is_species(A, /datum/species/mush))
#define isshadow(A) (is_species(A, /datum/species/shadow))
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
+#define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz))
#define isethereal(A) (is_species(A, /datum/species/ethereal))
// Citadel specific species
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 674cc16980..f054f163b5 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -205,6 +205,7 @@
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
#define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing.
#define TRAIT_FAST_PUMP "fast_pump"
+#define TRAIT_NO_PROCESS_FOOD "no-process-food" // You don't get benefits from nutriment, nor nutrition from reagent consumables
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good...
// mobility flag traits
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index a2f534115a..d46694d89c 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -128,6 +128,9 @@
duration = set_duration
. = ..()
+/datum/status_effect/no_combat_mode/robotic_emp
+ id = "emp_no_combat_mode"
+
/datum/status_effect/mesmerize
id = "Mesmerize"
alert_type = /obj/screen/alert/status_effect/mesmerized
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 2e12a2ab8c..4cada03307 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -110,13 +110,18 @@
var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected))
if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM)
+ //only heal to 25 if limb is damaged to or past 25 brute, otherwise heal normally
+ var/difference = affecting.brute_dam - 25
+ var/heal_amount = 15
+ if(difference >= 0)
+ heal_amount = difference
if(src.use_tool(H, user, 0, volume=50, amount=1))
if(user == H)
user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].",
"You start fixing some of the dents on [H]'s [affecting.name].")
if(!do_mob(user, H, 50))
return
- item_heal_robotic(H, user, 15, 0)
+ item_heal_robotic(H, user, heal_amount, 0)
else
return ..()
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
index d1f7f15ac9..4faef230df 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
@@ -51,7 +51,7 @@
/datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
- return (!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
+ return (!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/xeno_head/standard
name = "Standard"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
index 7515ce560a..1d9138465f 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
@@ -5,7 +5,7 @@
/datum/sprite_accessory/ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
- return (!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
+ return (!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/ears/none
name = "None"
@@ -187,7 +187,7 @@
/datum/sprite_accessory/ears/mam_ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
- return (!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
+ return (!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/ears/mam_ears/none
name = "None"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
index aff342c7a6..accbc4ee36 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
@@ -5,7 +5,7 @@
/datum/sprite_accessory/horns/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
- return (!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
+ return (!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/horns/none
name = "None"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
index 99d2c67cc9..0cd7d301db 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
@@ -5,7 +5,7 @@
/datum/sprite_accessory/snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
- return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
+ return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/snout/guilmon
name = "Guilmon"
@@ -163,7 +163,7 @@
/datum/sprite_accessory/snouts/mam_snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
- return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
+ return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/snouts/mam_snouts/none
name = "None"
diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm
index a853416e6f..59a119a89a 100644
--- a/code/modules/mob/living/brain/brain_item.dm
+++ b/code/modules/mob/living/brain/brain_item.dm
@@ -284,11 +284,19 @@
QDEL_LIST(traumas)
return ..()
+//other types of brains
+
/obj/item/organ/brain/alien
name = "alien brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
icon_state = "brain-x"
+/obj/item/organ/brain/ipc
+ name = "positronic brain"
+ desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. It has an IPC serial number engraved on the top. It is usually slotted into the head of synthetic crewmembers."
+ icon = 'icons/obj/surgery.dmi'
+ icon_state = "posibrain-ipc"
+
////////////////////////////////////TRAUMAS////////////////////////////////////////
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index ecaa5e16c3..96fda36370 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -407,6 +407,9 @@
if(. & EMP_PROTECT_CONTENTS)
return
var/informed = FALSE
+ if(isrobotic(src))
+ apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
+ severity *= 0.5
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.status == BODYPART_ROBOTIC)
if(!informed)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index b6fdbfafdd..554013c7bc 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -362,7 +362,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.client && has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
H.LoadComponent(/datum/component/field_of_vision, H.field_of_vision_type)
- update_species_slowdown(C)
+ C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod)
+
+ if(ROBOTIC_LIMBS in species_traits)
+ for(var/obj/item/bodypart/B in C.bodyparts)
+ B.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE) // Makes all Bodyparts robotic.
+ B.render_like_organic = TRUE
+
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
/datum/species/proc/update_species_slowdown(mob/living/carbon/human/H)
@@ -403,6 +409,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(F)
qdel(F)
+
+ if(ROBOTIC_LIMBS in species_traits)
+ for(var/obj/item/bodypart/B in C.bodyparts)
+ B.change_bodypart_status(BODYPART_ORGANIC, FALSE, TRUE)
+ B.render_like_organic = FALSE
+
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
@@ -423,7 +435,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/dynamic_fhair_suffix = ""
//for augmented heads
- if(HD.status == BODYPART_ROBOTIC)
+ if(HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)
return
//we check if our hat or helmet hides our facial hair.
diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm
index c5b57b82ab..5d43d18429 100644
--- a/code/modules/mob/living/carbon/human/species_types/android.dm
+++ b/code/modules/mob/living/carbon/human/species_types/android.dm
@@ -2,7 +2,7 @@
name = "Android"
id = "android"
say_mod = "states"
- species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL)
+ species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,ROBOTIC_LIMBS)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
meat = null
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index b675925aeb..9bfe661f47 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -5,19 +5,26 @@
default_color = "00FF00"
blacklisted = 0
sexes = 0
- species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR)
+ inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD)
+ species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR,ROBOTIC_LIMBS)
hair_alpha = 210
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
- mutanttongue = /obj/item/organ/tongue/robot/ipc
-//Just robo looking parts.
+
+ //Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
mutantliver = /obj/item/organ/liver/ipc
mutantstomach = /obj/item/organ/stomach/ipc
mutanteyes = /obj/item/organ/eyes/ipc
+ mutantears = /obj/item/organ/ears/ipc
+ mutanttongue = /obj/item/organ/tongue/robot/ipc
+ mutant_brain = /obj/item/organ/brain/ipc
+
+ //special cybernetic organ for getting power from apcs
+ mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord)
exotic_bloodtype = "HF"
exotic_blood_color = BLOOD_COLOR_OIL
diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
index 70afa2f476..b446e3796e 100644
--- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
@@ -3,18 +3,24 @@
id = "synthliz"
say_mod = "beeps"
default_color = "00FF00"
- species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,HAS_FLESH,HAS_BONE)
+ species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE)
+ inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
- mutanttongue = /obj/item/organ/tongue/robot/ipc
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
mutantliver = /obj/item/organ/liver/ipc
mutantstomach = /obj/item/organ/stomach/ipc
mutanteyes = /obj/item/organ/eyes/ipc
+ mutantears = /obj/item/organ/ears/ipc
+ mutanttongue = /obj/item/organ/tongue/robot/ipc
+ mutant_brain = /obj/item/organ/brain/ipc
+
+ //special cybernetic organ for getting power from apcs
+ mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord)
exotic_bloodtype = "S"
exotic_blood_color = BLOOD_COLOR_OIL
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 6dcb08512c..3f1e688120 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -549,11 +549,16 @@ By design, d1 is the smallest direction and d2 is the highest
var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected))
if(affecting && affecting.status == BODYPART_ROBOTIC)
+ //only heal to 25 if limb is damaged to or past 25 burn, otherwise heal normally
+ var/difference = affecting.burn_dam - 25
+ var/heal_amount = 15
+ if(difference >= 0)
+ heal_amount = difference
if(user == H)
user.visible_message("[user] starts to fix some of the wires in [H]'s [affecting.name].", "You start fixing some of the wires in [H]'s [affecting.name].")
if(!do_mob(user, H, 50))
return
- if(item_heal_robotic(H, user, 0, 15))
+ if(item_heal_robotic(H, user, 0, heal_amount))
use(1)
return
else
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 4dac668adc..fe05365dd9 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -185,6 +185,23 @@
/obj/item/stock_parts/cell/get_part_rating()
return rating * maxcharge
+// stuff so ipcs and synthlizards can eat power cells, taken from how moths can eat clothing
+/obj/item/reagent_containers/food/snacks/cell
+ name = "oops"
+ desc = "If you're reading this it means I messed up. This is related to ipcs/synths eating cells and I didn't know a better way to do it than making a new food object."
+ list_reagents = list(/datum/reagent/consumable/nutriment = 0.5)
+ tastes = list("electricity" = 1, "metal" = 1)
+
+/obj/item/stock_parts/cell/attack(mob/M, mob/user, def_zone)
+ if(user.a_intent != INTENT_HARM && isrobotic(M))
+ var/obj/item/reagent_containers/food/snacks/cell/cell_as_food = new
+ cell_as_food.name = name
+ if(cell_as_food.attack(M, user, def_zone))
+ take_damage(40, sound_effect=FALSE)
+ qdel(cell_as_food)
+ else
+ return ..()
+
/* Cell variants*/
/obj/item/stock_parts/cell/empty
start_charged = FALSE
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 7979c7b0c7..1975eede70 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -17,8 +17,9 @@
var/quality = 0 //affects mood, typically higher for mixed drinks with more complex recipes
/datum/reagent/consumable/on_mob_life(mob/living/carbon/M)
- current_cycle++
- M.adjust_nutrition(nutriment_factor, max_nutrition)
+ if(!HAS_TRAIT(M, TRAIT_NO_PROCESS_FOOD))
+ current_cycle++
+ M.adjust_nutrition(nutriment_factor, max_nutrition)
M.CheckBloodsuckerEatFood(nutriment_factor)
holder.remove_reagent(type, metabolization_rate)
@@ -49,10 +50,11 @@
var/burn_heal = 0
/datum/reagent/consumable/nutriment/on_mob_life(mob/living/carbon/M)
- if(prob(50))
- M.heal_bodypart_damage(brute_heal,burn_heal, 0)
- . = 1
- ..()
+ if(!HAS_TRAIT(M, TRAIT_NO_PROCESS_FOOD))
+ if(prob(50))
+ M.heal_bodypart_damage(brute_heal,burn_heal, 0)
+ . = 1
+ ..()
/datum/reagent/consumable/nutriment/on_new(list/supplied_data)
// taste data can sometimes be ("salt" = 3, "chips" = 1)
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 773415b15c..421c3bccca 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -71,6 +71,8 @@
var/medium_burn_msg = "blistered"
var/heavy_burn_msg = "peeling away"
+ var/render_like_organic = FALSE // forces limb to render as if it were an organic limb
+
/// The wounds currently afflicting this body part
var/list/wounds
@@ -555,7 +557,7 @@
if(status == BODYPART_ORGANIC)
icon = base_bp_icon || DEFAULT_BODYPART_ICON_ORGANIC
else if(status == BODYPART_ROBOTIC)
- icon = DEFAULT_BODYPART_ICON_ROBOTIC
+ icon = base_bp_icon || DEFAULT_BODYPART_ICON_ROBOTIC
if(owner)
owner.updatehealth()
@@ -669,8 +671,9 @@
if(status == BODYPART_ROBOTIC)
dmg_overlay_type = "robotic"
- body_markings = null
- aux_marking = null
+ if(!render_like_organic)
+ body_markings = null
+ aux_marking = null
if(dropping_limb)
no_update = TRUE //when attached, the limb won't be affected by the appearance changes of its mob owner.
@@ -736,7 +739,7 @@
if((body_zone != BODY_ZONE_HEAD && body_zone != BODY_ZONE_CHEST))
should_draw_gender = FALSE
- if(is_organic_limb())
+ if(is_organic_limb() || render_like_organic)
limb.icon = base_bp_icon || 'icons/mob/human_parts.dmi'
if(should_draw_gender)
limb.icon_state = "[species_id]_[body_zone]_[icon_gender]"
diff --git a/code/modules/surgery/brain_surgery.dm b/code/modules/surgery/brain_surgery.dm
index afaa66dae9..239bd8a98d 100644
--- a/code/modules/surgery/brain_surgery.dm
+++ b/code/modules/surgery/brain_surgery.dm
@@ -10,7 +10,7 @@
target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_HEAD)
- requires_bodypart_type = 0
+ requires_bodypart_type = BODYPART_ORGANIC
/datum/surgery_step/fix_brain
name = "fix brain"
implements = list(TOOL_HEMOSTAT = 85, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) //don't worry, pouring some alcohol on their open brain will get that chance to 100
diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm
index d1d478ddfe..69f5062032 100644
--- a/code/modules/surgery/coronary_bypass.dm
+++ b/code/modules/surgery/coronary_bypass.dm
@@ -3,6 +3,7 @@
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise_heart, /datum/surgery_step/coronary_bypass, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = BODYPART_ORGANIC
/datum/surgery/coronary_bypass/can_start(mob/user, mob/living/carbon/target, obj/item/tool)
var/obj/item/organ/heart/H = target.getorganslot(ORGAN_SLOT_HEART)
diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm
index 87e6d096b3..57803f7461 100644
--- a/code/modules/surgery/dental_implant.dm
+++ b/code/modules/surgery/dental_implant.dm
@@ -2,6 +2,7 @@
name = "dental implant"
steps = list(/datum/surgery_step/drill, /datum/surgery_step/insert_pill)
possible_locs = list(BODY_ZONE_PRECISE_MOUTH)
+ requires_bodypart_type = BODYPART_ORGANIC
/datum/surgery_step/insert_pill
name = "insert pill"
diff --git a/code/modules/surgery/embalming.dm b/code/modules/surgery/embalming.dm
index c6d2c72caa..a4494c606a 100644
--- a/code/modules/surgery/embalming.dm
+++ b/code/modules/surgery/embalming.dm
@@ -7,7 +7,7 @@
target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
- requires_bodypart_type = 0
+ requires_bodypart_type = BODYPART_ORGANIC
/datum/surgery_step/embalming
name = "embalming body"
diff --git a/code/modules/surgery/emergency_cardioversion_recovery.dm b/code/modules/surgery/emergency_cardioversion_recovery.dm
index 5df90c5e80..2508bf135f 100644
--- a/code/modules/surgery/emergency_cardioversion_recovery.dm
+++ b/code/modules/surgery/emergency_cardioversion_recovery.dm
@@ -3,6 +3,7 @@
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise_heart, /datum/surgery_step/ventricular_electrotherapy, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = BODYPART_ORGANIC
/datum/surgery_step/ventricular_electrotherapy
name = "ventricular electrotherapy"
diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm
index 006dbe2af1..c26fda4158 100644
--- a/code/modules/surgery/eye_surgery.dm
+++ b/code/modules/surgery/eye_surgery.dm
@@ -3,7 +3,8 @@
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/fix_eyes, /datum/surgery_step/close)
target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_PRECISE_EYES)
- requires_bodypart_type = 0
+ requires_bodypart_type = BODYPART_ORGANIC
+
//fix eyes
/datum/surgery_step/fix_eyes
name = "fix eyes"
diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm
index 0680dda404..f5b23e6087 100644
--- a/code/modules/surgery/healing.dm
+++ b/code/modules/surgery/healing.dm
@@ -8,7 +8,7 @@
target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
- requires_bodypart_type = FALSE
+ requires_bodypart_type = BODYPART_ORGANIC
replaced_by = /datum/surgery
ignore_clothes = TRUE
var/healing_step_type
diff --git a/code/modules/surgery/lipoplasty.dm b/code/modules/surgery/lipoplasty.dm
index 5a0fd819f1..ecdc5477f1 100644
--- a/code/modules/surgery/lipoplasty.dm
+++ b/code/modules/surgery/lipoplasty.dm
@@ -2,10 +2,13 @@
name = "Lipoplasty"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/cut_fat, /datum/surgery_step/remove_fat, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = BODYPART_ORGANIC
+
/datum/surgery/lipoplasty/can_start(mob/user, mob/living/carbon/target, obj/item/tool)
if(HAS_TRAIT(target, TRAIT_FAT))
return 1
return 0
+
//cut fat
/datum/surgery_step/cut_fat
name = "cut excess fat"
diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm
index 7ef7e4cd7f..34b40258c8 100644
--- a/code/modules/surgery/lobectomy.dm
+++ b/code/modules/surgery/lobectomy.dm
@@ -3,6 +3,7 @@
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/lobectomy, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = BODYPART_ORGANIC
/datum/surgery/lobectomy/can_start(mob/user, mob/living/carbon/target, obj/item/tool)
var/obj/item/organ/lungs/L = target.getorganslot(ORGAN_SLOT_LUNGS)
diff --git a/code/modules/surgery/mechanic_steps.dm b/code/modules/surgery/mechanic_steps.dm
index 9366e585c3..101be7f103 100644
--- a/code/modules/surgery/mechanic_steps.dm
+++ b/code/modules/surgery/mechanic_steps.dm
@@ -85,3 +85,107 @@
display_results(user, target, "You begin to open the hatch holders in [target]'s [parse_zone(target_zone)]...",
"[user] begins to open the hatch holders in [target]'s [parse_zone(target_zone)].",
"[user] begins to open the hatch holders in [target]'s [parse_zone(target_zone)].")
+
+//cut wires
+/datum/surgery_step/cut_wires
+ name = "cut wires"
+ implements = list(
+ TOOL_WIRECUTTER = 100,
+ TOOL_SCALPEL = 75,
+ /obj/item/kitchen/knife = 50,
+ /obj/item = 10) // 10% success with any sharp item.
+ time = 24
+
+/datum/surgery_step/cut_wires/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You begin to cut loose wires in [target]'s [parse_zone(target_zone)]...",
+ "[user] begins to cut loose wires in [target]'s [parse_zone(target_zone)].",
+ "[user] begins to cut loose wires in [target]'s [parse_zone(target_zone)].")
+
+/datum/surgery_step/cut_wires/tool_check(mob/user, obj/item/tool)
+ if(implement_type == /obj/item && !tool.get_sharpness())
+ return FALSE
+ return TRUE
+
+//pry off plating
+/datum/surgery_step/pry_off_plating
+ name = "pry off plating"
+ implements = list(
+ TOOL_CROWBAR = 100,
+ TOOL_HEMOSTAT = 10)
+ time = 24
+
+/datum/surgery_step/pry_off_plating/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ do_sparks(rand(5, 9), FALSE, target.loc)
+ return TRUE
+
+/datum/surgery_step/pry_off_plating/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You begin to pry off [target]'s [parse_zone(target_zone)] plating...",
+ "[user] begins to pry off [target]'s [parse_zone(target_zone)] plating.",
+ "[user] begins to pry off [target]'s [parse_zone(target_zone)] plating.")
+
+//weld plating
+/datum/surgery_step/weld_plating
+ name = "weld plating"
+ implements = list(
+ TOOL_WELDER = 100)
+ time = 24
+
+/datum/surgery_step/weld_plating/tool_check(mob/user, obj/item/tool)
+ if(implement_type == TOOL_WELDER && !tool.use_tool(user, user, 0, volume=50, amount=1))
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/weld_plating/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You begin to weld [target]'s [parse_zone(target_zone)] plating...",
+ "[user] begins to weld [target]'s [parse_zone(target_zone)] plating.",
+ "[user] begins to weld [target]'s [parse_zone(target_zone)] plating.")
+
+//replace wires
+/datum/surgery_step/replace_wires
+ name = "replace wires"
+ implements = list(/obj/item/stack/cable_coil = 100)
+ time = 24
+ var/cableamount = 5
+
+/datum/surgery_step/replace_wires/tool_check(mob/user, obj/item/tool)
+ var/obj/item/stack/cable_coil/coil = tool
+ if(coil.get_amount() < cableamount)
+ to_chat(user, "Not enough cable!")
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/replace_wires/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/obj/item/stack/cable_coil/coil = tool
+ if(coil && !(coil.get_amount()You begin to replace [target]'s [parse_zone(target_zone)] wiring...",
+ "[user] begins to replace [target]'s [parse_zone(target_zone)] wiring.",
+ "[user] begins to replace [target]'s [parse_zone(target_zone)] wiring.")
+
+//add plating
+/datum/surgery_step/add_plating
+ name = "add plating"
+ implements = list(/obj/item/stack/sheet/metal = 100)
+ time = 24
+ var/metalamount = 5
+
+/datum/surgery_step/add_plating/tool_check(mob/user, obj/item/tool)
+ var/obj/item/stack/sheet/metal/plat = tool
+ if(plat.get_amount() < metalamount)
+ to_chat(user, "Not enough metal!")
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/add_plating/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/obj/item/stack/sheet/metal/plat = tool
+ if(plat && !(plat.get_amount()You begin to add plating to [target]'s [parse_zone(target_zone)]...",
+ "[user] begins to add plating to [target]'s [parse_zone(target_zone)].",
+ "[user] begins to add plating to [target]'s [parse_zone(target_zone)].")
\ No newline at end of file
diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm
index 4ce51ae119..85b400d2da 100644
--- a/code/modules/surgery/organ_manipulation.dm
+++ b/code/modules/surgery/organ_manipulation.dm
@@ -2,6 +2,7 @@
name = "organ manipulation"
target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
+ requires_bodypart_type = BODYPART_ORGANIC
requires_real_bodypart = 1
steps = list(
/datum/surgery_step/incise,
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index b42770723b..e3c32ad009 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -306,3 +306,69 @@
var/obj/item/assembly/flash/armimplant/F = new(src)
items_list += F
F.I = src
+
+/////////////////
+
+
+//IPC/Synth Arm//
+
+
+/////////////////
+
+/obj/item/organ/cyberimp/arm/power_cord
+ name = "power cord implant"
+ desc = "An internal power cord hooked up to a battery. Useful if you run on volts."
+ contents = newlist(/obj/item/apc_powercord)
+ zone = "l_arm"
+
+/obj/item/apc_powercord
+ name = "power cord"
+ desc = "An internal power cord hooked up to a battery. Useful if you run on electricity. Not so much otherwise."
+ icon = 'icons/obj/power.dmi'
+ icon_state = "wire1"
+
+/obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag)
+ return ..()
+ user.DelayNextAction(CLICK_CD_MELEE)
+ var/obj/machinery/power/apc/A = target
+ var/mob/living/carbon/human/H = user
+ var/obj/item/organ/stomach/ipc/cell = locate(/obj/item/organ/stomach/ipc) in H.internal_organs
+ if(!cell)
+ to_chat(H, "You try to siphon energy from the [A], but your power cell is gone!")
+ return
+
+ if(A.cell && A.cell.charge > 0)
+ if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
+ to_chat(user, "You are already fully charged!")
+ return
+ else
+ powerdraw_loop(A, H)
+ return
+
+ to_chat(user, "There is no charge to draw from that APC.")
+
+/obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/A, mob/living/carbon/human/H)
+ H.visible_message("[H] inserts a power connector into the [A].", "You begin to draw power from the [A].")
+ while(do_after(H, 10, target = A))
+ if(loc != H)
+ to_chat(H, "You must keep your connector out while charging!")
+ break
+ if(A.cell.charge == 0)
+ to_chat(H, "The [A] doesn't have enough charge to spare.")
+ break
+ A.charging = 1
+ if(A.cell.charge >= 500)
+ do_sparks(1, FALSE, A)
+ H.nutrition += 50
+ A.cell.charge -= 150
+ to_chat(H, "You siphon off some of the stored charge for your own use.")
+ else
+ H.nutrition += A.cell.charge/10
+ A.cell.charge = 0
+ to_chat(H, "You siphon off as much as the [A] can spare.")
+ break
+ if(H.nutrition > NUTRITION_LEVEL_WELL_FED)
+ to_chat(H, "You are now fully charged.")
+ break
+ H.visible_message("[H] unplugs from the [A].", "You unplug from the [A].")
diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm
index 7b55b842dc..3787d4e781 100644
--- a/code/modules/surgery/organs/ears.dm
+++ b/code/modules/surgery/organs/ears.dm
@@ -131,4 +131,31 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
- damage += 0.5 * severity
+ damage += 0.15 * severity
+
+/obj/item/organ/ears/ipc
+ name = "auditory sensors"
+ icon_state = "ears-c"
+ desc = "A pair of microphones intended to be installed in an IPC head, that grant the ability to hear."
+ zone = BODY_ZONE_HEAD
+ slot = ORGAN_SLOT_EARS
+ gender = PLURAL
+ organ_flags = ORGAN_SYNTHETIC
+
+/obj/item/organ/ears/ipc/emp_act(severity)
+ . = ..()
+ if(!owner || . & EMP_PROTECT_SELF)
+ return
+ to_chat(owner, "Alert: Auditory systems corrupted!.")
+ switch(severity)
+ if(1)
+ owner.Jitter(30)
+ owner.Dizzy(30)
+ owner.DefaultCombatKnockdown(80)
+ deaf = 30
+
+ if(2)
+ owner.Jitter(15)
+ owner.Dizzy(15)
+ owner.DefaultCombatKnockdown(40)
+ damage += 0.15 * severity
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 7c28be6883..efceefc131 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -421,6 +421,15 @@
name = "ipc eyes"
icon_state = "cybernetic_eyeballs"
+/obj/item/organ/eyes/ipc/emp_act(severity)
+ . = ..()
+ if(!owner || . & EMP_PROTECT_SELF)
+ return
+ to_chat(owner, "Alert: Perception visuals damaged!")
+ owner.flash_act(visual = 1)
+ if(severity >= 70)
+ owner.adjustOrganLoss(ORGAN_SLOT_EYES, 20)
+
#undef BLURRY_VISION_ONE
#undef BLURRY_VISION_TWO
#undef BLIND_VISION_THREE
diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm
index 2e210bd6e4..953c8b2c1b 100644
--- a/code/modules/surgery/organs/lungs.dm
+++ b/code/modules/surgery/organs/lungs.dm
@@ -521,9 +521,20 @@
failed = FALSE
/obj/item/organ/lungs/ipc
- name = "ipc lungs"
+ name = "ipc cooling system"
icon_state = "lungs-c"
+/obj/item/organ/lungs/ipc/emp_act(severity) //Should probably put it somewhere else later
+ . = ..()
+ if(. & EMP_PROTECT_SELF)
+ return
+ to_chat(owner, "Alert: Critical cooling system failure!")
+ switch(severity)
+ if(1)
+ owner.adjust_bodytemperature(100*TEMPERATURE_DAMAGE_COEFFICIENT)
+ if(2)
+ owner.adjust_bodytemperature(30*TEMPERATURE_DAMAGE_COEFFICIENT)
+
/obj/item/organ/lungs/plasmaman
name = "plasma filter"
desc = "A spongy rib-shaped mass for filtering plasma from the air."
diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm
old mode 100755
new mode 100644
index 44b4f6362a..cabe49db25
--- a/code/modules/surgery/organs/stomach.dm
+++ b/code/modules/surgery/organs/stomach.dm
@@ -89,9 +89,20 @@
desc = "A strange crystal that is responsible for metabolizing the unseen energy force that feeds plasmamen."
/obj/item/organ/stomach/ipc
- name = "ipc stomach"
+ name = "ipc cell"
icon_state = "stomach-ipc"
+/obj/item/organ/stomach/ipc/emp_act(severity)
+ . = ..()
+ if(!owner || . & EMP_PROTECT_SELF)
+ return
+ switch(severity)
+ if(1)
+ owner.nutrition = min(owner.nutrition - 50, 0)
+ to_chat(owner, "Alert: Detected severe battery discharge!")
+ if(2)
+ owner.nutrition = min(owner.nutrition - 100, 0)
+ to_chat(owner, "Alert: Minor battery discharge!")
/obj/item/organ/stomach/ethereal
name = "biological battery"
diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm
index c4e056583c..d3597ba516 100644
--- a/code/modules/surgery/plastic_surgery.dm
+++ b/code/modules/surgery/plastic_surgery.dm
@@ -2,6 +2,8 @@
name = "Plastic surgery"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/reshape_face, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_HEAD)
+ requires_bodypart_type = BODYPART_ORGANIC
+
//reshape_face
/datum/surgery_step/reshape_face
name = "reshape face"
diff --git a/code/modules/surgery/robot_brain_surgery.dm b/code/modules/surgery/robot_brain_surgery.dm
new file mode 100644
index 0000000000..5feca7382f
--- /dev/null
+++ b/code/modules/surgery/robot_brain_surgery.dm
@@ -0,0 +1,51 @@
+/datum/surgery/robot_brain_surgery
+ name = "Reset posibrain logic (Brain surgery)"
+ steps = list(
+ /datum/surgery_step/mechanic_open,
+ /datum/surgery_step/mechanic_unwrench,
+ /datum/surgery_step/pry_off_plating,
+ /datum/surgery_step/prepare_electronics,
+ /datum/surgery_step/fix_robot_brain,
+ /datum/surgery_step/mechanic_close)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ possible_locs = list(BODY_ZONE_HEAD)
+ requires_bodypart_type = BODYPART_ROBOTIC
+ desc = "A surgical procedure that restores the default behavior logic and personality matrix of an IPC posibrain."
+
+/datum/surgery_step/fix_robot_brain
+ name = "fix posibrain (multitool)"
+ implements = list(TOOL_MULTITOOL = 100, TOOL_HEMOSTAT = 35, TOOL_SCREWDRIVER = 15)
+ time = 120 //long and complicated
+
+/datum/surgery/robot_brain_surgery/can_start(mob/user, mob/living/carbon/target, obj/item/tool)
+ var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN)
+ if(!B)
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/fix_robot_brain/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You begin to fix [target]'s posibrain...",
+ "[user] begins to fix [target]'s posibrain.",
+ "[user] begins to perform surgery on [target]'s posibrain.")
+
+/datum/surgery_step/fix_robot_brain/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You succeed in fixing [target]'s posibrain.",
+ "[user] successfully fixes [target]'s posibrain!",
+ "[user] completes the surgery on [target]'s posibrain.")
+ if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed))
+ target.mind.remove_antag_datum(/datum/antagonist/brainwashed)
+ target.setOrganLoss(ORGAN_SLOT_BRAIN, target.getOrganLoss(ORGAN_SLOT_BRAIN) - 60) //we set damage in this case in order to clear the "failing" flag
+ target.cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY) //Lobotomy tier fix cause you can't clone this!
+ return TRUE
+
+/datum/surgery_step/fix_robot_brain/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ if(target.getorganslot(ORGAN_SLOT_BRAIN))
+ display_results(user, target, "You screw up, causing more damage!",
+ "[user] screws up, causing damage to the circuits!",
+ "[user] completes the surgery on [target]'s posibrain.")
+ target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60)
+ target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY)
+ else
+ user.visible_message("[user] suddenly notices that the posibrain [user.p_they()] [user.p_were()] working on is not there anymore.", "You suddenly notice that the posibrain you were working on is not there anymore.")
+ return FALSE
diff --git a/code/modules/surgery/robot_healing.dm b/code/modules/surgery/robot_healing.dm
new file mode 100644
index 0000000000..6355410a79
--- /dev/null
+++ b/code/modules/surgery/robot_healing.dm
@@ -0,0 +1,125 @@
+//Almost copypaste of tend wounds, with some changes
+
+/datum/surgery/robot_healing
+ name = "Repair robotic limbs (basic)"
+ desc = "A surgical procedure that provides repairs and maintenance to robotic limbs. Is slightly more efficient when the patient is severely damaged."
+
+ steps = list(/datum/surgery_step/mechanic_open,
+ /datum/surgery_step/pry_off_plating,
+ /datum/surgery_step/cut_wires,
+ /datum/surgery_step/robot_heal,
+ /datum/surgery_step/mechanic_close)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = BODYPART_ROBOTIC
+ ignore_clothes = TRUE
+ var/antispam = FALSE
+ var/healing_step_type = /datum/surgery_step/robot_heal/basic
+
+/datum/surgery/robot_healing/New(surgery_target, surgery_location, surgery_bodypart)
+ ..()
+ if(healing_step_type)
+ steps = list(/datum/surgery_step/mechanic_open,
+ /datum/surgery_step/pry_off_plating,
+ /datum/surgery_step/cut_wires,
+ healing_step_type,
+ /datum/surgery_step/mechanic_close)
+
+/datum/surgery_step/robot_heal
+ name = "repair body (welder/cable)"
+ implements = list(TOOL_WELDER = 100, /obj/item/stack/cable_coil = 100)
+ repeatable = TRUE
+ time = 15
+ var/healsbrute = FALSE
+ var/healsburn = FALSE
+ var/brutehealing = 0
+ var/burnhealing = 0
+ var/missinghpbonus = 0 //heals an extra point of damager per X missing damage of type (burn damage for burn healing, brute for brute). Smaller Number = More Healing!
+
+/datum/surgery_step/robot_heal/tool_check(mob/user, obj/item/tool)
+ if(implement_type == TOOL_WELDER && !tool.tool_use_check(user, 1))
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/robot_heal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/woundtype
+ if(implement_type == TOOL_WELDER)
+ healsbrute = TRUE
+ healsburn = FALSE
+ woundtype = "dents"
+ else
+ healsbrute = FALSE
+ healsburn = TRUE
+ woundtype = "wiring"
+
+ if(istype(surgery,/datum/surgery/robot_healing))
+ var/datum/surgery/robot_healing/the_surgery = surgery
+ if(!the_surgery.antispam)
+ display_results(user, target, "You attempt to fix some of [target]'s [woundtype].",
+ "[user] attempts to fix some of [target]'s [woundtype].",
+ "[user] attempts to fix some of [target]'s [woundtype].")
+
+/datum/surgery_step/robot_heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
+ if(..())
+ while((healsbrute && target.getBruteLoss() && tool.tool_use_check(user,1)) || (healsburn && target.getFireLoss() && tool))
+ if(!..())
+ break
+
+/datum/surgery_step/robot_heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/umsg = "You succeed in fixing some of [target]'s damage" //no period, add initial space to "addons"
+ var/tmsg = "[user] fixes some of [target]'s damage" //see above
+ var/urhealedamt_brute = 0
+ if(healsbrute)
+ urhealedamt_brute = brutehealing
+ tool.use_tool(target, user, 0, volume=50, amount=1)
+ var/urhealedamt_burn = 0
+ if(healsburn)
+ urhealedamt_burn = burnhealing
+ if(tool)
+ tool.use(1)
+ if(missinghpbonus)
+ if(target.stat != DEAD)
+ urhealedamt_brute += round((target.getBruteLoss()/ missinghpbonus),0.1)
+ urhealedamt_burn += round((target.getFireLoss()/ missinghpbonus),0.1)
+ else //less healing bonus for the dead since they're expected to have lots of damage to begin with (to make TW into defib not TOO simple)
+ urhealedamt_brute += round((target.getBruteLoss()/ (missinghpbonus*5)),0.1)
+ urhealedamt_burn += round((target.getFireLoss()/ (missinghpbonus*5)),0.1)
+ if(!get_location_accessible(target, target_zone))
+ urhealedamt_brute *= 0.55
+ urhealedamt_burn *= 0.55
+ umsg += " as best as you can while they have clothing on"
+ tmsg += " as best as they can while [target] has clothing on"
+ target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn, only_organic = FALSE, only_robotic = TRUE)
+ display_results(user, target, "[umsg].",
+ "[tmsg].",
+ "[tmsg].")
+ if(istype(surgery, /datum/surgery/robot_healing))
+ var/datum/surgery/robot_healing/the_surgery = surgery
+ the_surgery.antispam = TRUE
+ return TRUE
+
+/datum/surgery_step/robot_heal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You screwed up!",
+ "[user] screws up!",
+ "[user] fixes some of [target]'s damage.", TRUE)
+ var/urdamageamt_brute = 0
+ if(healsbrute)
+ urdamageamt_brute = brutehealing * 0.8
+ var/urdamageamt_burn = 0
+ if(healsburn)
+ urdamageamt_burn = burnhealing * 0.8
+ if(missinghpbonus)
+ urdamageamt_brute += round((target.getBruteLoss()/ (missinghpbonus*2)),0.1)
+ urdamageamt_burn += round((target.getFireLoss()/ (missinghpbonus*2)),0.1)
+
+ target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn)
+ return FALSE
+
+/***************************STEPS***************************/
+
+/datum/surgery_step/robot_heal/basic
+ name = "repair damage"
+ brutehealing = 10
+ burnhealing = 10
+ missinghpbonus = 15
\ No newline at end of file
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 8db1156dea..454138a254 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 2c25780671..23f262d7a5 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3400,6 +3400,8 @@
#include "code\modules\surgery\prosthetic_replacement.dm"
#include "code\modules\surgery\remove_embedded_object.dm"
#include "code\modules\surgery\repair_puncture.dm"
+#include "code\modules\surgery\robot_brain_surgery.dm"
+#include "code\modules\surgery\robot_healing.dm"
#include "code\modules\surgery\surgery.dm"
#include "code\modules\surgery\surgery_step.dm"
#include "code\modules\surgery\tools.dm"