From 75202c986e4c2af780b160f7d918cd3a13ed3d2f Mon Sep 17 00:00:00 2001
From: kyunkyunkyun <120701975+kyunkyunkyun@users.noreply.github.com>
Date: Wed, 23 Jul 2025 22:32:47 +0500
Subject: [PATCH] Fix and refactor of chainsaws (#28893)
* code improvements
* linters
* oh
* Update spellblade.dm
* Update spellblade.dm
* Update melee.dm
* melee's death
* update paths
* Update code/game/objects/items/weapons/melee/melee.dm
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: kyunkyunkyun <120701975+kyunkyunkyun@users.noreply.github.com>
* fix icon states
---------
Signed-off-by: kyunkyunkyun <120701975+kyunkyunkyun@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
---
code/datums/actions/item_action.dm | 3 -
code/datums/uplink_items/uplink_general.dm | 2 +-
code/game/objects/effects/mines.dm | 3 +-
code/game/objects/items/toys.dm | 12 +-
.../objects/items/weapons/holy_weapons.dm | 2 +-
.../game/objects/items/weapons/melee/melee.dm | 321 +++++++++++
.../objects/items/weapons/melee/melee_misc.dm | 520 +-----------------
.../objects/items/weapons/melee/spellblade.dm | 288 ++++++++++
code/game/objects/items/weapons/twohanded.dm | 141 -----
.../changeling/powers/mutations.dm | 2 +-
.../hallucinations/effects/moderate.dm | 2 +-
code/modules/surgery/encased.dm | 2 -
code/modules/surgery/generic.dm | 2 -
code/modules/surgery/organs_internal.dm | 5 +-
code/tests/test_anti_drop.dm | 2 +-
icons/mob/inhands/weapons_lefthand.dmi | Bin 74465 -> 70961 bytes
icons/mob/inhands/weapons_righthand.dmi | Bin 73714 -> 68688 bytes
icons/obj/weapons/melee.dmi | Bin 15968 -> 15961 bytes
paradise.dme | 2 +
.../Scripts/28893_chainsaw_refactor.txt | 1 +
20 files changed, 628 insertions(+), 682 deletions(-)
create mode 100644 code/game/objects/items/weapons/melee/melee.dm
create mode 100644 code/game/objects/items/weapons/melee/spellblade.dm
create mode 100644 tools/UpdatePaths/Scripts/28893_chainsaw_refactor.txt
diff --git a/code/datums/actions/item_action.dm b/code/datums/actions/item_action.dm
index 7dccc057642..3150dff47b5 100644
--- a/code/datums/actions/item_action.dm
+++ b/code/datums/actions/item_action.dm
@@ -55,9 +55,6 @@
/datum/action/item_action/toggle_firemode
name = "Toggle Firemode"
-/datum/action/item_action/startchainsaw
- name = "Pull The Starting Cord"
-
/datum/action/item_action/print_report
name = "Print Report"
diff --git a/code/datums/uplink_items/uplink_general.dm b/code/datums/uplink_items/uplink_general.dm
index 446c485c18f..88553cc4976 100644
--- a/code/datums/uplink_items/uplink_general.dm
+++ b/code/datums/uplink_items/uplink_general.dm
@@ -240,7 +240,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Chainsaw"
desc = "A high powered chainsaw for cutting up ...you know...."
reference = "CH"
- item = /obj/item/butcher_chainsaw
+ item = /obj/item/chainsaw/syndie
cost = 65
surplus = 0 // This has caused major problems with un-needed chainsaw massacres. Bwoink bait.
excludefrom = list(UPLINK_TYPE_NUCLEAR)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 328f2781ab3..d610ea2c3e4 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -149,7 +149,8 @@
victim.drop_l_hand()
victim.drop_r_hand()
victim.put_in_hands(chainsaw)
- chainsaw.attack_self__legacy__attackchain(victim)
+ chainsaw.activate_self(victim)
+ victim.regenerate_icons()
victim.reagents.add_reagent("adminordrazine", 25)
victim.flash_screen_color(red_splash, 10)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index bf58a5abf28..3c88cdb26ee 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1622,6 +1622,7 @@
name = "cursed russian revolver"
desc = "To play with this revolver requires wagering your very soul."
cursed_shot = TRUE
+
/*
* Rubber Chainsaw
*/
@@ -1631,21 +1632,16 @@
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/melee.dmi'
- icon_state = "chainsaw0"
+ icon_state = "chainsaw"
base_icon_state = "chainsaw"
- force = 0
- throwforce = 0
- throw_speed = 4
- throw_range = 20
attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
/obj/item/toy/chainsaw/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/two_handed, wieldsound = 'sound/weapons/chainsawstart.ogg', icon_wielded = "[base_icon_state]1")
-
+ AddComponent(/datum/component/two_handed, wieldsound = 'sound/weapons/chainsawstart.ogg', icon_wielded = "[base_icon_state]_on")
/obj/item/toy/chainsaw/update_icon_state()
- icon_state = "[base_icon_state]0"
+ icon_state = base_icon_state
/*
* Cat Toy
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index f6e550203dc..5148b6696fa 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -398,7 +398,7 @@
lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
icon = 'icons/obj/weapons/melee.dmi'
- icon_state = "chainsaw1"
+ icon_state = "chainsaw_on"
item_state = "mounted_chainsaw"
w_class = WEIGHT_CLASS_HUGE
flags = NODROP | ABSTRACT
diff --git a/code/game/objects/items/weapons/melee/melee.dm b/code/game/objects/items/weapons/melee/melee.dm
new file mode 100644
index 00000000000..282a11db1b6
--- /dev/null
+++ b/code/game/objects/items/weapons/melee/melee.dm
@@ -0,0 +1,321 @@
+/obj/item/melee
+ icon = 'icons/obj/weapons/melee.dmi'
+ lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
+ needs_permit = TRUE
+
+// MARK: CAPTAIN'S SABER
+/obj/item/melee/saber
+ name = "captain's saber"
+ desc = "An elegant weapon, for a more civilized age."
+ icon_state = "saber"
+ item_state = "saber"
+ flags = CONDUCT
+ force = 15
+ throwforce = 10
+ w_class = WEIGHT_CLASS_BULKY
+ armour_penetration_percentage = 75
+ sharp = TRUE
+ origin_tech = null
+ attack_verb = list("lunged at", "stabbed")
+ hitsound = 'sound/weapons/rapierhit.ogg'
+ materials = list(MAT_METAL = 1000)
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF // Theft targets should be hard to destroy
+ // values for slapping
+ var/slap_sound = 'sound/effects/woodhit.ogg'
+ COOLDOWN_DECLARE(slap_cooldown)
+
+/obj/item/melee/saber/examine(mob/user)
+ . = ..()
+ . += "The blade looks very well-suited for piercing armour."
+
+/obj/item/melee/saber/examine_more(mob/user)
+ . = ..()
+ . += "Swords are a traditional ceremonial weapon carried by commanding officers of many armies and navies, even long after firearms and laserarms rendered them obsolete. \
+ Despite having no roots in such traditions, Nanotrasen participates in them, as these trappings of old tradition help to promote the air of authority the company wishes for its captains to possess."
+ . += ""
+ . += "Whilst not intended to actually be used in combat, the ceremonial blades issued by Nanotrasen are in-fact quite functional, \
+ able to both inflict grievous wounds on aggressors that get too close, whilst also elegantly parrying their blows (assuming the wielder is skilled with the blade). \
+ The sharp edge is adept at hacking unarmored targets, whilst the rigid tip is also quite effective at at defeating even modern body armor with thrusting attacks, as modern armor is generally designed to defeat ballistic and laser weapons rather than swords..."
+
+/obj/item/melee/saber/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS)
+ AddElement(/datum/element/high_value_item)
+
+/obj/item/melee/saber/attack__legacy__attackchain(mob/living/target, mob/living/user)
+ if(user.a_intent != INTENT_HELP || !ishuman(target))
+ return ..()
+ if(!COOLDOWN_FINISHED(src, slap_cooldown))
+ return
+ var/mob/living/carbon/human/H = target
+ if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
+ user.visible_message("[user] accidentally slaps [user.p_themselves()] with [src]!", \
+ "You accidentally slap yourself with [src]!")
+ slap(user, user)
+ else
+ user.visible_message("[user] slaps [H] with the flat of the blade!", \
+ "You slap [H] with the flat of the blade!")
+ slap(target, user)
+
+/obj/item/melee/saber/proc/slap(mob/living/carbon/human/target, mob/living/user)
+ user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
+ playsound(loc, slap_sound, 50, TRUE, -1)
+ target.AdjustConfused(4 SECONDS, 0, 4 SECONDS)
+ target.apply_damage(10, STAMINA)
+ add_attack_logs(user, target, "Slapped by [src]", ATKLOG_ALL)
+ COOLDOWN_START(src, slap_cooldown, 4 SECONDS)
+
+/obj/item/melee/saber/suicide_act(mob/user)
+ user.visible_message(pick("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!", \
+ "[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return BRUTELOSS
+
+// MARK: SNAKESFANG
+/obj/item/melee/snakesfang
+ name = "snakesfang"
+ desc = "A uniquely curved, black and red sword. Extra-edgy and cutting-edge."
+ icon_state = "snakesfang"
+ item_state = "snakesfang"
+ flags = CONDUCT
+ force = 25
+ throwforce = 10
+ w_class = WEIGHT_CLASS_BULKY
+ sharp = TRUE
+ origin_tech = "combat=6;syndicate=3"
+ attack_verb = list("slashed", "sliced", "chopped")
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ materials = list(MAT_METAL = 1000)
+
+/obj/item/melee/snakesfang/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS)
+
+/obj/item/melee/snakesfang/examine_more(mob/user)
+ . = ..()
+ . += "A uniquely curved, black and red sword. Extra-edgy and cutting-edge."
+ . += ""
+ . += "The MK-IV Enhanced Combat Blade, more colloquially known as the ‘Snakesfang’, is a vicious yet stylish weapon designed \
+ by a relatively unknown weapons forge with known ties to the Syndicate. With a wide, curved blade and dual points \
+ resembling the fangs of the organization’s serpent motif, the Snakesfang is a statement like no other."
+ . += ""
+ . += "While the benefits of its unique design are dubious at best, the Snakesfang is undoubtedly a perilous weapon, with a hardened \
+ plastitanium edge that can cause untold harm to a soft target. In the right hands, it can be a terrifying weapon to behold, \
+ and it’s said that blood runs down the blade in just the right way, to drip artfully from the twin ‘fangs’ at its apex."
+
+// MARK: BREACH CLEAVER
+/obj/item/melee/breach_cleaver
+ name = "breach cleaver"
+ desc = "Massive, heavy, and utterly impractical. This sharpened chunk of steel is too big and too heavy to be called a sword."
+ base_icon_state = "breach_cleaver"
+ icon_state = "breach_cleaver0"
+ flags = CONDUCT
+ force = 5
+ throwforce = 5
+ armour_penetration_flat = 30
+ w_class = WEIGHT_CLASS_BULKY
+ sharp = TRUE
+ origin_tech = "combat=6;syndicate=5"
+ attack_verb = list("slashed", "cleaved", "chopped")
+ hitsound = 'sound/weapons/swordhitheavy.ogg'
+ materials = list(MAT_METAL = 2000)
+ /// How much damage the sword does when wielded
+ var/force_wield = 40
+
+/obj/item/melee/breach_cleaver/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/two_handed, force_wielded = force_wield, force_unwielded = force, icon_wielded = "[base_icon_state]1", wield_callback = CALLBACK(src, PROC_REF(wield)), unwield_callback = CALLBACK(src, PROC_REF(unwield)))
+ AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS)
+
+/obj/item/melee/breach_cleaver/examine(mob/user)
+ . = ..()
+ if(isAntag(user))
+ . += "When wielded, this blade has different effects depending on your intent, similar to a martial art. \
+ Help intent will strike with the flat, dealing stamina, disarm intent forces them away, grab intent knocks down the target, \
+ and harm intent deals heavy damage."
+
+/obj/item/melee/breach_cleaver/examine_more(mob/user)
+ . = ..()
+ . += "Massive, heavy, and utterly impractical. This sharpened chunk of steel is too big and too heavy to be called a sword."
+ . += ""
+ . += "The Unathi Breach Cleaver is a weapon the scaled, warlike race favours for its impressive weight and myriad combat applications. \
+ The pinnacle of Moghes' combat technology, it combines all of this knowledge into a massive, heavy slab of alloyed metal that most \
+ species find difficult to lift, let alone use in any sort of fight."
+ . += ""
+ . += "Actually a little lightweight for its size, a Breach Cleaver is unmatched in combat utility as a weapon, a tool for getting into\
+ places and as a slab of armour for the wielder. The leather of the Kar'oche beast, a predator native to Moghes, binds the hilt, \
+ allowing it to be gripped securely by its warrior. The wide blade is often etched with scenes depicting military victories or great hunts."
+
+/obj/item/melee/breach_cleaver/update_icon_state()
+ icon_state = "[base_icon_state]0"
+
+/obj/item/melee/breach_cleaver/proc/wield(obj/item/source, mob/living/carbon/human/user)
+ to_chat(user, "You heave [src] up in both hands.")
+ user.apply_status_effect(STATUS_EFFECT_BREACH_AND_CLEAVE)
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/melee/breach_cleaver/proc/unwield(obj/item/source, mob/living/carbon/human/user)
+ user.remove_status_effect(STATUS_EFFECT_BREACH_AND_CLEAVE)
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/melee/breach_cleaver/attack_obj__legacy__attackchain(obj/O, mob/living/user, params)
+ if(!HAS_TRAIT(src, TRAIT_WIELDED)) // Only works good when wielded
+ return ..()
+ if(!ismachinery(O) && !isstructure(O)) // This sword hates doors
+ return ..()
+ if(SEND_SIGNAL(src, COMSIG_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
+ return
+ if(flags & (NOBLUDGEON))
+ return
+ var/mob/living/carbon/human/H = user
+ H.changeNext_move(CLICK_CD_MELEE)
+ H.do_attack_animation(O)
+ H.visible_message("[H] has hit [O] with [src]!", "You hit [O] with [src]!")
+ var/damage = force_wield
+ damage += H.physiology.melee_bonus
+ O.take_damage(damage * 3, BRUTE, MELEE, TRUE, get_dir(src, H), 30) // Multiplied to do big damage to doors, closets, windows, and machines, but normal damage to mobs.
+
+/obj/item/melee/breach_cleaver/attack__legacy__attackchain(mob/target, mob/living/user)
+ if(!HAS_TRAIT(src, TRAIT_WIELDED) || !ishuman(target))
+ return ..()
+
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/external/targetlimb = H.get_organ(ran_zone(user.zone_selected))
+
+ switch(user.a_intent)
+ if(INTENT_HELP) // Stamina damage
+ H.visible_message("[user] slams [H] with the flat of the blade!", \
+ "[user] slams you with the flat of the blade!", \
+ "You hear a thud.")
+ user.do_attack_animation(H, ATTACK_EFFECT_DISARM)
+ playsound(loc, 'sound/weapons/swordhit.ogg', 50, TRUE, -1)
+ H.AdjustConfused(4 SECONDS, 0, 4 SECONDS)
+ H.apply_damage(40, STAMINA, targetlimb, H.run_armor_check(targetlimb, MELEE))
+ add_attack_logs(user, H, "Slammed by a breach cleaver. (Help intent, Stamina)", ATKLOG_ALL)
+
+ if(INTENT_DISARM) // Slams away
+ if(H.stat != CONSCIOUS || IS_HORIZONTAL(H))
+ return ..()
+
+ H.visible_message("[user] smashes [H] with the blade's tip!", \
+ "[user] smashes you with the blade's tip!", \
+ "You hear crushing.")
+
+ user.do_attack_animation(H, ATTACK_EFFECT_KICK)
+ playsound(get_turf(user), 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE, -1)
+ H.apply_damage(25, BRUTE, targetlimb, H.run_armor_check(targetlimb, MELEE))
+ var/atom/throw_target = get_edge_target_turf(H, user.dir, TRUE)
+ H.throw_at(throw_target, 4, 1)
+ add_attack_logs(user, H, "Smashed away by a breach cleaver. (Disarm intent, Knockback)", ATKLOG_ALL)
+
+ if(INTENT_GRAB) // Knocks down
+ H.visible_message("[user] cleaves [H] with an overhead strike!", \
+ "[user] cleaves you with an overhead strike!", \
+ "You hear a chopping noise.")
+
+ user.do_attack_animation(H, ATTACK_EFFECT_DISARM)
+ playsound(get_turf(user), 'sound/weapons/armblade.ogg', 50, TRUE, -1)
+ H.apply_damage(30, BRUTE, targetlimb, H.run_armor_check(targetlimb, MELEE), TRUE)
+ H.KnockDown(4 SECONDS)
+ add_attack_logs(user, H, "Cleaved overhead with a breach cleaver. (Grab intent, Knockdown)", ATKLOG_ALL)
+
+ if(INTENT_HARM)
+ return ..()
+
+// MARK: CHAINSAW
+/obj/item/chainsaw
+ name = "chainsaw"
+ desc = "A versatile power tool. Useful for limbing trees and delimbing humans."
+ icon = 'icons/obj/weapons/melee.dmi'
+ icon_state = "gchainsaw"
+ base_icon_state = "gchainsaw"
+ lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
+ hitsound = "swing_hit"
+ attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
+ origin_tech = "materials=3;engineering=4;combat=2"
+ materials = list(MAT_METAL = 13000)
+ w_class = WEIGHT_CLASS_HUGE
+ needs_permit = TRUE
+ flags = CONDUCT
+ sharp = TRUE
+ force = 13
+ throwforce = 13 // how
+ throw_range = 4
+ var/force_on = 24
+ new_attack_chain = TRUE
+
+// These 2 are currently used by syndie chainsaw
+/obj/item/chainsaw/proc/wield()
+ return
+
+/obj/item/chainsaw/proc/unwield()
+ return
+
+/obj/item/chainsaw/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/two_handed, \
+ icon_wielded = "[icon_state]_on", \
+ force_wielded = force_on, \
+ force_unwielded = force, \
+ attacksound = 'sound/weapons/chainsaw.ogg', \
+ wieldsound = 'sound/weapons/chainsawstart.ogg', \
+ wield_callback = CALLBACK(src, PROC_REF(wield)), \
+ unwield_callback = CALLBACK(src, PROC_REF(unwield)), \
+ )
+
+/obj/item/chainsaw/update_icon_state()
+ icon_state = base_icon_state
+
+// MARK: SYNDIE CHAINSAW
+/obj/item/chainsaw/syndie
+ desc = "Perfect for felling trees or fellow spacemen."
+ icon_state = "chainsaw"
+ base_icon_state = "chainsaw"
+ origin_tech = "materials=6;syndicate=4"
+ flags_2 = RANDOM_BLOCKER_2
+ w_class = WEIGHT_CLASS_BULKY // can't fit in backpacks
+ force = 15
+ throwforce = 15
+ force_on = 40
+ throw_speed = 1
+ throw_range = 5
+ armour_penetration_percentage = 50
+ armour_penetration_flat = 10
+
+/obj/item/chainsaw/syndie/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/butchers_humans)
+
+/obj/item/chainsaw/syndie/wield() // you can't disarm an active chainsaw, you crazy person.
+ set_nodrop(TRUE, loc)
+
+/obj/item/chainsaw/syndie/unwield()
+ set_nodrop(FALSE, loc)
+
+/obj/item/chainsaw/syndie/attack(mob/living/target, mob/living/user, params)
+ if(..())
+ return FINISH_ATTACK
+ if(HAS_TRAIT(src, TRAIT_WIELDED))
+ target.KnockDown(8 SECONDS)
+ if(target.stat != DEAD && !isrobot(target) && user.reagents.get_reagent_amount("mephedrone") <= 15)
+ user.apply_status_effect(STATUS_EFFECT_CHAINSAW_SLAYING)
+
+/obj/item/chainsaw/syndie/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 in NON_PROJECTILE_ATTACKS) && owner.has_status_effect(STATUS_EFFECT_CHAINSAW_SLAYING)) // It's a chainsaw, you can't block projectiles with it
+ final_block_chance = 80 // Need to be ready to ruuuummbllleeee
+ return ..()
+
+// MARK: SLAYER CHAINSAW
+/obj/item/chainsaw/doomslayer
+ name = "OOOH BABY"
+ desc = "VRRRRRRR!!!"
+ armour_penetration_percentage = 100
+ force_on = 30
+
+/obj/item/chainsaw/doomslayer/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 == PROJECTILE_ATTACK)
+ owner.visible_message("Ranged attacks just make [owner] angrier!")
+ playsound(src, pick('sound/weapons/bulletflyby.ogg','sound/weapons/bulletflyby2.ogg','sound/weapons/bulletflyby3.ogg'), 75, 1)
+ return TRUE
+ return FALSE
diff --git a/code/game/objects/items/weapons/melee/melee_misc.dm b/code/game/objects/items/weapons/melee/melee_misc.dm
index a8a6cc08f2f..f2f73b8de6a 100644
--- a/code/game/objects/items/weapons/melee/melee_misc.dm
+++ b/code/game/objects/items/weapons/melee/melee_misc.dm
@@ -1,9 +1,4 @@
-/obj/item/melee
- icon = 'icons/obj/weapons/melee.dmi'
- lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
- needs_permit = TRUE
-
+// MARK: CHAIN OF COMMAND
/obj/item/melee/chainofcommand
name = "chain of command"
desc = "A tool used by great men to placate the frothing masses."
@@ -18,232 +13,11 @@
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
hitsound = 'sound/weapons/slash.ogg' //pls replace
-
/obj/item/melee/chainofcommand/suicide_act(mob/user)
to_chat(viewers(user), "[user] is strangling [user.p_themselves()] with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return OXYLOSS
-/obj/item/melee/saber
- name = "captain's saber"
- desc = "An elegant weapon, for a more civilized age."
- icon_state = "saber"
- item_state = "saber"
- flags = CONDUCT
- force = 15
- throwforce = 10
- w_class = WEIGHT_CLASS_BULKY
- armour_penetration_percentage = 75
- sharp = TRUE
- origin_tech = null
- attack_verb = list("lunged at", "stabbed")
- hitsound = 'sound/weapons/rapierhit.ogg'
- materials = list(MAT_METAL = 1000)
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF // Theft targets should be hard to destroy
- // values for slapping
- var/slap_sound = 'sound/effects/woodhit.ogg'
- COOLDOWN_DECLARE(slap_cooldown)
-
-/obj/item/melee/saber/examine(mob/user)
- . = ..()
- . += "The blade looks very well-suited for piercing armour."
-
-/obj/item/melee/saber/examine_more(mob/user)
- . = ..()
- . += "Swords are a traditional ceremonial weapon carried by commanding officers of many armies and navies, even long after firearms and laserarms rendered them obsolete. \
- Despite having no roots in such traditions, Nanotrasen participates in them, as these trappings of old tradition help to promote the air of authority the company wishes for its captains to possess."
- . += ""
- . += "Whilst not intended to actually be used in combat, the ceremonial blades issued by Nanotrasen are in-fact quite functional, \
- able to both inflict grievous wounds on aggressors that get too close, whilst also elegantly parrying their blows (assuming the wielder is skilled with the blade). \
- The sharp edge is adept at hacking unarmored targets, whilst the rigid tip is also quite effective at at defeating even modern body armor with thrusting attacks, as modern armor is generally designed to defeat ballistic and laser weapons rather than swords..."
-
-/obj/item/melee/saber/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS)
- AddElement(/datum/element/high_value_item)
-
-/obj/item/melee/saber/attack__legacy__attackchain(mob/living/target, mob/living/user)
- if(user.a_intent != INTENT_HELP || !ishuman(target))
- return ..()
- if(!COOLDOWN_FINISHED(src, slap_cooldown))
- return
- var/mob/living/carbon/human/H = target
- if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- user.visible_message("[user] accidentally slaps [user.p_themselves()] with [src]!", \
- "You accidentally slap yourself with [src]!")
- slap(user, user)
- else
- user.visible_message("[user] slaps [H] with the flat of the blade!", \
- "You slap [H] with the flat of the blade!")
- slap(target, user)
-
-/obj/item/melee/saber/proc/slap(mob/living/carbon/human/target, mob/living/user)
- user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
- playsound(loc, slap_sound, 50, TRUE, -1)
- target.AdjustConfused(4 SECONDS, 0, 4 SECONDS)
- target.apply_damage(10, STAMINA)
- add_attack_logs(user, target, "Slapped by [src]", ATKLOG_ALL)
- COOLDOWN_START(src, slap_cooldown, 4 SECONDS)
-
-/obj/item/melee/saber/suicide_act(mob/user)
- user.visible_message(pick("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!", \
- "[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
- return BRUTELOSS
-
-// Traitor Sword
-/obj/item/melee/snakesfang
- name = "snakesfang"
- desc = "A uniquely curved, black and red sword. Extra-edgy and cutting-edge."
- lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
- icon_state = "snakesfang"
- item_state = "snakesfang"
- flags = CONDUCT
- force = 25
- throwforce = 10
- w_class = WEIGHT_CLASS_BULKY
- sharp = TRUE
- origin_tech = "combat=6;syndicate=3"
- attack_verb = list("slashed", "sliced", "chopped")
- hitsound = 'sound/weapons/bladeslice.ogg'
- materials = list(MAT_METAL = 1000)
-
-/obj/item/melee/snakesfang/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS)
-
-/obj/item/melee/snakesfang/examine_more(mob/user)
- . = ..()
- . += "A uniquely curved, black and red sword. Extra-edgy and cutting-edge."
- . += ""
- . += "The MK-IV Enhanced Combat Blade, more colloquially known as the ‘Snakesfang’, is a vicious yet stylish weapon designed \
- by a relatively unknown weapons forge with known ties to the Syndicate. With a wide, curved blade and dual points \
- resembling the fangs of the organization’s serpent motif, the Snakesfang is a statement like no other."
- . += ""
- . += "While the benefits of its unique design are dubious at best, the Snakesfang is undoubtedly a perilous weapon, with a hardened \
- plastitanium edge that can cause untold harm to a soft target. In the right hands, it can be a terrifying weapon to behold, \
- and it’s said that blood runs down the blade in just the right way, to drip artfully from the twin ‘fangs’ at its apex."
-
-// Unathi Sword
-/obj/item/melee/breach_cleaver
- name = "breach cleaver"
- desc = "Massive, heavy, and utterly impractical. This sharpened chunk of steel is too big and too heavy to be called a sword."
- lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
- base_icon_state = "breach_cleaver"
- icon_state = "breach_cleaver0"
- flags = CONDUCT
- force = 5
- throwforce = 5
- armour_penetration_flat = 30
- w_class = WEIGHT_CLASS_BULKY
- sharp = TRUE
- origin_tech = "combat=6;syndicate=5"
- attack_verb = list("slashed", "cleaved", "chopped")
- hitsound = 'sound/weapons/swordhitheavy.ogg'
- materials = list(MAT_METAL = 2000)
- /// How much damage the sword does when wielded
- var/force_wield = 40
-
-/obj/item/melee/breach_cleaver/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/two_handed, force_wielded = force_wield, force_unwielded = force, icon_wielded = "[base_icon_state]1", wield_callback = CALLBACK(src, PROC_REF(wield)), unwield_callback = CALLBACK(src, PROC_REF(unwield)))
- AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS)
-
-/obj/item/melee/breach_cleaver/examine(mob/user)
- . = ..()
- if(isAntag(user))
- . += "When wielded, this blade has different effects depending on your intent, similar to a martial art. \
- Help intent will strike with the flat, dealing stamina, disarm intent forces them away, grab intent knocks down the target, \
- and harm intent deals heavy damage."
-
-/obj/item/melee/breach_cleaver/examine_more(mob/user)
- . = ..()
- . += "Massive, heavy, and utterly impractical. This sharpened chunk of steel is too big and too heavy to be called a sword."
- . += ""
- . += "The Unathi Breach Cleaver is a weapon the scaled, warlike race favours for its impressive weight and myriad combat applications. \
- The pinnacle of Moghes' combat technology, it combines all of this knowledge into a massive, heavy slab of alloyed metal that most \
- species find difficult to lift, let alone use in any sort of fight."
- . += ""
- . += "Actually a little lightweight for its size, a Breach Cleaver is unmatched in combat utility as a weapon, a tool for getting into\
- places and as a slab of armour for the wielder. The leather of the Kar'oche beast, a predator native to Moghes, binds the hilt, \
- allowing it to be gripped securely by its warrior. The wide blade is often etched with scenes depicting military victories or great hunts."
-
-/obj/item/melee/breach_cleaver/update_icon_state()
- icon_state = "[base_icon_state]0"
-
-/obj/item/melee/breach_cleaver/proc/wield(obj/item/source, mob/living/carbon/human/user)
- to_chat(user, "You heave [src] up in both hands.")
- user.apply_status_effect(STATUS_EFFECT_BREACH_AND_CLEAVE)
- update_icon(UPDATE_ICON_STATE)
-
-/obj/item/melee/breach_cleaver/proc/unwield(obj/item/source, mob/living/carbon/human/user)
- user.remove_status_effect(STATUS_EFFECT_BREACH_AND_CLEAVE)
- update_icon(UPDATE_ICON_STATE)
-
-/obj/item/melee/breach_cleaver/attack_obj__legacy__attackchain(obj/O, mob/living/user, params)
- if(!HAS_TRAIT(src, TRAIT_WIELDED)) // Only works good when wielded
- return ..()
- if(!ismachinery(O) && !isstructure(O)) // This sword hates doors
- return ..()
- if(SEND_SIGNAL(src, COMSIG_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
- return
- if(flags & (NOBLUDGEON))
- return
- var/mob/living/carbon/human/H = user
- H.changeNext_move(CLICK_CD_MELEE)
- H.do_attack_animation(O)
- H.visible_message("[H] has hit [O] with [src]!", "You hit [O] with [src]!")
- var/damage = force_wield
- damage += H.physiology.melee_bonus
- O.take_damage(damage * 3, BRUTE, MELEE, TRUE, get_dir(src, H), 30) // Multiplied to do big damage to doors, closets, windows, and machines, but normal damage to mobs.
-
-/obj/item/melee/breach_cleaver/attack__legacy__attackchain(mob/target, mob/living/user)
- if(!HAS_TRAIT(src, TRAIT_WIELDED) || !ishuman(target))
- return ..()
-
- var/mob/living/carbon/human/H = target
- var/obj/item/organ/external/targetlimb = H.get_organ(ran_zone(user.zone_selected))
-
- switch(user.a_intent)
- if(INTENT_HELP) // Stamina damage
- H.visible_message("[user] slams [H] with the flat of the blade!", \
- "[user] slams you with the flat of the blade!", \
- "You hear a thud.")
- user.do_attack_animation(H, ATTACK_EFFECT_DISARM)
- playsound(loc, 'sound/weapons/swordhit.ogg', 50, TRUE, -1)
- H.AdjustConfused(4 SECONDS, 0, 4 SECONDS)
- H.apply_damage(40, STAMINA, targetlimb, H.run_armor_check(targetlimb, MELEE))
- add_attack_logs(user, H, "Slammed by a breach cleaver. (Help intent, Stamina)", ATKLOG_ALL)
-
- if(INTENT_DISARM) // Slams away
- if(H.stat != CONSCIOUS || IS_HORIZONTAL(H))
- return ..()
-
- H.visible_message("[user] smashes [H] with the blade's tip!", \
- "[user] smashes you with the blade's tip!", \
- "You hear crushing.")
-
- user.do_attack_animation(H, ATTACK_EFFECT_KICK)
- playsound(get_turf(user), 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE, -1)
- H.apply_damage(25, BRUTE, targetlimb, H.run_armor_check(targetlimb, MELEE))
- var/atom/throw_target = get_edge_target_turf(H, user.dir, TRUE)
- H.throw_at(throw_target, 4, 1)
- add_attack_logs(user, H, "Smashed away by a breach cleaver. (Disarm intent, Knockback)", ATKLOG_ALL)
-
- if(INTENT_GRAB) // Knocks down
- H.visible_message("[user] cleaves [H] with an overhead strike!", \
- "[user] cleaves you with an overhead strike!", \
- "You hear a chopping noise.")
-
- user.do_attack_animation(H, ATTACK_EFFECT_DISARM)
- playsound(get_turf(user), 'sound/weapons/armblade.ogg', 50, TRUE, -1)
- H.apply_damage(30, BRUTE, targetlimb, H.run_armor_check(targetlimb, MELEE), TRUE)
- H.KnockDown(4 SECONDS)
- add_attack_logs(user, H, "Cleaved overhead with a breach cleaver. (Grab intent, Knockdown)", ATKLOG_ALL)
-
- if(INTENT_HARM)
- return ..()
-
+// MARK: ICE PICK
/obj/item/melee/icepick
name = "ice pick"
desc = "Used for chopping ice. Also excellent for mafia esque murders."
@@ -254,6 +28,7 @@
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("stabbed", "jabbed", "iced,")
+// MARK: CANDY SWORD
/obj/item/melee/candy_sword
name = "candy cane sword"
desc = "A large candy cane with a sharpened point. Definitely too dangerous for schoolchildren."
@@ -264,6 +39,7 @@
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("slashed", "stabbed", "sliced", "caned")
+// MARK: FLYSWATTER
/obj/item/melee/flyswatter
name = "flyswatter"
desc = "Useful for killing insects of all sizes."
@@ -298,291 +74,3 @@
bug.death(TRUE)
if(!QDELETED(M))
qdel(M)
-
-/obj/item/melee/spellblade
- name = "spellblade"
- desc = "An enchanted blade with a series of runes along the side."
- icon = 'icons/obj/guns/magic.dmi'
- icon_state = "spellblade"
- item_state = "spellblade"
- hitsound = 'sound/weapons/rapierhit.ogg'
- w_class = WEIGHT_CLASS_BULKY
- force = 25
- armour_penetration_flat = 50
- sharp = TRUE
- new_attack_chain = TRUE
- resistance_flags = LAVA_PROOF | FIRE_PROOF
- ///enchantment holder, gives it unique on hit effects.
- var/datum/enchantment/enchant = null
- ///the cooldown and power of enchantments are multiplied by this var when its applied
- var/power = 1
-
-/obj/item/melee/spellblade/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = ALL_ATTACK_TYPES)
-
-/obj/item/melee/spellblade/Destroy()
- QDEL_NULL(enchant)
- return ..()
-
-/obj/item/melee/spellblade/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers)
- enchant?.pre_hit(target, user, src)
-
-/obj/item/melee/spellblade/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
- . = ..()
- enchant?.on_hit(target, user, src)
-
-/obj/item/melee/spellblade/activate_self(mob/user)
- if(..())
- return
- if(enchant)
- return
-
- var/static/list/options = list(
- "Lightning" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "chain_lightning"),
- "Fire" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "fire"),
- "Bluespace" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "blink"),
- "Forcewall" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "shield"),
- "Temporal Slash" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "spacetime"),
- )
- var/static/list/options_to_type = list(
- "Lightning" = /datum/enchantment/lightning,
- "Fire" = /datum/enchantment/fire,
- "Bluespace" = /datum/enchantment/bluespace,
- "Forcewall" = /datum/enchantment/forcewall,
- "Temporal Slash" = /datum/enchantment/time_slash,
- )
-
- var/choice = show_radial_menu(user, src, options)
- if(!choice)
- return
- add_enchantment(options_to_type[choice], user)
-
-/obj/item/melee/spellblade/proc/add_enchantment(new_enchant, mob/living/user, intentional = TRUE)
- var/datum/enchantment/E = new new_enchant
- enchant = E
- E.on_gain(src, user)
- E.power *= power
- E.on_apply_to_blade(src)
- if(intentional)
- SSblackbox.record_feedback("nested tally", "spellblade_enchants", 1, list("[E.name]"))
-
-/obj/item/melee/spellblade/examine(mob/user)
- . = ..()
- if(enchant && (iswizard(user) || IS_CULTIST(user))) // only wizards and cultists understand runes
- . += "The runes along the side read; [enchant.desc]."
-
-/datum/enchantment
- /// used for blackbox logging
- var/name = "You shouldn't be seeing this, file an issue report."
- /// used for wizards/cultists examining the runes on the blade
- var/desc = "Someone messed up, file an issue report."
- /// used for damage values
- var/power = 1
- /// whether the enchant procs despite not being in proximity
- var/ranged = FALSE
- /// stores cooldown between activations.
- var/cooldown = 0
- /// If the spellblade has traits, has it applied them?
- var/applied_traits = FALSE
- COOLDOWN_DECLARE(enchant_cooldown)
-
-/datum/enchantment/proc/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- if(!COOLDOWN_FINISHED(src, enchant_cooldown) || !istype(target) || target.stat == DEAD)
- return FALSE
- return TRUE
-
-/datum/enchantment/proc/pre_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- if(!ranged || !COOLDOWN_FINISHED(src, enchant_cooldown) || !istype(target) || target.stat == DEAD)
- return FALSE
- return TRUE
-
-/datum/enchantment/proc/on_gain(obj/item/melee/spellblade/S, mob/living/user)
- return
-
-/datum/enchantment/proc/toggle_traits(obj/item/I, mob/living/user)
- return
-
-/datum/enchantment/proc/on_apply_to_blade(obj/item/melee/spellblade/S)
- return
-
-/datum/enchantment/lightning
- name = "lightning"
- desc = "this blade conducts arcane energy to arc between its victims. It also makes the user immune to shocks"
- // the damage of the first lighting arc.
- power = 20
- cooldown = 3 SECONDS
-
-/datum/enchantment/lightning/on_gain(obj/item/melee/spellblade/S, mob/living/user)
- ..()
- RegisterSignal(S, list(COMSIG_ITEM_PICKUP, COMSIG_ITEM_DROPPED), PROC_REF(toggle_traits))
- if(user)
- toggle_traits(S, user)
-
-/datum/enchantment/lightning/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- . = ..()
- if(.)
- zap(target, user, list(user), power)
- COOLDOWN_START(src, enchant_cooldown, cooldown)
-
-/datum/enchantment/lightning/toggle_traits(obj/item/I, mob/living/user)
- var/enchant_ID = UID() // so it only removes the traits applied by this specific enchant.
- if(applied_traits)
- REMOVE_TRAIT(user, TRAIT_SHOCKIMMUNE, "[enchant_ID]")
- else
- ADD_TRAIT(user, TRAIT_SHOCKIMMUNE, "[enchant_ID]")
- applied_traits = !applied_traits
-
-/datum/enchantment/lightning/proc/zap(mob/living/target, mob/living/source, protected_mobs, voltage)
- source.Beam(target, "lightning[rand(1,12)]", 'icons/effects/effects.dmi', time = 2 SECONDS, maxdistance = 7, beam_type = /obj/effect/ebeam/chain)
- if(!target.electrocute_act(voltage, "lightning", flags = SHOCK_TESLA)) // if it fails to shock someone, break the chain
- return
- protected_mobs += target
- addtimer(CALLBACK(src, PROC_REF(arc), target, voltage, protected_mobs), 2.5 SECONDS)
-
-/datum/enchantment/lightning/proc/arc(mob/living/source, voltage, protected_mobs)
- voltage = voltage - 4
- if(voltage <= 0)
- return
-
- for(var/mob/living/L in oview(7, get_turf(source)))
- if(L in protected_mobs)
- continue
- zap(L, source, protected_mobs, voltage)
- break
-
-/datum/enchantment/fire
- name = "fire"
- desc = "this blade ignites on striking a foe, releasing a ball of fire. It also makes the wielder immune to fire"
- cooldown = 8 SECONDS
-
-/datum/enchantment/fire/on_gain(obj/item/melee/spellblade/S, mob/living/user)
- ..()
- RegisterSignal(S, list(COMSIG_ITEM_PICKUP, COMSIG_ITEM_DROPPED), PROC_REF(toggle_traits))
- if(user)
- toggle_traits(S, user)
-
-/datum/enchantment/fire/toggle_traits(obj/item/I, mob/living/user)
- var/enchant_ID = UID() // so it only removes the traits applied by this specific enchant.
- if(applied_traits)
- REMOVE_TRAIT(user, TRAIT_NOFIRE, "[enchant_ID]")
- REMOVE_TRAIT(user, TRAIT_RESISTHEAT, "[enchant_ID]")
- applied_traits = FALSE
- else
- ADD_TRAIT(user, TRAIT_RESISTHEAT, "[enchant_ID]")
- ADD_TRAIT(user, TRAIT_NOFIRE, "[enchant_ID]")
- applied_traits = TRUE
-
-/datum/enchantment/fire/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- . = ..()
- if(.)
- fireflash_s(target, 4, 8000 * power, 500)
- COOLDOWN_START(src, enchant_cooldown, cooldown)
-
-/datum/enchantment/forcewall
- name = "forcewall"
- desc = "this blade will partially shield you against attacks and stuns for a short duration after striking a foe"
- cooldown = 4 SECONDS
- // multiplier for how much the cooldown is reduced by. A miner spellblade can only buff every 4 seconds, making it more vunerable, the wizard one is much more consistant.
- power = 2
-
-/datum/enchantment/forcewall/on_apply_to_blade(obj/item/melee/spellblade/S)
- cooldown /= power
-
-/datum/enchantment/forcewall/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- . = ..()
- if(.)
- user.apply_status_effect(STATUS_EFFECT_FORCESHIELD)
- COOLDOWN_START(src, enchant_cooldown, cooldown)
-
-/datum/enchantment/bluespace
- name = "bluespace"
- desc = "this blade will cut through the fabric of space, transporting its wielder over medium distances to strike foes"
- cooldown = 2.5 SECONDS
- ranged = TRUE
- // the number of deciseconds of stun applied by the teleport strike
- power = 5
-
-/datum/enchantment/bluespace/pre_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- . = ..()
- if(.)
- var/turf/user_turf = get_turf(user)
- if(get_dist(user_turf, get_turf(target)) > 9) //blocks cameras without blocking xray or thermals
- return
- if(!((target in view(9, user)) || user.sight & SEE_MOBS))
- return
- var/list/turfs = list()
- for(var/turf/T in orange(1, get_turf(target)))
- if(T.is_blocked_turf(exclude_mobs = TRUE))
- continue
- turfs += T
-
- var/target_turf = pick(turfs)
- user_turf.Beam(target_turf, "warp_beam", time = 0.3 SECONDS)
- user.forceMove(target_turf)
- S.melee_attack_chain(user, target)
- target.Weaken(power)
- COOLDOWN_START(src, enchant_cooldown, cooldown)
-
-/datum/enchantment/bluespace/on_apply_to_blade(obj/item/melee/spellblade/S)
- cooldown /= S.power
-
-/datum/enchantment/time_slash
- name = "temporal"
- desc = "this blade will slice faster but weaker, and will curse the target, slashing them a few seconds after they have not been swinged at for each hit"
- power = 20 // This should come out to 32.5 damage per hit. However, delayed.
-
-/datum/enchantment/time_slash/on_apply_to_blade(obj/item/melee/spellblade/S)
- S.force /= 2
-
-/datum/enchantment/time_slash/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
- user.changeNext_move(CLICK_CD_MELEE * 0.5)
- . = ..()
- if(.)
- target.apply_status_effect(STATUS_EFFECT_TEMPORAL_SLASH, power)
-
-/obj/effect/temp_visual/temporal_slash
- name = "temporal slash"
- desc = "A cut through spacetime"
- icon = 'icons/obj/projectiles.dmi'
- icon_state = "arcane_barrage"
- layer = FLY_LAYER
- plane = GRAVITY_PULSE_PLANE
- appearance_flags = PIXEL_SCALE|LONG_GLIDE
- duration = 0.5 SECONDS
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT // Let us not have this visual block clicks
- /// Who we are orbiting
- var/target
- /// A funky color matrix to recolor the slash to
- var/list/funky_color_matrix = list(0.4,0,0,0, 0,1.1,0,0, 0,0,1.65,0, -0.3,0.15,0,1, 0,0,0,0)
-
-/obj/effect/temp_visual/temporal_slash/Initialize(mapload, new_target)
- . = ..()
- target = new_target
- INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, orbit), target, 0, FALSE, 0, 0, FALSE, TRUE)
- var/matrix/M = matrix()
- M.Scale(1, 2)
- M.Turn(rand(0, 360))
- transform = M
- addtimer(CALLBACK(src, PROC_REF(animate_slash)), 0.25 SECONDS)
-
-/obj/effect/temp_visual/temporal_slash/proc/animate_slash()
- plane = -1
- color = funky_color_matrix
- animate(src, alpha = 0, time = duration, easing = EASE_OUT)
-
-/obj/item/melee/spellblade/random
- power = 0.5
-
-/obj/item/melee/spellblade/random/Initialize(mapload)
- . = ..()
- var/list/options = list(
- /datum/enchantment/lightning,
- /datum/enchantment/fire,
- /datum/enchantment/forcewall,
- /datum/enchantment/bluespace,
- /datum/enchantment/time_slash,
- )
-
- var/datum/enchantment/E = pick(options)
- add_enchantment(E, intentional = FALSE)
diff --git a/code/game/objects/items/weapons/melee/spellblade.dm b/code/game/objects/items/weapons/melee/spellblade.dm
new file mode 100644
index 00000000000..db18899b2e5
--- /dev/null
+++ b/code/game/objects/items/weapons/melee/spellblade.dm
@@ -0,0 +1,288 @@
+// MARK: SPELLBLADE
+/obj/item/melee/spellblade
+ name = "spellblade"
+ desc = "An enchanted blade with a series of runes along the side."
+ icon = 'icons/obj/guns/magic.dmi'
+ icon_state = "spellblade"
+ item_state = "spellblade"
+ hitsound = 'sound/weapons/rapierhit.ogg'
+ resistance_flags = LAVA_PROOF | FIRE_PROOF
+ w_class = WEIGHT_CLASS_BULKY
+ force = 25
+ armour_penetration_flat = 50
+ sharp = TRUE
+ new_attack_chain = TRUE
+ ///enchantment holder, gives it unique on hit effects.
+ var/datum/enchantment/enchant = null
+ ///the cooldown and power of enchantments are multiplied by this var when its applied
+ var/power = 1
+
+/obj/item/melee/spellblade/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = ALL_ATTACK_TYPES)
+
+/obj/item/melee/spellblade/Destroy()
+ QDEL_NULL(enchant)
+ return ..()
+
+/obj/item/melee/spellblade/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers)
+ enchant?.pre_hit(target, user, src)
+
+/obj/item/melee/spellblade/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ enchant?.on_hit(target, user, src)
+
+/obj/item/melee/spellblade/activate_self(mob/user)
+ if(..())
+ return
+ if(enchant)
+ return
+
+ var/static/list/options = list(
+ "Lightning" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "chain_lightning"),
+ "Fire" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "fire"),
+ "Bluespace" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "blink"),
+ "Forcewall" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "shield"),
+ "Temporal Slash" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "spacetime"),
+ )
+ var/static/list/options_to_type = list(
+ "Lightning" = /datum/enchantment/lightning,
+ "Fire" = /datum/enchantment/fire,
+ "Bluespace" = /datum/enchantment/bluespace,
+ "Forcewall" = /datum/enchantment/forcewall,
+ "Temporal Slash" = /datum/enchantment/time_slash,
+ )
+
+ var/choice = show_radial_menu(user, src, options)
+ if(!choice)
+ return
+ add_enchantment(options_to_type[choice], user)
+
+/obj/item/melee/spellblade/proc/add_enchantment(new_enchant, mob/living/user, intentional = TRUE)
+ var/datum/enchantment/E = new new_enchant
+ enchant = E
+ E.on_gain(src, user)
+ E.power *= power
+ E.on_apply_to_blade(src)
+ if(intentional)
+ SSblackbox.record_feedback("nested tally", "spellblade_enchants", 1, list("[E.name]"))
+
+/obj/item/melee/spellblade/examine(mob/user)
+ . = ..()
+ if(enchant && (iswizard(user) || IS_CULTIST(user))) // only wizards and cultists understand runes
+ . += "The runes along the side read; [enchant.desc]."
+
+/datum/enchantment
+ /// used for blackbox logging
+ var/name = "You shouldn't be seeing this, file an issue report."
+ /// used for wizards/cultists examining the runes on the blade
+ var/desc = "Someone messed up, file an issue report."
+ /// used for damage values
+ var/power = 1
+ /// whether the enchant procs despite not being in proximity
+ var/ranged = FALSE
+ /// stores cooldown between activations.
+ var/cooldown = 0
+ /// If the spellblade has traits, has it applied them?
+ var/applied_traits = FALSE
+ COOLDOWN_DECLARE(enchant_cooldown)
+
+/datum/enchantment/proc/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ if(!COOLDOWN_FINISHED(src, enchant_cooldown) || !istype(target) || target.stat == DEAD)
+ return FALSE
+ return TRUE
+
+/datum/enchantment/proc/pre_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ if(!ranged || !COOLDOWN_FINISHED(src, enchant_cooldown) || !istype(target) || target.stat == DEAD)
+ return FALSE
+ return TRUE
+
+/datum/enchantment/proc/on_gain(obj/item/melee/spellblade/S, mob/living/user)
+ return
+
+/datum/enchantment/proc/toggle_traits(obj/item/I, mob/living/user)
+ return
+
+/datum/enchantment/proc/on_apply_to_blade(obj/item/melee/spellblade/S)
+ return
+
+/datum/enchantment/lightning
+ name = "lightning"
+ desc = "this blade conducts arcane energy to arc between its victims. It also makes the user immune to shocks"
+ // the damage of the first lighting arc.
+ power = 20
+ cooldown = 3 SECONDS
+
+/datum/enchantment/lightning/on_gain(obj/item/melee/spellblade/S, mob/living/user)
+ ..()
+ RegisterSignal(S, list(COMSIG_ITEM_PICKUP, COMSIG_ITEM_DROPPED), PROC_REF(toggle_traits))
+ if(user)
+ toggle_traits(S, user)
+
+/datum/enchantment/lightning/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ . = ..()
+ if(.)
+ zap(target, user, list(user), power)
+ COOLDOWN_START(src, enchant_cooldown, cooldown)
+
+/datum/enchantment/lightning/toggle_traits(obj/item/I, mob/living/user)
+ var/enchant_ID = UID() // so it only removes the traits applied by this specific enchant.
+ if(applied_traits)
+ REMOVE_TRAIT(user, TRAIT_SHOCKIMMUNE, "[enchant_ID]")
+ else
+ ADD_TRAIT(user, TRAIT_SHOCKIMMUNE, "[enchant_ID]")
+ applied_traits = !applied_traits
+
+/datum/enchantment/lightning/proc/zap(mob/living/target, mob/living/source, protected_mobs, voltage)
+ source.Beam(target, "lightning[rand(1,12)]", 'icons/effects/effects.dmi', time = 2 SECONDS, maxdistance = 7, beam_type = /obj/effect/ebeam/chain)
+ if(!target.electrocute_act(voltage, "lightning", flags = SHOCK_TESLA)) // if it fails to shock someone, break the chain
+ return
+ protected_mobs += target
+ addtimer(CALLBACK(src, PROC_REF(arc), target, voltage, protected_mobs), 2.5 SECONDS)
+
+/datum/enchantment/lightning/proc/arc(mob/living/source, voltage, protected_mobs)
+ voltage = voltage - 4
+ if(voltage <= 0)
+ return
+
+ for(var/mob/living/L in oview(7, get_turf(source)))
+ if(L in protected_mobs)
+ continue
+ zap(L, source, protected_mobs, voltage)
+ break
+
+/datum/enchantment/fire
+ name = "fire"
+ desc = "this blade ignites on striking a foe, releasing a ball of fire. It also makes the wielder immune to fire"
+ cooldown = 8 SECONDS
+
+/datum/enchantment/fire/on_gain(obj/item/melee/spellblade/S, mob/living/user)
+ ..()
+ RegisterSignal(S, list(COMSIG_ITEM_PICKUP, COMSIG_ITEM_DROPPED), PROC_REF(toggle_traits))
+ if(user)
+ toggle_traits(S, user)
+
+/datum/enchantment/fire/toggle_traits(obj/item/I, mob/living/user)
+ var/enchant_ID = UID() // so it only removes the traits applied by this specific enchant.
+ if(applied_traits)
+ REMOVE_TRAIT(user, TRAIT_NOFIRE, "[enchant_ID]")
+ REMOVE_TRAIT(user, TRAIT_RESISTHEAT, "[enchant_ID]")
+ applied_traits = FALSE
+ else
+ ADD_TRAIT(user, TRAIT_RESISTHEAT, "[enchant_ID]")
+ ADD_TRAIT(user, TRAIT_NOFIRE, "[enchant_ID]")
+ applied_traits = TRUE
+
+/datum/enchantment/fire/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ . = ..()
+ if(.)
+ fireflash_s(target, 4, 8000 * power, 500)
+ COOLDOWN_START(src, enchant_cooldown, cooldown)
+
+/datum/enchantment/forcewall
+ name = "forcewall"
+ desc = "this blade will partially shield you against attacks and stuns for a short duration after striking a foe"
+ cooldown = 4 SECONDS
+ // multiplier for how much the cooldown is reduced by. A miner spellblade can only buff every 4 seconds, making it more vunerable, the wizard one is much more consistant.
+ power = 2
+
+/datum/enchantment/forcewall/on_apply_to_blade(obj/item/melee/spellblade/S)
+ cooldown /= power
+
+/datum/enchantment/forcewall/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ . = ..()
+ if(.)
+ user.apply_status_effect(STATUS_EFFECT_FORCESHIELD)
+ COOLDOWN_START(src, enchant_cooldown, cooldown)
+
+/datum/enchantment/bluespace
+ name = "bluespace"
+ desc = "this blade will cut through the fabric of space, transporting its wielder over medium distances to strike foes"
+ cooldown = 2.5 SECONDS
+ ranged = TRUE
+ // the number of deciseconds of stun applied by the teleport strike
+ power = 5
+
+/datum/enchantment/bluespace/pre_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ . = ..()
+ if(.)
+ var/turf/user_turf = get_turf(user)
+ if(get_dist(user_turf, get_turf(target)) > 9) //blocks cameras without blocking xray or thermals
+ return
+ if(!((target in view(9, user)) || user.sight & SEE_MOBS))
+ return
+ var/list/turfs = list()
+ for(var/turf/T in orange(1, get_turf(target)))
+ if(T.is_blocked_turf(exclude_mobs = TRUE))
+ continue
+ turfs += T
+
+ var/target_turf = pick(turfs)
+ user_turf.Beam(target_turf, "warp_beam", time = 0.3 SECONDS)
+ user.forceMove(target_turf)
+ S.melee_attack_chain(user, target)
+ target.Weaken(power)
+ COOLDOWN_START(src, enchant_cooldown, cooldown)
+
+/datum/enchantment/bluespace/on_apply_to_blade(obj/item/melee/spellblade/S)
+ cooldown /= S.power
+
+/datum/enchantment/time_slash
+ name = "temporal"
+ desc = "this blade will slice faster but weaker, and will curse the target, slashing them a few seconds after they have not been swinged at for each hit"
+ power = 20 // This should come out to 32.5 damage per hit. However, delayed.
+
+/datum/enchantment/time_slash/on_apply_to_blade(obj/item/melee/spellblade/S)
+ S.force /= 2
+
+/datum/enchantment/time_slash/on_hit(mob/living/target, mob/living/user, obj/item/melee/spellblade/S)
+ user.changeNext_move(CLICK_CD_MELEE * 0.5)
+ . = ..()
+ if(.)
+ target.apply_status_effect(STATUS_EFFECT_TEMPORAL_SLASH, power)
+
+/obj/effect/temp_visual/temporal_slash
+ name = "temporal slash"
+ desc = "A cut through spacetime"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "arcane_barrage"
+ layer = FLY_LAYER
+ plane = GRAVITY_PULSE_PLANE
+ appearance_flags = PIXEL_SCALE|LONG_GLIDE
+ duration = 0.5 SECONDS
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT // Let us not have this visual block clicks
+ /// Who we are orbiting
+ var/target
+ /// A funky color matrix to recolor the slash to
+ var/list/funky_color_matrix = list(0.4,0,0,0, 0,1.1,0,0, 0,0,1.65,0, -0.3,0.15,0,1, 0,0,0,0)
+
+/obj/effect/temp_visual/temporal_slash/Initialize(mapload, new_target)
+ . = ..()
+ target = new_target
+ INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, orbit), target, 0, FALSE, 0, 0, FALSE, TRUE)
+ var/matrix/M = matrix()
+ M.Scale(1, 2)
+ M.Turn(rand(0, 360))
+ transform = M
+ addtimer(CALLBACK(src, PROC_REF(animate_slash)), 0.25 SECONDS)
+
+/obj/effect/temp_visual/temporal_slash/proc/animate_slash()
+ plane = -1
+ color = funky_color_matrix
+ animate(src, alpha = 0, time = duration, easing = EASE_OUT)
+
+/obj/item/melee/spellblade/random
+ power = 0.5
+
+/obj/item/melee/spellblade/random/Initialize(mapload)
+ . = ..()
+ var/list/options = list(
+ /datum/enchantment/lightning,
+ /datum/enchantment/fire,
+ /datum/enchantment/forcewall,
+ /datum/enchantment/bluespace,
+ /datum/enchantment/time_slash,
+ )
+
+ var/datum/enchantment/E = pick(options)
+ add_enchantment(E, intentional = FALSE)
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 84041150bca..c3e1e5d6699 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -435,147 +435,6 @@
mounted_head = null
qdel(src)
-// DIY CHAINSAW
-/obj/item/chainsaw
- name = "chainsaw"
- desc = "A versatile power tool. Useful for limbing trees and delimbing humans."
- lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
- icon = 'icons/obj/weapons/melee.dmi'
- icon_state = "gchainsaw_off"
- flags = CONDUCT
- force = 13
- var/force_on = 24
- w_class = WEIGHT_CLASS_HUGE
- throwforce = 13
- throw_speed = 2
- throw_range = 4
- materials = list(MAT_METAL = 13000)
- origin_tech = "materials=3;engineering=4;combat=2"
- attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
- hitsound = "swing_hit"
- sharp = TRUE
- actions_types = list(/datum/action/item_action/startchainsaw)
- var/on = FALSE
-
-/obj/item/chainsaw/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/two_handed, require_twohands = TRUE)
-
-
-/obj/item/chainsaw/attack_self__legacy__attackchain(mob/user)
- on = !on
- to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]")
- if(on)
- playsound(loc, 'sound/weapons/chainsawstart.ogg', 50, 1)
- force = on ? force_on : initial(force)
- throwforce = on ? force_on : initial(throwforce)
- icon_state = "gchainsaw_[on ? "on" : "off"]"
-
- if(hitsound == "swing_hit")
- hitsound = 'sound/weapons/chainsaw.ogg'
- else
- hitsound = "swing_hit"
-
- if(src == user.get_active_hand()) //update inhands
- user.update_inv_l_hand()
- user.update_inv_r_hand()
- update_action_buttons()
-
-/obj/item/chainsaw/attack_hand(mob/user)
- . = ..()
- force = on ? force_on : initial(force)
- throwforce = on ? force_on : initial(throwforce)
-
-/obj/item/chainsaw/on_give(mob/living/carbon/giver, mob/living/carbon/receiver)
- . = ..()
- force = on ? force_on : initial(force)
- throwforce = on ? force_on : initial(throwforce)
-
-/obj/item/chainsaw/doomslayer
- name = "OOOH BABY"
- desc = "VRRRRRRR!!!"
- armour_penetration_percentage = 100
- force_on = 30
-
-/obj/item/chainsaw/doomslayer/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 == PROJECTILE_ATTACK)
- owner.visible_message("Ranged attacks just make [owner] angrier!")
- playsound(src, pick('sound/weapons/bulletflyby.ogg','sound/weapons/bulletflyby2.ogg','sound/weapons/bulletflyby3.ogg'), 75, 1)
- return TRUE
- return FALSE
-
-
-///CHAINSAW///
-/obj/item/butcher_chainsaw
- name = "chainsaw"
- desc = "Perfect for felling trees or fellow spacemen."
- lefthand_file = 'icons/mob/inhands/weapons_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons_righthand.dmi'
- icon = 'icons/obj/weapons/melee.dmi'
- base_icon_state = "chainsaw"
- icon_state = "chainsaw0"
- force = 15
- throwforce = 15
- throw_speed = 1
- throw_range = 5
- w_class = WEIGHT_CLASS_BULKY // can't fit in backpacks
- hitsound = null // Handled in the snowflaked attack proc
- armour_penetration_percentage = 50
- armour_penetration_flat = 10
- origin_tech = "materials=6;syndicate=4"
- attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
- sharp = TRUE
- flags_2 = RANDOM_BLOCKER_2
-
-/obj/item/butcher_chainsaw/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/butchers_humans)
- AddComponent(/datum/component/two_handed, \
- force_wielded = 40, \
- force_unwielded = force, \
- icon_wielded = "[base_icon_state]1", \
- wieldsound = 'sound/weapons/chainsawstart.ogg', \
- wield_callback = CALLBACK(src, PROC_REF(wield)), \
- unwield_callback = CALLBACK(src, PROC_REF(unwield)))
-
-/obj/item/butcher_chainsaw/update_icon_state()
- icon_state = "[base_icon_state]0"
-
-/obj/item/butcher_chainsaw/attack__legacy__attackchain(mob/living/target, mob/living/user)
- . = ..()
- if(HAS_TRAIT(src, TRAIT_WIELDED))
- playsound(loc, 'sound/weapons/chainsaw.ogg', 100, TRUE, -1) //incredibly loud; you ain't goin' for stealth with this thing. Credit to Lonemonk of Freesound for this sound.
- if(isnull(.)) //necessary check, successful attacks return null, without it target will drop any shields they may have before they get a chance to block
- target.KnockDown(8 SECONDS)
-
-/obj/item/butcher_chainsaw/afterattack__legacy__attackchain(mob/living/target, mob/living/user, proximity)
- if(!proximity) //only works on adjacent targets, no telekinetic chainsaws
- return
- if(!HAS_TRAIT(src, TRAIT_WIELDED))
- return
- if(isrobot(target)) //no buff from attacking robots
- return
- if(!isliving(target)) //no buff from attacking inanimate objects
- return
- if(user.reagents.get_reagent_amount("mephedrone") > 15) // No patrick, you do not get to be chainsaw stun immune and bullet immune at once
- return
- if(target.stat != DEAD) //no buff from attacking dead targets
- user.apply_status_effect(STATUS_EFFECT_CHAINSAW_SLAYING)
-
-/obj/item/butcher_chainsaw/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 == PROJECTILE_ATTACK)
- final_block_chance = 0 //It's a chainsaw, you try blocking bullets with it
- else if(owner.has_status_effect(STATUS_EFFECT_CHAINSAW_SLAYING))
- final_block_chance = 80 //Need to be ready to ruuuummbllleeee
- return ..()
-
-/obj/item/butcher_chainsaw/proc/wield() //you can't disarm an active chainsaw, you crazy person.
- set_nodrop(TRUE, loc)
-
-/obj/item/butcher_chainsaw/proc/unwield()
- set_nodrop(FALSE, loc)
-
// SINGULOHAMMER
/obj/item/singularityhammer
name = "singularity hammer"
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index 74948f38762..755a993a9c7 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -541,7 +541,7 @@
// snowflake checks my beloved
// this will become tooltype checks I swear
- if(!istype(I, /obj/item/circular_saw) && !istype(I, /obj/item/chainsaw) && !istype(I, /obj/item/butcher_chainsaw))
+ if(!istype(I, /obj/item/circular_saw) && !istype(I, /obj/item/chainsaw))
return
user.visible_message(
diff --git a/code/modules/hallucinations/effects/moderate.dm b/code/modules/hallucinations/effects/moderate.dm
index 515803ee627..3f5c3ec897f 100644
--- a/code/modules/hallucinations/effects/moderate.dm
+++ b/code/modules/hallucinations/effects/moderate.dm
@@ -61,7 +61,7 @@
"\improper ARG" = list('icons/obj/guns/projectile.dmi', "arg-30"),
"\improper C4" = list('icons/obj/grenade.dmi', "plastic-explosive0"),
"\improper L6 SAW" = list('icons/obj/guns/projectile.dmi', "l6closed100"),
- "chainsaw" = list('icons/obj/weapons/melee.dmi', "chainsaw0"),
+ "chainsaw" = list('icons/obj/weapons/melee.dmi', "chainsaw"),
"combat shotgun" = list('icons/obj/guns/projectile.dmi', "cshotgun"),
"double-bladed energy sword" = list('icons/obj/weapons/energy_melee.dmi', "dualsaberred1"),
"energy sword" = list('icons/obj/weapons/energy_melee.dmi', "swordred"),
diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm
index 871f91d8038..3db821ea1be 100644
--- a/code/modules/surgery/encased.dm
+++ b/code/modules/surgery/encased.dm
@@ -12,7 +12,6 @@
TOOL_SAW = 100,
/obj/item/hatchet = 90,
/obj/item/chainsaw = 90, // Chainsaws were actually invented to replace manual bonesaws. Obvously *these* chainsaws aren't exactly designed for that, but then again, neither is a hatchet or a set of wirecutters.
- /obj/item/butcher_chainsaw = 90,
TOOL_WIRECUTTER = 35 // Silly goose!
)
@@ -20,7 +19,6 @@
TOOL_SAW = 'sound/surgery/saw.ogg',
/obj/item/hatchet = 'sound/surgery/scalpel1.ogg',
/obj/item/chainsaw = 'sound/weapons/chainsaw.ogg',
- /obj/item/butcher_chainsaw = 'sound/weapons/chainsaw.ogg',
TOOL_WIRECUTTER = 'sound/surgery/scalpel1.ogg'
)
diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm
index 4719f0b4808..deaffda320a 100644
--- a/code/modules/surgery/generic.dm
+++ b/code/modules/surgery/generic.dm
@@ -21,7 +21,6 @@
/obj/item/melee/energy = 6,
/obj/item/pen/edagger = 6,
/obj/item/chainsaw = 1,
- /obj/item/butcher_chainsaw = 1
)
preop_sound = 'sound/surgery/scalpel1.ogg'
@@ -327,7 +326,6 @@
allowed_tools = list(
TOOL_SAW = 100,
/obj/item/chainsaw = 100, // It's pretty good at doing this outside of surgery tbh...
- /obj/item/butcher_chainsaw = 100,
/obj/item/hatchet = 90,
/obj/item/melee/arm_blade = 75,
/obj/item/claymore = 75,
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index aaaa9df0165..985bcb06377 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -689,8 +689,7 @@
TOOL_SAW = 100,
/obj/item/melee/energy/sword/cyborg/saw = 100,
/obj/item/hatchet = 90,
- /obj/item/chainsaw/ = 90,
- /obj/item/butcher_chainsaw = 90,
+ /obj/item/chainsaw = 90,
TOOL_WIRECUTTER = 35
)
@@ -698,7 +697,6 @@
TOOL_SAW = 'sound/surgery/saw.ogg',
/obj/item/hatchet = 'sound/surgery/scalpel1.ogg',
/obj/item/chainsaw = 'sound/weapons/chainsaw.ogg',
- /obj/item/butcher_chainsaw = 'sound/weapons/chainsaw.ogg',
TOOL_WIRECUTTER = 'sound/surgery/scalpel1.ogg'
)
@@ -743,7 +741,6 @@
/obj/item/melee/energy = 6,
/obj/item/pen/edagger = 6,
/obj/item/chainsaw = 1,
- /obj/item/butcher_chainsaw = 1
)
preop_sound = 'sound/surgery/scalpel1.ogg'
diff --git a/code/tests/test_anti_drop.dm b/code/tests/test_anti_drop.dm
index 96d1a3a7c71..7bb6df97879 100644
--- a/code/tests/test_anti_drop.dm
+++ b/code/tests/test_anti_drop.dm
@@ -30,7 +30,7 @@
player.puppet.drop_item_to_ground(belt)
TEST_ASSERT(!player.puppet.get_item_by_slot(ITEM_SLOT_BELT), "failed to remove belt after disabling NODROP")
- var/obj/item/butcher_chainsaw/saw = player.spawn_obj_in_hand(/obj/item/butcher_chainsaw)
+ var/obj/item/chainsaw/syndie/saw = player.spawn_obj_in_hand(/obj/item/chainsaw/syndie)
player.use_item_in_hand()
anti_drop.ui_action_click()
anti_drop.ui_action_click()
diff --git a/icons/mob/inhands/weapons_lefthand.dmi b/icons/mob/inhands/weapons_lefthand.dmi
index 3bb9588110f55fc3708aba82813a03ade1a40509..7966c89f2598a9619ed4e55ff255c95330bfcf09 100644
GIT binary patch
literal 70961
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%0DgZXrL8%L8Qbt=by6o_ZP{FN9O8jGEpD!
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