From d6dfd49a75bb6cc83b2675801252062016259aa4 Mon Sep 17 00:00:00 2001 From: CIB123 Date: Tue, 18 Sep 2012 21:32:39 +0000 Subject: [PATCH] Ported parts of the BS12 organ system. This includes: - Individual wounds - Dismemberment - Bone breaking It also adds configuration values to config/game_options.txt to control the point at which bones break and limbs are cut off. Does not include surgery or bleeding yet. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4720 316c924e-a436-60f5-8080-3fe189b3f50e --- code/controllers/configuration.dm | 7 + code/datums/organs/organ.dm | 9 +- code/datums/organs/organ_external.dm | 650 ++++++++++++++++-- code/datums/organs/organ_internal.dm | 3 + code/datums/organs/wound.dm | 196 ++++++ code/defines/obj/weapon.dm | 4 + code/game/dna.dm | 2 - code/game/gamemodes/events/ninja_equipment.dm | 11 +- code/game/objects/items/devices/PDA/PDA.dm | 4 +- code/game/objects/objs.dm | 1 + code/modules/mob/inventory.dm | 13 + .../mob/living/carbon/carbon_defines.dm | 5 + .../mob/living/carbon/human/examine.dm | 176 ++++- code/modules/mob/living/carbon/human/hud.dm | 2 + code/modules/mob/living/carbon/human/human.dm | 31 +- .../mob/living/carbon/human/human_damage.dm | 22 +- .../mob/living/carbon/human/human_defines.dm | 1 + code/modules/mob/living/carbon/human/life.dm | 68 ++ .../mob/living/carbon/human/update_icons.dm | 155 ++++- code/modules/mob/mob_defines.dm | 1 + code/modules/mob/mob_helpers.dm | 3 + code/setup.dm | 33 + config/game_options.txt | 8 + icons/mob/dam_human.dmi | Bin 4915 -> 9738 bytes icons/mob/dam_mask.dmi | Bin 0 -> 1503 bytes icons/mob/human.dmi | Bin 22849 -> 22915 bytes tgstation.dme | 2 +- 27 files changed, 1243 insertions(+), 164 deletions(-) create mode 100644 code/datums/organs/wound.dm create mode 100644 icons/mob/dam_mask.dmi diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 6e3d1e3e52d..48d4f22934f 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -71,6 +71,9 @@ var/health_threshold_crit = 0 var/health_threshold_dead = -100 + var/organ_health_multiplier = 1 + var/organ_regeneration_multiplier = 1 + var/revival_pod_plants = 1 var/revival_cloning = 1 var/revival_brain_life = -1 @@ -365,6 +368,10 @@ config.metroid_delay = value if("animal_delay") config.animal_delay = value + if("organ_health_multiplier") + config.organ_health_multiplier = value / 100 + if("organ_regeneration_multiplier") + config.organ_regeneration_multiplier = value / 100 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/datums/organs/organ.dm b/code/datums/organs/organ.dm index 81b45f51287..ba7b1bf014c 100644 --- a/code/datums/organs/organ.dm +++ b/code/datums/organs/organ.dm @@ -1,8 +1,6 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - /datum/organ var/name = "organ" - var/mob/owner = null + var/mob/living/carbon/human/owner = null ///datum/organ/proc/process() // return 0 @@ -10,5 +8,8 @@ ///datum/organ/proc/receive_chem(chemical as obj) // return 0 + proc/process() + return 0 - + proc/receive_chem(chemical as obj) + return 0 \ No newline at end of file diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm index 85df6bf56fe..9d8dc5c45ce 100644 --- a/code/datums/organs/organ_external.dm +++ b/code/datums/organs/organ_external.dm @@ -1,142 +1,640 @@ +/**************************************************** + EXTERNAL ORGANS +****************************************************/ /datum/organ/external name = "external" var/icon_name = null var/body_part = null - var/brutestate = 0 - var/burnstate = 0 + + var/damage_state = "00" var/brute_dam = 0 var/burn_dam = 0 var/max_damage = 0 -// var/bandaged = 0 -// var/wound_size = 0 -// var/max_size = 0 + var/max_size = 0 + var/tmp/list/obj/item/weapon/implant/implant + + var/display_name + var/list/wounds = list() + 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/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/status = 0 + var/broken_description + var/open = 0 + var/stage = 0 + + proc/take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list()) + // TODO: this proc needs to be rewritten to not update damages directly + 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(brute_dam >= max_damage * config.organ_health_multiplier) + if(prob(5 * brute)) + status |= ORGAN_DESTROYED + droplimb() + return + + else if(prob(nux)) + createwound( CUT, brute ) + if(!(status & ORGAN_ROBOT)) + owner << "You feel something wet on your [display_name]" + + if((brute_dam + burn_dam + brute + burn) < max_damage) + if(brute) + brute_dam += brute + if( (prob(brute*2) && !sharp) || sharp ) + createwound( CUT, brute ) + else if(!sharp) + createwound( BRUISE, brute ) + if(burn) + burn_dam += burn + createwound( BURN, burn ) + else + var/can_inflict = max_damage - (brute_dam + burn_dam) //How much damage can we actually cause? + if(can_inflict) + if (brute > 0 && burn > 0) + brute = can_inflict/2 + burn = can_inflict/2 + var/ratio = brute / (brute + burn) + brute_dam += ratio * can_inflict + burn_dam += (1 - ratio) * can_inflict + else + if (brute > 0) + brute = can_inflict + brute_dam += brute + createwound(BRUISE, brute) + else + burn = can_inflict + burn_dam += burn + createwound(BRUISE, brute) + 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) + message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage too!") + 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") + + 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(!W.bandaged && W.damage > 4) + 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.is_treated()) + // slow healing + var/amount = 0.2 + if(W.bandaged) amount++ + if(W.salved) amount++ + if(W.disinfected) amount++ + // amount of healing is spread over all the wounds + W.heal_damage((amount * W.amount * config.organ_regeneration_multiplier) / (5*owner.number_wounds+1)) + + // sync the organ's damage with its wounds + src.update_damages() + + + 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 + + process() + // process wounds, doing healing etc., only do this every 4 ticks to save processing power + if(owner.life_tick % 4 == 0) + update_wounds() + if(status & ORGAN_DESTROYED) + if(!destspawn) + droplimb() + return + if(!(status & ORGAN_BROKEN)) + perma_dmg = 0 + if(parent) + if(parent.status & ORGAN_DESTROYED) + status |= ORGAN_DESTROYED + owner:update_body() + return + if(brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) + if(!(status & ORGAN_BROKEN)) + 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 + return + +// new damage icon system +// returns just the brute/burn damage code + proc/damage_state_text() + 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 (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() + return 1 + return 0 + + proc/droplimb(var/override = 0,var/no_explode = 0) + if(override) + status |= ORGAN_DESTROYED + if(status & ORGAN_DESTROYED) + if(status & ORGAN_SPLINTED) + status &= ~ORGAN_SPLINTED + if(implant) + for(var/implants in implant) + del(implants) + //owner.unlock_medal("Lost something?", 0, "Lose a limb.", "easy") + + for(var/datum/organ/external/I in children) + if(I && !(I.status & ORGAN_DESTROYED)) + I.droplimb(1,1) + var/obj/item/weapon/organ/H + 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) + if(ishuman(owner)) + if(owner.gender == FEMALE) + H.icon_state = "head_f_l" + 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" + + // TODO: re-add this when dismemberment has been ported properly + //if(ishuman(owner)) + // owner.update_face() + owner.update_body() + owner.death() + if(ARM_RIGHT) + H = new /obj/item/weapon/organ/r_arm(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "r_arm_l" + if(ARM_LEFT) + H = new /obj/item/weapon/organ/l_arm(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "l_arm_l" + if(LEG_RIGHT) + H = new /obj/item/weapon/organ/r_leg(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "r_leg_l" + if(LEG_LEFT) + H = new /obj/item/weapon/organ/l_leg(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "l_leg_l" + if(HAND_RIGHT) + H = new /obj/item/weapon/organ/r_hand(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "r_hand_l" + if(HAND_LEFT) + H = new /obj/item/weapon/organ/l_hand(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "l_hand_l" + if(FOOT_RIGHT) + H = new /obj/item/weapon/organ/r_foot/(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "r_foot_l" + if(FOOT_LEFT) + H = new /obj/item/weapon/organ/l_foot(owner.loc, owner) + if(ismonkey(owner)) + H.icon_state = "l_foot_l" + if(ismonkey(owner)) + H.icon = 'monkey.dmi' + var/lol = pick(cardinal) + step(H,lol) + destspawn = 1 + if(status & ORGAN_ROBOT) + 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, src) + spark_system.attach(src) + 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.") + owner.update_body() + // TODO: also add stuff to update the appropriate clothing + + 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(25)) + if((type == CUT || type == BRUISE) && damage >= 5) + var/datum/wound/W = pick(wounds) + if(W.amount == 1 && W.started_healing()) + W.open_wound() + 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) + 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) + wound_type = size_names[size] + + W = new wound_type(damage) + + + + // 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)) + return + if(prob(30*severity)) + take_damage(4(4-severity), 0, 1, used_weapon = "EMP") + else + droplimb(1) + + 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 /datum/organ/external/chest name = "chest" icon_name = "chest" + display_name = "chest" max_damage = 150 + min_broken_damage = 75 body_part = UPPER_TORSO +/datum/organ/external/groin + name = "groin" + icon_name = "diaper" + display_name = "groin" + max_damage = 115 + min_broken_damage = 70 + body_part = LOWER_TORSO + /datum/organ/external/head name = "head" icon_name = "head" - max_damage = 125 + display_name = "head" + max_damage = 75 + min_broken_damage = 40 body_part = HEAD + var/disfigured = 0 /datum/organ/external/l_arm name = "l_arm" + display_name = "left arm" icon_name = "l_arm" max_damage = 75 + min_broken_damage = 30 body_part = ARM_LEFT /datum/organ/external/l_leg name = "l_leg" + display_name = "left leg" icon_name = "l_leg" max_damage = 75 + min_broken_damage = 30 body_part = LEG_LEFT /datum/organ/external/r_arm name = "r_arm" + display_name = "right arm" icon_name = "r_arm" max_damage = 75 + min_broken_damage = 30 body_part = ARM_RIGHT /datum/organ/external/r_leg name = "r_leg" + display_name = "right leg" icon_name = "r_leg" max_damage = 75 + min_broken_damage = 30 body_part = LEG_RIGHT -/*Leaving these here in case we want to use them later /datum/organ/external/l_foot - name = "l foot" + name = "l_foot" + display_name = "left foot" icon_name = "l_foot" + max_damage = 40 + min_broken_damage = 15 body_part = FOOT_LEFT /datum/organ/external/r_foot - name = "r foot" + name = "r_foot" + display_name = "right foot" icon_name = "r_foot" + max_damage = 40 + min_broken_damage = 15 body_part = FOOT_RIGHT /datum/organ/external/r_hand - name = "r hand" + name = "r_hand" + display_name = "right hand" icon_name = "r_hand" + max_damage = 40 + min_broken_damage = 15 body_part = HAND_RIGHT /datum/organ/external/l_hand - name = "l hand" + name = "l_hand" + display_name = "left hand" icon_name = "l_hand" + max_damage = 40 + min_broken_damage = 15 body_part = HAND_LEFT -/datum/organ/external/groin - name = "groin" - icon_name = "groin" - body_part = LOWER_TORSO -*/ +/**************************************************** + EXTERNAL ORGAN ITEMS +****************************************************/ -//Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. -//Damage will not exceed max_damage using this proc -//Cannot apply negative damage -/datum/organ/external/proc/take_damage(brute, burn) - if(owner && owner.nodamage) return 0 //godmode - brute = max(brute,0) - burn = max(burn,0) +obj/item/weapon/organ + icon = 'human.dmi' - 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)) + return + if(H.dna) + if(!blood_DNA) + blood_DNA = list() + blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - if((brute + burn) < can_inflict) - brute_dam += brute - burn_dam += burn + var/icon/I = new /icon(icon, icon_state) + + if (H.s_tone >= 0) + I.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) else - if(brute > 0) - if(burn > 0) - brute = round( (brute/(brute+burn)) * can_inflict, 1 ) - burn = can_inflict - brute //gets whatever damage is left over - brute_dam += brute - burn_dam += burn + I.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) + icon = I + +obj/item/weapon/organ/head + name = "head" + icon_state = "head_m_l" + var/mob/living/carbon/brain/brainmob + var/brain_op_stage = 0 + +obj/item/weapon/organ/head/New() + ..() + spawn(5) + if(brainmob && brainmob.client) + brainmob.client.screen.len = null //clear the hud + +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) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.dna = H.dna + if(H.mind) + H.mind.transfer_to(brainmob) + brainmob.container = src + +obj/item/weapon/organ/head/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W,/obj/item/weapon/scalpel)) + switch(brain_op_stage) + if(0) + for(var/mob/O in (oviewers(brainmob) - user)) + O.show_message("\red [brainmob] is beginning to have \his head cut open with [src] by [user].", 1) + brainmob << "\red [user] begins to cut open your head with [src]!" + user << "\red You cut [brainmob]'s head open with [src]!" + + brain_op_stage = 1 + + if(2) + for(var/mob/O in (oviewers(brainmob) - user)) + O.show_message("\red [brainmob] is having \his connections to the brain delicately severed with [src] by [user].", 1) + brainmob << "\red [user] begins to cut open your head with [src]!" + user << "\red You cut [brainmob]'s head open with [src]!" + + brain_op_stage = 3.0 else - brute_dam += can_inflict - else - if(burn > 0) - burn_dam += can_inflict + ..() + else if(istype(W,/obj/item/weapon/circular_saw)) + switch(brain_op_stage) + if(1) + for(var/mob/O in (oviewers(brainmob) - user)) + O.show_message("\red [brainmob] has \his skull sawed open with [src] by [user].", 1) + brainmob << "\red [user] begins to saw open your head with [src]!" + user << "\red You saw [brainmob]'s head open with [src]!" + + brain_op_stage = 2 + if(3) + for(var/mob/O in (oviewers(brainmob) - user)) + O.show_message("\red [brainmob] has \his spine's connection to the brain severed with [src] by [user].", 1) + brainmob << "\red [user] severs your brain's connection to the spine with [src]!" + user << "\red You sever [brainmob]'s brain's connection to the spine with [src]!" + + user.attack_log += "\[[time_stamp()]\] Debrained [brainmob.name] ([brainmob.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" + brainmob.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" + log_admin("ATTACK: [brainmob] ([brainmob.ckey]) debrained [user] ([user.ckey]).") + message_admins("ATTACK: [brainmob] ([brainmob.ckey]) debrained [user] ([user.ckey]).") + + var/obj/item/brain/B = new(loc) + B.transfer_identity(brainmob) + + brain_op_stage = 4.0 else - return 0 - return update_icon() + ..() + else + ..() - -//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all. -//Damage cannot go below zero. -//Cannot remove negative damage (i.e. apply damage) -/datum/organ/external/proc/heal_damage(brute, burn) - brute = max(brute, 0) - burn = max(burn, 0) - brute_dam = max(brute_dam - brute, 0) - burn_dam = max(burn_dam - burn, 0) - return update_icon() - - -//Returns total damage...kinda pointless really -/datum/organ/external/proc/get_damage() //returns total damage - return brute_dam + burn_dam - - -//Updates an organ's brute/burn states for use by updateDamageIcon() -//Returns 1 if we need to update overlays. 0 otherwise. -/datum/organ/external/proc/update_icon() - var/tbrute = round( (brute_dam/max_damage)*3, 1 ) - var/tburn = round( (burn_dam/max_damage)*3, 1 ) - if((tbrute != brutestate) || (tburn != burnstate)) - brutestate = tbrute - burnstate = tburn - return 1 - return 0 - -//Returns a display name for the organ -/datum/organ/external/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" - else return name +obj/item/weapon/organ/l_arm + name = "left arm" + icon_state = "l_arm_l" +obj/item/weapon/organ/l_foot + name = "left foot" + icon_state = "l_foot_l" +obj/item/weapon/organ/l_hand + name = "left hand" + icon_state = "l_hand_l" +obj/item/weapon/organ/l_leg + name = "left leg" + icon_state = "l_leg_l" +obj/item/weapon/organ/r_arm + name = "right arm" + icon_state = "r_arm_l" +obj/item/weapon/organ/r_foot + name = "right foot" + icon_state = "r_foot_l" +obj/item/weapon/organ/r_hand + name = "right hand" + icon_state = "r_hand_l" +obj/item/weapon/organ/r_leg + name = "right leg" + icon_state = "r_leg_l" \ No newline at end of file diff --git a/code/datums/organs/organ_internal.dm b/code/datums/organs/organ_internal.dm index 66496141bbc..2f1738bea2d 100644 --- a/code/datums/organs/organ_internal.dm +++ b/code/datums/organs/organ_internal.dm @@ -1,3 +1,6 @@ +/**************************************************** + INTERNAL ORGANS +****************************************************/ /datum/organ/internal name = "internal" diff --git a/code/datums/organs/wound.dm b/code/datums/organs/wound.dm new file mode 100644 index 00000000000..1caf45b7587 --- /dev/null +++ b/code/datums/organs/wound.dm @@ -0,0 +1,196 @@ + +/**************************************************** + WOUNDS +****************************************************/ +/datum/wound + // stages such as "cut", "deep cut", etc. + var/list/stages + // number representing the current stage + var/current_stage = 0 + + // description of the wound + var/desc = "" + + // amount of damage this wound causes + var/damage = 0 + + // amount of damage the current wound type requires(less means we need to apply the next healing stage) + var/min_damage = 0 + + // one of CUT, BRUISE, BURN + var/damage_type = CUT + + // whether this wound needs a bandage/salve to heal at all + var/needs_treatment = 0 + + // is the wound bandaged? + var/tmp/bandaged = 0 + // is the wound salved? + var/tmp/salved = 0 + // is the wound disinfected? + var/tmp/disinfected = 0 + var/tmp/created = 0 + + // number of wounds of this type + var/tmp/amount = 1 + + // helper lists + var/tmp/list/desc_list = list() + var/tmp/list/damage_list = list() + New(var/damage) + + created = world.time + + // reading from a list("stage" = damage) is pretty difficult, so build two separate + // lists from them instead + for(var/V in stages) + desc_list += V + damage_list += stages[V] + + src.damage = damage + + // initialize with the first stage + next_stage() + + // this will ensure the size of the wound matches the damage + src.heal_damage(0) + + // returns 1 if there's a next stage, 0 otherwise + proc/next_stage() + if(current_stage + 1 > src.desc_list.len) + return 0 + + current_stage++ + + src.min_damage = damage_list[current_stage] + src.desc = desc_list[current_stage] + return 1 + + // returns 1 if the wound has started healing + proc/started_healing() + return (current_stage > 1) + + // checks whether the wound has been appropriately treated + // always returns 1 for wounds that don't need to be treated + proc/is_treated() + if(!needs_treatment) return 1 + + if(damage_type == BRUISE || damage_type == CUT) + return bandaged + else if(damage_type == BURN) + return salved + + // heal the given amount of damage, and if the given amount of damage was more + // than what needed to be healed, return how much heal was left + proc/heal_damage(amount) + var/healed_damage = min(src.damage, amount) + amount -= healed_damage + src.damage -= healed_damage + + while(src.damage / src.amount < damage_list[current_stage] && current_stage < src.desc_list.len) + current_stage++ + desc = desc_list[current_stage] + + // return amount of healing still leftover, can be used for other wounds + return amount + + // opens the wound again + proc/open_wound() + if(current_stage > 1) + // e.g. current_stage is 2, then reset it to 0 and do next_stage(), bringing it to 1 + src.current_stage -= 2 + next_stage() + src.damage = src.min_damage + 5 + +/** CUTS **/ +/datum/wound/cut + // link wound descriptions to amounts of damage + stages = list("cut" = 5, "healing cut" = 2, "small scab" = 0) + +/datum/wound/deep_cut + stages = list("deep cut" = 15, "clotted cut" = 8, "scab" = 2, "fresh skin" = 0) + +/datum/wound/flesh_wound + stages = list("flesh wound" = 25, "blood soaked clot" = 15, "large scab" = 5, "fresh skin" = 0) + +/datum/wound/gaping_wound + 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 + stages = list("big gaping wound" = 60, "gauze wrapped wound" = 50, "blood soaked bandage" = 25,\ + "large angry scar" = 10, "large straight scar" = 0) + + needs_treatment = 1 // this only heals when bandaged + +/datum/wound/massive_wound + stages = list("massive wound" = 70, "massive blood soaked bandage" = 40, "huge bloody mess" = 20,\ + "massive angry scar" = 10, "massive jagged scar" = 0) + + needs_treatment = 1 // this only heals when bandaged + +/** BRUISES **/ +/datum/wound/bruise + stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30,\ + "moderate bruise" = 20, "small bruise" = 10, "tiny bruise" = 5) + + needs_treatment = 1 // this only heals when bandaged + damage_type = BRUISE + +/datum/wound/bruise/monumental_bruise + +// implement sub-paths by starting at a later stage +/datum/wound/bruise/huge_bruise + current_stage = 1 + +/datum/wound/bruise/large_bruise + current_stage = 2 + +/datum/wound/bruise/moderate_bruise + current_stage = 3 + needs_treatment = 0 + +/datum/wound/bruise/small_bruise + current_stage = 4 + needs_treatment = 0 + +/datum/wound/bruise/tiny_bruise + current_stage = 5 + needs_treatment = 0 + +/** BURNS **/ +/datum/wound/moderate_burn + stages = list("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 + stages = list("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 + stages = list("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 + stages = list("deep burn" = 40, "deep salved burn" = 15, "large burn scar" = 0) + + needs_treatment = 1 // this only heals when bandaged + + damage_type = BURN + + +/datum/wound/carbonised_area + stages = list("carbonised area" = 50, "treated carbonised area" = 20, "massive burn scar" = 0) + + needs_treatment = 1 // this only heals when bandaged + + damage_type = BURN \ No newline at end of file diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 81a0c4a1737..851445c6200 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -1355,6 +1355,7 @@ m_amt = 12000 origin_tech = "materials=1" attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharp = 1 /obj/item/weapon/kitchenknife/ritual name = "ritual knife" @@ -1436,6 +1437,7 @@ icon_state = "knife" force = 10.0 throwforce = 10.0 + sharp = 1 /obj/item/weapon/kitchen/utensil/spoon name = "spoon" @@ -1458,6 +1460,7 @@ g_amt = 5000 origin_tech = "materials=1;biotech=1" attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharp = 1 /obj/item/weapon/retractor name = "retractor" @@ -1524,6 +1527,7 @@ g_amt = 10000 origin_tech = "materials=1;biotech=1" attack_verb = list("attacked", "slashed", "sawed", "cut") + sharp = 1 /obj/item/weapon/syntiflesh name = "syntiflesh" diff --git a/code/game/dna.dm b/code/game/dna.dm index 0ea61c118e2..eec31a2565c 100644 --- a/code/game/dna.dm +++ b/code/game/dna.dm @@ -505,8 +505,6 @@ for(var/obj/T in (M.contents-implants)) del(T) - //for(var/R in M.organs) - // del(M.organs[text("[]", R)]) O.loc = M.loc diff --git a/code/game/gamemodes/events/ninja_equipment.dm b/code/game/gamemodes/events/ninja_equipment.dm index dd77de486bc..58bfa17ff48 100644 --- a/code/game/gamemodes/events/ninja_equipment.dm +++ b/code/game/gamemodes/events/ninja_equipment.dm @@ -844,15 +844,16 @@ ________________________________________________________________________________ U << "\red Procedure interrupted. Protocol terminated." return else if(istype(I, /obj/item/weapon/disk/tech_disk))//If it's a data disk, we want to copy the research on to the suit. - if(I:stored)//If it has something on it. + var/obj/item/weapon/disk/tech_disk/tdisk = I + if(tdisk.stored)//If it has something on it. U << "Research information detected, processing..." if(do_after(U,s_delay)) for(var/datum/tech/current_data in stored_research) - if(current_data.id==I:stored.id) - if(current_data.levelERROR: \black Procedure interrupted. Process terminated." diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 8363837874f..80dc869698c 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -837,8 +837,8 @@ var/global/list/obj/item/device/pda/PDAs = list() C.loc = src user << "You insert [C] into [src]." cartridge = C - if(C:radio) - C:radio.hostpda = src + if(cartridge.radio) + cartridge.radio.hostpda = src else if(istype(C, /obj/item/weapon/card/id)) var/obj/item/weapon/card/id/idcard = C diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 01f0f06a5d1..9d782959bdd 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -11,6 +11,7 @@ animate_movement = 2 var/throwforce = 1 var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]" + var/sharp = 0 // whether this object cuts /obj/proc/process() processing_objects.Remove(src) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 5bc421dee4d..4277e3b301f 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -203,3 +203,16 @@ //if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand return items + +/** BS12's proc to get the item in the active hand. Couldn't find the /tg/ equivalent. **/ +/mob/proc/equipped() + if(issilicon(src)) + if(isrobot(src)) + if(src:module_active) + return src:module_active + else + if (hand) + return l_hand + else + return r_hand + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 22142887241..0f1fedb8de4 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -10,3 +10,8 @@ var/silent = null //Can't talk. Value goes down every life proc. var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm + + var/life_tick = 0 // The amount of life ticks that have processed on this mob. + + // total amount of wounds on mob, used to spread out healing and the like over all wounds + var/number_wounds = 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index c1a12fd29d0..12160fcc265 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -201,40 +201,6 @@ msg += "...\n" else - - msg += "" - - var/temp = getBruteLoss() //no need to calculate each of these twice - if(temp) - if(temp < 30) - msg += "[t_He] [t_has] minor bruising.\n" - else - msg += "[t_He] [t_has] severe bruising!\n" - - temp = getFireLoss() - if(temp) - if(temp < 30) - msg += "[t_He] [t_has] minor burns.\n" - else - msg += "[t_He] [t_has] severe burns!\n" - - temp = getCloneLoss() - if(temp) - if(temp < 30) - msg += "[t_He] [t_has] minor genetic deformities.\n" - else - msg += "[t_He] [t_has] severe genetic deformities.\n" - - if(nutrition < 100) - msg += "[t_He] [t_is] severely malnourished.\n" - else if(nutrition >= 500) - if(usr.nutrition < 100) - msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" - else - msg += "[t_He] [t_is] quite chubby.\n" - - msg += "" - if(stat == UNCONSCIOUS) msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" else if(getBrainLoss() >= 60) @@ -245,6 +211,148 @@ else if(!client) msg += "[t_He] [t_has] a vacant, braindead stare...\n" + msg += "" + + if(nutrition < 100) + msg += "[t_He] [t_is] severely malnourished.\n" + else if(nutrition >= 500) + if(usr.nutrition < 100) + msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" + else + msg += "[t_He] [t_is] quite chubby.\n" + msg += "" + + var/list/wound_flavor_text = list() + var/list/is_destroyed = list() + var/list/is_bleeding = list() + for(var/datum/organ/external/temp in organs) + if(temp) + if(temp.status & ORGAN_DESTROYED) + is_destroyed["[temp.display_name]"] = 1 + wound_flavor_text["[temp.display_name]"] = "[t_He] is missing [t_his] [temp.display_name].\n" + continue + if(temp.status & ORGAN_ROBOT) + if(!(temp.brute_dam + temp.burn_dam)) + wound_flavor_text["[temp.display_name]"] = "[t_He] has a robot [temp.display_name]!\n" + continue + else + wound_flavor_text["[temp.display_name]"] = "[t_He] has a robot [temp.display_name], it has" + if(temp.brute_dam) switch(temp.brute_dam) + if(0 to 20) + wound_flavor_text["[temp.display_name]"] += " some dents" + if(21 to INFINITY) + wound_flavor_text["[temp.display_name]"] += pick(" a lot of dents"," severe denting") + if(temp.brute_dam && temp.burn_dam) + wound_flavor_text["[temp.display_name]"] += " and" + if(temp.burn_dam) switch(temp.burn_dam) + if(0 to 20) + wound_flavor_text["[temp.display_name]"] += " some burns" + if(21 to INFINITY) + wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe melting") + wound_flavor_text["[temp.display_name]"] += "!\n" + else if(temp.wounds.len > 0) + var/list/wound_descriptors = list() + for(var/datum/wound/W in temp.wounds) + if(W.desc in wound_descriptors) + wound_descriptors[W.desc] += W.amount + continue + wound_descriptors[W.desc] = W.amount + var/list/flavor_text = list() + var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\ + "huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area") + for(var/wound in wound_descriptors) + switch(wound_descriptors[wound]) + if(1) + if(!flavor_text.len) + flavor_text += "[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]" + else + flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]" + if(2) + if(!flavor_text.len) + flavor_text += "[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s" + else + flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s" + if(3 to 5) + if(!flavor_text.len) + flavor_text += "[t_He] has several [wound]s" + else + flavor_text += " several [wound]s" + if(6 to INFINITY) + if(!flavor_text.len) + flavor_text += "[t_He] has a bunch of [wound]s" + else + flavor_text += " a ton of [wound]\s" + var/flavor_text_string = "" + for(var/text = 1, text <= flavor_text.len, text++) + if(text == flavor_text.len && flavor_text.len > 1) + flavor_text_string += ", and" + else if(flavor_text.len > 1 && text > 1) + flavor_text_string += "," + flavor_text_string += flavor_text[text] + flavor_text_string += " on [t_his] [temp.display_name].
" + wound_flavor_text["[temp.name]"] = flavor_text_string + if(temp.status & ORGAN_BLEEDING) + is_bleeding["[temp.name]"] = 1 + else + wound_flavor_text["[temp.display_name]"] = "" + + //Handles the text strings being added to the actual description. + //If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext. + var/display_chest = 0 + var/display_shoes = 0 + var/display_gloves = 0 + if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas))))) + msg += wound_flavor_text["head"] + else if(is_bleeding["head"]) + msg += "[src] has blood running down [t_his] face!\n" + if(wound_flavor_text["chest"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you. + msg += wound_flavor_text["chest"] + else if(is_bleeding["chest"]) + display_chest = 1 + if(wound_flavor_text["left arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["left arm"] + else if(is_bleeding["left arm"]) + display_chest = 1 + if(wound_flavor_text["left hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves))) + msg += wound_flavor_text["left hand"] + else if(is_bleeding["left hand"]) + display_gloves = 1 + if(wound_flavor_text["right arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["right arm"] + else if(is_bleeding["right arm"]) + display_chest = 1 + if(wound_flavor_text["right hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves))) + msg += wound_flavor_text["right hand"] + else if(is_bleeding["right hand"]) + display_gloves = 1 + if(wound_flavor_text["groin"] && (is_destroyed["groin"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["groin"] + else if(is_bleeding["groin"]) + display_chest = 1 + if(wound_flavor_text["left leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["left leg"] + else if(is_bleeding["left leg"]) + display_chest = 1 + if(wound_flavor_text["left foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes))) + msg += wound_flavor_text["left foot"] + else if(is_bleeding["left foot"]) + display_shoes = 1 + if(wound_flavor_text["right leg"] && (is_destroyed["right leg"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["right leg"] + else if(is_bleeding["right leg"]) + display_chest = 1 + if(wound_flavor_text["right foot"]&& (is_destroyed["right foot"] || (!shoes && !skipshoes))) + msg += wound_flavor_text["right foot"] + else if(is_bleeding["right foot"]) + display_shoes = 1 + if(display_chest) + msg += "[src] has blood soaking through from under [t_his] clothing!\n" + if(display_shoes) + msg += "[src] has blood running from [t_his] shoes!\n" + if(display_gloves) + msg += "[src] has blood running from under [t_his] gloves!\n" + + if(digitalcamo) msg += "[t_He] [t_is] repulsively uncanny!\n" diff --git a/code/modules/mob/living/carbon/human/hud.dm b/code/modules/mob/living/carbon/human/hud.dm index 4d017d14d59..e0e3361924e 100644 --- a/code/modules/mob/living/carbon/human/hud.dm +++ b/code/modules/mob/living/carbon/human/hud.dm @@ -587,6 +587,8 @@ mymob.flash.screen_loc = "1,1 to 15,15" mymob.flash.layer = 17 + mymob.pain = new /obj/screen( null ) + /* mymob.hands = new /obj/screen( null ) mymob.hands.icon = ui_style diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f9c572ae67b..b2d5cf58624 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -21,8 +21,31 @@ dna = new /datum/dna(null) //initialise organs - organs = newlist(/datum/organ/external/chest, /datum/organ/external/head, /datum/organ/external/l_arm, \ - /datum/organ/external/r_arm, /datum/organ/external/r_leg, /datum/organ/external/l_leg) + organs = list() + organs_by_name["chest"] = new/datum/organ/external/chest() + organs_by_name["head"] = new/datum/organ/external/head() + organs_by_name["l_arm"] = new/datum/organ/external/l_arm() + organs_by_name["r_arm"] = new/datum/organ/external/r_arm() + organs_by_name["r_leg"] = new/datum/organ/external/r_leg() + organs_by_name["l_leg"] = new/datum/organ/external/l_leg() + organs_by_name["l_hand"] = new/datum/organ/external/l_hand() + organs_by_name["r_hand"] = new/datum/organ/external/r_hand() + organs_by_name["l_foot"] = new/datum/organ/external/l_foot() + organs_by_name["r_foot"] = new/datum/organ/external/r_foot() + + // connect feet to legs and hands to arms + var/datum/organ/external/organ = organs_by_name["l_hand"] + organ.parent = organs_by_name["l_arm"] + organ = organs_by_name["r_hand"] + organ.parent = organs_by_name["r_arm"] + organ = organs_by_name["l_foot"] + organ.parent = organs_by_name["l_leg"] + organ = organs_by_name["r_foot"] + organ.parent = organs_by_name["r_leg"] + + for(var/name in organs_by_name) + organs += organs_by_name[name] + for(var/datum/organ/external/O in organs) O.owner = src @@ -518,8 +541,8 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() - var/datum/organ/external/O = get_organ("head") - if( (status_flags&DISFIGURED) || (O.brutestate+O.burnstate)>2 || !real_name ) //disfigured. use id-name if possible + var/datum/organ/external/head/head = get_organ("head") + if( !head || head.disfigured || !real_name ) //disfigured. use id-name if possible return "Unknown" return real_name diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 13672c0baf3..e2110f90fa5 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -86,11 +86,11 @@ //Damages ONE external organ, organ gets randomly selected from damagable ones. //It automatically updates damage overlays if necesary //It automatically updates health status -/mob/living/carbon/human/take_organ_damage(var/brute, var/burn) +/mob/living/carbon/human/take_organ_damage(var/brute, var/burn, var/sharp = 0) var/list/datum/organ/external/parts = get_damageable_organs() if(!parts.len) return var/datum/organ/external/picked = pick(parts) - if(picked.take_damage(brute,burn)) + if(picked.take_damage(brute,burn,sharp)) UpdateDamageIcon() updatehealth() @@ -116,7 +116,7 @@ if(update) UpdateDamageIcon() // damage MANY external organs, in random order -/mob/living/carbon/human/take_overall_damage(var/brute, var/burn) +/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/sharp = 0) if(nodamage) return //godmode var/list/datum/organ/external/parts = get_damageable_organs() var/update = 0 @@ -126,7 +126,7 @@ var/brute_was = picked.brute_dam var/burn_was = picked.burn_dam - update |= picked.take_damage(brute,burn) + update |= picked.take_damage(brute,burn,sharp) brute -= (picked.brute_dam - brute_was) burn -= (picked.burn_dam - burn_was) @@ -150,19 +150,17 @@ /mob/living/carbon/human/proc/get_organ(var/zone) if(!zone) zone = "chest" - for(var/datum/organ/external/O in organs) - if(O.name == zone) - return O - return null + return organs_by_name[zone] - -/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0) +/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/obj/item/weapon) if((damagetype != BRUTE) && (damagetype != BURN)) ..(damage, damagetype, def_zone, blocked) return 1 if(blocked >= 2) return 0 + var/sharp = weapon.sharp + var/datum/organ/external/organ = null if(isorgan(def_zone)) organ = def_zone @@ -178,10 +176,10 @@ switch(damagetype) if(BRUTE) - if(organ.take_damage(damage, 0)) + if(organ.take_damage(damage, 0, sharp)) UpdateDamageIcon() if(BURN) - if(organ.take_damage(0, damage)) + if(organ.take_damage(0, damage, sharp)) UpdateDamageIcon() updatehealth() return 1 diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index c593b32b1dc..ad2d4dc294e 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -44,6 +44,7 @@ var/icon/lying_icon = null var/list/organs = list() + var/list/organs_by_name = list() // map organ names to organs var/miming = null //Toggle for the mime's abilities. diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 75bacdc02b4..e62aca49398 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -53,6 +53,8 @@ fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it. //TODO: seperate this out + // update the current life tick, can be used to e.g. only do something every 4 ticks + life_tick++ var/datum/gas_mixture/environment = loc.return_air() //No need to update all of these procs if the guy is dead. @@ -167,6 +169,71 @@ if(3) emote("drool") + proc/handle_organs() + // take care of organ related updates, such as broken and missing limbs + + // recalculate number of wounds + number_wounds = 0 + for(var/datum/organ/external/E in organs) + if(!E) + world << name + continue + number_wounds += E.number_wounds + + var/leg_tally = 2 + for(var/datum/organ/external/E in organs) + E.process() + if(E.status & ORGAN_ROBOT && prob(E.brute_dam + E.burn_dam)) + if(E.name == "l_hand" || E.name == "l_arm") + if(hand && equipped()) + drop_item() + emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!") + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + spark_system.start() + spawn(10) + del(spark_system) + else if(E.name == "r_hand" || E.name == "r_arm") + if(!hand && equipped()) + drop_item() + emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!") + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + spark_system.start() + spawn(10) + del(spark_system) + else if(E.name == "l_leg" || E.name == "l_foot" \ + || E.name == "r_leg" || E.name == "r_foot" && !lying) + leg_tally-- // let it fail even if just foot&leg + if(E.status & ORGAN_BROKEN || E.status & ORGAN_DESTROYED) + if(E.name == "l_hand" || E.name == "l_arm") + if(hand && equipped()) + if(E.status & ORGAN_SPLINTED && prob(10)) + drop_item() + emote("scream") + else + drop_item() + emote("scream") + else if(E.name == "r_hand" || E.name == "r_arm") + if(!hand && equipped()) + if(E.status & ORGAN_SPLINTED && prob(10)) + drop_item() + emote("scream") + else + drop_item() + emote("scream") + else if(E.name == "l_leg" || E.name == "l_foot" \ + || E.name == "r_leg" || E.name == "r_foot" && !lying) + if(!(E.status & ORGAN_SPLINTED)) + leg_tally-- // let it fail even if just foot&leg + // can't stand + if(leg_tally == 0 && !paralysis && !(lying || resting)) + emote("scream") + emote("collapse") + paralysis = 10 + proc/handle_mutations_and_radiation() if(getFireLoss()) @@ -817,6 +884,7 @@ silent = 0 else //ALIVE. LIGHTS ARE ON updatehealth() //TODO + handle_organs() if(health <= config.health_threshold_dead || brain_op_stage == 4.0) death() blinded = 1 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 8f9135de521..eeaf1e23aa5 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -122,6 +122,7 @@ Please contact me on #coderbus IRC. ~Carn x /mob/living/carbon/human var/list/overlays_lying[TOTAL_LAYERS] var/list/overlays_standing[TOTAL_LAYERS] + var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed //UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING @@ -164,39 +165,108 @@ Please contact me on #coderbus IRC. ~Carn x //DAMAGE OVERLAYS //constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists /mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1) - var/image/standing = image("icon" = 'icons/mob/dam_human.dmi', "icon_state" = "blank") - var/image/lying = image("icon" = 'icons/mob/dam_human.dmi', "icon_state" = "blank2") - for(var/datum/organ/external/O in organs) - if(O.brutestate) - standing.overlays += "[O.icon_name]_[O.brutestate]0" //we're adding icon_states of the base image as overlays - lying.overlays += "[O.icon_name]2_[O.brutestate]0" - if(O.burnstate) - standing.overlays += "[O.icon_name]_0[O.burnstate]" - lying.overlays += "[O.icon_name]2_0[O.burnstate]" + // first check whether something actually changed about damage appearance + var/damage_appearance = "" + + for(var/datum/organ/external/O in organs) + if(O.status & ORGAN_DESTROYED) damage_appearance += "d" + else + damage_appearance += O.damage_state + + if(damage_appearance == previous_damage_appearance) + // nothing to do here + return + + previous_damage_appearance = damage_appearance + + var/icon/standing = new /icon('dam_human.dmi', "00") + var/icon/lying = new /icon('dam_human.dmi', "00-2") + + // blend the individual damage states with our icons + for(var/datum/organ/external/O in organs) + if(!(O.status & ORGAN_DESTROYED)) + O.update_icon() + var/icon/DI = new /icon('icons/mob/dam_human.dmi', O.damage_state) // the damage icon for whole human + DI.Blend(new /icon('dam_mask.dmi', O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels + + standing.Blend(DI,ICON_OVERLAY) + DI = new /icon('icons/mob/dam_human.dmi', "[O.damage_state]-2") // repeat for lying icons + DI.Blend(new /icon('dam_mask.dmi', "[O.icon_name]2"), ICON_MULTIPLY) + + lying.Blend(DI,ICON_OVERLAY) + + var/image/standing_image = new /image("icon" = standing) + var/image/lying_image = new /image("icon" = lying) + + overlays_standing[DAMAGE_LAYER] = standing_image + overlays_lying[DAMAGE_LAYER] = lying_image - overlays_standing[DAMAGE_LAYER] = standing - overlays_lying[DAMAGE_LAYER] = lying if(update_icons) update_icons() //BASE MOB SPRITE /mob/living/carbon/human/proc/update_body(var/update_icons=1) + if(stand_icon) del(stand_icon) if(lying_icon) del(lying_icon) if(dna && dna.mutantrace) return - var/husk = (HUSK in src.mutations) - var/fat = (FAT in src.mutations) + var/g = "m" if(gender == FEMALE) g = "f" + var/husk = (HUSK in src.mutations) + var/obese = (FAT in src.mutations) + + // whether to draw the individual limbs + var/individual_limbs = 1 + //Base mob icon - if(husk) - stand_icon = new /icon('icons/mob/human.dmi', "husk_s") - lying_icon = new /icon('icons/mob/human.dmi', "husk_l") - else if(fat) + if(obese) + // Sorry, no dismemberment for fat people. stand_icon = new /icon('icons/mob/human.dmi', "fatbody_s") lying_icon = new /icon('icons/mob/human.dmi', "fatbody_l") + individual_limbs = 0 else - stand_icon = new /icon('icons/mob/human.dmi', "body_[g]_s") - lying_icon = new /icon('icons/mob/human.dmi', "body_[g]_l") + stand_icon = new /icon('icons/mob/human.dmi', "torso_[g]_s") + lying_icon = new /icon('icons/mob/human.dmi', "torso_[g]_l") + + // Draw each individual limb + if(individual_limbs) + stand_icon.Blend(new /icon('icons/mob/human.dmi', "chest_[g]_s"), ICON_OVERLAY) + lying_icon.Blend(new /icon('icons/mob/human.dmi', "chest_[g]_l"), ICON_OVERLAY) + + var/datum/organ/external/head = get_organ("head") + if(head && !(head.status & ORGAN_DESTROYED)) + stand_icon.Blend(new /icon('icons/mob/human.dmi', "head_[g]_s"), ICON_OVERLAY) + lying_icon.Blend(new /icon('icons/mob/human.dmi', "head_[g]_l"), ICON_OVERLAY) + + for(var/datum/organ/external/part in organs) + if(!istype(part, /datum/organ/external/groin) \ + && !istype(part, /datum/organ/external/chest) \ + && !istype(part, /datum/organ/external/head) \ + && !(part.status & ORGAN_DESTROYED)) + var/icon/temp = new /icon('human.dmi', "[part.icon_name]_s") + if(part.status & ORGAN_ROBOT) temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) + stand_icon.Blend(temp, ICON_OVERLAY) + temp = new /icon('human.dmi', "[part.icon_name]_l") + if(part.status & ORGAN_ROBOT) temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) + lying_icon.Blend(temp , ICON_OVERLAY) + + stand_icon.Blend(new /icon('human.dmi', "groin_[g]_s"), ICON_OVERLAY) + lying_icon.Blend(new /icon('human.dmi', "groin_[g]_l"), ICON_OVERLAY) + + if (husk) + var/icon/husk_s = new /icon('human.dmi', "husk_s") + var/icon/husk_l = new /icon('human.dmi', "husk_l") + + for(var/datum/organ/external/part in organs) + if(!istype(part, /datum/organ/external/groin) \ + && !istype(part, /datum/organ/external/chest) \ + && !istype(part, /datum/organ/external/head) \ + && (part.status & ORGAN_DESTROYED)) + husk_s.Blend(new /icon('dam_mask.dmi', "[part.icon_name]"), ICON_SUBTRACT) + husk_l.Blend(new /icon('dam_mask.dmi', "[part.icon_name]2"), ICON_SUBTRACT) + + stand_icon.Blend(husk_s, ICON_OVERLAY) + lying_icon.Blend(husk_l, ICON_OVERLAY) //Skin tone if(s_tone >= 0) @@ -207,6 +277,7 @@ Please contact me on #coderbus IRC. ~Carn x lying_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) //Eyes + // Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head var/icon/eyes_s = new/icon('icons/mob/human_face.dmi', "eyes_s") var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l") eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) @@ -219,11 +290,11 @@ Please contact me on #coderbus IRC. ~Carn x lying_icon.Blend(new/icon('icons/mob/human_face.dmi', "mouth_[g]_l"), ICON_OVERLAY) //Underwear - if(underwear < 12 && underwear > 0) - if(!fat) - stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY) - lying_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_l"), ICON_OVERLAY) - if(update_icons) update_icons() + if(underwear < 6 && underwear > 0) + if(!obese) + stand_icon.Blend(new /icon('human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY) + lying_icon.Blend(new /icon('human.dmi', "underwear[underwear]_[g]_l"), ICON_OVERLAY) + //HAIR OVERLAY @@ -649,6 +720,42 @@ Please contact me on #coderbus IRC. ~Carn x overlays_standing[L_HAND_LAYER] = null if(update_icons) update_icons() +// Used mostly for creating head items +/mob/living/carbon/human/proc/generate_head_icon() + var/g = "m" + if (gender == FEMALE) g = "f" + + //base icons + var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l") + + if(f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(facial_hair_style) + var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l") + facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + face_lying.Blend(facial_l, ICON_OVERLAY) + + if(h_style) + var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(hair_style) + var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l") + hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + face_lying.Blend(hair_l, ICON_OVERLAY) + + //Eyes + // Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head + var/icon/eyes_s = new/icon('icons/mob/human_face.dmi', "eyes_s") + var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l") + eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) + eyes_l.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) + face_lying.Blend(eyes_l, ICON_OVERLAY) + + //Mouth + face_lying.Blend(new/icon('icons/mob/human_face.dmi', "mouth_[g]_l"), ICON_OVERLAY) + + var/image/face_lying_image = new /image(icon = face_lying) + return face_lying_image + //Human Overlays Indexes///////// #undef MUTANTRACE_LAYER #undef MUTATIONS_LAYER diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 4a442e48e62..c46484f1e63 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -30,6 +30,7 @@ var/obj/screen/nutrition_icon = null var/obj/screen/pressure = null var/obj/screen/damageoverlay = null + var/obj/screen/pain = null /*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob. A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such. diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index c7921f001b4..6702beab34d 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -115,6 +115,9 @@ proc/isorgan(A) return 1 return 0 +proc/hasorgans(A) + return (ishuman(A) || ismonkey(A)) + /proc/hsl2rgb(h, s, l) return diff --git a/code/setup.dm b/code/setup.dm index e77c20295f4..ad54c4008ab 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -500,3 +500,36 @@ var/list/liftable_structures = list(\ //some arbitrary defines to be used by self-pruning global lists. (see master_controller) #define PROCESS_KILL 26 //Used to trigger removal from a processing list + +//Damage things +#define CUT "cut" +#define BRUISE "bruise" +#define BRUTE "brute" +#define BURN "fire" +#define TOX "tox" +#define OXY "oxy" +#define CLONE "clone" +#define HALLOSS "halloss" + +#define STUN "stun" +#define WEAKEN "weaken" +#define PARALYZE "paralize" +#define IRRADIATE "irradiate" +#define STUTTER "stutter" +#define SLUR "slur" +#define EYE_BLUR "eye_blur" +#define DROWSY "drowsy" + +///////////////// +//ORGAN DEFINES// +///////////////// +#define ORGAN_CUT_AWAY 1 +#define ORGAN_GAUZED 2 +#define ORGAN_ATTACHABLE 4 +#define ORGAN_BLEEDING 8 +#define ORGAN_BANDAGED 16 +#define ORGAN_BROKEN 32 +#define ORGAN_DESTROYED 64 +#define ORGAN_ROBOT 128 +#define ORGAN_SPLINTED 256 +#define SALVED 512 \ No newline at end of file diff --git a/config/game_options.txt b/config/game_options.txt index 9ec32a29484..9eef19a5c8e 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -6,6 +6,14 @@ HEALTH_THRESHOLD_CRIT 0 ## level of health at which a mob becomes dead HEALTH_THRESHOLD_DEAD -100 +## multiplier which enables organs to take more damage before bones breaking or limbs being destroyed +## 100 means normal, 50 means half +ORGAN_HEALTH_MULTIPLIER 100 + +## multiplier which influences how fast organs regenerate naturally +## 100 means normal, 50 means half +ORGAN_REGENERATION_MULTIPLIER 100 + ### REVIVAL ### ## whether pod plants work or not diff --git a/icons/mob/dam_human.dmi b/icons/mob/dam_human.dmi index 379f7dc5eb864c7a5cd67ec6da3abb4c7d92e317..c68299554c88736776d7bce2763b4ea93f4c1f8e 100644 GIT binary patch literal 9738 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 bEO9w#ri4xj;BpfDmt39uh8k6Bb|L=*;`19U diff --git a/icons/mob/dam_mask.dmi b/icons/mob/dam_mask.dmi new file mode 100644 index 0000000000000000000000000000000000000000..5cf1e09f19b352e63f737ab31b7f43c4a9b654df GIT binary patch literal 1503 zcmV<51t9u~P)lXaA%~@1|t%R5s&%=a4edGVk|KWY#-+tfy%m3kh;s4A3 z-hSZWeB|PO;H<2y{KAL(!Gz`I<==ha%F4>`@9*M#-`;-W;C|!(m;e9D{{GGU{+j*$ z&Hv(j;*w3`S^xk50d!JMQvg8b*k%9#0NZ+0Sad{Xb7OL8aCB*JZU6vyoQ;&R4#FT5 zMd$Jrq@6WdU0sZg>0p1ML3u4iS`486zE~y)!`%6vuKBhDugQ?R;FftQee_D9u06N@lTvptOVmd9EL< z4Oz@!nClIVKo~+vEgs~u*iDf~iU~IX#SqH%O3eA2H5jHypq6S-Q=VHqA#o6vOy#*n z6;du*K*~W_vW3K9+}Bs0x*9Rx^KafhgTko4M^?P)PRqCS0h|6ymXVcprI9ES!igZ0ZM|0vY_pwV{&}dMnS6q1+71N*9Is%Vak3ALr>36(a*|2 zKkJU})d5O1{M64QdZ3?mN9*bUub_-qP*ugw*ZGc4Cu$5%A(1K(d$7C$D(}NWmyip3 zLC9r8i|7GC<-JA2k?e%`NQm;C5+J>G+HUARZn~fu3M2rxC2s&I zXys__0T{h~09;F8!XPT1L=5}&3D&R0=_m5j@!fRhxPyCzya}WUn(5+~I#LWCl>2Dy z(itu&w1hhx2CZlbj64Va5*IGcups~NI3qLrTqSP;2L#R5QeK^^)v?Mz&(M7PQX;8> zuJOWuShz;ro~efUCmx?C=D`s^roF3P_k1^R0{^X`dEH);XrRzLS-G}bvh3j$cP;4l z6m_$;>-jztgxkD)K?%G0dGNk@LY_Rk{W*IW53YlJ+q^oO(-JhX=>pzcCqWOl@bh0_ z{VQGBoeb88{$lAb7e23%EFu^U@s|D~*y9yDNfdVOmj?O%%j=}`){oCqX1g!s>G5vp zh99vG7(G3%-S=Lq932J-nnx>A2Qo*{0=v1_G+z>eD3bot zgShpfx8UWK{R(=r^MMADf41GvuhDmGzSVL*#}l5Jje`7H{$CxHJYUIgt8#E;T*DUD zkK#ZlaP`EUj){7Zg;5 zW}Ob5`dj;<5ieNeb;?q|jiQ^^1qDTP=Erp(8t@}nqG74u=hV&1om(@u5Ri({8XWZ= zS;1dCfmYo8lTz}MlM_QW`4A*$*5yt4uO8^;QBVZg;~(wWEF;68&QJgV002ovPDHLk FV1i2o28jRw literal 0 HcmV?d00001 diff --git a/icons/mob/human.dmi b/icons/mob/human.dmi index 1526448c6fd4151bc3c48299b4f46db1d2565680..1dff87d69e0c518f09c180ec9faa661617a051c5 100644 GIT binary patch literal 22915 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 R6>N