diff --git a/code/datums/martial.dm b/code/datums/martial.dm index 32cff9c168c..71dca89f54f 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -482,6 +482,7 @@ attack_verb = list("smashed", "slammed", "whacked", "thwacked") icon = 'icons/obj/weapons.dmi' icon_state = "bostaff0" + block_chance = 50 /obj/item/weapon/twohanded/bostaff/update_icon() icon_state = "bostaff[wielded]" @@ -539,8 +540,7 @@ return ..() return ..() -/obj/item/weapon/twohanded/bostaff/IsShield() +/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) if(wielded) - return 1 - else - return 0 + return ..() + return 0 diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 97dfc82ffd8..372262aeb30 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -286,12 +286,12 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine containername = "tactical armor crate" /datum/supply_packs/security/armory/laserarmor - name = "Ablative Armor Crate" + name = "Reflector Vest Crate" contains = list(/obj/item/clothing/suit/armor/laserproof, /obj/item/clothing/suit/armor/laserproof) // Only two vests to keep costs down for balance cost = 20 containertype = /obj/structure/closet/crate/secure/plasma - containername = "ablative armor crate" + containername = "reflector vest crate" /////// Weapons: Specialist diff --git a/code/game/gamemodes/abduction/abduction_gear.dm b/code/game/gamemodes/abduction/abduction_gear.dm index 75f2066ba27..a14280395e6 100644 --- a/code/game/gamemodes/abduction/abduction_gear.dm +++ b/code/game/gamemodes/abduction/abduction_gear.dm @@ -77,9 +77,10 @@ M.regenerate_icons() return -/obj/item/clothing/suit/armor/abductor/vest/IsShield() +/obj/item/clothing/suit/armor/abductor/vest/hit_reaction() DeactivateStealth() return 0 + /obj/item/clothing/suit/armor/abductor/vest/IsReflect() DeactivateStealth() return 0 diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index 59f08343ef0..4640b1fe26c 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -227,6 +227,7 @@ flags = ABSTRACT | NODROP icon = 'icons/obj/weapons.dmi' icon_state = "ling_shield" + block_chance = 50 var/remaining_uses //Set by the changeling ability. @@ -238,7 +239,7 @@ /obj/item/clothing/head/helmet/space/changeling/dropped() qdel(src) -/obj/item/weapon/shield/changeling/IsShield() +/obj/item/weapon/shield/changeling/hit_reaction() if(remaining_uses < 1) if(ishuman(loc)) var/mob/living/carbon/human/H = loc @@ -248,7 +249,7 @@ return 0 else remaining_uses-- - return 1 + return ..() /***************************************\ diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 8294e1831eb..9f1c99cea84 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -59,8 +59,8 @@ difficulty = 5 excludefromjob = list("Captain") -/datum/objective_item/steal/ablative - name = "an ablative armor vest" +/datum/objective_item/steal/reflector + name = "a reflector vest" targetitem = /obj/item/clothing/suit/armor/laserproof difficulty = 3 excludefromjob = list("Head of Security", "Warden") diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index bfbd12f0b99..a033392c4fc 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -99,13 +99,15 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s var/sharpness = IS_BLUNT var/toolspeed = 1 + var/block_chance = 0 + var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom + /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside)) || is_type_in_list(target, can_be_placed_into)) return 0 else return 1 - /obj/item/device icon = 'icons/obj/device.dmi' @@ -315,6 +317,12 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s // afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency +/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0) + if(prob(final_block_chance)) + owner.visible_message("[owner] blocks [attack_text] with [src]!") + return 1 + return 0 + /obj/item/proc/talk_into(mob/M, input, channel, spans) return @@ -372,9 +380,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s /obj/item/proc/ui_action_click() attack_self(usr) -/obj/item/proc/IsShield() - return 0 - /obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit return 0 diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index b5042a9f868..4552aff3498 100755 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -288,7 +288,7 @@ origin_tech = null attack_verb = list("attacked", "struck", "hit") -/obj/item/weapon/twohanded/dualsaber/toy/IsShield() +/obj/item/weapon/twohanded/dualsaber/toy/hit_reaction() return 0 /obj/item/weapon/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 4a79da30820..f3ce9565824 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -55,15 +55,16 @@ embedded_impact_pain_multiplier = 10 flags = NOSHIELD origin_tech = "magnets=3;syndicate=4" + block_chance = 50 var/hacked = 0 /obj/item/weapon/melee/energy/sword/New() if(item_color == null) item_color = pick("red", "blue", "green", "purple") -/obj/item/weapon/melee/energy/sword/IsShield() +/obj/item/weapon/melee/energy/sword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) if(active) - return 1 + return ..() return 0 /obj/item/weapon/melee/energy/attack_self(mob/living/carbon/user) @@ -136,7 +137,7 @@ icon_state = "esaw_0" item_color = null -/obj/item/weapon/melee/energy/sword/cyborg/saw/IsShield() +/obj/item/weapon/melee/energy/sword/cyborg/saw/hit_reaction() return 0 /obj/item/weapon/melee/energy/sword/saber diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index e1ce991115a..08bd5d773f1 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -1,5 +1,6 @@ /obj/item/weapon/shield name = "shield" + block_chance = 50 /obj/item/weapon/shield/riot name = "riot shield" @@ -17,8 +18,6 @@ attack_verb = list("shoved", "bashed") var/cooldown = 0 //shield bash cooldown. based on world.time -/obj/item/weapon/shield/riot/IsShield() - return 1 /obj/item/weapon/shield/riot/attackby(obj/item/weapon/W, mob/user, params) if(istype(W, /obj/item/weapon/melee/baton)) @@ -49,8 +48,10 @@ attack_verb = list("shoved", "bashed") var/active = 0 -/obj/item/weapon/shield/energy/IsShield() - return (active) +/obj/item/weapon/shield/energy/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) + if(active) + return ..() + return 0 /obj/item/weapon/shield/energy/IsReflect() return (active) @@ -91,8 +92,10 @@ w_class = 3 var/active = 0 -/obj/item/weapon/shield/riot/tele/IsShield() - return (active) +/obj/item/weapon/shield/riot/tele/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) + if(active) + return ..() + return 0 /obj/item/weapon/shield/riot/tele/attack_self(mob/living/user) active = !active diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index b685d8da477..650e78dac30 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -115,13 +115,16 @@ /obj/item/weapon/twohanded/offhand/wield() qdel(src) -/obj/item/weapon/twohanded/offhand/IsShield()//if the actual twohanded weapon is a shield, we count as a shield too! +/obj/item/weapon/twohanded/offhand/hit_reaction()//if the actual twohanded weapon is a shield, we count as a shield too! var/mob/user = loc - if(!istype(user)) return 0 + if(!istype(user)) + return 0 var/obj/item/I = user.get_active_hand() - if(I == src) I = user.get_inactive_hand() - if(!I) return 0 - return I.IsShield() + if(I == src) + I = user.get_inactive_hand() + if(!I) + return 0 + return I.hit_reaction() ///////////Two hand required objects/////////////// //This is for objects that require two hands to even pick up @@ -209,6 +212,7 @@ origin_tech = "magnets=3;syndicate=4" item_color = "green" attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 var/hacked = 0 /obj/item/weapon/twohanded/dualsaber/New() @@ -240,11 +244,10 @@ else user.adjustStaminaLoss(25) -/obj/item/weapon/twohanded/dualsaber/IsShield() +/obj/item/weapon/twohanded/dualsaber/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) if(wielded) - return 1 - else - return 0 + return ..() + return 0 /obj/item/weapon/twohanded/dualsaber/attack_hulk(mob/living/carbon/human/user) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up if(wielded) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 7b30c4a03e0..667fc9e1b16 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -64,9 +64,7 @@ throwforce = 10 w_class = 3 attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/weapon/claymore/IsShield() - return 1 + block_chance = 50 /obj/item/weapon/claymore/suicide_act(mob/user) user.visible_message("[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.") @@ -84,6 +82,7 @@ w_class = 3 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 /obj/item/weapon/katana/cursed slot_flags = null @@ -92,9 +91,6 @@ user.visible_message("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") return(BRUTELOSS) -/obj/item/weapon/katana/IsShield() - return 1 - /obj/item/weapon/wirerod name = "wired rod" desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 00c9497c731..3504afd1c98 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -220,8 +220,6 @@ BLIND // can't see anything if(blood_DNA) . += image("icon"='icons/effects/blood.dmi', "icon_state"="[blood_overlay_type]blood") - - //Spacesuit //Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together. // Meaning the the suit is defined directly after the corrisponding helmet. Just like below! diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 4bda702b96b..b2219ef32e9 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -134,11 +134,8 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) action_button_name = "Toggle Armor" unacidable = 1 + hit_reaction_chance = 50 -/obj/item/clothing/suit/armor/reactive/IsShield() - if(active) - return 1 - return 0 /obj/item/clothing/suit/armor/reactive/attack_self(mob/user) src.active = !( src.active ) @@ -159,6 +156,46 @@ src.item_state = "reactiveoff" ..() +/obj/item/clothing/suit/armor/reactive/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) + if(!active) + return 0 + if(prob(hit_reaction_chance)) + var/mob/living/carbon/human/H = owner + owner.visible_message("The reactive teleport system flings [H] clear of [attack_text]!") + var/list/turfs = new/list() + for(var/turf/T in orange(6, H)) + if(T.density) + continue + if(T.x>world.maxx-6 || T.x<6) + continue + if(T.y>world.maxy-6 || T.y<6) + continue + turfs += T + if(!turfs.len) + turfs += pick(/turf in orange(6, src)) + var/turf/picked = pick(turfs) + if(!isturf(picked)) + return + if(H.buckled) + H.buckled.unbuckle_mob() + H.forceMove(picked) + return 1 + return 0 + +/obj/item/clothing/suit/armor/reactive/fire + name = "reactive incendiary armor" + + +/obj/item/clothing/suit/armor/reactive/fire/hit_reaction(mob/living/carbon/human/owner, attack_text) + if(prob(hit_reaction_chance)) + owner.visible_message("The [src] blocks the [attack_text], sending out jets of flame!") + for(var/mob/living/carbon/C in range(6, owner)) + if(C != owner) + C.fire_stacks += 8 + C.IgniteMob() + owner.fire_stacks = -20 + return 1 + return 0 //All of the armor below is mostly unused diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 5a66c2d61a0..25a2027e4c7 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -59,6 +59,9 @@ fitted = FEMALE_UNIFORM_TOP can_adjust = 0 +/obj/item/clothing/under/rank/clown/hit_reaction() + playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1) + return 0 /obj/item/clothing/under/rank/head_of_personnel desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"." diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index a2839eeb6ec..2c344adf61f 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -31,9 +31,9 @@ New() item_color = "red" -/obj/item/weapon/holo/esword/IsShield() +/obj/item/weapon/holo/esword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) if(active) - return 1 + return ..() return 0 /obj/item/weapon/holo/esword/attack(target as mob, mob/user as mob) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index e5e66dd7e27..d5a265800e6 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -82,41 +82,25 @@ emp_act //End Here /mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, thrown_proj = 0, armour_penetration = 0) - var/block_chance = 50 + 30*thrown_proj - round(damage / 3) //thrown things are easier to block + var/block_chance_modifier = 30*thrown_proj - round(damage / 3) //thrown things are easier to block if(AM) if(AM.flags & NOSHIELD) //weapon ignores shields altogether return 0 - var/blocker - if(l_hand) - if(l_hand.IsShield()) - block_chance -= Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100) //So armour piercing blades can still be parried by other blades, for example - if(prob(block_chance)) - blocker = l_hand - if(r_hand) - if(r_hand.IsShield()) - block_chance -= Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100) - if(prob(block_chance)) - blocker = r_hand - if(blocker) - visible_message("[src] blocks [attack_text] with [blocker]!", \ - "[src] blocks [attack_text] with [blocker]!") - return 1 + if(l_hand && !istype(l_hand, /obj/item/clothing)) + var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example + if(l_hand.hit_reaction(src, attack_text, final_block_chance)) + return 1 + if(r_hand && !istype(r_hand, /obj/item/clothing)) + var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts + if(r_hand.hit_reaction(src, attack_text, final_block_chance)) + return 1 if(wear_suit) - if(wear_suit.IsShield() && (prob(50))) - visible_message("The reactive teleport system flings [src] clear of [attack_text]!", \ - "The reactive teleport system flings [src] clear of [attack_text]!") - var/list/turfs = new/list() - for(var/turf/T in orange(6, src)) - if(T.density) continue - if(T.x>world.maxx-6 || T.x<6) continue - if(T.y>world.maxy-6 || T.y<6) continue - turfs += T - if(!turfs.len) turfs += pick(/turf in orange(6, src)) - var/turf/picked = pick(turfs) - if(!isturf(picked)) return - if(buckled) - buckled.unbuckle_mob() - forceMove(picked) + var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier + if(wear_suit.hit_reaction(src, attack_text, final_block_chance)) + return 1 + if(w_uniform) + var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier + if(w_uniform.hit_reaction(src, attack_text, final_block_chance)) return 1 return 0 diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index c1a304e6b72..98d72daabdd 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -884,7 +884,7 @@ /datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H) if(!istype(M)) //sanity check for drones. return - if((M != H) && H.check_shields(0, M.name)) + if((M != H) && M.a_intent != "help" && H.check_shields(0, M.name)) add_logs(M, H, "attempted to touch") H.visible_message("[M] attempted to touch [H]!") return 0 @@ -1005,8 +1005,8 @@ // Allows you to put in item-specific reactions based on species if(user != H) user.do_attack_animation(H) - if(H.check_shields(I.force, "the [I.name]", I, 0, I.armour_penetration)) - return 0 + if(H.check_shields(I.force, "the [I.name]", I, 0, I.armour_penetration)) + return 0 if(I.attack_verb && I.attack_verb.len) H.visible_message("[user] has [pick(I.attack_verb)] [H] in the [hit_area] with [I]!", \