From 92c8c34c2ad3c3d5d4b6a748a6c4234775f4eb7c Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sun, 17 Feb 2013 19:12:00 +0400 Subject: [PATCH 1/6] Removed getDisplayNameProc(), since all organs have display_name var anyway. Moved some severed head code into it's New() for readability. Fixed noexplode flag in droplimb still making limb give explosion message. --- code/datums/organs/organ_external.dm | 65 +++++++-------------- code/game/objects/items/devices/PDA/PDA.dm | 2 +- code/game/objects/items/devices/scanners.dm | 6 +- code/modules/mob/living/carbon/carbon.dm | 2 +- 4 files changed, 26 insertions(+), 49 deletions(-) diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm index 74c28006266..b7ded52a4f1 100644 --- a/code/datums/organs/organ_external.dm +++ b/code/datums/organs/organ_external.dm @@ -357,23 +357,10 @@ owner << "\red You are now sterile." if(HEAD) H = new /obj/item/weapon/organ/head(owner.loc, owner) - if(ishuman(owner)) - if(owner.gender == FEMALE) - H.icon_state = "head_f" - H.overlays += owner.generate_head_icon() - H:transfer_identity(owner) - H.pixel_x = -10 - H.pixel_y = 6 - H.name = "[owner.real_name]'s head" - owner.u_equip(owner.glasses) owner.u_equip(owner.head) owner.u_equip(owner.ears) owner.u_equip(owner.wear_mask) - - owner.regenerate_icons() - - owner.death() if(ARM_RIGHT) H = new /obj/item/weapon/organ/r_arm(owner.loc, owner) if(ismonkey(owner)) @@ -446,18 +433,17 @@ step(H,lol) destspawn = 1 - if(status & ORGAN_ROBOT) + if(status & ORGAN_ROBOT && !no_explode) owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\ "\red Your [display_name] explodes!",\ "You hear an explosion followed by a scream!") - if(!no_explode) - explosion(get_turf(owner),-1,-1,2,3) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, owner) - spark_system.attach(owner) - spark_system.start() - spawn(10) - del(spark_system) + explosion(get_turf(owner),-1,-1,2,3) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, owner) + spark_system.attach(owner) + spark_system.start() + spawn(10) + del(spark_system) else owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\ "Your [display_name] goes flying off!",\ @@ -542,27 +528,6 @@ else take_damage(damage, 0, 1, used_weapon = "EMP") - proc/getDisplayName() - switch(name) - if("l_leg") - return "left leg" - if("r_leg") - return "right leg" - if("l_arm") - return "left arm" - if("r_arm") - return "right arm" - if("l_foot") - return "left foot" - if("r_foot") - return "right foot" - if("l_hand") - return "left hand" - if("r_hand") - return "right hand" - else - return name - proc/robotize() src.status &= ~ORGAN_BROKEN src.status &= ~ORGAN_BLEEDING @@ -743,11 +708,23 @@ obj/item/weapon/organ/head var/mob/living/carbon/brain/brainmob var/brain_op_stage = 0 -obj/item/weapon/organ/head/New() +obj/item/weapon/organ/head/New(loc, mob/living/carbon/human/H) ..() spawn(5) if(brainmob && brainmob.client) brainmob.client.screen.len = null //clear the hud + if(ishuman(H)) + if(H.gender == FEMALE) + H.icon_state = "head_f" + H.overlays += H.generate_head_icon() + transfer_identity(H) + pixel_x = -10 + pixel_y = 6 + name = "[H.real_name]'s head" + + H.regenerate_icons() + + H.death() obj/item/weapon/organ/head/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->head brainmob = new(src) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 46b7a8b4f36..3d97d7eb7cd 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -914,7 +914,7 @@ var/global/list/obj/item/device/pda/PDAs = list() user.show_message("\blue Localized Damage, Brute/Burn:",1) if(length(damaged)>0) for(var/datum/organ/external/org in damaged) - user.show_message(text("\blue \t []: []\blue-[]",capitalize(org.getDisplayName()),(org.brute_dam > 0)?"\red [org.brute_dam]":0,(org.burn_dam > 0)?"\red [org.burn_dam]":0),1) + user.show_message(text("\blue \t []: []\blue-[]",capitalize(org.display_name),(org.brute_dam > 0)?"\red [org.brute_dam]":0,(org.burn_dam > 0)?"\red [org.burn_dam]":0),1) else user.show_message("\blue \t Limbs are OK.",1) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index a0f4f202d90..6d8a77549f2 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -112,7 +112,7 @@ MASS SPECTROMETER if(length(damaged)>0) for(var/datum/organ/external/org in damaged) user.show_message(text("\blue \t []: [][]\blue - []", \ - capitalize(org.getDisplayName()), \ + capitalize(org.display_name), \ (org.brute_dam > 0) ? "\red [org.brute_dam]" :0, \ (org.status & ORGAN_BLEEDING)?"\red \[Bleeding\]":"\t", \ (org.burn_dam > 0) ? "[org.burn_dam]" :0),1) @@ -146,7 +146,7 @@ MASS SPECTROMETER var/mob/living/carbon/human/H = M for(var/name in H.organs_by_name) var/datum/organ/external/e = H.organs_by_name[name] - var/limb = e.getDisplayName() + var/limb = e.display_name if(e.status & ORGAN_BROKEN) if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!(e.status & ORGAN_SPLINTED))) user << "\red Unsecured fracture in subject [limb]. Splinting recommended for transport." @@ -328,4 +328,4 @@ MASS SPECTROMETER name = "advanced mass-spectrometer" icon_state = "adv_spectrometer" details = 1 - origin_tech = "magnets=4;biotech=2" + origin_tech = "magnets=4;biotech=2" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 8f8fe88145a..7eca9638fc5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -188,7 +188,7 @@ status = "MISSING!" if(status == "") status = "OK" - src.show_message(text("\t []My [] is [].",status=="OK"?"\blue ":"\red ",org.getDisplayName(),status),1) + src.show_message(text("\t []My [] is [].",status=="OK"?"\blue ":"\red ",org.display_name,status),1) if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit)) H.play_xylophone() else From ab9ed98f07eb0e8f4a5cdb13915fc165993dc029 Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sun, 17 Feb 2013 19:32:31 +0400 Subject: [PATCH 2/6] Removed all cases for monkeys, since they do not have organs anymore. Moved dropped limb icon generation code to it's New() --- code/datums/organs/organ_external.dm | 209 ++++++++++++--------------- 1 file changed, 89 insertions(+), 120 deletions(-) diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm index b7ded52a4f1..00f903498a5 100644 --- a/code/datums/organs/organ_external.dm +++ b/code/datums/organs/organ_external.dm @@ -337,120 +337,81 @@ if(body_part == UPPER_TORSO) return - if(status & ORGAN_SPLINTED) - status &= ~ORGAN_SPLINTED + src.status &= ~ORGAN_BROKEN + src.status &= ~ORGAN_BLEEDING + src.status &= ~ORGAN_SPLINTED if(implant) for(var/implants in implant) del(implants) - //owner.unlock_medal("Lost something?", 0, "Lose a limb.", "easy") // If any organs are attached to this, destroy them for(var/datum/organ/external/O in owner.organs) if(O.parent == src) O.droplimb(1) - var/obj/item/weapon/organ/H + var/obj/organ switch(body_part) -// if(UPPER_TORSO) -// owner.gib() if(LOWER_TORSO) owner << "\red You are now sterile." if(HEAD) - H = new /obj/item/weapon/organ/head(owner.loc, owner) + organ= new /obj/item/weapon/organ/head(owner.loc, owner) owner.u_equip(owner.glasses) owner.u_equip(owner.head) owner.u_equip(owner.ears) owner.u_equip(owner.wear_mask) if(ARM_RIGHT) - H = new /obj/item/weapon/organ/r_arm(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "r_arm_l" + if(status & ORGAN_ROBOT) + organ = new /obj/item/robot_parts/r_arm(owner.loc) + else + organ= new /obj/item/weapon/organ/r_arm(owner.loc, owner) if(ARM_LEFT) - H = new /obj/item/weapon/organ/l_arm(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "l_arm_l" + if(status & ORGAN_ROBOT) + organ= new /obj/item/robot_parts/l_arm(owner.loc) + else + organ= new /obj/item/weapon/organ/l_arm(owner.loc, owner) if(LEG_RIGHT) - H = new /obj/item/weapon/organ/r_leg(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "r_leg_l" + if(status & ORGAN_ROBOT) + organ = new /obj/item/robot_parts/l_leg(owner.loc) + else + organ= new /obj/item/weapon/organ/r_leg(owner.loc, owner) if(LEG_LEFT) - H = new /obj/item/weapon/organ/l_leg(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "l_leg_l" + if(status & ORGAN_ROBOT) + organ = new /obj/item/robot_parts/r_leg(owner.loc) + else + organ= new /obj/item/weapon/organ/l_leg(owner.loc, owner) if(HAND_RIGHT) - H = new /obj/item/weapon/organ/r_hand(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "r_hand_l" + organ= new /obj/item/weapon/organ/r_hand(owner.loc, owner) owner.u_equip(owner.gloves) if(HAND_LEFT) - H = new /obj/item/weapon/organ/l_hand(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "l_hand_l" + organ= new /obj/item/weapon/organ/l_hand(owner.loc, owner) owner.u_equip(owner.gloves) if(FOOT_RIGHT) - H = new /obj/item/weapon/organ/r_foot/(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "r_foot_l" + organ= new /obj/item/weapon/organ/r_foot/(owner.loc, owner) owner.u_equip(owner.shoes) if(FOOT_LEFT) - H = new /obj/item/weapon/organ/l_foot(owner.loc, owner) - if(ismonkey(owner)) - H.icon_state = "l_foot_l" + organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner) owner.u_equip(owner.shoes) - if(H) - if(ismonkey(owner)) - H.icon = 'monkey.dmi' - else if(ishuman(owner) && owner.dna) - var/icon/I - switch(owner.dna.mutantrace) - if("tajaran") - I = new('icons/mob/human_races/r_tajaran.dmi') - if("lizard") - I = new('icons/mob/human_races/r_lizard.dmi') - if("skrell") - I = new('icons/mob/human_races/r_skrell.dmi') - else - I = new('icons/mob/human_races/r_human.dmi') - if(I) - H.icon = I.MakeLying() + if(organ) + destspawn = 1 + if(status & ORGAN_ROBOT && !no_explode) + owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\ + "\red Your [display_name] explodes!",\ + "You hear an explosion followed by a scream!") + explosion(get_turf(owner),-1,-1,2,3) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, owner) + spark_system.attach(owner) + spark_system.start() + spawn(10) + del(spark_system) else - H.icon_state = initial(H.icon_state)+"_l" - - if(status & ORGAN_ROBOT) - del H - switch(body_part) - if(LEG_RIGHT) - H = new /obj/item/robot_parts/r_leg(owner.loc) - if(LEG_LEFT) - H = new /obj/item/robot_parts/l_leg(owner.loc) - if(ARM_RIGHT) - H = new /obj/item/robot_parts/r_arm(owner.loc) - if(ARM_LEFT) - H = new /obj/item/robot_parts/l_arm(owner.loc) - - if(H) + owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\ + "Your [display_name] goes flying off!",\ + "You hear a terrible sound of ripping tendons and flesh.") var/lol = pick(cardinal) - step(H,lol) - - destspawn = 1 - if(status & ORGAN_ROBOT && !no_explode) - owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\ - "\red Your [display_name] explodes!",\ - "You hear an explosion followed by a scream!") - explosion(get_turf(owner),-1,-1,2,3) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, owner) - spark_system.attach(owner) - spark_system.start() - spawn(10) - del(spark_system) - else - owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\ - "Your [display_name] goes flying off!",\ - "You hear a terrible sound of ripping tendons and flesh.") - - // force the icon to rebuild - owner.regenerate_icons() + step(organ,lol) + // force the icon to rebuild + owner.regenerate_icons() proc/createwound(var/type = CUT, var/damage) if(hasorgans(owner)) @@ -673,18 +634,6 @@ obj/item/weapon/organ icon = 'icons/mob/human_races/r_human.dmi' -/* -//Damage will not exceed max_damage using this proc -//Cannot apply negative damage -/datum/organ/external/proc/take_damage(brute, burn) - if(owner && (owner.status_flags & GODMODE)) return 0 //godmode - brute = max(brute,0) - burn = max(burn,0) - - var/can_inflict = max_damage - (brute_dam + burn_dam) - if(!can_inflict) return 0 -*/ - obj/item/weapon/organ/New(loc, mob/living/carbon/human/H) ..(loc) if(!istype(H)) @@ -694,14 +643,59 @@ obj/item/weapon/organ/New(loc, mob/living/carbon/human/H) blood_DNA = list() blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + //Forming icon for the limb + + //Setting base icon for this mob's race + if(ishuman(H) && owner.dna) + var/icon/base + switch(H.dna.mutantrace) + if("tajaran") + base = new('icons/mob/human_races/r_tajaran.dmi') + if("lizard") + base = new('icons/mob/human_races/r_lizard.dmi') + if("skrell") + base = new('icons/mob/human_races/r_skrell.dmi') + else + base = new('icons/mob/human_races/r_human.dmi') + if(I) + icon = I.MakeLying() + else + icon_state = initial(icon_state)+"_l" + var/icon/I = new /icon(icon, icon_state) + //Changing limb's skin tone to match owner if (H.s_tone >= 0) I.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) else I.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) icon = I + +obj/item/weapon/organ/l_arm + name = "left arm" + icon_state = "l_arm" +obj/item/weapon/organ/l_foot + name = "left foot" + icon_state = "l_foot" +obj/item/weapon/organ/l_hand + name = "left hand" + icon_state = "l_hand" +obj/item/weapon/organ/l_leg + name = "left leg" + icon_state = "l_leg" +obj/item/weapon/organ/r_arm + name = "right arm" + icon_state = "r_arm" +obj/item/weapon/organ/r_foot + name = "right foot" + icon_state = "r_foot" +obj/item/weapon/organ/r_hand + name = "right hand" + icon_state = "r_hand" +obj/item/weapon/organ/r_leg + name = "right leg" + icon_state = "r_leg" obj/item/weapon/organ/head name = "head" icon_state = "head_m" @@ -783,28 +777,3 @@ obj/item/weapon/organ/head/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() else ..() - -obj/item/weapon/organ/l_arm - name = "left arm" - icon_state = "l_arm" -obj/item/weapon/organ/l_foot - name = "left foot" - icon_state = "l_foot" -obj/item/weapon/organ/l_hand - name = "left hand" - icon_state = "l_hand" -obj/item/weapon/organ/l_leg - name = "left leg" - icon_state = "l_leg" -obj/item/weapon/organ/r_arm - name = "right arm" - icon_state = "r_arm" -obj/item/weapon/organ/r_foot - name = "right foot" - icon_state = "r_foot" -obj/item/weapon/organ/r_hand - name = "right hand" - icon_state = "r_hand" -obj/item/weapon/organ/r_leg - name = "right leg" - icon_state = "r_leg" From 24351fbea8e0f455c7c7767825dd5ea12fc92e14 Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sun, 17 Feb 2013 20:28:42 +0400 Subject: [PATCH 3/6] Made all proc declarations full, updated indentation accordingly. Changed paths for wounds. --- code/datums/organs/organ_external.dm | 887 +++++++++++++-------------- code/datums/organs/wound.dm | 34 +- 2 files changed, 456 insertions(+), 465 deletions(-) diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm index 00f903498a5..4ce631435b5 100644 --- a/code/datums/organs/organ_external.dm +++ b/code/datums/organs/organ_external.dm @@ -12,7 +12,6 @@ var/burn_dam = 0 var/max_damage = 0 var/max_size = 0 - var/tmp/list/obj/item/weapon/implant/implant var/display_name var/list/wounds = list() @@ -38,478 +37,470 @@ // INTERNAL germs inside the organ, this is BAD if it's greater 0 var/germ_level = 0 - // how often wounds should be updated, a higher number means less often + // how often wounds should be updated, a higher number means less often var/wound_update_accuracy = 20 // update every 20 ticks(roughly every minute) - New(var/datum/organ/external/P) - if(P) - parent = P - if(!parent.children) - parent.children = list() - parent.children.Add(src) - return ..() + +/datum/organ/external/New(var/datum/organ/external/P) + if(P) + parent = P + if(!parent.children) + parent.children = list() + parent.children.Add(src) + return ..() - proc/take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list()) - if((brute <= 0) && (burn <= 0)) - return 0 - if(status & ORGAN_DESTROYED) - return 0 - if(status & ORGAN_ROBOT) - brute *= 0.66 //~2/3 damage for ROBOLIMBS - burn *= 0.66 //~2/3 damage for ROBOLIMBS - - //if(owner && !(status & ORGAN_ROBOT)) - // owner.pain(display_name, (brute+burn)*3, 1, burn > brute) - - if(sharp) - var/nux = brute * rand(10,15) - if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) - if(prob(5 * brute)) - droplimb(1) - return - - else if(prob(nux)) - createwound( CUT, brute ) - if(!(status & ORGAN_ROBOT)) - owner << "You feel something wet on your [display_name]" - - else if(brute > 20) - if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) - if(prob(5 * brute)) - droplimb(1) - return - - // If the limbs can break, make sure we don't exceed the maximum damage a limb can take before breaking - if((brute_dam + burn_dam + brute + burn) < max_damage || !config.limbs_can_break) - if(brute) - if( (prob(brute*2) && !sharp) || sharp ) - createwound( CUT, brute ) - else if(!sharp) - createwound( BRUISE, brute ) - if(burn) - createwound( BURN, burn ) - else - // If we can't inflict the full amount of damage, spread the damage in other ways - var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam) //How much damage can we actually cause? - if(can_inflict) - if (brute > 0) - brute = can_inflict - createwound(BRUISE, brute) - if (burn > 0) - burn = can_inflict - createwound(BURN, burn) - else if(!(status & ORGAN_ROBOT)) - var/passed_dam = (brute + burn) - can_inflict //Getting how much overdamage we have. - var/list/datum/organ/external/possible_points = list() - if(parent) - possible_points += parent - if(children) - possible_points += children - if(forbidden_limbs.len) - possible_points -= forbidden_limbs - if(!possible_points.len) - if(owner.stat != 2) - message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage to!") - else - var/datum/organ/external/target = pick(possible_points) - if(brute) - target.take_damage(passed_dam, 0, sharp, used_weapon, forbidden_limbs + src) - else - target.take_damage(0, passed_dam, sharp, used_weapon, forbidden_limbs + src) - else - droplimb(1) //Robot limbs just kinda fail at full damage. - - - if(status & ORGAN_BROKEN) - owner.emote("scream") - - if(used_weapon) add_autopsy_data(used_weapon, brute + burn) - - owner.updatehealth() - - // sync the organ's damage with its wounds - src.update_damages() - - var/result = update_icon() - return result - - - - proc/heal_damage(brute, burn, internal = 0, robo_repair = 0) - if(status & ORGAN_ROBOT && !robo_repair) - return - - // heal damage on the individual wounds - for(var/datum/wound/W in wounds) - if(brute == 0 && burn == 0) - break - - // heal brute damage - if(W.damage_type == CUT || W.damage_type == BRUISE) - brute = W.heal_damage(brute) - else if(W.damage_type == BURN) - burn = W.heal_damage(burn) - - // sync organ damage with wound damages - update_damages() - - if(internal) - status &= ~ORGAN_BROKEN - perma_injury = 0 - - // sync the organ's damage with its wounds - src.update_damages() - - owner.updatehealth() - var/result = update_icon() - return result - - proc/update_damages() - number_wounds = 0 - brute_dam = 0 - burn_dam = 0 - status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) - if(W.damage_type == CUT || W.damage_type == BRUISE) - brute_dam += W.damage - else if(W.damage_type == BURN) - burn_dam += W.damage - - if(!(status & ORGAN_ROBOT) && W.bleeding()) - status |= ORGAN_BLEEDING - - number_wounds += W.amount - - proc/update_wounds() - for(var/datum/wound/W in wounds) - // wounds can disappear after 10 minutes at the earliest - if(W.damage == 0 && W.created + 10 * 10 * 60 <= world.time) - wounds -= W - // let the GC handle the deletion of the wound - if(W.internal && !W.is_treated() && owner.bodytemperature >= 170) - // internal wounds get worse over time - W.open_wound(0.1 * wound_update_accuracy) - owner.vessel.remove_reagent("blood",0.07 * W.damage * wound_update_accuracy) - if(prob(1 * wound_update_accuracy)) - owner.custom_pain("You feel a stabbing pain in your [display_name]!",1) - - if(W.bandaged || W.salved) - // slow healing - var/amount = 0.2 - if(W.is_treated()) - amount += 10 - // amount of healing is spread over all the wounds - W.heal_damage((wound_update_accuracy * amount * W.amount * config.organ_regeneration_multiplier) / (20*owner.number_wounds+1)) - - if(W.germ_level > 100 && prob(10)) - owner.adjustToxLoss(1 * wound_update_accuracy) - if(W.germ_level > 1000) - owner.adjustToxLoss(1 * wound_update_accuracy) - - // Salving also helps against infection - if(W.germ_level > 0 && W.salved && prob(2)) - W.germ_level = 0 - - // sync the organ's damage with its wounds - src.update_damages() - - proc/bandage() - var/rval = 0 - src.status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) - if(W.internal) continue - rval |= !W.bandaged - W.bandaged = 1 - return rval - - proc/clamp() - var/rval = 0 - src.status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) - if(W.internal) continue - rval |= !W.clamped - W.clamped = 1 - return rval - - proc/salve() - var/rval = 0 - for(var/datum/wound/W in wounds) - rval |= !W.salved - W.salved = 1 - return rval - - proc/get_damage() //returns total damage - return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health? - - proc/get_damage_brute() - return max(brute_dam+perma_injury, perma_injury) - - proc/get_damage_fire() - return burn_dam - - proc/is_infected() - for(var/datum/wound/W in wounds) - if(W.germ_level > 100) - return 1 +/datum/organ/external/proc/take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list()) + if((brute <= 0) && (burn <= 0)) return 0 + if(status & ORGAN_DESTROYED) + return 0 + if(status & ORGAN_ROBOT) + brute *= 0.66 //~2/3 damage for ROBOLIMBS + burn *= 0.66 //~2/3 damage for ROBOLIMBS - process() - // process wounds, doing healing etc., only do this every 4 ticks to save processing power - if(owner.life_tick % wound_update_accuracy == 0) - update_wounds() - if(status & ORGAN_DESTROYED) - if(!destspawn && config.limbs_can_break) - droplimb() - return - if(!(status & ORGAN_BROKEN)) - perma_dmg = 0 - if(parent) - if(parent.status & ORGAN_DESTROYED) - status |= ORGAN_DESTROYED - owner.update_body(1) + //if(owner && !(status & ORGAN_ROBOT)) + // owner.pain(display_name, (brute+burn)*3, 1, burn > brute) + + if(sharp) + var/nux = brute * rand(10,15) + if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) + if(prob(5 * brute)) + droplimb(1) return - if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) - src.fracture() - if(germ_level > 0) - for(var/datum/wound/W in wounds) if(!W.bandaged && !W.salved) - W.germ_level = max(W.germ_level, germ_level) - update_icon() + + else if(prob(nux)) + createwound( CUT, brute ) + if(!(status & ORGAN_ROBOT)) + owner << "You feel something wet on your [display_name]" + + else if(brute > 20) + if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) + if(prob(5 * brute)) + droplimb(1) + return + + // If the limbs can break, make sure we don't exceed the maximum damage a limb can take before breaking + if((brute_dam + burn_dam + brute + burn) < max_damage || !config.limbs_can_break) + if(brute) + if( (prob(brute*2) && !sharp) || sharp ) + createwound( CUT, brute ) + else if(!sharp) + createwound( BRUISE, brute ) + if(burn) + createwound( BURN, burn ) + else + // If we can't inflict the full amount of damage, spread the damage in other ways + var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam) //How much damage can we actually cause? + if(can_inflict) + if (brute > 0) + brute = can_inflict + createwound(BRUISE, brute) + if (burn > 0) + burn = can_inflict + createwound(BURN, burn) + else if(!(status & ORGAN_ROBOT)) + var/passed_dam = (brute + burn) - can_inflict //Getting how much overdamage we have. + var/list/datum/organ/external/possible_points = list() + if(parent) + possible_points += parent + if(children) + possible_points += children + if(forbidden_limbs.len) + possible_points -= forbidden_limbs + if(!possible_points.len) + if(owner.stat != 2) + message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage to!") + else + var/datum/organ/external/target = pick(possible_points) + if(brute) + target.take_damage(passed_dam, 0, sharp, used_weapon, forbidden_limbs + src) + else + target.take_damage(0, passed_dam, sharp, used_weapon, forbidden_limbs + src) + else + droplimb(1) //Robot limbs just kinda fail at full damage. + + + if(status & ORGAN_BROKEN) + owner.emote("scream") + + if(used_weapon) add_autopsy_data(used_weapon, brute + burn) + + owner.updatehealth() + + // sync the organ's damage with its wounds + src.update_damages() + + var/result = update_icon() + return result + + + +/datum/organ/external/proc/heal_damage(brute, burn, internal = 0, robo_repair = 0) + if(status & ORGAN_ROBOT && !robo_repair) return - proc/fracture() - if(status & ORGAN_BROKEN) + // heal damage on the individual wounds + for(var/datum/wound/W in wounds) + if(brute == 0 && burn == 0) + break + + // heal brute damage + if(W.damage_type == CUT || W.damage_type == BRUISE) + brute = W.heal_damage(brute) + else if(W.damage_type == BURN) + burn = W.heal_damage(burn) + + // sync organ damage with wound damages + update_damages() + + if(internal) + status &= ~ORGAN_BROKEN + perma_injury = 0 + + // sync the organ's damage with its wounds + src.update_damages() + + owner.updatehealth() + var/result = update_icon() + return result + +/datum/organ/external/proc/update_damages() + number_wounds = 0 + brute_dam = 0 + burn_dam = 0 + status &= ~ORGAN_BLEEDING + for(var/datum/wound/W in wounds) + if(W.damage_type == CUT || W.damage_type == BRUISE) + brute_dam += W.damage + else if(W.damage_type == BURN) + burn_dam += W.damage + + if(!(status & ORGAN_ROBOT) && W.bleeding()) + status |= ORGAN_BLEEDING + + number_wounds += W.amount + +/datum/organ/external/proc/update_wounds() + for(var/datum/wound/W in wounds) + // wounds can disappear after 10 minutes at the earliest + if(W.damage == 0 && W.created + 10 * 10 * 60 <= world.time) + wounds -= W + // let the GC handle the deletion of the wound + if(W.internal && !W.is_treated() && owner.bodytemperature >= 170) + // internal wounds get worse over time + W.open_wound(0.1 * wound_update_accuracy) + owner.vessel.remove_reagent("blood",0.07 * W.damage * wound_update_accuracy) + if(prob(1 * wound_update_accuracy)) + owner.custom_pain("You feel a stabbing pain in your [display_name]!",1) + + if(W.bandaged || W.salved) + // slow healing + var/amount = 0.2 + if(W.is_treated()) + amount += 10 + // amount of healing is spread over all the wounds + W.heal_damage((wound_update_accuracy * amount * W.amount * config.organ_regeneration_multiplier) / (20*owner.number_wounds+1)) + + if(W.germ_level > 100 && prob(10)) + owner.adjustToxLoss(1 * wound_update_accuracy) + if(W.germ_level > 1000) + owner.adjustToxLoss(1 * wound_update_accuracy) + + // Salving also helps against infection + if(W.germ_level > 0 && W.salved && prob(2)) + W.germ_level = 0 + + // sync the organ's damage with its wounds + src.update_damages() + +/datum/organ/external/proc/bandage() + var/rval = 0 + src.status &= ~ORGAN_BLEEDING + for(var/datum/wound/W in wounds) + if(W.internal) continue + rval |= !W.bandaged + W.bandaged = 1 + return rval + +/datum/organ/external/proc/clamp() + var/rval = 0 + src.status &= ~ORGAN_BLEEDING + for(var/datum/wound/W in wounds) + if(W.internal) continue + rval |= !W.clamped + W.clamped = 1 + return rval + +/datum/organ/external/proc/salve() + var/rval = 0 + for(var/datum/wound/W in wounds) + rval |= !W.salved + W.salved = 1 + return rval + +/datum/organ/external/proc/get_damage() //returns total damage + return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health? + +/datum/organ/external/proc/get_damage_brute() + return max(brute_dam+perma_injury, perma_injury) + +/datum/organ/external/proc/get_damage_fire() + return burn_dam + +/datum/organ/external/proc/is_infected() + for(var/datum/wound/W in wounds) + if(W.germ_level > 100) + return 1 + return 0 + +/datum/organ/external/process() + // process wounds, doing healing etc., only do this every 4 ticks to save processing power + if(owner.life_tick % wound_update_accuracy == 0) + update_wounds() + if(status & ORGAN_DESTROYED) + if(!destspawn && config.limbs_can_break) + droplimb() + return + if(!(status & ORGAN_BROKEN)) + perma_dmg = 0 + if(parent) + if(parent.status & ORGAN_DESTROYED) + status |= ORGAN_DESTROYED + owner.update_body(1) return - owner.visible_message("\red You hear a loud cracking sound coming from \the [owner].","\red Something feels like it shattered in your [display_name]!","You hear a sickening crack.") - owner.emote("scream") - status |= ORGAN_BROKEN - broken_description = pick("broken","fracture","hairline fracture") - perma_injury = brute_dam + if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) + src.fracture() + if(germ_level > 0) + for(var/datum/wound/W in wounds) if(!W.bandaged && !W.salved) + W.germ_level = max(W.germ_level, germ_level) + update_icon() + return + +/datum/organ/external/proc/fracture() + if(status & ORGAN_BROKEN) + return + owner.visible_message("\red You hear a loud cracking sound coming from \the [owner].","\red Something feels like it shattered in your [display_name]!","You hear a sickening crack.") + owner.emote("scream") + status |= ORGAN_BROKEN + broken_description = pick("broken","fracture","hairline fracture") + perma_injury = brute_dam // new damage icon system // returns just the brute/burn damage code - proc/damage_state_text() - if(status & ORGAN_DESTROYED) - return "--" +/datum/organ/external/proc/damage_state_text() + if(status & ORGAN_DESTROYED) + return "--" - var/tburn = 0 - var/tbrute = 0 + var/tburn = 0 + var/tbrute = 0 - if(burn_dam ==0) - tburn =0 - else if (burn_dam < (max_damage * 0.25 / 2)) - tburn = 1 - else if (burn_dam < (max_damage * 0.75 / 2)) - tburn = 2 - else - tburn = 3 + if(burn_dam ==0) + tburn =0 + else if (burn_dam < (max_damage * 0.25 / 2)) + tburn = 1 + else if (burn_dam < (max_damage * 0.75 / 2)) + tburn = 2 + else + tburn = 3 - if (brute_dam == 0) - tbrute = 0 - else if (brute_dam < (max_damage * 0.25 / 2)) - tbrute = 1 - else if (brute_dam < (max_damage * 0.75 / 2)) - tbrute = 2 - else - tbrute = 3 - return "[tbrute][tburn]" + if (brute_dam == 0) + tbrute = 0 + else if (brute_dam < (max_damage * 0.25 / 2)) + tbrute = 1 + else if (brute_dam < (max_damage * 0.75 / 2)) + tbrute = 2 + else + tbrute = 3 + return "[tbrute][tburn]" // new damage icon system // adjusted to set damage_state to brute/burn code only (without r_name0 as before) - proc/update_icon() - var/n_is = damage_state_text() - if (n_is != damage_state) - damage_state = n_is - owner.update_body(1) - return 1 - return 0 +/datum/organ/external/proc/update_icon() + var/n_is = damage_state_text() + if (n_is != damage_state) + damage_state = n_is + owner.update_body(1) + return 1 + return 0 - proc/setAmputatedTree() - for(var/datum/organ/external/O in children) - O.amputated=amputated - O.setAmputatedTree() +/datum/organ/external/proc/setAmputatedTree() + for(var/datum/organ/external/O in children) + O.amputated=amputated + O.setAmputatedTree() - proc/droplimb(var/override = 0,var/no_explode = 0) - if(destspawn) return - if(override) - status |= ORGAN_DESTROYED - if(status & ORGAN_DESTROYED) - if(body_part == UPPER_TORSO) - return - - src.status &= ~ORGAN_BROKEN - src.status &= ~ORGAN_BLEEDING - src.status &= ~ORGAN_SPLINTED - if(implant) - for(var/implants in implant) - del(implants) - - // If any organs are attached to this, destroy them - for(var/datum/organ/external/O in owner.organs) - if(O.parent == src) - O.droplimb(1) - - var/obj/organ - switch(body_part) - if(LOWER_TORSO) - owner << "\red You are now sterile." - if(HEAD) - organ= new /obj/item/weapon/organ/head(owner.loc, owner) - owner.u_equip(owner.glasses) - owner.u_equip(owner.head) - owner.u_equip(owner.ears) - owner.u_equip(owner.wear_mask) - if(ARM_RIGHT) - if(status & ORGAN_ROBOT) - organ = new /obj/item/robot_parts/r_arm(owner.loc) - else - organ= new /obj/item/weapon/organ/r_arm(owner.loc, owner) - if(ARM_LEFT) - if(status & ORGAN_ROBOT) - organ= new /obj/item/robot_parts/l_arm(owner.loc) - else - organ= new /obj/item/weapon/organ/l_arm(owner.loc, owner) - if(LEG_RIGHT) - if(status & ORGAN_ROBOT) - organ = new /obj/item/robot_parts/l_leg(owner.loc) - else - organ= new /obj/item/weapon/organ/r_leg(owner.loc, owner) - if(LEG_LEFT) - if(status & ORGAN_ROBOT) - organ = new /obj/item/robot_parts/r_leg(owner.loc) - else - organ= new /obj/item/weapon/organ/l_leg(owner.loc, owner) - if(HAND_RIGHT) - organ= new /obj/item/weapon/organ/r_hand(owner.loc, owner) - owner.u_equip(owner.gloves) - if(HAND_LEFT) - organ= new /obj/item/weapon/organ/l_hand(owner.loc, owner) - owner.u_equip(owner.gloves) - if(FOOT_RIGHT) - organ= new /obj/item/weapon/organ/r_foot/(owner.loc, owner) - owner.u_equip(owner.shoes) - if(FOOT_LEFT) - organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner) - owner.u_equip(owner.shoes) - if(organ) - destspawn = 1 - if(status & ORGAN_ROBOT && !no_explode) - owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\ - "\red Your [display_name] explodes!",\ - "You hear an explosion followed by a scream!") - explosion(get_turf(owner),-1,-1,2,3) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, owner) - spark_system.attach(owner) - spark_system.start() - spawn(10) - del(spark_system) - else - owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\ - "Your [display_name] goes flying off!",\ - "You hear a terrible sound of ripping tendons and flesh.") - var/lol = pick(cardinal) - step(organ,lol) - // force the icon to rebuild - owner.regenerate_icons() - - proc/createwound(var/type = CUT, var/damage) - if(hasorgans(owner)) - var/wound_type - var/size = min( max( 1, damage/10 ) , 6) - - // first check whether we can widen an existing wound - if(wounds.len > 0 && prob(max(50+owner.number_wounds*10,100))) - if((type == CUT || type == BRUISE) && damage >= 5) - var/datum/wound/W = pick(wounds) - if(W.amount == 1 && W.started_healing()) - W.open_wound(damage) - if(prob(25)) - owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping voice.",\ - "\red The wound on your [display_name] widens with a nasty ripping voice.",\ - "You hear a nasty ripping noise, as if flesh is being torn apart.") - - return - - if(damage == 0) return - - // the wound we will create - var/datum/wound/W - - switch(type) - if(CUT) - if(!(status & ORGAN_ROBOT)) - src.status |= ORGAN_BLEEDING - var/list/size_names = list(/datum/wound/cut, /datum/wound/deep_cut, /datum/wound/flesh_wound, /datum/wound/gaping_wound, /datum/wound/big_gaping_wound, /datum/wound/massive_wound) - wound_type = size_names[size] - - W = new wound_type(damage) - - if(BRUISE) - var/list/size_names = list(/datum/wound/bruise/tiny_bruise, /datum/wound/bruise/small_bruise, /datum/wound/bruise/moderate_bruise, /datum/wound/bruise/large_bruise, /datum/wound/bruise/huge_bruise, /datum/wound/bruise/monumental_bruise) - wound_type = size_names[size] - - W = new wound_type(damage) - if(BURN) - var/list/size_names = list(/datum/wound/moderate_burn, /datum/wound/large_burn, /datum/wound/severe_burn, /datum/wound/deep_burn, /datum/wound/carbonised_area, /datum/wound/carbonised_area) - wound_type = size_names[size] - - W = new wound_type(damage) - - // Possibly trigger an internal wound, too. - var/local_damage = brute_dam + burn_dam + damage - if(damage > 10 && type != BURN && local_damage > 20 && prob(damage) && !(status & ORGAN_ROBOT)) - var/datum/wound/internal_bleeding/I = new (15) - wounds += I - owner.custom_pain("You feel something rip in your [display_name]!", 1) - - // check whether we can add the wound to an existing wound - for(var/datum/wound/other in wounds) - if(other.desc == W.desc) - // okay, add it! - other.damage += W.damage - other.amount += 1 - W = null // to signify that the wound was added - break - - // if we couldn't add the wound to another wound, ignore - if(W) - wounds += W - - proc/emp_act(severity) - if(!(status & ORGAN_ROBOT)) +/datum/organ/external/proc/droplimb(var/override = 0,var/no_explode = 0) + if(destspawn) return + if(override) + status |= ORGAN_DESTROYED + if(status & ORGAN_DESTROYED) + if(body_part == UPPER_TORSO) return - var/probability = 30 - var/damage = 15 - if(severity == 2) - probability = 1 - damage = 3 - if(prob(probability)) - droplimb(1) - else - take_damage(damage, 0, 1, used_weapon = "EMP") - proc/robotize() src.status &= ~ORGAN_BROKEN src.status &= ~ORGAN_BLEEDING src.status &= ~ORGAN_SPLINTED - src.status &= ~ORGAN_ATTACHABLE - src.status &= ~ORGAN_DESTROYED - src.status |= ORGAN_ROBOT - for (var/datum/organ/external/T in children) - if(T) - T.robotize() + for(var/implant in implants) + del(implant) - 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 + // If any organs are attached to this, destroy them + for(var/datum/organ/external/O in owner.organs) + if(O.parent == src) + O.droplimb(1) - W.hits += 1 - W.damage += damage - W.time_inflicted = world.time + var/obj/organ + switch(body_part) + if(LOWER_TORSO) + owner << "\red You are now sterile." + if(HEAD) + organ= new /obj/item/weapon/organ/head(owner.loc, owner) + owner.u_equip(owner.glasses) + owner.u_equip(owner.head) + owner.u_equip(owner.ears) + owner.u_equip(owner.wear_mask) + if(ARM_RIGHT) + if(status & ORGAN_ROBOT) + organ = new /obj/item/robot_parts/r_arm(owner.loc) + else + organ= new /obj/item/weapon/organ/r_arm(owner.loc, owner) + if(ARM_LEFT) + if(status & ORGAN_ROBOT) + organ= new /obj/item/robot_parts/l_arm(owner.loc) + else + organ= new /obj/item/weapon/organ/l_arm(owner.loc, owner) + if(LEG_RIGHT) + if(status & ORGAN_ROBOT) + organ = new /obj/item/robot_parts/l_leg(owner.loc) + else + organ= new /obj/item/weapon/organ/r_leg(owner.loc, owner) + if(LEG_LEFT) + if(status & ORGAN_ROBOT) + organ = new /obj/item/robot_parts/r_leg(owner.loc) + else + organ= new /obj/item/weapon/organ/l_leg(owner.loc, owner) + if(HAND_RIGHT) + organ= new /obj/item/weapon/organ/r_hand(owner.loc, owner) + owner.u_equip(owner.gloves) + if(HAND_LEFT) + organ= new /obj/item/weapon/organ/l_hand(owner.loc, owner) + owner.u_equip(owner.gloves) + if(FOOT_RIGHT) + organ= new /obj/item/weapon/organ/r_foot/(owner.loc, owner) + owner.u_equip(owner.shoes) + if(FOOT_LEFT) + organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner) + owner.u_equip(owner.shoes) + if(organ) + destspawn = 1 + if(status & ORGAN_ROBOT && !no_explode) + owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\ + "\red Your [display_name] explodes!",\ + "You hear an explosion followed by a scream!") + explosion(get_turf(owner),-1,-1,2,3) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, owner) + spark_system.attach(owner) + spark_system.start() + spawn(10) + del(spark_system) + else + owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\ + "Your [display_name] goes flying off!",\ + "You hear a terrible sound of ripping tendons and flesh.") + var/lol = pick(cardinal) + step(organ,lol) + // force the icon to rebuild + owner.regenerate_icons() + +/datum/organ/external/proc/createwound(var/type = CUT, var/damage) + if(damage == 0) return + + // first check whether we can widen an existing wound + if(wounds.len > 0 && prob(max(50+owner.number_wounds*10,100))) + if((type == CUT || type == BRUISE) && damage >= 5) + var/datum/wound/W = pick(wounds) + if(W.amount == 1 && W.started_healing()) + W.open_wound(damage) + if(prob(25)) + owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping voice.",\ + "\red The wound on your [display_name] widens with a nasty ripping voice.",\ + "You hear a nasty ripping noise, as if flesh is being torn apart.") + return + + // the wound we will create + var/datum/wound/W + var/wound_type + var/size = min( max( 1, damage/10 ) , 6) + + switch(type) + if(CUT) + var/list/size_names = typesof(/datum/wound/cut/) - /datum/wound/cut/ + wound_type = size_names[size] + + if(BRUISE) + var/list/size_names = typesof(/datum/wound/bruise/) - /datum/wound/bruise/ + wound_type = size_names[size] + + if(BURN) + var/list/size_names = typesof(/datum/wound/burn/) - /datum/wound/burn/ + wound_type = size_names[size] + + W = new wound_type(damage) + + // Possibly trigger an internal wound, too. + var/local_damage = brute_dam + burn_dam + damage + if(damage > 10 && type != BURN && local_damage > 20 && prob(damage) && !(status & ORGAN_ROBOT)) + var/datum/wound/internal_bleeding/I = new (15) + wounds += I + owner.custom_pain("You feel something rip in your [display_name]!", 1) + + // check whether we can add the wound to an existing wound + for(var/datum/wound/other in wounds) + if(other.desc == W.desc) + // okay, add it! + other.damage += W.damage + other.amount += 1 + W = null // to signify that the wound was added + break + + // if we couldn't add the wound to another wound, ignore + if(W) + wounds += W + +/datum/organ/external/proc/emp_act(severity) + if(!(status & ORGAN_ROBOT)) + return + var/probability = 30 + var/damage = 15 + if(severity == 2) + probability = 1 + damage = 3 + if(prob(probability)) + droplimb(1) + else + take_damage(damage, 0, 1, used_weapon = "EMP") + +/datum/organ/external/proc/robotize() + src.status &= ~ORGAN_BROKEN + src.status &= ~ORGAN_BLEEDING + src.status &= ~ORGAN_SPLINTED + src.status &= ~ORGAN_ATTACHABLE + src.status &= ~ORGAN_DESTROYED + src.status |= ORGAN_ROBOT + for (var/datum/organ/external/T in children) + if(T) + T.robotize() + +/datum/organ/external/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" @@ -646,7 +637,7 @@ obj/item/weapon/organ/New(loc, mob/living/carbon/human/H) //Forming icon for the limb //Setting base icon for this mob's race - if(ishuman(H) && owner.dna) + if(ishuman(H) && H.dna) var/icon/base switch(H.dna.mutantrace) if("tajaran") @@ -657,8 +648,8 @@ obj/item/weapon/organ/New(loc, mob/living/carbon/human/H) base = new('icons/mob/human_races/r_skrell.dmi') else base = new('icons/mob/human_races/r_human.dmi') - if(I) - icon = I.MakeLying() + if(base) + icon = base.MakeLying() else icon_state = initial(icon_state)+"_l" diff --git a/code/datums/organs/wound.dm b/code/datums/organs/wound.dm index c9ef227c904..4e4c5d73a9d 100644 --- a/code/datums/organs/wound.dm +++ b/code/datums/organs/wound.dm @@ -131,31 +131,31 @@ return (!(bandaged||clamped) && (damage_type == BRUISE && damage >= 20 || damage_type == CUT) && current_stage <= max_bleeding_stage && !src.internal) /** CUTS **/ -/datum/wound/cut +/datum/wound/cut/small // link wound descriptions to amounts of damage max_bleeding_stage = 2 stages = list("ugly ripped cut" = 20, "ripped cut" = 10, "cut" = 5, "healing cut" = 2, "small scab" = 0) -/datum/wound/deep_cut +/datum/wound/cut/deep max_bleeding_stage = 3 stages = list("ugly deep ripped cut" = 25, "deep ripped cut" = 20, "deep cut" = 15, "clotted cut" = 8, "scab" = 2, "fresh skin" = 0) -/datum/wound/flesh_wound +/datum/wound/cut/flesh max_bleeding_stage = 3 stages = list("ugly ripped flesh wound" = 35, "ugly flesh wound" = 30, "flesh wound" = 25, "blood soaked clot" = 15, "large scab" = 5, "fresh skin" = 0) -/datum/wound/gaping_wound +/datum/wound/cut/gaping max_bleeding_stage = 2 stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "large clot" = 15, "small angry scar" = 5, \ "small straight scar" = 0) -/datum/wound/big_gaping_wound +/datum/wound/cut/gaping_big max_bleeding_stage = 2 stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large angry scar" = 10, "large straight scar" = 0) needs_treatment = 1 // this only heals when bandaged -/datum/wound/massive_wound +datum/wound/cut/massive max_bleeding_stage = 2 stages = list("massive wound" = 70, "massive healing wound" = 50, "massive angry scar" = 10, "massive jagged scar" = 0) @@ -169,50 +169,50 @@ needs_treatment = 1 // this only heals when bandaged damage_type = BRUISE -/datum/wound/bruise/monumental_bruise +/datum/wound/bruise/monumental // implement sub-paths by starting at a later stage -/datum/wound/bruise/huge_bruise +/datum/wound/bruise/huge current_stage = 1 -/datum/wound/bruise/large_bruise +/datum/wound/bruise/large current_stage = 2 -/datum/wound/bruise/moderate_bruise +/datum/wound/bruise/moderate current_stage = 3 needs_treatment = 0 -/datum/wound/bruise/small_bruise +/datum/wound/bruise/small current_stage = 4 needs_treatment = 0 -/datum/wound/bruise/tiny_bruise +/datum/wound/bruise/tiny current_stage = 5 needs_treatment = 0 /** BURNS **/ -/datum/wound/moderate_burn +/datum/wound/burn/moderate stages = list("ripped burn" = 10, "moderate burn" = 5, "moderate salved burn" = 2, "fresh skin" = 0) needs_treatment = 1 // this only heals when bandaged damage_type = BURN -/datum/wound/large_burn +/datum/wound/burn/large stages = list("ripped large burn" = 20, "large burn" = 15, "large salved burn" = 5, "fresh skin" = 0) needs_treatment = 1 // this only heals when bandaged damage_type = BURN -/datum/wound/severe_burn +/datum/wound/burn/severe stages = list("ripped severe burn" = 35, "severe burn" = 30, "severe salved burn" = 10, "burn scar" = 0) needs_treatment = 1 // this only heals when bandaged damage_type = BURN -/datum/wound/deep_burn +/datum/wound/burn/deep stages = list("ripped deep burn" = 45, "deep burn" = 40, "deep salved burn" = 15, "large burn scar" = 0) needs_treatment = 1 // this only heals when bandaged @@ -220,7 +220,7 @@ damage_type = BURN -/datum/wound/carbonised_area +/datum/wound/burn/carbonised stages = list("carbonised area" = 50, "treated carbonised area" = 20, "massive burn scar" = 0) needs_treatment = 1 // this only heals when bandaged From baec30f6902598ef2d659ac55dc72b75cd6d070b Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sun, 17 Feb 2013 22:06:26 +0400 Subject: [PATCH 4/6] Moved procs around, added comments. --- code/datums/organs/organ_external.dm | 519 ++++++++++++++------------- 1 file changed, 262 insertions(+), 257 deletions(-) diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm index 4ce631435b5..e45a6a15014 100644 --- a/code/datums/organs/organ_external.dm +++ b/code/datums/organs/organ_external.dm @@ -18,18 +18,17 @@ var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len! var/tmp/perma_injury = 0 - var/tmp/perma_dmg = 0 var/tmp/destspawn = 0 //Has it spawned the broken limb? - var/tmp/amputated = 0 // Whether this has been cleanly amputated, thus causing no pain + var/tmp/amputated = 0 //Whether this has been cleanly amputated, thus causing no pain var/min_broken_damage = 30 var/datum/organ/external/parent var/list/datum/organ/external/children var/damage_msg = "\red You feel an intense pain" + var/broken_description var/status = 0 - var/broken_description var/open = 0 var/stage = 0 @@ -48,98 +47,117 @@ parent.children.Add(src) return ..() +/datum/organ/external/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 + +/**************************************************** + DAMAGE PROCS +****************************************************/ + +/datum/organ/external/proc/emp_act(severity) + if(!(status & ORGAN_ROBOT)) //meatbags do not care about EMP + return + var/probability = 30 + var/damage = 15 + if(severity == 2) + probability = 1 + damage = 3 + if(prob(probability)) + droplimb(1) + else + take_damage(damage, 0, 1, used_weapon = "EMP") /datum/organ/external/proc/take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list()) if((brute <= 0) && (burn <= 0)) return 0 + if(status & ORGAN_DESTROYED) return 0 if(status & ORGAN_ROBOT) brute *= 0.66 //~2/3 damage for ROBOLIMBS burn *= 0.66 //~2/3 damage for ROBOLIMBS - //if(owner && !(status & ORGAN_ROBOT)) - // owner.pain(display_name, (brute+burn)*3, 1, burn > brute) + //If limb took enough damage, try to cut or tear it off + if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) + if( (sharp && prob(5 * brute)) || (brute > 20 && prob(2 * brute)) ) + droplimb(1) + return - if(sharp) - var/nux = brute * rand(10,15) - if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) - if(prob(5 * brute)) - droplimb(1) - return - - else if(prob(nux)) - createwound( CUT, brute ) - if(!(status & ORGAN_ROBOT)) - owner << "You feel something wet on your [display_name]" - - else if(brute > 20) - if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) - if(prob(5 * brute)) - droplimb(1) - return + if(status & ORGAN_BROKEN && prob(40) && brute) + owner.emote("scream") //getting hit on broken hand hurts + if(used_weapon) + add_autopsy_data(used_weapon, brute + burn) + var/can_cut = (prob(brute*2) || sharp) && !(status & ORGAN_ROBOT) // If the limbs can break, make sure we don't exceed the maximum damage a limb can take before breaking if((brute_dam + burn_dam + brute + burn) < max_damage || !config.limbs_can_break) if(brute) - if( (prob(brute*2) && !sharp) || sharp ) + if(can_cut) createwound( CUT, brute ) - else if(!sharp) + else createwound( BRUISE, brute ) if(burn) createwound( BURN, burn ) else - // If we can't inflict the full amount of damage, spread the damage in other ways - var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam) //How much damage can we actually cause? + //If we can't inflict the full amount of damage, spread the damage in other ways + //How much damage can we actually cause? + var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam) if(can_inflict) if (brute > 0) - brute = can_inflict - createwound(BRUISE, brute) - if (burn > 0) - burn = can_inflict - createwound(BURN, burn) - else if(!(status & ORGAN_ROBOT)) - var/passed_dam = (brute + burn) - can_inflict //Getting how much overdamage we have. - var/list/datum/organ/external/possible_points = list() - if(parent) - possible_points += parent - if(children) - possible_points += children - if(forbidden_limbs.len) - possible_points -= forbidden_limbs - if(!possible_points.len) - if(owner.stat != 2) - message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage to!") - else - var/datum/organ/external/target = pick(possible_points) - if(brute) - target.take_damage(passed_dam, 0, sharp, used_weapon, forbidden_limbs + src) + //Inflict all burte damage we can + if(can_cut) + createwound( CUT, min(brute,can_inflict) ) else - target.take_damage(0, passed_dam, sharp, used_weapon, forbidden_limbs + src) - else - droplimb(1) //Robot limbs just kinda fail at full damage. + createwound( BRUISE, min(brute,can_inflict) ) + var/temp = can_inflict + //How much mroe damage can we inflict + can_inflict = max(0, can_inflict - brute) + //How much brute damage is left to inflict + brute = max(0, brute - temp) - - if(status & ORGAN_BROKEN) - owner.emote("scream") - - if(used_weapon) add_autopsy_data(used_weapon, brute + burn) - - owner.updatehealth() + if (burn > 0 && can_inflict) + //Inflict all burn damage we can + createwound(BURN, min(burn,can_inflict)) + //How much burn damage is left to inflict + burn = max(0, burn - can_inflict) + //If there are still hurties to dispense + if (burn || brute) + if (status & ORGAN_ROBOT) + droplimb(1) //Robot limbs just kinda fail at full damage. + else + //List organs we can pass it to + var/list/datum/organ/external/possible_points = list() + if(parent) + possible_points += parent + if(children) + possible_points += children + if(forbidden_limbs.len) + possible_points -= forbidden_limbs + if(possible_points.len) + //And pass the pain around + var/datum/organ/external/target = pick(possible_points) + target.take_damage(brute, burn, sharp, used_weapon, forbidden_limbs + src) // sync the organ's damage with its wounds src.update_damages() + owner.updatehealth() var/result = update_icon() return result - - /datum/organ/external/proc/heal_damage(brute, burn, internal = 0, robo_repair = 0) if(status & ORGAN_ROBOT && !robo_repair) return - // heal damage on the individual wounds + //Heal damage on the individual wounds for(var/datum/wound/W in wounds) if(brute == 0 && burn == 0) break @@ -150,44 +168,104 @@ else if(W.damage_type == BURN) burn = W.heal_damage(burn) - // sync organ damage with wound damages - update_damages() - if(internal) status &= ~ORGAN_BROKEN perma_injury = 0 - // sync the organ's damage with its wounds + //Sync the organ's damage with its wounds src.update_damages() - owner.updatehealth() + var/result = update_icon() return result -/datum/organ/external/proc/update_damages() - number_wounds = 0 - brute_dam = 0 - burn_dam = 0 - status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) - if(W.damage_type == CUT || W.damage_type == BRUISE) - brute_dam += W.damage - else if(W.damage_type == BURN) - burn_dam += W.damage - if(!(status & ORGAN_ROBOT) && W.bleeding()) - status |= ORGAN_BLEEDING +/datum/organ/external/proc/createwound(var/type = CUT, var/damage) + if(damage == 0) return - number_wounds += W.amount + // first check whether we can widen an existing wound + if(wounds.len > 0 && prob(max(50+owner.number_wounds*10,100))) + if((type == CUT || type == BRUISE) && damage >= 5) + var/datum/wound/W = pick(wounds) + if(W.amount == 1 && W.started_healing()) + W.open_wound(damage) + if(prob(25)) + owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping voice.",\ + "\red The wound on your [display_name] widens with a nasty ripping voice.",\ + "You hear a nasty ripping noise, as if flesh is being torn apart.") + return + //Creating wound + var/datum/wound/W + var/size = min( max( 1, damage/10 ) , 6) + //Possible types of wound + var/list/size_names = list() + switch(type) + if(CUT) + size_names = typesof(/datum/wound/cut/) - /datum/wound/cut/ + if(BRUISE) + size_names = typesof(/datum/wound/bruise/) - /datum/wound/bruise/ + if(BURN) + size_names = typesof(/datum/wound/burn/) - /datum/wound/burn/ + + var/wound_type = size_names[size] + W = new wound_type(damage) + + //Possibly trigger an internal wound, too. + var/local_damage = brute_dam + burn_dam + damage + if(damage > 10 && type != BURN && local_damage > 20 && prob(damage) && !(status & ORGAN_ROBOT)) + var/datum/wound/internal_bleeding/I = new (15) + wounds += I + owner.custom_pain("You feel something rip in your [display_name]!", 1) + + //Check whether we can add the wound to an existing wound + for(var/datum/wound/other in wounds) + if(other.desc == W.desc) + // okay, add it! + other.damage += W.damage + other.amount += 1 + W = null // to signify that the wound was added + break + if(W) + wounds += W + +/**************************************************** + PROCESSING & UPDATING +****************************************************/ + +/datum/organ/external/process() + // process wounds, doing healing etc., only do this every 4 ticks to save processing power + if(owner.life_tick % wound_update_accuracy == 0) + update_wounds() + if(status & ORGAN_DESTROYED) + if(!destspawn && config.limbs_can_break) + droplimb() + return + if(!(status & ORGAN_BROKEN)) + perma_injury = 0 + if(parent) + if(parent.status & ORGAN_DESTROYED) + status |= ORGAN_DESTROYED + owner.update_body(1) + return + if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) + src.fracture() + if(germ_level > 0) + for(var/datum/wound/W in wounds) if(!W.bandaged && !W.salved) + W.germ_level = max(W.germ_level, germ_level) + update_icon() + return + +//Updating wounds. Handles wound natural healing, internal bleedings and infections /datum/organ/external/proc/update_wounds() for(var/datum/wound/W in wounds) // wounds can disappear after 10 minutes at the earliest if(W.damage == 0 && W.created + 10 * 10 * 60 <= world.time) wounds -= W // let the GC handle the deletion of the wound + + // Internal wounds get worse over time. Low temperatures (cryo) stop them. if(W.internal && !W.is_treated() && owner.bodytemperature >= 170) - // internal wounds get worse over time W.open_wound(0.1 * wound_update_accuracy) owner.vessel.remove_reagent("blood",0.07 * W.damage * wound_update_accuracy) if(prob(1 * wound_update_accuracy)) @@ -213,78 +291,34 @@ // sync the organ's damage with its wounds src.update_damages() -/datum/organ/external/proc/bandage() - var/rval = 0 - src.status &= ~ORGAN_BLEEDING +//Updates brute_damn and burn_damn from wound damages. Updates BLEEDING status. +/datum/organ/external/proc/update_damages() + number_wounds = 0 + brute_dam = 0 + burn_dam = 0 + status &= ~ORGAN_BLEEDING for(var/datum/wound/W in wounds) - if(W.internal) continue - rval |= !W.bandaged - W.bandaged = 1 - return rval + if(W.damage_type == CUT || W.damage_type == BRUISE) + brute_dam += W.damage + else if(W.damage_type == BURN) + burn_dam += W.damage -/datum/organ/external/proc/clamp() - var/rval = 0 - src.status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) - if(W.internal) continue - rval |= !W.clamped - W.clamped = 1 - return rval + if(!(status & ORGAN_ROBOT) && W.bleeding()) + status |= ORGAN_BLEEDING -/datum/organ/external/proc/salve() - var/rval = 0 - for(var/datum/wound/W in wounds) - rval |= !W.salved - W.salved = 1 - return rval + number_wounds += W.amount -/datum/organ/external/proc/get_damage() //returns total damage - return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health? -/datum/organ/external/proc/get_damage_brute() - return max(brute_dam+perma_injury, perma_injury) - -/datum/organ/external/proc/get_damage_fire() - return burn_dam - -/datum/organ/external/proc/is_infected() - for(var/datum/wound/W in wounds) - if(W.germ_level > 100) - return 1 +// new damage icon system +// adjusted to set damage_state to brute/burn code only (without r_name0 as before) +/datum/organ/external/proc/update_icon() + var/n_is = damage_state_text() + if (n_is != damage_state) + damage_state = n_is + owner.update_body(1) + return 1 return 0 -/datum/organ/external/process() - // process wounds, doing healing etc., only do this every 4 ticks to save processing power - if(owner.life_tick % wound_update_accuracy == 0) - update_wounds() - if(status & ORGAN_DESTROYED) - if(!destspawn && config.limbs_can_break) - droplimb() - return - if(!(status & ORGAN_BROKEN)) - perma_dmg = 0 - if(parent) - if(parent.status & ORGAN_DESTROYED) - status |= ORGAN_DESTROYED - owner.update_body(1) - return - if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) - src.fracture() - if(germ_level > 0) - for(var/datum/wound/W in wounds) if(!W.bandaged && !W.salved) - W.germ_level = max(W.germ_level, germ_level) - update_icon() - return - -/datum/organ/external/proc/fracture() - if(status & ORGAN_BROKEN) - return - owner.visible_message("\red You hear a loud cracking sound coming from \the [owner].","\red Something feels like it shattered in your [display_name]!","You hear a sickening crack.") - owner.emote("scream") - status |= ORGAN_BROKEN - broken_description = pick("broken","fracture","hairline fracture") - perma_injury = brute_dam - // new damage icon system // returns just the brute/burn damage code /datum/organ/external/proc/damage_state_text() @@ -313,22 +347,17 @@ tbrute = 3 return "[tbrute][tburn]" +/**************************************************** + DISMEMBERMENT +****************************************************/ -// new damage icon system -// adjusted to set damage_state to brute/burn code only (without r_name0 as before) -/datum/organ/external/proc/update_icon() - var/n_is = damage_state_text() - if (n_is != damage_state) - damage_state = n_is - owner.update_body(1) - return 1 - return 0 - +//Recursive setting of all child organs to amputated /datum/organ/external/proc/setAmputatedTree() for(var/datum/organ/external/O in children) O.amputated=amputated O.setAmputatedTree() +//Handles dismemberment /datum/organ/external/proc/droplimb(var/override = 0,var/no_explode = 0) if(destspawn) return if(override) @@ -348,7 +377,7 @@ if(O.parent == src) O.droplimb(1) - var/obj/organ + var/obj/organ //Dropped limb object switch(body_part) if(LOWER_TORSO) owner << "\red You are now sterile." @@ -392,6 +421,7 @@ owner.u_equip(owner.shoes) if(organ) destspawn = 1 + //Robotic limbs explode until specified otherwise if(status & ORGAN_ROBOT && !no_explode) owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\ "\red Your [display_name] explodes!",\ @@ -407,78 +437,51 @@ owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\ "Your [display_name] goes flying off!",\ "You hear a terrible sound of ripping tendons and flesh.") + + //Throw organs around var/lol = pick(cardinal) step(organ,lol) - // force the icon to rebuild + owner.regenerate_icons() -/datum/organ/external/proc/createwound(var/type = CUT, var/damage) - if(damage == 0) return - // first check whether we can widen an existing wound - if(wounds.len > 0 && prob(max(50+owner.number_wounds*10,100))) - if((type == CUT || type == BRUISE) && damage >= 5) - var/datum/wound/W = pick(wounds) - if(W.amount == 1 && W.started_healing()) - W.open_wound(damage) - if(prob(25)) - owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping voice.",\ - "\red The wound on your [display_name] widens with a nasty ripping voice.",\ - "You hear a nasty ripping noise, as if flesh is being torn apart.") - return +/**************************************************** + HELPERS +****************************************************/ - // the wound we will create - var/datum/wound/W - var/wound_type - var/size = min( max( 1, damage/10 ) , 6) +/datum/organ/external/proc/bandage() + var/rval = 0 + src.status &= ~ORGAN_BLEEDING + for(var/datum/wound/W in wounds) + if(W.internal) continue + rval |= !W.bandaged + W.bandaged = 1 + return rval - switch(type) - if(CUT) - var/list/size_names = typesof(/datum/wound/cut/) - /datum/wound/cut/ - wound_type = size_names[size] +/datum/organ/external/proc/clamp() + var/rval = 0 + src.status &= ~ORGAN_BLEEDING + for(var/datum/wound/W in wounds) + if(W.internal) continue + rval |= !W.clamped + W.clamped = 1 + return rval - if(BRUISE) - var/list/size_names = typesof(/datum/wound/bruise/) - /datum/wound/bruise/ - wound_type = size_names[size] +/datum/organ/external/proc/salve() + var/rval = 0 + for(var/datum/wound/W in wounds) + rval |= !W.salved + W.salved = 1 + return rval - if(BURN) - var/list/size_names = typesof(/datum/wound/burn/) - /datum/wound/burn/ - wound_type = size_names[size] - - W = new wound_type(damage) - - // Possibly trigger an internal wound, too. - var/local_damage = brute_dam + burn_dam + damage - if(damage > 10 && type != BURN && local_damage > 20 && prob(damage) && !(status & ORGAN_ROBOT)) - var/datum/wound/internal_bleeding/I = new (15) - wounds += I - owner.custom_pain("You feel something rip in your [display_name]!", 1) - - // check whether we can add the wound to an existing wound - for(var/datum/wound/other in wounds) - if(other.desc == W.desc) - // okay, add it! - other.damage += W.damage - other.amount += 1 - W = null // to signify that the wound was added - break - - // if we couldn't add the wound to another wound, ignore - if(W) - wounds += W - -/datum/organ/external/proc/emp_act(severity) - if(!(status & ORGAN_ROBOT)) +/datum/organ/external/proc/fracture() + if(status & ORGAN_BROKEN) return - var/probability = 30 - var/damage = 15 - if(severity == 2) - probability = 1 - damage = 3 - if(prob(probability)) - droplimb(1) - else - take_damage(damage, 0, 1, used_weapon = "EMP") + owner.visible_message("\red You hear a loud cracking sound coming from \the [owner].","\red Something feels like it shattered in your [display_name]!","You hear a sickening crack.") + owner.emote("scream") + status |= ORGAN_BROKEN + broken_description = pick("broken","fracture","hairline fracture") + perma_injury = brute_dam /datum/organ/external/proc/robotize() src.status &= ~ORGAN_BROKEN @@ -491,16 +494,18 @@ if(T) T.robotize() -/datum/organ/external/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 +/datum/organ/external/proc/get_damage() //returns total damage + return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health? - W.hits += 1 - W.damage += damage - W.time_inflicted = world.time +/datum/organ/external/proc/is_infected() + for(var/datum/wound/W in wounds) + if(W.germ_level > 100) + return 1 + return 0 + +/**************************************************** + ORGAN DEFINES +****************************************************/ /datum/organ/external/chest name = "chest" @@ -519,37 +524,6 @@ min_broken_damage = 70 body_part = LOWER_TORSO -/datum/organ/external/head - name = "head" - icon_name = "head" - display_name = "head" - max_damage = 75 - min_broken_damage = 40 - body_part = HEAD - var/disfigured = 0 - - take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list()) - ..(brute, burn, sharp, used_weapon, forbidden_limbs) - if (!disfigured) - if (brute_dam > 40) - if (prob(50)) - disfigure("brute") - if (burn_dam > 40) - disfigure("burn") - - proc/disfigure(var/type = "brute") - if (disfigured) - return - if(type == "brute") - owner.visible_message("\red You hear a sickening cracking sound coming from \the [owner]'s face.", \ - "\red Your face becomes unrecognizible mangled mess!", \ - "\red You hear a sickening crack.") - else - owner.visible_message("\red [owner]'s face melts away, turning into mangled mess!", \ - "\red Your face melts off!", \ - "\red You hear a sickening sizzle.") - disfigured = 1 - /datum/organ/external/l_arm name = "l_arm" display_name = "left arm" @@ -618,6 +592,37 @@ min_broken_damage = 15 body_part = HAND_LEFT +/datum/organ/external/head + name = "head" + icon_name = "head" + display_name = "head" + max_damage = 75 + min_broken_damage = 40 + body_part = HEAD + var/disfigured = 0 + + take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list()) + ..(brute, burn, sharp, used_weapon, forbidden_limbs) + if (!disfigured) + if (brute_dam > 40) + if (prob(50)) + disfigure("brute") + if (burn_dam > 40) + disfigure("burn") + + proc/disfigure(var/type = "brute") + if (disfigured) + return + if(type == "brute") + owner.visible_message("\red You hear a sickening cracking sound coming from \the [owner]'s face.", \ + "\red Your face becomes unrecognizible mangled mess!", \ + "\red You hear a sickening crack.") + else + owner.visible_message("\red [owner]'s face melts away, turning into mangled mess!", \ + "\red Your face melts off!", \ + "\red You hear a sickening sizzle.") + disfigured = 1 + /**************************************************** EXTERNAL ORGAN ITEMS ****************************************************/ From 334da25223fa232d61270d3793f0801aecd356cf Mon Sep 17 00:00:00 2001 From: Chinsky Date: Mon, 18 Feb 2013 13:22:23 +0400 Subject: [PATCH 5/6] Added surgery to put things in people. --- code/datums/organs/organ_external.dm | 1 + code/modules/surgery/other.dm | 68 ++++++++++++++++++++++++---- html/changelog.html | 7 +++ 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm index e45a6a15014..31a5c2f1275 100644 --- a/code/datums/organs/organ_external.dm +++ b/code/datums/organs/organ_external.dm @@ -32,6 +32,7 @@ var/open = 0 var/stage = 0 + var/obj/item/hidden = null var/list/implants = list() // INTERNAL germs inside the organ, this is BAD if it's greater 0 var/germ_level = 0 diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 8c0d01c06d8..5d8c98053a4 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -80,15 +80,23 @@ find_prob +=40 if (isright(tool)) find_prob +=20 - - if (prob(find_prob)) + if (prob(find_prob)) + user.visible_message("\blue [user] takes something out of incision on [target]'s [affected.display_name] with \the [tool].", \ + "\blue You take something out of incision on [target]'s [affected.display_name]s with \the [tool]." ) + affected.implants -= imp + imp.loc = get_turf(target) + imp.imp_in = null + imp.implanted = 0 + else if (affected.hidden) user.visible_message("\blue [user] takes something out of incision on [target]'s [affected.display_name] with \the [tool].", \ "\blue You take something out of incision on [target]'s [affected.display_name]s with \the [tool]." ) - var/obj/item/weapon/implant/imp = affected.implants[1] - affected.implants -= imp - imp.loc = get_turf(target) - imp.imp_in = null - imp.implanted = 0 + affected.hidden.loc = get_turf(target) + if(!affected.hidden.blood_DNA) + affected.hidden.blood_DNA = list() + affected.hidden.blood_DNA[target.dna.unique_enzymes] = target.dna.b_type + affected.hidden.update_icon() + affected.hidden = null + else user.visible_message("\blue [user] could not find anything inside [target]'s [affected.display_name], and pulls \the [tool] out.", \ "\blue You could not find anything inside [target]'s [affected.display_name]." ) @@ -107,4 +115,48 @@ user.visible_message("\red Something beeps inside [target]'s [affected.display_name]!") playsound(imp.loc, 'sound/items/countdown.ogg', 75, 1, -3) spawn(25) - imp.activate() \ No newline at end of file + imp.activate() + +////////////////////////////////////////////////////////////////// +// ITEM PLACEMENT SURGERY // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/item_place + required_tool = /obj/item + + min_duration = 80 + max_duration = 100 + var/max_size = 2 //maximum w_class of item that fits. + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + if (affected.name in list("chest","groin","head")) + max_size = 3 + return affected.open == 2 && !(affected.status & ORGAN_BLEEDING) && tool.w_class <= max_size && !affected.hidden + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] starts putting [tool] inside the incision on [target]'s [affected.display_name].", \ + "You start putting [tool] inside the incision on [target]'s [affected.display_name]." ) + target.custom_pain("The pain in your chest is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/chest/affected = target.get_organ(target_zone) + + user.visible_message("\blue [user] puts [tool] inside [target]'s [affected.display_name].", \ + "\blue You put [tool] inside [target]'s [affected.display_name]." ) + if (tool.w_class > max_size/2 && prob(50)) + user << "\red You tear some vessels trying to fit such big object in this cavity." + var/datum/wound/internal_bleeding/I = new (15) + affected.wounds += I + affected.owner.custom_pain("You feel something rip in your [affected.display_name]!", 1) + user.drop_item() + affected.hidden = tool + tool.loc = target + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/chest/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, scraping tissue inside [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, scraping tissue inside [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(CUT, 20) diff --git a/html/changelog.html b/html/changelog.html index a2ac370d751..0578670796c 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -58,6 +58,13 @@ Stuff which is in development and not yet visible to players or just code relate should be listed in the changelog upon commit though. Thanks. --> +
+

