diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 1171bd7bf79..bfc05a5d88f 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -2,6 +2,10 @@ name = "shield" block_chance = 50 armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) + var/transparent = FALSE // makes beam projectiles pass through the shield + +/obj/item/shield/proc/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK) + return TRUE /obj/item/shield/riot name = "riot shield" @@ -19,7 +23,17 @@ materials = list(MAT_GLASS=7500, MAT_METAL=1000) attack_verb = list("shoved", "bashed") var/cooldown = 0 //shield bash cooldown. based on world.time + transparent = TRUE + max_integrity = 75 +/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(transparent && (hitby.pass_flags & PASSGLASS)) + return FALSE + if(attack_type == THROWN_PROJECTILE_ATTACK) + final_block_chance += 30 + if(attack_type == LEAP_ATTACK) + final_block_chance = 100 + return ..() /obj/item/shield/riot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/melee/baton)) @@ -27,14 +41,40 @@ user.visible_message("[user] bashes [src] with [W]!") playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) cooldown = world.time + else if(istype(W, /obj/item/stack/sheet/mineral/titanium)) + if (obj_integrity >= max_integrity) + to_chat(user, "[src] is already in perfect condition.") + else + var/obj/item/stack/sheet/mineral/titanium/T = W + T.use(1) + obj_integrity = max_integrity + to_chat(user, "You repair [src] with [T].") else return ..() -/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == THROWN_PROJECTILE_ATTACK) - final_block_chance += 30 - if(attack_type == LEAP_ATTACK) - final_block_chance = 100 +/obj/item/shield/riot/examine(mob/user) + ..() + var/healthpercent = round((obj_integrity/max_integrity) * 100, 1) + switch(healthpercent) + if(50 to 99) + to_chat(user, "It looks slightly damaged.") + if(25 to 50) + to_chat(user, "It appears heavily damaged.") + if(0 to 25) + to_chat(user, "It's falling apart!") + +/obj/item/shield/riot/proc/shatter(mob/living/carbon/human/owner) + playsound(owner, 'sound/effects/glassbr3.ogg', 100) + new /obj/item/shard((get_turf(src))) + +/obj/item/shield/riot/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK) + if (obj_integrity <= damage) + var/turf/T = get_turf(owner) + T.visible_message("[hitby] destroys [src]!") + shatter(owner) + qdel(src) + return FALSE + take_damage(damage) return ..() /obj/item/shield/riot/roman @@ -44,11 +84,19 @@ item_state = "roman_shield" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' + transparent = FALSE + materials = list(MAT_METAL=8500) + max_integrity = 65 /obj/item/shield/riot/roman/fake desc = "Bears an inscription on the inside: \"Romanes venio domus\". It appears to be a bit flimsy." block_chance = 0 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + max_integrity = 30 + +/obj/item/shield/riot/roman/shatter(mob/living/carbon/human/owner) + playsound(owner, 'sound/effects/grillehit.ogg', 100) + new /obj/item/stack/sheet/metal(get_turf(src)) /obj/item/shield/riot/buckler name = "wooden buckler" @@ -60,6 +108,74 @@ materials = list() resistance_flags = FLAMMABLE block_chance = 30 + transparent = FALSE + max_integrity = 65 + +/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner) + playsound(owner, 'sound/effects/bang.ogg', 50) + new /obj/item/stack/sheet/mineral/wood(get_turf(src)) + +/obj/item/shield/riot/flash + name = "strobe shield" + desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs." + icon_state = "flashshield" + item_state = "flashshield" + var/obj/item/assembly/flash/handheld/embedded_flash + +/obj/item/shield/riot/flash/Initialize() + . = ..() + embedded_flash = new(src) + +/obj/item/shield/riot/flash/attack(mob/living/M, mob/user) + . = embedded_flash.attack(M, user) + update_icon() + +/obj/item/shield/riot/flash/attack_self(mob/living/carbon/user) + . = embedded_flash.attack_self(user) + update_icon() + +/obj/item/shield/riot/flash/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + . = ..() + if (. && !embedded_flash.crit_fail) + embedded_flash.activate() + update_icon() + + +/obj/item/shield/riot/flash/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/assembly/flash/handheld)) + var/obj/item/assembly/flash/handheld/flash = W + if(flash.crit_fail) + to_chat(user, "No sense replacing it with a broken bulb.") + return + else + to_chat(user, "You begin to replace the bulb.") + if(do_after(user, 20, target = user)) + if(flash.crit_fail || !flash || QDELETED(flash)) + return + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) + qdel(embedded_flash) + embedded_flash = flash + flash.forceMove(src) + update_icon() + return + ..() + +/obj/item/shield/riot/flash/emp_act(severity) + . = ..() + embedded_flash.emp_act(severity) + update_icon() + +/obj/item/shield/riot/flash/update_icon() + if(!embedded_flash || embedded_flash.crit_fail) + icon_state = "riot" + item_state = "riot" + else + icon_state = "flashshield" + item_state = "flashshield" + +/obj/item/shield/riot/flash/examine(mob/user) + ..() + to_chat(user, "The mounted bulb has burnt out. You can try replacing it with a new one.") /obj/item/shield/energy name = "energy combat shield" diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index 8ec25ab5c91..ff2874715ea 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -249,79 +249,15 @@ /obj/item/assembly/flash/armimplant/proc/cooldown() overheat = FALSE -/obj/item/assembly/flash/shield - name = "strobe shield" - desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "flashshield" - item_state = "flashshield" - lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' - slot_flags = ITEM_SLOT_BACK - force = 10 - throwforce = 5 - throw_speed = 2 - throw_range = 3 - w_class = WEIGHT_CLASS_BULKY - materials = list(MAT_GLASS=7500, MAT_METAL=1000) - attack_verb = list("shoved", "bashed") - block_chance = 50 - armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) - -/obj/item/assembly/flash/shield/flash_recharge(interval=10) - if(times_used >= 4) - burn_out() - return FALSE - return TRUE - -/obj/item/assembly/flash/shield/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/assembly/flash/handheld)) - var/obj/item/assembly/flash/handheld/flash = W - if(flash.crit_fail) - to_chat(user, "No sense replacing it with a broken bulb.") - return - else - to_chat(user, "You begin to replace the bulb.") - if(do_after(user, 20, target = src)) - if(flash.crit_fail || !flash || QDELETED(flash)) - return - crit_fail = FALSE - times_used = 0 - playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) - update_icon() - flash.crit_fail = TRUE - flash.update_icon() - return - ..() - -/obj/item/assembly/flash/shield/update_icon(flash = FALSE) - icon_state = "flashshield" - item_state = "flashshield" - - if(crit_fail) - icon_state = "riot" - item_state = "riot" - else if(flash) - icon_state = "flashshield_flash" - item_state = "flashshield_flash" - addtimer(CALLBACK(src, .proc/update_icon), 5) - - if(holder) - holder.update_icon() - -/obj/item/assembly/flash/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - activate() - return ..() - /obj/item/assembly/flash/hypnotic desc = "A modified flash device, programmed to emit a sequence of subliminal flashes that can send a vulnerable target into a hypnotic trance." flashing_overlay = "flash-hypno" light_color = LIGHT_COLOR_PINK cooldown = 20 - + /obj/item/assembly/flash/hypnotic/burn_out() return - + /obj/item/assembly/flash/hypnotic/flash_carbon(mob/living/carbon/M, mob/user, power = 15, targeted = TRUE, generic_message = FALSE) if(!istype(M)) return @@ -337,25 +273,25 @@ if(M.hypnosis_vulnerable()) hypnosis = TRUE if(user) - user.visible_message("[user] blinds [M] with the flash!", "You hypno-flash [M]!") - + user.visible_message("[user] blinds [M] with the flash!", "You hypno-flash [M]!") + if(!hypnosis) to_chat(M, "The light makes you feel oddly relaxed...") M.confused += min(M.confused + 10, 20) M.dizziness += min(M.dizziness + 10, 20) M.drowsyness += min(M.drowsyness + 10, 20) - M.apply_status_effect(STATUS_EFFECT_PACIFY, 100) + M.apply_status_effect(STATUS_EFFECT_PACIFY, 100) else - M.apply_status_effect(/datum/status_effect/trance, 200, TRUE) - + M.apply_status_effect(/datum/status_effect/trance, 200, TRUE) + else if(user) user.visible_message("[user] fails to blind [M] with the flash!", "You fail to hypno-flash [M]!") else to_chat(M, "[src] fails to blind you!") - + else if(M.flash_act()) to_chat(M, "Such a pretty light...") M.confused += min(M.confused + 4, 20) M.dizziness += min(M.dizziness + 4, 20) M.drowsyness += min(M.drowsyness + 4, 20) - M.apply_status_effect(STATUS_EFFECT_PACIFY, 40) \ No newline at end of file + M.apply_status_effect(STATUS_EFFECT_PACIFY, 40) diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index 948b3cafd21..6e56e7d6029 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -47,7 +47,7 @@ /datum/crafting_recipe/strobeshield name = "Strobe Shield" - result = /obj/item/assembly/flash/shield + result = /obj/item/shield/riot/flash reqs = list(/obj/item/wallframe/flasher = 1, /obj/item/assembly/flash/handheld = 1, /obj/item/shield/riot = 1) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index af8e9cf7dbc..df48f153570 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -105,6 +105,9 @@ if(!istype(I, /obj/item/clothing)) var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) + if (istype(I, /obj/item/shield)) + var/obj/item/shield/S = I + return S.on_shield_block(src, AM, attack_text, damage, attack_type) return 1 if(wear_suit) var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier