/obj/item/shield name = "shield" icon = 'icons/obj/items_and_weapons.dmi' block_chance = 50 armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) /// Shield flags var/shield_flags = SHIELD_FLAGS_DEFAULT /// Last shieldbash world.time var/last_shieldbash = 0 /// Shieldbashing cooldown var/shieldbash_cooldown = 5 SECONDS /// Shieldbashing stamina cost var/shieldbash_stamcost = 7.5 /// Shieldbashing knockback var/shieldbash_knockback = 2 /// Shield bashing brute damage var/shieldbash_brutedamage = 5 /// Shield bashing stamina damage var/shieldbash_stamdmg = 15 /// Shield bashing stagger duration var/shieldbash_stagger_duration = 3.5 SECONDS /// Shield bashing push distance var/shieldbash_push_distance = 1 /obj/item/shield/examine(mob/user) . = ..() if(shield_flags & SHIELD_CAN_BASH) . += "Right click on combat mode attack with [src] to shield bash!" if(shield_flags & SHIELD_BASH_GROUND_SLAM) . += "Directly rightclicking on a downed target with [src] will slam them instead of bashing." /obj/item/shield/proc/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance) return TRUE /obj/item/shield/alt_pre_attack(atom/A, mob/living/user, params) user_shieldbash(user, A, user.a_intent != INTENT_HARM) return TRUE /obj/item/shield/altafterattack(atom/target, mob/user, proximity_flag, click_parameters) user_shieldbash(user, target, user.a_intent != INTENT_HARM) return TRUE /obj/item/shield/proc/do_shieldbash_effect(mob/living/user, dir) var/px = 0 var/py = 0 switch(dir) if(NORTH) py = 12 if(SOUTH) py = -12 if(EAST) px = 12 if(WEST) px = -12 var/oldpx = user.pixel_x var/oldpy = user.pixel_y animate(user, pixel_x = px, pixel_y = py, time = 3, easing = SINE_EASING | EASE_OUT, flags = ANIMATION_END_NOW) animate(user, pixel_x = oldpx, pixel_y = oldpy, time = 3) user.visible_message("[user] [harmful? "charges forwards with" : "sweeps"] [src]!") var/obj/effect/temp_visual/dir_setting/shield_bash/effect = new(user.loc, dir) animate(effect, alpha = 0, pixel_x = px + 4, pixel_y = py + 4, time = 3) /obj/item/shield/proc/bash_target(mob/living/user, mob/living/target, bashdir, harmful) if(!(target.status_flags & CANKNOCKDOWN) || HAS_TRAIT(src, TRAIT_STUNIMMUNE)) // should probably add stun absorption check at some point I guess.. // unified stun absorption system when lol target.visible_message("[user] slams [target] with [src], but [target] doesn't falter!", "[user] slams you with [src], but it barely fazes you!") return FALSE var/target_downed = !CHECK_MOBILITY(target, MOBILITY_STAND) var/wallhit = FALSE var/turf/target_current_turf = get_turf(target) if(harmful) target.visible_message("[target_downed? "[user] slams [src] into [target]" : "[user] bashes [target] with [src]"]!", "[target_downed? "[user] slams [src] into you" : "[user] bashes you with [src]"]!") else target.visible_message("[user] shoves [target] with [src]!", "[user] shoves you with [src]!") for(var/i in 1 to harmful? shieldbash_knockback : shieldbash_push_distance) var/turf/new_turf = get_step(target, bashdir) var/mob/living/carbon/human/H = locate() in new_turf if(H && harmful) H.visible_message("[target] is sent crashing into [H]!", "[target] is sent crashing into you!") H.KnockToFloor() wallhit = TRUE break else step(target, bashdir) if(get_turf(target) == target_current_turf) wallhit = TRUE break else target_current_turf = get_turf(target) var/disarming = (target_downed && (shield_flags & SHIELD_BASH_GROUND_SLAM_DISARM)) || (shield_flags & SHIELD_BASH_ALWAYS_DISARM) || (wallhit && (shield_flags & SHIELD_BASH_WALL_DISARM)) var/knockdown = !target_downed && ((shield_flags & SHIELD_BASH_ALWAYS_KNOCKDOWN) || (wallhit && (shield_flags & SHIELD_BASH_WALL_KNOCKDOWN))) if(shieldbash_stagger_duration || knockdown) target.visible_message("[target] is knocked [knockdown? "to the floor" : "off balanace"]!", "You are knocked [knockdown? "to the floor" : "off balanace"]!") if(knockdown) target.KnockToFloor(disarming) else if(disarming) target.drop_all_held_items() if(harmful) target.apply_damage(shieldbash_stamdmg, STAMINA, BODY_ZONE_CHEST) target.apply_damage(shieldbash_brutedamage, BRUTE, BODY_ZONE_CHEST) target.Stagger(shieldbash_stagger_duration) return TRUE /obj/item/shield/proc/user_shieldbash(mob/living/user, atom/target, harmful) if(!(shield_flags & SHIELD_CAN_BASH)) to_chat(user, "[src] can't be used to shield bash!") return FALSE if(world.time < last_shieldbash + shieldbash_cooldown) to_chat(user, "You can't bash with [src] again so soon!") return FALSE if(isliving(target)) //GROUND SLAAAM if(!(shield_flags & SHIELD_BASH_GROUND_SLAM)) to_chat(user, "You can't ground slam with [src]!") return FALSE bash_target(user, target, NONE, harmful) user.do_attack_animation(target, used_item = src) playsound(src, harmful? "swing_hit" : 'sound/weapons/thudswoosh.ogg', 75, 1) last_shieldbash = world.time user.adjustStaminaLossBuffered(shieldbash_stamcost) return 1 // Directional sweep! last_shieldbash = world.time user.adjustStaminaLossBuffered(shieldbash_stamcost) // Since we are in combat mode, we can probably safely use the user's dir instead of getting their mouse pointing cardinal dir. var/bashdir = user.dir do_shieldbash_effect(user, bashdir, harmful) var/list/checking = list(get_step(user, user.dir), get_step(user, turn(user.dir, 45)), get_step(user, turn(user.dir, -45))) var/list/victims = list() for(var/i in checking) var/turf/T = i for(var/mob/living/L in T.contents) victims += L if(length(victims)) for(var/i in victims) bash_target(user, i, bashdir, harmful) playsound(src, harmful? "swing_hit" : 'sound/weapons/thudswoosh.ogg', 75, 1) else playsound(src, 'sound/weapons/punchmiss.ogg', 75, 1) return length(victims) /obj/effect/temp_visual/dir_setting/shield_bash icon = 'icons/effects/96x96_attack_sweep.dmi' icon_state = "shield_bash" duration = 3 /obj/item/shield/riot name = "riot shield" desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder." icon_state = "riot" 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 custom_materials = list(/datum/material/glass=7500, /datum/material/iron=1000) attack_verb = list("shoved", "bashed") var/cooldown = 0 //shield bash cooldown. based on world.time shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_TRANSPARENT max_integrity = 75 /obj/item/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(ismovableatom(object)) var/atom/movable/AM = object if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS)) return BLOCK_NONE if(attack_type & ATTACK_TYPE_THROWN) final_block_chance += 30 if(attack_type & ATTACK_TYPE_TACKLE) final_block_chance = 100 . = ..() if(. & BLOCK_SUCCESS) on_shield_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) /obj/item/shield/riot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/melee/baton)) if(cooldown < world.time - 25) 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/riot/examine(mob/user) . = ..() var/healthpercent = round((obj_integrity/max_integrity) * 100, 1) switch(healthpercent) if(50 to 99) . += "It looks slightly damaged." if(25 to 50) . += "It appears heavily damaged." if(0 to 25) . += "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/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(obj_integrity <= damage) var/turf/T = get_turf(owner) T.visible_message("[attack_text] destroys [src]!") shatter(owner) qdel(src) return FALSE take_damage(damage) return ..() /obj/item/shield/riot/roman name = "\improper Roman shield" desc = "Bears an inscription on the inside: \"Romanes venio domus\"." icon_state = "roman_shield" item_state = "roman_shield" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' shield_flags = SHIELD_FLAGS_DEFAULT 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" desc = "A medieval wooden buckler." icon_state = "buckler" item_state = "buckler" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' custom_materials = null resistance_flags = FLAMMABLE block_chance = 30 shield_flags = SHIELD_FLAGS_DEFAULT max_integrity = 55 /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/energy name = "energy combat shield" desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere." lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' w_class = WEIGHT_CLASS_TINY attack_verb = list("shoved", "bashed") throw_range = 5 force = 3 throwforce = 3 throw_speed = 3 var/base_icon_state = "eshield" // [base_icon_state]1 for expanded, [base_icon_state]0 for contracted var/on_force = 10 var/on_throwforce = 8 var/on_throw_speed = 2 var/active = 0 var/clumsy_check = TRUE /obj/item/shield/energy/Initialize() . = ..() icon_state = "[base_icon_state]0" /obj/item/shield/energy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object)) block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT return ..() /obj/item/shield/energy/attack_self(mob/living/carbon/human/user) if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) to_chat(user, "You beat yourself in the head with [src]!") user.take_bodypart_damage(5) active = !active icon_state = "[base_icon_state][active]" if(active) force = on_force throwforce = on_throwforce throw_speed = on_throw_speed w_class = WEIGHT_CLASS_BULKY playsound(user, 'sound/weapons/saberon.ogg', 35, TRUE) to_chat(user, "[src] is now active.") else force = initial(force) throwforce = initial(throwforce) throw_speed = initial(throw_speed) w_class = WEIGHT_CLASS_TINY playsound(user, 'sound/weapons/saberoff.ogg', 35, TRUE) to_chat(user, "[src] can now be concealed.") add_fingerprint(user) /obj/item/shield/riot/tele name = "telescopic shield" desc = "An advanced riot shield made of lightweight materials that collapses for easy storage." icon_state = "teleriot0" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' slot_flags = null force = 3 throwforce = 3 throw_speed = 3 throw_range = 4 w_class = WEIGHT_CLASS_NORMAL var/active = 0 /obj/item/shield/riot/tele/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(!active) return BLOCK_NONE return ..() /obj/item/shield/riot/tele/attack_self(mob/living/user) active = !active icon_state = "teleriot[active]" playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) if(active) force = 8 throwforce = 5 throw_speed = 2 w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK to_chat(user, "You extend \the [src].") else force = 3 throwforce = 3 throw_speed = 3 w_class = WEIGHT_CLASS_NORMAL slot_flags = null to_chat(user, "[src] can now be concealed.") add_fingerprint(user) /obj/item/shield/makeshift name = "metal shield" desc = "A large shield made of wired and welded sheets of metal. The handle is made of cloth and leather making it unwieldy." armor = list("melee" = 25, "bullet" = 25, "laser" = 5, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 80) lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' icon = 'icons/obj/items_and_weapons.dmi' item_state = "metal" icon_state = "makeshift_shield" custom_materials = list(/datum/material/iron = 18000) slot_flags = null block_chance = 35 force = 10 throwforce = 7 /obj/item/shield/riot/tower name = "tower shield" desc = "A massive shield that can block a lot of attacks, can take a lot of abuse before braking." armor = list("melee" = 95, "bullet" = 95, "laser" = 75, "energy" = 60, "bomb" = 90, "bio" = 90, "rad" = 0, "fire" = 90, "acid" = 10) //Armor for the item, dosnt transfer to user item_state = "metal" icon_state = "metal" icon = 'icons/obj/items_and_weapons.dmi' block_chance = 75 //1/4 shots will hit* force = 16 slowdown = 2 throwforce = 15 //Massive pice of metal w_class = WEIGHT_CLASS_HUGE item_flags = SLOWS_WHILE_IN_HAND shield_flags = SHIELD_FLAGS_DEFAULT /obj/item/shield/riot/implant name = "riot tower shield" desc = "A massive shield that can block a lot of attacks and can take a lot of abuse before breaking." //It cant break unless it is removed from the implant item_state = "metal" icon_state = "metal" icon = 'icons/obj/items_and_weapons.dmi' block_chance = 30 //May be big but hard to move around to block. slowdown = 1 shield_flags = SHIELD_FLAGS_DEFAULT item_flags = SLOWS_WHILE_IN_HAND /obj/item/shield/riot/implant/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(attack_type & ATTACK_TYPE_PROJECTILE) final_block_chance = 60 //Massive shield return ..()