18.02.13

+

Chinsky updated:

+
    +
  • Added new surgery: putting items inside people. After you use retractor to keep incision open, just click with any item to put it inside. But be wary, if you try to fit something too big, you might rip the veins. To remove items, use implant removal surgery.
  • +
+

February 18th 2013

From c403582ea1b41f5d767791da9143a14e3e81abe5 Mon Sep 17 00:00:00 2001 From: Gamerofthegame Date: Mon, 18 Feb 2013 17:27:58 -0500 Subject: [PATCH 6/6] Changes the Security hardsuit from the fugly TG one into the pre-merge Bay one. --- icons/mob/head.dmi | Bin 125268 -> 125276 bytes icons/mob/suit.dmi | Bin 269553 -> 269559 bytes icons/obj/clothing/hats.dmi | Bin 45459 -> 45459 bytes icons/obj/clothing/suits.dmi | Bin 65635 -> 65633 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 1f8d62db91f7eca7ee35d1006c6d2ad094a97da6..aba2c63aef679d71d80c8142ca095715d6d80441 100644 GIT binary patch delta 1775 zcmVj=%w;R7R1V2r_D%_-1_fiYwwX@n*YAP;pnHb+H92cAp0an3_jesj+lBdu4-`0i%HDK;tOpKn?(Z6LK6}dE z-{0*V4eYb0th~h@FI@RL*D!_7|2I(+mAs&F*;;H=uNDglRV^EKq}K%RIvf0GL-v%F zA08gdhu6(9U(e#Kw(S9l{tRQ%p4H?eVA3ZTlm1Rdf_0Gckp+b9Q2R;ZbL|A;lGVPG zz_{=&ACdn@$7l0@g2m(ZtYBf!3Y-^8*aY!FqL*}B+yO7OL*8aTl8QeqKa%3On4%HW zJApua2h)h6z z8(nUDGncj-9lNb#b(_b^rj?CDWz)*mk+Nxplh=c#E#P=hz*@H_WKr8w$Vp>zIq8&j z5>G;0G}y5N20dfQCf{=b?C?DonApk_e|LY^u%<)yl$8%xmA|5X^--@|g>EtpyT%Uj z>@L{&820jilU)2AoiShzkO_o5uoD=U9QV>j<;K0V$e}W@3i2G!;h6+x0h^%g5T8^t z2Nj}$B)%ISIUs{Ha{LT7(#XK+3qCF4C&g#!#k3#>57Rchcr|*=qSUhisBTb-*4OR0j;+dPQS=(AFy&fyLcwQQWbP??4wc zF1ynds;f97Ah0gmeQggQ1`J#rQftl_(D5SEkfC_5YvzFXG_?~qRv``0B@9d^@${ELd20ioZZ-5-o!B9rf{yF4zq#(OS0?U5Okw zV8wnWfhRv119bl-93pZf=6hW4$N{s?3NYKO0JBWdi0scZ zhMY!d)Fh_rtc{0wMaRX>1nQnZWXZDeUBHP2HUTp^&qy=i1R@t+dkwsvGX@=Iz1;!b zikX82tDTl{M0%gseB43nmOqr^vEG=rRag;by^#)p?oMGKK%JY0eB_sP&;<< z?=DUta(?t-a!^VxC{$c23(SNghx8lWu>O6>4fYrxOFJKCpyT6(MP_U}d0@V_lSlSX z*IH;*J(CHd@XGqa0$5u$HA2X7?My;{kvFwDHzrxal0`m=g(+C(Z zEL$eX7P)8j?`JStR*y^em(ilKB`T{X9pE+S!eX^%)mhsh-v%sUsJw#8f+GhD!X?2C z4{T3*VkqPjh)cpj-x`2NL@4YtnIH-W{=y>eWWLmdLcgFXvT*P(O`sGV(6k@mtRGU7 zen^XYzJ`V3zMv_xaO^KlfRl@V3|QI(jIZf0ZJ;Yy?6&I!0`q;h6U7dbUBbZq0l9_^ro3R$l9C%yK$BuF{c!lKj8>p1 zT{F3nf$HQ00u9Q6JkkO@a!Au(RL`bk;GYf)7Hg%(J2gMpSfEqmq%CrP3Im{cLBYof z%a*7tX;EAaN;#&gOu9|GHBEK4*%k18E4hQIdfBmC_wzap6h2cg)j+{dO=`-nO*b1N zxxThQdOX%w)MyeQV@nvgv9gZ3s&>-0K55j~hN+H{p3JRj$_+6$&tj^;n#a!iv9rje zd(8-VN-p64EL_5vw6eopK&Aoi0$9YB@wuRd)n^=+$Nn(1fRX#Lw(3|9mFgI{*ty16<=8+9E0ozx9kQ1XyVkrVhaEO delta 1767 zcmVa!B?Os7CZa2O+VN@MQAzdtm-BV`F_H$Eo`D*R4iKtrqh>`}@m3U%zLc zzkR)bX6MD4>?!;BM{$3*mnL-CQ}*HU{;p$byDsg%Dwml%xpJ7bevznX)O!@?4(m%*Zuntl_vVgE1YClPQuAM+!vf6hN z7#F_fBl7?1_-tN(uz1{_6)fyof%8HMn;;%Y^pcK?JK&{u$lL5kQt_wdM^YRYQ#4|F zClHA5U>Z>rIPX{wdFz->Jlt1|wzMHmz(ODVtU}c|BO#0*?0ttaW=r7PUQvoHQnvlTKMD z@g&4WgB?3y&@+Z?@;w*84&QTuiLE^G5BGNsYdU04S^02P`77#IAN9Ib=qA&!YwQru z?t+bvVK2Xb$i?5$83X13nLx+`JArY@aW8FDZrn?Y94Z5=AkXm}o=IR9unEcz@kupv zP$3#f;=AFI12RY>$IoCRjSQT=;L{?0Qhb(PObcQ_{yN^plh^SsF4d81ItoQ~V6E*w z-rcz7VFzWRgEG}YQGq4E4WBTAGzVp>g91F8U*idX@h8cbiSk8-R6k}pwtCv9$*t(LbrWRnc41NO+EI$-eDD;nd2wqDT)Ebdl|;*NEE2fCnf z*`20PUBwvzfpyvLYkL4OVBq4AT64yLju)AR48?n0GY7<{shzm73Tc2YVPFa|HC_u) z3!X`TAOY-v{(a33Y2Q!2Bhyo3_whPr!NS5*`~^CbXc3(6sE=oK!ERWI*1DbOO60f! zEA}%9Jo(8Op!+`=0~K>ta{z-}!g1+d!dl(=>E`5geR}F8Aa!UjAsoaQpjf`3!0ck( zh-ufS?47oDT(Mb|UpGp36CcAsPJDcEoH5{k5Rn@(KjL~v4w!XTfZ1jRm}QDaWPhG9 zqG3YSs?GETx z%p5FO?X-*|()+yT;|^NKY|vU|34;YdRZ|0;;udUN_$M2nKk}0e(j6H%IOJtNazLGb z#sQk7M-EvlMGq9OdyX8igiJbMtH%*UB)KNN^6A1~uWY6dCYDmz$;;g+Odm& zcX0xd^P>-wgHm!qq2fweU?v%yWx>;f0F(+4jmYa9P310P)N4KWy=KFB4^WzVRmnv zJXQ_B$P-xyvEssIig1zpgJ}c{*dI)PBVfF+ zY?&ZiP}pZOK@<-Bg+<)Se3=P_enC@Y;ox7IKq)$)X+OYOKcpu8kQViP{R+i> zK~rSm*k76eCl(p7*iRrX3CDeZYXGzwCO2vW^y9~)yWA2 z8j}Ngr1f{?kY>NAo=wNVKO7b;)K!?UjTjUf5K=Fctj}w-EEm2w0qPQBA za!gg3bc=Rtn(Az`tGJ^;?qI53cI?*uyiNm!&(upbQ1DZenzC!t&4x&>uPu@bjNfIGk|8WTrVx48w237`5=kn#z}dlp!-uV}n`0gIOj;(l_iqOk)1_p_vN z@wv!_)n^=+$NoIDfRVehw(3|9mFgI{fBSm>KfuRJ{i3!0iG%b8 JxAX=9XyO_|VZ;Cc diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 3e1964161f7775411dca5787afec9dd84c0bca8a..55a1dd3c104c030184303639ac23c32864fb4584 100644 GIT binary patch delta 1565 zcmV+&2IBegxe)ic5RfE)<$6?DbVOxyV{&P5bZKvH004NLotnXN+c*q{&+$`e+H1VC z^>$}Zx$Lyl$)W9KPkYfoBrGA3NG(V?ah`q;l5EM1!=IU)GV|dFK|urv`D5|-*KhYf ziZ9>qHwV@r-W7Mn=ih$c+&qbmO>tNJvD@4ic}?n(c3#tBmLr=e2i{_`7kt`*icbfx z;(@@cp=~+#>is^woo5yh7M~Ur4+)huJ638D!I{N`52C*H^$}8@VN5!(8B`)BJ;Rvv z138I6Vl7y3%|_UNMG3&GwWKj|(?J~h_VR{74Vb^vzj6{CDt9j71hD>nI#yppT)qZ-YB^4;k>;?noT#jck8u-Mg- z6;*EjWoKTk%x-H*b6%#iQI4zZRCrGkWWGVjyQ5NXp(AnR(t-ysSJXalZY;NSEbfZk z?e2DWyIWgb(SFM;L?x-4SU!+>1RC)RJ{?VLSUaHMo4B-K!*ocuV&RF>!8A+m-LmW1~c=^y5JU=-;T=7<24Tm&9}54i}0{V-UdEqNF$(u(j8|u}kUsmeX1MfgDiqzN<1LRt& z2e#fI)1oB|G*mvMJ0&0BRs|XlEm&ZM1eJ#oOUvy=8JalFAQU>*V$2|Lhz+4_{b~PumfLj)*uoNe{qgFfHkZbhvH+LNyKbEr}}|?=5h@zu?mj zr0ZE_=*rH!bd6upX>lMmB#zg*61yp{c_jB%2Bq(j>BTEX_*n$GSi)JyT%P=FfV-$O z)ay*)ytU5;xQm0N3)O@G28&0=>Q%g8cIx}r%3*1Tc&#-*-&soBGi=Pef z68at-IElqPvV*Grf<>CARxBNR6=Y;gMz{C7ryZK%P^$qXX1A$sF~ zTKm`LG=TneyZHOn{)(qRUlI7#*zeOX%7R6%{vitRd2-^AUb!9uGCG_=P!ej_P9!in zB(?0&ZvrbC>G0K7UTdJkA3>mRCKnpf^ipRK7(=%MM@lbp;-K*qKUVViU48 z4%|O9;y;XE!kD!2T}RFWk7q?=;^ P1_Fl?1_QSe1_a+08A0bM delta 1565 zcmV+&2IBemxe)QW5RfE)-+EM7bVOxyV{&P5bZKvH004NLotnXN<2DS2&+$`ecCT@# zaktY`E}iUja@gH_FB*!3B_tB5f|L{Q)Au0Bmb`KBGm}$hKKvjkhyWpfF8==d&*S&v z;oIZpKoU9l;=cIu+wYs37j~&B?u$Qmo12EXZqoQqOeRrrUwqnsv(Tr_jbn+$eeq>; zvlr7*EbfcDHMBcZcW+Y_x!4dTRc;1#Nh4hlRnJHlL>F_E$R<9}7L&c;bqB&h4_-I` zfmcJ@QtBmyy}q4i77*s33vz&j%9=chX%WGh#e@$mp$+vBQl4QwnDmqJ zoPfkyu;7|4lTRFffmdruW8$`hGNQB{k`+zRr(oG|P8?Cm)DQJ`xxCn)AaVUvpMe zx%ro!d9@JvtuvDIGM$ZbTxF-iN0K1(4MN@>;d%=li6f^A9s*xc`?9%l)S6>)U+ivo zx4YZj+Ukn-duB0-;krrXld;c0BYwf_(WHi?0~)@G(*+wc2fY=GFGdfhA#(s4wfJIy zKpmOX#Qz3=pwymGUA8rq4L~dtm+?B_Zvv3B1az7Qf*Q=wRgl~a0y*fggL2{!L8Ou- z2i1-j{%OQ*_vTrDBnuW51~q|$jvT0XB7wx=&{6_*moSj%ThIQ4Kqk*7VrOYrz65MO8B-8`5*!HUy-N=_TkdtLY^G??BIj)YuUNB)iPHr;BOLY9cEq3~A`PDP0oV-cl77&`^#c&9ZA{-9_GJ@-1Mc@1yzYRz zo`i?4?1I;8{EF7afz;qMUh7Kiro85n+*=uxp+}|{Zy4cc5#(YCXB~5S^0NW%qRvpS zGllckJ{#aJ4y+fd1)C+DxAxf}qeg&`+fi%PMF6Abn0H>j&w9t0(zL9vc6hQD7Tt@NzPP$ZW{GbFKY< zYjYYv-`y_$ezm{i>CZO=el-qz{Y6=@$kjh420l+t9MUV-LqtZ0GYCpT?b?Y1CWl5G zdGwpWibgtoaaE8S=cV+*IA-}+SOCel-?Jr2#)CdC4WQ?c6T}*advq(2Dx$TngF%{87QkM#5_8Xvh-gZT7s9uALZszLlX_ssNgF?PB7xpNrz zGB!-WXZQ;qxPm9)z9%W`G8{;M?-wius@y$xpFD@i_0#Ubik9xN+wUF@N|D#!H>{kg4Oymt>dQY1*|y$HhTGI7 zSus?(_Z(vHlsVlM)LYWy*2t`s+~$W|qxvAu1JnBJ*!|YvDJ+{Gb_!%R&&w3Z9Pe9< zHT3Q$?IQ!J^|QeH)^d&2dk5v@+;IX2}ul|^uHJbM8u>>d9rwAaGt zVrXt-q}Ed%#tVm#&nUm&$Pc51EcqtC2_Ht#d~fpG_yJshpPT$9d>9e?ziA`ze3rH~ z%sGf*&!KH#hd^~i(&@~>BDOS(B3sHt$x@=WTp+iw%?7Du&tyvwz+)#?pmAM_r*tHn z&uxdlvI{Vi@9bVh+vY8<&wyztTX5WINvUnIC&_^;D0!5Mxc1cp3mY^Wf!U6v zQrdY|`XuRBrOlnPwBOgzjGa*o%}DJTPjetiqtCfLdRjnGCAVuJEm|09zovW++^*5W zrsM-~x>>pL5M-VKV|2=#U{|3Tc+`oN>o}1G_LIm}k<@tQ1hkbiS7^?Yi~<^eE&wzF z-KBTy4)edd`SNr2Whqq*&yw2b)GG@%KUW%RWv(oC=Dos5D-g*o1+W-(8LGG&iPu~p zD}?OKhSW}3-PqpIZoSjI#Q6xEt#17j8oh82U)q?QxLu4c-fIy!g~(9 zyM}I>HG8UUz!bhRXN~%n*abH X07*naRCt{1oq2pyRr>$4Bm{4*k+A@= delta 1000 zcmVOKFGYgFhop}njL2DXy!@jMsg>7H z--Fic7D&KPzS+QUK2qe&$07G~_vg32o_=&+zds!=tVMF_9=k8U4TpzSZ1vq^_s8#t z2hZYs-To<+DtC|FC(j{r{d9P+qNRK6j)#YnQsnLLJ62X|Lzbz3`tr|0wyigl;Wl+m zRt#0{J%`vkWlkRo>MiMcZ)8?VZuca&s6L4Ez_R{2_P95A3d`=vPJztsb(sR0^T#%0 z3;pm+`^Z3Q{Vecfd%4BxM+fEP6@Oph?y|d!U3@c_p>|iOy|F%au))3-F1Q zDj~xgI`aTg?X@v~oT|wYP@5}BJC&+;IX2}ul|^uHT)hAl_J;o*+I!)1 zF*LU^QtPP>=PthsA4bIf@7f4FuhO=L zIR`Q9IkXMz6sV3!I;|WmVoS3qa->X@EG25o1#%19Y>-;^Otu68Ja%FQ8rP+GN@ucp zZ9DvpU4WI8SJL)QuTqU~o42?=1E!&D!EvW0rMAUhBnPgb+BXj@Y|v~3Ry&eP zY3Et#lceWXHh0O={$4{fc1JNZBeiEd&4DD1KIiu6X#qi%+^&JNXkn!Nn(`XBU899f z$tU1;vvK1o$UFna=#)9Zu0k^~)rpnsIFSX;lgL$()Og_pw3RbgXw8$20vdlF05k&K zrFYv2^S`?J@^kiiDOC*5lG^vw8w)l+HyUbXZY*}^y}?K;5XmhCuo!h2s<=Ce*IXbg zgq+NV)J|F5*gnzjz0YPgHS7936U2P7<>s zjhKo%?hP3FC^A$O;#{X7#(_~`Pei8&@7>jK4(h-$g(9=G{vT{ zFjUiTAY9U$|3TXC=)OZ562Fssw6Cc2b(ivXrG&KKQCNLmbPkyMI|{2SNt(b7{SS-l zv&FPG4%Uqlu{C)EVP&5ScKgexlNeSEUP&z{jNOcutr(!+*_;-HCnkTL88DldNCkRR z^rb5ky(*XmX5{EYR4qR{SxMwT|fev)1wL$c4`vY#MKe z4n~(nouPT$90SI&A6ITL_#;ksqvsGu=w-JQv|IP8Z{A9r^VDa3aDr#5If?1y&?3BKEZ-FcEa?1w*gcZ)#A z>)$WX%z0KJkj$b|9viwwCmd~jL^xeks-B@49t|zle>!+Q-wIA|OT83N4jPU@5X)A6 z^dQF#K`c?bB2nu#sU6tJLwKr*o>5>6cSp__@PimnSa8+?F5%`o#b@l+jQX;k&Go;lC8lO3GS zk(y2PYNz&>;jqM@DFS}79Q=zys$_!Mu|fD=E~l(`trwo|*x++_1*Kk^f=hO>B{+)c2{YzvqXB$795^&2?Z zEWQvMj73ig+bYcZbUeRV*wBT5Wn0@$q^s>KcH@~u)K}AMcw73$-?y;lR?N1lLm&o>AYPGqGuZb4IAG>sRQN4y;{P-CAI&SWK2R zhMyhA{jWAM*v#@X$cx_mL$8et>X0GyYH^bpLa!!mJ%e~GR@do3{LB*cg#e{S5`&hd zjt%sLg5H8*33UaBlkFzs23RPJwl6uMFk%T*5QU22-6)KiiWRMw;&oFm6vi_>*)pR0 z`-^UW|4%58l0NpXr#69PHq7*km_X8x;EeNZ=~Co6r;f%;9l81fr;8nLP>e7y3ptbx z)!ZVsRCEimS9Klw4Mkl8w$yZuu$KgqSth|H87#3-7&Cg4)&7pf@SP_VMrheUE-Y9o zxoY#S|KS$hUgW04HsgTOCdWBL@u-g)O0)kmeumN}Yl~6Z^sIMQy|Hl|qTy==B(rSG iIl74OO9%0O`26i*c=-Cb`xi|TVW{;egWR*x1Csnom*pn_ delta 962 zcmV;z13moVfCS@!1dt?uq)5+8CVJ2x>psU}xCBP?|rpTYa=Y99rm%kssbq`-3 zcPF+Yn!9~>|M8FA-C2B%-M;($X?GV{Laf(+N~Ox(zI!)`@w?rBofj+JzWZ}`HyI_q z{`~@tn#LwXmeiV*=gO|iiF=HXOs7keDrc&|qp8O7?@GQMZz0z%OSxn(jw<)TnDbV? z_hiQnhtw#CEm@88x(z3{C7*F7cijBy*HdpvtxpWx+%IR|P&9JK-rn#i&OzEwG6}uT z?dT_!HZ+PN%n&$#v(XH(Co!Ehw1;jK9SXbEq+;-avQ%K^N711;;asJ($9mK>mQ`?Y zI7g|N=#^FKKfq-fpeaUvKra48A)Dk(qfzTwIcUteJqDScq+L4B)oE&SI(tWd3${mL@UVJ7FBdVSpO%@z z%3d8Z_E8Jk@`Fol;XBI{neQh$wiCUw?HOhdlBLg*4+Kg5jYTY~Mw#WzpL0yU!m!-GBJG2|(AeS`dfqy_?n-c1<>sNoik}qouA{+VS#= zh$$^INgkqqss~Jlq=ik^G$hTy-L6uvGB;qp>}P(^1-Ogn$=w9Iq}YLx$)b2*tKYx@ zv-ljkDxh|&Ko{r}?3md8sIBzT4N!n`rirsi8k=v{3HM}i+)$dzaICwBd%jlxG zBWK7|MxDjeWif%R6XcAN<|ALA6x=#j(~;ZTa}w6@iYUSXcGFw9x~eBIRjsLCZVUA0CG~}T*MX3 zx&FWr)t>C8!&D0^;?8e7GGJ!7jh16pFXIy|c#sy0{_CZR7HBJjaNmedd# k`w_Euk?FT4;(hn!+e7#8^>Ozf_!eVI51>Fjv(E#P{HHeLumAu6