diff --git a/code/game/objects/items/boxcutter.dm b/code/game/objects/items/boxcutter.dm
deleted file mode 100644
index 5452cd013fb..00000000000
--- a/code/game/objects/items/boxcutter.dm
+++ /dev/null
@@ -1,62 +0,0 @@
-/obj/item/boxcutter
- name = "boxcutter"
- desc = "A tool for cutting boxes, or throats."
- icon = 'icons/obj/tools.dmi'
- icon_state = "boxcutter"
- inhand_icon_state = "boxcutter"
- base_icon_state = "boxcutter"
- icon_angle = -90
- lefthand_file = 'icons/mob/inhands/equipment/boxcutter_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/boxcutter_righthand.dmi'
- inhand_icon_state = null
- attack_verb_continuous = list("prods", "pokes")
- attack_verb_simple = list("prod", "poke")
- w_class = WEIGHT_CLASS_SMALL
- resistance_flags = FIRE_PROOF
- force = 0
- /// Used on Initialize, how much time to cut cable restraints and zipties.
- var/snap_time_weak_handcuffs = 0 SECONDS
- /// Used on Initialize, how much time to cut real handcuffs. Null means it can't.
- var/snap_time_strong_handcuffs = null
- /// Starts open if true
- var/start_extended = FALSE
-
-/obj/item/boxcutter/get_all_tool_behaviours()
- return list(TOOL_KNIFE)
-
-/obj/item/boxcutter/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/update_icon_updates_onmob)
- AddComponent(/datum/component/butchering, \
- speed = 7 SECONDS, \
- effectiveness = 100, \
- )
-
- AddComponent( \
- /datum/component/transforming, \
- start_transformed = start_extended, \
- force_on = 10, \
- throwforce_on = 4, \
- throw_speed_on = throw_speed, \
- sharpness_on = SHARP_EDGED, \
- hitsound_on = 'sound/items/weapons/bladeslice.ogg', \
- w_class_on = WEIGHT_CLASS_NORMAL, \
- attack_verb_continuous_on = list("cuts", "stabs", "slashes"), \
- attack_verb_simple_on = list("cut", "stab", "slash"), \
- )
-
- RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
-
-/obj/item/boxcutter/proc/on_transform(obj/item/source, mob/user, active)
- SIGNAL_HANDLER
-
- playsound(src, 'sound/items/boxcutter_activate.ogg', 50)
- tool_behaviour = (active ? TOOL_KNIFE : NONE)
- if(active)
- AddElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
- else
- RemoveElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
- return COMPONENT_NO_DEFAULT_MESSAGE
-
-/obj/item/boxcutter/extended
- start_extended = TRUE
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index a3d41245399..c0e35ee303a 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -4,6 +4,7 @@
* Bike Horns
* Air Horns
* Canned Laughter
+ * Balloon Mallet
*/
/*
@@ -294,3 +295,46 @@
icon_state = "laughter"
volume = 50
list_reagents = list(/datum/reagent/consumable/laughter = 50)
+
+//balloon mallet
+/obj/item/balloon_mallet
+ name = "balloon mallet"
+ desc = "It's a mallet, a weapon known for being heavy, but made from notoriously light balloons. Air inside removes any force from the swings. It'd be quite embarrassing to get hit by this."
+ icon = 'icons/obj/weapons/hammer.dmi'
+ icon_state = "balloon_mallet"
+ inhand_icon_state = "balloon_mallet"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
+ siemens_coefficient = 0
+ force = 1
+ throw_speed = 1
+ throwforce = 1
+ throw_range = 1
+ w_class = WEIGHT_CLASS_HUGE
+ attack_verb_continuous = list("mallets", "smoother")
+ attack_verb_simple = list("mallet", "smoother")
+ max_integrity = 20
+ armor_type = /datum/armor/item_banhammer
+ resistance_flags = FIRE_PROOF
+
+/obj/item/balloon_mallet/examine(mob/user)
+ . = ..()
+ if(HAS_TRAIT(user,TRAIT_BALLOON_SUTRA))
+ . += "A sacred weapon of the higher castes from the clown planet, used to strike fear into the hearts of their foes. Wield it with care."
+
+/obj/item/balloon_mallet/attack(mob/living/target, mob/living/user)
+ playsound(loc, 'sound/mobs/non-humanoids/clown/hehe.ogg', 20)
+ if (!isliving(target))
+ return
+ switch(target.mob_mood.sanity)
+ if (SANITY_INSANE to SANITY_CRAZY)
+ force = 8
+ if (SANITY_UNSTABLE to SANITY_DISTURBED)
+ force = 4
+ target.add_mood_event("humiliated", /datum/mood_event/mallet_humiliation)
+ if (SANITY_NEUTRAL to SANITY_GREAT)
+ target.add_mood_event("humiliated", /datum/mood_event/mallet_humiliation)
+
+ if(user.combat_mode)
+ return ..(target, user)
diff --git a/code/game/objects/items/tongs.dm b/code/game/objects/items/tongs.dm
deleted file mode 100644
index a6be04b604f..00000000000
--- a/code/game/objects/items/tongs.dm
+++ /dev/null
@@ -1,102 +0,0 @@
-/// Tongs, let you pick up and feed people food from further away.
-/obj/item/kitchen/tongs
- name = "tongs"
- desc = "So you never have to touch anything with your dirty, unwashed hands."
- reach = 2
- icon_state = "tongs"
- base_icon_state = "tongs"
- inhand_icon_state = "fork" // close enough
- icon_angle = -45
- attack_verb_continuous = list("pinches", "tongs", "nips")
- attack_verb_simple = list("pinch", "tong", "nip")
- /// What are we holding in our tongs?
- var/obj/item/tonged
- /// Sound to play when we click our tongs together
- var/clack_sound = 'sound/items/handling/component_drop.ogg'
- /// Time to wait between clacking sounds
- var/clack_delay = 2 SECONDS
- /// Have we clacked recently?
- COOLDOWN_DECLARE(clack_cooldown)
-
-/obj/item/kitchen/tongs/Destroy(force)
- QDEL_NULL(tonged)
- return ..()
-
-/obj/item/kitchen/tongs/examine(mob/user)
- . = ..()
- if (!isnull(tonged))
- . += span_notice("It is holding [tonged].")
-
-/obj/item/kitchen/tongs/dropped(mob/user, silent)
- . = ..()
- drop_tonged()
-
-/obj/item/kitchen/tongs/attack_self(mob/user, modifiers)
- . = ..()
- if(.)
- return TRUE
- if (!isnull(tonged))
- drop_tonged()
- return TRUE
- if (!COOLDOWN_FINISHED(src, clack_cooldown))
- return TRUE
- user.visible_message(span_notice("[user] clacks [user.p_their()] [name] together like a crab. Click clack!"))
- click_clack()
- return TRUE
-
-/// Release the food we are holding
-/obj/item/kitchen/tongs/proc/drop_tonged()
- if (isnull(tonged))
- return
- visible_message(span_notice("[tonged] falls to the ground!"))
- var/turf/location = drop_location()
- tonged.forceMove(location)
- tonged.do_drop_animation(location)
-
-/// Play a clacking sound and appear closed, then open again
-/obj/item/kitchen/tongs/proc/click_clack()
- COOLDOWN_START(src, clack_cooldown, clack_delay)
- playsound(src, clack_sound, vol = 100, vary = FALSE)
- icon_state = "[base_icon_state]_closed"
- var/delay = min(0.5 SECONDS, clack_delay / 2) // Just in case someone's been fucking with the cooldown
- addtimer(CALLBACK(src, PROC_REF(clack)), delay, TIMER_DELETE_ME)
-
-/// Plays a clacking sound and appear open
-/obj/item/kitchen/tongs/proc/clack()
- playsound(src, clack_sound, vol = 100, vary = FALSE)
- icon_state = base_icon_state
-
-/obj/item/kitchen/tongs/Exited(atom/movable/leaving, direction)
- . = ..()
- if (leaving != tonged)
- return
- tonged = null
- update_appearance(UPDATE_ICON)
-
-/obj/item/kitchen/tongs/pre_attack(obj/item/attacked, mob/living/user, list/modifiers, list/attack_modifiers)
- if (!isnull(tonged) && tonged.force <= 0) // prevents tongs from giving food-weapons extra range
- attacked.attackby(tonged, user)
- return TRUE
- if (isliving(attacked))
- if (COOLDOWN_FINISHED(src, clack_cooldown))
- click_clack()
- return ..()
- if (!IS_EDIBLE(attacked) || attacked.w_class > WEIGHT_CLASS_NORMAL || !isnull(tonged))
- return ..()
- tonged = attacked
- attacked.do_pickup_animation(src)
- attacked.forceMove(src)
- update_appearance(UPDATE_ICON)
- return TRUE
-
-/obj/item/kitchen/tongs/update_overlays()
- . = ..()
- if (isnull(tonged))
- return
- var/mutable_appearance/held_food = new /mutable_appearance(tonged.appearance)
- held_food.layer = layer
- held_food.plane = plane
- held_food.transform = held_food.transform.Scale(0.7, 0.7)
- held_food.pixel_w = 6
- held_food.pixel_z = 6
- . += held_food
diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/tools/control_wand.dm
similarity index 100%
rename from code/game/objects/items/control_wand.dm
rename to code/game/objects/items/tools/control_wand.dm
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/engineering/crowbar.dm
similarity index 100%
rename from code/game/objects/items/tools/crowbar.dm
rename to code/game/objects/items/tools/engineering/crowbar.dm
diff --git a/code/game/objects/items/tools/painter/airlock_painter.dm b/code/game/objects/items/tools/engineering/painter/airlock_painter.dm
similarity index 100%
rename from code/game/objects/items/tools/painter/airlock_painter.dm
rename to code/game/objects/items/tools/engineering/painter/airlock_painter.dm
diff --git a/code/game/objects/items/tools/painter/decal_painter.dm b/code/game/objects/items/tools/engineering/painter/decal_painter.dm
similarity index 100%
rename from code/game/objects/items/tools/painter/decal_painter.dm
rename to code/game/objects/items/tools/engineering/painter/decal_painter.dm
diff --git a/code/game/objects/items/tools/painter/paintable_decals.dm b/code/game/objects/items/tools/engineering/painter/paintable_decals.dm
similarity index 100%
rename from code/game/objects/items/tools/painter/paintable_decals.dm
rename to code/game/objects/items/tools/engineering/painter/paintable_decals.dm
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/engineering/screwdriver.dm
similarity index 100%
rename from code/game/objects/items/tools/screwdriver.dm
rename to code/game/objects/items/tools/engineering/screwdriver.dm
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/engineering/weldingtool.dm
similarity index 100%
rename from code/game/objects/items/tools/weldingtool.dm
rename to code/game/objects/items/tools/engineering/weldingtool.dm
diff --git a/code/game/objects/items/tools/wirebrush.dm b/code/game/objects/items/tools/engineering/wirebrush.dm
similarity index 100%
rename from code/game/objects/items/tools/wirebrush.dm
rename to code/game/objects/items/tools/engineering/wirebrush.dm
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/engineering/wirecutters.dm
similarity index 100%
rename from code/game/objects/items/tools/wirecutters.dm
rename to code/game/objects/items/tools/engineering/wirecutters.dm
diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/engineering/wrench.dm
similarity index 100%
rename from code/game/objects/items/tools/wrench.dm
rename to code/game/objects/items/tools/engineering/wrench.dm
diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/tools/extinguisher.dm
similarity index 100%
rename from code/game/objects/items/extinguisher.dm
rename to code/game/objects/items/tools/extinguisher.dm
diff --git a/code/game/objects/items/inducer.dm b/code/game/objects/items/tools/inducer.dm
similarity index 100%
rename from code/game/objects/items/inducer.dm
rename to code/game/objects/items/tools/inducer.dm
diff --git a/code/game/objects/items/broom.dm b/code/game/objects/items/tools/janitorial/broom.dm
similarity index 100%
rename from code/game/objects/items/broom.dm
rename to code/game/objects/items/tools/janitorial/broom.dm
diff --git a/code/game/objects/items/janitor_key.dm b/code/game/objects/items/tools/janitorial/janitor_key.dm
similarity index 100%
rename from code/game/objects/items/janitor_key.dm
rename to code/game/objects/items/tools/janitorial/janitor_key.dm
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/tools/medical/bodybag.dm
similarity index 100%
rename from code/game/objects/items/bodybag.dm
rename to code/game/objects/items/tools/medical/bodybag.dm
diff --git a/code/game/objects/items/tools/medical/cane.dm b/code/game/objects/items/tools/medical/cane.dm
new file mode 100644
index 00000000000..132f03a9b37
--- /dev/null
+++ b/code/game/objects/items/tools/medical/cane.dm
@@ -0,0 +1,147 @@
+/obj/item/cane
+ name = "cane"
+ desc = "A cane used by a true gentleman. Or a clown."
+ icon = 'icons/obj/weapons/staff.dmi'
+ icon_state = "cane"
+ inhand_icon_state = "stick"
+ icon_angle = 135
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 5
+ throwforce = 5
+ w_class = WEIGHT_CLASS_SMALL
+ custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5)
+ attack_verb_continuous = list("bludgeons", "whacks", "disciplines", "thrashes")
+ attack_verb_simple = list("bludgeon", "whack", "discipline", "thrash")
+
+/obj/item/cane/examine(mob/user, thats)
+ . = ..()
+ . += span_notice("This item can be used to support your weight, preventing limping from any broken bones on your legs you may have.")
+
+/obj/item/cane/equipped(mob/living/user, slot, initial)
+ ..()
+ if(!(slot & ITEM_SLOT_HANDS))
+ return
+ movement_support_add(user)
+
+/obj/item/cane/dropped(mob/living/user, silent = FALSE)
+ . = ..()
+ movement_support_del(user)
+
+/obj/item/cane/proc/movement_support_add(mob/living/user)
+ RegisterSignal(user, COMSIG_CARBON_LIMPING, PROC_REF(handle_limping))
+ return TRUE
+
+/obj/item/cane/proc/movement_support_del(mob/living/user)
+ UnregisterSignal(user, list(COMSIG_CARBON_LIMPING))
+ return TRUE
+
+/obj/item/cane/proc/handle_limping(mob/living/user)
+ SIGNAL_HANDLER
+ return COMPONENT_CANCEL_LIMP
+
+/obj/item/cane/crutch
+ name = "medical crutch"
+ desc = "A medical crutch used by people missing a leg. Not all that useful if you're missing both of them, though."
+ icon = 'icons/obj/weapons/staff.dmi'
+ icon_state = "crutch_med"
+ inhand_icon_state = "crutch_med"
+ icon_angle = 45
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 12
+ throwforce = 8
+ w_class = WEIGHT_CLASS_BULKY
+ custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5)
+ attack_verb_continuous = list("bludgeons", "whacks", "thrashes")
+ attack_verb_simple = list("bludgeon", "whack", "thrash")
+
+/obj/item/cane/crutch/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/cuffable_item)
+
+/obj/item/cane/crutch/examine(mob/user, thats)
+ . = ..()
+ // tacked on after the cane string
+ . += span_notice("As a crutch, it can also help lessen the slowdown incurred by missing a leg.")
+
+/obj/item/cane/crutch/movement_support_add(mob/living/user)
+ . = ..()
+ if(!.)
+ return
+ RegisterSignal(user, COMSIG_LIVING_LIMBLESS_SLOWDOWN, PROC_REF(handle_slowdown))
+ user.update_usable_leg_status()
+ user.AddElementTrait(TRAIT_WADDLING, REF(src), /datum/element/waddling)
+
+/obj/item/cane/crutch/movement_support_del(mob/living/user)
+ . = ..()
+ if(!.)
+ return
+ UnregisterSignal(user, list(COMSIG_LIVING_LIMBLESS_SLOWDOWN, COMSIG_CARBON_LIMPING))
+ user.update_usable_leg_status()
+ REMOVE_TRAIT(user, TRAIT_WADDLING, REF(src))
+
+/obj/item/cane/crutch/proc/handle_slowdown(mob/living/user, limbless_slowdown, list/slowdown_mods)
+ SIGNAL_HANDLER
+ var/leg_amount = user.usable_legs
+ // Don't do anything if the number is equal (or higher) to the usual.
+ if(leg_amount >= user.default_num_legs)
+ return
+ // If we have at least one leg and it's less than the default, reduce slowdown by 60%.
+ if(leg_amount && (leg_amount < user.default_num_legs))
+ slowdown_mods += 0.4
+
+/obj/item/cane/crutch/wood
+ name = "wooden crutch"
+ desc = "A handmade crutch. Also makes a decent bludgeon if you need it."
+ icon_state = "crutch_wood"
+ inhand_icon_state = "crutch_wood"
+ custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 5)
+
+/obj/item/cane/white
+ name = "white cane"
+ desc = "Traditionally used by the blind to help them see. Folds down to be easier to transport."
+ icon_state = "cane_white"
+ inhand_icon_state = "cane_white"
+ icon_angle = 45
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 1
+ w_class = WEIGHT_CLASS_SMALL
+ custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 6)
+
+/obj/item/cane/white/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/cuffable_item)
+ AddComponent( \
+ /datum/component/transforming, \
+ force_on = 7, \
+ hitsound_on = hitsound, \
+ w_class_on = WEIGHT_CLASS_BULKY, \
+ clumsy_check = FALSE, \
+ attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \
+ attack_verb_simple_on = list("smack", "strike", "crack", "beat"), \
+ )
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
+
+/obj/item/cane/white/handle_limping(mob/living/user)
+ return HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE) ? COMPONENT_CANCEL_LIMP : NONE
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Gives feedback to the user and makes it show up inhand.
+ */
+/obj/item/cane/white/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ if(user)
+ balloon_alert(user, active ? "extended" : "collapsed")
+
+ if(!HAS_TRAIT(src, TRAIT_BLIND_TOOL))
+ ADD_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT)
+ else
+ REMOVE_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT)
+
+ playsound(src, 'sound/items/weapons/batonextend.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/tools/medical/defib.dm
similarity index 100%
rename from code/game/objects/items/defib.dm
rename to code/game/objects/items/tools/medical/defib.dm
diff --git a/code/game/objects/items/reflex_hammer.dm b/code/game/objects/items/tools/medical/reflex_hammer.dm
similarity index 100%
rename from code/game/objects/items/reflex_hammer.dm
rename to code/game/objects/items/tools/medical/reflex_hammer.dm
diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/tools/theft_tools.dm
similarity index 100%
rename from code/game/objects/items/theft_tools.dm
rename to code/game/objects/items/tools/theft_tools.dm
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index c9f04348682..2bd52a0577e 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -16,7 +16,7 @@
* Toy big red button
* Beach ball
* Toy xeno
- * Kitty toys!
+ * Kitty toys!
* Snowballs
* Clockwork Watches
* Toy Daggers
@@ -25,6 +25,8 @@
* Fake heretic codex
* Fake Pierced Reality
* Intento
+ * Extendo hand
+ * Ban hammer
*/
/obj/item/toy
abstract_type = /obj/item/toy
@@ -1846,3 +1848,70 @@ GLOBAL_LIST_EMPTY(intento_players)
attack_verb_simple = list("smack", "club", "wack", "vendor")
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
+
+/obj/item/extendohand
+ name = "extendo-hand"
+ desc = "Futuristic tech has allowed these classic spring-boxing toys to essentially act as a fully functional hand-operated hand prosthetic."
+ icon = 'icons/obj/toys/toy.dmi'
+ icon_state = "extendohand"
+ inhand_icon_state = "extendohand"
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 0
+ throwforce = 5
+ reach = 2
+ var/min_reach = 2
+
+/obj/item/extendohand/acme
+ name = "\improper ACME Extendo-Hand"
+ desc = "A novelty extendo-hand produced by the ACME corporation. Originally designed to knock out roadrunners."
+
+/obj/item/extendohand/attack(atom/M, mob/living/carbon/human/user, list/modifiers, list/attack_modifiers)
+ var/dist = get_dist(M, user)
+ if(dist < min_reach)
+ to_chat(user, span_warning("[M] is too close to use [src] on."))
+ return
+ M.attack_hand(user, modifiers)
+
+/obj/item/banhammer
+ desc = "A banhammer."
+ name = "banhammer"
+ icon = 'icons/obj/weapons/hammer.dmi'
+ icon_state = "toyhammer"
+ icon_angle = -45
+ slot_flags = ITEM_SLOT_BELT
+ throwforce = 0
+ force = 1
+ w_class = WEIGHT_CLASS_TINY
+ throw_speed = 3
+ throw_range = 7
+ attack_verb_continuous = list("bans")
+ attack_verb_simple = list("ban")
+ max_integrity = 200
+ armor_type = /datum/armor/item_banhammer
+ resistance_flags = FIRE_PROOF
+
+/datum/armor/item_banhammer
+ fire = 100
+ acid = 70
+
+/obj/item/banhammer/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/kneejerk)
+
+/obj/item/banhammer/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life."))
+ return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
+/*
+oranges says: This is a meme relating to the english translation of the ss13 russian wiki page on lurkmore.
+mrdoombringer sez: and remember kids, if you try and PR a fix for this item's grammar, you are admitting that you are, indeed, a newfriend.
+for further reading, please see: https://github.com/tgstation/tgstation/pull/30173 and https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=%2F%2Flurkmore.to%2FSS13&edit-text=&act=url
+*/
+/obj/item/banhammer/attack(mob/M, mob/living/user)
+ if(user.zone_selected == BODY_ZONE_HEAD)
+ M.visible_message(span_danger("[user] are stroking the head of [M] with a bangammer."), span_userdanger("[user] are stroking your head with a bangammer."), span_hear("You hear a bangammer stroking a head.")) // see above comment
+ else
+ M.visible_message(span_danger("[M] has been banned FOR NO REISIN by [user]!"), span_userdanger("You have been banned FOR NO REISIN by [user]!"), span_hear("You hear a banhammer banning someone."))
+ playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much
+ if(user.combat_mode)
+ return ..(M, user)
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
deleted file mode 100644
index 5b128b21ab0..00000000000
--- a/code/game/objects/items/weaponry.dm
+++ /dev/null
@@ -1,1315 +0,0 @@
-/obj/item/banhammer
- desc = "A banhammer."
- name = "banhammer"
- icon = 'icons/obj/weapons/hammer.dmi'
- icon_state = "toyhammer"
- icon_angle = -45
- slot_flags = ITEM_SLOT_BELT
- throwforce = 0
- force = 1
- w_class = WEIGHT_CLASS_TINY
- throw_speed = 3
- throw_range = 7
- attack_verb_continuous = list("bans")
- attack_verb_simple = list("ban")
- max_integrity = 200
- armor_type = /datum/armor/item_banhammer
- resistance_flags = FIRE_PROOF
-
-/datum/armor/item_banhammer
- fire = 100
- acid = 70
-
-/obj/item/banhammer/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/kneejerk)
-
-/obj/item/banhammer/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life."))
- return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
-/*
-oranges says: This is a meme relating to the english translation of the ss13 russian wiki page on lurkmore.
-mrdoombringer sez: and remember kids, if you try and PR a fix for this item's grammar, you are admitting that you are, indeed, a newfriend.
-for further reading, please see: https://github.com/tgstation/tgstation/pull/30173 and https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=%2F%2Flurkmore.to%2FSS13&edit-text=&act=url
-*/
-/obj/item/banhammer/attack(mob/M, mob/living/user)
- if(user.zone_selected == BODY_ZONE_HEAD)
- M.visible_message(span_danger("[user] are stroking the head of [M] with a bangammer."), span_userdanger("[user] are stroking your head with a bangammer."), span_hear("You hear a bangammer stroking a head.")) // see above comment
- else
- M.visible_message(span_danger("[M] has been banned FOR NO REISIN by [user]!"), span_userdanger("You have been banned FOR NO REISIN by [user]!"), span_hear("You hear a banhammer banning someone."))
- playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much
- if(user.combat_mode)
- return ..(M, user)
-
-
-/obj/item/balloon_mallet
- name = "balloon mallet"
- desc = "It's a mallet, a weapon known for being heavy, but made from notoriously light balloons. Air inside removes any force from the swings. It'd be quite embarrassing to get hit by this."
- icon = 'icons/obj/weapons/hammer.dmi'
- icon_state = "balloon_mallet"
- inhand_icon_state = "balloon_mallet"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
- siemens_coefficient = 0
- force = 1
- throw_speed = 1
- throwforce = 1
- throw_range = 1
- w_class = WEIGHT_CLASS_HUGE
- attack_verb_continuous = list("mallets", "smoother")
- attack_verb_simple = list("mallet", "smoother")
- max_integrity = 20
- armor_type = /datum/armor/item_banhammer
- resistance_flags = FIRE_PROOF
-
-/obj/item/balloon_mallet/examine(mob/user)
- . = ..()
- if(HAS_TRAIT(user,TRAIT_BALLOON_SUTRA))
- . += "A sacred weapon of the higher castes from the clown planet, used to strike fear into the hearts of their foes. Wield it with care."
-
-/obj/item/balloon_mallet/attack(mob/living/target, mob/living/user)
- playsound(loc, 'sound/mobs/non-humanoids/clown/hehe.ogg', 20)
- if (!isliving(target))
- return
- switch(target.mob_mood.sanity)
- if (SANITY_INSANE to SANITY_CRAZY)
- force = 8
- if (SANITY_UNSTABLE to SANITY_DISTURBED)
- force = 4
- target.add_mood_event("humiliated", /datum/mood_event/mallet_humiliation)
- if (SANITY_NEUTRAL to SANITY_GREAT)
- target.add_mood_event("humiliated", /datum/mood_event/mallet_humiliation)
-
- if(user.combat_mode)
- return ..(target, user)
-
-/obj/item/sord
- name = "\improper SORD"
- desc = "This thing is so unspeakably shitty you are having a hard time even holding it."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "sord"
- inhand_icon_state = "sord"
- icon_angle = -35
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- slot_flags = ITEM_SLOT_BELT
- force = 2
- throwforce = 1
- w_class = WEIGHT_CLASS_NORMAL
- hitsound = 'sound/items/weapons/bladeslice.ogg'
- attack_verb_continuous = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
-
-/obj/item/sord/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty."), \
- span_suicide("You try to impale yourself with [src], but it's USELESS..."))
- return SHAME
-
-/obj/item/claymore
- name = "claymore"
- desc = "What are you standing around staring at this for? Get to killing!"
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "claymore"
- inhand_icon_state = "claymore"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- hitsound = 'sound/items/weapons/bladeslice.ogg'
- obj_flags = CONDUCTS_ELECTRICITY
- slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
- force = 40
- throwforce = 10
- w_class = WEIGHT_CLASS_NORMAL
- attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
- block_chance = 50
- block_sound = 'sound/items/weapons/parry.ogg'
- sharpness = SHARP_EDGED
- max_integrity = 200
- armor_type = /datum/armor/item_claymore
- resistance_flags = FIRE_PROOF
- var/list/alt_continuous = list("stabs", "pierces", "impales")
- var/list/alt_simple = list("stab", "pierce", "impale")
-
-/datum/armor/item_claymore
- fire = 100
- acid = 50
-
-/obj/item/claymore/Initialize(mapload)
- . = ..()
- alt_continuous = string_list(alt_continuous)
- alt_simple = string_list(alt_simple)
- make_stabby()
- AddComponent(/datum/component/butchering, \
- speed = 4 SECONDS, \
- effectiveness = 105, \
- )
-
-// Applies alt sharpness component, for overrides
-/obj/item/claymore/proc/make_stabby()
- AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -15)
-
-/obj/item/claymore/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
- return BRUTELOSS
-
-/obj/item/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
- if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
- final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you.
- return ..()
-
-//statistically similar to e-cutlasses
-/obj/item/claymore/cutlass
- name = "cutlass"
- desc = "A piratey sword used by buckaneers to \"negotiate\" the transfer of treasure."
- icon_state = "cutlass"
- inhand_icon_state = "cutlass"
- worn_icon_state = "cutlass"
- slot_flags = ITEM_SLOT_BACK
- force = 30
- throwforce = 20
- throw_speed = 3
- throw_range = 5
- armour_penetration = 35
-
-/obj/item/claymore/cutlass/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/cuffable_item) //closed sword guard
-
-/obj/item/claymore/cutlass/old
- name = "old cutlass"
- desc = parent_type::desc + " This one seems a tad old."
- force = 24
- throwforce = 17
- armour_penetration = 20
- block_chance = 30
-
-/obj/item/claymore/carrot
- name = "carrot sword"
- desc = "A full-sized carrot sword. Definitely not good for the eyes, not anymore."
- icon_state = "carrot_sword"
- inhand_icon_state = "carrot_sword"
- worn_icon_state = "carrot_sword"
- flags_1 = NONE
- force = 19
- throwforce = 7
- throw_speed = 3
- throw_range = 7
- armour_penetration = 5
- block_chance = 10
- resistance_flags = NONE
-
-//bootleg claymore
-/obj/item/claymore/shortsword
- name = "shortsword"
- desc = "A mercenary's sword, chipped and worn from battles long gone. You could say it is a swordsman's shortsword short sword."
- icon_state = "shortsword"
- inhand_icon_state = "shortsword"
- worn_icon_state = "shortsword"
- slot_flags = ITEM_SLOT_BELT
- force = 20
- demolition_mod = 0.75
- block_chance = 30
-
-/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
- desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim."
- obj_flags = CONDUCTS_ELECTRICITY
- item_flags = DROPDEL //WOW BRO YOU LOST AN ARM, GUESS WHAT YOU DONT GET YOUR SWORD ANYMORE //I CANT BELIEVE SPOOKYDONUT WOULD BREAK THE REQUIREMENTS
- slot_flags = null
- block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
- light_range = 3
- attack_verb_continuous = list("brutalizes", "eviscerates", "disembowels", "hacks", "carves", "cleaves") //ONLY THE MOST VISCERAL ATTACK VERBS
- attack_verb_simple = list("brutalize", "eviscerate", "disembowel", "hack", "carve", "cleave")
- var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE
- var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK
-
-/obj/item/claymore/highlander/Initialize(mapload)
- . = ..()
- ADD_TRAIT(src, TRAIT_NODROP, HIGHLANDER_TRAIT)
- START_PROCESSING(SSobj, src)
-
-/obj/item/claymore/highlander/Destroy()
- if(nuke_disk)
- nuke_disk.forceMove(get_turf(src))
- nuke_disk.visible_message(span_warning("The nuke disk is vulnerable!"))
- nuke_disk = null
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-/obj/item/claymore/highlander/process()
- if(ishuman(loc))
- var/mob/living/carbon/human/holder = loc
- holder.layer = ABOVE_ALL_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS)
- ADD_TRAIT(holder, TRAIT_NOBLOOD, HIGHLANDER_TRAIT) //AND WE WON'T BLEED OUT LIKE COWARDS
- else
- if(!(flags_1 & ADMIN_SPAWNED_1))
- qdel(src)
-
-
-/obj/item/claymore/highlander/pickup(mob/living/user)
- . = ..()
- to_chat(user, span_notice("The power of Scotland protects you! You are shielded from all stuns and knockdowns."))
- user.ignore_slowdown(HIGHLANDER_TRAIT)
- user.add_stun_absorption(
- source = HIGHLANDER_TRAIT,
- message = span_warning("%EFFECT_OWNER is protected by the power of Scotland!"),
- self_message = span_boldwarning("The power of Scotland absorbs the stun!"),
- examine_message = span_warning("%EFFECT_OWNER_THEYRE protected by the power of Scotland!"),
- )
-
-/obj/item/claymore/highlander/dropped(mob/living/user)
- . = ..()
- user.unignore_slowdown(HIGHLANDER_TRAIT)
- user.remove_stun_absorption(HIGHLANDER_TRAIT)
-
-/obj/item/claymore/highlander/examine(mob/user)
- . = ..()
- . += "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade."
- if(nuke_disk)
- . += span_boldwarning("It's holding the nuke disk!")
-
-/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user)
- . = ..()
- if(!QDELETED(target) && target.stat == DEAD && target.mind?.has_antag_datum(/datum/antagonist/highlander))
- user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
- add_notch(user)
- target.visible_message(span_warning("[target] crumbles to dust beneath [user]'s blows!"), span_userdanger("As you fall, your body crumbles to dust!"))
- target.investigate_log("has been dusted by a highlander claymore.", INVESTIGATE_DEATHS)
- target.dust()
-
-/obj/item/claymore/highlander/attack_self(mob/living/user)
- var/closest_victim
- var/closest_distance = 255
- for(var/mob/living/carbon/human/scot in GLOB.player_list - user)
- if(scot.mind?.has_antag_datum(/datum/antagonist/highlander) && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
- closest_victim = scot
- for(var/mob/living/silicon/robot/siliscot in GLOB.player_list - user)
- if(siliscot.mind?.has_antag_datum(/datum/antagonist/highlander) && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
- closest_victim = siliscot
-
- if(!closest_victim)
- to_chat(user, span_warning("[src] thrums for a moment and falls dark. Perhaps there's nobody nearby."))
- return
- to_chat(user, span_danger("[src] thrums and points to the [dir2text(get_dir(user, closest_victim))]."))
-
-/obj/item/claymore/highlander/IsReflect()
- return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME?
-
-/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
- notches++
- force++
- var/new_name = name
- switch(notches)
- if(1)
- to_chat(user, span_notice("Your first kill - hopefully one of many. You scratch a notch into [src]'s blade."))
- to_chat(user, span_warning("You feel your fallen foe's soul entering your blade, restoring your wounds!"))
- new_name = "notched claymore"
- if(2)
- to_chat(user, span_notice("Another falls before you. Another soul fuses with your own. Another notch in the blade."))
- new_name = "double-notched claymore"
- add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY)
- if(3)
- to_chat(user, span_notice("You're beginning to relish the thrill of battle."))
- new_name = "triple-notched claymore"
- add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY)
- if(4)
- to_chat(user, span_notice("You've lost count of how many you've killed."))
- new_name = "many-notched claymore"
- add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY)
- if(5)
- to_chat(user, span_bolddanger("Five voices now echo in your mind, cheering the slaughter."))
- new_name = "battle-tested claymore"
- add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY)
- if(6)
- to_chat(user, span_bolddanger("Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe."))
- new_name = "battle-scarred claymore"
- add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY)
- if(7)
- to_chat(user, span_bolddanger("Kill. Butcher. Conquer."))
- new_name = "vicious claymore"
- add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY)
- if(8)
- to_chat(user, span_userdanger("IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE."))
- new_name = "bloodthirsty claymore"
- add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY)
- if(9)
- to_chat(user, span_userdanger("ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE."))
- new_name = "gore-stained claymore"
- add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY)
- if(10)
- user.visible_message(span_warning("[user]'s eyes light up with a vengeful fire!"), \
- span_userdanger("YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!"))
- new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]"
- icon_state = "claymore_gold"
- inhand_icon_state = "cultblade"
- lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
- remove_atom_colour(ADMIN_COLOUR_PRIORITY)
- user.update_held_items()
-
- name = new_name
- playsound(user, 'sound/items/tools/screwdriver2.ogg', 50, TRUE)
-
-/obj/item/claymore/highlander/robot //BLOODTHIRSTY BORGS NOW COME IN PLAID
- icon = 'icons/obj/items_cyborg.dmi'
- icon_state = "claymore_cyborg"
-
-/obj/item/claymore/highlander/robot/Initialize(mapload)
- . = ..()
- if(!iscyborg(loc))
- return INITIALIZE_HINT_QDEL
-
-/obj/item/claymore/highlander/robot/process()
- loc.layer = ABOVE_ALL_MOB_LAYER
-
-/obj/item/claymore/gladius
- name = "gladius"
- desc = "A short but formidable sword, favored by recently-reanimated ancient warriors."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "gladius"
- inhand_icon_state = "gladius"
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- sharpness = SHARP_POINTY
- attack_verb_continuous = list("stabs", "cuts")
- attack_verb_simple = list("stab", "cut")
- slot_flags = null
- sound_vary = TRUE
- block_sound = 'sound/items/weapons/parry.ogg'
- hitsound = 'sound/items/weapons/bladeslice.ogg'
- pickup_sound = SFX_KNIFE_PICKUP
- drop_sound = SFX_KNIFE_DROP
-
-
-/obj/item/katana
- name = "katana"
- desc = "Woefully underpowered in D20."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "katana"
- inhand_icon_state = "katana"
- worn_icon_state = "katana"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- obj_flags = CONDUCTS_ELECTRICITY
- slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
- force = 40
- throwforce = 10
- w_class = WEIGHT_CLASS_HUGE
- hitsound = 'sound/items/weapons/bladeslice.ogg'
- attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
- block_chance = 50
- block_sound = 'sound/items/weapons/parry.ogg'
- sharpness = SHARP_EDGED
- max_integrity = 200
- armor_type = /datum/armor/item_katana
- resistance_flags = FIRE_PROOF
- var/list/alt_continuous = list("stabs", "pierces", "impales")
- var/list/alt_simple = list("stab", "pierce", "impale")
-
-/obj/item/katana/Initialize(mapload)
- . = ..()
- alt_continuous = string_list(alt_continuous)
- alt_simple = string_list(alt_simple)
- AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -15)
-
-/obj/item/katana/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
- if(attack_type == OVERWHELMING_ATTACK)
- final_block_chance = 0 //Not a high freuqnecy blade, sorry pal
- return ..()
-
-/datum/armor/item_katana
- fire = 100
- acid = 50
-
-/obj/item/katana/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!"))
- return BRUTELOSS
-
-/obj/item/katana/cursed //used by wizard events, see the tendril_loot.dm file for the miner one
- slot_flags = null
-
-/obj/item/throwing_star
- name = "throwing star"
- desc = "An ancient weapon still used to this day, due to its ease of lodging itself into its victim's body parts."
- icon = 'icons/obj/weapons/thrown.dmi'
- icon_state = "throwingstar"
- inhand_icon_state = "eshield"
- lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
- force = 2
- throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
- throw_speed = 4
- embed_type = /datum/embedding/throwing_star
- armour_penetration = 40
- mob_throw_hit_sound = 'sound/items/weapons/pierce.ogg'
- hitsound = 'sound/items/weapons/bladeslice.ogg'
-
- w_class = WEIGHT_CLASS_SMALL
- sharpness = SHARP_POINTY
- custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 5)
- resistance_flags = FIRE_PROOF
-
-/datum/embedding/throwing_star
- pain_mult = 4
- embed_chance = 100
- fall_chance = 0
-
-/obj/item/throwing_star/stamina
- name = "shock throwing star"
- desc = "An aerodynamic disc designed to cause excruciating pain when stuck inside fleeing targets, hopefully without causing fatal harm."
- throwforce = 5
- embed_type = /datum/embedding/throwing_star/stamina
-
-/datum/embedding/throwing_star/stamina
- pain_mult = 5
- jostle_chance = 10
- pain_stam_pct = 0.8
- jostle_pain_mult = 3
-
-/obj/item/throwing_star/toy
- name = "toy throwing star"
- desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security."
- sharpness = NONE
- force = 0
- throwforce = 0
- embed_type = /datum/embedding/throwing_star/toy
-
-/datum/embedding/throwing_star/toy
- pain_mult = 0
- jostle_pain_mult = 0
-
-/obj/item/carpenter_hammer
- name = "carpenter hammer"
- icon = 'icons/obj/weapons/hammer.dmi'
- icon_state = "carpenter_hammer"
- inhand_icon_state = "carpenter_hammer"
- worn_icon_state = "clawhammer" //plaecholder
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
- desc = "Uncanny looking hammer."
- force = 17
- throwforce = 14
- throw_range = 4
- w_class = WEIGHT_CLASS_NORMAL
- wound_bonus = 20
- demolition_mod = 1.15
- slot_flags = ITEM_SLOT_BELT
-
-/obj/item/carpenter_hammer/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/kneejerk)
- AddComponent(/datum/component/item_killsound, \
- allowed_mobs = list(/mob/living/carbon/human), \
- killsound = 'sound/items/weapons/hammer_death_scream.ogg', \
- replace_default_death_sound = TRUE, \
- )
-
-/obj/item/carpenter_hammer/examine(mob/user)
- . = ..()
- . += ""
- . += "Real World Tip:"
- . += pick(
- "Every building, from hospitals to homes, has a room that serves as the heart of the building \
- and carries blood and nutrients to its extremities. Try to find the heart of your home!",
- "All the food you've tried is rotten. You've never eaten fresh food.",
- "Viruses do not exist. Illness is simply your body punishing you for what you have done wrong.",
- "Space stations must have at least 50 mammalian teeth embedded in the north walls for structural safety reasons.",
- "Queen dragonfly sleeps and smiles.",
- )
-
-/obj/item/switchblade
- name = "switchblade"
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "switchblade"
- base_icon_state = "switchblade"
- icon_angle = -90
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- desc = "A sharp, concealable, spring-loaded knife."
- obj_flags = CONDUCTS_ELECTRICITY
- force = 3
- w_class = WEIGHT_CLASS_SMALL
- throwforce = 5
- throw_speed = 3
- throw_range = 6
- custom_materials = list(/datum/material/iron= SHEET_MATERIAL_AMOUNT * 6)
- hitsound = 'sound/items/weapons/genhit.ogg'
- attack_verb_continuous = list("stubs", "pokes")
- attack_verb_simple = list("stub", "poke")
- resistance_flags = FIRE_PROOF
- /// Whether the switchblade starts extended or not.
- var/start_extended = FALSE
- var/list/alt_continuous = list("stabs", "pierces", "shanks")
- var/list/alt_simple = list("stab", "pierce", "shank")
-
-/obj/item/switchblade/get_all_tool_behaviours()
- return list(TOOL_KNIFE)
-
-/obj/item/switchblade/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/update_icon_updates_onmob)
- AddComponent(/datum/component/butchering, \
- speed = 7 SECONDS, \
- effectiveness = 100, \
- )
-
- AddComponent( \
- /datum/component/transforming, \
- start_transformed = start_extended, \
- force_on = 20, \
- throwforce_on = 23, \
- throw_speed_on = throw_speed, \
- sharpness_on = SHARP_EDGED, \
- hitsound_on = 'sound/items/weapons/bladeslice.ogg', \
- w_class_on = WEIGHT_CLASS_NORMAL, \
- attack_verb_continuous_on = list("slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts"), \
- attack_verb_simple_on = list("slash", "slice", "tear", "lacerate", "rip", "dice", "cut"), \
- )
-
- alt_continuous = string_list(alt_continuous)
- alt_simple = string_list(alt_simple)
- AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -5, TRAIT_TRANSFORM_ACTIVE)
-
- RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
-
-/obj/item/switchblade/proc/on_transform(obj/item/source, mob/user, active)
- SIGNAL_HANDLER
-
- tool_behaviour = (active ? TOOL_KNIFE : NONE)
-
-/obj/item/switchblade/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
- return BRUTELOSS
-
-/obj/item/switchblade/extended
- start_extended = TRUE
-
-/obj/item/phone
- name = "red phone"
- desc = "Should anything ever go wrong..."
- icon = 'icons/obj/devices/voice.dmi'
- icon_state = "red_phone"
- force = 3
- throwforce = 2
- throw_speed = 3
- throw_range = 4
- w_class = WEIGHT_CLASS_SMALL
- attack_verb_continuous = list("calls", "rings")
- attack_verb_simple = list("call", "ring")
- hitsound = 'sound/items/weapons/ring.ogg'
-
-/obj/item/phone/suicide_act(mob/living/user)
- if(locate(/obj/structure/chair/stool) in user.loc)
- user.visible_message(span_suicide("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
- else
- user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
- return OXYLOSS
-
-/obj/item/bambostaff
- name = "bamboo staff"
- desc = "A long bamboo-made staff with steel-capped ends. It is rumoured that initiates of Spider Clan train with such before getting to learn how to use a katana."
- force = 10
- block_chance = 45
- block_sound = 'sound/items/weapons/genhit.ogg'
- slot_flags = ITEM_SLOT_BACK
- w_class = WEIGHT_CLASS_BULKY
- hitsound = SFX_SWING_HIT
- attack_verb_continuous = list("smashes", "slams", "whacks", "thwacks")
- attack_verb_simple = list("smash", "slam", "whack", "thwack")
- icon = 'icons/obj/weapons/staff.dmi'
- icon_state = "bambostaff0"
- base_icon_state = "bambostaff"
- inhand_icon_state = "bambostaff0"
- worn_icon_state = "bambostaff0"
- icon_angle = -135
- lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
- custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 4)
-
-/obj/item/bambostaff/Initialize(mapload)
- . = ..()
- // there are too many puns to choose from. ('Bo' is the 'real' name for this kind of weapon.)
- name = pick("bamboo staff", "bambo staff", "bam-Bo staff", "bam boo staff", "bam-boo staff", "bam Bo", "bambo", "bam-Bo", "bamboo-Bo")
- AddComponent(/datum/component/two_handed, \
- force_unwielded = 10, \
- force_wielded = 14, \
- )
-
-/obj/item/bambostaff/update_icon_state()
- icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]"
- return ..()
-
-/obj/item/bambostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
- if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
- final_block_chance = 0 //Don't bring a staff to a gunfight, and also you aren't going to really block someone full body tackling you with a staff. Or a road roller, if one happened to hit you.
- return ..()
-
-/obj/item/cane
- name = "cane"
- desc = "A cane used by a true gentleman. Or a clown."
- icon = 'icons/obj/weapons/staff.dmi'
- icon_state = "cane"
- inhand_icon_state = "stick"
- icon_angle = 135
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 5
- throwforce = 5
- w_class = WEIGHT_CLASS_SMALL
- custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5)
- attack_verb_continuous = list("bludgeons", "whacks", "disciplines", "thrashes")
- attack_verb_simple = list("bludgeon", "whack", "discipline", "thrash")
-
-/obj/item/cane/examine(mob/user, thats)
- . = ..()
- . += span_notice("This item can be used to support your weight, preventing limping from any broken bones on your legs you may have.")
-
-/obj/item/cane/equipped(mob/living/user, slot, initial)
- ..()
- if(!(slot & ITEM_SLOT_HANDS))
- return
- movement_support_add(user)
-
-/obj/item/cane/dropped(mob/living/user, silent = FALSE)
- . = ..()
- movement_support_del(user)
-
-/obj/item/cane/proc/movement_support_add(mob/living/user)
- RegisterSignal(user, COMSIG_CARBON_LIMPING, PROC_REF(handle_limping))
- return TRUE
-
-/obj/item/cane/proc/movement_support_del(mob/living/user)
- UnregisterSignal(user, list(COMSIG_CARBON_LIMPING))
- return TRUE
-
-/obj/item/cane/proc/handle_limping(mob/living/user)
- SIGNAL_HANDLER
- return COMPONENT_CANCEL_LIMP
-
-/obj/item/cane/crutch
- name = "medical crutch"
- desc = "A medical crutch used by people missing a leg. Not all that useful if you're missing both of them, though."
- icon = 'icons/obj/weapons/staff.dmi'
- icon_state = "crutch_med"
- inhand_icon_state = "crutch_med"
- icon_angle = 45
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 12
- throwforce = 8
- w_class = WEIGHT_CLASS_BULKY
- custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5)
- attack_verb_continuous = list("bludgeons", "whacks", "thrashes")
- attack_verb_simple = list("bludgeon", "whack", "thrash")
-
-/obj/item/cane/crutch/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/cuffable_item)
-
-/obj/item/cane/crutch/examine(mob/user, thats)
- . = ..()
- // tacked on after the cane string
- . += span_notice("As a crutch, it can also help lessen the slowdown incurred by missing a leg.")
-
-/obj/item/cane/crutch/movement_support_add(mob/living/user)
- . = ..()
- if(!.)
- return
- RegisterSignal(user, COMSIG_LIVING_LIMBLESS_SLOWDOWN, PROC_REF(handle_slowdown))
- user.update_usable_leg_status()
- user.AddElementTrait(TRAIT_WADDLING, REF(src), /datum/element/waddling)
-
-/obj/item/cane/crutch/movement_support_del(mob/living/user)
- . = ..()
- if(!.)
- return
- UnregisterSignal(user, list(COMSIG_LIVING_LIMBLESS_SLOWDOWN, COMSIG_CARBON_LIMPING))
- user.update_usable_leg_status()
- REMOVE_TRAIT(user, TRAIT_WADDLING, REF(src))
-
-/obj/item/cane/crutch/proc/handle_slowdown(mob/living/user, limbless_slowdown, list/slowdown_mods)
- SIGNAL_HANDLER
- var/leg_amount = user.usable_legs
- // Don't do anything if the number is equal (or higher) to the usual.
- if(leg_amount >= user.default_num_legs)
- return
- // If we have at least one leg and it's less than the default, reduce slowdown by 60%.
- if(leg_amount && (leg_amount < user.default_num_legs))
- slowdown_mods += 0.4
-
-/obj/item/cane/crutch/wood
- name = "wooden crutch"
- desc = "A handmade crutch. Also makes a decent bludgeon if you need it."
- icon_state = "crutch_wood"
- inhand_icon_state = "crutch_wood"
- custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 5)
-
-/obj/item/cane/white
- name = "white cane"
- desc = "Traditionally used by the blind to help them see. Folds down to be easier to transport."
- icon_state = "cane_white"
- inhand_icon_state = "cane_white"
- icon_angle = 45
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 1
- w_class = WEIGHT_CLASS_SMALL
- custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 6)
-
-/obj/item/cane/white/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/cuffable_item)
- AddComponent( \
- /datum/component/transforming, \
- force_on = 7, \
- hitsound_on = hitsound, \
- w_class_on = WEIGHT_CLASS_BULKY, \
- clumsy_check = FALSE, \
- attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \
- attack_verb_simple_on = list("smack", "strike", "crack", "beat"), \
- )
- RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
-
-/obj/item/cane/white/handle_limping(mob/living/user)
- return HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE) ? COMPONENT_CANCEL_LIMP : NONE
-
-/*
- * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
- *
- * Gives feedback to the user and makes it show up inhand.
- */
-/obj/item/cane/white/proc/on_transform(obj/item/source, mob/user, active)
- SIGNAL_HANDLER
-
- if(user)
- balloon_alert(user, active ? "extended" : "collapsed")
-
- if(!HAS_TRAIT(src, TRAIT_BLIND_TOOL))
- ADD_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT)
- else
- REMOVE_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT)
-
- playsound(src, 'sound/items/weapons/batonextend.ogg', 50, TRUE)
- return COMPONENT_NO_DEFAULT_MESSAGE
-
-/obj/item/staff
- name = "wizard staff"
- desc = "Apparently a staff used by the wizard."
- icon = 'icons/obj/weapons/guns/magic.dmi'
- icon_state = "staff"
- inhand_icon_state = "staff"
- lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
- force = 3
- throwforce = 5
- throw_speed = 2
- throw_range = 5
- w_class = WEIGHT_CLASS_SMALL
- armour_penetration = 100
- attack_verb_continuous = list("bludgeons", "whacks", "disciplines")
- attack_verb_simple = list("bludgeon", "whack", "discipline")
- resistance_flags = FLAMMABLE
-
-/obj/item/staff/broom
- name = "broom"
- desc = "Used for sweeping, and flying into the night while cackling. Black cat not included."
- icon_state = "broom"
- inhand_icon_state = "broom"
- resistance_flags = FLAMMABLE
-
-/obj/item/staff/tape
- name = "tape staff"
- desc = "A roll of tape snugly attached to a stick."
- icon_state = "tapestaff"
- inhand_icon_state = "tapestaff"
- resistance_flags = FLAMMABLE
-
-/obj/item/staff/stick
- name = "stick"
- desc = "A great tool to drag someone else's drinks across the bar."
- icon = 'icons/obj/weapons/staff.dmi'
- icon_state = "cane"
- inhand_icon_state = "stick"
- icon_angle = 135
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 3
- throwforce = 5
- throw_speed = 2
- throw_range = 5
- w_class = WEIGHT_CLASS_SMALL
-
-/obj/item/ectoplasm
- name = "ectoplasm"
- desc = "Spooky."
- gender = PLURAL
- icon = 'icons/effects/magic.dmi'
- icon_state = "ectoplasm"
-
-/obj/item/ectoplasm/grind_results()
- return list(/datum/reagent/hauntium = 25)
-
-/obj/item/ectoplasm/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!"))
- return OXYLOSS
-
-/obj/item/ectoplasm/angelic
- icon = 'icons/effects/magic.dmi'
- icon_state = "angelplasm"
-
-/obj/item/ectoplasm/mystic
- icon_state = "mysticplasm"
-
-/obj/item/tailclub
- name = "tail club"
- desc = "For the beating to death of lizards with their own tails."
- icon = 'icons/obj/weapons/club.dmi'
- icon_state = "tailclub"
- icon_angle = -25
- force = 14
- throwforce = 1 // why are you throwing a club do you even weapon
- throw_speed = 1
- throw_range = 1
- attack_verb_continuous = list("clubs", "bludgeons")
- attack_verb_simple = list("club", "bludgeon")
- custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT)
-
-/obj/item/melee/baseball_bat
- name = "baseball bat"
- desc = "There ain't a skull in the league that can withstand a swatter."
- icon = 'icons/obj/weapons/bat.dmi'
- icon_state = "baseball_bat"
- inhand_icon_state = "baseball_bat"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 12
- wound_bonus = -10
- throwforce = 12
- demolition_mod = 1.25
- attack_verb_continuous = list("beats", "smacks")
- attack_verb_simple = list("beat", "smack")
- custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 3.5)
- resistance_flags = FLAMMABLE
- w_class = WEIGHT_CLASS_HUGE
- /// Are we able to do a homerun?
- var/homerun_able = FALSE
- /// Are we ready to do a homerun?
- var/homerun_ready = FALSE
- /// Can we launch mobs thrown at us away?
- var/mob_thrower = FALSE
- /// List of all thrown datums we sent.
- var/list/thrown_datums = list()
-
-/obj/item/melee/baseball_bat/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/kneecapping)
- // No subtypes
- if(type != /obj/item/melee/baseball_bat)
- return
- if(prob(check_holidays(APRIL_FOOLS) ? 50 : 1))
- make_silly()
-
-/obj/item/melee/baseball_bat/attack_self(mob/user)
- if(!homerun_able)
- return ..()
- if(homerun_ready)
- to_chat(user, span_warning("You're already ready to do a home run!"))
- return ..()
- to_chat(user, span_warning("You begin gathering strength..."))
- playsound(get_turf(src), 'sound/effects/magic/lightning_chargeup.ogg', 65, TRUE)
- if(do_after(user, 9 SECONDS, target = src))
- to_chat(user, span_userdanger("You gather power! Time for a home run!"))
- homerun_ready = TRUE
- return ..()
-
-/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user)
- // we obtain the relative direction from the bat itself to the target
- var/relative_direction = get_cardinal_dir(src, target)
- var/atom/throw_target = get_edge_target_turf(target, relative_direction)
- . = ..()
- if(HAS_TRAIT(user, TRAIT_PACIFISM))
- return
- if(homerun_ready)
- user.visible_message(span_userdanger("It's a home run!"))
- if(!QDELETED(target))
- target.throw_at(throw_target, rand(8,10), 14, user)
- SSexplosions.medturf += throw_target
- playsound(get_turf(src), 'sound/items/weapons/homerun.ogg', 100, TRUE)
- homerun_ready = FALSE
- return
- else if(!QDELETED(target) && !target.anchored)
- var/whack_speed = (prob(60) ? 1 : 4)
- target.throw_at(throw_target, rand(1, 2), whack_speed, user, gentle = TRUE) // sorry friends, 7 speed batting caused wounds to absolutely delete whoever you knocked your target into (and said target)
-
-/obj/item/melee/baseball_bat/Destroy(force)
- for(var/target in thrown_datums)
- var/datum/thrownthing/throw_datum = thrown_datums[target]
- throw_datum.callback.Invoke()
- thrown_datums.Cut()
- return ..()
-
-/obj/item/melee/baseball_bat/pre_attack(atom/movable/target, mob/living/user, list/modifiers, list/attack_modifiers)
- var/turf/target_turf = get_turf(target)
- if(!target_turf)
- return ..()
- for(var/atom/movable/atom as anything in target_turf)
- if(!try_launch(atom, user))
- continue
- return TRUE
- return ..()
-
-/obj/item/melee/baseball_bat/proc/try_launch(atom/movable/target, mob/living/user)
- if(!target.throwing || (ismob(target) && !mob_thrower))
- return FALSE
- var/datum/thrownthing/throw_datum = target.throwing
- var/datum_throw_speed = throw_datum.speed
- var/angle = 0
- var/target_to_user = get_dir(target, user)
- if(target.dir & turn(target_to_user, 90))
- angle = 270
- if(target.dir & turn(target_to_user, 270))
- angle = 90
- if(target.dir & REVERSE_DIR(target_to_user))
- angle = 180
- if(target.dir & target_to_user)
- angle = 360
- var/turf/return_to_sender = get_ranged_target_turf_direct(user, throw_datum.starting_turf, max(3, round(target.throw_range * 1.5, 1)), offset = angle + (rand(-1, 1) * 10))
- throw_datum.finalize(hit = FALSE)
- target.mouse_opacity = MOUSE_OPACITY_TRANSPARENT //dont mess with our ball
- target.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3) //make them super light
- animate(target, 0.5 SECONDS, color = null, flags = ANIMATION_PARALLEL)
- user.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3)
- animate(user, 0.5 SECONDS, color = null, flags = ANIMATION_PARALLEL)
- playsound(src, 'sound/items/baseballhit.ogg', 100, TRUE)
- user.do_attack_animation(target, used_item = src)
- ADD_TRAIT(user, TRAIT_IMMOBILIZED, type)
- addtimer(CALLBACK(src, PROC_REF(launch_back), target, user, return_to_sender, datum_throw_speed), 0.5 SECONDS)
- return TRUE
-
-/obj/item/melee/baseball_bat/proc/launch_back(atom/movable/target, mob/living/user, turf/target_turf, datum_throw_speed)
- playsound(target, 'sound/effects/magic/tail_swing.ogg', 50, TRUE)
- REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, type)
- target.mouse_opacity = initial(target.mouse_opacity)
- target.add_filter("baseball_launch", 3, motion_blur_filter(1, 3))
- target.throwforce *= 2
- target.throw_at(target_turf, get_dist(target, target_turf), datum_throw_speed + 1, user, callback = CALLBACK(src, PROC_REF(on_hit), target))
- thrown_datums[target] = target.throwing
-
-/obj/item/melee/baseball_bat/proc/make_silly()
- name = "cricket bat"
- icon_state = "baseball_bat_brit"
- inhand_icon_state = "baseball_bat_brit"
- desc = pick("You've got red on you.", "You gotta know what a crumpet is to understand cricket.")
-
-/obj/item/melee/baseball_bat/proc/on_hit(atom/movable/target)
- target.remove_filter("baseball_launch")
- target.throwforce *= 0.5
- thrown_datums -= target
-
-/obj/item/melee/baseball_bat/homerun
- name = "home run bat"
- desc = "This thing looks dangerous... Dangerously good at baseball, that is."
- icon_state = "baseball_bat_home"
- inhand_icon_state = "baseball_bat_home"
- homerun_able = TRUE
- mob_thrower = TRUE
-
-/obj/item/melee/baseball_bat/ablative
- name = "metal baseball bat"
- desc = "This bat is made of highly reflective, highly armored material."
- icon_state = "baseball_bat_metal"
- inhand_icon_state = "baseball_bat_metal"
- custom_materials = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 3.5)
- resistance_flags = NONE
- force = 20
- throwforce = 20
- mob_thrower = TRUE
- block_sound = 'sound/items/weapons/effects/batreflect.ogg'
-
-/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers
- return TRUE
-
-// In case you ever want to spawn it via map/admin console
-/obj/item/melee/baseball_bat/british/Initialize(mapload)
- . = ..()
- make_silly()
-
-/obj/item/melee/flyswatter
- name = "flyswatter"
- desc = "Useful for killing pests of all sizes."
- icon = 'icons/obj/service/hydroponics/equipment.dmi'
- icon_state = "flyswatter"
- inhand_icon_state = "flyswatter"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 1
- throwforce = 1
- attack_verb_continuous = list("swats", "smacks")
- attack_verb_simple = list("swat", "smack")
- hitsound = 'sound/effects/snap.ogg'
- w_class = WEIGHT_CLASS_SMALL
- /// Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc.
- var/static/list/splattable
-
-/obj/item/melee/flyswatter/Initialize(mapload)
- . = ..()
- if (isnull(splattable))
- splattable = typecacheof(list(
- /mob/living/basic/ant,
- /mob/living/basic/butterfly,
- /mob/living/basic/cockroach,
- /mob/living/basic/cockroach/bloodroach,
- /mob/living/basic/spider/growing/spiderling,
- /mob/living/basic/bee,
- /obj/effect/decal/cleanable/ants,
- /obj/item/queen_bee,
- ))
- AddElement(/datum/element/bane, mob_biotypes = MOB_BUG, target_type = /mob/living/basic, damage_multiplier = 0, added_damage = 24, requires_combat_mode = FALSE)
-
-/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, list/modifiers, list/attack_modifiers)
- if(is_type_in_typecache(target, splattable))
- to_chat(user, span_warning("You easily splat [target]."))
- if(QDELETED(target))
- return
- if(isliving(target))
- new /obj/effect/decal/cleanable/insectguts(target.drop_location())
- var/mob/living/bug = target
- bug.investigate_log("has been splatted by a flyswatter.", INVESTIGATE_DEATHS)
- bug.gib(DROP_ALL_REMAINS)
- else
- qdel(target)
-
-/obj/item/proc/can_trigger_gun(mob/living/user, akimbo_usage)
- if(!user.can_use_guns(src))
- return FALSE
- return TRUE
-
-/obj/item/extendohand
- name = "extendo-hand"
- desc = "Futuristic tech has allowed these classic spring-boxing toys to essentially act as a fully functional hand-operated hand prosthetic."
- icon = 'icons/obj/toys/toy.dmi'
- icon_state = "extendohand"
- inhand_icon_state = "extendohand"
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- force = 0
- throwforce = 5
- reach = 2
- var/min_reach = 2
-
-/obj/item/extendohand/acme
- name = "\improper ACME Extendo-Hand"
- desc = "A novelty extendo-hand produced by the ACME corporation. Originally designed to knock out roadrunners."
-
-/obj/item/extendohand/attack(atom/M, mob/living/carbon/human/user, list/modifiers, list/attack_modifiers)
- var/dist = get_dist(M, user)
- if(dist < min_reach)
- to_chat(user, span_warning("[M] is too close to use [src] on."))
- return
- M.attack_hand(user, modifiers)
-
-/obj/item/gohei
- name = "gohei"
- desc = "A wooden stick with white streamers at the end. Originally used by shrine maidens to purify things. Now used by the station's valued weeaboos."
- resistance_flags = FLAMMABLE
- force = 5
- throwforce = 5
- hitsound = SFX_SWING_HIT
- attack_verb_continuous = list("whacks", "thwacks", "wallops", "socks")
- attack_verb_simple = list("whack", "thwack", "wallop", "sock")
- icon = 'icons/obj/weapons/club.dmi'
- icon_state = "gohei"
- inhand_icon_state = "gohei"
- icon_angle = -65
- lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
-
-/obj/item/melee/moonlight_greatsword
- name = "moonlight greatsword"
- desc = "Don't tell anyone you put any points into dex, though."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "swordon"
- inhand_icon_state = "swordon"
- worn_icon_state = "swordon"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- w_class = WEIGHT_CLASS_BULKY
- slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT
- block_chance = 20
- block_sound = 'sound/items/weapons/parry.ogg'
- sharpness = SHARP_EDGED
- force = 14
- throwforce = 12
- hitsound = 'sound/items/weapons/bladeslice.ogg'
- attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
- var/list/alt_continuous = list("stabs", "pierces", "impales")
- var/list/alt_simple = list("stab", "pierce", "impale")
-
-/obj/item/melee/moonlight_greatsword/Initialize(mapload)
- . = ..()
- alt_continuous = string_list(alt_continuous)
- alt_simple = string_list(alt_simple)
- AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple)
-
-//High Frequency Blade
-
-/obj/item/highfrequencyblade
- name = "high frequency blade"
- desc = "A sword reinforced by a powerful alternating current and resonating at extremely high vibration frequencies. \
- This oscillation weakens the molecular bonds of anything it cuts, thereby increasing its cutting ability."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "hfrequency0"
- worn_icon_state = "hfrequency0"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- force = 10
- wound_bonus = 25
- exposed_wound_bonus = 50
- throwforce = 25
- throw_speed = 4
- attack_speed = CLICK_CD_HYPER_RAPID
- embed_type = /datum/embedding/hfr_blade
- block_chance = 25
- block_sound = 'sound/items/weapons/parry.ogg'
- sharpness = SHARP_EDGED
- w_class = WEIGHT_CLASS_BULKY
- slot_flags = ITEM_SLOT_BACK
- /// The color of the slash we create
- var/slash_color = COLOR_BLUE
- /// Previous x position of where we clicked on the target's icon
- var/previous_x
- /// Previous y position of where we clicked on the target's icon
- var/previous_y
- /// The previous target we attacked
- var/datum/weakref/previous_target
-
-/datum/embedding/hfr_blade
- embed_chance = 100
-
-/obj/item/highfrequencyblade/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/two_handed, \
- wield_callback = CALLBACK(src, PROC_REF(on_wield)), \
- unwield_callback = CALLBACK(src, PROC_REF(on_unwield)), \
- )
- AddElement(/datum/element/update_icon_updates_onmob)
-
-/obj/item/highfrequencyblade/update_icon_state()
- icon_state = "hfrequency[HAS_TRAIT(src, TRAIT_WIELDED)]"
- return ..()
-
-/obj/item/highfrequencyblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
- if(attack_type == PROJECTILE_ATTACK)
- if(HAS_TRAIT(src, TRAIT_WIELDED) || prob(final_block_chance))
- owner.visible_message(span_danger("[owner] deflects [attack_text] with [src]!"))
- playsound(src, SFX_BULLET_MISS, 75, TRUE)
- return TRUE
- return FALSE
- var/stop_that_blade = (final_block_chance + (attack_type == OVERWHELMING_ATTACK ? 25 : 0)) * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1)
- if(prob(stop_that_blade))
- owner.visible_message(span_danger("[owner] parries [attack_text] with [src]!"))
- return TRUE
- return FALSE
-
-/obj/item/highfrequencyblade/pre_attack(atom/target, mob/living/user, list/modifiers, list/attack_modifiers)
- . = ..()
- if(.)
- return .
- if(!HAS_TRAIT(src, TRAIT_WIELDED))
- return . // Default attack
- if(isliving(target) && HAS_TRAIT(src, TRAIT_PACIFISM))
- return . // Default attack (ultimately nothing)
-
- return slash(target, user, modifiers)
-
-/// triggered on wield of two handed item
-/obj/item/highfrequencyblade/proc/on_wield(obj/item/source, mob/user)
- update_icon(UPDATE_ICON_STATE)
-
-/// triggered on unwield of two handed item
-/obj/item/highfrequencyblade/proc/on_unwield(obj/item/source, mob/user)
- update_icon(UPDATE_ICON_STATE)
-
-/obj/item/highfrequencyblade/proc/slash(atom/target, mob/living/user, list/modifiers)
- user.do_attack_animation(target, "nothing")
- var/damage_mod = 1
- var/x_slashed = text2num(modifiers[ICON_X]) || ICON_SIZE_X/2 //in case we arent called by a client
- var/y_slashed = text2num(modifiers[ICON_Y]) || ICON_SIZE_Y/2 //in case we arent called by a client
- new /obj/effect/temp_visual/slash(get_turf(target), target, x_slashed, y_slashed, slash_color)
- if(target == previous_target?.resolve()) //if the same target, we calculate a damage multiplier if you swing your mouse around
- var/x_mod = previous_x - x_slashed
- var/y_mod = previous_y - y_slashed
- damage_mod = max(1, round((sqrt(x_mod ** 2 + y_mod ** 2) / 10), 0.1))
- previous_target = WEAKREF(target)
- previous_x = x_slashed
- previous_y = y_slashed
- playsound(src, 'sound/items/weapons/bladeslice.ogg', 100, vary = TRUE)
- playsound(src, 'sound/items/weapons/zapbang.ogg', 50, vary = TRUE)
- if(isliving(target))
- var/mob/living/living_target = target
- living_target.apply_damage(force*damage_mod, BRUTE, sharpness = SHARP_EDGED, wound_bonus = wound_bonus, exposed_wound_bonus = exposed_wound_bonus, def_zone = user.zone_selected)
- log_combat(user, living_target, "slashed", src)
- if(living_target.stat == DEAD && prob(force*damage_mod*0.5))
- living_target.visible_message(span_danger("[living_target] explodes in a shower of gore!"), blind_message = span_hear("You hear organic matter ripping and tearing!"))
- living_target.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
- living_target.gib(DROP_ALL_REMAINS)
- log_combat(user, living_target, "gibbed", src)
- return TRUE
- else if(target.uses_integrity)
- target.take_damage(force*damage_mod*3, BRUTE, MELEE, FALSE, null, 50)
- return TRUE
- else if(iswallturf(target) && prob(force*damage_mod*0.5))
- var/turf/closed/wall/wall_target = target
- wall_target.dismantle_wall()
- return TRUE
- else if(ismineralturf(target) && prob(force*damage_mod))
- var/turf/closed/mineral/mineral_target = target
- mineral_target.gets_drilled()
- return TRUE
- return FALSE
-
-/obj/effect/temp_visual/slash
- icon_state = "highfreq_slash"
- alpha = 150
- duration = 0.5 SECONDS
- layer = ABOVE_ALL_MOB_LAYER
- plane = ABOVE_GAME_PLANE
-
-/obj/effect/temp_visual/slash/Initialize(mapload, atom/target, x_slashed, y_slashed, slash_color)
- . = ..()
- if(!target)
- return
- var/matrix/new_transform = matrix()
- new_transform.Turn(rand(1, 360)) // Random slash angle
- var/datum/decompose_matrix/decomp = target.transform.decompose()
- new_transform.Translate((x_slashed - ICON_SIZE_X/2) * decomp.scale_x, (y_slashed - ICON_SIZE_Y/2) * decomp.scale_y) // Move to where we clicked
- //Follow target's transform while ignoring scaling
- new_transform.Turn(decomp.rotation)
- new_transform.Translate(decomp.shift_x, decomp.shift_y)
- new_transform.Translate(target.pixel_x, target.pixel_y) // Follow target's pixel offsets
- transform = new_transform
- //Double the scale of the matrix by doubling the 2x2 part without touching the translation part
- var/matrix/scaled_transform = new_transform + matrix(new_transform.a, new_transform.b, 0, new_transform.d, new_transform.e, 0)
- animate(src, duration*0.5, color = slash_color, transform = scaled_transform, alpha = 255)
-
-/obj/item/highfrequencyblade/wizard
- desc = "A blade that was mastercrafted by a legendary blacksmith. Its enchantments let it slash through anything."
- force = 8
- throwforce = 20
- wound_bonus = 20
- exposed_wound_bonus = 25
-
-/obj/item/highfrequencyblade/wizard/attack_self(mob/user, modifiers)
- if(!HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED))
- balloon_alert(user, "you're too weak!")
- return
- return ..()
diff --git a/code/game/objects/items/weaponry/melee/baseball_bat.dm b/code/game/objects/items/weaponry/melee/baseball_bat.dm
new file mode 100644
index 00000000000..8d12e772436
--- /dev/null
+++ b/code/game/objects/items/weaponry/melee/baseball_bat.dm
@@ -0,0 +1,160 @@
+/obj/item/melee/baseball_bat
+ name = "baseball bat"
+ desc = "There ain't a skull in the league that can withstand a swatter."
+ icon = 'icons/obj/weapons/bat.dmi'
+ icon_state = "baseball_bat"
+ inhand_icon_state = "baseball_bat"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 12
+ wound_bonus = -10
+ throwforce = 12
+ demolition_mod = 1.25
+ attack_verb_continuous = list("beats", "smacks")
+ attack_verb_simple = list("beat", "smack")
+ custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 3.5)
+ resistance_flags = FLAMMABLE
+ w_class = WEIGHT_CLASS_HUGE
+ /// Are we able to do a homerun?
+ var/homerun_able = FALSE
+ /// Are we ready to do a homerun?
+ var/homerun_ready = FALSE
+ /// Can we launch mobs thrown at us away?
+ var/mob_thrower = FALSE
+ /// List of all thrown datums we sent.
+ var/list/thrown_datums = list()
+
+/obj/item/melee/baseball_bat/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/kneecapping)
+ // No subtypes
+ if(type != /obj/item/melee/baseball_bat)
+ return
+ if(prob(check_holidays(APRIL_FOOLS) ? 50 : 1))
+ make_silly()
+
+/obj/item/melee/baseball_bat/attack_self(mob/user)
+ if(!homerun_able)
+ return ..()
+ if(homerun_ready)
+ to_chat(user, span_warning("You're already ready to do a home run!"))
+ return ..()
+ to_chat(user, span_warning("You begin gathering strength..."))
+ playsound(get_turf(src), 'sound/effects/magic/lightning_chargeup.ogg', 65, TRUE)
+ if(do_after(user, 9 SECONDS, target = src))
+ to_chat(user, span_userdanger("You gather power! Time for a home run!"))
+ homerun_ready = TRUE
+ return ..()
+
+/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user)
+ // we obtain the relative direction from the bat itself to the target
+ var/relative_direction = get_cardinal_dir(src, target)
+ var/atom/throw_target = get_edge_target_turf(target, relative_direction)
+ . = ..()
+ if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ return
+ if(homerun_ready)
+ user.visible_message(span_userdanger("It's a home run!"))
+ if(!QDELETED(target))
+ target.throw_at(throw_target, rand(8,10), 14, user)
+ SSexplosions.medturf += throw_target
+ playsound(get_turf(src), 'sound/items/weapons/homerun.ogg', 100, TRUE)
+ homerun_ready = FALSE
+ return
+ else if(!QDELETED(target) && !target.anchored)
+ var/whack_speed = (prob(60) ? 1 : 4)
+ target.throw_at(throw_target, rand(1, 2), whack_speed, user, gentle = TRUE) // sorry friends, 7 speed batting caused wounds to absolutely delete whoever you knocked your target into (and said target)
+
+/obj/item/melee/baseball_bat/Destroy(force)
+ for(var/target in thrown_datums)
+ var/datum/thrownthing/throw_datum = thrown_datums[target]
+ throw_datum.callback.Invoke()
+ thrown_datums.Cut()
+ return ..()
+
+/obj/item/melee/baseball_bat/pre_attack(atom/movable/target, mob/living/user, list/modifiers, list/attack_modifiers)
+ var/turf/target_turf = get_turf(target)
+ if(!target_turf)
+ return ..()
+ for(var/atom/movable/atom as anything in target_turf)
+ if(!try_launch(atom, user))
+ continue
+ return TRUE
+ return ..()
+
+/obj/item/melee/baseball_bat/proc/try_launch(atom/movable/target, mob/living/user)
+ if(!target.throwing || (ismob(target) && !mob_thrower))
+ return FALSE
+ var/datum/thrownthing/throw_datum = target.throwing
+ var/datum_throw_speed = throw_datum.speed
+ var/angle = 0
+ var/target_to_user = get_dir(target, user)
+ if(target.dir & turn(target_to_user, 90))
+ angle = 270
+ if(target.dir & turn(target_to_user, 270))
+ angle = 90
+ if(target.dir & REVERSE_DIR(target_to_user))
+ angle = 180
+ if(target.dir & target_to_user)
+ angle = 360
+ var/turf/return_to_sender = get_ranged_target_turf_direct(user, throw_datum.starting_turf, max(3, round(target.throw_range * 1.5, 1)), offset = angle + (rand(-1, 1) * 10))
+ throw_datum.finalize(hit = FALSE)
+ target.mouse_opacity = MOUSE_OPACITY_TRANSPARENT //dont mess with our ball
+ target.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3) //make them super light
+ animate(target, 0.5 SECONDS, color = null, flags = ANIMATION_PARALLEL)
+ user.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3)
+ animate(user, 0.5 SECONDS, color = null, flags = ANIMATION_PARALLEL)
+ playsound(src, 'sound/items/baseballhit.ogg', 100, TRUE)
+ user.do_attack_animation(target, used_item = src)
+ ADD_TRAIT(user, TRAIT_IMMOBILIZED, type)
+ addtimer(CALLBACK(src, PROC_REF(launch_back), target, user, return_to_sender, datum_throw_speed), 0.5 SECONDS)
+ return TRUE
+
+/obj/item/melee/baseball_bat/proc/launch_back(atom/movable/target, mob/living/user, turf/target_turf, datum_throw_speed)
+ playsound(target, 'sound/effects/magic/tail_swing.ogg', 50, TRUE)
+ REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, type)
+ target.mouse_opacity = initial(target.mouse_opacity)
+ target.add_filter("baseball_launch", 3, motion_blur_filter(1, 3))
+ target.throwforce *= 2
+ target.throw_at(target_turf, get_dist(target, target_turf), datum_throw_speed + 1, user, callback = CALLBACK(src, PROC_REF(on_hit), target))
+ thrown_datums[target] = target.throwing
+
+/obj/item/melee/baseball_bat/proc/make_silly()
+ name = "cricket bat"
+ icon_state = "baseball_bat_brit"
+ inhand_icon_state = "baseball_bat_brit"
+ desc = pick("You've got red on you.", "You gotta know what a crumpet is to understand cricket.")
+
+/obj/item/melee/baseball_bat/proc/on_hit(atom/movable/target)
+ target.remove_filter("baseball_launch")
+ target.throwforce *= 0.5
+ thrown_datums -= target
+
+/obj/item/melee/baseball_bat/homerun
+ name = "home run bat"
+ desc = "This thing looks dangerous... Dangerously good at baseball, that is."
+ icon_state = "baseball_bat_home"
+ inhand_icon_state = "baseball_bat_home"
+ homerun_able = TRUE
+ mob_thrower = TRUE
+
+/obj/item/melee/baseball_bat/ablative
+ name = "metal baseball bat"
+ desc = "This bat is made of highly reflective, highly armored material."
+ icon_state = "baseball_bat_metal"
+ inhand_icon_state = "baseball_bat_metal"
+ custom_materials = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 3.5)
+ resistance_flags = NONE
+ force = 20
+ throwforce = 20
+ mob_thrower = TRUE
+ block_sound = 'sound/items/weapons/effects/batreflect.ogg'
+
+/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers
+ return TRUE
+
+// In case you ever want to spawn it via map/admin console
+/obj/item/melee/baseball_bat/british/Initialize(mapload)
+ . = ..()
+ make_silly()
diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/weaponry/melee/baton.dm
similarity index 100%
rename from code/game/objects/items/melee/baton.dm
rename to code/game/objects/items/weaponry/melee/baton.dm
diff --git a/code/game/objects/items/melee/chainofcommand.dm b/code/game/objects/items/weaponry/melee/chainofcommand.dm
similarity index 100%
rename from code/game/objects/items/melee/chainofcommand.dm
rename to code/game/objects/items/weaponry/melee/chainofcommand.dm
diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/weaponry/melee/chainsaw.dm
similarity index 100%
rename from code/game/objects/items/chainsaw.dm
rename to code/game/objects/items/weaponry/melee/chainsaw.dm
diff --git a/code/game/objects/items/weaponry/melee/claymore.dm b/code/game/objects/items/weaponry/melee/claymore.dm
new file mode 100644
index 00000000000..2fb5b93fadd
--- /dev/null
+++ b/code/game/objects/items/weaponry/melee/claymore.dm
@@ -0,0 +1,274 @@
+/obj/item/claymore
+ name = "claymore"
+ desc = "What are you standing around staring at this for? Get to killing!"
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "claymore"
+ inhand_icon_state = "claymore"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+ obj_flags = CONDUCTS_ELECTRICITY
+ slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
+ force = 40
+ throwforce = 10
+ w_class = WEIGHT_CLASS_NORMAL
+ attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
+ attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
+ block_chance = 50
+ block_sound = 'sound/items/weapons/parry.ogg'
+ sharpness = SHARP_EDGED
+ max_integrity = 200
+ armor_type = /datum/armor/item_claymore
+ resistance_flags = FIRE_PROOF
+ var/list/alt_continuous = list("stabs", "pierces", "impales")
+ var/list/alt_simple = list("stab", "pierce", "impale")
+
+/datum/armor/item_claymore
+ fire = 100
+ acid = 50
+
+/obj/item/claymore/Initialize(mapload)
+ . = ..()
+ alt_continuous = string_list(alt_continuous)
+ alt_simple = string_list(alt_simple)
+ make_stabby()
+ AddComponent(/datum/component/butchering, \
+ speed = 4 SECONDS, \
+ effectiveness = 105, \
+ )
+
+// Applies alt sharpness component, for overrides
+/obj/item/claymore/proc/make_stabby()
+ AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -15)
+
+/obj/item/claymore/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return BRUTELOSS
+
+/obj/item/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
+ final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you.
+ return ..()
+
+//statistically similar to e-cutlasses
+/obj/item/claymore/cutlass
+ name = "cutlass"
+ desc = "A piratey sword used by buckaneers to \"negotiate\" the transfer of treasure."
+ icon_state = "cutlass"
+ inhand_icon_state = "cutlass"
+ worn_icon_state = "cutlass"
+ slot_flags = ITEM_SLOT_BACK
+ force = 30
+ throwforce = 20
+ throw_speed = 3
+ throw_range = 5
+ armour_penetration = 35
+
+/obj/item/claymore/cutlass/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/cuffable_item) //closed sword guard
+
+/obj/item/claymore/cutlass/old
+ name = "old cutlass"
+ desc = parent_type::desc + " This one seems a tad old."
+ force = 24
+ throwforce = 17
+ armour_penetration = 20
+ block_chance = 30
+
+/obj/item/claymore/carrot
+ name = "carrot sword"
+ desc = "A full-sized carrot sword. Definitely not good for the eyes, not anymore."
+ icon_state = "carrot_sword"
+ inhand_icon_state = "carrot_sword"
+ worn_icon_state = "carrot_sword"
+ flags_1 = NONE
+ force = 19
+ throwforce = 7
+ throw_speed = 3
+ throw_range = 7
+ armour_penetration = 5
+ block_chance = 10
+ resistance_flags = NONE
+
+//bootleg claymore
+/obj/item/claymore/shortsword
+ name = "shortsword"
+ desc = "A mercenary's sword, chipped and worn from battles long gone. You could say it is a swordsman's shortsword short sword."
+ icon_state = "shortsword"
+ inhand_icon_state = "shortsword"
+ worn_icon_state = "shortsword"
+ slot_flags = ITEM_SLOT_BELT
+ force = 20
+ demolition_mod = 0.75
+ block_chance = 30
+
+/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
+ desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim."
+ obj_flags = CONDUCTS_ELECTRICITY
+ item_flags = DROPDEL //WOW BRO YOU LOST AN ARM, GUESS WHAT YOU DONT GET YOUR SWORD ANYMORE //I CANT BELIEVE SPOOKYDONUT WOULD BREAK THE REQUIREMENTS
+ slot_flags = null
+ block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
+ light_range = 3
+ attack_verb_continuous = list("brutalizes", "eviscerates", "disembowels", "hacks", "carves", "cleaves") //ONLY THE MOST VISCERAL ATTACK VERBS
+ attack_verb_simple = list("brutalize", "eviscerate", "disembowel", "hack", "carve", "cleave")
+ var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE
+ var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK
+
+/obj/item/claymore/highlander/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_NODROP, HIGHLANDER_TRAIT)
+ START_PROCESSING(SSobj, src)
+
+/obj/item/claymore/highlander/Destroy()
+ if(nuke_disk)
+ nuke_disk.forceMove(get_turf(src))
+ nuke_disk.visible_message(span_warning("The nuke disk is vulnerable!"))
+ nuke_disk = null
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/claymore/highlander/process()
+ if(ishuman(loc))
+ var/mob/living/carbon/human/holder = loc
+ holder.layer = ABOVE_ALL_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS)
+ ADD_TRAIT(holder, TRAIT_NOBLOOD, HIGHLANDER_TRAIT) //AND WE WON'T BLEED OUT LIKE COWARDS
+ else
+ if(!(flags_1 & ADMIN_SPAWNED_1))
+ qdel(src)
+
+
+/obj/item/claymore/highlander/pickup(mob/living/user)
+ . = ..()
+ to_chat(user, span_notice("The power of Scotland protects you! You are shielded from all stuns and knockdowns."))
+ user.ignore_slowdown(HIGHLANDER_TRAIT)
+ user.add_stun_absorption(
+ source = HIGHLANDER_TRAIT,
+ message = span_warning("%EFFECT_OWNER is protected by the power of Scotland!"),
+ self_message = span_boldwarning("The power of Scotland absorbs the stun!"),
+ examine_message = span_warning("%EFFECT_OWNER_THEYRE protected by the power of Scotland!"),
+ )
+
+/obj/item/claymore/highlander/dropped(mob/living/user)
+ . = ..()
+ user.unignore_slowdown(HIGHLANDER_TRAIT)
+ user.remove_stun_absorption(HIGHLANDER_TRAIT)
+
+/obj/item/claymore/highlander/examine(mob/user)
+ . = ..()
+ . += "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade."
+ if(nuke_disk)
+ . += span_boldwarning("It's holding the nuke disk!")
+
+/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user)
+ . = ..()
+ if(!QDELETED(target) && target.stat == DEAD && target.mind?.has_antag_datum(/datum/antagonist/highlander))
+ user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
+ add_notch(user)
+ target.visible_message(span_warning("[target] crumbles to dust beneath [user]'s blows!"), span_userdanger("As you fall, your body crumbles to dust!"))
+ target.investigate_log("has been dusted by a highlander claymore.", INVESTIGATE_DEATHS)
+ target.dust()
+
+/obj/item/claymore/highlander/attack_self(mob/living/user)
+ var/closest_victim
+ var/closest_distance = 255
+ for(var/mob/living/carbon/human/scot in GLOB.player_list - user)
+ if(scot.mind?.has_antag_datum(/datum/antagonist/highlander) && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
+ closest_victim = scot
+ for(var/mob/living/silicon/robot/siliscot in GLOB.player_list - user)
+ if(siliscot.mind?.has_antag_datum(/datum/antagonist/highlander) && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
+ closest_victim = siliscot
+
+ if(!closest_victim)
+ to_chat(user, span_warning("[src] thrums for a moment and falls dark. Perhaps there's nobody nearby."))
+ return
+ to_chat(user, span_danger("[src] thrums and points to the [dir2text(get_dir(user, closest_victim))]."))
+
+/obj/item/claymore/highlander/IsReflect()
+ return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME?
+
+/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
+ notches++
+ force++
+ var/new_name = name
+ switch(notches)
+ if(1)
+ to_chat(user, span_notice("Your first kill - hopefully one of many. You scratch a notch into [src]'s blade."))
+ to_chat(user, span_warning("You feel your fallen foe's soul entering your blade, restoring your wounds!"))
+ new_name = "notched claymore"
+ if(2)
+ to_chat(user, span_notice("Another falls before you. Another soul fuses with your own. Another notch in the blade."))
+ new_name = "double-notched claymore"
+ add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY)
+ if(3)
+ to_chat(user, span_notice("You're beginning to relish the thrill of battle."))
+ new_name = "triple-notched claymore"
+ add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY)
+ if(4)
+ to_chat(user, span_notice("You've lost count of how many you've killed."))
+ new_name = "many-notched claymore"
+ add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY)
+ if(5)
+ to_chat(user, span_bolddanger("Five voices now echo in your mind, cheering the slaughter."))
+ new_name = "battle-tested claymore"
+ add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY)
+ if(6)
+ to_chat(user, span_bolddanger("Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe."))
+ new_name = "battle-scarred claymore"
+ add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY)
+ if(7)
+ to_chat(user, span_bolddanger("Kill. Butcher. Conquer."))
+ new_name = "vicious claymore"
+ add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY)
+ if(8)
+ to_chat(user, span_userdanger("IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE."))
+ new_name = "bloodthirsty claymore"
+ add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY)
+ if(9)
+ to_chat(user, span_userdanger("ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE."))
+ new_name = "gore-stained claymore"
+ add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY)
+ if(10)
+ user.visible_message(span_warning("[user]'s eyes light up with a vengeful fire!"), \
+ span_userdanger("YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!"))
+ new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]"
+ icon_state = "claymore_gold"
+ inhand_icon_state = "cultblade"
+ lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
+ remove_atom_colour(ADMIN_COLOUR_PRIORITY)
+ user.update_held_items()
+
+ name = new_name
+ playsound(user, 'sound/items/tools/screwdriver2.ogg', 50, TRUE)
+
+/obj/item/claymore/highlander/robot //BLOODTHIRSTY BORGS NOW COME IN PLAID
+ icon = 'icons/obj/items_cyborg.dmi'
+ icon_state = "claymore_cyborg"
+
+/obj/item/claymore/highlander/robot/Initialize(mapload)
+ . = ..()
+ if(!iscyborg(loc))
+ return INITIALIZE_HINT_QDEL
+
+/obj/item/claymore/highlander/robot/process()
+ loc.layer = ABOVE_ALL_MOB_LAYER
+
+/obj/item/claymore/gladius
+ name = "gladius"
+ desc = "A short but formidable sword, favored by recently-reanimated ancient warriors."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "gladius"
+ inhand_icon_state = "gladius"
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ sharpness = SHARP_POINTY
+ attack_verb_continuous = list("stabs", "cuts")
+ attack_verb_simple = list("stab", "cut")
+ slot_flags = null
+ sound_vary = TRUE
+ block_sound = 'sound/items/weapons/parry.ogg'
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+ pickup_sound = SFX_KNIFE_PICKUP
+ drop_sound = SFX_KNIFE_DROP
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/weaponry/melee/dualsaber.dm
similarity index 100%
rename from code/game/objects/items/dualsaber.dm
rename to code/game/objects/items/weaponry/melee/dualsaber.dm
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/weaponry/melee/energy.dm
similarity index 100%
rename from code/game/objects/items/melee/energy.dm
rename to code/game/objects/items/weaponry/melee/energy.dm
diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/weaponry/melee/fireaxe.dm
similarity index 100%
rename from code/game/objects/items/fireaxe.dm
rename to code/game/objects/items/weaponry/melee/fireaxe.dm
diff --git a/code/game/objects/items/weaponry/melee/high_frequency_blade.dm b/code/game/objects/items/weaponry/melee/high_frequency_blade.dm
new file mode 100644
index 00000000000..618c5d24cf9
--- /dev/null
+++ b/code/game/objects/items/weaponry/melee/high_frequency_blade.dm
@@ -0,0 +1,152 @@
+/obj/item/highfrequencyblade
+ name = "high frequency blade"
+ desc = "A sword reinforced by a powerful alternating current and resonating at extremely high vibration frequencies. \
+ This oscillation weakens the molecular bonds of anything it cuts, thereby increasing its cutting ability."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "hfrequency0"
+ worn_icon_state = "hfrequency0"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ force = 10
+ wound_bonus = 25
+ exposed_wound_bonus = 50
+ throwforce = 25
+ throw_speed = 4
+ attack_speed = CLICK_CD_HYPER_RAPID
+ embed_type = /datum/embedding/hfr_blade
+ block_chance = 25
+ block_sound = 'sound/items/weapons/parry.ogg'
+ sharpness = SHARP_EDGED
+ w_class = WEIGHT_CLASS_BULKY
+ slot_flags = ITEM_SLOT_BACK
+ /// The color of the slash we create
+ var/slash_color = COLOR_BLUE
+ /// Previous x position of where we clicked on the target's icon
+ var/previous_x
+ /// Previous y position of where we clicked on the target's icon
+ var/previous_y
+ /// The previous target we attacked
+ var/datum/weakref/previous_target
+
+/datum/embedding/hfr_blade
+ embed_chance = 100
+
+/obj/item/highfrequencyblade/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/two_handed, \
+ wield_callback = CALLBACK(src, PROC_REF(on_wield)), \
+ unwield_callback = CALLBACK(src, PROC_REF(on_unwield)), \
+ )
+ AddElement(/datum/element/update_icon_updates_onmob)
+
+/obj/item/highfrequencyblade/update_icon_state()
+ icon_state = "hfrequency[HAS_TRAIT(src, TRAIT_WIELDED)]"
+ return ..()
+
+/obj/item/highfrequencyblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == PROJECTILE_ATTACK)
+ if(HAS_TRAIT(src, TRAIT_WIELDED) || prob(final_block_chance))
+ owner.visible_message(span_danger("[owner] deflects [attack_text] with [src]!"))
+ playsound(src, SFX_BULLET_MISS, 75, TRUE)
+ return TRUE
+ return FALSE
+ var/stop_that_blade = (final_block_chance + (attack_type == OVERWHELMING_ATTACK ? 25 : 0)) * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1)
+ if(prob(stop_that_blade))
+ owner.visible_message(span_danger("[owner] parries [attack_text] with [src]!"))
+ return TRUE
+ return FALSE
+
+/obj/item/highfrequencyblade/pre_attack(atom/target, mob/living/user, list/modifiers, list/attack_modifiers)
+ . = ..()
+ if(.)
+ return .
+ if(!HAS_TRAIT(src, TRAIT_WIELDED))
+ return . // Default attack
+ if(isliving(target) && HAS_TRAIT(src, TRAIT_PACIFISM))
+ return . // Default attack (ultimately nothing)
+
+ return slash(target, user, modifiers)
+
+/// triggered on wield of two handed item
+/obj/item/highfrequencyblade/proc/on_wield(obj/item/source, mob/user)
+ update_icon(UPDATE_ICON_STATE)
+
+/// triggered on unwield of two handed item
+/obj/item/highfrequencyblade/proc/on_unwield(obj/item/source, mob/user)
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/highfrequencyblade/proc/slash(atom/target, mob/living/user, list/modifiers)
+ user.do_attack_animation(target, "nothing")
+ var/damage_mod = 1
+ var/x_slashed = text2num(modifiers[ICON_X]) || ICON_SIZE_X/2 //in case we arent called by a client
+ var/y_slashed = text2num(modifiers[ICON_Y]) || ICON_SIZE_Y/2 //in case we arent called by a client
+ new /obj/effect/temp_visual/slash(get_turf(target), target, x_slashed, y_slashed, slash_color)
+ if(target == previous_target?.resolve()) //if the same target, we calculate a damage multiplier if you swing your mouse around
+ var/x_mod = previous_x - x_slashed
+ var/y_mod = previous_y - y_slashed
+ damage_mod = max(1, round((sqrt(x_mod ** 2 + y_mod ** 2) / 10), 0.1))
+ previous_target = WEAKREF(target)
+ previous_x = x_slashed
+ previous_y = y_slashed
+ playsound(src, 'sound/items/weapons/bladeslice.ogg', 100, vary = TRUE)
+ playsound(src, 'sound/items/weapons/zapbang.ogg', 50, vary = TRUE)
+ if(isliving(target))
+ var/mob/living/living_target = target
+ living_target.apply_damage(force*damage_mod, BRUTE, sharpness = SHARP_EDGED, wound_bonus = wound_bonus, exposed_wound_bonus = exposed_wound_bonus, def_zone = user.zone_selected)
+ log_combat(user, living_target, "slashed", src)
+ if(living_target.stat == DEAD && prob(force*damage_mod*0.5))
+ living_target.visible_message(span_danger("[living_target] explodes in a shower of gore!"), blind_message = span_hear("You hear organic matter ripping and tearing!"))
+ living_target.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
+ living_target.gib(DROP_ALL_REMAINS)
+ log_combat(user, living_target, "gibbed", src)
+ return TRUE
+ else if(target.uses_integrity)
+ target.take_damage(force*damage_mod*3, BRUTE, MELEE, FALSE, null, 50)
+ return TRUE
+ else if(iswallturf(target) && prob(force*damage_mod*0.5))
+ var/turf/closed/wall/wall_target = target
+ wall_target.dismantle_wall()
+ return TRUE
+ else if(ismineralturf(target) && prob(force*damage_mod))
+ var/turf/closed/mineral/mineral_target = target
+ mineral_target.gets_drilled()
+ return TRUE
+ return FALSE
+
+/obj/effect/temp_visual/slash
+ icon_state = "highfreq_slash"
+ alpha = 150
+ duration = 0.5 SECONDS
+ layer = ABOVE_ALL_MOB_LAYER
+ plane = ABOVE_GAME_PLANE
+
+/obj/effect/temp_visual/slash/Initialize(mapload, atom/target, x_slashed, y_slashed, slash_color)
+ . = ..()
+ if(!target)
+ return
+ var/matrix/new_transform = matrix()
+ new_transform.Turn(rand(1, 360)) // Random slash angle
+ var/datum/decompose_matrix/decomp = target.transform.decompose()
+ new_transform.Translate((x_slashed - ICON_SIZE_X/2) * decomp.scale_x, (y_slashed - ICON_SIZE_Y/2) * decomp.scale_y) // Move to where we clicked
+ //Follow target's transform while ignoring scaling
+ new_transform.Turn(decomp.rotation)
+ new_transform.Translate(decomp.shift_x, decomp.shift_y)
+ new_transform.Translate(target.pixel_x, target.pixel_y) // Follow target's pixel offsets
+ transform = new_transform
+ //Double the scale of the matrix by doubling the 2x2 part without touching the translation part
+ var/matrix/scaled_transform = new_transform + matrix(new_transform.a, new_transform.b, 0, new_transform.d, new_transform.e, 0)
+ animate(src, duration*0.5, color = slash_color, transform = scaled_transform, alpha = 255)
+
+/obj/item/highfrequencyblade/wizard
+ desc = "A blade that was mastercrafted by a legendary blacksmith. Its enchantments let it slash through anything."
+ force = 8
+ throwforce = 20
+ wound_bonus = 20
+ exposed_wound_bonus = 25
+
+/obj/item/highfrequencyblade/wizard/attack_self(mob/user, modifiers)
+ if(!HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED))
+ balloon_alert(user, "you're too weak!")
+ return
+ return ..()
diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/weaponry/melee/his_grace.dm
similarity index 100%
rename from code/game/objects/items/his_grace.dm
rename to code/game/objects/items/weaponry/melee/his_grace.dm
diff --git a/code/game/objects/items/weaponry/melee/katana.dm b/code/game/objects/items/weaponry/melee/katana.dm
new file mode 100644
index 00000000000..28747b8a0ef
--- /dev/null
+++ b/code/game/objects/items/weaponry/melee/katana.dm
@@ -0,0 +1,50 @@
+/obj/item/katana
+ name = "katana"
+ desc = "Woefully underpowered in D20."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "katana"
+ inhand_icon_state = "katana"
+ worn_icon_state = "katana"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ obj_flags = CONDUCTS_ELECTRICITY
+ slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
+ force = 40
+ throwforce = 10
+ w_class = WEIGHT_CLASS_HUGE
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+ attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
+ attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
+ block_chance = 50
+ block_sound = 'sound/items/weapons/parry.ogg'
+ sharpness = SHARP_EDGED
+ max_integrity = 200
+ armor_type = /datum/armor/item_katana
+ resistance_flags = FIRE_PROOF
+ var/list/alt_continuous = list("stabs", "pierces", "impales")
+ var/list/alt_simple = list("stab", "pierce", "impale")
+
+/obj/item/katana/Initialize(mapload)
+ . = ..()
+ alt_continuous = string_list(alt_continuous)
+ alt_simple = string_list(alt_simple)
+ AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -15)
+
+/obj/item/katana/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == OVERWHELMING_ATTACK)
+ final_block_chance = 0 //Not a high freuqnecy blade, sorry pal
+ return ..()
+
+/datum/armor/item_katana
+ fire = 100
+ acid = 50
+
+/obj/item/katana/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!"))
+ return BRUTELOSS
+
+/obj/item/katana/cursed //used by wizard events, see the tendril_loot.dm file for the miner one
+ slot_flags = null
+
+//Ninja energy katana is located in the antagonist module.
diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/weaponry/melee/knives.dm
similarity index 72%
rename from code/game/objects/items/knives.dm
rename to code/game/objects/items/weaponry/melee/knives.dm
index b94a91e3456..c26f460871b 100644
--- a/code/game/objects/items/knives.dm
+++ b/code/game/objects/items/weaponry/melee/knives.dm
@@ -1,3 +1,9 @@
+///Includes
+//*Knives
+//*Boxcutter
+//*Switchblades
+///
+
// Knife Template, should not appear in game normaly //
/obj/item/knife
name = "knife"
@@ -339,3 +345,133 @@
inhand_icon_state = "rootshiv"
icon_angle = -45
custom_materials = null
+
+/obj/item/switchblade
+ name = "switchblade"
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "switchblade"
+ base_icon_state = "switchblade"
+ icon_angle = -90
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ desc = "A sharp, concealable, spring-loaded knife."
+ obj_flags = CONDUCTS_ELECTRICITY
+ force = 3
+ w_class = WEIGHT_CLASS_SMALL
+ throwforce = 5
+ throw_speed = 3
+ throw_range = 6
+ custom_materials = list(/datum/material/iron= SHEET_MATERIAL_AMOUNT * 6)
+ hitsound = 'sound/items/weapons/genhit.ogg'
+ attack_verb_continuous = list("stubs", "pokes")
+ attack_verb_simple = list("stub", "poke")
+ resistance_flags = FIRE_PROOF
+ /// Whether the switchblade starts extended or not.
+ var/start_extended = FALSE
+ var/list/alt_continuous = list("stabs", "pierces", "shanks")
+ var/list/alt_simple = list("stab", "pierce", "shank")
+
+/obj/item/switchblade/get_all_tool_behaviours()
+ return list(TOOL_KNIFE)
+
+/obj/item/switchblade/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+ AddComponent(/datum/component/butchering, \
+ speed = 7 SECONDS, \
+ effectiveness = 100, \
+ )
+
+ AddComponent( \
+ /datum/component/transforming, \
+ start_transformed = start_extended, \
+ force_on = 20, \
+ throwforce_on = 23, \
+ throw_speed_on = throw_speed, \
+ sharpness_on = SHARP_EDGED, \
+ hitsound_on = 'sound/items/weapons/bladeslice.ogg', \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ attack_verb_continuous_on = list("slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts"), \
+ attack_verb_simple_on = list("slash", "slice", "tear", "lacerate", "rip", "dice", "cut"), \
+ )
+
+ alt_continuous = string_list(alt_continuous)
+ alt_simple = string_list(alt_simple)
+ AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -5, TRAIT_TRANSFORM_ACTIVE)
+
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
+
+/obj/item/switchblade/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ tool_behaviour = (active ? TOOL_KNIFE : NONE)
+
+/obj/item/switchblade/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return BRUTELOSS
+
+/obj/item/switchblade/extended
+ start_extended = TRUE
+
+/obj/item/boxcutter
+ name = "boxcutter"
+ desc = "A tool for cutting boxes, or throats."
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "boxcutter"
+ inhand_icon_state = "boxcutter"
+ base_icon_state = "boxcutter"
+ icon_angle = -90
+ lefthand_file = 'icons/mob/inhands/equipment/boxcutter_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/boxcutter_righthand.dmi'
+ inhand_icon_state = null
+ attack_verb_continuous = list("prods", "pokes")
+ attack_verb_simple = list("prod", "poke")
+ w_class = WEIGHT_CLASS_SMALL
+ resistance_flags = FIRE_PROOF
+ force = 0
+ /// Used on Initialize, how much time to cut cable restraints and zipties.
+ var/snap_time_weak_handcuffs = 0 SECONDS
+ /// Used on Initialize, how much time to cut real handcuffs. Null means it can't.
+ var/snap_time_strong_handcuffs = null
+ /// Starts open if true
+ var/start_extended = FALSE
+
+/obj/item/boxcutter/get_all_tool_behaviours()
+ return list(TOOL_KNIFE)
+
+/obj/item/boxcutter/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+ AddComponent(/datum/component/butchering, \
+ speed = 7 SECONDS, \
+ effectiveness = 100, \
+ )
+
+ AddComponent( \
+ /datum/component/transforming, \
+ start_transformed = start_extended, \
+ force_on = 10, \
+ throwforce_on = 4, \
+ throw_speed_on = throw_speed, \
+ sharpness_on = SHARP_EDGED, \
+ hitsound_on = 'sound/items/weapons/bladeslice.ogg', \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ attack_verb_continuous_on = list("cuts", "stabs", "slashes"), \
+ attack_verb_simple_on = list("cut", "stab", "slash"), \
+ )
+
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
+
+/obj/item/boxcutter/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ playsound(src, 'sound/items/boxcutter_activate.ogg', 50)
+ tool_behaviour = (active ? TOOL_KNIFE : NONE)
+ if(active)
+ AddElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
+ else
+ RemoveElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
+/obj/item/boxcutter/extended
+ start_extended = TRUE
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/weaponry/melee/misc.dm
similarity index 55%
rename from code/game/objects/items/melee/misc.dm
rename to code/game/objects/items/weaponry/melee/misc.dm
index 2f4defafa2c..8bb68ee396e 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/weaponry/melee/misc.dm
@@ -33,163 +33,6 @@
)
//very imprecise
-/obj/item/melee/sabre
- name = "officer's sabre"
- desc = "An elegant weapon, its monomolecular edge is capable of cutting through flesh and bone with ease."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "sabre"
- inhand_icon_state = "sabre"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- obj_flags = CONDUCTS_ELECTRICITY | UNIQUE_RENAME
- force = 20
- throwforce = 10
- demolition_mod = 0.75 //but not metal
- w_class = WEIGHT_CLASS_BULKY
- block_chance = 50
- armour_penetration = 75
- sharpness = SHARP_EDGED
- attack_verb_continuous = list("slashes", "cuts")
- attack_verb_simple = list("slash", "cut")
- block_sound = 'sound/items/weapons/parry.ogg'
- hitsound = 'sound/items/weapons/rapierhit.ogg'
- custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT)
- wound_bonus = 10
- exposed_wound_bonus = 25
-
-/obj/item/melee/sabre/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/cuffable_item) //closed sword guard
- AddComponent(/datum/component/jousting)
- //fast and effective, but as a sword, it might damage the results.
- AddComponent(/datum/component/butchering, \
- speed = 3 SECONDS, \
- effectiveness = 95, \
- bonus_modifier = 5, \
- )
- // The weight of authority comes down on the tider's crimes.
- AddElement(/datum/element/bane, target_type = /mob/living/carbon/human, damage_multiplier = 0.35)
- RegisterSignal(src, COMSIG_OBJECT_PRE_BANING, PROC_REF(attempt_bane))
- RegisterSignal(src, COMSIG_OBJECT_ON_BANING, PROC_REF(bane_effects))
-
-/**
- * If the target reeks of maintenance, the blade can tear through their body with a total of 20 damage.
- */
-/obj/item/melee/sabre/proc/attempt_bane(element_owner, mob/living/carbon/criminal)
- SIGNAL_HANDLER
- var/obj/item/organ/liver/liver = criminal.get_organ_slot(ORGAN_SLOT_LIVER)
- if(isnull(liver) || !HAS_TRAIT(liver, TRAIT_MAINTENANCE_METABOLISM))
- return COMPONENT_CANCEL_BANING
-
-/**
- * Assistants should fear this weapon.
- */
-/obj/item/melee/sabre/proc/bane_effects(element_owner, mob/living/carbon/human/baned_target)
- SIGNAL_HANDLER
- baned_target.visible_message(
- span_warning("[src] tears through [baned_target] with unnatural ease!"),
- span_userdanger("As [src] tears into your body, you feel the weight of authority collapse into your wounds!"),
- )
- INVOKE_ASYNC(baned_target, TYPE_PROC_REF(/mob/living/carbon/human, emote), "scream")
-
-/obj/item/melee/sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
- if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
- final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you.
- return ..()
-
-/obj/item/melee/sabre/on_exit_storage(datum/storage/container)
- playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE)
-
-/obj/item/melee/sabre/on_enter_storage(datum/storage/container)
- playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE)
-
-/obj/item/melee/sabre/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is trying to cut off all [user.p_their()] limbs with [src]! it looks like [user.p_theyre()] trying to commit suicide!"))
- var/i = 0
- ADD_TRAIT(src, TRAIT_NODROP, SABRE_SUICIDE_TRAIT)
- if(iscarbon(user))
- var/mob/living/carbon/Cuser = user
- var/obj/item/bodypart/holding_bodypart = Cuser.get_holding_bodypart_of_item(src)
- var/list/limbs_to_dismember
- var/list/arms = list()
- var/list/legs = list()
- var/obj/item/bodypart/bodypart
-
- for(bodypart in Cuser.bodyparts)
- if(bodypart == holding_bodypart)
- continue
- if(bodypart.body_part & ARMS)
- arms += bodypart
- else if (bodypart.body_part & LEGS)
- legs += bodypart
-
- limbs_to_dismember = arms + legs
- if(holding_bodypart)
- limbs_to_dismember += holding_bodypart
-
- var/speedbase = abs((4 SECONDS) / limbs_to_dismember.len)
- for(bodypart in limbs_to_dismember)
- i++
- addtimer(CALLBACK(src, PROC_REF(suicide_dismember), user, bodypart), speedbase * i)
- addtimer(CALLBACK(src, PROC_REF(manual_suicide), user), (5 SECONDS) * i)
- return MANUAL_SUICIDE
-
-/obj/item/melee/sabre/proc/suicide_dismember(mob/living/user, obj/item/bodypart/affecting)
- if(!QDELETED(affecting) && !(affecting.bodypart_flags & BODYPART_UNREMOVABLE) && affecting.owner == user && !QDELETED(user))
- playsound(user, hitsound, 25, TRUE)
- affecting.dismember(BRUTE)
- user.adjust_brute_loss(force * 1.25)
-
-/obj/item/melee/sabre/proc/manual_suicide(mob/living/user, originally_nodropped)
- if(!QDELETED(user))
- user.adjust_brute_loss(200)
- user.death(FALSE)
- REMOVE_TRAIT(src, TRAIT_NODROP, SABRE_SUICIDE_TRAIT)
-
-
-/obj/item/melee/parsnip_sabre
- name = "parsnip sabre"
- desc = "A weird, yet elegant weapon. Surprisingly sharp for something made from a parsnip."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "parsnip_sabre"
- inhand_icon_state = "parsnip_sabre"
- icon_angle = -45
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- force = 15
- throwforce = 10
- demolition_mod = 0.3
- w_class = WEIGHT_CLASS_BULKY
- block_chance = 40
- armour_penetration = 40
- sharpness = SHARP_EDGED
- attack_verb_continuous = list("slashes", "cuts")
- attack_verb_simple = list("slash", "cut")
- block_sound = 'sound/items/weapons/parry.ogg'
- hitsound = 'sound/items/weapons/rapierhit.ogg'
- custom_materials = null
- wound_bonus = 5
- exposed_wound_bonus = 15
-
-/obj/item/melee/parsnip_sabre/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/cuffable_item) //closed sword guard
- AddComponent(/datum/component/jousting)
-
-/obj/item/melee/parsnip_sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
- if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
- final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you.
- return ..()
-
-/obj/item/melee/parsnip_sabre/on_exit_storage(datum/storage/container)
- . = ..()
- playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE)
-
-/obj/item/melee/parsnip_sabre/on_enter_storage(datum/storage/container)
- . = ..()
- playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE)
-
/obj/item/melee/beesword
name = "The Stinger"
desc = "Taken from a giant bee and folded over one thousand times in pure honey. Can sting through anything."
@@ -228,122 +71,6 @@
playsound(get_turf(src), hitsound, 75, TRUE, -1)
return TOXLOSS
-/obj/item/melee/supermatter_sword
- name = "supermatter sword"
- desc = "In a station full of bad ideas, this might just be the worst."
- icon = 'icons/obj/weapons/sword.dmi'
- icon_state = "supermatter_sword_balanced"
- inhand_icon_state = "supermatter_sword"
- icon_angle = -90
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- slot_flags = null
- w_class = WEIGHT_CLASS_BULKY
- force = 0.001
- armour_penetration = 1000
- force_string = "INFINITE"
- item_flags = NEEDS_PERMIT|NO_BLOOD_ON_ITEM
- custom_materials = list(/datum/material/adamantine = SHEET_MATERIAL_AMOUNT * 20, /datum/material/iron = SHEET_MATERIAL_AMOUNT)
- var/obj/machinery/power/supermatter_crystal/shard
- var/balanced = 1
-
-/obj/item/melee/supermatter_sword/Initialize(mapload)
- . = ..()
- shard = new /obj/machinery/power/supermatter_crystal(src)
- qdel(shard.countdown)
- shard.countdown = null
- START_PROCESSING(SSobj, src)
- visible_message(span_warning("[src] appears, balanced ever so perfectly on its hilt. This isn't ominous at all."))
- RegisterSignal(src, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(eat_bullets))
-
-/obj/item/melee/supermatter_sword/process()
- if(balanced || throwing || ismob(src.loc) || isnull(src.loc))
- return
- if(!isturf(src.loc))
- var/atom/target = src.loc
- forceMove(target.loc)
- consume_everything(target)
- else
- var/turf/turf = get_turf(src)
- if(!isspaceturf(turf))
- consume_turf(turf)
-
-/obj/item/melee/supermatter_sword/pre_attack(atom/target, mob/living/user, list/modifiers, list/attack_modifiers)
- . = ..()
- if(.)
- return .
-
- if(target == user)
- user.dropItemToGround(src, TRUE)
- else
- user.do_attack_animation(target)
- consume_everything(target)
- return TRUE
-
-/obj/item/melee/supermatter_sword/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- ..()
- if(ismob(hit_atom))
- var/mob/mob = hit_atom
- if(src.loc == mob)
- mob.dropItemToGround(src, TRUE)
- consume_everything(hit_atom)
-
-/obj/item/melee/supermatter_sword/pickup(user)
- ..()
- balanced = 0
- icon_state = "supermatter_sword"
- icon_angle = -45
-
-/obj/item/melee/supermatter_sword/ex_act(severity, target)
- visible_message(
- span_danger("The blast wave smacks into [src] and rapidly flashes to ash."),
- span_hear("You hear a loud crack as you are washed with a wave of heat.")
- )
- consume_everything()
- return TRUE
-
-/obj/item/melee/supermatter_sword/acid_act()
- visible_message(span_danger("The acid smacks into [src] and rapidly flashes to ash."),\
- span_hear("You hear a loud crack as you are washed with a wave of heat."))
- consume_everything()
- return TRUE
-
-/obj/item/melee/supermatter_sword/proc/eat_bullets(datum/source, obj/projectile/hitting_projectile)
- SIGNAL_HANDLER
-
- visible_message(
- span_danger("[hitting_projectile] smacks into [source] and rapidly flashes to ash."),
- null,
- span_hear("You hear a loud crack as you are washed with a wave of heat."),
- )
- consume_everything(hitting_projectile)
- return COMPONENT_BULLET_BLOCKED
-
-/obj/item/melee/supermatter_sword/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] touches [src]'s blade. It looks like [user.p_theyre()] tired of waiting for the radiation to kill [user.p_them()]!"))
- user.dropItemToGround(src, TRUE)
- shard.Bumped(user)
-
-/obj/item/melee/supermatter_sword/proc/consume_everything(target)
- if(isnull(target))
- shard.Bump(target)
- else if(!isturf(target))
- shard.Bumped(target)
- else
- consume_turf(target)
-
-/obj/item/melee/supermatter_sword/proc/consume_turf(turf/turf)
- var/oldtype = turf.type
- var/turf/newT = turf.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
- if(newT.type == oldtype)
- return
- playsound(turf, 'sound/effects/supermatter.ogg', 50, TRUE)
- turf.visible_message(
- span_danger("[turf] smacks into [src] and rapidly flashes to ash."),
- span_hear("You hear a loud crack as you are washed with a wave of heat."),
- )
- shard.Bump(turf)
-
/obj/item/melee/curator_whip
name = "curator's whip"
desc = "Somewhat eccentric and outdated, it still stings like hell to be hit by."
@@ -548,3 +275,281 @@
final_block_chance = 0 //Don't bring a...mace to a gunfight, and also you aren't going to really block someone full body tackling you with a mace. Or a road roller, if one happened to hit you.
return ..()
+/obj/item/sord
+ name = "\improper SORD"
+ desc = "This thing is so unspeakably shitty you are having a hard time even holding it."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "sord"
+ inhand_icon_state = "sord"
+ icon_angle = -35
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ slot_flags = ITEM_SLOT_BELT
+ force = 2
+ throwforce = 1
+ w_class = WEIGHT_CLASS_NORMAL
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+ attack_verb_continuous = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts")
+ attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
+
+/obj/item/sord/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty."), \
+ span_suicide("You try to impale yourself with [src], but it's USELESS..."))
+ return SHAME
+
+/obj/item/carpenter_hammer
+ name = "carpenter hammer"
+ icon = 'icons/obj/weapons/hammer.dmi'
+ icon_state = "carpenter_hammer"
+ inhand_icon_state = "carpenter_hammer"
+ worn_icon_state = "clawhammer" //plaecholder
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
+ desc = "Uncanny looking hammer."
+ force = 17
+ throwforce = 14
+ throw_range = 4
+ w_class = WEIGHT_CLASS_NORMAL
+ wound_bonus = 20
+ demolition_mod = 1.15
+ slot_flags = ITEM_SLOT_BELT
+
+/obj/item/carpenter_hammer/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/kneejerk)
+ AddComponent(/datum/component/item_killsound, \
+ allowed_mobs = list(/mob/living/carbon/human), \
+ killsound = 'sound/items/weapons/hammer_death_scream.ogg', \
+ replace_default_death_sound = TRUE, \
+ )
+
+/obj/item/carpenter_hammer/examine(mob/user)
+ . = ..()
+ . += ""
+ . += "Real World Tip:"
+ . += pick(
+ "Every building, from hospitals to homes, has a room that serves as the heart of the building \
+ and carries blood and nutrients to its extremities. Try to find the heart of your home!",
+ "All the food you've tried is rotten. You've never eaten fresh food.",
+ "Viruses do not exist. Illness is simply your body punishing you for what you have done wrong.",
+ "Space stations must have at least 50 mammalian teeth embedded in the north walls for structural safety reasons.",
+ "Queen dragonfly sleeps and smiles.",
+ )
+
+/obj/item/phone
+ name = "red phone"
+ desc = "Should anything ever go wrong..."
+ icon = 'icons/obj/devices/voice.dmi'
+ icon_state = "red_phone"
+ force = 3
+ throwforce = 2
+ throw_speed = 3
+ throw_range = 4
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb_continuous = list("calls", "rings")
+ attack_verb_simple = list("call", "ring")
+ hitsound = 'sound/items/weapons/ring.ogg'
+
+/obj/item/phone/suicide_act(mob/living/user)
+ if(locate(/obj/structure/chair/stool) in user.loc)
+ user.visible_message(span_suicide("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
+ else
+ user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return OXYLOSS
+
+/obj/item/bambostaff
+ name = "bamboo staff"
+ desc = "A long bamboo-made staff with steel-capped ends. It is rumoured that initiates of Spider Clan train with such before getting to learn how to use a katana."
+ force = 10
+ block_chance = 45
+ block_sound = 'sound/items/weapons/genhit.ogg'
+ slot_flags = ITEM_SLOT_BACK
+ w_class = WEIGHT_CLASS_BULKY
+ hitsound = SFX_SWING_HIT
+ attack_verb_continuous = list("smashes", "slams", "whacks", "thwacks")
+ attack_verb_simple = list("smash", "slam", "whack", "thwack")
+ icon = 'icons/obj/weapons/staff.dmi'
+ icon_state = "bambostaff0"
+ base_icon_state = "bambostaff"
+ inhand_icon_state = "bambostaff0"
+ worn_icon_state = "bambostaff0"
+ icon_angle = -135
+ lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
+ custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 4)
+
+/obj/item/bambostaff/Initialize(mapload)
+ . = ..()
+ // there are too many puns to choose from. ('Bo' is the 'real' name for this kind of weapon.)
+ name = pick("bamboo staff", "bambo staff", "bam-Bo staff", "bam boo staff", "bam-boo staff", "bam Bo", "bambo", "bam-Bo", "bamboo-Bo")
+ AddComponent(/datum/component/two_handed, \
+ force_unwielded = 10, \
+ force_wielded = 14, \
+ )
+
+/obj/item/bambostaff/update_icon_state()
+ icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]"
+ return ..()
+
+/obj/item/bambostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
+ final_block_chance = 0 //Don't bring a staff to a gunfight, and also you aren't going to really block someone full body tackling you with a staff. Or a road roller, if one happened to hit you.
+ return ..()
+
+/obj/item/staff
+ name = "wizard staff"
+ desc = "Apparently a staff used by the wizard."
+ icon = 'icons/obj/weapons/guns/magic.dmi'
+ icon_state = "staff"
+ inhand_icon_state = "staff"
+ lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
+ force = 3
+ throwforce = 5
+ throw_speed = 2
+ throw_range = 5
+ w_class = WEIGHT_CLASS_SMALL
+ armour_penetration = 100
+ attack_verb_continuous = list("bludgeons", "whacks", "disciplines")
+ attack_verb_simple = list("bludgeon", "whack", "discipline")
+ resistance_flags = FLAMMABLE
+
+/obj/item/staff/broom
+ name = "broom"
+ desc = "Used for sweeping, and flying into the night while cackling. Black cat not included."
+ icon_state = "broom"
+ inhand_icon_state = "broom"
+ resistance_flags = FLAMMABLE
+
+/obj/item/staff/tape
+ name = "tape staff"
+ desc = "A roll of tape snugly attached to a stick."
+ icon_state = "tapestaff"
+ inhand_icon_state = "tapestaff"
+ resistance_flags = FLAMMABLE
+
+/obj/item/staff/stick
+ name = "stick"
+ desc = "A great tool to drag someone else's drinks across the bar."
+ icon = 'icons/obj/weapons/staff.dmi'
+ icon_state = "cane"
+ inhand_icon_state = "stick"
+ icon_angle = 135
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 3
+ throwforce = 5
+ throw_speed = 2
+ throw_range = 5
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/tailclub
+ name = "tail club"
+ desc = "For the beating to death of lizards with their own tails."
+ icon = 'icons/obj/weapons/club.dmi'
+ icon_state = "tailclub"
+ icon_angle = -25
+ force = 14
+ throwforce = 1 // why are you throwing a club do you even weapon
+ throw_speed = 1
+ throw_range = 1
+ attack_verb_continuous = list("clubs", "bludgeons")
+ attack_verb_simple = list("club", "bludgeon")
+ custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT)
+
+/obj/item/melee/flyswatter
+ name = "flyswatter"
+ desc = "Useful for killing pests of all sizes."
+ icon = 'icons/obj/service/hydroponics/equipment.dmi'
+ icon_state = "flyswatter"
+ inhand_icon_state = "flyswatter"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ force = 1
+ throwforce = 1
+ attack_verb_continuous = list("swats", "smacks")
+ attack_verb_simple = list("swat", "smack")
+ hitsound = 'sound/effects/snap.ogg'
+ w_class = WEIGHT_CLASS_SMALL
+ /// Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc.
+ var/static/list/splattable
+
+/obj/item/melee/flyswatter/Initialize(mapload)
+ . = ..()
+ if (isnull(splattable))
+ splattable = typecacheof(list(
+ /mob/living/basic/ant,
+ /mob/living/basic/butterfly,
+ /mob/living/basic/cockroach,
+ /mob/living/basic/cockroach/bloodroach,
+ /mob/living/basic/spider/growing/spiderling,
+ /mob/living/basic/bee,
+ /obj/effect/decal/cleanable/ants,
+ /obj/item/queen_bee,
+ ))
+ AddElement(/datum/element/bane, mob_biotypes = MOB_BUG, target_type = /mob/living/basic, damage_multiplier = 0, added_damage = 24, requires_combat_mode = FALSE)
+
+/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, list/modifiers, list/attack_modifiers)
+ if(is_type_in_typecache(target, splattable))
+ to_chat(user, span_warning("You easily splat [target]."))
+ if(QDELETED(target))
+ return
+ if(isliving(target))
+ new /obj/effect/decal/cleanable/insectguts(target.drop_location())
+ var/mob/living/bug = target
+ bug.investigate_log("has been splatted by a flyswatter.", INVESTIGATE_DEATHS)
+ bug.gib(DROP_ALL_REMAINS)
+ else
+ qdel(target)
+
+/obj/item/proc/can_trigger_gun(mob/living/user, akimbo_usage)
+ if(!user.can_use_guns(src))
+ return FALSE
+ return TRUE
+
+/obj/item/gohei
+ name = "gohei"
+ desc = "A wooden stick with white streamers at the end. Originally used by shrine maidens to purify things. Now used by the station's valued weeaboos."
+ resistance_flags = FLAMMABLE
+ force = 5
+ throwforce = 5
+ hitsound = SFX_SWING_HIT
+ attack_verb_continuous = list("whacks", "thwacks", "wallops", "socks")
+ attack_verb_simple = list("whack", "thwack", "wallop", "sock")
+ icon = 'icons/obj/weapons/club.dmi'
+ icon_state = "gohei"
+ inhand_icon_state = "gohei"
+ icon_angle = -65
+ lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
+
+/obj/item/melee/moonlight_greatsword
+ name = "moonlight greatsword"
+ desc = "Don't tell anyone you put any points into dex, though."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "swordon"
+ inhand_icon_state = "swordon"
+ worn_icon_state = "swordon"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ w_class = WEIGHT_CLASS_BULKY
+ slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT
+ block_chance = 20
+ block_sound = 'sound/items/weapons/parry.ogg'
+ sharpness = SHARP_EDGED
+ force = 14
+ throwforce = 12
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+ attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
+ attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
+ var/list/alt_continuous = list("stabs", "pierces", "impales")
+ var/list/alt_simple = list("stab", "pierce", "impale")
+
+/obj/item/melee/moonlight_greatsword/Initialize(mapload)
+ . = ..()
+ alt_continuous = string_list(alt_continuous)
+ alt_simple = string_list(alt_simple)
+ AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple)
diff --git a/code/game/objects/items/powerfist.dm b/code/game/objects/items/weaponry/melee/powerfist.dm
similarity index 100%
rename from code/game/objects/items/powerfist.dm
rename to code/game/objects/items/weaponry/melee/powerfist.dm
diff --git a/code/game/objects/items/weaponry/melee/sabre.dm b/code/game/objects/items/weaponry/melee/sabre.dm
new file mode 100644
index 00000000000..770f5b53a9c
--- /dev/null
+++ b/code/game/objects/items/weaponry/melee/sabre.dm
@@ -0,0 +1,156 @@
+/obj/item/melee/sabre
+ name = "officer's sabre"
+ desc = "An elegant weapon, its monomolecular edge is capable of cutting through flesh and bone with ease."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "sabre"
+ inhand_icon_state = "sabre"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ obj_flags = CONDUCTS_ELECTRICITY | UNIQUE_RENAME
+ force = 20
+ throwforce = 10
+ demolition_mod = 0.75 //but not metal
+ w_class = WEIGHT_CLASS_BULKY
+ block_chance = 50
+ armour_penetration = 75
+ sharpness = SHARP_EDGED
+ attack_verb_continuous = list("slashes", "cuts")
+ attack_verb_simple = list("slash", "cut")
+ block_sound = 'sound/items/weapons/parry.ogg'
+ hitsound = 'sound/items/weapons/rapierhit.ogg'
+ custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT)
+ wound_bonus = 10
+ exposed_wound_bonus = 25
+
+/obj/item/melee/sabre/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/cuffable_item) //closed sword guard
+ AddComponent(/datum/component/jousting)
+ //fast and effective, but as a sword, it might damage the results.
+ AddComponent(/datum/component/butchering, \
+ speed = 3 SECONDS, \
+ effectiveness = 95, \
+ bonus_modifier = 5, \
+ )
+ // The weight of authority comes down on the tider's crimes.
+ AddElement(/datum/element/bane, target_type = /mob/living/carbon/human, damage_multiplier = 0.35)
+ RegisterSignal(src, COMSIG_OBJECT_PRE_BANING, PROC_REF(attempt_bane))
+ RegisterSignal(src, COMSIG_OBJECT_ON_BANING, PROC_REF(bane_effects))
+
+/**
+ * If the target reeks of maintenance, the blade can tear through their body with a total of 20 damage.
+ */
+/obj/item/melee/sabre/proc/attempt_bane(element_owner, mob/living/carbon/criminal)
+ SIGNAL_HANDLER
+ var/obj/item/organ/liver/liver = criminal.get_organ_slot(ORGAN_SLOT_LIVER)
+ if(isnull(liver) || !HAS_TRAIT(liver, TRAIT_MAINTENANCE_METABOLISM))
+ return COMPONENT_CANCEL_BANING
+
+/**
+ * Assistants should fear this weapon.
+ */
+/obj/item/melee/sabre/proc/bane_effects(element_owner, mob/living/carbon/human/baned_target)
+ SIGNAL_HANDLER
+ baned_target.visible_message(
+ span_warning("[src] tears through [baned_target] with unnatural ease!"),
+ span_userdanger("As [src] tears into your body, you feel the weight of authority collapse into your wounds!"),
+ )
+ INVOKE_ASYNC(baned_target, TYPE_PROC_REF(/mob/living/carbon/human, emote), "scream")
+
+/obj/item/melee/sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
+ final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you.
+ return ..()
+
+/obj/item/melee/sabre/on_exit_storage(datum/storage/container)
+ playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE)
+
+/obj/item/melee/sabre/on_enter_storage(datum/storage/container)
+ playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE)
+
+/obj/item/melee/sabre/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is trying to cut off all [user.p_their()] limbs with [src]! it looks like [user.p_theyre()] trying to commit suicide!"))
+ var/i = 0
+ ADD_TRAIT(src, TRAIT_NODROP, SABRE_SUICIDE_TRAIT)
+ if(iscarbon(user))
+ var/mob/living/carbon/Cuser = user
+ var/obj/item/bodypart/holding_bodypart = Cuser.get_holding_bodypart_of_item(src)
+ var/list/limbs_to_dismember
+ var/list/arms = list()
+ var/list/legs = list()
+ var/obj/item/bodypart/bodypart
+
+ for(bodypart in Cuser.bodyparts)
+ if(bodypart == holding_bodypart)
+ continue
+ if(bodypart.body_part & ARMS)
+ arms += bodypart
+ else if (bodypart.body_part & LEGS)
+ legs += bodypart
+
+ limbs_to_dismember = arms + legs
+ if(holding_bodypart)
+ limbs_to_dismember += holding_bodypart
+
+ var/speedbase = abs((4 SECONDS) / limbs_to_dismember.len)
+ for(bodypart in limbs_to_dismember)
+ i++
+ addtimer(CALLBACK(src, PROC_REF(suicide_dismember), user, bodypart), speedbase * i)
+ addtimer(CALLBACK(src, PROC_REF(manual_suicide), user), (5 SECONDS) * i)
+ return MANUAL_SUICIDE
+
+/obj/item/melee/sabre/proc/suicide_dismember(mob/living/user, obj/item/bodypart/affecting)
+ if(!QDELETED(affecting) && !(affecting.bodypart_flags & BODYPART_UNREMOVABLE) && affecting.owner == user && !QDELETED(user))
+ playsound(user, hitsound, 25, TRUE)
+ affecting.dismember(BRUTE)
+ user.adjust_brute_loss(force * 1.25)
+
+/obj/item/melee/sabre/proc/manual_suicide(mob/living/user, originally_nodropped)
+ if(!QDELETED(user))
+ user.adjust_brute_loss(200)
+ user.death(FALSE)
+ REMOVE_TRAIT(src, TRAIT_NODROP, SABRE_SUICIDE_TRAIT)
+
+
+/obj/item/melee/parsnip_sabre
+ name = "parsnip sabre"
+ desc = "A weird, yet elegant weapon. Surprisingly sharp for something made from a parsnip."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "parsnip_sabre"
+ inhand_icon_state = "parsnip_sabre"
+ icon_angle = -45
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ force = 15
+ throwforce = 10
+ demolition_mod = 0.3
+ w_class = WEIGHT_CLASS_BULKY
+ block_chance = 40
+ armour_penetration = 40
+ sharpness = SHARP_EDGED
+ attack_verb_continuous = list("slashes", "cuts")
+ attack_verb_simple = list("slash", "cut")
+ block_sound = 'sound/items/weapons/parry.ogg'
+ hitsound = 'sound/items/weapons/rapierhit.ogg'
+ custom_materials = null
+ wound_bonus = 5
+ exposed_wound_bonus = 15
+
+/obj/item/melee/parsnip_sabre/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/cuffable_item) //closed sword guard
+ AddComponent(/datum/component/jousting)
+
+/obj/item/melee/parsnip_sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK || attack_type == OVERWHELMING_ATTACK)
+ final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword. Or a road roller, if one happened to hit you.
+ return ..()
+
+/obj/item/melee/parsnip_sabre/on_exit_storage(datum/storage/container)
+ . = ..()
+ playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE)
+
+/obj/item/melee/parsnip_sabre/on_enter_storage(datum/storage/container)
+ . = ..()
+ playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE)
diff --git a/code/game/objects/items/soulscythe.dm b/code/game/objects/items/weaponry/melee/soulscythe.dm
similarity index 100%
rename from code/game/objects/items/soulscythe.dm
rename to code/game/objects/items/weaponry/melee/soulscythe.dm
diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/weaponry/melee/spear.dm
similarity index 100%
rename from code/game/objects/items/spear.dm
rename to code/game/objects/items/weaponry/melee/spear.dm
diff --git a/code/game/objects/items/weaponry/melee/supermatter_sword.dm b/code/game/objects/items/weaponry/melee/supermatter_sword.dm
new file mode 100644
index 00000000000..cbfff58e9cd
--- /dev/null
+++ b/code/game/objects/items/weaponry/melee/supermatter_sword.dm
@@ -0,0 +1,115 @@
+/obj/item/melee/supermatter_sword
+ name = "supermatter sword"
+ desc = "In a station full of bad ideas, this might just be the worst."
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "supermatter_sword_balanced"
+ inhand_icon_state = "supermatter_sword"
+ icon_angle = -90
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ slot_flags = null
+ w_class = WEIGHT_CLASS_BULKY
+ force = 0.001
+ armour_penetration = 1000
+ force_string = "INFINITE"
+ item_flags = NEEDS_PERMIT|NO_BLOOD_ON_ITEM
+ custom_materials = list(/datum/material/adamantine = SHEET_MATERIAL_AMOUNT * 20, /datum/material/iron = SHEET_MATERIAL_AMOUNT)
+ var/obj/machinery/power/supermatter_crystal/shard
+ var/balanced = 1
+
+/obj/item/melee/supermatter_sword/Initialize(mapload)
+ . = ..()
+ shard = new /obj/machinery/power/supermatter_crystal(src)
+ qdel(shard.countdown)
+ shard.countdown = null
+ START_PROCESSING(SSobj, src)
+ visible_message(span_warning("[src] appears, balanced ever so perfectly on its hilt. This isn't ominous at all."))
+ RegisterSignal(src, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(eat_bullets))
+
+/obj/item/melee/supermatter_sword/process()
+ if(balanced || throwing || ismob(src.loc) || isnull(src.loc))
+ return
+ if(!isturf(src.loc))
+ var/atom/target = src.loc
+ forceMove(target.loc)
+ consume_everything(target)
+ else
+ var/turf/turf = get_turf(src)
+ if(!isspaceturf(turf))
+ consume_turf(turf)
+
+/obj/item/melee/supermatter_sword/pre_attack(atom/target, mob/living/user, list/modifiers, list/attack_modifiers)
+ . = ..()
+ if(.)
+ return .
+
+ if(target == user)
+ user.dropItemToGround(src, TRUE)
+ else
+ user.do_attack_animation(target)
+ consume_everything(target)
+ return TRUE
+
+/obj/item/melee/supermatter_sword/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ ..()
+ if(ismob(hit_atom))
+ var/mob/mob = hit_atom
+ if(src.loc == mob)
+ mob.dropItemToGround(src, TRUE)
+ consume_everything(hit_atom)
+
+/obj/item/melee/supermatter_sword/pickup(user)
+ ..()
+ balanced = 0
+ icon_state = "supermatter_sword"
+ icon_angle = -45
+
+/obj/item/melee/supermatter_sword/ex_act(severity, target)
+ visible_message(
+ span_danger("The blast wave smacks into [src] and rapidly flashes to ash."),
+ span_hear("You hear a loud crack as you are washed with a wave of heat.")
+ )
+ consume_everything()
+ return TRUE
+
+/obj/item/melee/supermatter_sword/acid_act()
+ visible_message(span_danger("The acid smacks into [src] and rapidly flashes to ash."),\
+ span_hear("You hear a loud crack as you are washed with a wave of heat."))
+ consume_everything()
+ return TRUE
+
+/obj/item/melee/supermatter_sword/proc/eat_bullets(datum/source, obj/projectile/hitting_projectile)
+ SIGNAL_HANDLER
+
+ visible_message(
+ span_danger("[hitting_projectile] smacks into [source] and rapidly flashes to ash."),
+ null,
+ span_hear("You hear a loud crack as you are washed with a wave of heat."),
+ )
+ consume_everything(hitting_projectile)
+ return COMPONENT_BULLET_BLOCKED
+
+/obj/item/melee/supermatter_sword/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] touches [src]'s blade. It looks like [user.p_theyre()] tired of waiting for the radiation to kill [user.p_them()]!"))
+ user.dropItemToGround(src, TRUE)
+ shard.Bumped(user)
+
+/obj/item/melee/supermatter_sword/proc/consume_everything(target)
+ if(isnull(target))
+ shard.Bump(target)
+ else if(!isturf(target))
+ shard.Bumped(target)
+ else
+ consume_turf(target)
+
+/obj/item/melee/supermatter_sword/proc/consume_turf(turf/turf)
+ var/oldtype = turf.type
+ var/turf/newT = turf.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
+ if(newT.type == oldtype)
+ return
+ playsound(turf, 'sound/effects/supermatter.ogg', 50, TRUE)
+ turf.visible_message(
+ span_danger("[turf] smacks into [src] and rapidly flashes to ash."),
+ span_hear("You hear a loud crack as you are washed with a wave of heat."),
+ )
+ shard.Bump(turf)
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/weaponry/ranged/flamethrower.dm
similarity index 100%
rename from code/game/objects/items/flamethrower.dm
rename to code/game/objects/items/weaponry/ranged/flamethrower.dm
diff --git a/code/game/objects/items/pneumatic_cannon.dm b/code/game/objects/items/weaponry/ranged/pneumatic_cannon.dm
similarity index 100%
rename from code/game/objects/items/pneumatic_cannon.dm
rename to code/game/objects/items/weaponry/ranged/pneumatic_cannon.dm
diff --git a/code/game/objects/items/weaponry/ranged/throwing_star.dm b/code/game/objects/items/weaponry/ranged/throwing_star.dm
new file mode 100644
index 00000000000..ec86607ab00
--- /dev/null
+++ b/code/game/objects/items/weaponry/ranged/throwing_star.dm
@@ -0,0 +1,51 @@
+/obj/item/throwing_star
+ name = "throwing star"
+ desc = "An ancient weapon still used to this day, due to its ease of lodging itself into its victim's body parts."
+ icon = 'icons/obj/weapons/thrown.dmi'
+ icon_state = "throwingstar"
+ inhand_icon_state = "eshield"
+ lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
+ force = 2
+ throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
+ throw_speed = 4
+ embed_type = /datum/embedding/throwing_star
+ armour_penetration = 40
+ mob_throw_hit_sound = 'sound/items/weapons/pierce.ogg'
+ hitsound = 'sound/items/weapons/bladeslice.ogg'
+
+ w_class = WEIGHT_CLASS_SMALL
+ sharpness = SHARP_POINTY
+ custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 5)
+ resistance_flags = FIRE_PROOF
+
+/datum/embedding/throwing_star
+ pain_mult = 4
+ embed_chance = 100
+ fall_chance = 0
+
+/obj/item/throwing_star/stamina
+ name = "shock throwing star"
+ desc = "An aerodynamic disc designed to cause excruciating pain when stuck inside fleeing targets, hopefully without causing fatal harm."
+ throwforce = 5
+ embed_type = /datum/embedding/throwing_star/stamina
+
+/datum/embedding/throwing_star/stamina
+ pain_mult = 5
+ jostle_chance = 10
+ pain_stam_pct = 0.8
+ jostle_pain_mult = 3
+
+/obj/item/throwing_star/toy
+ name = "toy throwing star"
+ desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security."
+ sharpness = NONE
+ force = 0
+ throwforce = 0
+ embed_type = /datum/embedding/throwing_star/toy
+
+/datum/embedding/throwing_star/toy
+ pain_mult = 0
+ jostle_pain_mult = 0
+
+//Ninja throwing stars are located in the ninja mod modules
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/weaponry/shields.dm
similarity index 100%
rename from code/game/objects/items/shields.dm
rename to code/game/objects/items/weaponry/shields.dm
diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm
index 0b8f2259855..0d587f2343d 100644
--- a/code/modules/antagonists/wizard/equipment/soulstone.dm
+++ b/code/modules/antagonists/wizard/equipment/soulstone.dm
@@ -614,11 +614,28 @@
/obj/item/soulstone/anybody
required_role = null
+/obj/item/ectoplasm
+ name = "ectoplasm"
+ desc = "Spooky."
+ gender = PLURAL
+ icon = 'icons/effects/magic.dmi'
+ icon_state = "ectoplasm"
+
+/obj/item/ectoplasm/grind_results()
+ return list(/datum/reagent/hauntium = 25)
+
+/obj/item/ectoplasm/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!"))
+ return OXYLOSS
+
/obj/item/soulstone/mystic
icon_state = "mystic_soulstone"
theme = THEME_WIZARD
required_role = /datum/antagonist/wizard
+/obj/item/ectoplasm/mystic
+ icon_state = "mysticplasm"
+
/obj/item/soulstone/anybody/revolver
one_use = TRUE
grab_sleeping = FALSE
@@ -627,6 +644,10 @@
icon_state = "purified_soulstone"
theme = THEME_HOLY
+/obj/item/ectoplasm/angelic
+ icon = 'icons/effects/magic.dmi'
+ icon_state = "angelplasm"
+
/obj/item/soulstone/anybody/chaplain
name = "mysterious old shard"
one_use = TRUE
diff --git a/code/game/objects/items/kitchen.dm b/code/modules/food_and_drinks/equipment/kitchen_utensils.dm
similarity index 78%
rename from code/game/objects/items/kitchen.dm
rename to code/modules/food_and_drinks/equipment/kitchen_utensils.dm
index 95412ef4088..ca5a338fa4c 100644
--- a/code/game/objects/items/kitchen.dm
+++ b/code/modules/food_and_drinks/equipment/kitchen_utensils.dm
@@ -4,6 +4,7 @@
* Kitchen knives
* Rolling Pins
* Plastic Utensils
+ * Tongs
*/
#define PLASTIC_BREAK_PROBABILITY 25
@@ -354,4 +355,107 @@
. = ..()
create_reagents(SOUP_SERVING_SIZE + 5, INJECTABLE|OPENCONTAINER)
+/// Tongs, let you pick up and feed people food from further away.
+/obj/item/kitchen/tongs
+ name = "tongs"
+ desc = "So you never have to touch anything with your dirty, unwashed hands."
+ reach = 2
+ icon_state = "tongs"
+ base_icon_state = "tongs"
+ inhand_icon_state = "fork" // close enough
+ icon_angle = -45
+ attack_verb_continuous = list("pinches", "tongs", "nips")
+ attack_verb_simple = list("pinch", "tong", "nip")
+ /// What are we holding in our tongs?
+ var/obj/item/tonged
+ /// Sound to play when we click our tongs together
+ var/clack_sound = 'sound/items/handling/component_drop.ogg'
+ /// Time to wait between clacking sounds
+ var/clack_delay = 2 SECONDS
+ /// Have we clacked recently?
+ COOLDOWN_DECLARE(clack_cooldown)
+
+/obj/item/kitchen/tongs/Destroy(force)
+ QDEL_NULL(tonged)
+ return ..()
+
+/obj/item/kitchen/tongs/examine(mob/user)
+ . = ..()
+ if (!isnull(tonged))
+ . += span_notice("It is holding [tonged].")
+
+/obj/item/kitchen/tongs/dropped(mob/user, silent)
+ . = ..()
+ drop_tonged()
+
+/obj/item/kitchen/tongs/attack_self(mob/user, modifiers)
+ . = ..()
+ if(.)
+ return TRUE
+ if (!isnull(tonged))
+ drop_tonged()
+ return TRUE
+ if (!COOLDOWN_FINISHED(src, clack_cooldown))
+ return TRUE
+ user.visible_message(span_notice("[user] clacks [user.p_their()] [name] together like a crab. Click clack!"))
+ click_clack()
+ return TRUE
+
+/// Release the food we are holding
+/obj/item/kitchen/tongs/proc/drop_tonged()
+ if (isnull(tonged))
+ return
+ visible_message(span_notice("[tonged] falls to the ground!"))
+ var/turf/location = drop_location()
+ tonged.forceMove(location)
+ tonged.do_drop_animation(location)
+
+/// Play a clacking sound and appear closed, then open again
+/obj/item/kitchen/tongs/proc/click_clack()
+ COOLDOWN_START(src, clack_cooldown, clack_delay)
+ playsound(src, clack_sound, vol = 100, vary = FALSE)
+ icon_state = "[base_icon_state]_closed"
+ var/delay = min(0.5 SECONDS, clack_delay / 2) // Just in case someone's been fucking with the cooldown
+ addtimer(CALLBACK(src, PROC_REF(clack)), delay, TIMER_DELETE_ME)
+
+/// Plays a clacking sound and appear open
+/obj/item/kitchen/tongs/proc/clack()
+ playsound(src, clack_sound, vol = 100, vary = FALSE)
+ icon_state = base_icon_state
+
+/obj/item/kitchen/tongs/Exited(atom/movable/leaving, direction)
+ . = ..()
+ if (leaving != tonged)
+ return
+ tonged = null
+ update_appearance(UPDATE_ICON)
+
+/obj/item/kitchen/tongs/pre_attack(obj/item/attacked, mob/living/user, list/modifiers, list/attack_modifiers)
+ if (!isnull(tonged) && tonged.force <= 0) // prevents tongs from giving food-weapons extra range
+ attacked.attackby(tonged, user)
+ return TRUE
+ if (isliving(attacked))
+ if (COOLDOWN_FINISHED(src, clack_cooldown))
+ click_clack()
+ return ..()
+ if (!IS_EDIBLE(attacked) || attacked.w_class > WEIGHT_CLASS_NORMAL || !isnull(tonged))
+ return ..()
+ tonged = attacked
+ attacked.do_pickup_animation(src)
+ attacked.forceMove(src)
+ update_appearance(UPDATE_ICON)
+ return TRUE
+
+/obj/item/kitchen/tongs/update_overlays()
+ . = ..()
+ if (isnull(tonged))
+ return
+ var/mutable_appearance/held_food = new /mutable_appearance(tonged.appearance)
+ held_food.layer = layer
+ held_food.plane = plane
+ held_food.transform = held_food.transform.Scale(0.7, 0.7)
+ held_food.pixel_w = 6
+ held_food.pixel_z = 6
+ . += held_food
+
#undef PLASTIC_BREAK_PROBABILITY
diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/equipment/plate.dm
similarity index 100%
rename from code/modules/food_and_drinks/plate.dm
rename to code/modules/food_and_drinks/equipment/plate.dm
diff --git a/code/game/objects/items/surgery_tray.dm b/code/modules/surgery/surgery_tray.dm
similarity index 100%
rename from code/game/objects/items/surgery_tray.dm
rename to code/modules/surgery/surgery_tray.dm
diff --git a/icons/map_icons/items/_item.dmi b/icons/map_icons/items/_item.dmi
index f4aec3e61db..f1e1a9f5f02 100644
Binary files a/icons/map_icons/items/_item.dmi and b/icons/map_icons/items/_item.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index b7cd4d5d5bb..f6fc9e6042c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2511,42 +2511,32 @@
#include "code\game\objects\items\binoculars.dm"
#include "code\game\objects\items\blueprints.dm"
#include "code\game\objects\items\body_egg.dm"
-#include "code\game\objects\items\bodybag.dm"
#include "code\game\objects\items\botpad_remote.dm"
-#include "code\game\objects\items\boxcutter.dm"
-#include "code\game\objects\items\broom.dm"
#include "code\game\objects\items\busts_and_figurines.dm"
#include "code\game\objects\items\cardboard_cutouts.dm"
#include "code\game\objects\items\cards_ids.dm"
-#include "code\game\objects\items\chainsaw.dm"
#include "code\game\objects\items\charter.dm"
#include "code\game\objects\items\choice_beacon.dm"
#include "code\game\objects\items\chromosome.dm"
#include "code\game\objects\items\cigarettes.dm"
#include "code\game\objects\items\climbingrope.dm"
#include "code\game\objects\items\clown_items.dm"
-#include "code\game\objects\items\control_wand.dm"
#include "code\game\objects\items\cosmetics.dm"
#include "code\game\objects\items\courtroom.dm"
#include "code\game\objects\items\crab17.dm"
#include "code\game\objects\items\crayons.dm"
#include "code\game\objects\items\credit_holochip.dm"
#include "code\game\objects\items\debug_items.dm"
-#include "code\game\objects\items\defib.dm"
#include "code\game\objects\items\dehy_carp.dm"
#include "code\game\objects\items\dice.dm"
#include "code\game\objects\items\dna_injector.dm"
#include "code\game\objects\items\dna_probe.dm"
#include "code\game\objects\items\door_seal.dm"
#include "code\game\objects\items\drug_items.dm"
-#include "code\game\objects\items\dualsaber.dm"
#include "code\game\objects\items\dyespray.dm"
#include "code\game\objects\items\eightball.dm"
#include "code\game\objects\items\emags.dm"
#include "code\game\objects\items\etherealdiscoball.dm"
-#include "code\game\objects\items\extinguisher.dm"
-#include "code\game\objects\items\fireaxe.dm"
-#include "code\game\objects\items\flamethrower.dm"
#include "code\game\objects\items\flatpacks.dm"
#include "code\game\objects\items\floppy_disk.dm"
#include "code\game\objects\items\forensicsspoofer.dm"
@@ -2555,15 +2545,10 @@
#include "code\game\objects\items\gun_maintenance.dm"
#include "code\game\objects\items\hand_items.dm"
#include "code\game\objects\items\handcuffs.dm"
-#include "code\game\objects\items\his_grace.dm"
#include "code\game\objects\items\holosign_creator.dm"
#include "code\game\objects\items\hot_potato.dm"
#include "code\game\objects\items\hourglass.dm"
-#include "code\game\objects\items\inducer.dm"
#include "code\game\objects\items\inspector.dm"
-#include "code\game\objects\items\janitor_key.dm"
-#include "code\game\objects\items\kitchen.dm"
-#include "code\game\objects\items\knives.dm"
#include "code\game\objects\items\latexballoon.dm"
#include "code\game\objects\items\lighter.dm"
#include "code\game\objects\items\machine_wand.dm"
@@ -2579,31 +2564,22 @@
#include "code\game\objects\items\pinpointer.dm"
#include "code\game\objects\items\pitchfork.dm"
#include "code\game\objects\items\plushes.dm"
-#include "code\game\objects\items\pneumatic_cannon.dm"
-#include "code\game\objects\items\powerfist.dm"
#include "code\game\objects\items\puzzle_pieces.dm"
-#include "code\game\objects\items\reflex_hammer.dm"
#include "code\game\objects\items\religion.dm"
#include "code\game\objects\items\rollertable_dock.dm"
#include "code\game\objects\items\scrolls.dm"
#include "code\game\objects\items\secret_documents.dm"
#include "code\game\objects\items\sharpener.dm"
-#include "code\game\objects\items\shields.dm"
#include "code\game\objects\items\shooting_range.dm"
#include "code\game\objects\items\shrapnel.dm"
#include "code\game\objects\items\signs.dm"
#include "code\game\objects\items\skateboards.dm"
#include "code\game\objects\items\skub.dm"
-#include "code\game\objects\items\soulscythe.dm"
-#include "code\game\objects\items\spear.dm"
#include "code\game\objects\items\stickers.dm"
-#include "code\game\objects\items\surgery_tray.dm"
#include "code\game\objects\items\syndie_spraycan.dm"
#include "code\game\objects\items\tail_pin.dm"
#include "code\game\objects\items\taster.dm"
#include "code\game\objects\items\teleportation.dm"
-#include "code\game\objects\items\theft_tools.dm"
-#include "code\game\objects\items\tongs.dm"
#include "code\game\objects\items\toy_mechs.dm"
#include "code\game\objects\items\toys.dm"
#include "code\game\objects\items\trash.dm"
@@ -2611,7 +2587,6 @@
#include "code\game\objects\items\vending_items.dm"
#include "code\game\objects\items\virgin_mary.dm"
#include "code\game\objects\items\wall_mounted.dm"
-#include "code\game\objects\items\weaponry.dm"
#include "code\game\objects\items\wiki_manuals.dm"
#include "code\game\objects\items\wind_turbine.dm"
#include "code\game\objects\items\AI_modules\_AI_modules.dm"
@@ -2777,10 +2752,6 @@
#include "code\game\objects\items\kirby_plants\kirbyplants.dm"
#include "code\game\objects\items\kirby_plants\organic_plants.dm"
#include "code\game\objects\items\kirby_plants\synthetic_plants.dm"
-#include "code\game\objects\items\melee\baton.dm"
-#include "code\game\objects\items\melee\chainofcommand.dm"
-#include "code\game\objects\items\melee\energy.dm"
-#include "code\game\objects\items\melee\misc.dm"
#include "code\game\objects\items\rcd\RCD.dm"
#include "code\game\objects\items\rcd\RCL.dm"
#include "code\game\objects\items\rcd\RHD.dm"
@@ -2871,16 +2842,48 @@
#include "code\game\objects\items\tanks\watertank.dm"
#include "code\game\objects\items\tcg\tcg.dm"
#include "code\game\objects\items\tcg\tcg_machines.dm"
-#include "code\game\objects\items\tools\crowbar.dm"
-#include "code\game\objects\items\tools\screwdriver.dm"
+#include "code\game\objects\items\tools\control_wand.dm"
+#include "code\game\objects\items\tools\extinguisher.dm"
+#include "code\game\objects\items\tools\inducer.dm"
#include "code\game\objects\items\tools\spess_knife.dm"
-#include "code\game\objects\items\tools\weldingtool.dm"
-#include "code\game\objects\items\tools\wirebrush.dm"
-#include "code\game\objects\items\tools\wirecutters.dm"
-#include "code\game\objects\items\tools\wrench.dm"
-#include "code\game\objects\items\tools\painter\airlock_painter.dm"
-#include "code\game\objects\items\tools\painter\decal_painter.dm"
-#include "code\game\objects\items\tools\painter\paintable_decals.dm"
+#include "code\game\objects\items\tools\theft_tools.dm"
+#include "code\game\objects\items\tools\engineering\crowbar.dm"
+#include "code\game\objects\items\tools\engineering\screwdriver.dm"
+#include "code\game\objects\items\tools\engineering\weldingtool.dm"
+#include "code\game\objects\items\tools\engineering\wirebrush.dm"
+#include "code\game\objects\items\tools\engineering\wirecutters.dm"
+#include "code\game\objects\items\tools\engineering\wrench.dm"
+#include "code\game\objects\items\tools\engineering\painter\airlock_painter.dm"
+#include "code\game\objects\items\tools\engineering\painter\decal_painter.dm"
+#include "code\game\objects\items\tools\engineering\painter\paintable_decals.dm"
+#include "code\game\objects\items\tools\janitorial\broom.dm"
+#include "code\game\objects\items\tools\janitorial\janitor_key.dm"
+#include "code\game\objects\items\tools\medical\bodybag.dm"
+#include "code\game\objects\items\tools\medical\cane.dm"
+#include "code\game\objects\items\tools\medical\defib.dm"
+#include "code\game\objects\items\tools\medical\reflex_hammer.dm"
+#include "code\game\objects\items\weaponry\shields.dm"
+#include "code\game\objects\items\weaponry\melee\baseball_bat.dm"
+#include "code\game\objects\items\weaponry\melee\baton.dm"
+#include "code\game\objects\items\weaponry\melee\chainofcommand.dm"
+#include "code\game\objects\items\weaponry\melee\chainsaw.dm"
+#include "code\game\objects\items\weaponry\melee\claymore.dm"
+#include "code\game\objects\items\weaponry\melee\dualsaber.dm"
+#include "code\game\objects\items\weaponry\melee\energy.dm"
+#include "code\game\objects\items\weaponry\melee\fireaxe.dm"
+#include "code\game\objects\items\weaponry\melee\high_frequency_blade.dm"
+#include "code\game\objects\items\weaponry\melee\his_grace.dm"
+#include "code\game\objects\items\weaponry\melee\katana.dm"
+#include "code\game\objects\items\weaponry\melee\knives.dm"
+#include "code\game\objects\items\weaponry\melee\misc.dm"
+#include "code\game\objects\items\weaponry\melee\powerfist.dm"
+#include "code\game\objects\items\weaponry\melee\sabre.dm"
+#include "code\game\objects\items\weaponry\melee\soulscythe.dm"
+#include "code\game\objects\items\weaponry\melee\spear.dm"
+#include "code\game\objects\items\weaponry\melee\supermatter_sword.dm"
+#include "code\game\objects\items\weaponry\ranged\flamethrower.dm"
+#include "code\game\objects\items\weaponry\ranged\pneumatic_cannon.dm"
+#include "code\game\objects\items\weaponry\ranged\throwing_star.dm"
#include "code\game\objects\structures\aliens.dm"
#include "code\game\objects\structures\bedsheet_bin.dm"
#include "code\game\objects\structures\billboard.dm"
@@ -4433,7 +4436,8 @@
#include "code\modules\fishing\sources\subtypes\turfs.dm"
#include "code\modules\flufftext\dreaming.dm"
#include "code\modules\food_and_drinks\pizzabox.dm"
-#include "code\modules\food_and_drinks\plate.dm"
+#include "code\modules\food_and_drinks\equipment\kitchen_utensils.dm"
+#include "code\modules\food_and_drinks\equipment\plate.dm"
#include "code\modules\food_and_drinks\machinery\coffeemaker.dm"
#include "code\modules\food_and_drinks\machinery\deep_fryer.dm"
#include "code\modules\food_and_drinks\machinery\food_cart.dm"
@@ -6351,6 +6355,7 @@
#include "code\modules\station_goals\vault_mutation.dm"
#include "code\modules\surgery\surgery_disks.dm"
#include "code\modules\surgery\surgery_tools.dm"
+#include "code\modules\surgery\surgery_tray.dm"
#include "code\modules\surgery\bodyparts\_bodyparts.dm"
#include "code\modules\surgery\bodyparts\bodypart_effects.dm"
#include "code\modules\surgery\bodyparts\dismemberment.dm"