From 9c92d3851acce7dfc10a7e463aa7f8b1bd39b907 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Wed, 25 Mar 2015 23:11:00 +1030 Subject: [PATCH] Got various kinds of limb loss plus dislocation working. --- code/_onclick/item_attack.dm | 15 ++-- code/game/objects/items/weapons/twohanded.dm | 2 +- code/modules/hydroponics/trays/tray_tools.dm | 2 +- .../living/carbon/human/human_attackhand.dm | 19 ++-- .../mob/living/carbon/human/human_defense.dm | 77 ++++++++-------- .../mob/living/carbon/human/human_organs.dm | 2 +- .../living/carbon/human/species/species.dm | 1 + code/modules/organs/organ_external.dm | 87 +++++++++++++------ code/modules/organs/organ_icon.dm | 4 +- 9 files changed, 128 insertions(+), 81 deletions(-) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 52b6fe94242..1d68fb54e8e 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -43,14 +43,15 @@ var/mob/living/carbon/human/H = M // Handle striking to cripple. - if(user.a_intent == "disarm" && H.attack_joint(src, user, def_zone)) - add_fingerprint(user) - return 1 - - var/hit = H.attacked_by(src, user, def_zone) - if(hit && hitsound) + var/dislocation_str + if(user.a_intent == "disarm") + dislocation_str = H.attack_joint(src, user, def_zone) + if(H.attacked_by(src, user, def_zone) && hitsound) playsound(loc, hitsound, 50, 1, -1) - return hit + spawn(1) //ugh I hate this but I don't want to root through human attack procs to print it after this call resolves. + if(dislocation_str) user.visible_message("[dislocation_str]") + return 1 + return 0 else if(attack_verb.len) user.visible_message("[M] has been [pick(attack_verb)] with [src] by [user]!") diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 2ccd78d3616..5367f39c979 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -218,7 +218,7 @@ throw_speed = 3 throw_range = 7 throwforce = 7 - attack_verb = list("smashed", "beaten", "slammed", "smacked", "striked", "battered", "bonked") + attack_verb = list("smashed", "beaten", "slammed", "smacked", "struck", "battered", "bonked") hitsound = 'sound/weapons/genhit3.ogg' force_wielded = 23 diff --git a/code/modules/hydroponics/trays/tray_tools.dm b/code/modules/hydroponics/trays/tray_tools.dm index 67d630119a8..10f5961da71 100644 --- a/code/modules/hydroponics/trays/tray_tools.dm +++ b/code/modules/hydroponics/trays/tray_tools.dm @@ -226,7 +226,7 @@ icon_state = "hatchet" flags = CONDUCT force = 12.0 - w_class = 2.0 + w_class = 3.0 throwforce = 15.0 throw_speed = 4 throw_range = 4 diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index cb2e1aec47c..f666ab6a0b4 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -302,13 +302,16 @@ return 1 /mob/living/carbon/human/proc/attack_joint(var/obj/item/W, var/mob/living/user, var/def_zone) - - var/obj/item/organ/external/organ = get_organ(check_zone(def_zone)) - if(!organ || organ.is_dislocated() || organ.dislocated == -1) //Cannot dislocate this organ. - return 0 - - user.visible_message("[src] has been [pick(W.attack_verb)] in \the [organ] with \the [W] by [user]!") + var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src) + if(user == src) // Attacking yourself can't miss + target_zone = user.zone_sel.selecting + if(!target_zone) + return null + var/obj/item/organ/external/organ = get_organ(check_zone(target_zone)) + if(!organ || organ.is_dislocated() || organ.dislocated == -1) + return null + var/dislocation_str if(prob(W.force)) - user.visible_message("[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")] with a grisly crunch!") + dislocation_str = "[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")] with a grisly crunch!" organ.dislocate() - return 1 + return dislocation_str diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 7f002de7882..bfc7756e4ff 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -11,6 +11,8 @@ emp_act /mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone) var/obj/item/organ/external/organ = get_organ(check_zone(def_zone)) + if(!organ) + return //Shields if(check_shields(P.damage, "the [P.name]")) @@ -85,16 +87,18 @@ emp_act if(isorgan(def_zone)) return getarmor_organ(def_zone, type) var/obj/item/organ/external/affecting = get_organ(def_zone) - return getarmor_organ(affecting, type) + if(affecting) + return getarmor_organ(affecting, type) //If a specific bodypart is targetted, check how that bodypart is protected and return the value. //If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values for(var/organ_name in organs_by_name) if (organ_name in organ_rel_size) var/obj/item/organ/external/organ = organs_by_name[organ_name] - var/weight = organ_rel_size[organ_name] - armorval += getarmor_organ(organ, type) * weight - total += weight + if(organ) + var/weight = organ_rel_size[organ_name] + armorval += getarmor_organ(organ, type) * weight + total += weight return (armorval/max(total, 1)) //this proc returns the Siemens coefficient of electrical resistivity for a particular external organ. @@ -113,13 +117,13 @@ emp_act //this proc returns the armour value for a particular external organ. /mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type) - if(!type) return 0 + if(!type || !def_zone) return 0 var/protection = 0 var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) for(var/gear in protective_gear) if(gear && istype(gear ,/obj/item/clothing)) var/obj/item/clothing/C = gear - if(C.body_parts_covered & def_zone.body_part) + if(istype(C) && C.body_parts_covered & def_zone.body_part) protection += C.armor[type] return protection @@ -186,7 +190,7 @@ emp_act target_zone = user.zone_sel.selecting if(!target_zone) visible_message("\red [user] misses [src] with \the [I]!") - return 0 + return 1 var/obj/item/organ/external/affecting = get_organ(target_zone) @@ -194,9 +198,11 @@ emp_act user << "They are missing that limb!" return + var/effective_force = I.force + if(user.a_intent == "disarm") effective_force = round(I.force/2) var/hit_area = affecting.name - if((user != src) && check_shields(I.force, "the [I.name]")) + if((user != src) && check_shields(effective_force, "the [I.name]")) return 0 if(istype(I,/obj/item/weapon/card/emag)) @@ -224,14 +230,14 @@ emp_act weapon_sharp = 0 weapon_edge = 0 - if(armor >= 2) return 0 - if(!I.force) return 0 - var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) + if(armor >= 2) return 0 + if(!effective_force) return 0 + var/Iforce = effective_force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) - apply_damage(I.force, I.damtype, affecting, armor, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) + apply_damage(effective_force, I.damtype, affecting, armor, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) var/bloody = 0 - if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2))) + if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (effective_force * 2))) I.add_blood(src) //Make the weapon bloody, not the person. // if(user.hand) user.update_inv_l_hand() //updates the attacker's overlay for the (now bloodied) weapon // else user.update_inv_r_hand() //removed because weapons don't have on-mob blood overlays @@ -246,36 +252,37 @@ emp_act H.bloody_body(src) H.bloody_hands(src) - switch(hit_area) - if("head")//Harder to score a stun but if you do it lasts a bit longer - if(prob(I.force)) - apply_effect(20, PARALYZE, armor) - visible_message("\red [src] has been knocked unconscious!") - if(bloody)//Apply blood - if(wear_mask) - wear_mask.add_blood(src) - update_inv_wear_mask(0) - if(head) - head.add_blood(src) - update_inv_head(0) - if(glasses && prob(33)) - glasses.add_blood(src) - update_inv_glasses(0) + if(!stat) + switch(hit_area) + if("head")//Harder to score a stun but if you do it lasts a bit longer + if(prob(effective_force)) + apply_effect(20, PARALYZE, armor) + visible_message("\red [src] has been knocked unconscious!") + if(bloody)//Apply blood + if(wear_mask) + wear_mask.add_blood(src) + update_inv_wear_mask(0) + if(head) + head.add_blood(src) + update_inv_head(0) + if(glasses && prob(33)) + glasses.add_blood(src) + update_inv_glasses(0) - if("chest")//Easier to score a stun but lasts less time - if(prob((I.force + 10))) - apply_effect(6, WEAKEN, armor) - visible_message("\red [src] has been knocked down!") + if("chest")//Easier to score a stun but lasts less time + if(prob((effective_force + 10))) + apply_effect(6, WEAKEN, armor) + visible_message("\red [src] has been knocked down!") - if(bloody) - bloody_body(src) + if(bloody) + bloody_body(src) if(Iforce > 10 || Iforce >= 5 && prob(33)) forcesay(hit_appends) //forcesay checks stat already //Melee weapon embedded object code. if (I && I.damtype == BRUTE && !I.anchored && !I.is_robot_module()) - var/damage = I.force + var/damage = effective_force if (armor) damage /= armor+1 diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 0255a23d374..fb9955b481f 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -39,7 +39,7 @@ if (!lying && world.time - l_move_time < 15) //Moving around with fractured ribs won't do you any good - if (E.is_broken() && E.internal_organs && prob(15)) + if (E.is_broken() && E.internal_organs && E.internal_organs.len && prob(15)) var/obj/item/organ/I = pick(E.internal_organs) custom_pain("You feel broken bones moving in your [E.name]!", 1) I.take_damage(rand(3,5)) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 45fae614608..a04bfdebdc6 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -41,6 +41,7 @@ // Death vars. var/gibber_type = /obj/effect/gibspawner/human + var/single_gib_type = /obj/effect/decal/cleanable/blood/gibs var/remains_type = /obj/effect/decal/remains/xeno var/gibbed_anim = "gibbed-h" var/dusted_anim = "dust-h" diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index e7d5b0b5e77..602f353ee6f 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -13,7 +13,6 @@ var/max_size = 0 var/last_dam = -1 var/icon/mob_icon - var/icon/item_icon var/gendered_icon = 0 var/limb_name var/disfigured = 1 @@ -51,6 +50,7 @@ min_broken_damage = 30 max_damage = 0 + dir = SOUTH /obj/item/organ/external/attackby(obj/item/weapon/W as obj, mob/user as mob) switch(stage) @@ -78,7 +78,7 @@ ..() /obj/item/organ/external/proc/is_dislocated() - if(dislocated) + if(dislocated > 0) return 1 if(parent) return parent.is_dislocated() @@ -202,11 +202,18 @@ src.update_damages() //If limb took enough damage, try to cut or tear it off - if(body_part != UPPER_TORSO) //as hilarious as it is, getting hit on the chest too much shouldn't effectively gib you. - if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) - if( (edge && prob(5 * brute)) || (brute > 20 && prob(brute)) ) - droplimb() - return + if(!cannot_amputate && config.limbs_can_break && (brute_dam + burn_dam) >= (max_damage * config.organ_health_multiplier)) + if((sharp || edge) && used_weapon) + if(istype(used_weapon,/obj/item)) + var/obj/item/W = used_weapon + if(W.w_class >= 3) droplimb() + return + if(brute >= 23 && prob(brute)) // Wooden baseball bat in both hands == 23 + droplimb(0,2) + return + if(burn >= 20) // Most laser rifle shots. + droplimb(0,1) + return owner.updatehealth() @@ -592,16 +599,31 @@ Note that amputating the affected organ does in fact remove the infection from t ****************************************************/ //Handles dismemberment -/obj/item/organ/external/proc/droplimb(var/clean) +/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate) - if(cannot_amputate) + if(cannot_amputate || !owner) return - if(!clean) - owner.visible_message( - "\The [owner]'s [src.name] flies off in an arc!",\ - "Your [src.name] goes flying off!",\ - "You hear a terrible sound of ripping tendons and flesh.") + if(!disintegrate) + disintegrate = 0 + + switch(disintegrate) + if(0) + if(!clean) + owner.visible_message( + "\The [owner]'s [src.name] flies off in an arc!",\ + "Your [src.name] goes flying off!",\ + "You hear a terrible sound of ripping tendons and flesh.") + if(1) + owner.visible_message( + "\The [owner]'s [src.name] flashes away into ashes!",\ + "Your [src.name] flashes away into ashes!",\ + "You hear the crackling sound of burning flesh.") + if(2) + owner.visible_message( + "\The [owner]'s [src.name] explodes in a shower of gore!",\ + "Your [src.name] explodes in a shower of gore!",\ + "You hear the sickening splatter of gore.") src.removed() @@ -613,18 +635,30 @@ Note that amputating the affected organ does in fact remove the infection from t update_health() owner.update_body() - compile_icon() - add_blood(owner) - - var/matrix/M = matrix() - M.Turn(rand(180)) - src.transform = M - - if(!clean) - // Throw limb around. - if(src && istype(loc,/turf)) - throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + switch(disintegrate) + if(0) + compile_icon() + add_blood(owner) + var/matrix/M = matrix() + M.Turn(rand(180)) + src.transform = M + if(!clean) + // Throw limb around. + if(src && istype(loc,/turf)) + throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + return + if(1) + new /obj/effect/decal/cleanable/ash(get_turf(owner)) + if(2) + var/obj/effect/decal/cleanable/blood/gibs/gore = new owner.species.single_gib_type(get_turf(owner)) + if(owner.species.flesh_color) + gore.fleshcolor = owner.species.flesh_color + if(owner.species.blood_color) + gore.basecolor = owner.species.blood_color + gore.update_icon() + gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + del(src) /**************************************************** HELPERS @@ -801,8 +835,6 @@ Note that amputating the affected organ does in fact remove the infection from t status |= ORGAN_DESTROYED owner.bad_external_organs -= src - icon = item_icon - for(var/implant in implants) //todo: check if this can be left alone del(implant) @@ -853,6 +885,7 @@ Note that amputating the affected organ does in fact remove the infection from t dislocated = -1 gendered_icon = 1 cannot_amputate = 1 + parent_organ = null /obj/item/organ/external/groin name = "lower body" diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 7fbdf3bf1d5..9361ec3f4a7 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -1,5 +1,8 @@ var/global/list/limb_icon_cache = list() +/obj/item/organ/external/set_dir() + return + /obj/item/organ/proc/get_icon(var/image/supplied) var/key = "internal-[icon_state]" var/image/I @@ -56,7 +59,6 @@ var/global/list/limb_icon_cache = list() mob_icon.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin), ICON_ADD) dir = EAST - item_icon = icon(mob_icon,icon_state,SOUTH) icon = mob_icon return mob_icon