Migrate two-handed weapons to the new attack chain. (#32313)

* Migrate two-handed weapons to the new attack chain.

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Separate two-handed weapons into several files in their own folder.

* Formatting tweaks.

* Apply suggestions from CRUNCH review.

* Include paradise.dme.

* Migrate a bit more, clean up a bit more.

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Apply suggestions from CRUNCH review

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Hopefully resolve CRLF error.

* Define some variables.

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Apply suggestions from CRUNCH review

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Fix supermatter halberd dusting condition, spelling errors.

* Apply suggestion from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* GITHUB NO. PUT THAT BACK.

* Fix pyro claws door force.

* Restore the coveted trailing newline.

* Apply suggestion from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Migrate bo staff to the two handed folder and new attack chain.

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

---------

Signed-off-by: Alan <alfalfascout@users.noreply.github.com>
Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
This commit is contained in:
Alan
2026-08-12 23:23:39 +00:00
committed by GitHub
co-authored by CRUNCH
parent b9d22b0538
commit 6a83c1ad67
9 changed files with 1268 additions and 1089 deletions
@@ -0,0 +1,109 @@
/*
* Fireaxe
*/
/// DEM AXES MAN, marker -Agouri
/obj/item/fireaxe
base_icon_state = "fireaxe"
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/melee.dmi'
icon_state = "fireaxe0"
name = "fire axe"
desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?"
force = 5
throwforce = 15
sharp = TRUE
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
toolspeed = 0.25
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
usesound = 'sound/items/crowbar.ogg'
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 30)
resistance_flags = FIRE_PROOF
var/force_unwielded = 5
var/force_wielded = 24
new_attack_chain = TRUE
/obj/item/fireaxe/Initialize(mapload)
. = ..()
AddComponent(/datum/component/forces_doors_open)
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.7, \
_parryable_attack_types = MELEE_ATTACK, \
_parry_cooldown = (10 / 3) SECONDS, \
_requires_two_hands = TRUE) // 2.3333 seconds of parry cooldown for 30% uptime.
AddComponent(/datum/component/two_handed, \
force_unwielded = force_unwielded, \
force_wielded = force_wielded, \
icon_wielded = "[base_icon_state]1")
/obj/item/fireaxe/update_icon_state() // Currently only here to fuck with the on-mob icons.
icon_state = "[base_icon_state]0"
return ..()
/obj/item/fireaxe/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return FINISH_ATTACK
if(!HAS_TRAIT(src, TRAIT_WIELDED)) // Destroys windows and grilles in one hit.
return ..()
if(!istype(target, /obj/structure/window) && !istype(target, /obj/structure/grille))
return ..()
var/obj/structure/target_structure = target
target_structure.obj_destruction("fireaxe")
return FINISH_ATTACK
/// Blatant imitation of the fireaxe, but made out of bone.
/obj/item/fireaxe/boneaxe
icon_state = "bone_axe0"
base_icon_state = "bone_axe"
name = "bone axe"
desc = "A large, vicious axe crafted out of several sharpened bone plates and crudely tied together. Made of monsters, by killing monsters, for killing monsters."
force_wielded = 23
needs_permit = TRUE
/obj/item/fireaxe/energized
desc = "Someone with a love for fire axes decided to turn this one into a high-powered energy weapon. Seems excessive."
force_wielded = 35
armor_penetration_flat = 10
armor_penetration_percentage = 30
var/charge = 20
var/max_charge = 20
/obj/item/fireaxe/energized/Initialize(mapload)
. = ..()
// only update the new args
START_PROCESSING(SSobj, src)
AddComponent(/datum/component/two_handed, \
force_wielded = force_wielded, \
icon_wielded = "[base_icon_state]2")
/obj/item/fireaxe/energized/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/fireaxe/energized/process()
charge = min(charge + 1, max_charge)
/obj/item/fireaxe/energized/after_attack(mob/living/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!HAS_TRAIT(src, TRAIT_WIELDED) || charge != max_charge)
return
if(!isliving(target))
return
charge = 0
playsound(loc, 'sound/magic/lightningbolt.ogg', 5, 1)
target.visible_message(
SPAN_DANGER("[user] slams the charged axe into [target] with all [user.p_their()] might!"),
SPAN_USERDANGER("[user] slams into you with incredible force!"),
SPAN_HEAR("You hear a collossal impact!")
)
do_sparks(1, 1, src)
target.KnockDown(8 SECONDS)
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
target.throw_at(throw_target, 5, 1)
return FINISH_ATTACK
@@ -0,0 +1,216 @@
// SINGULOHAMMER.
/obj/item/singularityhammer
name = "singularity hammer"
desc = "The pinnacle of close combat technology, the hammer harnesses the power of a miniaturized singularity to deal crushing blows."
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/magical_weapons.dmi'
icon_state = "singulohammer0"
base_icon_state = "singulohammer"
flags = CONDUCT
slot_flags = ITEM_SLOT_BACK
force = 5
throwforce = 15
throw_range = 1
w_class = WEIGHT_CLASS_HUGE
armor = list(MELEE = 50, BULLET = 50, LASER = 50, ENERGY = 0, BOMB = 50, RAD = 0, FIRE = 100, ACID = 100)
resistance_flags = FIRE_PROOF | ACID_PROOF
var/charged = 2
origin_tech = "combat=4;bluespace=4;plasmatech=7"
new_attack_chain = TRUE
/obj/item/singularityhammer/Initialize(mapload)
. = ..()
AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.25, _parryable_attack_types = ALL_ATTACK_TYPES, _parry_cooldown = (4 / 3) SECONDS, _requires_two_hands = TRUE) // 0.3333 seconds of cooldown for 75% uptime
AddComponent(/datum/component/two_handed, \
force_wielded = 40, \
force_unwielded = force, \
icon_wielded = "[base_icon_state]1")
START_PROCESSING(SSobj, src)
/obj/item/singularityhammer/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/singularityhammer/process()
if(charged < 2)
charged++
/obj/item/singularityhammer/update_icon_state() // Currently only here to fuck with the on-mob icons.
icon_state = "singulohammer0"
/obj/item/singularityhammer/proc/vortex(turf/pull, mob/wielder)
for(var/atom/movable/X in range(5, pull))
if(X.move_resist == INFINITY)
continue
if(X == wielder)
continue
if((X) && (!X.anchored) && (!ishuman(X)))
step_towards(X, pull)
step_towards(X, pull)
step_towards(X, pull)
else if(ishuman(X))
var/mob/living/carbon/human/H = X
if(HAS_TRAIT(H, TRAIT_MAGPULSE))
continue
H.Weaken(4 SECONDS)
step_towards(H, pull)
step_towards(H, pull)
step_towards(H, pull)
/obj/item/singularityhammer/after_attack(mob/living/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return FINISH_ATTACK
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
if(charged < 2)
return ..()
charged = 0
if(isliving(target))
target.take_organ_damage(20, 0)
playsound(user, 'sound/weapons/marauder.ogg', 50, 1)
var/turf/target_turf = get_turf(target)
vortex(target_turf, user)
return FINISH_ATTACK
/obj/item/mjollnir
name = "Mjolnir"
desc = "A weapon worthy of a god, able to strike with the force of a lightning bolt. It crackles with barely contained energy."
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/magical_weapons.dmi'
icon_state = "mjollnir0"
base_icon_state = "mjollnir"
flags = CONDUCT
slot_flags = ITEM_SLOT_BACK
force = 5
throwforce = 30
w_class = WEIGHT_CLASS_HUGE
origin_tech = "combat=4;powerstorage=7"
new_attack_chain = TRUE
/obj/item/mjollnir/Initialize(mapload)
. = ..()
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.25, \
_parryable_attack_types = ALL_ATTACK_TYPES, \
_parry_cooldown = (4 / 3) SECONDS, \
_requires_two_hands = TRUE) // 0.3333 seconds of parry cooldown for 75% uptime.
AddComponent(/datum/component/two_handed, \
force_wielded = 25, \
force_unwielded = force, \
icon_wielded = "[base_icon_state]1")
/obj/item/mjollnir/proc/shock(mob/living/target)
do_sparks(5, 1, target.loc)
target.visible_message(
SPAN_DANGER("[target] was shocked by [src]!"),
SPAN_USERDANGER("You feel a powerful shock course through your body sending you flying!"),
SPAN_DANGER("You hear a heavy electrical crack!")
)
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
target.throw_at(throw_target, 200, 4)
/obj/item/mjollnir/after_attack(mob/living/target, mob/user, proximity_flag, click_parameters)
if(!isliving(target))
return ..()
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
playsound(loc, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
target.Stun(6 SECONDS)
shock(target)
return FINISH_ATTACK
/obj/item/mjollnir/throw_impact(atom/target)
. = ..()
if(isliving(target))
var/mob/living/L = target
L.Stun(6 SECONDS)
shock(L)
/obj/item/mjollnir/update_icon_state() // Currently only here to fuck with the on-mob icons.
icon_state = "mjollnir0"
/obj/item/knighthammer
name = "singuloth knight's hammer"
desc = "A hammer made of sturdy metal with a golden skull adorned with wings on either side of the head. <br>This weapon causes devastating damage to those it hits due to a power field sustained by a mini-singularity inside of the hammer."
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/magical_weapons.dmi'
icon_state = "knighthammer0"
base_icon_state = "knighthammer"
flags = CONDUCT
slot_flags = ITEM_SLOT_BACK
force = 5
throwforce = 15
throw_range = 1
w_class = WEIGHT_CLASS_HUGE
var/charged = 5
origin_tech = "combat=5;bluespace=4"
new_attack_chain = TRUE
/obj/item/knighthammer/Initialize(mapload)
. = ..()
START_PROCESSING(SSobj, src)
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.25, \
_parryable_attack_types = ALL_ATTACK_TYPES, \
_parry_cooldown = (4 / 3) SECONDS, \
_requires_two_hands = TRUE) // 0.3333 seconds of parry cooldown for 75% uptime.
AddComponent(/datum/component/two_handed, \
force_wielded = 30, \
force_unwielded = force, \
icon_wielded = "[base_icon_state]1")
/obj/item/knighthammer/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/knighthammer/process()
if(charged < 5)
charged++
/obj/item/knighthammer/update_icon_state() // Currently only here to fuck with the on-mob icons.
icon_state = "knighthammer0"
/obj/item/knighthammer/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return FINISH_ATTACK
if(charged < 5)
return ..()
charged = 0
if(isliving(target))
var/mob/living/Z = target
if(Z.health > HEALTH_THRESHOLD_CRIT)
Z.visible_message(
SPAN_DANGER("[Z.name] was sent flying by a blow from [src]!"),
SPAN_USERDANGER("You feel a powerful blow connect with your body and send you flying!"),
SPAN_DANGER("You hear something heavy impact flesh!")
)
var/atom/throw_target = get_edge_target_turf(Z, get_dir(src, get_step_away(Z, src)))
Z.throw_at(throw_target, 200, 4)
// Target is in crit, check if we're holding securely enough to gib them.
else if(HAS_TRAIT(src, TRAIT_WIELDED))
Z.visible_message(
SPAN_DANGER("[Z.name] was blown to pieces by the power of [src]!"),
SPAN_USERDANGER("You feel a powerful blow rip you apart!"),
SPAN_DANGER("You hear a heavy impact and the sound of ripping flesh!")
)
Z.gib()
playsound(user, 'sound/weapons/marauder.ogg', 50, 1)
return FINISH_ATTACK
if(HAS_TRAIT(src, TRAIT_WIELDED))
if(iswallturf(target))
var/turf/simulated/wall/Z = target
Z.ex_act(EXPLODE_HEAVY)
else if(isstructure(target) || ismecha(target))
var/obj/Z = target
Z.ex_act(EXPLODE_HEAVY)
charged = 3
playsound(user, 'sound/weapons/marauder.ogg', 50, 1)
return FINISH_ATTACK
@@ -0,0 +1,435 @@
/*
* Double-Bladed Energy Swords - Cheridan
*/
/obj/item/dualsaber
name = "double-bladed energy sword"
desc = "Handle with care."
icon = 'icons/obj/weapons/energy_melee.dmi'
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
hitsound = "swing_hit"
icon_state = "dualsaber0"
force = 3
throwforce = 5
throw_speed = 1
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
var/w_class_on = WEIGHT_CLASS_BULKY
armor_penetration_flat = 10
armor_penetration_percentage = 50
origin_tech = "magnets=4;syndicate=5"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 70)
resistance_flags = FIRE_PROOF
light_power = 2
needs_permit = TRUE
var/hacked = FALSE
var/blade_color
var/brightness_on = 2
var/colormap = list(
red = LIGHT_COLOR_RED,
blue = LIGHT_COLOR_LIGHTBLUE,
green = LIGHT_COLOR_GREEN,
purple = LIGHT_COLOR_PURPLE,
rainbow = LIGHT_COLOR_WHITE,
)
var/force_unwielded = 3
var/force_wielded = 34
var/wieldsound = 'sound/weapons/saberon.ogg'
var/unwieldsound = 'sound/weapons/saberoff.ogg'
new_attack_chain = TRUE
/obj/item/dualsaber/Initialize(mapload)
. = ..()
if(!blade_color)
blade_color = pick("red", "blue", "green", "purple")
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.25, \
_parryable_attack_types = ALL_ATTACK_TYPES, \
_parry_cooldown = (4 / 3) SECONDS, /* 0.33 seconds of parry cooldown for 75% uptime. */ \
_requires_two_hands = TRUE)
AddComponent(/datum/component/two_handed, \
force_wielded = force_wielded, \
force_unwielded = force_unwielded, \
wieldsound = wieldsound, \
unwieldsound = unwieldsound, \
attacksound = 'sound/weapons/blade1.ogg', \
wield_callback = CALLBACK(src, PROC_REF(on_wield)), \
unwield_callback = CALLBACK(src, PROC_REF(on_unwield)), \
only_sharp_when_wielded = TRUE)
/obj/item/dualsaber/update_icon_state()
if(HAS_TRAIT(src, TRAIT_WIELDED))
icon_state = "dualsaber[blade_color]1"
set_light(brightness_on, l_color=colormap[blade_color])
else
icon_state = "dualsaber0"
set_light(0)
/obj/item/dualsaber/interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(cigarette_lighter_act(user, target))
return ITEM_INTERACT_COMPLETE
return ..()
/obj/item/dualsaber/pre_attack(atom/target, mob/living/user, params)
if(HAS_TRAIT(user, TRAIT_HULK))
to_chat(user, SPAN_WARNING("You grip the blade too hard and accidentally drop it!"))
if(HAS_TRAIT(src, TRAIT_WIELDED))
user.drop_item_to_ground(src)
return FINISH_ATTACK
if(HAS_TRAIT(user, TRAIT_CLUMSY) && HAS_TRAIT(src, TRAIT_WIELDED) && prob(40) && force)
to_chat(user, SPAN_WARNING("You twirl around a bit before losing your balance and impaling yourself on [src]!"))
user.take_organ_damage(20, 25)
return FINISH_ATTACK
if((HAS_TRAIT(src, TRAIT_WIELDED)) && prob(50))
INVOKE_ASYNC(src, PROC_REF(jedi_spin), user)
return ..()
/obj/item/dualsaber/cigarette_lighter_act(mob/living/user, mob/living/target, obj/item/direct_attackby_item)
var/obj/item/clothing/mask/cigarette/cig = ..()
if(!cig)
return !isnull(cig)
if(!HAS_TRAIT(src, TRAIT_WIELDED))
to_chat(user, SPAN_WARNING("You need to activate [src] before you can light anything with it!"))
return TRUE
if(target == user)
user.visible_message(
SPAN_DANGER("[user] flips through the air and spins [src] wildly! It brushes against [user.p_their()] [cig] and sets it alight!"),
SPAN_NOTICE("You flip through the air and twist [src] so it brushes against [cig], lighting it with the blade."),
SPAN_DANGER("You hear an energy blade slashing something!")
)
else
user.visible_message(
SPAN_DANGER("[user] flips through the air and slashes at [user] with [src]! The blade barely misses, brushing against [user.p_their()] [cig] and setting it alight!"),
SPAN_NOTICE("You flip through the air and slash [src] at [cig], lighting it for [target]."),
SPAN_DANGER("You hear an energy blade slashing something!")
)
user.do_attack_animation(target)
playsound(user.loc, hitsound, 50, TRUE)
cig.light(user, target)
INVOKE_ASYNC(src, PROC_REF(jedi_spin), user)
return TRUE
/obj/item/dualsaber/proc/jedi_spin(mob/living/user)
for(var/i in list(NORTH, SOUTH, EAST, WEST, EAST, SOUTH, NORTH, SOUTH, EAST, WEST, EAST, SOUTH))
user.setDir(i)
if(i == WEST)
user.SpinAnimation(7, 1)
sleep(1)
/obj/item/dualsaber/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(!HAS_TRAIT(src, TRAIT_WIELDED))
return FALSE
. = ..()
if(!.) // They did not block the attack.
return
if(attack_type == THROWN_PROJECTILE_ATTACK)
if(!isitem(hitby))
return TRUE
var/obj/item/TT = hitby
//Timer set to 0.2 seconds to ensure item finshes the throwing to prevent double embeds
addtimer(CALLBACK(TT, TYPE_PROC_REF(/atom/movable, throw_at), locateUID(TT.thrownby), 10, 4, owner), 0.2 SECONDS)
return TRUE
if(isitem(hitby))
melee_attack_chain(owner, hitby.loc)
else
melee_attack_chain(owner, hitby)
return TRUE
// In case it just so happens that it is still activated on the ground, prevents hulk from picking it up.
/obj/item/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(HAS_TRAIT(src, TRAIT_WIELDED))
to_chat(user, SPAN_WARNING("You can't pick up such a dangerous item with your meaty hands without losing fingers, better not to!"))
return TRUE
/obj/item/dualsaber/green
blade_color = "green"
/obj/item/dualsaber/red
blade_color = "red"
/obj/item/dualsaber/purple
blade_color = "purple"
/obj/item/dualsaber/blue
blade_color = "blue"
/obj/item/dualsaber/proc/on_wield(obj/item/source, mob/living/carbon/user)
if(user && HAS_TRAIT(user, TRAIT_HULK))
to_chat(user, SPAN_WARNING("You lack the grace to wield this!"))
return COMPONENT_TWOHANDED_BLOCK_WIELD
w_class = w_class_on
/obj/item/dualsaber/proc/on_unwield()
w_class = initial(w_class)
/obj/item/dualsaber/IsReflect()
if(HAS_TRAIT(src, TRAIT_WIELDED))
return TRUE
/obj/item/dualsaber/multitool_act(mob/user, obj/item/I)
. = TRUE
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
return
if(!hacked)
hacked = TRUE
to_chat(user, SPAN_WARNING("2XRNBW_ENGAGE"))
blade_color = "rainbow"
update_icon()
else
to_chat(user, SPAN_WARNING("It's starting to look like a triple rainbow - no, nevermind."))
// PYRO CLAWS
/obj/item/pyro_claws
name = "hardplasma energy claws"
desc = "The power of the sun, in the claws of your hand."
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/energy_melee.dmi'
icon_state = "pyro_claws"
flags = ABSTRACT | NODROP | DROPDEL
force = 22
damtype = BURN
armor_penetration_percentage = 50
sharp = TRUE
attack_effect_override = ATTACK_EFFECT_CLAW
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut", "savaged", "clawed")
sprite_sheets_inhand = list(
"Vox" = 'icons/mob/clothing/species/vox/held.dmi',
"Drask" = 'icons/mob/clothing/species/drask/held.dmi'
)
toolspeed = 0.5
var/lifetime = 60 SECONDS
var/next_spark_time
new_attack_chain = TRUE
/obj/item/pyro_claws/Initialize(mapload)
. = ..()
START_PROCESSING(SSobj, src)
AddComponent(/datum/component/forces_doors_open)
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.5, \
_parryable_attack_types = ALL_ATTACK_TYPES)
AddComponent(/datum/component/two_handed, require_twohands = TRUE)
/obj/item/pyro_claws/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/pyro_claws/customised_abstract_text(mob/living/carbon/owner)
return SPAN_WARNING("[owner.p_they(TRUE)] [owner.p_have(FALSE)] energy claws extending [owner.p_their(FALSE)] wrists.")
/obj/item/pyro_claws/process()
lifetime -= 2 SECONDS
if(lifetime <= 0)
visible_message(SPAN_WARNING("[src] slides back into the depths of [loc]'s wrists."))
do_sparks(rand(1, 6), 1, loc)
qdel(src)
return
if(prob(15))
do_sparks(rand(1, 6), 1, loc)
/obj/item/pyro_claws/door_force_try_message(obj/machinery/door/door, mob/user)
user.visible_message(
SPAN_WARNING("[user] jams [user.p_their()] [name] into [door] and starts prying it open!"),
SPAN_WARNING("You start forcing [door] open."),
SPAN_HEAR("You hear a metal screeching sound.")
)
/obj/item/pyro_claws/door_force_success_message(obj/machinery/door/door, mob/user)
user.visible_message(
SPAN_WARNING("[user] forces [door] open with [user.p_their()] [name]!"),
SPAN_WARNING("You force open [door]."),
SPAN_HEAR("You hear a metal screeching come to a halt.")
)
/obj/item/pyro_claws/interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(prob(60) && world.time > next_spark_time)
do_sparks(rand(1, 6), 1, loc)
next_spark_time = world.time + 0.8 SECONDS
return NONE
/obj/item/clothing/gloves/color/black/pyro_claws
name = "Fusion gauntlets"
desc = "A pair of heavy combat gauntlets that project lethal energy claws via the power of a captive pyroclastic anomaly core."
icon_state = "pyro"
inhand_icon_state = null
worn_icon_state = null
can_be_cut = FALSE
actions_types = list(/datum/action/item_action/toggle)
dyeable = FALSE
materials = list(MAT_METAL = 10000, MAT_GLASS = 5000, MAT_SILVER = 4000, MAT_TITANIUM = 4000, MAT_PLASMA = 8000)
var/on_cooldown = FALSE
var/obj/item/assembly/signaler/anomaly/pyro/core
var/next_spark_time
/obj/item/clothing/gloves/color/black/pyro_claws/Destroy()
QDEL_NULL(core)
return ..()
/obj/item/clothing/gloves/color/black/pyro_claws/examine(mob/user)
. = ..()
if(core)
. += SPAN_NOTICE("[src] are fully operational!")
else
. += SPAN_WARNING("It is missing a pyroclastic anomaly core.")
/obj/item/clothing/gloves/color/black/pyro_claws/item_action_slot_check(slot)
if(slot == ITEM_SLOT_GLOVES)
return TRUE
/obj/item/clothing/gloves/color/black/pyro_claws/ui_action_click(mob/user)
if(!core)
to_chat(user, SPAN_NOTICE("[src] has no core to power it!"))
return
if(on_cooldown)
to_chat(user, SPAN_NOTICE("[src] is on cooldown!"))
return
if((user.l_hand && !user.drop_l_hand()) || (user.r_hand && !user.drop_r_hand()))
to_chat(user, SPAN_NOTICE("[src] are unable to deploy the blades with the items in your hands!"))
return
var/obj/item/W = new /obj/item/pyro_claws
user.visible_message(
SPAN_WARNING("[user] deploys [W] from [user.p_their()] wrists in a shower of sparks!"),
SPAN_NOTICE("You deploy [W] from your wrists!"),
SPAN_HEAR("You hear the shower of sparks!")
)
user.put_in_hands(W)
on_cooldown = TRUE
set_nodrop(TRUE, user)
addtimer(CALLBACK(src, PROC_REF(reboot)), 2 MINUTES)
if(world.time > next_spark_time)
do_sparks(rand(1,6), 1, loc)
next_spark_time = world.time + 0.8 SECONDS
/obj/item/clothing/gloves/color/black/pyro_claws/wirecutter_act(mob/living/user, obj/item/I)
return
/obj/item/clothing/gloves/color/black/pyro_claws/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(!istype(used, /obj/item/assembly/signaler/anomaly/pyro))
return ..()
if(core)
to_chat(user, SPAN_NOTICE("[src] already has a [used]!"))
return ITEM_INTERACT_COMPLETE
if(!user.drop_item())
to_chat(user, SPAN_WARNING("[used] is stuck to your hand!"))
return ITEM_INTERACT_COMPLETE
to_chat(user, SPAN_NOTICE("You insert [used] into [src], and [src] starts to warm up."))
used.forceMove(src)
core = used
return ITEM_INTERACT_COMPLETE
/obj/item/clothing/gloves/color/black/pyro_claws/proc/reboot()
on_cooldown = FALSE
set_nodrop(FALSE, loc)
atom_say("Internal plasma canisters recharged. Gloves sufficiently cooled")
/obj/item/bostaff
name = "bo staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate."
icon = 'icons/obj/weapons/melee.dmi'
icon_state = "bostaff0"
base_icon_state = "bostaff"
lefthand_file = 'icons/mob/inhands/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/staves_righthand.dmi'
force = 10
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
throwforce = 20
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
new_attack_chain = TRUE
/obj/item/bostaff/Initialize(mapload)
. = ..()
AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = ALL_ATTACK_TYPES)
AddComponent(/datum/component/two_handed, force_wielded = 24, force_unwielded = force, icon_wielded = "[base_icon_state]1")
/obj/item/bostaff/update_icon_state()
icon_state = "[base_icon_state]0"
/obj/item/bostaff/pre_attack(atom/target, mob/living/user, params)
add_fingerprint(user)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, SPAN_WARNING("You feel violence is not the answer."))
return FINISH_ATTACK
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
to_chat(user, SPAN_WARNING("You club yourself over the head with [src]."))
user.do_attack_animation(target)
user.Weaken(6 SECONDS)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2 * force, BRUTE, "head")
else
user.take_organ_damage(2 * force)
return FINISH_ATTACK
if(isrobot(target))
return ..()
if(!isliving(target))
return ..()
var/mob/living/carbon/carbon_target = target
if(carbon_target.stat)
to_chat(user, SPAN_WARNING("It would be dishonorable to attack a foe while [carbon_target.p_they()] cannot retaliate."))
return FINISH_ATTACK
if(user.a_intent != INTENT_DISARM)
return ..()
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
if(!ishuman(target))
return ..()
var/mob/living/carbon/human/human_target = target
var/list/fluffmessages = list("[user] clubs [human_target] with [src]!",
"[user] smacks [human_target] with the butt of [src]!",
"[user] broadsides [human_target] with [src]!",
"[user] smashes [human_target]'s head with [src]!",
"[user] beats [human_target] with front of [src]!",
"[user] twirls and slams [human_target] with [src]!")
human_target.visible_message(
SPAN_WARNING("[pick(fluffmessages)]"),
SPAN_USERDANGER("[pick(fluffmessages)]"),
SPAN_DANGER("You hear someone being attacked with a weapon!")
)
user.do_attack_animation(target)
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, TRUE, -1)
human_target.apply_damage(rand(13, 20), STAMINA)
if(prob(10))
human_target.visible_message(
SPAN_WARNING("[human_target] collapses!"),
SPAN_USERDANGER("Your legs give out!"),
SPAN_HEAR("You hear a body fall to the ground!")
)
human_target.Weaken(8 SECONDS)
if(human_target.getStaminaLoss() && !human_target.IsSleeping())
var/total_health = (human_target.health - human_target.getStaminaLoss())
if(total_health <= HEALTH_THRESHOLD_CRIT && !human_target.stat)
human_target.visible_message(
SPAN_WARNING("[user] delivers a heavy hit to [human_target]'s head, knocking [human_target.p_them()] out cold!"),
SPAN_USERDANGER("[user] knocks you unconscious!"),
SPAN_HEAR("You hear a body fall to the ground!")
)
human_target.SetSleeping(60 SECONDS)
human_target.adjustBrainLoss(25)
return FINISH_ATTACK
/obj/item/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)
if(HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
return FALSE
@@ -0,0 +1,169 @@
/// Max number of atoms a broom can sweep at once.
#define BROOM_PUSH_LIMIT 20
/obj/item/push_broom
name = "push broom"
desc = "This is my BROOMSTICK! It can be used manually or braced with two hands to sweep items as you move. It has a telescopic handle for compact storage."
icon = 'icons/obj/janitor.dmi'
icon_state = "broom0"
base_icon_state = "broom"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
force = 8
throwforce = 10
throw_speed = 3
attack_verb = list("swept", "brushed off", "bludgeoned", "whacked")
resistance_flags = FLAMMABLE
new_attack_chain = TRUE
/obj/item/push_broom/Initialize(mapload)
. = ..()
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.75, \
_parryable_attack_types = MELEE_ATTACK, \
_parry_cooldown = (7 / 3) SECONDS, \
_requires_two_hands = TRUE)
AddComponent(/datum/component/two_handed, \
force_wielded = 12, \
force_unwielded = force, \
icon_wielded = "[base_icon_state]1", \
wield_callback = CALLBACK(src, PROC_REF(wield)), \
unwield_callback = CALLBACK(src, PROC_REF(unwield)))
/obj/item/push_broom/update_icon_state()
icon_state = "[base_icon_state]0"
/obj/item/push_broom/proc/wield(obj/item/source, mob/user)
to_chat(user, SPAN_NOTICE("You brace [src] against the ground in a firm sweeping stance."))
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(sweep))
/obj/item/push_broom/proc/unwield(obj/item/source, mob/user)
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
/obj/item/push_broom/interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(isturf(target) || isitem(target))
return ..()
if(user.a_intent != INTENT_HELP)
return ..()
sweep(user, target, FALSE)
add_fingerprint(user)
return ITEM_INTERACT_COMPLETE
/obj/item/push_broom/proc/sweep(mob/user, atom/A, moving = TRUE)
SIGNAL_HANDLER
var/turf/current_item_loc = moving ? user.loc : (isturf(A) ? A : A.loc)
if(!isturf(current_item_loc))
return
var/turf/new_item_loc = get_step(current_item_loc, user.dir)
var/obj/machinery/disposal/target_bin = locate(/obj/machinery/disposal) in new_item_loc.contents
var/obj/structure/janitorialcart/jani_cart = locate(/obj/structure/janitorialcart) in new_item_loc.contents
var/obj/vehicle/janicart/jani_vehicle = locate(/obj/vehicle/janicart) in new_item_loc.contents
var/trash_amount = 1
for(var/obj/item/garbage in current_item_loc.contents)
if(garbage.anchored)
continue
var/obj/item/storage/bag/trash/bag = jani_vehicle?.mybag || jani_cart?.my_bag
var/obj/trashed_into
if(bag?.can_be_inserted(garbage, TRUE))
bag.handle_item_insertion(garbage, user, TRUE)
trashed_into = bag
else if(target_bin)
move_into_storage(user, target_bin, garbage)
trashed_into = target_bin
else
garbage.Move(new_item_loc, user.dir)
if(trashed_into)
to_chat(user, SPAN_NOTICE("You sweep the pile of garbage into [trashed_into]."))
trash_amount++
if(trash_amount > BROOM_PUSH_LIMIT)
break
if(trash_amount > 1)
playsound(loc, 'sound/weapons/sweeping.ogg', 70, TRUE, -1)
/obj/item/push_broom/proc/move_into_storage(mob/user, obj/storage, obj/trash)
trash.forceMove(storage)
storage.update_icon()
/obj/item/push_broom/traitor
name = "titanium push broom"
desc = "This is my BROOMSTICK! All of the functionality of a normal broom, but at least half again more robust."
attack_verb = list("smashed", "slammed", "whacked", "thwacked", "swept")
force = 10
/obj/item/push_broom/traitor/Initialize(mapload)
. = ..()
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.25, \
_parryable_attack_types = ALL_ATTACK_TYPES, \
_parry_cooldown = (4 / 3) SECONDS, \
_requires_two_hands = TRUE) // 0.3333 seconds of parry cooldown for 75% uptime.
// Parent component handles this.
AddComponent(/datum/component/two_handed, force_wielded = 25, force_unwielded = force)
/obj/item/push_broom/traitor/examine(mob/user)
. = ..()
if(isAntag(user))
. += SPAN_WARNING("When wielded, the broom has different effects depending on your intent, similar to a martial art. \
Help intent will sweep foes away from you, disarm intent sweeps their legs from under them, grab intent confuses \
and minorly fatigues them, and harm intent hits them normally.")
/obj/item/push_broom/traitor/interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(!HAS_TRAIT(src, TRAIT_WIELDED) || !ishuman(target))
return ..()
var/mob/living/carbon/human/human_target = target
switch(user.a_intent)
if(INTENT_HELP)
human_target.visible_message(
SPAN_DANGER("[user] sweeps [human_target] away!"),
SPAN_USERDANGER("[user] sweeps you away!"),
SPAN_HEAR("You hear sweeping.")
)
user.do_attack_animation(human_target, ATTACK_EFFECT_BOOP)
playsound(loc, 'sound/weapons/sweeping.ogg', 70, TRUE, -1)
var/atom/throw_target = get_edge_target_turf(human_target, get_dir(src, get_step_away(human_target, src)))
human_target.throw_at(throw_target, 3, 1)
add_attack_logs(user, human_target, "Swept away with titanium push broom", ATKLOG_ALL)
return ITEM_INTERACT_COMPLETE
if(INTENT_DISARM)
if(human_target.stat || IS_HORIZONTAL(human_target))
return ..()
human_target.visible_message(
SPAN_DANGER("[user] sweeps [human_target]'s legs out from under [human_target.p_them()]!"),
SPAN_USERDANGER("[user] sweeps your legs out from under you!"),
SPAN_HEAR("You hear sweeping.")
)
user.do_attack_animation(human_target, ATTACK_EFFECT_KICK)
playsound(get_turf(user), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
human_target.apply_damage(5, BRUTE)
human_target.KnockDown(4 SECONDS)
add_attack_logs(user, human_target, "Leg swept with titanium push broom", ATKLOG_ALL)
return ITEM_INTERACT_COMPLETE
if(INTENT_GRAB)
human_target.visible_message(
SPAN_DANGER("[user] smacks [human_target] with the brush of [user.p_their()] broom!"),
SPAN_USERDANGER("[user] smacks you with the brush of [user.p_their()] broom!"),
SPAN_HEAR("You hear a smacking noise.")
)
user.do_attack_animation(human_target, ATTACK_EFFECT_DISARM)
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 50, TRUE, -1)
human_target.AdjustConfused(4 SECONDS, 0, 4 SECONDS) // No stacking infinitely.
human_target.apply_damage(15, STAMINA)
add_attack_logs(user, human_target, "Swept with the brush of the titanium push broom", ATKLOG_ALL)
return ITEM_INTERACT_COMPLETE
if(INTENT_HARM)
return ..()
#undef BROOM_PUSH_LIMIT
@@ -0,0 +1,320 @@
/// Spears.
/obj/item/spear
name = "spear"
desc = "A haphazardly-constructed yet still deadly weapon of ancient design."
icon = 'icons/obj/weapons/spears.dmi'
base_icon_state = "spearglass"
icon_state = "spearglass0"
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
force = 10
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
var/force_unwielded = 10
var/force_wielded = 18
throwforce = 20
throw_speed = 4
armor_penetration_flat = 5
materials = list(MAT_METAL = 1150, MAT_GLASS = 2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
sharp = TRUE
no_spin_thrown = TRUE
var/obj/item/grenade/explosive = null
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 50, ACID = 30)
needs_permit = TRUE
new_attack_chain = TRUE
/obj/item/spear/Initialize(mapload)
. = ..()
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.7, \
_parryable_attack_types = MELEE_ATTACK, \
_parry_cooldown = (10 / 3) SECONDS, \
_requires_two_hands = TRUE) // 2.3333 seconds of parry cooldown for 30% uptime.
AddComponent(/datum/component/two_handed, \
force_wielded = force_wielded, \
force_unwielded = force_unwielded, \
icon_wielded = "[base_icon_state]1")
/obj/item/spear/update_icon_state()
icon_state = "[base_icon_state]0"
/obj/item/spear/proc/add_plasmaglass()
// Re-add the component to reset the stats.
force_wielded = 19
force_unwielded = 11
throwforce = 21
base_icon_state = "spearplasma"
AddComponent(/datum/component/two_handed, \
force_wielded = force_wielded, \
force_unwielded = force_unwielded, \
icon_wielded = "[base_icon_state]1")
update_icon()
/obj/item/spear/CheckParts(list/parts_list)
var/obj/item/shard/tip = locate() in parts_list
if(istype(tip, /obj/item/shard/plasma))
// Re-add the component to reset the stats.
add_plasmaglass()
update_icon()
qdel(tip)
..()
/obj/item/spear/after_attack(mob/living/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return FINISH_ATTACK
if(explosive && HAS_TRAIT(src, TRAIT_WIELDED))
explosive.forceMove(target)
explosive.prime()
qdel(src)
return FINISH_ATTACK
return ..()
/obj/item/spear/throw_impact(atom/target)
. = ..()
if(explosive)
explosive.prime()
qdel(src)
/// Blatant imitation of spear, but made out of bone. Not valid for explosive modification.
/obj/item/spear/bonespear
name = "bone spear"
desc = "A haphazardly-constructed yet still deadly weapon. The pinnacle of modern technology."
base_icon_state = "bone_spear"
icon_state = "bone_spear0"
force = 11
force_unwielded = 11
force_wielded = 20 // I have no idea how to balance.
throwforce = 22
armor_penetration_percentage = 15 // Enhanced armor piercing.
// Blatant imitation of spear, but all natural. Also not valid for explosive modification.
/obj/item/spear/bamboo
name = "bamboo spear"
desc = "A haphazardly-constructed bamboo stick with a sharpened tip, ready to poke holes into unsuspecting people."
base_icon_state = "bamboo_spear"
icon_state = "bamboo_spear0"
throwforce = 22
// GREY TIDE.
/obj/item/spear/grey_tide
name = "\improper Grey Tide"
desc = "Recovered from the aftermath of a revolt aboard Defense Outpost Theta Aegis, in which a seemingly endless tide of Assistants caused heavy casualities among Nanotrasen military forces."
force_unwielded = 15
force_wielded = 25
attack_verb = list("gored")
/obj/item/spear/grey_tide/after_attack(mob/living/target, mob/living/user, proximity_flag, click_parameters)
if(!proximity_flag)
return FINISH_ATTACK
user.faction |= "greytide(\ref[user])"
if(!isliving(target))
return ..()
if(istype (target, /mob/living/simple_animal/hostile/illusion))
return FINISH_ATTACK
if(!target.stat && prob(50))
var/mob/living/simple_animal/hostile/illusion/M = new(user.loc)
M.faction = user.faction.Copy()
M.attack_sound = hitsound
M.Copy_Parent(user, 100, user.health/2.5, 12, 30)
M.GiveTarget(target)
return FINISH_ATTACK
// Putting heads on spears.
/obj/item/spear/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(!istype(used, /obj/item/organ/external/head))
return ..()
if(!(user.unequip(src) && user.drop_item()))
to_chat(user, SPAN_WARNING("You can't attach [src] to [used] when one is stuck to your hand!"))
return ITEM_INTERACT_COMPLETE
to_chat(user, SPAN_NOTICE("You stick [used] onto the spear and stand it upright on the ground."))
var/obj/structure/headspear/head_spear = new /obj/structure/headspear(get_turf(src))
var/matrix/transform_matrix = matrix()
used.transform = transform_matrix
var/image/spear_overlays = image(used.icon, used.icon_state)
spear_overlays.overlays = used.overlays.Copy()
head_spear.overlays += spear_overlays
used.forceMove(head_spear)
head_spear.mounted_head = used
forceMove(head_spear)
head_spear.contained_spear = src
head_spear.add_fingerprint(user)
return ITEM_INTERACT_COMPLETE
/obj/structure/headspear
name = "head on a spear"
desc = "How barbaric."
icon_state = "headspear"
anchored = TRUE
var/obj/item/organ/external/head/mounted_head = null
var/obj/item/spear/contained_spear = null
/obj/structure/headspear/Destroy()
QDEL_NULL(mounted_head)
QDEL_NULL(contained_spear)
return ..()
/obj/structure/headspear/attack_hand(mob/living/user)
user.visible_message(
SPAN_WARNING("[user] kicks over [src]!"),
SPAN_DANGER("You kick down [src]!"),
SPAN_HEAR("You hear a sharp kick and a head rolling!")
)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
var/turf/T = get_turf(src)
if(contained_spear)
contained_spear.forceMove(T)
contained_spear = null
if(mounted_head)
mounted_head.forceMove(T)
mounted_head = null
qdel(src)
/// Supermatter Halberd, used by Oblivion Enforcers.
/obj/item/supermatter_halberd
name = "supermatter halberd"
desc = "The revered weapon of Oblivion Enforcers, used to enforce the Order's will."
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/magical_weapons.dmi'
icon_state = "smhalberd0"
base_icon_state = "smhalberd"
force = 5
sharp = TRUE
damtype = BURN
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
throwforce = 15
toolspeed = 0.25
attack_verb = list("enlightened", "enforced", "cleaved", "stabbed", "whacked")
hitsound = 'sound/weapons/bladeslice.ogg'
resistance_flags = FIRE_PROOF
var/static/list/obliteration_targets = list(/turf/simulated/wall, /obj/machinery/door/airlock)
/// Whether we'll knockdown on hit
var/charged = TRUE
new_attack_chain = TRUE
/obj/item/supermatter_halberd/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SUPERMATTER_IMMUNE, ROUNDSTART_TRAIT) // So it can't be dusted by the SM.
AddComponent(/datum/component/forces_doors_open)
AddComponent(/datum/component/parry, \
_stamina_constant = 2, \
_stamina_coefficient = 0.25, \
_parryable_attack_types = ALL_ATTACK_TYPES, \
_parry_cooldown = (4 / 3) SECONDS, \
_requires_two_hands = TRUE) // 0.3333 seconds of parry cooldown for 75% uptime.
AddComponent(/datum/component/two_handed, \
force_wielded = 40, \
force_unwielded = force, \
icon_wielded = "[base_icon_state]1")
/obj/item/supermatter_halberd/update_icon_state()
icon_state = "[base_icon_state]0"
return ..()
/obj/item/supermatter_halberd/interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
// Dusting dead people.
if(isliving(target))
var/mob/living/living_target = target
if(living_target.stat != DEAD)
return ..() // Attack as normal.
visible_message(SPAN_DANGER("[user] raises [src] high, ready to bring it down on [living_target]!"))
if(!do_after(user, 1 SECONDS, TRUE, living_target))
to_chat(user, SPAN_NOTICE("You lower [src]. There'll be time to obliterate them later..."))
return ITEM_INTERACT_COMPLETE
visible_message(
SPAN_DANGER("[user] brings down [src], obliterating [living_target] with a heavy blow!"),
SPAN_DANGER("A deafening resonance fills the air, followed by silence...")
)
user.do_attack_animation(living_target)
playsound(loc, 'sound/effects/supermatter.ogg', 50, TRUE)
living_target.dust()
return ITEM_INTERACT_COMPLETE
// Walls and airlock obliteration logic.
if(!is_type_in_list(target, obliteration_targets))
return ..()
if(istype(target, /turf/simulated/wall/indestructible))
return ..()
user.visible_message(
SPAN_DANGER("[user] embeds [src] into [target] and starts to obliterate it!"),
SPAN_NOTICE("You embed [src] into [target] and start to obliterate it."),
SPAN_DANGER("You hear something being struck by a weapon!") // Default deaf message.
)
user.do_attack_animation(target)
playsound(loc, hitsound, 50, TRUE)
var/obj/effect/temp_visual/obliteration_rays/rays = new(get_turf(target))
if(!do_after(user, 5 SECONDS * toolspeed, target = target))
user.visible_message(
SPAN_NOTICE("[user] removes [src] from [target]."),
SPAN_NOTICE("You remove [src] from [target]. There'll be time to obliterate it later...")
)
qdel(rays)
return ITEM_INTERACT_COMPLETE
user.visible_message(
SPAN_DANGER("[user] obliterates [target]!"),
SPAN_NOTICE("You obliterate [target]."),
SPAN_DANGER("A deafening resonance fills the air, followed by silence...")
)
new /obj/effect/temp_visual/obliteration(target, target)
playsound(loc, 'sound/effects/supermatter.ogg', 25, TRUE)
if(iswallturf(target))
var/turf/target_turf = target
target_turf.ChangeTurf(/turf/simulated/floor/plating)
return ITEM_INTERACT_COMPLETE
if(istype(target, /obj/machinery/door/airlock))
qdel(target)
return ITEM_INTERACT_COMPLETE
qdel(rays)
return ITEM_INTERACT_COMPLETE
/obj/item/supermatter_halberd/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return FINISH_ATTACK
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
if(isliving(target) && charged)
var/mob/living/living_target = target
playsound(loc, 'sound/magic/lightningbolt.ogg', 5, TRUE)
living_target.visible_message(
SPAN_DANGER("[src] flares with energy and shocks [living_target]!"),
SPAN_USERDANGER("You're shocked by [src]!"),
SPAN_HEAR("You hear shocking!")
)
living_target.KnockDown(4 SECONDS)
do_sparks(3, FALSE, src)
charged = FALSE
addtimer(CALLBACK(src, PROC_REF(recharge)), 4 SECONDS)
return FINISH_ATTACK
// Same behavior as a fireaxe for windows.
if(istype(target, /obj/structure/window) || istype(target, /obj/structure/grille))
var/obj/structure/target_structure = target
target_structure.obj_destruction("fireaxe")
return FINISH_ATTACK
/obj/item/supermatter_halberd/proc/recharge()
charged = TRUE
playsound(loc, 'sound/machines/sm/accent/normal/1.ogg', 25, TRUE)
File diff suppressed because it is too large Load Diff