diff --git a/code/datums/components/shielded.dm b/code/datums/components/shielded.dm index 8be81267828..1f3269dab2d 100644 --- a/code/datums/components/shielded.dm +++ b/code/datums/components/shielded.dm @@ -28,6 +28,8 @@ var/show_charge_as_alpha = FALSE /// The item we use for recharging var/recharge_path + /// The item can block OVERWHELMING_ATTACK, which is mostly used by mech melee attacks. + var/can_block_overwhelming = FALSE /// The cooldown tracking when we were last hit COOLDOWN_DECLARE(recently_hit_cd) @@ -36,7 +38,7 @@ /// A callback for the sparks/message that play when a charge is used, see [/datum/component/shielded/proc/default_run_hit_callback] var/datum/callback/on_hit_effects -/datum/component/shielded/Initialize(max_charges = 3, recharge_start_delay = 20 SECONDS, charge_increment_delay = 1 SECONDS, charge_recovery = 1, lose_multiple_charges = FALSE, show_charge_as_alpha = FALSE, recharge_path = null, starting_charges = null, shield_icon_file = 'icons/effects/effects.dmi', shield_icon = "shield-old", shield_inhand = FALSE, run_hit_callback) +/datum/component/shielded/Initialize(max_charges = 3, recharge_start_delay = 20 SECONDS, charge_increment_delay = 1 SECONDS, charge_recovery = 1, lose_multiple_charges = FALSE, show_charge_as_alpha = FALSE, recharge_path = null, can_block_overwhelming = FALSE, starting_charges = null, shield_icon_file = 'icons/effects/effects.dmi', shield_icon = "shield-old", shield_inhand = FALSE, run_hit_callback) if(!isitem(parent) || max_charges <= 0) return COMPONENT_INCOMPATIBLE @@ -47,6 +49,7 @@ src.lose_multiple_charges = lose_multiple_charges src.show_charge_as_alpha = show_charge_as_alpha src.recharge_path = recharge_path + src.can_block_overwhelming = can_block_overwhelming src.shield_icon_file = shield_icon_file src.shield_icon = shield_icon src.shield_inhand = shield_inhand @@ -165,6 +168,11 @@ if(current_charges <= 0) return + + // if our shield is unable to block OVERWHELMING_ATTACK type attacks, we just let it pass. + if(attack_type == OVERWHELMING_ATTACK && !can_block_overwhelming) + return + . = COMPONENT_HIT_REACTION_BLOCK var/charge_loss = 1 // how many charges do we lose @@ -175,6 +183,9 @@ else if(damage < 3) charge_loss = 0 + else if(attack_type == OVERWHELMING_ATTACK && !lose_multiple_charges) // Always expend all charges when blocking an overwhelming attack unless we're using our shield like health. + charge_loss = max_charges + adjust_charge(-charge_loss) INVOKE_ASYNC(src, PROC_REF(actually_run_hit_callback), owner, attack_text, current_charges) diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index 223697af576..4e3815a1e5d 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -50,20 +50,30 @@ return NONE if(attack_type == PROJECTILE_ATTACK) return NONE - if(!prob(block_chance)) + + var/blocking_text = "block" + var/blocking_text_s = "blocks" + var/potential_block_chance = block_chance + + if(attack_type == OVERWHELMING_ATTACK) + blocking_text = "dodge" + blocking_text_s = "dodges" + potential_block_chance = clamp(round(potential_block_chance / (attack_type == OVERWHELMING_ATTACK ? 2 : 1), 1), 0, 100) + + if(!prob(potential_block_chance)) return NONE var/mob/living/attacker = GET_ASSAILANT(hitby) if(istype(attacker) && cqc_user.Adjacent(attacker)) cqc_user.visible_message( - span_danger("[cqc_user] blocks [attack_text] and twists [attacker]'s arm behind [attacker.p_their()] back!"), - span_userdanger("You block [attack_text]!"), + span_danger("[cqc_user] [blocking_text_s] [attack_text] and twists [attacker]'s arm behind [attacker.p_their()] back!"), + span_userdanger("You [blocking_text] [attack_text]!"), ) attacker.Stun(4 SECONDS) else cqc_user.visible_message( - span_danger("[cqc_user] blocks [attack_text]!"), - span_userdanger("You block [attack_text]!"), + span_danger("[cqc_user] [blocking_text_s] [attack_text]!"), + span_userdanger("You [blocking_text] [attack_text]!"), ) return SUCCESSFUL_BLOCK diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index d489dd3d732..a7978c40d57 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -280,11 +280,11 @@ ) return COMPONENT_NO_AFTERATTACK -/// If our user has committed to being as nautically radical as they can be, they may be able to avoid incoming attacks. +/// If our user has committed to being as martial arty as they can be, they may be able to avoid incoming attacks. /datum/martial_art/the_sleeping_carp/proc/check_dodge(mob/living/carp_user, atom/movable/hitby, damage, attack_text, attack_type, ...) SIGNAL_HANDLER - var/determine_avoidance = clamp(carp_style_check(carp_user), 0, 75) + var/determine_avoidance = clamp(round(carp_style_check(carp_user) / (attack_type == OVERWHELMING_ATTACK ? 2 : 1), 1), 0, 75) if(!can_deflect(carp_user)) return diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index 98219df708c..189a9423268 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -214,6 +214,9 @@ if(!HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE)) return FALSE + if(attack_type == OVERWHELMING_ATTACK) + return FALSE + if(attack_type == LEAP_ATTACK) final_block_chance -= 25 //OH GOD GET IT OFF ME @@ -509,6 +512,12 @@ if(!HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE)) return FALSE + if(attack_type == OVERWHELMING_ATTACK) + return FALSE + + if(attack_type == LEAP_ATTACK) + final_block_chance -= 25 + if(prob(final_block_chance) && charge) expend_charge(owner) return TRUE diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 1f97cb21bb2..b0d917da2f5 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -94,7 +94,7 @@ INVOKE_ASYNC(baned_target, TYPE_PROC_REF(/mob/living/carbon/human, emote), "scream") /obj/item/melee/sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() @@ -178,7 +178,7 @@ AddComponent(/datum/component/jousting) /obj/item/melee/parsnip_sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() @@ -214,7 +214,7 @@ block_sound = 'sound/items/weapons/parry.ogg' /obj/item/melee/beesword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() @@ -543,7 +543,7 @@ desc = "[initial(desc)] Its handle is made of [material.name]." /obj/item/melee/cleric_mace/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a...mace to a gunfight, and also you aren't going to really block someone full body tackling you with a mace. Or a road roller, if one happened to hit you. return ..() diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 9fa8714e098..4393a980e00 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -54,7 +54,7 @@ if(attack_type == LEAP_ATTACK) effective_block_chance = 100 if(attack_type == OVERWHELMING_ATTACK) - effective_block_chance -= 25 + effective_block_chance = 0 final_block_chance = clamp(effective_block_chance, 0, 100) . = ..() if(.) @@ -345,7 +345,7 @@ var/effective_block_chance = final_block_chance if(attack_type == OVERWHELMING_ATTACK) - effective_block_chance -= 25 + effective_block_chance = 0 if(attack_type == PROJECTILE_ATTACK) var/obj/projectile/our_projectile = hitby diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 6264e8cd371..be6a468e1b9 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -323,7 +323,7 @@ /* * Bamboo Spear */ -/obj/item/spear/bamboospear //Blatant imitation of spear, but all natural. Also not valid for explosive modification. +/obj/item/spear/bamboospear //Blatant imitation of spear, but all natural. icon_state = "bamboo_spear0" base_icon_state = "bamboo_spear0" icon_prefix = "bamboo_spear" diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 736e5754d73..852f3af1260 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -155,7 +155,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 return BRUTELOSS /obj/item/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() @@ -415,6 +415,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 alt_simple = string_list(alt_simple) AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -15) +/obj/item/katana/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == OVERWHELMING_ATTACK) + final_block_chance = 0 //Not a high freuqnecy blade, sorry pal + return ..() + /datum/armor/item_katana fire = 100 acid = 50 @@ -637,6 +642,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]" return ..() +/obj/item/bambostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) + final_block_chance = 0 //Don't bring a staff to a gunfight, and also you aren't going to really block someone full body tackling you with a staff. Or a road roller, if one happened to hit you. + return ..() + /obj/item/cane name = "cane" desc = "A cane used by a true gentleman. Or a clown." @@ -1198,7 +1208,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 playsound(src, SFX_BULLET_MISS, 75, TRUE) return TRUE return FALSE - if(prob(final_block_chance * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1))) + var/stop_that_blade = (final_block_chance + (attack_type == OVERWHELMING_ATTACK ? 25 : 0)) * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1) + if(prob(stop_that_blade)) owner.visible_message(span_danger("[owner] parries [attack_text] with [src]!")) return TRUE return FALSE diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index cc2350e685c..409c51e6866 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -523,6 +523,9 @@ loc.visible_message(span_warning("The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!"), span_warning("We inflate our hand into a strong shield."), span_hear("You hear organic matter ripping and tearing!")) /obj/item/shield/changeling/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == OVERWHELMING_ATTACK) + return FALSE + if(remaining_uses < 1) if(ishuman(loc)) var/mob/living/carbon/human/H = loc diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index ed423464aa3..2a150443e77 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -55,7 +55,7 @@ Striking a noncultist, however, will tear their flesh."} if(owner.get_active_held_item() != src) block_message = "[owner] parries [attack_text] with [src] in their offhand" - if(IS_CULTIST(owner) && prob(final_block_chance) && attack_type != (PROJECTILE_ATTACK || OVERWHELMING_ATTACK)) + if(IS_CULTIST(owner) && prob(final_block_chance) && (attack_type != PROJECTILE_ATTACK || attack_type != OVERWHELMING_ATTACK)) new /obj/effect/temp_visual/cult/sparks(get_turf(owner)) owner.visible_message(span_danger("[block_message]")) return TRUE diff --git a/code/modules/antagonists/heretic/items/heretic_blades.dm b/code/modules/antagonists/heretic/items/heretic_blades.dm index 3d4924d2211..d5dc25187b5 100644 --- a/code/modules/antagonists/heretic/items/heretic_blades.dm +++ b/code/modules/antagonists/heretic/items/heretic_blades.dm @@ -304,6 +304,11 @@ return ITEM_INTERACT_BLOCKING return NONE +/obj/item/melee/sickly_blade/cursed/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == OVERWHELMING_ATTACK) + return FALSE + return ..() + // Weaker blade variant given to people so they can participate in the heretic arena spell /obj/item/melee/sickly_blade/training name = "\improper imperfect blade" diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 93f352539da..1a4116b9579 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -188,7 +188,7 @@ name = "Inquisition Commander" back = /obj/item/mod/control/pre_equipped/responsory/inquisitory/commander - r_hand = /obj/item/nullrod/vibro/talking/chainsword + r_hand = /obj/item/nullrod/claymore/talking/chainsword backpack_contents = null /datum/outfit/centcom/ert/security/inquisitor diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index f46b31086a9..c51b6602478 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -259,6 +259,11 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( slapperoni(user, iteration = 1) return MANUAL_SUICIDE +/obj/item/fish/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == OVERWHELMING_ATTACK) + return FALSE + return ..() + /obj/item/fish/proc/slapperoni(mob/living/user, iteration) stoplag(0.1 SECONDS) user.visible_message(span_bolddanger(suicide_slap_text)) diff --git a/code/modules/hydroponics/soil.dm b/code/modules/hydroponics/soil.dm index 4b6389923a2..c46685ac689 100644 --- a/code/modules/hydroponics/soil.dm +++ b/code/modules/hydroponics/soil.dm @@ -175,6 +175,11 @@ qdel(src) return ITEM_INTERACT_SUCCESS +/obj/item/soil_sack/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == OVERWHELMING_ATTACK) + return FALSE + return ..() + ///Remove slowdown and add block chance when wielded. /obj/item/soil_sack/proc/on_wield() slowdown = 0 diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm index a734904b905..549060e62ca 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm @@ -128,7 +128,7 @@ GLOBAL_LIST_INIT(nullrod_variants, init_nullrod_variants()) AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -3) /obj/item/nullrod/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() @@ -191,62 +191,26 @@ GLOBAL_LIST_INIT(nullrod_variants, init_nullrod_variants()) SET_ATTACK_FORCE(attack_modifiers, rand(max(force - 15, 1), force + 15)) return ..() -/// Vibro Variant -/// This subtype possesses armor penetration and is sharp. - -/obj/item/nullrod/vibro - name = "high frequency blade" - desc = "Bad references are the DNA of the soul." - icon = 'icons/obj/weapons/sword.dmi' - icon_state = "hfrequency0" - inhand_icon_state = "hfrequency1" - worn_icon_state = "hfrequency0" - icon_angle = -45 - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - w_class = WEIGHT_CLASS_BULKY - armour_penetration = 35 - slot_flags = ITEM_SLOT_BACK - sharpness = SHARP_EDGED - attack_verb_continuous = list("chops", "slices", "cuts", "zandatsu's") - attack_verb_simple = list("chop", "slice", "cut", "zandatsu") - hitsound = 'sound/items/weapons/rapierhit.ogg' - menu_description = "A sharp blade which partially penetrates armor. Very effective at butchering bodies. Can be worn on the back." - var/list/alt_continuous = list("stabs", "pierces", "impales") - var/list/alt_simple = list("stab", "pierce", "impale") - -/obj/item/nullrod/vibro/Initialize(mapload) - . = ..() - alt_continuous = string_list(alt_continuous) - alt_simple = string_list(alt_simple) - AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -3) - -/obj/item/nullrod/vibro/Initialize(mapload) - . = ..() - AddComponent( - /datum/component/butchering, \ - speed = 7 SECONDS, \ - effectiveness = 110, \ - ) - -/obj/item/nullrod/vibro/spellblade +/obj/item/nullrod/claymore/spellblade name = "dormant spellblade" desc = "The blade grants the wielder nearly limitless power...if they can figure out how to turn it on, that is." icon = 'icons/obj/weapons/guns/magic.dmi' icon_state = "spellblade" inhand_icon_state = "spellblade" + slot_flags = ITEM_SLOT_BACK lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' worn_icon_state = "spellblade" hitsound = 'sound/items/weapons/rapierhit.ogg' - menu_description = "A sharp blade which partially penetrates armor. Very effective at butchering bodies. Can be worn on the back." + menu_description = "A sharp blade which provides a low chance of blocking incoming melee attacks. Can be worn on the back." -/obj/item/nullrod/vibro/talking +/obj/item/nullrod/claymore/talking name = "possessed blade" desc = "When the station falls into chaos, it's nice to have a friend by your side." icon = 'icons/obj/weapons/sword.dmi' icon_state = "talking_sword" inhand_icon_state = "talking_sword" + slot_flags = ITEM_SLOT_BACK icon_angle = 45 lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' @@ -254,13 +218,13 @@ GLOBAL_LIST_INIT(nullrod_variants, init_nullrod_variants()) attack_verb_continuous = list("chops", "slices", "cuts") attack_verb_simple= list("chop", "slice", "cut") hitsound = 'sound/items/weapons/rapierhit.ogg' - menu_description = "A sharp blade which partially penetrates armor. Able to awaken a friendly spirit to provide guidance. Very effective at butchering bodies. Can be worn on the back." + menu_description = "A sharp blade which provides a low chance of blocking incoming melee attacks. Able to awaken a friendly spirit to provide guidance. Can be worn on the back." -/obj/item/nullrod/vibro/talking/Initialize(mapload) +/obj/item/nullrod/spellblade/talking/Initialize(mapload) . = ..() AddComponent(/datum/component/spirit_holding) -/obj/item/nullrod/vibro/talking/chainsword +/obj/item/nullrod/claymore/talking/chainsword name = "possessed chainsaw sword" desc = "Suffer not a heretic to live." icon_state = "chainswordon" @@ -275,13 +239,70 @@ GLOBAL_LIST_INIT(nullrod_variants, init_nullrod_variants()) toolspeed = 0.5 //same speed as an active chainsaw chaplain_spawnable = FALSE //prevents being pickable as a chaplain weapon (it has 30 force) -/obj/item/nullrod/vibro/talking/chainsword/Initialize(mapload) +/obj/item/nullrod/spellblade/talking/chainsword/Initialize(mapload) . = ..() AddElement(/datum/element/cuffable_item) //Thanks goodness it cannot be selected by chappies + AddComponent( + /datum/component/butchering, \ + speed = 7 SECONDS, \ + effectiveness = 110, \ + ) /// Other Variants /// Not a special category on their own, but usually possess more unique mechanics +// High Frequency Blade - Two-handed, has armor penetration, and can block exosuit attacks relatively easily. Can't block anything else. + +/obj/item/nullrod/vibro + name = "high frequency blade" + desc = "Bad references are the DNA of the soul." + icon = 'icons/obj/weapons/sword.dmi' + icon_state = "hfrequency0" + inhand_icon_state = "hfrequency0" + base_icon_state = "hfrequency" + worn_icon_state = "hfrequency0" + icon_angle = -45 + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + w_class = WEIGHT_CLASS_BULKY + force = 10 + armour_penetration = 35 + block_chance = 40 + slot_flags = ITEM_SLOT_BACK + sharpness = SHARP_EDGED + attack_verb_continuous = list("chops", "slices", "cuts", "zandatsu's") + attack_verb_simple = list("chop", "slice", "cut", "zandatsu") + hitsound = 'sound/items/weapons/rapierhit.ogg' + block_sound = 'sound/items/weapons/parry.ogg' + menu_description = "A sharp blade which partially penetrates armor. Unusualy adept at blocking melee attacks from exosuits. Very effective at butchering bodies. Can be worn on the back." + var/list/alt_continuous = list("stabs", "pierces", "impales") + var/list/alt_simple = list("stab", "pierce", "impale") + +/obj/item/nullrod/vibro/Initialize(mapload) + . = ..() + alt_continuous = string_list(alt_continuous) + alt_simple = string_list(alt_simple) + AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -3) + AddComponent(/datum/component/two_handed, \ + force_unwielded = 10, \ + force_wielded = 18, \ + ) + AddComponent( + /datum/component/butchering, \ + speed = 7 SECONDS, \ + effectiveness = 110, \ + ) + +/obj/item/nullrod/vibro/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(prob(final_block_chance * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1)) && attack_type == OVERWHELMING_ATTACK) + owner.visible_message(span_danger("[owner] parries [attack_text] with [src]!")) + return TRUE + return FALSE + +/obj/item/nullrod/vibro/update_icon_state() + icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]" + return ..() + // God Hand - Cannot be dropped. Does burn damage. /obj/item/nullrod/godhand @@ -585,7 +606,7 @@ GLOBAL_LIST_INIT(nullrod_variants, init_nullrod_variants()) AddElement(/datum/element/nullrod_core) AddComponent(/datum/component/faction_granter, FACTION_CARP, holy_role_required = HOLY_ROLE_PRIEST, grant_message = span_boldnotice("You are blessed by Carp-Sie. Wild space carp will no longer attack you.")) -// Monk's Staff - Higher block, lower damage. +// Monk's Staff - Good block, two-handed. Great for showing off. /obj/item/nullrod/bostaff name = "monk's staff" @@ -620,7 +641,7 @@ GLOBAL_LIST_INIT(nullrod_variants, init_nullrod_variants()) return ..() /obj/item/nullrod/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a stick to a gunfight, and also you aren't going to really block someone full body tackling you with a stick. Or a road roller, if one happened to hit you. return ..() diff --git a/code/modules/mining/lavaland/mining_loot/cursed_katana.dm b/code/modules/mining/lavaland/mining_loot/cursed_katana.dm index 8de94828932..4b0019166f7 100644 --- a/code/modules/mining/lavaland/mining_loot/cursed_katana.dm +++ b/code/modules/mining/lavaland/mining_loot/cursed_katana.dm @@ -107,7 +107,7 @@ return ..() /obj/item/cursed_katana/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm index da860fdb3b6..876283599fa 100644 --- a/code/modules/mob_spawn/corpses/mining_corpses.dm +++ b/code/modules/mob_spawn/corpses/mining_corpses.dm @@ -350,7 +350,7 @@ dame.physique = FEMALE dame.update_body() if(prob(30)) - back = /obj/item/nullrod/vibro/talking + back = /obj/item/nullrod/claymore/talking else back = /obj/item/shield/buckler belt = /obj/item/nullrod/claymore diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index 6b7d814aa3e..44443c90fa2 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -29,6 +29,8 @@ var/shield_icon = "shield-red" /// Charges the shield should start with. var/charges + /// Whether or not we allow this shield to block overwhelming attacks, such as from mechs. + var/block_overwhelming_attacks = FALSE /obj/item/mod/module/energy_shield/Initialize(mapload) . = ..() @@ -43,6 +45,7 @@ charge_recovery = charge_recovery, \ lose_multiple_charges = lose_multiple_charges, \ starting_charges = charges, \ + can_block_overwhelming = block_overwhelming_attacks, \ shield_icon_file = shield_icon_file, \ shield_icon = shield_icon) RegisterSignal(mod.wearer, COMSIG_LIVING_CHECK_BLOCK, PROC_REF(shield_reaction)) @@ -64,7 +67,7 @@ SIGNAL_HANDLER if(mod.hit_reaction(owner, hitby, attack_text, 0, damage, attack_type)) - drain_power(use_energy_cost) + drain_power(use_energy_cost + use_energy_cost * (attack_type == OVERWHELMING_ATTACK ? (damage/100) : 0)) return SUCCESSFUL_BLOCK return NONE @@ -80,6 +83,7 @@ max_charges = 5 recharge_start_delay = 20 SECONDS charge_increment_delay = 3 SECONDS + block_overwhelming_attacks = TRUE // It's magic, bitch shield_icon_file = 'icons/effects/magic.dmi' shield_icon = "mageshield" required_slots = list() diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index 6792f653a05..b1d664a6271 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -264,7 +264,7 @@ ) /obj/item/gun/magic/staff/spellblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) - if(attack_type == (PROJECTILE_ATTACK || LEAP_ATTACK || OVERWHELMING_ATTACK)) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you. return ..() diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm index f8ccec3e202..76a23c28159 100644 --- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm @@ -108,8 +108,6 @@ return ..() if(victim.check_block(chassis, clamp_damage, name, attack_type = OVERWHELMING_ATTACK)) - source.visible_message(span_danger("[chassis] attempts to squeeze [victim] with [src], but the [name] is blocked!"), span_userdanger("You attempt to squeeze [victim] with [src], but [victim.p_They()] managed to block the attempt!"), ignored_mobs = victim) - to_chat(victim, span_userdanger("You block [chassis]'s attempt to squeeze you with [src]!")) return ..() if(iscarbon(victim) && killer_clamp)//meme clamp here diff --git a/code/modules/vehicles/mecha/mech_melee_attack.dm b/code/modules/vehicles/mecha/mech_melee_attack.dm index 3aee7762b76..6d868f52e36 100644 --- a/code/modules/vehicles/mecha/mech_melee_attack.dm +++ b/code/modules/vehicles/mecha/mech_melee_attack.dm @@ -100,9 +100,14 @@ if(!isnull(user) && HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, span_warning("You don't want to harm other living beings!")) return + mecha_attacker.do_attack_animation(src) if(mecha_attacker.damtype == BRUTE) step_away(src, mecha_attacker, 15) + + if(check_block(mecha_attacker, mecha_attacker.force * 3, "the [mecha_attacker.attack_verbs[1]]", attack_type = OVERWHELMING_ATTACK)) + return + switch(mecha_attacker.damtype) if(BRUTE) if(mecha_attacker.force > 35) // durand and other heavy mechas diff --git a/tools/UpdatePaths/Scripts/94089_vibro_repaths.txt b/tools/UpdatePaths/Scripts/94089_vibro_repaths.txt new file mode 100644 index 00000000000..4ee856206b9 --- /dev/null +++ b/tools/UpdatePaths/Scripts/94089_vibro_repaths.txt @@ -0,0 +1,5 @@ +/obj/item/nullrod/claymore/spellblade : /obj/item/nullrod/vibro/spellblade{@OLD} + +/obj/item/nullrod/claymore/talking : /obj/item/nullrod/vibro/talking{@OLD} + +/obj/item/nullrod/claymore/talking/chainsword : /obj/item/nullrod/vibro/talking/chainsword{@OLD} \ No newline at end of file