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