Merge pull request #1941 from CIB/master

Ported autopsy
This commit is contained in:
Mloc
2012-11-14 13:29:20 -08:00
16 changed files with 307 additions and 52 deletions
+189
View File
@@ -0,0 +1,189 @@
/datum/autopsy_data_scanner
var/weapon = null // this is the DEFINITE weapon type that was used
var/list/organs_scanned = list() // this maps a number of scanned organs to
// the wounds to those organs with this data's weapon type
var/organ_names = ""
/datum/autopsy_data
var/weapon = null
var/pretend_weapon = null
var/damage = 0
var/hits = 0
var/time_inflicted = 0
proc/copy()
var/datum/autopsy_data/W = new()
W.weapon = weapon
W.pretend_weapon = pretend_weapon
W.damage = damage
W.hits = hits
W.time_inflicted = time_inflicted
return W
/obj/item/weapon/autopsy_scanner/proc/add_data(var/datum/organ/external/O)
if(!O.autopsy_data.len && !O.trace_chemicals.len) return
for(var/V in O.autopsy_data)
var/datum/autopsy_data/W = O.autopsy_data[V]
if(!W.pretend_weapon)
/*
// the more hits, the more likely it is that we get the right weapon type
if(prob(50 + W.hits * 10 + W.damage))
*/
// Buffing this stuff up for now!
if(1)
W.pretend_weapon = W.weapon
else
W.pretend_weapon = pick("mechanical toolbox", "wirecutters", "revolver", "crowbar", "fire extinguisher", "tomato soup", "oxygen tank", "emergency oxygen tank", "laser", "bullet")
var/datum/autopsy_data_scanner/D = wdata[V]
if(!D)
D = new()
D.weapon = W.weapon
wdata[V] = D
if(!D.organs_scanned[O.name])
if(D.organ_names == "")
D.organ_names = O.display_name
else
D.organ_names += ", [O.display_name]"
del D.organs_scanned[O.name]
D.organs_scanned[O.name] = W.copy()
for(var/V in O.trace_chemicals)
if(O.trace_chemicals[V] > 0 && !chemtraces.Find(V))
chemtraces += V
/obj/item/weapon/autopsy_scanner/verb/print_data()
set src in view(usr, 1)
set name = "Print Data"
if(usr.stat)
usr << "No."
return
if(wdata.len == 0 && chemtraces.len == 0)
usr << "<b>* There is no data about any wounds in the scanner's database. You may have to scan more bodyparts, or otherwise this wound type may not be in the scanner's database."
return
var/scan_data = ""
if(timeofdeath)
scan_data += "<b>Time of death:</b> [worldtime2text(timeofdeath)]<br><br>"
var/n = 1
for(var/wdata_idx in wdata)
var/datum/autopsy_data_scanner/D = wdata[wdata_idx]
var/total_hits = 0
var/total_score = 0
var/list/weapon_chances = list() // maps weapon names to a score
var/age = 0
for(var/wound_idx in D.organs_scanned)
var/datum/autopsy_data/W = D.organs_scanned[wound_idx]
total_hits += W.hits
var/wname = W.pretend_weapon
if(wname in weapon_chances) weapon_chances[wname] += W.damage
else weapon_chances[wname] = max(W.damage, 1)
total_score+=W.damage
var/wound_age = W.time_inflicted
age = max(age, wound_age)
var/damage_desc
var/damaging_weapon = (total_score != 0)
// total score happens to be the total damage
switch(total_score)
if(0)
damage_desc = "Unknown"
if(1 to 5)
damage_desc = "<font color='green'>negligible</font>"
if(5 to 15)
damage_desc = "<font color='green'>light</font>"
if(15 to 30)
damage_desc = "<font color='orange'>moderate</font>"
if(30 to 1000)
damage_desc = "<font color='red'>severe</font>"
if(!total_score) total_score = D.organs_scanned.len
scan_data += "<b>Weapon #[n]</b><br>"
if(damaging_weapon)
scan_data += "Severity: [damage_desc]<br>"
scan_data += "Hits by weapon: [total_hits]<br>"
scan_data += "Approximate time of wound infliction: [worldtime2text(age)]<br>"
scan_data += "Affected limbs: [D.organ_names]<br>"
scan_data += "Possible weapons:<br>"
for(var/weapon_name in weapon_chances)
scan_data += "\t[100*weapon_chances[weapon_name]/total_score]% [weapon_name]<br>"
scan_data += "<br>"
n++
if(chemtraces.len)
scan_data += "<b>Trace Chemicals: </b><br>"
for(var/chemID in chemtraces)
scan_data += chemID
scan_data += "<br>"
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 = "<tt>[scan_data]</tt>"
P.overlays += "paper_words"
if(istype(usr,/mob/living/carbon))
// place the item in the usr's hand if possible
if(!usr.r_hand)
P.loc = usr
usr.r_hand = P
P.layer = 20
else if(!usr.l_hand)
P.loc = usr
usr.l_hand = P
P.layer = 20
if(istype(usr,/mob/living/carbon/human))
usr:update_inv_l_hand()
usr:update_inv_r_hand()
/obj/item/weapon/autopsy_scanner/attack(mob/living/carbon/human/M as mob, mob/living/carbon/user as mob)
if(!istype(M))
return
if(!can_operate(M))
return
if(target_name != M.name)
target_name = M.name
src.wdata = list()
user << "\red A new patient has been registered.. Purging data for previous patient."
src.timeofdeath = M.timeofdeath
var/datum/organ/external/S = M.get_organ(user.zone_sel.selecting)
if(!S)
usr << "<b>You can't scan this body part.</b>"
return
if(!S.open)
usr << "<b>You have to cut the limb open first!</b>"
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
+6 -1
View File
@@ -1,6 +1,11 @@
/datum/organ
var/name = "organ"
var/mob/living/carbon/human/owner = null
var/list/datum/autopsy_data/autopsy_data = 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
///datum/organ/proc/process()
// return 0
@@ -12,4 +17,4 @@
return 0
proc/receive_chem(chemical as obj)
return 0
return 0
+13
View File
@@ -122,6 +122,8 @@
if(status & ORGAN_BROKEN)
owner.emote("scream")
if(used_weapon) add_autopsy_data(used_weapon, brute + burn)
owner.updatehealth()
@@ -519,6 +521,17 @@
if(T)
T.robotize()
proc/add_autopsy_data(var/used_weapon, var/damage)
var/datum/autopsy_data/W = autopsy_data[used_weapon]
if(!W)
W = new()
W.weapon = used_weapon
autopsy_data[used_weapon] = W
W.hits += 1
W.damage += damage
W.time_inflicted = world.time
/datum/organ/external/chest
name = "chest"
icon_name = "chest"
+14
View File
@@ -1964,3 +1964,17 @@
icon_state = "capacitor"
desc = "A debug item for research."
origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8"
/obj/item/weapon/autopsy_scanner
name = "autopsy scanner"
desc = "Extracts information on wounds."
icon = 'icons/obj/autopsy_scanner.dmi'
icon_state = ""
flags = FPRINT | TABLEPASS | CONDUCT
w_class = 1.0
origin_tech = "materials=1;biotech=1"
/obj/item/weapon/autopsy_scanner/var/list/datum/autopsy_data_scanner/wdata = list()
/obj/item/weapon/autopsy_scanner/var/list/datum/autopsy_data_scanner/chemtraces = list()
/obj/item/weapon/autopsy_scanner/var/target_name = null
/obj/item/weapon/autopsy_scanner/var/timeofdeath = null
+4 -2
View File
@@ -260,5 +260,7 @@ proc/tg_list2text(list/list, glue=",")
return dir2text(angle2dir(degree))
//Returns the world time in english
proc/worldtime2text()
return "[round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]"
proc/worldtime2text(var/time = 0)
if(time == 0)
time = world.time
return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]"
+1 -1
View File
@@ -141,7 +141,7 @@
shock_damage *= siemens_coeff
if (shock_damage<1)
return 0
src.take_overall_damage(0,shock_damage)
src.take_overall_damage(0,shock_damage,used_weapon="Electrocution")
//src.burn_skin(shock_damage)
//src.adjustFireLoss(shock_damage) //burn_skin will do this for us
//src.updatehealth()
+18 -16
View File
@@ -272,34 +272,36 @@
// focus most of the blast on one organ
var/datum/organ/external/take_blast = pick(organs)
update |= take_blast.take_damage(b_loss * 0.9, f_loss * 0.9)
update |= take_blast.take_damage(b_loss * 0.9, f_loss * 0.9, used_weapon = "Explosive blast")
// distribute the remaining 10% on all limbs equally
b_loss *= 0.1
f_loss *= 0.1
var/weapon_message = "Explosive Blast"
for(var/datum/organ/external/temp in organs)
switch(temp.name)
if("head")
update |= temp.take_damage(b_loss * 0.2, f_loss * 0.2)
update |= temp.take_damage(b_loss * 0.2, f_loss * 0.2, used_weapon = weapon_message)
if("chest")
update |= temp.take_damage(b_loss * 0.4, f_loss * 0.4)
update |= temp.take_damage(b_loss * 0.4, f_loss * 0.4, used_weapon = weapon_message)
if("l_arm")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("r_arm")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("l_leg")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("r_leg")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("r_foot")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("l_foot")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("r_arm")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if("l_arm")
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(update) UpdateDamageIcon()
@@ -945,11 +947,11 @@
return gender
/mob/living/carbon/human/proc/increase_germ_level(n)
if(gloves)
gloves.germ_level += n
else
germ_level += n
if(gloves)
gloves.germ_level += n
else
germ_level += n
/mob/living/carbon/human/revive()
for (var/datum/organ/external/O in organs)
O.status &= ~ORGAN_BROKEN
@@ -116,7 +116,7 @@
if(update) UpdateDamageIcon()
// damage MANY external organs, in random order
/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/sharp = 0)
/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/sharp = 0, var/used_weapon = null)
if(nodamage) return //godmode
var/list/datum/organ/external/parts = get_damageable_organs()
var/update = 0
@@ -126,7 +126,7 @@
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.take_damage(brute,burn,sharp)
update |= picked.take_damage(brute,burn,sharp,used_weapon)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
@@ -154,7 +154,7 @@
zone = "head"
return organs_by_name[zone]
/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
@@ -176,10 +176,10 @@
switch(damagetype)
if(BRUTE)
if(organ.take_damage(damage, 0, sharp))
if(organ.take_damage(damage, 0, sharp, used_weapon))
UpdateDamageIcon()
if(BURN)
if(organ.take_damage(0, damage, sharp))
if(organ.take_damage(0, damage, sharp, used_weapon))
UpdateDamageIcon()
updatehealth()
return 1
@@ -133,7 +133,7 @@ emp_act
if(armor >= 2) return 0
if(!I.force) return 0
apply_damage(I.force, I.damtype, affecting, armor , I.sharp)
apply_damage(I.force, I.damtype, affecting, armor , I.sharp, I.name)
var/bloody = 0
if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2)))
+27 -7
View File
@@ -459,15 +459,18 @@
radiation = 0
else
var/damage = 0
switch(radiation)
if(1 to 49)
radiation--
if(prob(25))
adjustToxLoss(1)
damage = 1
updatehealth()
if(50 to 74)
radiation -= 2
damage = 1
adjustToxLoss(1)
if(prob(5))
radiation -= 5
@@ -479,13 +482,17 @@
if(75 to 100)
radiation -= 3
adjustToxLoss(3)
damage = 1
if(prob(1))
src << "\red You mutate!"
randmutb(src)
domutcheck(src,null)
emote("gasp")
updatehealth()
if(damage && organs.len)
var/datum/organ/external/O = pick(organs)
if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage)
proc/breathe()
if(reagents.has_reagent("lexorin")) return
@@ -688,22 +695,22 @@
switch(breath.temperature)
if(-INFINITY to 120)
apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head")
apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Cold")
fire_alert = max(fire_alert, 1)
if(120 to 200)
apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head")
apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Cold")
fire_alert = max(fire_alert, 1)
if(200 to 260)
apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head")
apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Cold")
fire_alert = max(fire_alert, 1)
if(360 to 400)
apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head")
apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
if(400 to 1000)
apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head")
apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
if(1000 to INFINITY)
apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head")
apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
if(oxyloss >= 50 && prob(oxyloss / 5))
@@ -1063,6 +1070,19 @@
dizziness = max(0, dizziness - 3)
jitteriness = max(0, jitteriness - 3)
if(life_tick % 10 == 0)
// handle trace chemicals for autopsy
for(var/datum/organ/O in organs)
for(var/chemID in O.trace_chemicals)
O.trace_chemicals[chemID] = O.trace_chemicals[chemID] - 1
if(O.trace_chemicals[chemID] <= 0)
O.trace_chemicals.Remove(chemID)
for(var/datum/reagent/A in reagents.reagent_list)
// add chemistry traces to a random organ
var/datum/organ/O = pick(organs)
O.trace_chemicals[A.name] = 100
updatehealth()
return //TODO: DEFERRED
+2 -2
View File
@@ -57,6 +57,6 @@
P.on_hit(src,2)
return 2
if(!P.nodamage)
apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone)
apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, used_weapon = "Projectile([P.name])")
P.on_hit(src, absorb)
return absorb
return absorb
+7 -1
View File
@@ -112,6 +112,12 @@
killing = 0
hud1.icon_state = "disarm/kill"
return
if(ishuman(affecting))
var/mob/living/carbon/human/H = affecting
var/datum/organ/external/head = H.get_organ("head")
head.add_autopsy_data("Strangulation", 0)
affecting.Weaken(5) // Should keep you down unless you get help.
affecting.Stun(5) // It will hamper your voice, being choked and all.
affecting.losebreath = min(affecting.losebreath + 2, 3)
@@ -293,4 +299,4 @@
/obj/item/weapon/grab/Del()
del(hud1)
..()
return
return
+1 -1
View File
@@ -527,7 +527,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
/obj/item/weapon/cable_coil/attack(mob/M as mob, mob/user as mob)
if(hasorgans(M))
var/datum/organ/external/S = M:organs[user.zone_sel.selecting]
var/datum/organ/external/S = M:get_organ(user.zone_sel.selecting)
if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help")
return ..()
if(S.burn_dam > 0)