Reworks armor damage reduction + armor components + more goodies. (#11106)

Ports Baystation12/Baystation12#27254 and Baystation12/Baystation12#24787 and everything inbetween I guess.

Note that this PR makes guns and armor overall stronger. Lasers also once again do organ damage.
This commit is contained in:
Matt Atlas
2021-02-14 17:54:45 +02:00
committed by GitHub
parent 3ab59b8ff7
commit c30cd94024
138 changed files with 2187 additions and 848 deletions
@@ -61,7 +61,7 @@
sleeping = 0
willfully_sleeping = FALSE
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
var/t_him = "it"
if (src.gender == MALE)
t_him = "him"
@@ -85,12 +85,12 @@
"<span class='danger'>You attack [src] with [I], but they do not respond... Maybe they have S.S.D?</span>")
else if(client && willfully_sleeping)
user.visible_message("<span class='danger'>[user] attacked [src] with [I] waking [t_him] up!</span>", \
"<span class='danger'>You attack [src] with [I], waking [t_him] up!</span>")
"<span class='danger'>You attack [src] with [I], waking [t_him] up!</span>")
sleeping = 0
willfully_sleeping = FALSE
if(!effective_force || blocked >= 100)
if(!effective_force)
return 0
//Hulk modifier
@@ -99,19 +99,14 @@
//Apply weapon damage
var/damage_flags = I.damage_flags()
if(prob(blocked)) //armor provides a chance to turn sharp/edge weapon attacks into blunt ones
damage_flags &= ~DAM_SHARP
damage_flags &= ~DAM_EDGE
apply_damage(effective_force, I.damtype, hit_zone, blocked, used_weapon=I, damage_flags = damage_flags)
apply_damage(effective_force, I.damtype, hit_zone, I, damage_flags)
//Melee weapon embedded object code.
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
var/damage = effective_force //just the effective damage used for sorting out embedding, no further damage is applied here
if (blocked)
damage *= BLOCKED_MULT(blocked)
damage *= 1 - get_blocked_ratio(hit_zone, I.damtype, I.damage_flags(), I.armor_penetration, I.force)
if (I.can_embed)//If this weapon is allowed to embed in people
if(I.can_embed)//If this weapon is allowed to embed in people
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/sharp = damage_flags & DAM_SHARP
var/edge = damage_flags & DAM_EDGE
@@ -100,7 +100,7 @@
if (severity)
damage_factor = (1 / severity)
var/armorval = getarmor(null, "bomb")
var/armorval = get_blocked_ratio(BP_CHEST, BRUTE, DAM_DISPERSED, damage = damage)
if (armorval)
damage_factor *= (1 - (armorval * 0.01))
+13 -49
View File
@@ -233,15 +233,8 @@
if (1.0)
b_loss += 500
f_loss = 100
if (!prob(getarmor(null, "bomb")))
gib()
return
else
var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src)))
throw_at(target, 200, 4)
//return
// var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src)))
//user.throw_at(target, 200, 4)
var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src)))
throw_at(target, 200, 4)
if (2.0)
b_loss = 60
@@ -261,46 +254,15 @@
if (prob(50))
Paralyse(10)
// factor in armor
var/protection = BLOCKED_MULT(getarmor(null, "bomb"))
b_loss *= protection
f_loss *= protection
var/update = 0
// focus most of the blast on one organ
var/obj/item/organ/external/take_blast = pick(organs)
update |= take_blast.take_damage(b_loss * 0.7, f_loss * 0.7, used_weapon = "Explosive blast")
apply_damage(0.7 * b_loss, BRUTE, null, DAM_EXPLODE, used_weapon = "Explosive blast")
apply_damage(0.7 * f_loss, BURN, null, DAM_EXPLODE, used_weapon = "Explosive blast")
// distribute the remaining 30% on all limbs equally (including the one already dealt damage)
b_loss *= 0.3
f_loss *= 0.3
apply_damage(0.3 * b_loss, BRUTE, null, DAM_EXPLODE | DAM_DISPERSED, used_weapon = "Explosive blast")
apply_damage(0.3 * f_loss, BURN, null, DAM_EXPLODE | DAM_DISPERSED, used_weapon = "Explosive blast")
var/weapon_message = "Explosive Blast"
for(var/obj/item/organ/external/temp in organs)
switch(temp.name)
if(BP_HEAD)
update |= temp.take_damage(b_loss * 0.2, f_loss * 0.2, used_weapon = weapon_message)
if(BP_CHEST)
update |= temp.take_damage(b_loss * 0.4, f_loss * 0.4, used_weapon = weapon_message)
if(BP_L_ARM)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_R_ARM)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_L_LEG)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_R_LEG)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_R_FOOT)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_L_FOOT)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_R_ARM)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(BP_L_ARM)
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(update) UpdateDamageIcon()
UpdateDamageIcon()
/mob/living/carbon/human/proc/implant_loyalty(mob/living/carbon/human/M, override = FALSE) // Won't override by default.
if(!config.use_loyalty_implants && !override) return // Nuh-uh.
@@ -1988,15 +1950,17 @@
return BULLET_IMPACT_METAL
return BULLET_IMPACT_MEAT
/mob/living/carbon/human/bullet_impact_visuals(var/obj/item/projectile/P, var/def_zone, var/damage)
/mob/living/carbon/human/bullet_impact_visuals(var/obj/item/projectile/P, var/def_zone, var/damage, var/blocked_ratio)
..()
if(blocked_ratio > 0.7)
return
switch(get_bullet_impact_effect_type(def_zone))
if(BULLET_IMPACT_MEAT)
if(P.damage_type == BRUTE)
var/hit_dir = get_dir(P.starting, src)
var/obj/effect/decal/cleanable/blood/B = blood_splatter(get_step(src, hit_dir), src, 1, hit_dir)
B.icon_state = pick("dir_splatter_1","dir_splatter_2")
var/scale = min(1, round(P.damage / 50, 0.2))
var/scale = min(1, round(damage / 50, 0.2))
var/matrix/M = new()
B.transform = M.Scale(scale)
@@ -2011,9 +1975,9 @@
src.adjustToxLoss(-damage)
to_chat(src, SPAN_NOTICE("You can feel flow of energy which makes you regenerate."))
src.apply_effect((rand(15,30)),IRRADIATE,blocked = src.getarmor(null, "rad"))
apply_damage((rand(15,30)), IRRADIATE, damage_flags = DAM_DISPERSED)
if(prob(4))
src.apply_effect((rand(20,60)),IRRADIATE,blocked = src.getarmor(null, "rad"))
apply_damage((rand(20,60)), IRRADIATE, damage_flags = DAM_DISPERSED)
if (prob(75))
randmutb(src) // Applies bad mutation
domutcheck(src,null,MUTCHK_FORCED)
@@ -52,9 +52,8 @@
msg_admin_attack("[key_name_admin(M)] stungloved [src.name] ([src.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[M.x];Y=[M.y];Z=[M.z]'>JMP</a>)",ckey=key_name(M),ckey_target=key_name(src))
var/armorblock = run_armor_check(M.zone_sel.selecting, "energy")
apply_effects(5,5,0,0,5,0,0,0,0,armorblock)
apply_damage(rand(5,25), BURN, M.zone_sel.selecting,armorblock)
apply_effects(5,5,0,0,5,0,0,0,0)
apply_damage(rand(5,25), BURN, M.zone_sel.selecting)
if(prob(15))
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
@@ -84,7 +83,6 @@
visible_message("<span class='danger'>[H] has attempted to punch [src]!</span>")
return 0
var/obj/item/organ/external/affecting = get_organ(ran_zone(H.zone_sel.selecting))
var/armor_block = run_armor_check(affecting, "melee")
if(HULK in H.mutations)
damage += 5
@@ -93,10 +91,10 @@
visible_message("<span class='danger'>[H] has punched [src]!</span>")
apply_damage(damage, PAIN, affecting, armor_block)
apply_damage(damage, PAIN, affecting)
if(damage >= 9)
visible_message("<span class='danger'>[H] has weakened [src]!</span>")
apply_effect(4, WEAKEN, armor_block)
apply_effect(4, WEAKEN)
return
@@ -284,12 +282,11 @@
var/obj/item/clothing/gloves/force/X = H.gloves
real_damage *= X.amplification
var/armor = run_armor_check(hit_zone, "melee")
// Apply additional unarmed effects.
attack.apply_effects(H, src, armor, rand_damage, hit_zone)
attack.apply_effects(H, src, rand_damage, hit_zone)
// Finally, apply damage to target
apply_damage(real_damage, hit_dam_type, hit_zone, armor, damage_flags = damage_flags)
apply_damage(real_damage, hit_dam_type, hit_zone, damage_flags = damage_flags)
if(M.resting && src.help_up_offer)
@@ -375,7 +372,7 @@
var/randn = rand(1, 100)
if(randn <= 25)
if(H.gloves && istype(H.gloves,/obj/item/clothing/gloves/force))
apply_effect(6, WEAKEN, run_armor_check(affecting, "melee"))
apply_effect(6, WEAKEN)
playsound(loc, 'sound/weapons/push_connect.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] hurls [src] to the floor!</span>")
step_away(src,M,15)
@@ -384,7 +381,7 @@
return
else
var/armor_check = run_armor_check(affecting, "melee")
var/armor_check = 100 * get_blocked_ratio(affecting, BRUTE, damage = 20)
apply_effect(3, WEAKEN, armor_check)
if(armor_check < 100)
visible_message("<span class='danger'>[M] has pushed [src]!</span>")
@@ -406,7 +403,7 @@
sleep(1)
step_away(src,M,15)
sleep(1)
apply_effect(1, WEAKEN, run_armor_check(affecting, "melee"))
apply_effect(1, WEAKEN, get_blocked_ratio(M.zone_sel.selecting, BRUTE, damage = 20)*100)
return
//See about breaking grips or pulls
@@ -506,8 +503,7 @@
if(!dam_zone)
dam_zone = pick(organs)
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
apply_damage(damage, BRUTE, affecting)
updatehealth()
return TRUE
@@ -20,7 +20,6 @@
ChangeToHusk()
UpdateDamageIcon() // to fix that darn overlay bug
return
/mob/living/carbon/human/proc/get_total_health()
var/amount = maxHealth - getFireLoss() - getBruteLoss() - getOxyLoss() - getToxLoss() - getBrainLoss()
@@ -323,7 +322,8 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t
updatehealth()
BITSET(hud_updateflag, HEALTH_HUD)
speech_problem_flag = 1
if(update) UpdateDamageIcon()
if(update)
UpdateDamageIcon()
// damage MANY external organs, in random order
/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/damage_flags, var/used_weapon = null)
@@ -383,63 +383,76 @@ This function restores all organs.
zone = BP_HEAD
return organs_by_name[zone]
/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/obj/used_weapon = null, var/damage_flags)
//visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]")
/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone, var/obj/used_weapon, var/damage_flags, var/armor_pen, var/silent = FALSE)
if (invisibility == INVISIBILITY_LEVEL_TWO && back && (istype(back, /obj/item/rig)))
if(damage > 0)
to_chat(src, "<span class='danger'>You are now visible.</span>")
src.invisibility = 0
var/obj/item/organ/external/organ = get_organ(def_zone)
if(!organ)
if(isorgan(def_zone))
organ = def_zone
else
if(!def_zone)
if(damage_flags & DAM_DISPERSED)
var/old_damage = damage
var/tally
silent = TRUE // Will damage a lot of organs, probably, so avoid spam.
for(var/zone in organ_rel_size)
tally += organ_rel_size[zone]
for(var/zone in organ_rel_size)
damage = old_damage * organ_rel_size[zone]/tally
def_zone = zone
. = .() || .
return
def_zone = ran_zone(def_zone)
organ = get_organ(check_zone(def_zone))
//Handle other types of damage
if(damagetype != BRUTE && damagetype != BURN)
if(!(damagetype in list(BRUTE, BURN, PAIN, CLONE)))
if(!stat && damagetype == PAIN)
if((damage > 25 && prob(20)) || (damage > 50 && prob(60)))
emote("scream")
return ..()
..(damage, damagetype, def_zone, blocked)
return 1
if(!organ)
return FALSE
//Handle BRUTE and BURN damage
handle_suit_punctures(damagetype, damage, def_zone)
if(blocked >= 100)
return 0
var/obj/item/organ/external/organ = null
if(isorgan(def_zone))
organ = def_zone
else
if(!def_zone) def_zone = ran_zone(def_zone)
organ = get_organ(check_zone(def_zone))
if(!organ)
return 0
if(blocked)
damage *= BLOCKED_MULT(blocked)
var/list/after_armor = modify_damage_by_armor(def_zone, damage, damagetype, damage_flags, src, armor_pen, silent)
damage = after_armor[1]
damagetype = after_armor[2]
damage_flags = after_armor[3]
if(!damage)
return FALSE
if(damage > 15 && prob(damage*4) && organ.can_feel_pain())
make_adrenaline(round(damage/10))
switch(damagetype)
if(BRUTE)
damageoverlaytemp = 20
if(damage > 0)
damage *= species.brute_mod
if(organ.take_damage(damage, 0, damage_flags, used_weapon))
UpdateDamageIcon()
organ.take_damage(damage, 0, damage_flags, used_weapon)
UpdateDamageIcon()
if(BURN)
damageoverlaytemp = 20
if(damage > 0)
damage *= species.burn_mod
if(organ.take_damage(0, damage, damage_flags, used_weapon))
UpdateDamageIcon()
organ.take_damage(0, damage, damage_flags, used_weapon)
UpdateDamageIcon()
if(PAIN)
organ.add_pain(damage)
if(CLONE)
organ.add_genetic_damage(damage)
// Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life().
updatehealth()
BITSET(hud_updateflag, HEALTH_HUD)
return 1
return TRUE
/mob/living/carbon/human/apply_radiation(var/rads)
if(species && rads > 0)
@@ -43,11 +43,13 @@ emp_act
//Shrapnel
if(!(species.flags & NO_EMBED) && P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
var/armor = get_blocked_ratio(def_zone, BRUTE, P.damage_flags(), armor_pen = P.armor_penetration, damage = P.damage)*100
if(prob(20 + max(P.damage + P.embed_chance - armor, -10)))
P.do_embed(organ)
return (..(P , def_zone))
var/blocked = ..(P, def_zone)
return blocked
/mob/living/carbon/human/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone)
var/obj/item/organ/external/affected = get_organ(check_zone(def_zone))
@@ -78,27 +80,37 @@ emp_act
..(stun_amount, agony_amount, def_zone)
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
var/armorval = 0
var/total = 0
/mob/living/carbon/human/get_blocked_ratio(def_zone, damage_type, damage_flags, armor_pen, damage)
if(!def_zone && (damage_flags & DAM_DISPERSED))
var/tally
for(var/zone in organ_rel_size)
tally += organ_rel_size[zone]
for(var/zone in organ_rel_size)
def_zone = zone
. += .() * organ_rel_size/tally
return
return ..()
if(def_zone)
if(isorgan(def_zone))
return getarmor_organ(def_zone, type)
var/obj/item/organ/external/affecting = get_organ(def_zone)
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]
if(organ)
var/weight = organ_rel_size[organ_name]
armorval += getarmor_organ(organ, type) * weight
total += weight
return (armorval/max(total, 1))
/mob/living/carbon/human/get_armors_by_zone(obj/item/organ/external/def_zone, damage_type, damage_flags)
. = ..()
if(!def_zone)
def_zone = ran_zone()
if(!istype(def_zone))
def_zone = get_organ(check_zone(def_zone))
if(!def_zone)
return
var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
for(var/obj/item/clothing/gear in protective_gear)
if(gear.accessories && length(gear.accessories))
for(var/obj/item/clothing/accessory/bling in gear.accessories)
if(bling.body_parts_covered & def_zone.body_part)
var/armor = bling.GetComponent(/datum/component/armor)
if(armor)
. += armor
if(gear.body_parts_covered & def_zone.body_part)
var/armor = gear.GetComponent(/datum/component/armor)
if(armor)
. += armor
//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ.
/mob/living/carbon/human/proc/get_siemens_coefficient_organ(var/obj/item/organ/external/def_zone)
@@ -123,30 +135,16 @@ emp_act
results.Add(C)
return results
//this proc returns the armor value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type)
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/obj/item/clothing/gear in protective_gear)
if(!isnull(gear.armor) && gear.body_parts_covered & def_zone.body_part)
protection = add_armor(protection, gear.armor[type])
for(var/obj/item/clothing/accessory/A in gear.accessories)
if(!isnull(A.armor) && A.body_parts_covered & def_zone.body_part)
protection = add_armor(protection, A.armor[type])
return protection
/mob/living/carbon/human/proc/check_head_coverage()
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform)
for(var/bp in body_parts)
if(!bp) continue
if(!bp)
continue
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & HEAD)
return 1
return 0
return TRUE
return FALSE
/mob/living/carbon/human/proc/check_head_airtight_coverage()
var/list/clothing = list(head, wear_mask, wear_suit)
@@ -231,19 +229,18 @@ emp_act
if(user == src) // Attacking yourself can't miss
target_zone = user.zone_sel.selecting
if(!target_zone)
visible_message("<span class='danger'>[user] misses [src] with \the [I]!</span>")
return 0
//var/obj/item/organ/external/affecting = get_organ(target_zone)
if(!hit_zone)
visible_message("<span class='danger'>[user] misses [src] with \the [I]!</span>")
return
if(check_shields(I.force, I, user, target_zone, "the [I.name]"))
return null
return
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if (!affecting || affecting.is_stump())
to_chat(user, "<span class='danger'>They are missing that limb!</span>")
return null
return
return hit_zone
@@ -253,13 +250,9 @@ emp_act
return //should be prevented by attacked_with_item() but for sanity.
visible_message("<span class='danger'>[src] has been [LAZYPICK(I.attack_verb, "attacked")] in the [affecting.name] with [I] by [user]!</span>")
return standard_weapon_hit_effects(I, user, effective_force, hit_zone)
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
return blocked
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting)
return 0
@@ -273,23 +266,21 @@ emp_act
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
effective_force /= 2 //half the effective force
if(!..(I, user, effective_force, blocked, hit_zone))
return 0
if(!..(I, user, effective_force, hit_zone))
return FALSE
attack_joint(affecting, I, blocked) //but can dislocate joints
else if(!..())
return 0
return FALSE
// forceglove amplification
if(istype(user, /mob/living/carbon/human))
if(ishuman(user))
var/mob/living/carbon/human/X = user
if(X.gloves && istype(X.gloves,/obj/item/clothing/gloves/force))
var/obj/item/clothing/gloves/force/G = X.gloves
effective_force *= G.amplification
if(effective_force > 10 || effective_force >= 5 && prob(33))
forcesay(hit_appends) //forcesay checks stat already
if((I.damtype == BRUTE || I.damtype == PAIN) && prob(25 + (effective_force * 2)))
if(!stat)
if(headcheck(hit_zone))
@@ -326,7 +317,7 @@ emp_act
if(BP_CHEST)
bloody_body(src)
return 1
return TRUE
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/blocked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
@@ -396,12 +387,8 @@ emp_act
var/obj/item/organ/external/affecting = get_organ(zone)
var/hit_area = affecting.name
src.visible_message("<span class='warning'>[src] has been hit in the [hit_area] by [O].</span>", "<span class='warning'><font size='2'>You're hit in the [hit_area] by [O]!</font></span>")
var/armor = run_armor_check(affecting, "melee", O.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened the hit to your [hit_area].") //I guess "melee" is the best fit here
if(armor < 100)
var/damage_flags = O.damage_flags()
apply_damage(throw_damage, dtype, zone, armor, O, damage_flags = damage_flags)
src.visible_message("<span class='warning'>[src] has been hit in the [hit_area] by [O].</span>", "<span class='warning'><font size=2>You're hit in the [hit_area] by [O]!</font></span>")
apply_damage(throw_damage, dtype, zone, used_weapon = O, damage_flags = O.damage_flags(), armor_pen = O.armor_penetration)
if(ismob(O.thrower))
var/mob/M = O.thrower
@@ -418,12 +405,11 @@ emp_act
if (!is_robot_module(I))
var/sharp = is_sharp(I)
var/damage = throw_damage
if (armor)
damage *= BLOCKED_MULT(armor)
damage *= (1 - get_blocked_ratio(zone, BRUTE, O.damage_flags(), O.armor_penetration, damage))
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = sharp? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = sharp? 5*I.w_class : 15*I.w_class
var/embed_chance = sharp ? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = sharp ? 5*I.w_class : 15*I.w_class
//Sharp objects will always embed if they do enough damage.
//Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold
@@ -432,7 +418,7 @@ emp_act
// Begin BS12 momentum-transfer code.
var/mass = 1.5
if(istype(O, /obj/item))
if(isitem(O))
var/obj/item/I = O
mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR
var/momentum = speed*mass
@@ -1018,11 +1018,11 @@ mob/living/carbon/human/proc/change_monitor()
last_special = world.time + 20
src.drop_from_inventory(O)
drop_from_inventory(O)
O.replaced(src)
src.update_body()
src.updatehealth()
src.UpdateDamageIcon()
update_body()
updatehealth()
UpdateDamageIcon()
update_body()
updatehealth()
@@ -2,8 +2,8 @@
attack_verb = list("bit", "chomped on")
attack_sound = 'sound/weapons/bite.ogg'
shredding = 0
sharp = 1
edge = 1
sharp = TRUE
edge = TRUE
damage = 5
attack_name = "sharp bite"
@@ -21,8 +21,8 @@
eye_attack_text_victim = "sharp claws"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
sharp = 1
edge = 1
sharp = TRUE
edge = TRUE
damage = 5
attack_name = "claws"
@@ -64,13 +64,13 @@
/datum/unarmed_attack/claws/strong
attack_verb = list("slashed")
damage = 10
shredding = 1
shredding = TRUE
attack_name = "strong claws"
/datum/unarmed_attack/bite/strong
attack_verb = list("mauled")
damage = 10
shredding = 1
shredding = TRUE
attack_name = "strong bite"
/datum/unarmed_attack/slime_glomp
@@ -110,7 +110,7 @@
damage = 7
attack_sound = 'sound/weapons/smash.ogg'
attack_name = "heavy fist"
shredding = 1
shredding = TRUE
/datum/unarmed_attack/industrial/heavy
damage = 9
@@ -125,7 +125,7 @@
damage = 12
attack_sound = 'sound/weapons/beartrap_shut.ogg'
attack_name = "power fist"
shredding = 1
shredding = TRUE
/datum/unarmed_attack/terminator/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armor,var/attack_damage,var/zone)
..()
@@ -148,10 +148,10 @@
attack_verb = list("cleaved", "plowed", "swiped")
attack_noun = list("massive claws")
damage = 25
sharp = 1
edge = 1
sharp = TRUE
edge = TRUE
attack_name = "massive claws"
shredding = 1
shredding = TRUE
/datum/unarmed_attack/claws/cleave/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armor,var/attack_damage,var/zone)
..()
@@ -172,9 +172,9 @@
attack_verb = list("mauled","gored","perforated")
attack_noun = list("mandibles")
damage = 35
shredding = 1
sharp = 1
edge = 1
shredding = TRUE
sharp = TRUE
edge = TRUE
attack_name = "mandibles"
/datum/unarmed_attack/bite/infectious
@@ -188,7 +188,7 @@
to_chat(user, SPAN_WARNING("You feel that \the [target] has been already infected!"))
var/infection_chance = 80
infection_chance -= target.run_armor_check(zone,"melee")
infection_chance -= target.get_blocked_ratio(zone, BRUTE, damage_flags = DAM_SHARP|DAM_EDGE, damage = damage)*100
if(prob(infection_chance))
if(target.reagents)
var/trioxin_amount = REAGENT_VOLUME(target.reagents, /decl/reagent/toxin/trioxin)
@@ -200,7 +200,7 @@
damage = 15
attack_sound = 'sound/weapons/heavysmash.ogg'
attack_name = "crushing fist"
shredding = 1
shredding = TRUE
/datum/unarmed_attack/shocking
attack_verb = list("prodded", "touched")
@@ -766,7 +766,7 @@ var/global/list/golem_types = list(SPECIES_GOLEM_COAL,
/datum/species/golem/uranium/handle_environment_special(var/mob/living/carbon/human/H)
if(prob(25))
for(var/mob/living/L in view(7, H))
L.apply_effect(150, IRRADIATE, blocked = L.getarmor(null, "rad"))
L.apply_damage(150, IRRADIATE, damage_flags = DAM_DISPERSED)
/datum/species/golem/homunculus
name = SPECIES_GOLEM_MEAT
@@ -43,18 +43,19 @@ var/global/list/sparring_attack_cache = list()
/datum/unarmed_attack/proc/get_unarmed_damage()
return damage
/datum/unarmed_attack/proc/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armor,var/attack_damage,var/zone)
/datum/unarmed_attack/proc/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/attack_damage,var/zone)
if(target.stat == DEAD)
return
var/stun_chance = rand(0, 100)
var/armor = target.get_blocked_ratio(zone, BRUTE)
var/pain_message = TRUE
if(!target.can_feel_pain())
pain_message = FALSE
if(attack_damage >= 5 && armor < 100 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance
if(attack_damage >= 5 && armor < 1 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance
switch(zone) // strong punches can have effects depending on where they hit
if(BP_HEAD, BP_MOUTH, BP_EYES)
// Induce blurriness
@@ -92,12 +93,12 @@ var/global/list/sparring_attack_cache = list()
if(pain_message)
target.visible_message("<span class='warning'>[target] gives way slightly.</span>")
target.apply_effect(attack_damage*3, PAIN, armor)
else if(attack_damage >= 5 && !(target == user) && (stun_chance + attack_damage * 5 >= 100) && armor < 100) // Chance to get the usual throwdown as well (25% standard chance)
else if(attack_damage >= 5 && !(target == user) && (stun_chance + attack_damage * 5 >= 100) && armor < 1) // Chance to get the usual throwdown as well (25% standard chance)
if(!target.lying)
target.visible_message("<span class='danger'>[target] [pick("slumps", "falls", "drops")] down to the ground!</span>")
else
target.visible_message("<span class='danger'>[target] has been weakened!</span>")
target.apply_effect(3, WEAKEN, armor)
target.apply_effect(3, WEAKEN, armor*100)
/datum/unarmed_attack/proc/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
var/obj/item/organ/external/affecting = target.get_organ(zone)
@@ -183,7 +183,7 @@ There are several things that need to be remembered:
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_raw list (as a list of icons).
/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1)
/mob/living/carbon/human/UpdateDamageIcon(var/update_icons = 1)
// first check whether something actually changed about damage appearance
var/damage_appearance = ""
+24 -18
View File
@@ -8,36 +8,46 @@
standard 0 if fail
*/
/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/used_weapon = null, var/damage_flags)
if(!damage || (blocked >= 100))
return 0
/mob/living/proc/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone, var/used_weapon, var/damage_flags = 0, var/armor_pen, var/silent = FALSE)
if(!damage)
return FALSE
var/list/after_armor = modify_damage_by_armor(def_zone, damage, damagetype, damage_flags, src, armor_pen, silent)
damage = after_armor[1]
damagetype = after_armor[2]
damage_flags = after_armor[3] // args modifications in case of parent calls
if(!damage)
return FALSE
switch(damagetype)
if(BRUTE)
adjustBruteLoss(damage * BLOCKED_MULT(blocked))
adjustBruteLoss(damage)
if(BURN)
if(COLD_RESISTANCE in mutations)
damage = 0
adjustFireLoss(damage * BLOCKED_MULT(blocked))
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage * BLOCKED_MULT(blocked))
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage * BLOCKED_MULT(blocked))
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage * BLOCKED_MULT(blocked))
adjustCloneLoss(damage)
if(PAIN)
adjustHalLoss(damage * BLOCKED_MULT(blocked))
updatehealth()
return 1
adjustHalLoss(damage)
if(IRRADIATE)
apply_radiation(damage)
/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0)
if(blocked >= 100) return 0
updatehealth()
return TRUE
/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone, var/damage_flags = 0)
if(brute) apply_damage(brute, BRUTE, def_zone, blocked)
if(burn) apply_damage(burn, BURN, def_zone, blocked)
if(tox) apply_damage(tox, TOX, def_zone, blocked)
if(oxy) apply_damage(oxy, OXY, def_zone, blocked)
if(clone) apply_damage(clone, CLONE, def_zone, blocked)
if(halloss) apply_damage(halloss, PAIN, def_zone, blocked)
return 1
return TRUE
/mob/living/proc/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0)
if(!effect || (blocked >= 100)) return 0
@@ -50,9 +60,6 @@
Paralyse(effect * BLOCKED_MULT(blocked))
if(PAIN)
adjustHalLoss(effect * BLOCKED_MULT(blocked)) //Changed this to use the wrapper function, it shouldn't directly alter the value
if(IRRADIATE)
var/rad_protection = blocked ? getarmor(null, "rad")/100 : 0
apply_radiation(max((1-rad_protection) * BLOCKED_MULT(blocked),0))//Rads auto check armor
if(STUTTER)
if(status_flags & CANSTUN) // stun is usually associated with stutter
stuttering = max(stuttering, effect * BLOCKED_MULT(blocked))
@@ -71,7 +78,6 @@
if(stun) apply_effect(stun, STUN, blocked)
if(weaken) apply_effect(weaken, WEAKEN, blocked)
if(paralyze) apply_effect(paralyze, PARALYZE, blocked)
if(irradiate) apply_effect(irradiate, IRRADIATE, blocked)
if(stutter) apply_effect(stutter, STUTTER, blocked)
if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked)
if(drowsy) apply_effect(drowsy, DROWSY, blocked)
+38 -77
View File
@@ -1,58 +1,23 @@
/mob/living/proc/modify_damage_by_armor(def_zone, damage, damage_type, damage_flags, mob/living/victim, armor_pen, silent = FALSE)
var/list/armors = get_armors_by_zone(def_zone, damage_type, damage_flags)
. = args.Copy(2)
for(var/armor in armors)
var/datum/component/armor/armor_datum = armor
. = armor_datum.apply_damage_modifications(arglist(.))
/*
run_armor_check() args
def_zone - What part is getting hit, if null will check entire body
attack_flag - The type of armor to be checked
armor_pen - reduces the effectiveness of armor
absorb_text - shown if the armor check is 100% successful
soften_text - shown if the armor check is more than 0% successful and less than 100%
Returns
a blocked amount between 0 - 100, representing the success of the armor check.
*/
#define MOB_FIRE_LIGHT_RANGE 3 //These control the intensity and range of light given off by a mob which is on fire
#define MOB_FIRE_LIGHT_POWER 2
/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/armor_pen = 0, var/absorb_text = null, var/soften_text = null)
if(armor_pen >= 100)
return 0 //might as well just skip the processing
var/armor = getarmor(def_zone, attack_flag)
if(armor_pen >= armor)
return 0 //effective_armor is going to be 0
var/blocked = (armor - armor_pen)
if(blocked >= 100)
if(absorb_text)
show_message("<span class='warning'>[absorb_text]</span>")
else
show_message("<span class='warning'>Your armor absorbs the blow!</span>")
return 100
if(blocked > 20)
//Should we show this every single time?
if(soften_text)
show_message("<span class='warning'>[soften_text]</span>")
else
show_message("<span class='warning'>Your armor softens the blow!</span>")
return round(blocked, 1)
//Adds two armor values together.
//If armor_a and armor_b are between 0-100 the result will always also be between 0-100.
/proc/add_armor(var/armor_a, var/armor_b)
if(armor_a >= 100 || armor_b >= 100)
return 100 //adding to infinite protection doesn't make it any bigger
var/protection_a = 1/(BLOCKED_MULT(armor_a)) - 1
var/protection_b = 1/(BLOCKED_MULT(armor_b)) - 1
return 100 - 1/(protection_a + protection_b + 1)*100
//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage)
/mob/living/proc/getarmor(var/def_zone, var/type)
return 0
/mob/living/proc/get_blocked_ratio(def_zone, damage_type, damage_flags, armor_pen, damage)
var/list/armors = get_armors_by_zone(def_zone, damage_type, damage_flags)
. = 0
for(var/armor in armors)
var/datum/component/armor/armor_datum = armor
. = 1 - (1 - .) * (1 - armor_datum.get_blocked(damage_type, damage_flags, armor_pen, damage)) // multiply the amount we let through
. = min(1, .)
/mob/living/proc/get_armors_by_zone(def_zone, damage_type, damage_flags)
. = list()
var/natural_armor = GetComponent(/datum/component/armor)
if(natural_armor)
. += natural_armor
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone, var/used_weapon = null)
@@ -80,19 +45,15 @@
return
//Armor
var/absorb = run_armor_check(def_zone, P.check_armor, P.armor_penetration)
var/damage = P.damage
var/flags = P.damage_flags()
var/damaged
if(prob(absorb))
if(P.damage_flags & DAM_SHARP || P.damage_flags & DAM_SHARP || P.damage_flags & DAM_LASER)
P.damage_flags &= ~DAM_SHARP
P.damage_flags &= ~DAM_EDGE
P.damage_flags &= ~DAM_LASER
if(!P.nodamage)
damaged = apply_damage(P.damage, P.damage_type, def_zone, absorb, 0, P, damage_flags = P.damage_flags, used_weapon = P)
bullet_impact_visuals(P, def_zone, damaged)
P.on_hit(src, absorb, def_zone)
return absorb
damaged = apply_damage(damage, P.damage_type, def_zone, damage_flags = P.damage_flags(), used_weapon = P, armor_pen = P.armor_penetration)
if(damaged || P.nodamage) // Run the block computation if we did damage or if we only use armor for effects (nodamage)
. = get_blocked_ratio(def_zone, P.damage_type, flags, P.armor_penetration, P.damage)
bullet_impact_visuals(P, def_zone, damage, .)
P.on_hit(src, ., def_zone)
/mob/living/proc/aura_check(var/type)
if(!auras)
@@ -117,7 +78,7 @@
break
//For visuals, blood splatters and so on.
/mob/living/proc/bullet_impact_visuals(var/obj/item/projectile/P, var/def_zone, var/damage)
/mob/living/proc/bullet_impact_visuals(var/obj/item/projectile/P, var/def_zone, var/damage, var/blocked_ratio)
var/list/impact_sounds = LAZYACCESS(P.impact_sounds, get_bullet_impact_effect_type(def_zone))
if(length(impact_sounds))
playsound(src, pick(impact_sounds), 75)
@@ -136,7 +97,7 @@
apply_effect(stun_amount, EYE_BLUR)
if(agony_amount)
apply_damage(agony_amount, PAIN, def_zone, 0, used_weapon)
apply_damage(agony_amount, PAIN, def_zone, 0, used_weapon = used_weapon)
apply_effect(agony_amount / 10, STUTTER)
apply_effect(agony_amount / 10, EYE_BLUR)
@@ -159,8 +120,7 @@
/mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone, var/ground_zero)
visible_message("<span class='danger'>[src] has been [LAZYPICK(I.attack_verb,"attacked")] with [I] by [user]!</span>")
var/blocked = run_armor_check(hit_zone, "melee")
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
. = standard_weapon_hit_effects(I, user, effective_force, hit_zone)
if(I.damtype == BRUTE && prob(33) && I.force) // Added blood for whacking non-humans too
var/turf/simulated/location = get_turf(src)
@@ -169,9 +129,9 @@
return blocked
//returns 0 if the effects failed to apply for some reason, 1 otherwise.
/mob/living/proc/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
/mob/living/proc/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
if(!effective_force || blocked >= 100)
return 0
return FALSE
//Hulk modifier
if(HULK in user.mutations)
@@ -185,13 +145,13 @@
apply_damage(effective_force, I.damtype, hit_zone, blocked, used_weapon=I, damage_flags = damage_flags)
return 1
return TRUE
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM, var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
if(!aura_check(AURA_TYPE_THROWN, AM, speed))
return
if(istype(AM,/obj/))
if(isobj(AM))
var/obj/O = AM
var/dtype = O.damtype
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
@@ -207,10 +167,7 @@
return
src.visible_message("<span class='warning'>[src] has been hit by [O].</span>")
var/armor = run_armor_check(null, "melee")
var/damage_flags = O.damage_flags()
apply_damage(throw_damage, dtype, null, armor, O, damage_flags = damage_flags)
apply_damage(throw_damage, dtype, null, damage_flags = O.damage_flags(), used_weapon = O)
O.throwing = 0 //it hit, so stop moving
@@ -236,7 +193,8 @@
visible_message("<span class='warning'>[src] staggers under the impact!</span>","<span class='warning'>You stagger under the impact!</span>")
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
if(!O || !src) return
if(!O || !src)
return
if(O.sharp) //Projectile is suitable for pinning.
//Handles embedding for non-humans and simple_animals.
@@ -301,6 +259,9 @@
return FALSE
#define MOB_FIRE_LIGHT_RANGE 3 //These control the intensity and range of light given off by a mob which is on fire
#define MOB_FIRE_LIGHT_POWER 2
/mob/living/proc/set_on_fire()
to_chat(src, SPAN_DANGER(FONT_LARGE("You're set on fire!")))
on_fire = TRUE
@@ -17,8 +17,4 @@
M.apply_effect(5, STUTTER)
M.stun_effect_act(0, 70, check_zone(hit_zone), src)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.forcesay(hit_appends)
return FALSE
+2 -10
View File
@@ -282,22 +282,14 @@
if(1.0)
brute = 400
burn = 100
if(!anchored && !prob(getarmor(null, "bomb")))
gib()
if(2.0)
brute = 60
burn = 60
if(3.0)
brute = 30
var/protection = BLOCKED_MULT(getarmor(null, "bomb"))
brute *= protection
burn *= protection
adjustBruteLoss(brute)
adjustFireLoss(burn)
updatehealth()
apply_damage(brute, BRUTE, damage_flags = DAM_EXPLODE)
apply_damage(burn, BURN, damage_flags = DAM_EXPLODE)
/mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised)
if(!next_alarm_notice)
@@ -41,7 +41,7 @@
/mob/living/simple_animal/hostile/commanded/bear/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
. = ..()
if(!.)
if(.)
src.emote("roars in rage!")
/mob/living/simple_animal/hostile/commanded/bear/attack_hand(mob/living/carbon/human/M as mob)
@@ -206,7 +206,7 @@
target_mob = null
audible_emote("[pick(sad_emote)].",0)
return
if(!. && retribution)
if(. && retribution)
stance = HOSTILE_STANCE_ATTACK
target_mob = user
allowed_targets += user //fuck this guy in particular.
@@ -485,7 +485,7 @@
var/mob/living/carbon/human/H = parrot_interest
var/obj/item/organ/external/affecting = H.get_organ(ran_zone(pick(parrot_dam_zone)))
H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee"), damage_flags = DAM_SHARP)
H.apply_damage(damage, BRUTE, affecting, damage_flags = DAM_SHARP)
visible_emote(pick("pecks [H]'s [affecting].", "cuts [H]'s [affecting] with its talons."))
else
@@ -99,7 +99,7 @@
var/datum/weakref/original_body
var/datum/weakref/possessed_body
/mob/living/simple_animal/shade/bluespace/apply_damage(var/damage, var/damagetype, var/def_zone, var/blocked, var/used_weapon, var/damage_flags)
/mob/living/simple_animal/shade/bluespace/apply_damage(var/damage, var/damagetype, var/def_zone, var/blocked, var/used_weapon, var/damage_flags, var/armor_pen, var/silent = FALSE)
return 0
/mob/living/simple_animal/shade/bluespace/adjustBruteLoss()
@@ -549,7 +549,7 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
user.do_attack_animation(src)
return TRUE
/mob/living/simple_animal/apply_damage(damage, damagetype, def_zone, blocked, used_weapon, damage_flags)
/mob/living/simple_animal/apply_damage(damage, damagetype, def_zone, blocked, used_weapon, damage_flags, armor_pen, silent = FALSE)
. = ..()
handle_blood_overlay()
@@ -614,8 +614,6 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
switch (severity)
if (1.0)
damage = 500
if(!prob(getarmor(null, "bomb")))
gib()
if (2.0)
damage = 120
@@ -623,7 +621,7 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
if(3.0)
damage = 30
adjustBruteLoss(damage * BLOCKED_MULT(getarmor(null, "bomb")))
apply_damage(damage, BRUTE, damage_flags = DAM_EXPLODE)
/mob/living/simple_animal/proc/SA_attackable(target_mob)
if (isliving(target_mob))
+1 -1
View File
@@ -371,7 +371,7 @@
if(hit_zone == BP_EYES)
attack_eye(affecting, assailant)
else if(hit_zone == BP_HEAD)
headbut(affecting, assailant)
headbutt(affecting, assailant)
else
dislocate(affecting, assailant, hit_zone)
+5 -6
View File
@@ -55,8 +55,8 @@
return
attacker.visible_message("<span class='danger'>[attacker] [pick("bent", "twisted")] [target]'s [organ.name] into a jointlock!</span>")
var/armor = target.run_armor_check(target, "melee")
if(armor < 100)
var/armor = 100 * target.get_blocked_ratio(target, BRUTE, damage = 30)
if(armor < 70)
to_chat(target, "<span class='danger'>You feel extreme pain!</span>")
affecting.adjustHalLoss(Clamp(0, 60-affecting.getHalLoss(), 30)) //up to 60 halloss
@@ -86,7 +86,7 @@
attack.handle_eye_attack(attacker, target)
/obj/item/grab/proc/headbut(mob/living/carbon/human/target, mob/living/carbon/human/attacker)
/obj/item/grab/proc/headbutt(mob/living/carbon/human/target, mob/living/carbon/human/attacker)
if(!istype(attacker))
return
if(target.lying)
@@ -104,9 +104,8 @@
if(istype(hat))
damage += hat.force * 3
var/armor = target.run_armor_check(BP_HEAD, "melee")
target.apply_damage(damage, BRUTE, BP_HEAD, armor)
attacker.apply_damage(10, BRUTE, BP_HEAD, attacker.run_armor_check(BP_HEAD, "melee"))
target.apply_damage(damage, BRUTE, BP_HEAD)
attacker.apply_damage(10, BRUTE, BP_HEAD)
if(armor < 25 && target.headcheck(BP_HEAD) && prob(damage))
target.apply_effect(20, PARALYZE)