diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index a2b48e3ae79..e55a3d386b2 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -1433,6 +1433,15 @@ g_amt = 10000 origin_tech = "materials=1;biotech=1" +/obj/item/weapon/autopsy_scanner + name = "autopscy scanner" + desc = "Extracts information on wounds." + icon = 'autopsy_scanner.dmi' + icon_state = "" + flags = FPRINT | TABLEPASS | CONDUCT + w_class = 1.0 + origin_tech = "materials=1;biotech=1" + /obj/item/weapon/syntiflesh name = "Syntiflesh" desc = "Meat that appears...strange..." diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm index d3369524cd0..ed57993d029 100644 --- a/code/game/objects/items/weapons/surgery_tools.dm +++ b/code/game/objects/items/weapons/surgery_tools.dm @@ -269,6 +269,7 @@ CIRCULAR SAW if(!try_bone_surgery(M, user)) return ..() + /obj/item/weapon/hemostat/proc/try_bone_surgery(mob/living/carbon/human/H as mob, mob/living/user as mob) if(!istype(H)) return 0 @@ -315,6 +316,119 @@ CIRCULAR SAW return 1 +/////////////////// +//AUTOPSY SCANNER// +/////////////////// +/obj/item/weapon/autopsy_scanner/var/list/datum/wound_data/wdata = list() +/obj/item/weapon/autopsy_scanner/var/target_name = null + +/datum/wound_data + var + weapon_type = null // this is the DEFINITE weapon type that was used + list/organs_scanned = list() // this maps a number of scanned organs to + // the wounds to those organs with this data's weapon type + organ_names = "" + +/obj/item/weapon/autopsy_scanner/proc/add_data(var/datum/organ/external/O) + if(!O.weapon_wounds.len) return + + for(var/V in O.weapon_wounds) + var/datum/wound/W = O.weapon_wounds[V] + + if(!W.pretend_weapon_type) + // the more hits, the more likely it is that we get the right weapon type + if(prob(W.hits * 10 + W.damage)) + W.pretend_weapon_type = W.weapon_type + else + if(prob(50)) + W.pretend_weapon_type = pick(/obj/item/weapon/storage/toolbox, /obj/item/weapon/wirecutters, /obj/item/weapon/gun/projectile, /obj/item/weapon/crowbar, /obj/item/weapon/extinguisher) + else + W.pretend_weapon_type = pick(typesof(/obj/item/weapon)) + + var/datum/wound_data/D = wdata[V] + if(!D) + D = new() + D.weapon_type = W.weapon_type + wdata[V] = D + + if(!D.organs_scanned[O.name]) + D.organ_names += "[O.display_name] " + + del D.organs_scanned[O.name] + D.organs_scanned[O.name] = W.copy() + +/obj/item/weapon/autopsy_scanner/verb/print_data() + set src in view(usr, 1) + + var/scan_data = "" + var/n = 1 + for(var/wdata_idx in wdata) + var/datum/wound_data/D = wdata[wdata_idx] + var/total_hits = 0 + var/total_score = 0 + var/list/weapon_chances = list() // maps weapon names to a score + + for(var/wound_idx in D.organs_scanned) + var/datum/wound/W = D.organs_scanned[wound_idx] + total_hits += W.hits + + var/atom/weapon = new W.pretend_weapon_type() + + if(weapon.name in weapon_chances) weapon_chances[weapon.name] += W.damage + else weapon_chances[weapon.name] = W.damage + total_score+=W.damage + + del weapon + + scan_data += "Weapon #[n]
" + scan_data += "Hits by weapon: [total_hits]
" + scan_data += "Affected limbs: [D.organ_names]
" + scan_data += "Possible weapons:
" + for(var/weapon_name in weapon_chances) + scan_data += "\t[100*weapon_chances[weapon_name]/total_score]% [weapon_name]
" + + scan_data += "
" + + n++ + + for(var/mob/O in viewers(usr)) + O.show_message("\red The [src] rattles and prints out a sheet of paper.", 1) + + sleep(10) + + var/obj/item/weapon/paper/P = new(usr.loc) + P.name = "Autopsy Data ([target_name])" + P.info = "[scan_data]" + P.overlays += "paper_words" + +/obj/item/weapon/autopsy_scanner/attack(mob/living/carbon/human/M as mob, mob/living/carbon/user as mob) + if(!istype(M)) + return + + if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/table/, M.loc) && M.lying && prob(50)))) + return ..() + + if(target_name != M.name) + target_name = M.name + for(var/V in src.wdata) + del src.wdata[V] + src.wdata = list() + + var/datum/organ/external/S = M.organs[user.zone_sel.selecting] + if(!S) + usr << "You can't scan this body part." + return + if(!S.open) + usr << "You have to cut the limb open first!" + return + for(var/mob/O in viewers(M)) + O.show_message("\red [user.name] scans the wounds on [M.name]'s [S.display_name] with the [src.name]", 1) + + src.add_data(S) + + return 1 + + /////////// //Cautery// /////////// @@ -572,6 +686,7 @@ CIRCULAR SAW if(istype(M, /mob/living/carbon/human)) var/datum/organ/external/affecting = M:get_organ("head") affecting.take_damage(7) + affecting.open = 1 else M.take_organ_damage(7) diff --git a/code/game/objects/storage/toolbox.dm b/code/game/objects/storage/toolbox.dm index 62a17ab8cb0..fb9df4919de 100644 --- a/code/game/objects/storage/toolbox.dm +++ b/code/game/objects/storage/toolbox.dm @@ -1,9 +1,3 @@ -/obj/item/weapon/storage/toolbox/New() - ..() - if (src.type == /obj/item/weapon/storage/toolbox) - world << "BAD: [src] ([src.type]) spawned at [src.x] [src.y] [src.z]" - del(src) - /obj/item/weapon/storage/toolbox/emergency/New() ..() new /obj/item/weapon/crowbar/red(src) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index e0f779fb7a2..53f49a1ce50 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -39,7 +39,7 @@ return null -/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0) +/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/used_weapon = null) if((damagetype != BRUTE) && (damagetype != BURN)) ..(damage, damagetype, def_zone, blocked) return 1 @@ -61,6 +61,10 @@ organ.take_damage(damage, 0, sharp) if(BURN) organ.take_damage(0, damage, sharp) + + if(used_weapon) + organ.add_wound(used_weapon, damage) + UpdateDamageIcon() updatehealth() return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 06d43c66d9f..91e1f53566b 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -96,7 +96,7 @@ emp_act var/armor = run_armor_check(affecting, "melee", "Your armor has protected you from a hit to the [hit_area].", "Your armor has softened hit to your [hit_area].") if(armor >= 2) return 0 if(!I.force) return 0 - apply_damage(I.force, I.damtype, affecting, armor, is_cut(I)) + apply_damage(I.force, I.damtype, affecting, armor, is_cut(I), I) var/bloody = 0 if((I.damtype == BRUTE) && prob(25 + (I.force * 2))) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index b253c4de1c8..9c2c391b480 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -8,7 +8,7 @@ Returns standard 0 if fail */ -/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/slash = 0) +/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/slash = 0, var/used_weapon = null) if(!damage || (blocked >= 2)) return 0 switch(damagetype) if(BRUTE) diff --git a/code/modules/mob/organ/organ.dm b/code/modules/mob/organ/organ.dm index 85f14473c2b..4804634881e 100644 --- a/code/modules/mob/organ/organ.dm +++ b/code/modules/mob/organ/organ.dm @@ -3,6 +3,8 @@ name = "organ" mob/living/carbon/human/owner = null + list/datum/wound/weapon_wounds = list() + proc/process() return 0 @@ -10,6 +12,23 @@ proc/receive_chem(chemical as obj) return 0 +/datum/wound + var + weapon_type = null + pretend_weapon_type = null + damage = 0 + hits = 0 + scar = 0 + + proc/copy() + var/datum/wound/W = new() + W.weapon_type = src.weapon_type + W.pretend_weapon_type = src.pretend_weapon_type + W.damage = src.damage + W.hits = src.hits + W.scar = src.scar + return W + /**************************************************** EXTERNAL ORGANS ****************************************************/ @@ -108,8 +127,26 @@ if(internal) broken = 0 perma_injury = 0 + // if all damage is healed, replace the wounds with scars + if(brute_dam + burn_dam == 0) + for(var/V in weapon_wounds) + var/datum/wound/W = weapon_wounds[V] + W.scar = 1 return update_icon() + proc/add_wound(var/obj/item/used_weapon, var/damage) + var/weapon_type = "[used_weapon.type]" + + var/datum/wound/W = weapon_wounds[weapon_type] + if(!W) + W = new() + W.weapon_type = used_weapon.type + weapon_wounds[weapon_type] = W + + W.hits += 1 + W.damage += damage + + proc/get_damage() //returns total damage return max(brute_dam + burn_dam - perma_injury,perma_injury) //could use health? diff --git a/icons/obj/autopsy_scanner.dmi b/icons/obj/autopsy_scanner.dmi new file mode 100644 index 00000000000..82c47de4c1a Binary files /dev/null and b/icons/obj/autopsy_scanner.dmi differ diff --git a/maps/tgstation.2.0.8.dmm b/maps/tgstation.2.0.8.dmm index 7ce2495155e..1cdd3927502 100644 --- a/maps/tgstation.2.0.8.dmm +++ b/maps/tgstation.2.0.8.dmm @@ -4473,7 +4473,7 @@ "bIa" = (/obj/machinery/atmospherics/pipe/manifold{color = "red"; icon_state = "manifold-r-f"; level = 1; name = "pipe manifold"},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery) "bIb" = (/obj/structure/stool/chair{dir = 4},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery) "bIc" = (/obj/structure/grille,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "Obshutter"; name = "Observation Shutters"; opacity = 0},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/medical/surgery) -"bId" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/manifold{color = "red"; icon_state = "manifold-r-f"; level = 1; name = "pipe manifold"},/obj/item/weapon/scalpel,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery) +"bId" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/manifold{color = "red"; icon_state = "manifold-r-f"; level = 1; name = "pipe manifold"},/obj/item/weapon/scalpel,/obj/item/weapon/autopsy_scanner,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery) "bIe" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery) "bIf" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 9},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery) "bIg" = (/obj/structure/table,/obj/item/weapon/circular_saw,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)