From baec30f6902598ef2d659ac55dc72b75cd6d070b Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sun, 17 Feb 2013 22:06:26 +0400 Subject: [PATCH] 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 ****************************************************/