From fb6b94de8773e6855b362faf84ef8e0f427e608f Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 13 Jul 2015 01:33:50 -0400 Subject: [PATCH] Incorporates laser reflection into the shield system --- code/game/objects/items.dm | 7 ++- .../objects/items/weapons/material/swords.dm | 2 +- .../items/weapons/material/twohanded.dm | 2 +- .../objects/items/weapons/melee/energy.dm | 2 +- code/game/objects/items/weapons/shields.dm | 2 +- code/modules/clothing/suits/armor.dm | 24 +++++++++- code/modules/holodeck/HolodeckObjects.dm | 2 +- .../living/carbon/human/human_attackhand.dm | 2 +- .../mob/living/carbon/human/human_defense.dm | 45 +++++++------------ 9 files changed, 50 insertions(+), 38 deletions(-) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index b1e131dd87..ff7cecf169 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -409,7 +409,12 @@ var/list/global/slot_flags_enumeration = list( /obj/item/proc/ui_action_click() attack_self(usr) -/obj/item/proc/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +//RETURN VALUES +//handle_shield should return a positive value to indicate that the attack is blocked and should be prevented. +//If a negative value is returned, it should be treated as a special return value for bullet_act() and handled appropriately. +//For non-projectile attacks this usually means the attack is blocked. +//Otherwise should return 0 to indicate that the attack is not affected in any way. +/obj/item/proc/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") return 0 /obj/item/proc/get_loc_turf() diff --git a/code/game/objects/items/weapons/material/swords.dm b/code/game/objects/items/weapons/material/swords.dm index a907e2abdf..38ef718c8d 100644 --- a/code/game/objects/items/weapons/material/swords.dm +++ b/code/game/objects/items/weapons/material/swords.dm @@ -11,7 +11,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") hitsound = 'sound/weapons/bladeslice.ogg' -/obj/item/weapon/material/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +/obj/item/weapon/material/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") //parry only melee attacks if(istype(damage_source, /obj/item/projectile) || (attacker && get_dist(user, attacker) > 1)) diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm index e944ab743a..d11f798b8e 100644 --- a/code/game/objects/items/weapons/material/twohanded.dm +++ b/code/game/objects/items/weapons/material/twohanded.dm @@ -72,7 +72,7 @@ return unwield() //Allow a small chance of parrying melee attacks when wielded - maybe generalize this to other weapons someday -/obj/item/weapon/material/twohanded/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +/obj/item/weapon/material/twohanded/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") if(!wielded) return 0 diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index d1dee719e1..0936a1ad00 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -151,7 +151,7 @@ attack_verb = list() icon_state = initial(icon_state) -/obj/item/weapon/melee/energy/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +/obj/item/weapon/melee/energy/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") if(!active) return 0 diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 15a1eaf96b..d0e990b6de 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -2,7 +2,7 @@ name = "shield" var/base_block_chance = 50 -/obj/item/weapon/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +/obj/item/weapon/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") //block as long as they are not directly behind us var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block if(check_shield_arc(user, bad_arc, damage_source, attacker)) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 7a9d6f3f20..300422bc73 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -63,6 +63,26 @@ armor = list(melee = 10, bullet = 10, laser = 80, energy = 50, bomb = 0, bio = 0, rad = 0) siemens_coefficient = 0 +/obj/item/clothing/suit/armor/laserproof/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") + if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam)) + var/obj/item/projectile/P = damage_source + + var/reflectchance = 40 - round(damage/3) + if(!(def_zone in list("chest", "groin"))) + reflectchance /= 2 + if(P.starting && prob(reflectchance)) + visible_message("\The [user]'s [src.name] reflects [attack_text]!") + + // Find a turf near or on the original location to bounce to + var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/turf/curloc = get_turf(user) + + // redirect the projectile + P.redirect(new_x, new_y, curloc, user) + + return PROJECTILE_CONTINUE // complete projectile permutation + /obj/item/clothing/suit/armor/swat name = "swat suit" desc = "A heavily armored suit that protects against moderate damage. Used in special operations." @@ -113,7 +133,7 @@ slowdown = 1 armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) -/obj/item/clothing/suit/armor/reactive/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +/obj/item/clothing/suit/armor/reactive/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") if(prob(50)) user.visible_message("The reactive teleport system flings [user] clear of the attack!") var/list/turfs = new/list() @@ -133,7 +153,7 @@ playsound(user.loc, "sparks", 50, 1) user.loc = picked - return 1 + return PROJECTILE_FORCE_MISS return 0 /obj/item/clothing/suit/armor/reactive/attack_self(mob/user as mob) diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm index fbd998fc52..fbd3f7b41c 100644 --- a/code/modules/holodeck/HolodeckObjects.dm +++ b/code/modules/holodeck/HolodeckObjects.dm @@ -252,7 +252,7 @@ New() item_color = "red" -/obj/item/weapon/holo/esword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/attack_text = "the attack") +/obj/item/weapon/holo/esword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") if(!active) return 0 diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index e15f9a554d..68680a432c 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -19,7 +19,7 @@ // Should this all be in Touch()? if(istype(H)) - if(H != src && check_shields(0, null, H, H.name)) + if(H != src && check_shields(0, null, H, H.zone_sel.selecting, H.name)) H.do_attack_animation(src) return 0 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index b66a610368..284515a222 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -16,30 +16,14 @@ emp_act var/obj/item/organ/external/organ = get_organ() - //Shields - if(check_shields(P.damage, P, null, "the [P.name]")) - P.on_hit(src, 2, def_zone) - return 2 - - //Laserproof armour - if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/armor/laserproof)) - if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) - var/reflectchance = 40 - round(P.damage/3) - if(!(def_zone in list("chest", "groin"))) - reflectchance /= 2 - if(prob(reflectchance)) - visible_message("\red \The [P] gets reflected by \the [src]'s [wear_suit.name]!") - - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.redirect(new_x, new_y, curloc, src) - - return PROJECTILE_CONTINUE // complete projectile permutation + //Shields + var/shield_check = check_shields(P.damage, P, null, def_zone, "the [P.name]") + if(shield_check) + if(shield_check < 0) + return shield_check + else + P.on_hit(src, 2, def_zone) + return 2 //Shrapnel if(P.can_embed()) @@ -148,10 +132,13 @@ emp_act return gear return null -/mob/living/carbon/human/proc/check_shields(var/damage = 0, var/atom/damage_source = null, var/mob/attacker = null, var/attack_text = "the attack") +/mob/living/carbon/human/proc/check_shields(var/damage = 0, var/atom/damage_source = null, var/mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") for(var/obj/item/shield in list(l_hand, r_hand, wear_suit)) - if(shield && shield.handle_shield(src, damage, damage_source, attacker, attack_text)) - return 1 + if(!shield) + continue + var/result = shield.handle_shield(src, damage, damage_source, attacker, def_zone, attack_text) + if(result) + return result return 0 /mob/living/carbon/human/emp_act(severity) @@ -183,7 +170,7 @@ emp_act if(user.a_intent == "disarm") effective_force = round(I.force/2) var/hit_area = affecting.name - if((user != src) && check_shields(effective_force, I, user, "the [I.name]")) + if((user != src) && check_shields(effective_force, I, user, target_zone, "the [I.name]")) return 0 if(istype(I,/obj/item/weapon/card/emag)) @@ -312,7 +299,7 @@ emp_act O.throwing = 0 //it hit, so stop moving - if ((O.thrower != src) && check_shields(throw_damage, O, thrower, "[O]")) + if ((O.thrower != src) && check_shields(throw_damage, O, thrower, zone, "[O]")) return var/obj/item/organ/external/affecting = get_organ(zone)