diff --git a/code/__DEFINES/misc_defines.dm b/code/__DEFINES/misc_defines.dm index a407bb9657e..d74adff7d5d 100644 --- a/code/__DEFINES/misc_defines.dm +++ b/code/__DEFINES/misc_defines.dm @@ -191,24 +191,25 @@ #define FOAM_REACT_BEFORE_SPREAD (1<<3) //Human Overlays Indexes///////// -#define EYES_OVERLAY_LAYER 50 -#define MISC_LAYER 49 // Handles eye_shine() -> cybernetic eyes, specific eye traits. -#define WING_LAYER 48 -#define WING_UNDERLIMBS_LAYER 47 -#define MUTANTRACE_LAYER 46 -#define TAIL_UNDERLIMBS_LAYER 45 //Tail split-rendering. -#define LIMBS_LAYER 44 -#define MARKINGS_LAYER 43 -#define INTORGAN_LAYER 42 -#define UNDERWEAR_LAYER 41 -#define MUTATIONS_LAYER 40 -#define H_DAMAGE_LAYER 39 -#define UNIFORM_LAYER 38 -#define ID_LAYER 37 -#define HANDS_LAYER 36 //Exists to overlay hands over jumpsuits -#define SHOES_LAYER 35 -#define L_FOOT_BLOOD_LAYER 34 // Blood overlay separation Left-Foot -#define R_FOOT_BLOOD_LAYER 33 // Blood overlay separation Right-Foot +#define EYES_OVERLAY_LAYER 51 +#define MISC_LAYER 50 // Handles eye_shine() -> cybernetic eyes, specific eye traits. +#define WING_LAYER 49 +#define WING_UNDERLIMBS_LAYER 48 +#define MUTANTRACE_LAYER 47 +#define TAIL_UNDERLIMBS_LAYER 46 //Tail split-rendering. +#define LIMBS_LAYER 45 +#define MARKINGS_LAYER 44 +#define INTORGAN_LAYER 43 +#define UNDERWEAR_LAYER 42 +#define MUTATIONS_LAYER 41 +#define H_DAMAGE_LAYER 40 +#define UNIFORM_LAYER 39 +#define ID_LAYER 38 +#define HANDS_LAYER 37 //Exists to overlay hands over jumpsuits +#define SHOES_LAYER 36 +#define L_FOOT_BLOOD_LAYER 35 // Blood overlay separation Left-Foot +#define R_FOOT_BLOOD_LAYER 34 // Blood overlay separation Right-Foot +#define HAND_INTORGAN_LAYER 33 #define GLOVES_LAYER 32 #define L_HAND_BLOOD_LAYER 31 // Blood overlay separation Left-Hand #define R_HAND_BLOOD_LAYER 30 // Blood overlay separation Right-Hand @@ -241,7 +242,7 @@ #define HALO_LAYER 3 //blood cult ascended halo, because there's currently no better solution for adding/removing #define FIRE_LAYER 2 //If you're on fire #define FROZEN_LAYER 1 -#define TOTAL_LAYERS 50 +#define TOTAL_LAYERS 51 ///Access Region Codes/// #define REGION_ALL 0 diff --git a/code/game/objects/items/stacks/synthetic_skin.dm b/code/game/objects/items/stacks/synthetic_skin.dm new file mode 100644 index 00000000000..82b1378dc6c --- /dev/null +++ b/code/game/objects/items/stacks/synthetic_skin.dm @@ -0,0 +1,44 @@ +/obj/item/stack/synthetic_skin + name = "level-1 synthetic skin plate" + desc = "A sheet of level-1 synthetic skin plating. Used as a cheap covering for cybernetic organs, is able to match the colour of the limb but not the texture." + icon = 'icons/obj/surgery.dmi' + icon_state = "skin_1" + w_class = WEIGHT_CLASS_SMALL + singular_name = "skin plate" + max_amount = 10 + merge_type = /obj/item/stack/synthetic_skin + var/skin_level = 1 + +/obj/item/stack/synthetic_skin/attack__legacy__attackchain(mob/living/M as mob, mob/user as mob) + if(!ishuman(M) || !istype(user)) + return FALSE + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/external_limb = H.get_organ(user.zone_selected) + if(external_limb) + user.visible_message("[user] starts to apply [src] on [H]'s [external_limb.name]...") + if(!do_mob(user, H, 5 SECONDS)) + return FALSE + use(1) + if(external_limb.apply_augmented_skin(skin_level)) + user.visible_message("[user] applies some [src] on [H]'s [external_limb.name].") + return TRUE + else + to_chat(user, "You fail to apply a better skin cover to [H]'s [external_limb.name].") + return FALSE + +/obj/item/stack/synthetic_skin/level_2 + name = "level-2 synthetic skin patch" + desc = "A sealed patch of synthetic skin. An improvement over the basic version, more water resistant and less prone to peeling off." + icon_state = "skin_2" + merge_type = /obj/item/stack/synthetic_skin/level_2 + singular_name = "skin patch" + skin_level = 2 + + +/obj/item/stack/synthetic_skin/level_3 + name = "level-3 synthetic skin foam" + desc = "A nanite foam injector meeting the requirements of level-3 synthetic skin. The best one can buy, best used to hide major cybernetic alterations, for beauty or for infiltration." + icon_state = "skin_3" + merge_type = /obj/item/stack/synthetic_skin/level_3 + singular_name = "nanite foam" + skin_level = 3 diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index f9aaef94fb6..4cc16ad2a2b 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -155,6 +155,7 @@ new /obj/item/stack/cable_coil(src) new /obj/item/stack/cable_coil(src) new /obj/item/robotanalyzer(src) + new /obj/item/stack/synthetic_skin(src, 3) /obj/item/storage/firstaid/machine/empty/populate_contents() return diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 5015bf2d994..5411923516d 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -875,3 +875,11 @@ emp_act to_contaminate -= to_contaminate[1] for(var/atom/thing in to_contaminate) thing.AddComponent(/datum/component/radioactive, intensity, source, emission_type) + +/mob/living/carbon/human/proc/peel_off_synthetic_skin() + var/obj/item/organ/external/external_limb = get_organ(zone_selected) + if(external_limb && external_limb.augmented_skin_cover_level) + visible_message("[src] begins to pull at their skin...") + if(!do_mob(src, src, 5 SECONDS)) + return + external_limb.break_augmented_skin(TRUE) diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index d44871697cd..711fa84aae2 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -1356,6 +1356,20 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) overlays_standing[INTORGAN_LAYER] = standing apply_overlay(INTORGAN_LAYER) + update_hand_int_organs() + +/mob/living/carbon/human/proc/update_hand_int_organs() + remove_overlay(HAND_INTORGAN_LAYER) + + var/list/standing = list() + for(var/organ in internal_organs) + var/obj/item/organ/internal/I = organ + var/extra_render = I.extra_render() + if(extra_render) + standing += extra_render + + overlays_standing[HAND_INTORGAN_LAYER] = standing + apply_overlay(HAND_INTORGAN_LAYER) /mob/living/carbon/human/handle_transform_change() ..() diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 7f41a8ef6e1..a924c29823d 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -294,7 +294,11 @@ // End BS12 momentum-transfer code. /mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE) - if(user == src || anchored) + if(user == src && ishuman(user)) + var/mob/living/carbon/human/self = user + INVOKE_ASYNC(self, TYPE_PROC_REF(/mob/living/carbon/human, peel_off_synthetic_skin)) + return + if(anchored) return FALSE if(!(status_flags & CANPUSH)) return FALSE diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 3369b429aee..33a0c93b6a4 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -174,6 +174,39 @@ build_path = /obj/item/stack/nanopaste category = list("Medical") +/datum/design/skin_1 + name = "level-1 synthetic skin plate" + desc = "A sheet of level-1 synthetic skin plating. Used as a cheap covering for cybernetic organs, is able to match the colour of the limb but not the texture." + id = "skin_1" + req_tech = list("biotech" = 1, "materials" = 1) + build_type = PROTOLATHE | MECHFAB + construction_time = 20 + materials = list(MAT_METAL = 1000, MAT_GLASS = 500) + build_path = /obj/item/stack/synthetic_skin + category = list("Medical") + +/datum/design/skin_2 + name = "level-2 synthetic skin patch" + desc = "A sealed patch of synthetic skin. An improvement over the basic version, more water resistant and less prone to peeling off." + id = "skin_2" + req_tech = list("biotech" = 5, "materials" = 5) + build_type = PROTOLATHE | MECHFAB + construction_time = 40 + materials = list(MAT_METAL = 2000, MAT_GLASS = 1000, MAT_TITANIUM = 250) + build_path = /obj/item/stack/synthetic_skin/level_2 + category = list("Medical") + +/datum/design/skin_3 + name = "level-3 synthetic skin foam" + desc = "A nanite foam injector meeting the requirements of level-3 synthetic skin. The best one can buy, best used to hide major cybernetic alterations, for beauty or for infiltration." + id = "skin_3" + req_tech = list("biotech" = 7, "materials" = 7) + build_type = PROTOLATHE | MECHFAB + construction_time = 60 + materials = list(MAT_METAL = 2500, MAT_GLASS = 2000, MAT_TITANIUM = 500, MAT_BLUESPACE = 250) + build_path = /obj/item/stack/synthetic_skin/level_3 + category = list("Medical") + /datum/design/reagent_scanner name = "Reagent Scanner" desc = "A device for identifying chemicals." diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index d04f2b78897..a8cb43c31a3 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -14,6 +14,7 @@ var/obj/item/holder = null // You can use this var for item path, it would be converted into an item on New() + /obj/item/organ/internal/cyberimp/arm/New() ..() if(ispath(holder)) @@ -66,6 +67,34 @@ Retract() ..() +/obj/item/organ/internal/cyberimp/arm/proc/get_overlay_state(image_layer) + return "[augment_icon][parent_organ == BODY_ZONE_L_ARM ? "_left" : "_right"]" + +/obj/item/organ/internal/cyberimp/arm/render() + . = ..() + if(!.) + return + + var/mutable_appearance/arm_overlay = mutable_appearance( + icon = augment_state, + icon_state = get_overlay_state(), + layer = -INTORGAN_LAYER, + ) + return arm_overlay + +/obj/item/organ/internal/cyberimp/arm/extra_render() + . = ..() + if(!.) + return + var/mutable_appearance/hand_overlay = mutable_appearance( + icon = augment_state, + icon_state = "[get_overlay_state()]_hand", + layer = -HAND_INTORGAN_LAYER, + ) + return hand_overlay + + + /obj/item/organ/internal/cyberimp/arm/proc/retract_to_linked_implant() SIGNAL_HANDLER if(holder && holder == owner.get_active_hand()) @@ -231,6 +260,8 @@ contents = newlist(/obj/item/screwdriver/cyborg, /obj/item/wrench/cyborg, /obj/item/weldingtool/largetank/cyborg, /obj/item/crowbar/cyborg, /obj/item/wirecutters/cyborg, /obj/item/multitool/cyborg) actions_types = list(/datum/action/item_action/organ_action/toggle/utility_belt) + augment_icon = "toolkit_engi" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/toolset/l parent_organ = "l_arm" @@ -253,6 +284,8 @@ origin_tech = "materials=5;engineering=5;plasmatech=5;powerstorage=4;abductor=3" contents = newlist(/obj/item/screwdriver/abductor, /obj/item/wirecutters/abductor, /obj/item/crowbar/abductor, /obj/item/wrench/abductor, /obj/item/weldingtool/abductor, /obj/item/multitool/abductor) actions_types = list(/datum/action/item_action/organ_action/toggle/abductor_belt) + augment_icon = "toolkit_engi" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/toolset_abductor/l parent_organ = "l_arm" @@ -268,6 +301,8 @@ origin_tech = "materials=5;engineering=5;biotech=5;powerstorage=4;abductor=2" contents = newlist(/obj/item/mop/advanced/abductor, /obj/item/soap/syndie/abductor, /obj/item/lightreplacer/bluespace/abductor, /obj/item/holosign_creator/janitor, /obj/item/melee/flyswatter/abductor, /obj/item/reagent_containers/spray/cleaner/safety/abductor) actions_types = list(/datum/action/item_action/organ_action/toggle/abductor_belt) + augment_icon = "toolkit_jani" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/janitorial_abductor/l parent_organ = "l_arm" @@ -279,6 +314,8 @@ origin_tech = "materials=5;engineering=5;plasmatech=5;powerstorage=4;abductor=2" contents = newlist(/obj/item/retractor/alien, /obj/item/hemostat/alien, /obj/item/bonesetter/alien, /obj/item/scalpel/laser/alien, /obj/item/circular_saw/alien, /obj/item/bonegel/alien, /obj/item/fix_o_vein/alien, /obj/item/surgicaldrill/alien) actions_types = list(/datum/action/item_action/organ_action/toggle/abductor_belt) + augment_icon = "toolkit_med" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/surgical_abductor/l parent_organ = "l_arm" @@ -297,8 +334,11 @@ name = "integrated medical beamgun" desc = "A cybernetic implant that allows the user to project a healing beam from their hand." contents = newlist(/obj/item/gun/medbeam) + icon_state = "toolkit_surgical" origin_tech = "materials=5;combat=2;biotech=5;powerstorage=4;syndicate=1" actions_types = list(/datum/action/item_action/organ_action/toggle/medibeam) + augment_icon = "toolkit_med" + do_extra_render = TRUE /datum/action/item_action/organ_action/toggle/flash button_icon = 'icons/obj/device.dmi' @@ -310,6 +350,8 @@ contents = newlist(/obj/item/flash/armimplant) origin_tech = "materials=4;combat=3;biotech=4;magnets=4;powerstorage=3" actions_types = list(/datum/action/item_action/organ_action/toggle/flash) + augment_icon = "toolkit" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/flash/New() ..() @@ -322,6 +364,8 @@ desc = "An illegal combat implant that allows the user to administer disabling shocks from their arm." contents = newlist(/obj/item/borg/stun) origin_tech = "materials=3;combat=5;biotech=4;powerstorage=4;syndicate=3" + augment_icon = "toolkit" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/combat name = "combat cybernetics implant" @@ -355,6 +399,8 @@ contents = newlist(/obj/item/retractor/augment, /obj/item/hemostat/augment, /obj/item/cautery/augment, /obj/item/bonesetter/augment, /obj/item/scalpel/augment, /obj/item/circular_saw/augment, /obj/item/bonegel/augment, /obj/item/fix_o_vein/augment, /obj/item/surgicaldrill/augment) origin_tech = "materials=3;engineering=3;biotech=3;programming=2;magnets=3" actions_types = list(/datum/action/item_action/organ_action/toggle/dufflebag_med) + augment_icon = "toolkit_med" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/surgery/l parent_organ = "l_arm" @@ -371,6 +417,8 @@ contents = newlist(/obj/item/mop/advanced, /obj/item/soap, /obj/item/lightreplacer, /obj/item/holosign_creator/janitor, /obj/item/melee/flyswatter, /obj/item/reagent_containers/spray/cleaner/safety) origin_tech = "materials=3;engineering=4;biotech=3" actions_types = list(/datum/action/item_action/organ_action/toggle/janibelt) + augment_icon = "toolkit_jani" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/janitorial/l parent_organ = "l_arm" @@ -401,6 +449,8 @@ contents = newlist(/obj/item/plant_analyzer, /obj/item/cultivator, /obj/item/hatchet, /obj/item/shovel/spade, /obj/item/reagent_containers/spray/weedspray, /obj/item/reagent_containers/spray/pestspray) origin_tech = "materials=3;engineering=4;biotech=3" actions_types = list(/datum/action/item_action/organ_action/toggle/botanybelt) + augment_icon = "toolkit_hydro" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/botanical/l parent_organ = "l_arm" @@ -498,6 +548,8 @@ contents = newlist(/obj/item/melee/classic_baton) actions_types = list(/datum/action/item_action/organ_action/toggle/telebaton) + augment_icon = "toolkit" + do_extra_render = TRUE /datum/action/item_action/organ_action/toggle/advanced_mop button_icon = 'icons/obj/janitor.dmi' @@ -506,9 +558,12 @@ /obj/item/organ/internal/cyberimp/arm/advmop name = "advanced mop implant" desc = "Advanced mop implant. Does what it says on the tin" // A better description + icon_state = "toolkit_janitor" contents = newlist(/obj/item/mop/advanced) actions_types = list(/datum/action/item_action/organ_action/toggle/advanced_mop) + augment_icon = "toolkit_jani" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/cargo name = "integrated cargo implant" @@ -620,6 +675,8 @@ actions_types = list(/datum/action/item_action/organ_action/toggle/razorwire) origin_tech = "combat=5;biotech=5;syndicate=2" stealth_level = 1 // Hidden from health analyzers + augment_icon = "razor" // Note: By default the autosurgeons apply the highest level of cover plating. + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/razorwire/examine_more(mob/user) . = ..() @@ -674,6 +731,8 @@ contents = newlist(/obj/item/gun/projectile/revolver/doublebarrel/shell_launcher) icon_state = "shell_cannon" actions_types = list(/datum/action/item_action/organ_action/toggle/shell_cannon) + augment_icon = "razor" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/shell_launcher/emp_act(severity) if(!owner) @@ -737,6 +796,8 @@ contents = newlist(/obj/item/shield/v1_arm) actions_types = list(/datum/action/item_action/organ_action/toggle/v1_arm) + augment_icon = "v1_arm" + do_extra_render = TRUE var/disabled = FALSE /obj/item/organ/internal/cyberimp/arm/v1_arm/emp_act(severity) @@ -757,6 +818,15 @@ return FALSE ..() +/obj/item/organ/internal/cyberimp/arm/v1_arm/render() + if(isvox(owner)) + augment_icon = "v1_arm_vox" + else if(isdrask(owner)) + augment_icon = "v1_arm_drask" + else + augment_icon = "v1_arm" + return ..() + /obj/item/shield/v1_arm name = "vortex feedback arm" desc = "A modification to a users arm, allowing them to use a vortex core energy feedback, to parry, reflect, and even empower projectile attacks. Rumors that it runs on the user's blood are unconfirmed." @@ -865,6 +935,7 @@ slot = "l_arm_device" actions_types = list() + augment_icon = "strongarm" var/datum/martial_art/muscle_implant/muscle_implant /obj/item/organ/internal/cyberimp/arm/muscle/Initialize(mapload) @@ -962,6 +1033,8 @@ contents = newlist(/obj/item/melee/mantis_blade/syndicate) icon_state = "syndie_mantis" icon = 'icons/obj/weapons/melee.dmi' + augment_icon = "razor" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/syndie_mantis/l parent_organ = "l_arm" @@ -973,6 +1046,8 @@ contents = newlist(/obj/item/melee/mantis_blade/nt) icon_state = "mantis" icon = 'icons/obj/weapons/melee.dmi' + augment_icon = "razor" + do_extra_render = TRUE /obj/item/organ/internal/cyberimp/arm/nt_mantis/l parent_organ = "l_arm" diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 370e8aa97f9..730f50d7606 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -6,6 +6,7 @@ var/implant_overlay var/crit_fail = FALSE //Used by certain implants to disable them. tough = TRUE // Immune to damage + augment_state ='icons/mob/human_races/robotic.dmi' /obj/item/organ/internal/cyberimp/New(mob/M = null) . = ..() @@ -330,6 +331,8 @@ emp_proof = TRUE actions_types = list(/datum/action/item_action/organ_action/toggle/sensory_enhancer) origin_tech = "combat=6;biotech=6;syndicate=4" + augment_icon = "sandy" + always_show_augment = TRUE // A bit too big and bright to hide with synthetic skin. ///The icon state used for the on mob sprite. Default is sandy. Drask and vox have their own unique sprites var/custom_mob_sprite = "sandy" COOLDOWN_DECLARE(sensory_enhancer_cooldown) @@ -363,13 +366,16 @@ REMOVE_TRAIT(M, TRAIT_MEPHEDRONE_ADAPTED, "[UID()]") /obj/item/organ/internal/cyberimp/brain/sensory_enhancer/render() + . = ..() + if(!.) + return if(isvox(owner)) custom_mob_sprite = "vox_sandy" else if(isdrask(owner)) custom_mob_sprite = "drask_sandy" else custom_mob_sprite = "sandy" - var/mutable_appearance/our_MA = mutable_appearance('icons/mob/human_races/robotic.dmi', icon_state, layer = -INTORGAN_LAYER) + var/mutable_appearance/our_MA = mutable_appearance(augment_state, custom_mob_sprite, layer = -INTORGAN_LAYER) return our_MA /obj/item/organ/internal/cyberimp/brain/sensory_enhancer/emp_act(severity) @@ -581,6 +587,14 @@ slot = "breathing_tube" w_class = WEIGHT_CLASS_TINY origin_tech = "materials=2;biotech=3" + augment_icon = "breathing_tube" + +/obj/item/organ/internal/cyberimp/mouth/breathing_tube/render() + . = ..() + if(!.) + return + var/mutable_appearance/our_MA = mutable_appearance(augment_state, augment_icon, layer = -INTORGAN_LAYER) + return our_MA /obj/item/organ/internal/cyberimp/mouth/breathing_tube/emp_act(severity) if(emp_proof) @@ -607,6 +621,7 @@ var/disabled_by_emp = FALSE slot = "stomach" origin_tech = "materials=2;powerstorage=2;biotech=2" + augment_icon = "nutripump" /obj/item/organ/internal/cyberimp/chest/nutriment/examine(mob/user) . = ..() @@ -646,6 +661,14 @@ synthesizing = FALSE addtimer(CALLBACK(src, PROC_REF(emp_cool)), 60 SECONDS) +/obj/item/organ/internal/cyberimp/chest/nutriment/render() + . = ..() + if(!.) + return + var/mutable_appearance/our_MA = mutable_appearance(augment_state, augment_icon, layer = -INTORGAN_LAYER) + return our_MA + + /obj/item/organ/internal/cyberimp/chest/nutriment/plus name = "Nutriment pump implant PLUS" desc = "This implant will synthesize a small amount of nutriment and pumps it directly into your bloodstream when you are hungry." @@ -653,6 +676,7 @@ hunger_threshold = NUTRITION_LEVEL_HUNGRY poison_amount = 10 origin_tech = "materials=4;powerstorage=3;biotech=3" + augment_icon = "nutripump_adv" /obj/item/organ/internal/cyberimp/chest/nutriment/hardened name = "hardened nutriment pump implant" @@ -669,6 +693,7 @@ implant_overlay = null origin_tech = "materials=5;programming=5;biotech=6" slot = "heartdrive" + augment_icon = "reviver" /// How long the implant will go on cooldown for once the user has exited crit, in seconds. var/revive_cost = 0 SECONDS /// Are we in the progress of healing the user? @@ -692,6 +717,13 @@ . = ..() desc += " The implant has been hardened. It is invulnerable to EMPs." +/obj/item/organ/internal/cyberimp/chest/reviver/render() + . = ..() + if(!.) + return + var/mutable_appearance/our_MA = mutable_appearance(augment_state, augment_icon, layer = -INTORGAN_LAYER) + return our_MA + /obj/item/organ/internal/cyberimp/chest/reviver/dead_process() try_heal() // Allows implant to work even on dead people diff --git a/code/modules/surgery/organs/autosurgeon.dm b/code/modules/surgery/organs/autosurgeon.dm index 177ab68ed39..a3121e6998a 100644 --- a/code/modules/surgery/organs/autosurgeon.dm +++ b/code/modules/surgery/organs/autosurgeon.dm @@ -110,6 +110,11 @@ name = "suspicious implant autosurgeon" icon_state = "syndicate_autoimplanter" +/obj/item/autosurgeon/organ/syndicate/attack_self__legacy__attackchain(mob/user) + if(storedorgan && uses && storedorgan.is_robotic()) // Helps keep the syndicate ones hidden. One can peel them off if they want them to be visable. + storedorgan.self_augmented_skin_level = 3 + return ..() + /obj/item/autosurgeon/organ/syndicate/oneuse uses = 1 diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 2e020896125..c8382c1f7f6 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -63,6 +63,8 @@ var/splinted_count = 0 //Time when this organ was last splinted ///If this organ's max HP is reduced by the IPC magnetic joints implant var/fragile = FALSE + ///The level of false skin used to cover robotic organs on the limb. Updated when too damaged, when installed, or when an organ with it is installed. + var/augmented_skin_cover_level = 0 /obj/item/organ/external/necrotize(update_sprite=TRUE, ignore_vital_death = FALSE) if(status & (ORGAN_ROBOT|ORGAN_DEAD)) @@ -241,6 +243,8 @@ check_for_internal_bleeding(brute) // See if we need to inflict severe burns check_for_burn_wound(burn) + // See what happens to the skin covers. + check_skin_covers(brute, burn) // Threshold needed to have a chance of hurting internal bits with something sharp #define LIMB_SHARP_THRESH_INT_DMG 5 // Threshold needed to have a chance of hurting internal bits @@ -538,6 +542,15 @@ Note that amputating the affected organ does in fact remove the infection from t if(burn_dam >= min_broken_damage && prob(damage * max(owner.bodytemperature / BODYTEMP_HEAT_DAMAGE_LIMIT, 1))) cause_burn_wound(update_health) +/obj/item/organ/external/proc/check_skin_covers(brute, burn) + if(!augmented_skin_cover_level || augmented_skin_cover_level == 4) // No need to run it if they don't have it, or if it is unbreakable. + return + if(((brute_dam >= min_broken_damage && brute) || (burn_dam >= min_broken_damage && burn)) && augmented_skin_cover_level == 1) // We want this at 50% for arms / feet which have low max hp, 35% for head / chest + break_augmented_skin() + return + if((brute_dam >= max_damage * (augmented_skin_cover_level / 3) && brute) || (burn_dam >= max_damage * (augmented_skin_cover_level / 3) && burn)) // 66% for level 2, 100% for level 3 + break_augmented_skin() + // new damage icon system // returns just the brute/burn damage code /obj/item/organ/external/proc/damage_state_text() @@ -814,6 +827,31 @@ Note that amputating the affected organ does in fact remove the infection from t if(update_health) owner.updatehealth("burn wound fixed") +/obj/item/organ/external/proc/break_augmented_skin(intentional = FALSE) + augmented_skin_cover_level = 0 + if(!owner) + return + playsound(owner.loc, 'sound/items/poster_ripped.ogg', 50, TRUE) + if(!intentional) + owner.visible_message("Synthetic skin shatters and flakes off [owner]'s [name]!", + "Your synthetic skin fails on your [name]!") + else + owner.visible_message("[owner] tears their synthetic skin off their [name], exposing the cybernetics beneath!", + "You peel your synthetic skin off your cybernetics on your [name].") + if(ishuman(owner)) + var/mob/living/carbon/human/refreshing = owner + refreshing.update_int_organs() + +/obj/item/organ/external/proc/apply_augmented_skin(applied_level) + if(applied_level + is_robotic() <= augmented_skin_cover_level) // Don't do anything if the application matches or is below the current level. + return FALSE + augmented_skin_cover_level = (applied_level + is_robotic()) // Robotic limbs get an extra level of protection. + if(!owner || !ishuman(owner)) + return TRUE + var/mob/living/carbon/human/refreshing = owner + refreshing.update_int_organs() + return TRUE + /obj/item/organ/external/robotize(company, make_tough = FALSE, convert_all = TRUE) ..() //robot limbs take reduced damage @@ -821,6 +859,8 @@ Note that amputating the affected organ does in fact remove the infection from t dismember_at_max_damage = TRUE else tough = TRUE + if(augmented_skin_cover_level) + apply_augmented_skin(augmented_skin_cover_level) // Raises it a level // Robot parts also lack bones // This is so surgery isn't kaput, let's see how this does encased = null diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 71656876a6e..e24d5bf3a58 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -20,6 +20,16 @@ var/is_xeno_organ = FALSE /// Does this organ give a warning upon being inserted? var/warning = FALSE + /// Does this organ show outside the mob, and what is the icon state? + var/augment_state = null + /// Does this organ actually have a sprite for it being on the arm? And what is the path of it. + var/augment_icon = null + /// Does this organ have a extra render mechanic? + var/do_extra_render = FALSE + /// Does this organ ignore skin covers? + var/always_show_augment = FALSE + /// Does this organ have augmented skin to apply to the user on install? If so, apply it to the user and remove it. + var/self_augmented_skin_level = 0 /obj/item/organ/internal/New(mob/living/carbon/holder) ..() @@ -49,6 +59,8 @@ . = ..() if(is_xeno_organ) . += "It looks like it would replace \the [slot]." + if(self_augmented_skin_level) + . += "It seems to have level-[self_augmented_skin_level] synthetic skin applied." /obj/item/organ/internal/proc/insert(mob/living/carbon/M, special = 0, dont_remove_slot = 0) if(!iscarbon(M) || owner == M) @@ -80,6 +92,9 @@ stack_trace("[src] attempted to insert into a [parent_organ], but [parent_organ] wasn't an organ! [atom_loc_line(M)]") else parent.internal_organs |= src + if(self_augmented_skin_level) + parent.apply_augmented_skin(self_augmented_skin_level) + self_augmented_skin_level = 0 loc = null for(var/X in actions) var/datum/action/A = X @@ -218,7 +233,27 @@ // Rendering! /obj/item/organ/internal/proc/render() - return + if(!augment_state || !augment_icon || !owner) + return FALSE + var/obj/item/organ/external/our_parent = owner.get_organ(parent_organ) + if(!our_parent) // I don't know how you pulled that off, let us be safe. + return FALSE + if(our_parent.augmented_skin_cover_level && !always_show_augment) + return FALSE + + return TRUE + +// An extra render used in certain situations. +/obj/item/organ/internal/proc/extra_render() + if(!augment_state || !augment_icon || !owner || !do_extra_render) + return FALSE + var/obj/item/organ/external/our_parent = owner.get_organ(parent_organ) + if(!our_parent) // I don't know how you pulled that off, let us be safe. + return FALSE + if(our_parent.augmented_skin_cover_level && !always_show_augment) + return FALSE + + return TRUE /obj/item/organ/internal/attack__legacy__attackchain(mob/living/carbon/M, mob/user) if(M == user && ishuman(user)) @@ -235,6 +270,16 @@ else ..() +/obj/item/organ/internal/attackby__legacy__attackchain(obj/item/I, mob/user, params) + if(is_robotic() && istype(I, /obj/item/stack/synthetic_skin)) + var/obj/item/stack/synthetic_skin/skin = I + skin.use(1) + self_augmented_skin_level = skin.skin_level + to_chat(user, "You apply [skin] to [src].") + return + return ..() + + /**************************************************** INTERNAL ORGANS DEFINES ****************************************************/ diff --git a/icons/mob/human_races/robotic.dmi b/icons/mob/human_races/robotic.dmi index 7fe9926b98a..27ceb7e1978 100644 Binary files a/icons/mob/human_races/robotic.dmi and b/icons/mob/human_races/robotic.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index b54b4652cc7..051247ebb3d 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/paradise.dme b/paradise.dme index 553f0cd42d0..5ba9d08c69b 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1373,6 +1373,7 @@ #include "code\game\objects\items\stacks\seaweed.dm" #include "code\game\objects\items\stacks\stack.dm" #include "code\game\objects\items\stacks\stack_recipe.dm" +#include "code\game\objects\items\stacks\synthetic_skin.dm" #include "code\game\objects\items\stacks\telecrystal.dm" #include "code\game\objects\items\stacks\sheets\glass.dm" #include "code\game\objects\items\stacks\sheets\leather.dm"