diff --git a/baystation12.dme b/baystation12.dme index ef206c8cc5..76a77ca0a2 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1650,11 +1650,10 @@ #include "code\modules\surgery\eye.dm" #include "code\modules\surgery\face.dm" #include "code\modules\surgery\generic.dm" -#include "code\modules\surgery\headreattach.dm" #include "code\modules\surgery\implant.dm" +#include "code\modules\surgery\limb_reattach.dm" #include "code\modules\surgery\organs_internal.dm" #include "code\modules\surgery\other.dm" -#include "code\modules\surgery\robolimbs.dm" #include "code\modules\surgery\slimes.dm" #include "code\modules\surgery\surgery.dm" #include "code\modules\tables\flipping.dm" diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 8c6be59f71..645bfa5bcc 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -390,7 +390,8 @@ infected = "Acute Infection++:" if (INFECTION_LEVEL_THREE to INFINITY) infected = "Septic:" - + if(e.rejecting) + infected += "(being rejected)" if (e.implants.len) var/unknown_body = 0 for(var/I in e.implants) @@ -406,7 +407,7 @@ if(!(e.status & ORGAN_DESTROYED)) dat += "[e.name][e.burn_dam][e.brute_dam][robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]" else - dat += "[e.name]--Not Found" + dat += "[e.name]--Not [e.is_stump() ? "Found" : "Attached Completely"]" dat += "" for(var/obj/item/organ/i in occ["internal_organs"]) @@ -431,6 +432,8 @@ infection = "Acute Infection+:" if (INFECTION_LEVEL_TWO + 300 to INFINITY) infection = "Acute Infection++:" + if(i.rejecting) + infection += "(being rejected)" dat += "" dat += "[i.name]N/A[i.damage][infection]:[mech]" diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 563df642ef..8529e6db2e 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -68,6 +68,7 @@ name = "torso" desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell." icon_state = "chest" + part = list("groin","chest") construction_time = 350 construction_cost = list(DEFAULT_WALL_MATERIAL=40000) var/wires = 0.0 @@ -77,6 +78,7 @@ name = "head" desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals." icon_state = "head" + part = list("head") construction_time = 350 construction_cost = list(DEFAULT_WALL_MATERIAL=25000) var/obj/item/device/flash/flash1 = null diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 0f8cbcc10f..61968c7692 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -628,3 +628,15 @@ new /obj/item/weapon/light/tube(src) for(var/i = 0; i < 7; i++) new /obj/item/weapon/light/bulb(src) + +/obj/item/weapon/storage/box/freezer + name = "portable freezer" + desc = "This nifty shock-resistant device will keep your 'groceries' nice and non-spoiled." + icon = 'icons/obj/storage.dmi' + icon_state = "portafreezer" + item_state = "medicalpack" + storage_slots=7 + max_w_class = 3 + can_hold = list(/obj/item/organ, /obj/item/weapon/reagent_containers/food, /obj/item/weapon/reagent_containers/glass) + max_storage_space = 21 + use_to_pickup = 1 // for picking up broken bulbs, not that most people will try \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 52ba116d43..5f9527b93b 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -118,6 +118,7 @@ b_skin = blue force_update_limbs() + update_body() return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) @@ -127,6 +128,7 @@ s_tone = tone force_update_limbs() + update_body() return 1 /mob/living/carbon/human/proc/update_dna() diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 6c995d75e0..a198daa112 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -178,8 +178,13 @@ miss_type = 2 // See what attack they use + var/possible_moves = list() var/datum/unarmed_attack/attack = null - for(var/datum/unarmed_attack/u_attack in H.species.unarmed_attacks) + for(var/part in list("l_hand","r_hand","l_foot","r_foot","head")) + var/obj/item/organ/external/E = H.get_organ(part) + possible_moves |= E.species.unarmed_attacks + + for(var/datum/unarmed_attack/u_attack in possible_moves) if(!u_attack.is_usable(H, src, hit_zone)) continue else diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 382ff909b3..8b13178adf 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -234,15 +234,13 @@ var/global/list/damage_icon_parts = list() var/hulk = (HULK in src.mutations) var/skeleton = (SKELETON in src.mutations) - var/g = (gender == FEMALE ? "f" : "m") - //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. //Create a new, blank icon for our mob to use. if(stand_icon) qdel(stand_icon) stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") - var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]" + var/icon_key = "" var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"] if(eyes) @@ -260,7 +258,12 @@ var/global/list/damage_icon_parts = list() icon_key += "3" else icon_key += "1" - + if(part) + icon_key += "[part.species.race_key]" + icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" + icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" + if(part.s_col) + icon_key += "[rgb(part.s_col[1],part.s_col[2],part.s_col[3])]" icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" var/icon/base_icon @@ -894,22 +897,22 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/proc/get_tail_icon() var/icon_key = "[species.race_key][r_skin][g_skin][b_skin]" - + var/icon/tail_icon = tail_icon_cache[icon_key] - if(!tail_icon) - + if(!tail_icon) + //generate a new one tail_icon = new/icon(icon = (species.tail_animation? species.tail_animation : 'icons/effects/species.dmi')) tail_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - + tail_icon_cache[icon_key] = tail_icon - + return tail_icon /mob/living/carbon/human/proc/set_tail_state(var/t_state) var/image/tail_overlay = overlays_standing[TAIL_LAYER] - + if(tail_overlay && species.tail_animation) tail_overlay.icon_state = t_state return tail_overlay @@ -919,30 +922,30 @@ var/global/list/damage_icon_parts = list() //Update this if the ability to flick() images or make looping animation start at the first frame is ever added. /mob/living/carbon/human/proc/animate_tail_once(var/update_icons=1) var/t_state = "[species.tail]_once" - + var/image/tail_overlay = overlays_standing[TAIL_LAYER] if(tail_overlay && tail_overlay.icon_state == t_state) return //let the existing animation finish - + tail_overlay = set_tail_state(t_state) if(tail_overlay) spawn(15) //check that the animation hasn't changed in the meantime if(overlays_standing[TAIL_LAYER] == tail_overlay && tail_overlay.icon_state == t_state) animate_tail_stop() - + if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_start(var/update_icons=1) set_tail_state("[species.tail]_slow[rand(0,9)]") - + if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_fast(var/update_icons=1) set_tail_state("[species.tail]_loop[rand(0,9)]") - + if(update_icons) update_icons() @@ -951,14 +954,14 @@ var/global/list/damage_icon_parts = list() set_tail_state("[species.tail]_idle[rand(0,9)]") else set_tail_state("[species.tail]_static") - - + + if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1) set_tail_state("[species.tail]_static") - + if(update_icons) update_icons() diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 06dd521f64..405c058a23 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -23,6 +23,8 @@ var/list/organ_cache = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, // links chemical IDs to number of ticks for which they'll stay in the blood germ_level = 0 + var/datum/dna/dna + var/datum/species/species /obj/item/organ/proc/update_health() return @@ -34,6 +36,12 @@ var/list/organ_cache = list() max_damage = min_broken_damage * 2 if(istype(holder)) src.owner = holder + species = all_species["Human"] + if(holder.dna) + dna = holder.dna.Clone() + species = all_species[dna.species] + else + log_debug("[src] at [loc] spawned without a proper DNA.") var/mob/living/carbon/human/H = holder if(istype(H)) if(internal) @@ -42,10 +50,10 @@ var/list/organ_cache = list() if(E.internal_organs == null) E.internal_organs = list() E.internal_organs |= src - if(H.dna) + if(dna) if(!blood_DNA) blood_DNA = list() - blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + blood_DNA[dna.unique_enzymes] = dna.b_type if(internal) holder.internal_organs |= src @@ -53,16 +61,18 @@ var/list/organ_cache = list() if(status & ORGAN_ROBOT) return damage = max_damage + status |= ORGAN_DEAD processing_objects -= src if(dead_icon) icon_state = dead_icon /obj/item/organ/process() - // Don't process if we're in a freezer, an MMI or a stasis bag. //TODO: ambient temperature? - if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer)) + // Don't process if we're in a freezer, an MMI or a stasis bag.or a freezer or something I dunno + if(istype(loc,/obj/item/device/mmi)) + return + if(istype(loc,/obj/structure/closet/body_bag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer) || istype(loc,/obj/item/weapon/storage/box/freezer)) return - //Process infections if (robotic >= 2 || (owner && owner.species && (owner.species.flags & IS_PLANT))) germ_level = 0 @@ -76,8 +86,10 @@ var/list/organ_cache = list() if(B && prob(40)) reagents.remove_reagent("blood",0.1) blood_splatter(src,B,1) - damage += rand(1,3) - if(damage >= max_damage) + germ_level += rand(2,6) + if(germ_level >= INFECTION_LEVEL_TWO) + germ_level += rand(2,6) + if(germ_level >= INFECTION_LEVEL_THREE) die() else if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs @@ -86,6 +98,11 @@ var/list/organ_cache = list() handle_rejection() handle_germ_effects() +/obj/item/organ/examine(mob/user) + ..(user) + if(status & ORGAN_DEAD) + user << "The decay has set in." + /obj/item/organ/proc/handle_germ_effects() //** Handle the effects of infections var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") @@ -114,24 +131,23 @@ var/list/organ_cache = list() /obj/item/organ/proc/handle_rejection() // Process unsuitable transplants. TODO: consider some kind of // immunosuppressant that changes transplant data to make it match. - if(transplant_data) - if(!rejecting && prob(20) && owner.dna && blood_incompatible(transplant_data["blood_type"],owner.dna.b_type,owner.species,transplant_data["species"])) - rejecting = 1 + if(dna) + if(!rejecting) + if(blood_incompatible(dna.b_type, owner.dna.b_type, species, owner.species)) + rejecting = 1 else rejecting++ //Rejection severity increases over time. if(rejecting % 10 == 0) //Only fire every ten rejection ticks. switch(rejecting) if(1 to 50) - take_damage(1) + germ_level++ if(51 to 200) - owner.reagents.add_reagent("toxin", 1) - take_damage(1) + germ_level += rand(1,2) if(201 to 500) - take_damage(rand(2,3)) - owner.reagents.add_reagent("toxin", 2) + germ_level += rand(2,3) if(501 to INFINITY) - take_damage(4) - owner.reagents.add_reagent("toxin", rand(3,5)) + germ_level += rand(3,5) + owner.reagents.add_reagent("toxin", rand(1,2)) /obj/item/organ/proc/receive_chem(chemical as obj) return 0 diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index a539f5f421..0655bb6deb 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -369,11 +369,6 @@ This function completely restores a damaged organ to perfect condition. /obj/item/organ/external/process() if(owner) - //Dismemberment - if(status & ORGAN_DESTROYED) - if(config.limbs_can_break) - droplimb(0,DROPLIMB_EDGE) //Might be worth removing this check since take_damage handles it. - return if(parent) if(parent.status & ORGAN_DESTROYED) status |= ORGAN_DESTROYED @@ -933,6 +928,9 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/proc/get_wounds_desc() . = "" + if(status & ORGAN_DESTROYED && !is_stump()) + . += "tear at [amputation_point] so bad it barely hangs on few tendons" + if(status & ORGAN_ROBOT) if(brute_dam) switch(brute_dam) diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 7036e7e725..d25ce2f5a2 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -17,11 +17,23 @@ var/global/list/limb_icon_cache = list() s_col = null if(status & ORGAN_ROBOT) return + if(species && human.species && species.name != human.species.name) + return if(!isnull(human.s_tone) && (human.species.flags & HAS_SKIN_TONE)) s_tone = human.s_tone if(human.species.flags & HAS_SKIN_COLOR) s_col = list(human.r_skin, human.g_skin, human.b_skin) +/obj/item/organ/external/proc/sync_colour_to_dna() + s_tone = null + s_col = null + if(status & ORGAN_ROBOT) + return + if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.flags & HAS_SKIN_TONE)) + s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) + if(species.flags & HAS_SKIN_COLOR) + s_col = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B)) + /obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human) ..() var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] @@ -35,10 +47,10 @@ var/global/list/limb_icon_cache = list() ..() overlays.Cut() - if(owner.species.has_organ["eyes"]) + if(species.has_organ["eyes"]) var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] - if(owner.species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', owner.species.eyes) + if(species.eyes) + var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) if(eyes) eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD) else @@ -46,14 +58,14 @@ var/global/list/limb_icon_cache = list() mob_icon.Blend(eyes_icon, ICON_OVERLAY) overlays |= eyes_icon - if(owner.lip_style && (owner.species && (owner.species.flags & HAS_LIPS))) + if(owner.lip_style && (species && (species.flags & HAS_LIPS))) var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (owner.species.name in facial_hair_style.species_allowed)) + if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) @@ -61,7 +73,7 @@ var/global/list/limb_icon_cache = list() if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && (owner.species.name in hair_style.species_allowed)) + if(hair_style && (species.name in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration) hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD) @@ -75,25 +87,25 @@ var/global/list/limb_icon_cache = list() if(force_icon) mob_icon = new /icon(force_icon, "[icon_name]") else - if(!owner) + if(!dna) mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]") else if(gendered_icon) - if(owner.gender == FEMALE) + if(dna.GetUIState(DNA_UI_GENDER)) gender = "f" else gender = "m" if(skeletal) mob_icon = new /icon('icons/mob/human_races/r_skeleton.dmi', "[icon_name][gender ? "_[gender]" : ""]") - else if ((status & ORGAN_ROBOT) && !(owner.species && owner.species.flags & IS_SYNTHETIC)) + else if ((status & ORGAN_ROBOT) && !(species && species.flags & IS_SYNTHETIC)) mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]") else if (status & ORGAN_MUTATED) - mob_icon = new /icon(owner.species.deform, "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(species.deform, "[icon_name][gender ? "_[gender]" : ""]") else - mob_icon = new /icon(owner.species.icobase, "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(species.icobase, "[icon_name][gender ? "_[gender]" : ""]") if(status & ORGAN_DEAD) mob_icon.ColorTone(rgb(10,50,0)) diff --git a/code/modules/organs/organ_stump.dm b/code/modules/organs/organ_stump.dm index 728f9cd1bc..68201c1413 100644 --- a/code/modules/organs/organ_stump.dm +++ b/code/modules/organs/organ_stump.dm @@ -2,7 +2,6 @@ name = "limb stump" icon_name = "" dislocated = -1 - cannot_amputate = 1 /obj/item/organ/external/stump/New(var/mob/living/carbon/holder, var/internal, var/obj/item/organ/external/limb) if(istype(limb)) diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 8d19d60b49..bb2d571f5d 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -7,6 +7,7 @@ var/global/datum/robolimb/basic_robolimb for(var/limb_type in typesof(/datum/robolimb)) var/datum/robolimb/R = new limb_type() all_robolimbs[R.company] = R + world << "Adding [R.company] as [R], [R.type]" if(!R.unavailable_at_chargen) chargen_robolimbs[R.company] = R diff --git a/code/modules/surgery/headreattach.dm b/code/modules/surgery/headreattach.dm deleted file mode 100644 index ad47b14429..0000000000 --- a/code/modules/surgery/headreattach.dm +++ /dev/null @@ -1,33 +0,0 @@ -//This is an uguu head restoration surgery TOTALLY not yoinked from chinsky's limb reattacher -/datum/surgery_step/attach_head/ - priority = 3 // Must be higher than /datum/surgery_step/internal - allowed_tools = list(/obj/item/organ/external/head = 100) - can_infect = 0 - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/obj/item/organ/external/head = target.get_organ(target_zone) - return isnull(head) && target_zone == "head" && !isnull(target.species.has_limbs["head"]) - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts attaching [tool] to [target]'s neck.", \ - "You start attaching [tool] to [target]'s neck.") - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has attached [target]'s head to the body.", \ - "\blue You have attached [target]'s head to the body.") - var/obj/item/organ/external/head = tool - user.drop_from_inventory(head) - head.replaced(target) - head.loc = target - head.status = 0 - target.update_body() - target.updatehealth() - target.UpdateDamageIcon() - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, damaging [target]'s neck!", \ - "\red Your hand slips, damaging [target]'s neck!") - target.apply_damage(10, BRUTE, null, sharp=1) diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm new file mode 100644 index 0000000000..aee13ede83 --- /dev/null +++ b/code/modules/surgery/limb_reattach.dm @@ -0,0 +1,129 @@ +//Procedures in this file: Robotic limbs attachment, meat limbs attachment +////////////////////////////////////////////////////////////////// +// LIMB SURGERY // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/limb/ + priority = 3 // Must be higher than /datum/surgery_step/internal + can_infect = 0 + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return 0 + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if (affected) + return 0 + var/list/organ_data = target.species.has_limbs["[target_zone]"] + return !isnull(organ_data) + +/datum/surgery_step/limb/attach + allowed_tools = list(/obj/item/organ/external = 100) + + min_duration = 50 + max_duration = 70 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = tool + user.visible_message("[user] starts attaching [E.name] to [target]'s [E.amputation_point].", \ + "You start attaching [E.name] to [target]'s [E.amputation_point].") + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = tool + user.visible_message("[user] has attached [target]'s [E.name] to the [E.amputation_point].>", \ + "You have attached [target]'s [E.name] to the [E.amputation_point].") + user.drop_from_inventory(E) + E.replaced(target) + E.loc = target + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = tool + user.visible_message(" [user]'s hand slips, damaging [target]'s [E.amputation_point]!", \ + " Your hand slips, damaging [target]'s [E.amputation_point]!") + target.apply_damage(10, BRUTE, null, sharp=1) + +/datum/surgery_step/limb/connect + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/stack/cable_coil = 75, \ + /obj/item/device/assembly/mousetrap = 20 + ) + can_infect = 1 + + min_duration = 100 + max_duration = 120 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = target.get_organ(target_zone) + return E && !E.is_stump() && (E.status & ORGAN_DESTROYED) + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = target.get_organ(target_zone) + user.visible_message("[user] starts connecting tendons and muscles in [target]'s [E.amputation_point] with [tool].", \ + "You start connecting tendons and muscle in [target]'s [E.amputation_point].") + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = target.get_organ(target_zone) + user.visible_message("[user] has connected tendons and muscles in [target]'s [E.amputation_point] with [tool].", \ + "You have connected tendons and muscles in [target]'s [E.amputation_point] with [tool].") + E.status &= ~ORGAN_DESTROYED + if(E.children) + for(var/obj/item/organ/external/C in E.children) + C.status &= ~ORGAN_DESTROYED + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/E = tool + user.visible_message(" [user]'s hand slips, damaging [target]'s [E.amputation_point]!", \ + " Your hand slips, damaging [target]'s [E.amputation_point]!") + target.apply_damage(10, BRUTE, null, sharp=1) + +/datum/surgery_step/limb/mechanize + allowed_tools = list(/obj/item/robot_parts = 100) + + min_duration = 80 + max_duration = 100 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if(..()) + var/obj/item/robot_parts/p = tool + if (p.part) + if (!(target_zone in p.part)) + return 0 + return isnull(target.get_organ(target_zone)) + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts attaching \the [tool] to [target].", \ + "You start attaching \the [tool] to [target].") + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/robot_parts/L = tool + user.visible_message("[user] has attached \the [tool] to [target].", \ + "You have attached \the [tool] to [target].") + + if(L.part) + for(var/part_name in L.part) + if(!isnull(target.get_organ(part_name))) + continue + var/list/organ_data = target.species.has_limbs["[part_name]"] + if(!organ_data) + continue + var/new_limb_type = organ_data["path"] + var/obj/item/organ/external/new_limb = new new_limb_type(target) + new_limb.robotize(L.model_info) + if(L.sabotaged) + new_limb.sabotaged = 1 + + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + + qdel(tool) + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message(" [user]'s hand slips, damaging [target]'s flesh!", \ + " Your hand slips, damaging [target]'s flesh!") + target.apply_damage(10, BRUTE, null, sharp=1) diff --git a/code/modules/surgery/robolimbs.dm b/code/modules/surgery/robolimbs.dm deleted file mode 100644 index d8214837bf..0000000000 --- a/code/modules/surgery/robolimbs.dm +++ /dev/null @@ -1,62 +0,0 @@ -//Procedures in this file: Robotic limbs attachment -////////////////////////////////////////////////////////////////// -// LIMB SURGERY // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/limb/ - can_infect = 0 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (!hasorgans(target)) - return 0 - var/obj/item/organ/external/affected = target.get_organ(target_zone) - if (affected) - return 0 - var/list/organ_data = target.species.has_limbs["[target_zone]"] - return !isnull(organ_data) && !(target_zone in list("head","groin","chest")) - -/datum/surgery_step/limb/attach - allowed_tools = list(/obj/item/robot_parts = 100) - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if(..()) - var/obj/item/robot_parts/p = tool - if (p.part) - if (!(target_zone in p.part)) - return 0 - return isnull(target.get_organ(target_zone)) - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts attaching \the [tool] to [target].", \ - "You start attaching \the [tool] to [target].") - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/obj/item/robot_parts/L = tool - user.visible_message("\blue [user] has attached \the [tool] to [target].", \ - "\blue You have attached \the [tool] to [target].") - - if(L.part) - for(var/part_name in L.part) - if(!isnull(target.get_organ(part_name))) - continue - var/list/organ_data = target.species.has_limbs["[part_name]"] - if(!organ_data) - continue - var/new_limb_type = organ_data["path"] - var/obj/item/organ/external/new_limb = new new_limb_type(target) - new_limb.robotize(L.model_info) - if(L.sabotaged) - new_limb.sabotaged = 1 - - target.update_body() - target.updatehealth() - target.UpdateDamageIcon() - - qdel(tool) - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, damaging [target]'s flesh!", \ - "\red Your hand slips, damaging [target]'s flesh!") - target.apply_damage(10, BRUTE, null, sharp=1) diff --git a/html/changelogs/comma-frankenstein.yml b/html/changelogs/comma-frankenstein.yml new file mode 100644 index 0000000000..5210de96c4 --- /dev/null +++ b/html/changelogs/comma-frankenstein.yml @@ -0,0 +1,9 @@ + +author: Chinsky + +delete-after: True + +changes: + - rscadd: "Meat limbs now can be attached. Use limb on missing area, then hemostat to finalize it." + - rscadd: "Limbs from other races can be now attached. They'll cause rejection, but it can be kept at bay with spaceacilline to some point. Species special attack is carried over too, i.e. you can clawn people if you sew a cathand to yourself." + - rscadd: "Limbs that are left in open will rot in ~7 minutes. Use freezers or cryobags to stop it. You can still attach them, but you wish you couldn't." \ No newline at end of file diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 377d12b4ff..e754acbc1d 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