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"