diff --git a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm
index 09658a8b869..ad75f7c046f 100644
--- a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm
+++ b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm
@@ -514,7 +514,7 @@
/obj/structure/closet/crate/secure/gear{
req_one_access_txt = "150"
},
-/obj/item/melee/transforming/energy/sword/saber/red,
+/obj/item/melee/energy/sword/saber/red,
/obj/machinery/light/directional/north,
/turf/open/floor/pod/dark,
/area/ruin/space/has_grav/powered/syndicate_forgotten_vault)
diff --git a/_maps/RandomZLevels/spacebattle.dmm b/_maps/RandomZLevels/spacebattle.dmm
index f5a5cb88306..8fb1d3dc2ca 100644
--- a/_maps/RandomZLevels/spacebattle.dmm
+++ b/_maps/RandomZLevels/spacebattle.dmm
@@ -291,7 +291,7 @@
/area/awaymission/spacebattle/syndicate3)
"bt" = (
/obj/structure/table/reinforced,
-/obj/item/melee/transforming/energy/sword/saber/red,
+/obj/item/melee/energy/sword/saber/red,
/turf/open/floor/mineral/plastitanium/red,
/area/awaymission/spacebattle/syndicate1)
"bu" = (
@@ -1152,7 +1152,7 @@
/area/awaymission/spacebattle/cruiser)
"eW" = (
/obj/effect/mob_spawn/human/syndicatesoldier,
-/obj/item/melee/transforming/energy/sword/saber/red,
+/obj/item/melee/energy/sword/saber/red,
/obj/effect/decal/cleanable/blood,
/turf/open/floor/iron,
/area/awaymission/spacebattle/cruiser)
diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm
index adaecc5ce3e..402da938ea9 100644
--- a/_maps/map_files/debug/runtimestation.dmm
+++ b/_maps/map_files/debug/runtimestation.dmm
@@ -2036,7 +2036,7 @@
/area/engineering/atmos)
"jU" = (
/obj/structure/table,
-/obj/item/melee/transforming/energy/axe,
+/obj/item/melee/energy/axe,
/turf/open/floor/iron,
/area/commons/storage/primary)
"kj" = (
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index a5b6b21a4cc..987d85b3a18 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -112,7 +112,7 @@
/obj/item/clothing/suit/armor/tdome/red,
/obj/item/clothing/head/helmet/thunderdome,
/obj/item/melee/baton/loaded,
-/obj/item/melee/transforming/energy/sword/saber/red,
+/obj/item/melee/energy/sword/saber/red,
/obj/effect/turf_decal/stripes/line{
dir = 4
},
@@ -183,7 +183,7 @@
/obj/item/clothing/suit/armor/tdome/green,
/obj/item/clothing/head/helmet/thunderdome,
/obj/item/melee/baton/loaded,
-/obj/item/melee/transforming/energy/sword/saber/green,
+/obj/item/melee/energy/sword/saber/green,
/obj/effect/turf_decal/stripes/line{
dir = 8
},
@@ -12152,7 +12152,7 @@
/obj/item/clothing/suit/armor/tdome/red,
/obj/item/clothing/head/helmet/thunderdome,
/obj/item/melee/baton/loaded,
-/obj/item/melee/transforming/energy/sword/saber/red,
+/obj/item/melee/energy/sword/saber/red,
/obj/effect/turf_decal/stripes/line{
dir = 4
},
@@ -12276,7 +12276,7 @@
/obj/item/clothing/suit/armor/tdome/green,
/obj/item/clothing/head/helmet/thunderdome,
/obj/item/melee/baton/loaded,
-/obj/item/melee/transforming/energy/sword/saber/green,
+/obj/item/melee/energy/sword/saber/green,
/obj/effect/turf_decal/stripes/line{
dir = 8
},
diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm
index 3a9695a20d6..7b0728ecbb3 100644
--- a/_maps/shuttles/pirate_default.dmm
+++ b/_maps/shuttles/pirate_default.dmm
@@ -597,15 +597,15 @@
/obj/machinery/firealarm/directional/north,
/obj/effect/decal/cleanable/dirt,
/obj/structure/table,
-/obj/item/melee/transforming/energy/sword/pirate{
+/obj/item/melee/energy/sword/pirate{
pixel_x = -1;
pixel_y = 6
},
-/obj/item/melee/transforming/energy/sword/pirate{
+/obj/item/melee/energy/sword/pirate{
pixel_x = 6;
pixel_y = 6
},
-/obj/item/melee/transforming/energy/sword/pirate{
+/obj/item/melee/energy/sword/pirate{
pixel_x = 13;
pixel_y = 6
},
diff --git a/_maps/shuttles/pirate_silverscale.dmm b/_maps/shuttles/pirate_silverscale.dmm
index dc387cfcab6..009219c409e 100644
--- a/_maps/shuttles/pirate_silverscale.dmm
+++ b/_maps/shuttles/pirate_silverscale.dmm
@@ -358,14 +358,14 @@
dir = 8;
layer = 2.9
},
-/obj/item/melee/transforming/energy/sword/saber/purple{
+/obj/item/melee/energy/sword/saber/purple{
pixel_y = 12
},
-/obj/item/melee/transforming/energy/sword/saber/purple{
+/obj/item/melee/energy/sword/saber/purple{
pixel_x = 8;
pixel_y = 7
},
-/obj/item/melee/transforming/energy/sword/saber/purple{
+/obj/item/melee/energy/sword/saber/purple{
pixel_x = 17
},
/turf/open/floor/pod/dark,
diff --git a/_maps/templates/holodeck_thunderdome.dmm b/_maps/templates/holodeck_thunderdome.dmm
index e9b1eb5167a..a1ff05d6203 100644
--- a/_maps/templates/holodeck_thunderdome.dmm
+++ b/_maps/templates/holodeck_thunderdome.dmm
@@ -14,7 +14,7 @@
/obj/item/clothing/head/helmet/thunderdome/holosuit,
/obj/item/clothing/suit/armor/tdome/holosuit/green,
/obj/item/clothing/under/color/green,
-/obj/item/holo/esword/green,
+/obj/item/melee/energy/sword/holographic/green,
/turf/open/floor/holofloor/basalt,
/area/template_noop)
"q" = (
@@ -22,7 +22,7 @@
/obj/item/clothing/head/helmet/thunderdome/holosuit,
/obj/item/clothing/suit/armor/tdome/holosuit/red,
/obj/item/clothing/under/color/red,
-/obj/item/holo/esword/red,
+/obj/item/melee/energy/sword/holographic/red,
/turf/open/floor/holofloor/basalt,
/area/template_noop)
"x" = (
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 542f7272ec1..2b420439649 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -1177,6 +1177,17 @@
#define COMSIG_SWAB_FOR_SAMPLES "swab_for_samples" ///Called when you try to swab something using the swabable component, includes a mutable list of what has been swabbed so far so it can be modified.
#define COMPONENT_SWAB_FOUND (1<<0)
+// /datum/component/transforming signals
+
+/// From /datum/component/transforming/proc/on_attack_self(obj/item/source, mob/user): (obj/item/source, mob/user, active)
+#define COMSIG_TRANSFORMING_PRE_TRANSFORM "transforming_pre_transform"
+ /// Return COMPONENT_BLOCK_TRANSFORM to prevent the item from transforming.
+ #define COMPONENT_BLOCK_TRANSFORM (1<<0)
+/// From /datum/component/transforming/proc/do_transform(obj/item/source, mob/user): (obj/item/source, mob/user, active)
+#define COMSIG_TRANSFORMING_ON_TRANSFORM "transforming_on_transform"
+ /// Return COMPONENT_NO_DEFAULT_MESSAGE to prevent the transforming component from displaying the default transform message / sound.
+ #define COMPONENT_NO_DEFAULT_MESSAGE (1<<0)
+
// /datum/component/two_handed signals
///from base of datum/component/two_handed/proc/wield(mob/living/carbon/user): (/mob/user)
diff --git a/code/datums/components/transforming.dm b/code/datums/components/transforming.dm
new file mode 100644
index 00000000000..60adbd56b3b
--- /dev/null
+++ b/code/datums/components/transforming.dm
@@ -0,0 +1,253 @@
+/*
+ * Transforming weapon component. For weapons that swap between states.
+ * For example: Energy swords, cleaving saws, switch blades.
+ *
+ * Used to easily make an item that can be attack_self'd to gain force or change mode.
+ *
+ * Only values passed on initialize will update when the item is activated (except the icon_state).
+ * The icon_state of the item will swap between "[icon_state]" and "[icon_state]_on".
+ */
+/datum/component/transforming
+ /// Whether the weapon is transformed
+ var/active = FALSE
+ /// Cooldown on transforming this item back and forth
+ var/transform_cooldown_time
+ /// Force of the weapon when active
+ var/force_on
+ /// Throwforce of the weapon when active
+ var/throwforce_on
+ /// Throw speed of the weapon when active
+ var/throw_speed_on
+ /// Weight class of the weapon when active
+ var/w_class_on
+ /// The sharpness of the weapon when active
+ var/sharpness_on
+ /// Hitsound played when active
+ var/hitsound_on
+ /// List of the original continuous attack verbs the item has.
+ var/list/attack_verb_continuous_off
+ /// List of the original simple attack verbs the item has.
+ var/list/attack_verb_simple_off
+ /// List of continuous attack verbs used when the weapon is enabled
+ var/list/attack_verb_continuous_on
+ /// List of simple attack verbs used when the weapon is enabled
+ var/list/attack_verb_simple_on
+ /// Whether clumsy people need to succeed an RNG check to turn it on without hurting themselves
+ var/clumsy_check
+ /// If we get sharpened with a whetstone, save the bonus here for later use if we un/redeploy
+ var/sharpened_bonus = 0
+ /// Cooldown in between transforms
+ COOLDOWN_DECLARE(transform_cooldown)
+
+/datum/component/transforming/Initialize(
+ start_transformed = FALSE,
+ transform_cooldown_time = 0 SECONDS,
+ force_on = 0,
+ throwforce_on = 0,
+ throw_speed_on = 2,
+ sharpness_on = NONE,
+ hitsound_on = 'sound/weapons/blade1.ogg',
+ w_class_on = WEIGHT_CLASS_BULKY,
+ clumsy_check = TRUE,
+ list/attack_verb_continuous_on,
+ list/attack_verb_simple_on,
+ )
+
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ var/obj/item/item_parent = parent
+
+ src.transform_cooldown_time = transform_cooldown_time
+ src.force_on = force_on
+ src.throwforce_on = throwforce_on
+ src.throw_speed_on = throw_speed_on
+ src.sharpness_on = sharpness_on
+ src.hitsound_on = hitsound_on
+ src.w_class_on = w_class_on
+ src.clumsy_check = clumsy_check
+
+ if(attack_verb_continuous_on)
+ src.attack_verb_continuous_on = attack_verb_continuous_on
+ attack_verb_continuous_off = item_parent.attack_verb_continuous
+ if(attack_verb_simple_on)
+ src.attack_verb_simple_on = attack_verb_simple_on
+ attack_verb_simple_off = item_parent.attack_verb_simple
+
+ if(start_transformed)
+ toggle_active(parent)
+
+/datum/component/transforming/RegisterWithParent()
+ var/obj/item/item_parent = parent
+
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_self)
+ if(item_parent.sharpness || sharpness_on)
+ RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, .proc/on_sharpen)
+
+/datum/component/transforming/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK_SELF, COMSIG_ITEM_SHARPEN_ACT))
+
+/*
+ * Called on [COMSIG_ITEM_ATTACK_SELF].
+ *
+ * Check if we can transform our weapon, and if so, call [do_transform].
+ * Sends signal [COMSIG_TRANSFORMING_PRE_TRANSFORM], and stops the transform action if it returns [COMPONENT_BLOCK_TRANSFORM].
+ * And, if [do_transform] was successful, do a clumsy effect from [clumsy_transform_effect].
+ *
+ * source - source of the signal, the item being transformed / parent
+ * user - the mob transforming the weapon
+ */
+/datum/component/transforming/proc/on_attack_self(obj/item/source, mob/user)
+ SIGNAL_HANDLER
+
+ if(!COOLDOWN_FINISHED(src, transform_cooldown))
+ to_chat(user, span_warning("Wait a bit before trying to use [source] again!"))
+ return
+
+ if(SEND_SIGNAL(source, COMSIG_TRANSFORMING_PRE_TRANSFORM, user, active) & COMPONENT_BLOCK_TRANSFORM)
+ return
+
+ if(do_transform(source, user))
+ clumsy_transform_effect(user)
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
+
+/*
+ * Transform the weapon into its alternate form, calling [toggle_active].
+ *
+ * Sends signal [COMSIG_TRANSFORMING_ON_TRANSFORM], and calls [default_transform_message] if it does not return [COMPONENT_NO_DEFAULT_MESSAGE].
+ * Also starts the [transform_cooldown] if we have a set [transform_cooldown_time].
+ *
+ * source - the item being transformed / parent
+ * user - the mob transforming the item
+ *
+ * returns TRUE.
+ */
+/datum/component/transforming/proc/do_transform(obj/item/source, mob/user)
+ toggle_active(source)
+ if(!(SEND_SIGNAL(source, COMSIG_TRANSFORMING_ON_TRANSFORM, user, active) & COMPONENT_NO_DEFAULT_MESSAGE))
+ default_transform_message(source, user)
+
+ if(isnum(transform_cooldown_time))
+ COOLDOWN_START(src, transform_cooldown, transform_cooldown_time)
+ if(user)
+ source.add_fingerprint(user)
+ return TRUE
+
+/*
+ * The default feedback message and sound effect for an item transforming.
+ *
+ * source - the item being transformed / parent
+ * user - the mob transforming the item
+ */
+/datum/component/transforming/proc/default_transform_message(obj/item/source, mob/user)
+ source.balloon_alert(user, "[active ? "enabled" : "disabled"] [source]")
+ playsound(user ? user : source.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
+
+/*
+ * Toggle active between true and false, and call
+ * either set_active or set_inactive depending on whichever state is toggled.
+ *
+ * source - the item being transformed / parent
+ */
+/datum/component/transforming/proc/toggle_active(obj/item/source)
+ active = !active
+ if(active)
+ set_active(source)
+ else
+ set_inactive(source)
+
+/*
+ * Set our transformed item into its active state.
+ * Updates all the values that were passed from init and the icon_state.
+ *
+ * source - the item being transformed / parent
+ */
+/datum/component/transforming/proc/set_active(obj/item/source)
+ if(sharpness_on)
+ source.sharpness = sharpness_on
+ if(force_on)
+ source.force = force_on + (source.sharpness ? sharpened_bonus : 0)
+ if(throwforce_on)
+ source.throwforce = throwforce_on + (source.sharpness ? sharpened_bonus : 0)
+ if(throw_speed_on)
+ source.throw_speed = throw_speed_on
+
+ if(LAZYLEN(attack_verb_continuous_on))
+ source.attack_verb_continuous = attack_verb_continuous_on
+ if(LAZYLEN(attack_verb_simple_on))
+ source.attack_verb_simple = attack_verb_simple_on
+
+ source.hitsound = hitsound_on
+ source.w_class = w_class_on
+ source.icon_state = "[source.icon_state]_on"
+
+/*
+ * Set our transformed item into its inactive state.
+ * Updates all the values back to the item's initial values.
+ *
+ * source - the item being un-transformed / parent
+ */
+/datum/component/transforming/proc/set_inactive(obj/item/source)
+ if(sharpness_on)
+ source.sharpness = initial(source.sharpness)
+ if(force_on)
+ source.force = initial(source.force) + (source.sharpness ? sharpened_bonus : 0)
+ if(throwforce_on)
+ source.throwforce = initial(source.throwforce) + (source.sharpness ? sharpened_bonus : 0)
+ if(throw_speed_on)
+ source.throw_speed = initial(source.throw_speed)
+
+ if(LAZYLEN(attack_verb_continuous_on))
+ source.attack_verb_continuous = attack_verb_continuous_off
+ if(LAZYLEN(attack_verb_simple_off))
+ source.attack_verb_simple = attack_verb_simple_off
+
+ source.hitsound = initial(source.hitsound)
+ source.w_class = initial(source.w_class)
+ source.icon_state = initial(source.icon_state)
+
+/*
+ * If [clumsy_check] is set to TRUE, attempt to cause a side effect for clumsy people activating this item.
+ * Called after the transform is done, meaning [active] var has already updated.
+ *
+ * user - the clumsy mob, transforming our item (parent)
+ *
+ * Returns TRUE if side effects happened, FALSE otherwise
+ */
+/datum/component/transforming/proc/clumsy_transform_effect(mob/living/user)
+ if(!clumsy_check)
+ return FALSE
+
+ if(!HAS_TRAIT(user, TRAIT_CLUMSY))
+ return FALSE
+
+ if(active && prob(50))
+ var/hurt_self_verb_simple = LAZYLEN(attack_verb_simple_on) ? pick(attack_verb_simple_on) : "hit"
+ var/hurt_self_verb_continuous = LAZYLEN(attack_verb_continuous_on) ? pick(attack_verb_continuous_on) : "hits"
+ user.visible_message(
+ span_warning("[user] triggers [parent] while holding it backwards and [hurt_self_verb_continuous] themself, like a doofus!"),
+ span_warning("You trigger [parent] while holding it backwards and [hurt_self_verb_simple] yourself, like a doofus!")
+ )
+ user.take_bodypart_damage(10)
+ return TRUE
+ return FALSE
+
+/*
+ * Called on [COMSIG_ITEM_SHARPEN_ACT].
+ * We need to track our sharpened bonus here, so we correctly apply and unapply it
+ * if our item's sharpness state changes from transforming.
+ *
+ * source - the item being sharpened / parent
+ * increment - the amount of force added
+ * max - the maximum force that the item can be adjusted to.
+ *
+ * Does not return naturally [COMPONENT_BLOCK_SHARPEN_APPLIED] as this is only to track our sharpened bonus between transformation.
+ */
+/datum/component/transforming/proc/on_sharpen(obj/item/source, increment, max)
+ SIGNAL_HANDLER
+
+ if(sharpened_bonus)
+ return COMPONENT_BLOCK_SHARPEN_ALREADY
+ if(force_on + increment > max)
+ return COMPONENT_BLOCK_SHARPEN_MAXED
+ sharpened_bonus = increment
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index 3177df30987..19f71773335 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -160,7 +160,7 @@
return 1
/obj/item/dualsaber/ignition_effect(atom/A, mob/user)
- // same as /obj/item/melee/transforming/energy, mostly
+ // same as /obj/item/melee/energy, mostly
if(!wielded)
return ""
var/in_mouth = ""
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 81ca7b24873..bce11c884a1 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -1,57 +1,74 @@
-/obj/item/melee/transforming/energy
+/obj/item/melee/energy
icon = 'icons/obj/transforming_energy.dmi'
- hitsound_on = 'sound/weapons/blade1.ogg'
- heat = 3500
max_integrity = 200
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 30)
+ attack_verb_continuous = list("hits", "taps", "pokes")
+ attack_verb_simple = list("hit", "tap", "poke")
resistance_flags = FIRE_PROOF
light_system = MOVABLE_LIGHT
light_range = 3
light_power = 1
light_on = FALSE
- var/sword_color
+ bare_wound_bonus = 20
+ stealthy_audio = TRUE
+ w_class = WEIGHT_CLASS_SMALL
-/obj/item/melee/transforming/energy/Initialize()
+ /// The color of this energy based sword, for use in editing the icon_state.
+ var/sword_color_icon
+ /// Whether our blade is active or not.
+ var/blade_active = FALSE
+ /// Force while active.
+ var/active_force = 30
+ /// Throwforce while active.
+ var/active_throwforce = 20
+ /// Sharpness while active.
+ var/active_sharpness = SHARP_EDGED
+ /// Hitsound played attacking while active.
+ var/active_hitsound = 'sound/weapons/blade1.ogg'
+ /// Weight class while active.
+ var/active_w_class = WEIGHT_CLASS_BULKY
+ /// The heat given off when active.
+ var/active_heat = 3500
+
+/obj/item/melee/energy/Initialize()
. = ..()
- if(active)
- START_PROCESSING(SSobj, src)
+ make_transformable()
+ AddComponent(/datum/component/butchering, _speed = 5 SECONDS, _butcher_sound = active_hitsound)
-/obj/item/melee/transforming/energy/Destroy()
+/obj/item/melee/energy/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
-/obj/item/melee/transforming/energy/suicide_act(mob/user)
- if(!active)
- transform_weapon(user, TRUE)
+/*
+ * Gives our item the transforming component, passing in our various vars.
+ */
+/obj/item/melee/energy/proc/make_transformable()
+ AddComponent(/datum/component/transforming, \
+ force_on = active_force, \
+ throwforce_on = active_throwforce, \
+ throw_speed_on = 4, \
+ sharpness_on = active_sharpness, \
+ hitsound_on = active_hitsound, \
+ w_class_on = active_w_class, \
+ attack_verb_continuous_on = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts"), \
+ attack_verb_simple_on = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut"))
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/obj/item/melee/energy/suicide_act(mob/user)
+ if(!blade_active)
+ attack_self(user)
user.visible_message(span_suicide("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku!"))
return (BRUTELOSS|FIRELOSS)
-/obj/item/melee/transforming/energy/add_blood_DNA(list/blood_dna)
+/obj/item/melee/energy/add_blood_DNA(list/blood_dna)
return FALSE
-/obj/item/melee/transforming/energy/get_sharpness()
- return active * sharpness
+/obj/item/melee/energy/process(delta_time)
+ if(heat)
+ open_flame()
-/obj/item/melee/transforming/energy/process()
- open_flame()
-
-/obj/item/melee/transforming/energy/transform_weapon(mob/living/user, supress_message_text)
- . = ..()
- if(.)
- if(active)
- if(sword_color)
- icon_state = "sword[sword_color]"
- START_PROCESSING(SSobj, src)
- else
- STOP_PROCESSING(SSobj, src)
- set_light_on(active)
-
-
-/obj/item/melee/transforming/energy/get_temperature()
- return active * heat
-
-/obj/item/melee/transforming/energy/ignition_effect(atom/A, mob/user)
- if(!active)
+/obj/item/melee/energy/ignition_effect(atom/A, mob/user)
+ if(!heat && !blade_active)
return ""
var/in_mouth = ""
@@ -63,180 +80,234 @@
playsound(loc, hitsound, get_clamped_volume(), TRUE, -1)
add_fingerprint(user)
-/obj/item/melee/transforming/energy/axe
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Updates our icon to have the correct color,
+ * updates the amount of heat our item gives out,
+ * enables / disables embedding, and
+ * starts / stops processing.
+ *
+ * Also gives feedback to the user and activates or deactives the glow.
+ */
+/obj/item/melee/energy/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ blade_active = active
+ if(active)
+ if(sword_color_icon)
+ icon_state = "[icon_state]_[sword_color_icon]"
+ if(embedding)
+ updateEmbedding()
+ heat = active_heat
+ START_PROCESSING(SSobj, src)
+ else
+ if(embedding)
+ disableEmbedding()
+ heat = initial(heat)
+ STOP_PROCESSING(SSobj, src)
+
+ balloon_alert(user, "[name] [active ? "enabled":"disabled"]")
+ playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE)
+ set_light_on(active)
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
+/// Energy axe - extremely strong.
+/obj/item/melee/energy/axe
name = "energy axe"
desc = "An energized battle axe."
- icon_state = "axe0"
+ icon_state = "axe"
lefthand_file = 'icons/mob/inhands/weapons/axes_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/axes_righthand.dmi'
- force = 40
- force_on = 150
- throwforce = 25
- throwforce_on = 30
hitsound = 'sound/weapons/bladeslice.ogg'
+ attack_verb_continuous = list("attacks", "chops", "cleaves", "tears", "lacerates", "cuts")
+ attack_verb_simple = list("attack", "chop", "cleave", "tear", "lacerate", "cut")
+ force = 40
+ throwforce = 25
throw_speed = 3
throw_range = 5
- w_class = WEIGHT_CLASS_NORMAL
- w_class_on = WEIGHT_CLASS_HUGE
- flags_1 = CONDUCT_1
armour_penetration = 100
- attack_verb_off = list("attacks", "chops", "cleaves", "tears", "lacerates", "cuts")
- attack_verb_on = list()
+ sharpness = SHARP_EDGED
+ w_class = WEIGHT_CLASS_NORMAL
+ flags_1 = CONDUCT_1
light_color = LIGHT_COLOR_LIGHT_CYAN
-/obj/item/melee/transforming/energy/axe/suicide_act(mob/user)
+ active_force = 150
+ active_throwforce = 30
+ active_w_class = WEIGHT_CLASS_HUGE
+
+/obj/item/melee/energy/axe/make_transformable()
+ AddComponent(/datum/component/transforming, \
+ force_on = active_force, \
+ throwforce_on = active_throwforce, \
+ throw_speed_on = throw_speed, \
+ sharpness_on = sharpness, \
+ w_class_on = active_w_class)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/obj/item/melee/energy/axe/suicide_act(mob/user)
user.visible_message(span_suicide("[user] swings [src] towards [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!"))
return (BRUTELOSS|FIRELOSS)
-/obj/item/melee/transforming/energy/sword
+/// Energy swords.
+/obj/item/melee/energy/sword
name = "energy sword"
desc = "May the force be within you."
- icon_state = "sword0"
+ icon_state = "e_sword"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ hitsound = "swing_hit"
force = 3
throwforce = 5
- hitsound = "swing_hit" //it starts deactivated
- attack_verb_off = list("taps", "pokes")
throw_speed = 3
throw_range = 5
- sharpness = SHARP_EDGED
- embedding = list("embed_chance" = 75, "impact_pain_mult" = 10)
armour_penetration = 35
block_chance = 50
+ embedding = list("embed_chance" = 75, "impact_pain_mult" = 10)
-/obj/item/melee/transforming/energy/sword/transform_weapon(mob/living/user, supress_message_text)
- . = ..()
- if(. && active && sword_color)
- icon_state = "sword[sword_color]"
-
-/obj/item/melee/transforming/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- if(active)
+/obj/item/melee/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ if(blade_active)
return ..()
- return 0
+ return FALSE
-/obj/item/melee/transforming/energy/sword/cyborg
- sword_color = "red"
+/obj/item/melee/energy/sword/cyborg
+ name = "cyborg energy sword"
+ sword_color_icon = "red"
+ /// The cell cost of hitting something.
var/hitcost = 50
-/obj/item/melee/transforming/energy/sword/cyborg/attack(mob/M, mob/living/silicon/robot/R)
- if(R.cell)
- var/obj/item/stock_parts/cell/C = R.cell
- if(active && !(C.use(hitcost)))
- attack_self(R)
- to_chat(R, span_notice("It's out of charge!"))
- return
- return ..()
+/obj/item/melee/energy/sword/cyborg/attack(mob/target, mob/living/silicon/robot/user)
+ if(!user.cell)
+ return
-/obj/item/melee/transforming/energy/sword/cyborg/saw //Used by medical Syndicate cyborgs
+ var/obj/item/stock_parts/cell/our_cell = user.cell
+ if(blade_active && !(our_cell.use(hitcost)))
+ attack_self(user)
+ to_chat(user, span_notice("It's out of charge!"))
+ return
+ return ..()
+
+/obj/item/melee/energy/sword/cyborg/cyborg_unequip(mob/user)
+ if(!blade_active)
+ return
+ attack_self(user)
+
+/obj/item/melee/energy/sword/cyborg/saw //Used by medical Syndicate cyborgs
name = "energy saw"
desc = "For heavy duty cutting. It has a carbon-fiber blade in addition to a toggleable hard-light edge to dramatically increase sharpness."
- force_on = 30
- force = 18 //About as much as a spear
- hitsound = 'sound/weapons/circsawhit.ogg'
icon = 'icons/obj/surgery.dmi'
- icon_state = "esaw_0"
- icon_state_on = "esaw_1"
- sword_color = null //stops icon from breaking when turned on.
- hitcost = 75 //Costs more than a standard cyborg esword
+ icon_state = "esaw"
+ hitsound = 'sound/weapons/circsawhit.ogg'
+ force = 18
+ hitcost = 75 // Costs more than a standard cyborg esword.
w_class = WEIGHT_CLASS_NORMAL
sharpness = SHARP_EDGED
light_color = LIGHT_COLOR_LIGHT_CYAN
tool_behaviour = TOOL_SAW
- toolspeed = 0.7 //faster as a saw
+ toolspeed = 0.7 // Faster than a normal saw.
-/obj/item/melee/transforming/energy/sword/cyborg/saw/cyborg_unequip(mob/user)
- if(!active)
- return
- transform_weapon(user, TRUE)
+ active_force = 30
+ sword_color_icon = null // Stops icon from breaking when turned on.
-/obj/item/melee/transforming/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- return 0
+/obj/item/melee/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ return FALSE
-/obj/item/melee/transforming/energy/sword/saber
- var/list/possible_colors = list("red" = COLOR_SOFT_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
+// The colored energy swords we all know and love.
+/obj/item/melee/energy/sword/saber
+ /// Assoc list of all possible saber colors to color define.
+ var/list/possible_colors = list(
+ "red" = COLOR_SOFT_RED,
+ "blue" = LIGHT_COLOR_LIGHT_CYAN,
+ "green" = LIGHT_COLOR_GREEN,
+ "purple" = LIGHT_COLOR_LAVENDER,
+ )
+ /// Whether this saber has beel multitooled.
var/hacked = FALSE
-/obj/item/melee/transforming/energy/sword/saber/Initialize(mapload)
+/obj/item/melee/energy/sword/saber/Initialize(mapload)
. = ..()
- if(LAZYLEN(possible_colors))
- var/set_color = pick(possible_colors)
- sword_color = set_color
- set_light_color(possible_colors[set_color])
+ if(!sword_color_icon && LAZYLEN(possible_colors))
+ sword_color_icon = pick(possible_colors)
-/obj/item/melee/transforming/energy/sword/saber/process()
+ if(sword_color_icon)
+ set_light_color(possible_colors[sword_color_icon])
+
+/obj/item/melee/energy/sword/saber/process()
. = ..()
if(hacked)
- var/set_color = pick(possible_colors)
- set_light_color(possible_colors[set_color])
+ set_light_color(possible_colors[pick(possible_colors)])
-/obj/item/melee/transforming/energy/sword/saber/red
- possible_colors = list("red" = COLOR_SOFT_RED)
+/obj/item/melee/energy/sword/saber/red
+ sword_color_icon = "red"
-/obj/item/melee/transforming/energy/sword/saber/blue
- possible_colors = list("blue" = LIGHT_COLOR_LIGHT_CYAN)
+/obj/item/melee/energy/sword/saber/blue
+ sword_color_icon = "blue"
-/obj/item/melee/transforming/energy/sword/saber/green
- possible_colors = list("green" = LIGHT_COLOR_GREEN)
+/obj/item/melee/energy/sword/saber/green
+ sword_color_icon = "green"
-/obj/item/melee/transforming/energy/sword/saber/purple
- possible_colors = list("purple" = LIGHT_COLOR_LAVENDER)
+/obj/item/melee/energy/sword/saber/purple
+ sword_color_icon = "purple"
-/obj/item/melee/transforming/energy/sword/saber/attackby(obj/item/W, mob/living/user, params)
- if(W.tool_behaviour == TOOL_MULTITOOL)
- if(!hacked)
- hacked = TRUE
- sword_color = "rainbow"
- to_chat(user, span_warning("RNBW_ENGAGE"))
-
- if(active)
- icon_state = "swordrainbow"
- user.update_inv_hands()
- else
+/obj/item/melee/energy/sword/saber/attackby(obj/item/weapon, mob/living/user, params)
+ if(weapon.tool_behaviour == TOOL_MULTITOOL)
+ if(hacked)
to_chat(user, span_warning("It's already fabulous!"))
+ else
+ hacked = TRUE
+ sword_color_icon = "rainbow"
+ to_chat(user, span_warning("RNBW_ENGAGE"))
+ if(force >= active_force)
+ icon_state = "[initial(icon_state)]_on_rainbow"
+ user.update_inv_hands()
else
return ..()
-/obj/item/melee/transforming/energy/sword/pirate
+/obj/item/melee/energy/sword/pirate
name = "energy cutlass"
desc = "Arrrr matey."
- icon_state = "cutlass0"
+ icon_state = "e_cutlass"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- icon_state_on = "cutlass1"
light_color = COLOR_RED
-/obj/item/melee/transforming/energy/blade
+/// Energy blades, which are effectively perma-extended energy swords
+/obj/item/melee/energy/blade
name = "energy blade"
desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal."
icon_state = "blade"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- force = 30 //Normal attacks deal esword damage
hitsound = 'sound/weapons/blade1.ogg'
- active = 1
- throwforce = 1 //Throwing or dropping the item deletes it.
+ 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")
+ force = 30
+ throwforce = 1 // Throwing or dropping the item deletes it.
throw_speed = 3
throw_range = 1
- w_class = WEIGHT_CLASS_BULKY//So you can't hide it in your pocket or some such.
- var/datum/effect_system/spark_spread/spark_system
sharpness = SHARP_EDGED
+ heat = 3500
+ w_class = WEIGHT_CLASS_BULKY
+ blade_active = TRUE
+ /// Our linked spark system that emits from our sword.
+ var/datum/effect_system/spark_spread/spark_system
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
-/obj/item/melee/transforming/energy/blade/Initialize()
+/obj/item/melee/energy/blade/Initialize()
. = ..()
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
+ START_PROCESSING(SSobj, src)
-/obj/item/melee/transforming/energy/blade/Destroy()
+/obj/item/melee/energy/blade/Destroy()
QDEL_NULL(spark_system)
return ..()
-/obj/item/melee/transforming/energy/blade/transform_weapon(mob/living/user, supress_message_text)
- return
+/obj/item/melee/energy/blade/make_transformable()
+ return FALSE
-/obj/item/melee/transforming/energy/blade/hardlight
+/obj/item/melee/energy/blade/hardlight
name = "hardlight blade"
desc = "An extremely sharp blade made out of hard light. Packs quite a punch."
icon_state = "lightblade"
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 6e1a9ba965a..162c888fd79 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -183,9 +183,12 @@
slot_flags = ITEM_SLOT_BELT
force = 12 //9 hit crit
w_class = WEIGHT_CLASS_NORMAL
+ wound_bonus = 15
- var/cooldown_check = 0 // Used interally, you don't want to modify
-
+ /// Whether this baton is active or not
+ var/extended = TRUE
+ /// Used interally, you don't want to modify
+ var/cooldown_check = 0
/// Default wait time until can stun again.
var/cooldown = (4 SECONDS)
/// The length of the knockdown applied to a struck living, non-cyborg mob.
@@ -196,23 +199,11 @@
var/stamina_damage = 55
/// Can we stun cyborgs?
var/affect_cyborg = FALSE
- /// "On" sound, played when switching between able to stun or not.
- var/on_sound
/// The path of the default sound to play when we stun something.
var/on_stun_sound = 'sound/effects/woodhit.ogg'
/// Do we animate the "hit" when stunning something?
var/stun_animation = TRUE
- /// Are we on or off?
- var/on = TRUE
- var/on_icon_state // What is our sprite when turned on
- var/off_icon_state // What is our sprite when turned off
- var/on_inhand_icon_state // What is our in-hand sprite when turned on
- var/force_on // Damage when on - not stunning
- var/force_off // Damage when off - not stunning
- var/weight_class_on // What is the new size class when turned on
-
- wound_bonus = 15
/obj/item/melee/classic_baton/Initialize()
. = ..()
@@ -224,15 +215,6 @@
/obj/item/melee/classic_baton/proc/get_wait_description()
return
-/// Description for when turning the baton "on".
-/obj/item/melee/classic_baton/proc/get_on_description()
- . = list()
-
- .["local_on"] = "You extend the baton."
- .["local_off"] = "You collapse the baton."
-
- return .
-
/// Default message for stunning a living, non-cyborg mob.
/obj/item/melee/classic_baton/proc/get_stun_description(mob/living/target, mob/living/user)
. = list()
@@ -269,7 +251,7 @@
return
/obj/item/melee/classic_baton/attack(mob/living/target, mob/living/user, params)
- if(!on)
+ if(!extended)
return ..()
add_fingerprint(user)
@@ -361,94 +343,91 @@
name = "telescopic baton"
desc = "A compact yet robust personal defense weapon. Can be concealed when folded."
icon = 'icons/obj/items_and_weapons.dmi'
- icon_state = "telebaton_0"
+ icon_state = "telebaton"
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
inhand_icon_state = null
+ attack_verb_continuous = list("hits", "pokes")
+ attack_verb_simple = list("hit", "poke")
worn_icon_state = "tele_baton"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_flags = NONE
force = 0
- on = FALSE
- on_sound = 'sound/weapons/batonextend.ogg'
-
- on_icon_state = "telebaton_1"
- off_icon_state = "telebaton_0"
- on_inhand_icon_state = "nullrod"
- force_on = 10
- force_off = 0
- weight_class_on = WEIGHT_CLASS_BULKY
bare_wound_bonus = 5
+ extended = FALSE
+
+ /// The sound effecte played when our baton is extended.
+ var/on_sound = 'sound/weapons/batonextend.ogg'
+ /// The inhand iconstate used when our baton is extended.
+ var/on_inhand_icon_state = "nullrod"
+ /// The force on extension.
+ var/active_force = 10
+
+/obj/item/melee/classic_baton/telescopic/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = active_force, \
+ hitsound_on = hitsound, \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ 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/on_transform)
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
- var/mob/living/carbon/human/H = user
- var/obj/item/organ/brain/B = H.getorgan(/obj/item/organ/brain)
+ var/mob/living/carbon/human/human_user = user
+ var/obj/item/organ/brain/our_brain = human_user.getorgan(/obj/item/organ/brain)
user.visible_message(span_suicide("[user] stuffs [src] up [user.p_their()] nose and presses the 'extend' button! It looks like [user.p_theyre()] trying to clear [user.p_their()] mind."))
- if(!on)
- src.attack_self(user)
- else
+ if(extended)
playsound(src, on_sound, 50, TRUE)
add_fingerprint(user)
+ else
+ attack_self(user)
+
sleep(3)
- if (!QDELETED(H))
- if(!QDELETED(B))
- H.internal_organs -= B
- qdel(B)
- new /obj/effect/gibspawner/generic(H.drop_location(), H)
+ if (!QDELETED(human_user))
+ if(!QDELETED(our_brain))
+ human_user.internal_organs -= our_brain
+ qdel(our_brain)
+ new /obj/effect/gibspawner/generic(human_user.drop_location(), human_user)
return (BRUTELOSS)
-/obj/item/melee/classic_baton/telescopic/attack_self(mob/user)
- on = !on
- var/list/desc = get_on_description()
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Gives feedback to the user and makes it show up inhand.
+ */
+/obj/item/melee/classic_baton/telescopic/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
- if(on)
- to_chat(user, desc["local_on"])
- icon_state = on_icon_state
- inhand_icon_state = on_inhand_icon_state
- w_class = weight_class_on
- force = force_on
- attack_verb_continuous = list("smacks", "strikes", "cracks", "beats")
- attack_verb_simple = list("smack", "strike", "crack", "beat")
- else
- to_chat(user, desc["local_off"])
- icon_state = off_icon_state
- inhand_icon_state = null //no sprite for concealment even when in hand
- slot_flags = ITEM_SLOT_BELT
- w_class = WEIGHT_CLASS_SMALL
- force = force_off
- attack_verb_continuous = list("hits", "pokes")
- attack_verb_simple = list("hit", "poke")
-
- playsound(src.loc, on_sound, 50, TRUE)
- add_fingerprint(user)
+ extended = active
+ inhand_icon_state = active ? on_inhand_icon_state : null // When inactive, there is no inhand icon_state.
+ balloon_alert(user, "[active ? "extended" : "collapsed"] [src]")
+ playsound(user ? user : src, on_sound, 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/melee/classic_baton/telescopic/contractor_baton
name = "contractor baton"
desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets."
icon = 'icons/obj/items_and_weapons.dmi'
- icon_state = "contractor_baton_0"
+ icon_state = "contractor_baton"
+ worn_icon_state = "contractor_baton"
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- inhand_icon_state = null
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_flags = NONE
force = 5
-
cooldown = 25
stamina_damage = 85
affect_cyborg = TRUE
- on_sound = 'sound/weapons/contractorbatonextend.ogg'
on_stun_sound = 'sound/effects/contractorbatonhit.ogg'
- on_icon_state = "contractor_baton_1"
- off_icon_state = "contractor_baton_0"
- on_inhand_icon_state = "contractor_baton"
- force_on = 16
- force_off = 5
- weight_class_on = WEIGHT_CLASS_NORMAL
+ on_inhand_icon_state = "contractor_baton_on"
+ on_sound = 'sound/weapons/contractorbatonextend.ogg'
+ active_force = 16
/obj/item/melee/classic_baton/telescopic/contractor_baton/get_wait_description()
return span_danger("The baton is still charging!")
@@ -582,8 +561,8 @@
/obj/item/melee/roastingstick
name = "advanced roasting stick"
desc = "A telescopic roasting stick with a miniature shield generator designed to ensure entry into various high-tech shielded cooking ovens and firepits."
- icon_state = "roastingstick_0"
- inhand_icon_state = "null"
+ icon_state = "roastingstick"
+ inhand_icon_state = null
worn_icon_state = "tele_baton"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
@@ -591,33 +570,55 @@
force = 0
attack_verb_continuous = list("hits", "pokes")
attack_verb_simple = list("hit", "poke")
+ /// The sausage attatched to our stick.
var/obj/item/food/sausage/held_sausage
+ /// Static list of things our roasting stick can interact with.
var/static/list/ovens
- var/on = FALSE
+ /// The beam that links to the oven we use
var/datum/beam/beam
+ /// Whether or stick is extended and can recieve sausage
+ var/extended = FALSE
/obj/item/melee/roastingstick/Initialize()
. = ..()
if (!ovens)
ovens = typecacheof(list(/obj/singularity, /obj/energy_ball, /obj/machinery/power/supermatter_crystal, /obj/structure/bonfire))
+ AddComponent(/datum/component/transforming, \
+ hitsound_on = hitsound, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_PRE_TRANSFORM, .proc/attempt_transform)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-/obj/item/melee/roastingstick/attack_self(mob/user)
- on = !on
- if(on)
- extend(user)
- else
- if (held_sausage)
- to_chat(user, span_warning("You can't retract [src] while [held_sausage] is attached!"))
- return
- retract(user)
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_PRE_TRANSFORM].
+ *
+ * If there is a sausage attached, returns COMPONENT_BLOCK_TRANSFORM.
+ */
+/obj/item/melee/roastingstick/proc/attempt_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
- playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
- add_fingerprint(user)
+ if(held_sausage)
+ to_chat(user, span_warning("You can't retract [src] while [held_sausage] is attached!"))
+ return COMPONENT_BLOCK_TRANSFORM
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Gives feedback on stick extension.
+ */
+/obj/item/melee/roastingstick/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ extended = active
+ inhand_icon_state = active ? "nullrod" : null
+ balloon_alert(user, "[active ? "extended" : "collapsed"] [src]")
+ playsound(user ? user : src, 'sound/weapons/batonextend.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/melee/roastingstick/attackby(atom/target, mob/user)
..()
if (istype(target, /obj/item/food/sausage))
- if (!on)
+ if (!extended)
to_chat(user, span_warning("You must extend [src] to attach anything to it!"))
return
if (held_sausage)
@@ -641,18 +642,6 @@
if(held_sausage)
. += mutable_appearance(icon, "roastingstick_sausage")
-/obj/item/melee/roastingstick/proc/extend(user)
- to_chat(user, span_warning("You extend [src]."))
- icon_state = "roastingstick_1"
- inhand_icon_state = "nullrod"
- w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/melee/roastingstick/proc/retract(user)
- to_chat(user, span_notice("You collapse [src]."))
- icon_state = "roastingstick_0"
- inhand_icon_state = null
- w_class = WEIGHT_CLASS_SMALL
-
/obj/item/melee/roastingstick/handle_atom_del(atom/target)
if (target == held_sausage)
held_sausage = null
@@ -660,7 +649,7 @@
/obj/item/melee/roastingstick/afterattack(atom/target, mob/user, proximity)
. = ..()
- if (!on)
+ if (!extended)
return
if (is_type_in_typecache(target, ovens))
if (held_sausage?.roasted)
diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm
deleted file mode 100644
index 6e8bf4fda43..00000000000
--- a/code/game/objects/items/melee/transforming.dm
+++ /dev/null
@@ -1,101 +0,0 @@
-/obj/item/melee/transforming
- sharpness = SHARP_EDGED
- bare_wound_bonus = 20
- stealthy_audio = TRUE //Most of these are antag weps so we dont want them to be /too/ overt.
- var/active = FALSE
- var/force_on = 30 //force when active
- var/faction_bonus_force = 0 //Bonus force dealt against certain factions
- var/throwforce_on = 20
- var/icon_state_on = "axe1"
- var/hitsound_on = 'sound/weapons/blade1.ogg'
- var/list/attack_verb_on = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- var/list/attack_verb_off = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- w_class = WEIGHT_CLASS_SMALL
- var/bonus_active = FALSE //If the faction damage bonus is active
- var/list/nemesis_factions //Any mob with a faction that exists in this list will take bonus damage/effects
- var/w_class_on = WEIGHT_CLASS_BULKY
- var/clumsy_check = TRUE
- /// If we get sharpened with a whetstone, save the bonus here for later use if we un/redeploy
- var/sharpened_bonus
-
-/obj/item/melee/transforming/Initialize()
- . = ..()
- if(active)
- if(attack_verb_on.len)
- attack_verb_continuous = attack_verb_on
- else
- if(attack_verb_off.len)
- attack_verb_continuous = attack_verb_off
- if(embedding)
- updateEmbedding()
- if(sharpness)
- AddComponent(/datum/component/butchering, 50, 100, 0, hitsound)
- RegisterSignal(src, COMSIG_ITEM_SHARPEN_ACT, .proc/on_sharpen)
-
-/obj/item/melee/transforming/attack_self(mob/living/carbon/user)
- if(transform_weapon(user))
- clumsy_transform_effect(user)
-
-/obj/item/melee/transforming/attack(mob/living/target, mob/living/carbon/human/user)
- var/nemesis_faction = FALSE
- if(LAZYLEN(nemesis_factions))
- for(var/F in target.faction)
- if(F in nemesis_factions)
- nemesis_faction = TRUE
- force += faction_bonus_force
- nemesis_effects(user, target)
- break
- . = ..()
- if(nemesis_faction)
- force -= faction_bonus_force
-
-/obj/item/melee/transforming/proc/transform_weapon(mob/living/user, supress_message_text)
- active = !active
- if(active)
- force = force_on + sharpened_bonus
- throwforce = throwforce_on + sharpened_bonus
- hitsound = hitsound_on
- throw_speed = 4
- if(attack_verb_on.len)
- attack_verb_continuous = attack_verb_on
- icon_state = icon_state_on
- w_class = w_class_on
- if(embedding)
- updateEmbedding()
- else
- force = initial(force) + (get_sharpness() ? sharpened_bonus : 0)
- throwforce = initial(throwforce) + (get_sharpness() ? sharpened_bonus : 0)
- hitsound = initial(hitsound)
- throw_speed = initial(throw_speed)
- if(attack_verb_off.len)
- attack_verb_continuous = attack_verb_off
- icon_state = initial(icon_state)
- w_class = initial(w_class)
- if(embedding)
- disableEmbedding()
-
- transform_messages(user, supress_message_text)
- add_fingerprint(user)
- return TRUE
-
-/obj/item/melee/transforming/proc/nemesis_effects(mob/living/user, mob/living/target)
- return
-
-/obj/item/melee/transforming/proc/transform_messages(mob/living/user, supress_message_text)
- playsound(user, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE) //changed it from 50% volume to 35% because deafness
- if(!supress_message_text)
- to_chat(user, span_notice("[src] [active ? "is now active":"can now be concealed"]."))
-
-/obj/item/melee/transforming/proc/clumsy_transform_effect(mob/living/user)
- if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- to_chat(user, span_warning("You accidentally cut yourself with [src], like a doofus!"))
- user.take_bodypart_damage(5,5)
-
-/obj/item/melee/transforming/proc/on_sharpen(datum/source, increment, max)
- SIGNAL_HANDLER
-
- if(sharpened_bonus)
- return COMPONENT_BLOCK_SHARPEN_ALREADY
- if(force_on + increment > max)
- return COMPONENT_BLOCK_SHARPEN_MAXED
- sharpened_bonus = increment
diff --git a/code/game/objects/items/sharpener.dm b/code/game/objects/items/sharpener.dm
index acccb4eca20..7bf30c780a0 100644
--- a/code/game/objects/items/sharpener.dm
+++ b/code/game/objects/items/sharpener.dm
@@ -33,7 +33,7 @@
if(requires_sharpness && !I.get_sharpness())
to_chat(user, span_warning("You can only sharpen items that are already sharp, such as knives!"))
return
- if(is_type_in_list(I, list(/obj/item/melee/transforming/energy, /obj/item/dualsaber))) //You can't sharpen the photons in energy meelee weapons
+ if(is_type_in_list(I, list(/obj/item/melee/energy, /obj/item/dualsaber))) //You can't sharpen the photons in energy meelee weapons
to_chat(user, span_warning("You don't think \the [I] will be the thing getting modified if you use it on \the [src]!"))
return
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index ef38ecba4ef..cde1b0ac4a7 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -191,6 +191,7 @@
/obj/item/shield/energy
name = "energy combat shield"
desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere."
+ icon_state = "eshield"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
@@ -200,50 +201,51 @@
force = 3
throwforce = 3
throw_speed = 3
- base_icon_state = "eshield" // [base_icon_state]1 for expanded, [base_icon_state]0 for contracted
- var/on_force = 10
- var/on_throwforce = 8
- var/on_throw_speed = 2
- var/active = 0
- var/clumsy_check = TRUE
+
+ /// Whether the shield is currently extended and protecting the user.
+ var/enabled = FALSE
+ /// Force of the shield when active.
+ var/active_force = 10
+ /// Throwforce of the shield when active.
+ var/active_throwforce = 8
+ /// Throwspeed of ethe shield when active.
+ var/active_throw_speed = 2
+ /// Whether clumsy people can transform this without side effects.
+ var/can_clumsy_use = FALSE
/obj/item/shield/energy/Initialize()
. = ..()
- icon_state = "[base_icon_state]0"
+ AddComponent(/datum/component/transforming, \
+ force_on = active_force, \
+ throwforce_on = active_throwforce, \
+ throw_speed_on = active_throw_speed, \
+ hitsound_on = hitsound, \
+ clumsy_check = !can_clumsy_use)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
/obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- return 0
+ return FALSE
/obj/item/shield/energy/IsReflect()
- return (active)
+ return enabled
-/obj/item/shield/energy/attack_self(mob/living/carbon/human/user)
- if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- to_chat(user, span_userdanger("You beat yourself in the head with [src]!"))
- user.take_bodypart_damage(5)
- active = !active
- icon_state = "[base_icon_state][active]"
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ */
+/obj/item/shield/energy/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
- if(active)
- force = on_force
- throwforce = on_throwforce
- throw_speed = on_throw_speed
- w_class = WEIGHT_CLASS_BULKY
- playsound(user, 'sound/weapons/saberon.ogg', 35, TRUE)
- to_chat(user, span_notice("[src] is now active."))
- else
- force = initial(force)
- throwforce = initial(throwforce)
- throw_speed = initial(throw_speed)
- w_class = WEIGHT_CLASS_TINY
- playsound(user, 'sound/weapons/saberoff.ogg', 35, TRUE)
- to_chat(user, span_notice("[src] can now be concealed."))
- add_fingerprint(user)
+ enabled = active
+
+ balloon_alert(user, "[name] [active ? "activated":"deactivated"]")
+ playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/shield/riot/tele
name = "telescopic shield"
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
- icon_state = "teleriot0"
+ icon_state = "teleriot"
+ worn_icon_state = "teleriot"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
custom_materials = list(/datum/material/iron = 3600, /datum/material/glass = 3600, /datum/material/silver = 270, /datum/material/titanium = 180)
@@ -253,30 +255,36 @@
throw_speed = 3
throw_range = 4
w_class = WEIGHT_CLASS_NORMAL
- var/active = 0
+ /// Whether the shield is extended and protecting the user..
+ var/extended = FALSE
+
+/obj/item/shield/riot/tele/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = 8, \
+ throwforce_on = 5, \
+ throw_speed_on = 2, \
+ hitsound_on = hitsound, \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ 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/on_transform)
/obj/item/shield/riot/tele/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- if(active)
+ if(extended)
return ..()
- return 0
+ return FALSE
-/obj/item/shield/riot/tele/attack_self(mob/living/user)
- active = !active
- icon_state = "teleriot[active]"
- playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Allows it to be placed on back slot when active.
+ */
+/obj/item/shield/riot/tele/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
- if(active)
- force = 8
- throwforce = 5
- throw_speed = 2
- w_class = WEIGHT_CLASS_BULKY
- slot_flags = ITEM_SLOT_BACK
- to_chat(user, span_notice("You extend \the [src]."))
- else
- force = 3
- throwforce = 3
- throw_speed = 3
- w_class = WEIGHT_CLASS_NORMAL
- slot_flags = null
- to_chat(user, span_notice("[src] can now be concealed."))
- add_fingerprint(user)
+ extended = active
+ slot_flags = active ? ITEM_SLOT_BACK : null
+ playsound(user ? user : src, 'sound/weapons/batonextend.ogg', 50, TRUE)
+ balloon_alert(user, "[active ? "extended" : "collapsed"] [src]")
+ return COMPONENT_NO_DEFAULT_MESSAGE
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 3452362f26b..57d4994ef48 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -89,7 +89,7 @@
new /obj/item/encryptionkey/syndicate(src)
if(KIT_MURDER)
- new /obj/item/melee/transforming/energy/sword/saber(src)
+ new /obj/item/melee/energy/sword/saber(src)
new /obj/item/clothing/glasses/thermal/syndi(src)
new /obj/item/card/emag(src)
new /obj/item/clothing/shoes/chameleon/noslip(src)
@@ -236,7 +236,7 @@
new /obj/item/dnainjector/geladikinesis(src)
new /obj/item/dnainjector/cryokinesis(src)
new /obj/item/gun/energy/temperature/security(src)
- new /obj/item/melee/transforming/energy/sword/saber/blue(src) //see see it fits the theme bc its blue and ice is blue
+ new /obj/item/melee/energy/sword/saber/blue(src) //see see it fits the theme bc its blue and ice is blue
if(KIT_TRAITOR_2006) //A kit so old, it's probably older than you. //This bundle is filled with the entire unlink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code.
new /obj/item/storage/toolbox/emergency/old/ancientbundle(src) //Items fit neatly into a classic toolbox just to remind you what the theme is.
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index 6a10293c92d..4ac024e5eb7 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -62,7 +62,7 @@
/obj/item/crowbar/power
name = "jaws of life"
desc = "A set of jaws of life, compressed through the magic of science."
- icon_state = "jaws_pry"
+ icon_state = "jaws"
inhand_icon_state = "jawsoflife"
worn_icon_state = "jawsoflife"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
@@ -73,10 +73,33 @@
toolspeed = 0.7
force_opens = TRUE
+/obj/item/crowbar/power/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = force, \
+ throwforce_on = throwforce, \
+ hitsound_on = hitsound, \
+ w_class_on = w_class, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Toggles between crowbar and wirecutters and gives feedback to the user.
+ */
+/obj/item/crowbar/power/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ tool_behaviour = (active ? TOOL_WIRECUTTER : TOOL_CROWBAR)
+ balloon_alert(user, "attached [active ? "cutting" : "prying"]")
+ playsound(user ? user : src, 'sound/items/change_jaws.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
/obj/item/crowbar/power/syndicate
name = "Syndicate jaws of life"
desc = "A re-engineered copy of Nanotrasen's standard jaws of life. Can be used to force open airlocks in its crowbar configuration."
- icon_state = "jaws_pry_syndie"
+ icon_state = "jaws_syndie"
toolspeed = 0.5
force_opens = TRUE
@@ -99,34 +122,6 @@
playsound(loc, "desecration", 50, TRUE, -1)
return (BRUTELOSS)
-/obj/item/crowbar/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, TRUE)
- if(tool_behaviour == TOOL_CROWBAR)
- tool_behaviour = TOOL_WIRECUTTER
- balloon_alert(user, "attached cutting jaws")
- usesound = 'sound/items/jaws_cut.ogg'
- update_appearance()
-
- else
- tool_behaviour = TOOL_CROWBAR
- balloon_alert(user, "attached prying jaws")
- usesound = 'sound/items/jaws_pry.ogg'
- update_appearance()
-
-/obj/item/crowbar/power/update_icon_state()
- if(tool_behaviour == TOOL_WIRECUTTER)
- icon_state = "jaws_cutter"
- else
- icon_state = "jaws_pry"
- return ..()
-
-/obj/item/crowbar/power/syndicate/update_icon_state()
- if(tool_behaviour == TOOL_WIRECUTTER)
- icon_state = "jaws_cutter_syndie"
- else
- icon_state = "jaws_pry_syndie"
- return ..()
-
/obj/item/crowbar/power/attack(mob/living/carbon/C, mob/user)
if(istype(C) && C.handcuffed && tool_behaviour == TOOL_WIRECUTTER)
user.visible_message(span_notice("[user] cuts [C]'s restraints with [src]!"))
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm
index 19a47c47f85..b4e9030010f 100644
--- a/code/game/objects/items/tools/screwdriver.dm
+++ b/code/game/objects/items/tools/screwdriver.dm
@@ -72,7 +72,8 @@
/obj/item/screwdriver/power
name = "hand drill"
desc = "A simple powered hand drill."
- icon_state = "drill_screw"
+ icon_state = "drill"
+ belt_icon_state = null
inhand_icon_state = "drill"
worn_icon_state = "drill"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
@@ -89,9 +90,34 @@
usesound = 'sound/items/drill_use.ogg'
toolspeed = 0.7
random_color = FALSE
+ greyscale_config = null
+ greyscale_config_belt = null
greyscale_config_inhand_left = null
greyscale_config_inhand_right = null
+/obj/item/screwdriver/power/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = force, \
+ throwforce_on = throwforce, \
+ hitsound_on = hitsound, \
+ w_class_on = w_class, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Toggles between crowbar and wirecutters and gives feedback to the user.
+ */
+/obj/item/screwdriver/power/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ tool_behaviour = (active ? TOOL_WRENCH : TOOL_SCREWDRIVER)
+ balloon_alert(user, "attached [active ? "bolt bit" : "screw bit"]")
+ playsound(user ? user : src, 'sound/items/change_drill.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
/obj/item/screwdriver/power/examine()
. = ..()
. += " It's fitted with a [tool_behaviour == TOOL_SCREWDRIVER ? "screw" : "bolt"] bit."
@@ -104,17 +130,6 @@
playsound(loc, 'sound/items/drill_use.ogg', 50, TRUE, -1)
return(BRUTELOSS)
-/obj/item/screwdriver/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, TRUE)
- if(tool_behaviour == TOOL_SCREWDRIVER)
- tool_behaviour = TOOL_WRENCH
- balloon_alert(user, "attached bolt bit")
- icon_state = "drill_bolt"
- else
- tool_behaviour = TOOL_SCREWDRIVER
- balloon_alert(user, "attached screw bit")
- icon_state = "drill_screw"
-
/obj/item/screwdriver/cyborg
name = "automated screwdriver"
desc = "A powerful automated screwdriver, designed to be both precise and quick."
diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm
index 259f261dc45..5582d3d41ec 100644
--- a/code/game/objects/items/tools/wrench.dm
+++ b/code/game/objects/items/tools/wrench.dm
@@ -82,43 +82,37 @@
name = "combat wrench"
desc = "It's like a normal wrench but edgier. Can be found on the battlefield."
icon_state = "wrench_combat"
- inhand_icon_state = "wrench_combat"
+ belt_icon_state = "wrench_combat"
attack_verb_continuous = list("devastates", "brutalizes", "commits a war crime against", "obliterates", "humiliates")
attack_verb_simple = list("devastate", "brutalize", "commit a war crime against", "obliterate", "humiliate")
tool_behaviour = null
toolspeed = null
- var/on = FALSE
-/obj/item/wrench/combat/ComponentInitialize()
+/obj/item/wrench/combat/Initialize()
. = ..()
- AddElement(/datum/element/update_icon_updates_onmob)
+ AddComponent(/datum/component/transforming, \
+ force_on = 6, \
+ throwforce_on = 8, \
+ hitsound_on = hitsound, \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-/obj/item/wrench/combat/attack_self(mob/living/user)
- if(on)
- on = FALSE
- force = initial(force)
- w_class = initial(w_class)
- throwforce = initial(throwforce)
- tool_behaviour = initial(tool_behaviour)
- toolspeed = initial(toolspeed)
- playsound(user, 'sound/weapons/saberoff.ogg', 5, TRUE)
- to_chat(user, span_warning("[src] can now be kept at bay."))
- else
- on = TRUE
- force = 6
- w_class = WEIGHT_CLASS_NORMAL
- throwforce = 8
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Gives it wrench behaviors when active.
+ */
+/obj/item/wrench/combat/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ if(active)
tool_behaviour = TOOL_WRENCH
toolspeed = 1
- playsound(user, 'sound/weapons/saberon.ogg', 5, TRUE)
- to_chat(user, span_warning("[src] is now active. Woe onto your enemies!"))
- update_appearance()
-
-/obj/item/wrench/combat/update_icon_state()
- if(on)
- icon_state = "[initial(icon_state)]_on"
- inhand_icon_state = "[initial(inhand_icon_state)]1"
else
- icon_state = "[initial(icon_state)]"
- inhand_icon_state = "[initial(inhand_icon_state)]"
- return ..()
+ tool_behaviour = initial(tool_behaviour)
+ toolspeed = initial(toolspeed)
+
+ balloon_alert(user, "[name] [active ? "active, woe!":"restrained"]")
+ playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 5, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index cb1bb7b00f0..3f156b1e074 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -325,63 +325,68 @@
/obj/item/toy/sword
name = "toy sword"
desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up."
+ icon_state = "e_sword"
icon = 'icons/obj/transforming_energy.dmi'
- icon_state = "sword0"
- inhand_icon_state = "sword0"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- var/active = 0
w_class = WEIGHT_CLASS_SMALL
attack_verb_continuous = list("attacks", "strikes", "hits")
attack_verb_simple = list("attack", "strike", "hit")
+ /// Whether our sword has been multitooled to rainbow
var/hacked = FALSE
- var/saber_color
+ /// The color of our fake energy sword
+ var/saber_color = "blue"
-/obj/item/toy/sword/attack_self(mob/user)
- active = !( active )
- if (active)
- to_chat(user, span_notice("You extend the plastic blade with a quick flick of your wrist."))
- playsound(user, 'sound/weapons/saberon.ogg', 20, TRUE)
- if(hacked)
- icon_state = "swordrainbow"
- inhand_icon_state = "swordrainbow"
- else
- icon_state = "swordblue"
- inhand_icon_state = "swordblue"
- w_class = WEIGHT_CLASS_BULKY
- else
- to_chat(user, span_notice("You push the plastic blade back down into the handle."))
- playsound(user, 'sound/weapons/saberoff.ogg', 20, TRUE)
- icon_state = "sword0"
- inhand_icon_state = "sword0"
- w_class = WEIGHT_CLASS_SMALL
- add_fingerprint(user)
+/obj/item/toy/sword/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ throw_speed_on = throw_speed, \
+ hitsound_on = hitsound, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-// Copied from /obj/item/melee/transforming/energy/sword/attackby
-/obj/item/toy/sword/attackby(obj/item/W, mob/living/user, params)
- if(istype(W, /obj/item/toy/sword))
- if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
- to_chat(user, span_warning("\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!"))
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Updates our icon to have the correct color, and give some feedback.
+ */
+/obj/item/toy/sword/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ if(active)
+ icon_state = "[icon_state]_[saber_color]"
+
+ balloon_alert(user, "[active ? "flicked out":"pushed in"] [src]")
+ playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 20, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
+// Copied from /obj/item/melee/energy/sword/attackby
+/obj/item/toy/sword/attackby(obj/item/weapon, mob/living/user, params)
+ if(istype(weapon, /obj/item/toy/sword))
+ var/obj/item/toy/sword/attatched_sword = weapon
+ if(HAS_TRAIT(weapon, TRAIT_NODROP))
+ to_chat(user, span_warning("[weapon] is stuck to your hand, you can't attach it to [src]!"))
+ return
+ else if(HAS_TRAIT(src, TRAIT_NODROP))
+ to_chat(user, span_warning("[src] is stuck to your hand, you can't attach it to [weapon]!"))
return
else
to_chat(user, span_notice("You attach the ends of the two plastic swords, making a single double-bladed toy! You're fake-cool."))
- var/obj/item/dualsaber/toy/newSaber = new /obj/item/dualsaber/toy(user.loc)
- if(hacked) // That's right, we'll only check the "original" "sword".
- newSaber.hacked = TRUE
- newSaber.saber_color = "rainbow"
- qdel(W)
+ var/obj/item/dualsaber/toy/new_saber = new /obj/item/dualsaber/toy(user.loc)
+ if(attatched_sword.hacked || hacked)
+ new_saber.hacked = TRUE
+ new_saber.saber_color = "rainbow"
+ qdel(weapon)
qdel(src)
- else if(W.tool_behaviour == TOOL_MULTITOOL)
- if(!hacked)
+ user.put_in_hands(new_saber)
+ else if(weapon.tool_behaviour == TOOL_MULTITOOL)
+ if(hacked)
+ to_chat(user, span_warning("It's already fabulous!"))
+ else
hacked = TRUE
saber_color = "rainbow"
to_chat(user, span_warning("RNBW_ENGAGE"))
-
- if(active)
- icon_state = "swordrainbow"
- user.update_inv_hands()
- else
- to_chat(user, span_warning("It's already fabulous!"))
else
return ..()
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 41acb9be44a..c58ccbdb710 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -364,48 +364,30 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
attack_verb_continuous = list("stubs", "pokes")
attack_verb_simple = list("stub", "poke")
resistance_flags = FIRE_PROOF
- var/extended = FALSE
+ /// Whether the switchblade starts extended or not.
+ var/start_extended = FALSE
/obj/item/switchblade/Initialize()
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
AddComponent(/datum/component/butchering, 7 SECONDS, 100)
- set_extended(extended)
-
-/obj/item/switchblade/attack_self(mob/user)
- playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
- set_extended(!extended)
-
-/obj/item/switchblade/update_icon_state()
- icon_state = "[base_icon_state][extended ? "_ext" : ""]"
- return ..()
-
-/obj/item/switchblade/proc/set_extended(new_extended)
- extended = new_extended
- update_icon_state()
- if(extended)
- force = 20
- w_class = WEIGHT_CLASS_NORMAL
- throwforce = 23
- attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
- hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = SHARP_EDGED
- else
- force = 3
- w_class = WEIGHT_CLASS_SMALL
- throwforce = 5
- attack_verb_continuous = list("stubs", "pokes")
- attack_verb_simple = list("stub", "poke")
- hitsound = 'sound/weapons/genhit.ogg'
- sharpness = NONE
+ 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/weapons/bladeslice.ogg', \
+ w_class_on = WEIGHT_CLASS_NORMAL, \
+ attack_verb_continuous_on = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts"), \
+ attack_verb_simple_on = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut"))
/obj/item/switchblade/suicide_act(mob/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
- extended = TRUE
+ start_extended = TRUE
/obj/item/phone
name = "red phone"
diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
index 80c6f12fee6..c61e340e45a 100644
--- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm
+++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
@@ -67,7 +67,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/suit/armor/tdome/red(src)
for(var/i in 1 to 3)
- new /obj/item/melee/transforming/energy/sword/saber(src)
+ new /obj/item/melee/energy/sword/saber(src)
for(var/i in 1 to 3)
new /obj/item/gun/energy/laser(src)
for(var/i in 1 to 3)
@@ -86,7 +86,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/suit/armor/tdome/green(src)
for(var/i in 1 to 3)
- new /obj/item/melee/transforming/energy/sword/saber(src)
+ new /obj/item/melee/energy/sword/saber(src)
for(var/i in 1 to 3)
new /obj/item/gun/energy/laser(src)
for(var/i in 1 to 3)
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index d8f9f3fae07..a4ea6ed2597 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -187,7 +187,7 @@
var/can_transfer = TRUE //if golems can switch bodies to this new shell
var/mob/living/owner = null //golem's owner if it has one
short_desc = "You are a Free Golem. Your family worships The Liberator."
- flavour_text = "In his infinite and divine wisdom, he set your clan free to travel the stars with a single declaration: \"Yeah go do whatever.\""
+ flavour_text = "In his infinite and divine wisdom, he set your clan free to travel the stars with a single declaration: \"Yeah go do whatever.\""
/obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null)
if(species) //spawners list uses object name to register so this goes before ..()
@@ -488,7 +488,7 @@
/datum/outfit/syndicate_empty/battlecruiser/assault/captain
name = "Syndicate Battlecruiser Captain"
- l_pocket = /obj/item/melee/transforming/energy/sword/saber/red
+ l_pocket = /obj/item/melee/energy/sword/saber/red
r_pocket = /obj/item/melee/classic_baton/telescopic
suit = /obj/item/clothing/suit/armor/vest/capcarapace/syndicate
suit_store = /obj/item/gun/ballistic/revolver/mateba
diff --git a/code/modules/antagonists/clown_ops/clown_weapons.dm b/code/modules/antagonists/clown_ops/clown_weapons.dm
index d6c69905ff2..7d97c568b09 100644
--- a/code/modules/antagonists/clown_ops/clown_weapons.dm
+++ b/code/modules/antagonists/clown_ops/clown_weapons.dm
@@ -59,65 +59,65 @@
//BANANIUM SWORD
-/obj/item/melee/transforming/energy/sword/bananium
+/obj/item/melee/energy/sword/bananium
name = "bananium sword"
- desc = "An elegant weapon, for a more civilized age."
+ icon_state = "e_sword"
+ attack_verb_continuous = list("hits", "taps", "pokes")
+ attack_verb_simple = list("hit", "tap", "poke")
force = 0
throwforce = 0
- force_on = 0
- throwforce_on = 0
hitsound = null
- attack_verb_on = list("slips")
- clumsy_check = FALSE
- sharpness = NONE
- sword_color = "yellow"
- heat = 0
+ embedding = null
light_color = COLOR_YELLOW
- var/next_trombone_allowed = 0
+ sword_color_icon = "bananium"
+ active_heat = 0
+ /// Cooldown for making a trombone noise for failing to make a bananium desword
+ COOLDOWN_DECLARE(next_trombone_allowed)
-/obj/item/melee/transforming/energy/sword/bananium/Initialize()
+/obj/item/melee/energy/sword/bananium/make_transformable()
+ AddComponent(/datum/component/transforming, \
+ throw_speed_on = 4, \
+ attack_verb_continuous_on = list("slips"), \
+ attack_verb_simple_on = list("slip"), \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/obj/item/melee/energy/sword/bananium/on_transform(obj/item/source, mob/user, active)
. = ..()
adjust_slipperiness()
-/* Adds or removes a slippery component, depending on whether the sword
- * is active or not.
+/*
+ * Adds or removes a slippery component, depending on whether the sword is active or not.
*/
-/obj/item/melee/transforming/energy/sword/proc/adjust_slipperiness()
- if(active)
+/obj/item/melee/energy/sword/bananium/proc/adjust_slipperiness()
+ if(blade_active)
AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP)
else
qdel(GetComponent(/datum/component/slippery))
-/obj/item/melee/transforming/energy/sword/bananium/attack(mob/living/M, mob/living/user)
- ..()
- if(active)
+/obj/item/melee/energy/sword/bananium/attack(mob/living/M, mob/living/user)
+ . = ..()
+ if(blade_active)
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(src, M)
-/obj/item/melee/transforming/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum)
+/obj/item/melee/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum)
. = ..()
- if(active)
+ if(blade_active)
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(src, hit_atom)
-/obj/item/melee/transforming/energy/sword/bananium/attackby(obj/item/I, mob/living/user, params)
- if((world.time > next_trombone_allowed) && istype(I, /obj/item/melee/transforming/energy/sword/bananium))
- next_trombone_allowed = world.time + 50
+/obj/item/melee/energy/sword/bananium/attackby(obj/item/weapon, mob/living/user, params)
+ if(COOLDOWN_FINISHED(src, next_trombone_allowed) && istype(weapon, /obj/item/melee/energy/sword/bananium))
+ COOLDOWN_START(src, next_trombone_allowed, 5 SECONDS)
to_chat(user, span_warning("You slap the two swords together. Sadly, they do not seem to fit!"))
playsound(src, 'sound/misc/sadtrombone.ogg', 50)
return TRUE
return ..()
-/obj/item/melee/transforming/energy/sword/bananium/transform_weapon(mob/living/user, supress_message_text)
- . = ..()
- adjust_slipperiness()
-
-/obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user)
- return ""
-
-/obj/item/melee/transforming/energy/sword/bananium/suicide_act(mob/user)
- if(!active)
- transform_weapon(user, TRUE)
+/obj/item/melee/energy/sword/bananium/suicide_act(mob/user)
+ if(!blade_active)
+ attack_self(user)
user.visible_message(span_suicide("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku, but the blade slips off of [user.p_them()] harmlessly!"))
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(src, user)
@@ -128,42 +128,39 @@
/obj/item/shield/energy/bananium
name = "bananium energy shield"
desc = "A shield that stops most melee attacks, protects user from almost all energy projectiles, and can be thrown to slip opponents."
+ icon_state = "bananaeshield"
throw_speed = 1
- clumsy_check = 0
- base_icon_state = "bananaeshield"
force = 0
throwforce = 0
throw_range = 5
- on_force = 0
- on_throwforce = 0
- on_throw_speed = 1
-/obj/item/shield/energy/bananium/Initialize()
+ active_force = 0
+ active_throwforce = 0
+ active_throw_speed = 1
+ can_clumsy_use = TRUE
+
+/obj/item/shield/energy/bananium/on_transform(obj/item/source, mob/user, active)
. = ..()
adjust_slipperiness()
-/* Adds or removes a slippery component, depending on whether the shield
- * is active or not.
+/*
+ * Adds or removes a slippery component, depending on whether the shield is active or not.
*/
/obj/item/shield/energy/bananium/proc/adjust_slipperiness()
- if(active)
+ if(enabled)
AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP)
else
qdel(GetComponent(/datum/component/slippery))
-/obj/item/shield/energy/bananium/attack_self(mob/living/carbon/human/user)
- . = ..()
- adjust_slipperiness()
-
/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE)
- if(active)
+ if(enabled)
if(iscarbon(thrower))
var/mob/living/carbon/C = thrower
C.throw_mode_on(THROW_MODE_TOGGLE) //so they can catch it on the return.
return ..()
/obj/item/shield/energy/bananium/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- if(active)
+ if(enabled)
var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum)
if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index f9aa22f913e..b66a2c96351 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -491,7 +491,7 @@
/obj/item/dnainjector/lasereyesmut = 7,
/obj/item/gun/magic/wand/fireball/inert = 3,
/obj/item/pneumatic_cannon = 15,
- /obj/item/melee/transforming/energy/sword = 7,
+ /obj/item/melee/energy/sword = 7,
/obj/item/book/granter/spell/knock = 15,
/obj/item/book/granter/spell/summonitem = 20,
/obj/item/book/granter/spell/forcewall = 17,
diff --git a/code/modules/cargo/exports/lavaland.dm b/code/modules/cargo/exports/lavaland.dm
index 83b1b73d82e..86539a59b2c 100644
--- a/code/modules/cargo/exports/lavaland.dm
+++ b/code/modules/cargo/exports/lavaland.dm
@@ -42,7 +42,7 @@
cost = CARGO_CRATE_VALUE * 80
unit_name = "major lava planet artifact"
export_types = list(/obj/item/hierophant_club,
- /obj/item/melee/transforming/cleaving_saw,
+ /obj/item/melee/cleaving_saw,
/obj/item/organ/vocal_cords/colossus,
/obj/machinery/anomalous_crystal,
/obj/item/mayhem,
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index 16118b9ed6a..0be53013ce5 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -63,7 +63,7 @@
/obj/item/storage/box/survival/engineer = 1,
)
glasses = /obj/item/clothing/glasses/thermal/eyepatch
- l_pocket = /obj/item/melee/transforming/energy/sword/saber
+ l_pocket = /obj/item/melee/energy/sword/saber
/datum/outfit/centcom/ert/security
name = "ERT Security"
@@ -330,7 +330,7 @@
back = /obj/item/storage/backpack/ert/clown
backpack_contents = list(
/obj/item/gun/ballistic/revolver/reverse = 1,
- /obj/item/melee/transforming/energy/sword/bananium = 1,
+ /obj/item/melee/energy/sword/bananium = 1,
/obj/item/shield/energy/bananium = 1,
/obj/item/storage/box/survival/engineer = 1,
)
@@ -512,7 +512,7 @@
gloves = /obj/item/clothing/gloves/tackler/combat/insulated
mask = /obj/item/clothing/mask/gas/sechailer/swat
shoes = /obj/item/clothing/shoes/combat/swat
- l_pocket = /obj/item/melee/transforming/energy/sword/saber
+ l_pocket = /obj/item/melee/energy/sword/saber
r_pocket = /obj/item/shield/energy
l_hand = /obj/item/gun/energy/pulse/loyalpin
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index 06f3a31c87e..4ab0bc13d8a 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -236,7 +236,7 @@
gloves = /obj/item/clothing/gloves/color/black
glasses = /obj/item/clothing/glasses/sunglasses
shoes = /obj/item/clothing/shoes/sneakers/black
- l_pocket = /obj/item/melee/transforming/energy/sword/saber
+ l_pocket = /obj/item/melee/energy/sword/saber
l_hand = /obj/item/storage/secure/briefcase
/datum/outfit/assassin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
@@ -414,7 +414,7 @@
suit_store = /obj/item/tank/internals/oxygen
back = /obj/item/storage/backpack/holding
backpack_contents = list(
- /obj/item/melee/transforming/energy/axe = 1,
+ /obj/item/melee/energy/axe = 1,
/obj/item/storage/part_replacer/bluespace/tier4 = 1,
/obj/item/gun/magic/wand/resurrection/debug = 1,
/obj/item/gun/magic/wand/death/debug = 1,
@@ -446,7 +446,7 @@
suit_store = /obj/item/tank/internals/oxygen
back = /obj/item/storage/backpack/holding
backpack_contents = list(
- /obj/item/melee/transforming/energy/axe = 1,
+ /obj/item/melee/energy/axe = 1,
/obj/item/storage/part_replacer/bluespace/tier4 = 1,
/obj/item/gun/magic/wand/resurrection/debug = 1,
/obj/item/gun/magic/wand/death/debug = 1,
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 34564f13e16..9839ee46a27 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -417,7 +417,7 @@
hardsuit_type = "syndi"
w_class = WEIGHT_CLASS_NORMAL
armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 40, BOMB = 35, BIO = 100, RAD = 50, FIRE = 50, ACID = 90, WOUND = 25)
- allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
+ allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi
jetpack = /obj/item/tank/jetpack/suit
cell = /obj/item/stock_parts/cell/hyper
@@ -1043,7 +1043,7 @@
inhand_icon_state = "syndie_hardsuit"
hardsuit_type = "syndi"
armor = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 40, BOMB = 35, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 30)
- allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
+ allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi
slowdown = 0
shield_icon = "shield-red"
diff --git a/code/modules/clothing/spacesuits/pirate.dm b/code/modules/clothing/spacesuits/pirate.dm
index 03a1b257b6c..ba44254d11a 100644
--- a/code/modules/clothing/spacesuits/pirate.dm
+++ b/code/modules/clothing/spacesuits/pirate.dm
@@ -16,7 +16,7 @@
desc = "A modified suit to allow space pirates to board shuttles and stations while avoiding the maw of the void. Comes with additional protection, and is lighter to move in."
icon_state = "spacepirate"
w_class = WEIGHT_CLASS_NORMAL
- allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum)
+ allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum)
slowdown = 0
armor = list(MELEE = 30, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, RAD = 30, FIRE = 60, ACID = 75)
strip_delay = 40
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 8f00a602f97..97b3212b3b6 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -4,7 +4,7 @@
/obj/item/clothing/suit/space/eva/plasmaman
name = "EVA plasma envirosuit"
desc = "A special plasma containment suit designed to be space-worthy, as well as worn over other clothing. Like its smaller counterpart, it can automatically extinguish the wearer in a crisis, and holds twice as many charges."
- allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank)
+ allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank)
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 0, FIRE = 100, ACID = 75)
resistance_flags = FIRE_PROOF
icon_state = "plasmaman_suit"
diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm
index bf907fbbbc8..da5ff41829d 100644
--- a/code/modules/clothing/spacesuits/syndi.dm
+++ b/code/modules/clothing/spacesuits/syndi.dm
@@ -12,7 +12,7 @@
inhand_icon_state = "space_suit_syndicate"
desc = "Has a tag on it: Totally not property of an enemy corporation, honest!"
w_class = WEIGHT_CLASS_NORMAL
- allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
+ allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
armor = list(MELEE = 40, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, RAD = 30, FIRE = 80, ACID = 85)
cell = /obj/item/stock_parts/cell/hyper
diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm
index b819f322fbe..b6198419e23 100644
--- a/code/modules/clothing/suits/costume.dm
+++ b/code/modules/clothing/suits/costume.dm
@@ -18,7 +18,7 @@
desc = "Yarr."
icon_state = "pirate"
inhand_icon_state = "pirate"
- allowed = list(/obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum)
+ allowed = list(/obj/item/melee/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum)
species_exception = list(/datum/species/golem)
/obj/item/clothing/suit/pirate/armored
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
index 23600acdda4..ae032445399 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
@@ -81,7 +81,7 @@
name = "Energy cake"
reqs = list(
/obj/item/food/cake/birthday = 1,
- /obj/item/melee/transforming/energy/sword = 1,
+ /obj/item/melee/energy/sword = 1,
)
blacklist = list(/obj/item/food/cake/birthday/energy)
result = /obj/item/food/cake/birthday/energy
diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm
index 2a8189eb084..54caffca6cb 100644
--- a/code/modules/holodeck/items.dm
+++ b/code/modules/holodeck/items.dm
@@ -7,63 +7,29 @@
// Items
//
-/obj/item/holo
- damtype = STAMINA
-
-/obj/item/holo/esword
+/obj/item/melee/energy/sword/holographic
name = "holographic energy sword"
desc = "May the force be with you. Sorta."
- icon = 'icons/obj/transforming_energy.dmi'
- icon_state = "sword0"
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- force = 3.0
+ damtype = STAMINA
throw_speed = 2
- throw_range = 5
throwforce = 0
- w_class = WEIGHT_CLASS_SMALL
- hitsound = "swing_hit"
- armour_penetration = 50
- var/active = 0
- var/saber_color
+ embedding = null
+ sword_color_icon = null
-/obj/item/holo/esword/green/Initialize()
+ active_throwforce = 0
+ active_sharpness = NONE
+ active_heat = 0
+
+/obj/item/melee/energy/sword/holographic/Initialize()
. = ..()
- saber_color = "green"
+ if(!sword_color_icon)
+ sword_color_icon = pick("red", "blue", "green", "purple")
-/obj/item/holo/esword/red/Initialize()
- . = ..()
- saber_color = "red"
+/obj/item/melee/energy/sword/holographic/green
+ sword_color_icon = "green"
-/obj/item/holo/esword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- if(active)
- return ..()
- return 0
-
-/obj/item/holo/esword/attack(target, mob/user)
- ..()
-
-/obj/item/holo/esword/Initialize()
- . = ..()
- saber_color = pick("red","blue","green","purple")
-
-/obj/item/holo/esword/attack_self(mob/living/user)
- active = !active
- if (active)
- force = 30
- icon_state = "sword[saber_color]"
- w_class = WEIGHT_CLASS_BULKY
- hitsound = 'sound/weapons/blade1.ogg'
- playsound(user, 'sound/weapons/saberon.ogg', 20, TRUE)
- to_chat(user, span_notice("[src] is now active."))
- else
- force = 3
- icon_state = "sword0"
- w_class = WEIGHT_CLASS_SMALL
- hitsound = "swing_hit"
- playsound(user, 'sound/weapons/saberoff.ogg', 20, TRUE)
- to_chat(user, span_notice("[src] can now be concealed."))
- return
+/obj/item/melee/energy/sword/holographic/red
+ sword_color_icon = "red"
//BASKETBALL OBJECTS
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 6966b41d5d5..e21110678a6 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -196,7 +196,7 @@
if(88)
new /obj/item/reagent_containers/food/drinks/bottle/lizardwine(src)
if(89)
- new /obj/item/melee/transforming/energy/sword/bananium(src)
+ new /obj/item/melee/energy/sword/bananium(src)
if(90)
new /obj/item/dnainjector/wackymut(src)
if(91)
diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm
index 07062ac6cb8..3706bea017b 100644
--- a/code/modules/mining/lavaland/megafauna_loot.dm
+++ b/code/modules/mining/lavaland/megafauna_loot.dm
@@ -795,88 +795,84 @@
//Blood-Drunk Miner: Cleaving Saw
-/obj/item/melee/transforming/cleaving_saw
+
+/obj/item/melee/cleaving_saw
name = "cleaving saw"
desc = "This saw, effective at drawing the blood of beasts, transforms into a long cleaver that makes use of centrifugal force."
- force = 12
- force_on = 20 //force when active
- throwforce = 20
- throwforce_on = 20
icon = 'icons/obj/lavaland/artefacts.dmi'
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
+ icon_state = "cleaving_saw"
+ worn_icon_state = "cleaving_saw"
+ attack_verb_continuous = list("attacks", "saws", "slices", "tears", "lacerates", "rips", "dices", "cuts")
+ attack_verb_simple = list("attack", "saw", "slice", "tear", "lacerate", "rip", "dice", "cut")
+ force = 12
+ throwforce = 20
inhand_x_dimension = 64
inhand_y_dimension = 64
- icon_state = "cleaving_saw"
- icon_state_on = "cleaving_saw_open"
- worn_icon_state = "cleaving_saw"
slot_flags = ITEM_SLOT_BELT
- attack_verb_off = list("attacks", "saws", "slices", "tears", "lacerates", "rips", "dices", "cuts")
- attack_verb_on = list("cleaves", "swipes", "slashes", "chops")
hitsound = 'sound/weapons/bladeslice.ogg'
- hitsound_on = 'sound/weapons/bladeslice.ogg'
w_class = WEIGHT_CLASS_BULKY
sharpness = SHARP_EDGED
- faction_bonus_force = 30
- nemesis_factions = list("mining", "boss")
- resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- var/transform_cooldown
+ /// Whether the saw is open or not
+ var/is_open = FALSE
+ /// List of factions we deal bonus damage to
+ var/list/nemesis_factions = list("mining", "boss")
+ /// Amount of damage we deal to the above factions
+ var/faction_bonus_force = 30
+ /// Whether the cleaver is actively AoE swiping something.
var/swiping = FALSE
+ /// Amount of bleed stacks gained per hit
var/bleed_stacks_per_hit = 3
+ /// Force when the saw is opened.
+ var/open_force = 20
+ /// Throwforce when the saw is opened.
+ var/open_throwforce = 20
-/obj/item/melee/transforming/cleaving_saw/examine(mob/user)
+/obj/item/melee/cleaving_saw/Initialize()
. = ..()
- . += "It is [active ? "open, will cleave enemies in a wide arc and deal additional damage to fauna":"closed, and can be used for rapid consecutive attacks that cause fauna to bleed"].\n"+\
- "Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough.\n"+\
- "Transforming it immediately after an attack causes the next attack to come out faster."
+ AddComponent(/datum/component/transforming, \
+ transform_cooldown_time = (CLICK_CD_MELEE * 0.25), \
+ force_on = open_force, \
+ throwforce_on = open_throwforce, \
+ sharpness_on = sharpness, \
+ hitsound_on = hitsound, \
+ w_class_on = w_class, \
+ attack_verb_continuous_on = list("cleaves", "swipes", "slashes", "chops"), \
+ attack_verb_simple_on = list("cleave", "swipe", "slash", "chop"))
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-/obj/item/melee/transforming/cleaving_saw/suicide_act(mob/user)
- user.visible_message(span_suicide("[user] is [active ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!"))
- transform_cooldown = 0
- transform_weapon(user, TRUE)
+/obj/item/melee/cleaving_saw/examine(mob/user)
+ . = ..()
+ . += span_notice("It is [is_open ? "open, will cleave enemies in a wide arc and deal additional damage to fauna":"closed, and can be used for rapid consecutive attacks that cause fauna to bleed"].")
+ . += span_notice("Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough.")
+ . += span_notice("Transforming it immediately after an attack causes the next attack to come out faster.")
+
+/obj/item/melee/cleaving_saw/suicide_act(mob/user)
+ user.visible_message(span_suicide("[user] is [is_open ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ attack_self(user)
return BRUTELOSS
-/obj/item/melee/transforming/cleaving_saw/transform_weapon(mob/living/user, supress_message_text)
- if(transform_cooldown > world.time)
- return FALSE
+/obj/item/melee/cleaving_saw/melee_attack_chain(mob/user, atom/target, params)
. = ..()
- if(.)
- transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5)
- user.changeNext_move(CLICK_CD_MELEE * 0.25)
-
-/obj/item/melee/transforming/cleaving_saw/transform_messages(mob/living/user, supress_message_text)
- if(!supress_message_text)
- if(active)
- to_chat(user, span_notice("You open [src]. It will now cleave enemies in a wide arc and deal additional damage to fauna."))
- else
- to_chat(user, span_notice("You close [src]. It will now attack rapidly and cause fauna to bleed."))
- playsound(user, 'sound/magic/clockwork/fellowship_armory.ogg', 35, TRUE, frequency = 90000 - (active * 30000))
-
-/obj/item/melee/transforming/cleaving_saw/clumsy_transform_effect(mob/living/user)
- if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- to_chat(user, span_warning("You accidentally cut yourself with [src], like a doofus!"))
- user.take_bodypart_damage(10)
-
-/obj/item/melee/transforming/cleaving_saw/melee_attack_chain(mob/user, atom/target, params)
- ..()
- if(!active)
+ if(!is_open)
user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly
-/obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target)
- if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite))
- return
- var/datum/status_effect/stacking/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
- if(!B)
- target.apply_status_effect(STATUS_EFFECT_SAWBLEED,bleed_stacks_per_hit)
- else
- B.add_stacks(bleed_stacks_per_hit)
-
-/obj/item/melee/transforming/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user)
- if(!active || swiping || !target.density || get_turf(target) == get_turf(user))
- if(!active)
+/obj/item/melee/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user)
+ if(!is_open || swiping || !target.density || get_turf(target) == get_turf(user))
+ if(!is_open)
faction_bonus_force = 0
- ..()
- if(!active)
+ var/is_nemesis_faction = FALSE
+ for(var/found_faction in target.faction)
+ if(found_faction in nemesis_factions)
+ is_nemesis_faction = TRUE
+ force += faction_bonus_force
+ nemesis_effects(user, target)
+ break
+ . = ..()
+ if(is_nemesis_faction)
+ force -= faction_bonus_force
+ if(!is_open)
faction_bonus_force = initial(faction_bonus_force)
else
var/turf/user_turf = get_turf(user)
@@ -890,6 +886,36 @@
melee_attack_chain(user, living_target)
swiping = FALSE
+/*
+ * If we're attacking [target]s in our nemesis list, apply unique effects.
+ *
+ * user - the mob attacking with the saw
+ * target - the mob being attacked
+ */
+/obj/item/melee/cleaving_saw/proc/nemesis_effects(mob/living/user, mob/living/target)
+ if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite))
+ return
+ var/datum/status_effect/stacking/saw_bleed/existing_bleed = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
+ if(existing_bleed)
+ existing_bleed.add_stacks(bleed_stacks_per_hit)
+ else
+ target.apply_status_effect(STATUS_EFFECT_SAWBLEED, bleed_stacks_per_hit)
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Gives feedback and makes the nextmove after transforming much quicker.
+ */
+/obj/item/melee/cleaving_saw/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ is_open = active
+ user.changeNext_move(CLICK_CD_MELEE * 0.25)
+
+ balloon_alert(user, "[active ? "opened":"closed"] [src]")
+ playsound(user ? user : src, 'sound/magic/clockwork/fellowship_armory.ogg', 35, TRUE, frequency = 90000 - (is_open * 30000))
+ return COMPONENT_NO_DEFAULT_MESSAGE
+
//Legion: Staff of Storms
/obj/item/storm_staff
diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm
index cdcca6004aa..826acb13433 100644
--- a/code/modules/mining/lavaland/tendril_loot.dm
+++ b/code/modules/mining/lavaland/tendril_loot.dm
@@ -591,7 +591,7 @@
armor = list(MELEE = 30, BULLET = 30, LASER = 10, ENERGY = 20, BOMB = 50, BIO = 100, RAD = 10, FIRE = 100, ACID = 100)
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF
- allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/spear, /obj/item/organ/regenerative_core/legion, /obj/item/kitchen/knife, /obj/item/kinetic_crusher, /obj/item/resonator, /obj/item/melee/transforming/cleaving_saw)
+ allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/spear, /obj/item/organ/regenerative_core/legion, /obj/item/kitchen/knife, /obj/item/kinetic_crusher, /obj/item/resonator, /obj/item/melee/cleaving_saw)
/obj/item/clothing/suit/space/hardsuit/berserker/Initialize()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 98f76e062e5..51ce2ba4e46 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -519,7 +519,7 @@
name = "Syndicate Assault"
basic_modules = list(
/obj/item/assembly/flash/cyborg,
- /obj/item/melee/transforming/energy/sword/cyborg,
+ /obj/item/melee/energy/sword/cyborg,
/obj/item/gun/energy/printer,
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/card/emag,
@@ -556,7 +556,7 @@
/obj/item/cautery,
/obj/item/surgicaldrill,
/obj/item/scalpel,
- /obj/item/melee/transforming/energy/sword/cyborg/saw,
+ /obj/item/melee/energy/sword/cyborg/saw,
/obj/item/roller/robo,
/obj/item/crowbar/cyborg,
/obj/item/extinguisher/mini,
diff --git a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm
index 2b3a37ef215..8948109f61f 100644
--- a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm
+++ b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm
@@ -5,7 +5,7 @@
icon_state = "grievous"
health = 150
maxHealth = 150
- baton_type = /obj/item/melee/transforming/energy/sword/saber
+ baton_type = /obj/item/melee/energy/sword/saber
base_speed = 4 //he's a fast fucker
var/block_chance = 50
weapon_force = 30
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 5d31eded154..0613b78b417 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -414,7 +414,7 @@
new /obj/item/toy/sword(Tsec)
if(ASSEMBLY_FIFTH_STEP)
- if(istype(I, /obj/item/melee/transforming/energy/sword/saber))
+ if(istype(I, /obj/item/melee/energy/sword/saber))
if(swordamt < 3)
if(!user.temporarilyRemoveItemFromInventory(I))
return
@@ -439,7 +439,7 @@
icon_state = initial(icon_state)
to_chat(user, span_notice("You unbolt [src]'s energy swords."))
for(var/IS in 1 to swordamt)
- new /obj/item/melee/transforming/energy/sword/saber(Tsec)
+ new /obj/item/melee/energy/sword/saber(Tsec)
//Firebot Assembly
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index ed3fb305d15..c09d24b4bcd 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -41,8 +41,8 @@ Difficulty: Medium
ranged_cooldown_time = 1.6 SECONDS
pixel_x = -16
base_pixel_x = -16
- crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
- loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator)
+ crusher_loot = list(/obj/item/melee/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
+ loot = list(/obj/item/melee/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
@@ -50,7 +50,7 @@ Difficulty: Medium
achievement_type = /datum/award/achievement/boss/blood_miner_kill
crusher_achievement_type = /datum/award/achievement/boss/blood_miner_crusher
score_achievement_type = /datum/award/score/blood_miner_score
- var/obj/item/melee/transforming/cleaving_saw/miner/miner_saw
+ var/obj/item/melee/cleaving_saw/miner/miner_saw
var/time_until_next_transform = 0
var/dashing = FALSE
var/dash_cooldown = 0
@@ -119,13 +119,13 @@ Difficulty: Medium
shoot_ka()
transform_weapon()
-/obj/item/melee/transforming/cleaving_saw/miner //nerfed saw because it is very murdery
+/obj/item/melee/cleaving_saw/miner //nerfed saw because it is very murdery
force = 6
- force_on = 10
+ open_force = 10
-/obj/item/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
+/obj/item/melee/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
target.add_stun_absorption("miner", 10, INFINITY)
- ..()
+ . = ..()
target.stun_absorption -= "miner"
/obj/projectile/kinetic/miner
@@ -260,15 +260,14 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/transform_weapon()
if(time_until_next_transform <= world.time)
- miner_saw.transform_cooldown = 0
- miner_saw.transform_weapon(src, TRUE)
- if(!miner_saw.active)
+ miner_saw.attack_self(src)
+ if(!miner_saw.is_open)
rapid_melee = 5 // 4 deci cooldown before changes, npcpool subsystem wait is 20, 20/4 = 5
else
rapid_melee = 3 // same thing but halved (slightly rounded up)
transform_stop_attack = TRUE
- icon_state = "miner[miner_saw.active ? "_transformed":""]"
- icon_living = "miner[miner_saw.active ? "_transformed":""]"
+ icon_state = "miner[miner_saw.is_open ? "_transformed":""]"
+ icon_living = "miner[miner_saw.is_open ? "_transformed":""]"
update_cooldowns(list(COOLDOWN_UPDATE_SET_TRANSFORM = rand(5 SECONDS, 10 SECONDS)))
/obj/effect/temp_visual/dir_setting/miner_death
diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm
index 9414eba70f3..750cf4dfab5 100644
--- a/code/modules/mob/living/simple_animal/hostile/pirate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm
@@ -25,7 +25,7 @@
unsuitable_atmos_damage = 7.5
speak_emote = list("yarrs")
loot = list(/obj/effect/mob_spawn/human/corpse/pirate,
- /obj/item/melee/transforming/energy/sword/pirate)
+ /obj/item/melee/energy/sword/pirate)
del_on_death = 1
faction = list("pirate")
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 9ff2a05464a..deee8229680 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -122,6 +122,10 @@
desc = "It's an expensive [current_skin] fountain pen. The nib is quite sharp."
/obj/item/pen/attack_self(mob/living/carbon/user)
+ . = ..()
+ if(.)
+ return
+
var/deg = input(user, "What angle would you like to rotate the pen head to? (1-360)", "Rotate Pen Head") as null|num
if(deg && (deg > 0 && deg <= 360))
degrees = deg
@@ -216,62 +220,60 @@
/obj/item/pen/edagger
attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") //these won't show up if the pen is off
attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
- sharpness = SHARP_EDGED
- var/on = FALSE
+ sharpness = SHARP_POINTY
+ /// The real name of our item when extended.
+ var/hidden_name = "energy dagger"
+ /// Whether or pen is extended
+ var/extended = FALSE
-/obj/item/pen/edagger/ComponentInitialize()
+/obj/item/pen/edagger/Initialize()
. = ..()
- AddComponent(/datum/component/butchering, 60, 100, 0, 'sound/weapons/blade1.ogg')
- AddElement(/datum/element/update_icon_updates_onmob)
-
-/obj/item/pen/edagger/get_sharpness()
- return on * sharpness
+ AddComponent(/datum/component/butchering, _speed = 6 SECONDS, _butcher_sound = 'sound/weapons/blade1.ogg')
+ AddComponent(/datum/component/transforming, \
+ force_on = 18, \
+ throwforce_on = 35, \
+ throw_speed_on = 4, \
+ sharpness_on = SHARP_EDGED, \
+ w_class_on = WEIGHT_CLASS_NORMAL)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
/obj/item/pen/edagger/suicide_act(mob/user)
. = BRUTELOSS
- if(on)
+ if(extended)
user.visible_message(span_suicide("[user] forcefully rams the pen into their mouth!"))
else
user.visible_message(span_suicide("[user] is holding a pen up to their mouth! It looks like [user.p_theyre()] trying to commit suicide!"))
attack_self(user)
-/obj/item/pen/edagger/attack_self(mob/living/user)
- if(on)
- on = FALSE
- force = initial(force)
- throw_speed = initial(throw_speed)
- w_class = initial(w_class)
- name = initial(name)
- hitsound = initial(hitsound)
- embedding = list(embed_chance = EMBED_CHANCE)
- throwforce = initial(throwforce)
- playsound(user, 'sound/weapons/saberoff.ogg', 5, TRUE)
- to_chat(user, span_warning("[src] can now be concealed."))
- else
- on = TRUE
- force = 18
- throw_speed = 4
- w_class = WEIGHT_CLASS_NORMAL
- name = "energy dagger"
- hitsound = 'sound/weapons/blade1.ogg'
- embedding = list(embed_chance = 100) //rule of cool
- throwforce = 35
- playsound(user, 'sound/weapons/saberon.ogg', 5, TRUE)
- to_chat(user, span_warning("[src] is now active."))
- updateEmbedding()
- update_appearance()
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Handles swapping their icon files to edagger related icon files -
+ * as they're supposed to look like a normal pen.
+ */
+/obj/item/pen/edagger/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
-/obj/item/pen/edagger/update_icon_state()
- if(on)
- icon_state = inhand_icon_state = "edagger"
+ extended = active
+ if(active)
+ name = hidden_name
+ icon_state = "edagger"
+ inhand_icon_state = "edagger"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ embedding = list(embed_chance = 100) // Rule of cool
else
- icon_state = initial(icon_state) //looks like a normal pen when off.
+ name = initial(name)
+ icon_state = initial(icon_state)
inhand_icon_state = initial(inhand_icon_state)
lefthand_file = initial(lefthand_file)
righthand_file = initial(righthand_file)
- return ..()
+ embedding = list(embed_chance = EMBED_CHANCE)
+
+ updateEmbedding()
+ balloon_alert(user, "[hidden_name] [active ? "active":"concealed"]")
+ playsound(user ? user : src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 5, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/pen/survival
name = "survival pen"
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index cbc9842ed8a..aad506791e1 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -548,7 +548,7 @@
GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list(
/obj/item/gun/energy/plasmacutter,
- /obj/item/melee/transforming/energy,
+ /obj/item/melee/energy,
/obj/item/dualsaber
)))
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 67a7261c104..a451fed469c 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -162,7 +162,7 @@
/datum/outfit/lavaland_syndicate/comms
name = "Lavaland Syndicate Comms Agent"
- r_hand = /obj/item/melee/transforming/energy/sword/saber
+ r_hand = /obj/item/melee/energy/sword/saber
mask = /obj/item/clothing/mask/chameleon/gps
suit = /obj/item/clothing/suit/armor/vest
diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm
index 0c0046dfe5d..710fcfcbe77 100644
--- a/code/modules/surgery/advanced/lobotomy.dm
+++ b/code/modules/surgery/advanced/lobotomy.dm
@@ -25,7 +25,7 @@
name = "perform lobotomy"
implements = list(
TOOL_SCALPEL = 85,
- /obj/item/melee/transforming/energy/sword = 55,
+ /obj/item/melee/energy/sword = 55,
/obj/item/kitchen/knife = 35,
/obj/item/shard = 25,
/obj/item = 20)
diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm
index a6630578d3b..1a4887b3830 100644
--- a/code/modules/surgery/coronary_bypass.dm
+++ b/code/modules/surgery/coronary_bypass.dm
@@ -23,7 +23,7 @@
name = "incise heart"
implements = list(
TOOL_SCALPEL = 90,
- /obj/item/melee/transforming/energy/sword = 45,
+ /obj/item/melee/energy/sword = 45,
/obj/item/kitchen/knife = 45,
/obj/item/shard = 25)
time = 16
diff --git a/code/modules/surgery/gastrectomy.dm b/code/modules/surgery/gastrectomy.dm
index a7b4af48f6c..5698aa85f5f 100644
--- a/code/modules/surgery/gastrectomy.dm
+++ b/code/modules/surgery/gastrectomy.dm
@@ -24,7 +24,7 @@
name = "remove lower duodenum"
implements = list(
TOOL_SCALPEL = 95,
- /obj/item/melee/transforming/energy/sword = 65,
+ /obj/item/melee/energy/sword = 65,
/obj/item/kitchen/knife = 45,
/obj/item/shard = 35)
time = 52
diff --git a/code/modules/surgery/hepatectomy.dm b/code/modules/surgery/hepatectomy.dm
index 1899f0deaf1..2d2de0dd1cf 100644
--- a/code/modules/surgery/hepatectomy.dm
+++ b/code/modules/surgery/hepatectomy.dm
@@ -23,7 +23,7 @@
name = "remove damaged liver section"
implements = list(
TOOL_SCALPEL = 95,
- /obj/item/melee/transforming/energy/sword = 65,
+ /obj/item/melee/energy/sword = 65,
/obj/item/kitchen/knife = 45,
/obj/item/shard = 35)
time = 52
diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm
index 730741c3eef..d122cce3546 100644
--- a/code/modules/surgery/lobectomy.dm
+++ b/code/modules/surgery/lobectomy.dm
@@ -22,7 +22,7 @@
name = "excise damaged lung node"
implements = list(
TOOL_SCALPEL = 95,
- /obj/item/melee/transforming/energy/sword = 65,
+ /obj/item/melee/energy/sword = 65,
/obj/item/kitchen/knife = 45,
/obj/item/shard = 35)
time = 42
diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm
index 7c455a1e942..466e6f55695 100644
--- a/code/modules/surgery/organic_steps.dm
+++ b/code/modules/surgery/organic_steps.dm
@@ -4,7 +4,7 @@
name = "make incision"
implements = list(
TOOL_SCALPEL = 100,
- /obj/item/melee/transforming/energy/sword = 75,
+ /obj/item/melee/energy/sword = 75,
/obj/item/kitchen/knife = 65,
/obj/item/shard = 45,
/obj/item = 30) // 30% success with any sharp item.
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index acd69fc0086..f9c0fbd35a7 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -244,7 +244,7 @@
/obj/item/organ/cyberimp/arm/esword
name = "arm-mounted energy blade"
desc = "An illegal and highly dangerous cybernetic implant that can project a deadly blade of concentrated energy."
- items_to_create = list(/obj/item/melee/transforming/energy/blade/hardlight)
+ items_to_create = list(/obj/item/melee/energy/blade/hardlight)
/obj/item/organ/cyberimp/arm/medibeam
name = "integrated medical beamgun"
@@ -283,7 +283,7 @@
/obj/item/organ/cyberimp/arm/combat
name = "combat cybernetics implant"
desc = "A powerful cybernetic implant that contains combat modules built into the user's arm."
- items_to_create = list(/obj/item/melee/transforming/energy/blade/hardlight, /obj/item/gun/medbeam, /obj/item/borg/stun, /obj/item/assembly/flash/armimplant)
+ items_to_create = list(/obj/item/melee/energy/blade/hardlight, /obj/item/gun/medbeam, /obj/item/borg/stun, /obj/item/assembly/flash/armimplant)
/obj/item/organ/cyberimp/arm/combat/Initialize()
. = ..()
diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm
index 192a8100c2b..f455824d35a 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -68,28 +68,39 @@
name = "searing tool"
desc = "It projects a high power laser used for medical applications."
icon = 'icons/obj/surgery.dmi'
- icon_state = "cautery_a"
+ icon_state = "e_cautery"
hitsound = 'sound/items/welder.ogg'
toolspeed = 0.7
light_system = MOVABLE_LIGHT
light_range = 1
light_color = COLOR_SOFT_RED
+/obj/item/cautery/advanced/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = force, \
+ throwforce_on = throwforce, \
+ hitsound_on = hitsound, \
+ w_class_on = w_class, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-/obj/item/cautery/advanced/attack_self(mob/user)
- playsound(get_turf(user), 'sound/weapons/tap.ogg', 50, TRUE)
- if(tool_behaviour == TOOL_CAUTERY)
- tool_behaviour = TOOL_DRILL
- balloon_alert(user, "lenses set to drill")
- icon_state = "surgicaldrill_a"
- else
- tool_behaviour = TOOL_CAUTERY
- balloon_alert(user, "lenses set to mend")
- icon_state = "cautery_a"
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Toggles between drill and cautery and gives feedback to the user.
+ */
+/obj/item/cautery/advanced/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ tool_behaviour = (active ? TOOL_DRILL : TOOL_CAUTERY)
+ balloon_alert(user, "lenses set to [active ? "drill" : "mend"]")
+ playsound(user ? user : src, 'sound/weapons/tap.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/cautery/advanced/examine()
. = ..()
- . += " It's set to [tool_behaviour == TOOL_CAUTERY ? "mending" : "drilling"] mode."
+ . += span_notice("It's set to [tool_behaviour == TOOL_CAUTERY ? "mending" : "drilling"] mode.")
/obj/item/surgicaldrill
name = "surgical drill"
@@ -251,7 +262,7 @@
name = "laser scalpel"
desc = "An advanced scalpel which uses laser technology to cut."
icon = 'icons/obj/surgery.dmi'
- icon_state = "scalpel_a"
+ icon_state = "e_scalpel"
hitsound = 'sound/weapons/blade1.ogg'
force = 16
toolspeed = 0.7
@@ -260,47 +271,74 @@
light_color = LIGHT_COLOR_GREEN
sharpness = SHARP_EDGED
+/obj/item/scalpel/advanced/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = force + 1, \
+ throwforce_on = throwforce, \
+ throw_speed_on = throw_speed, \
+ sharpness_on = sharpness, \
+ hitsound_on = hitsound, \
+ w_class_on = w_class, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
-/obj/item/scalpel/advanced/attack_self(mob/user)
- playsound(get_turf(user), 'sound/machines/click.ogg', 50, TRUE)
- if(tool_behaviour == TOOL_SCALPEL)
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Toggles between saw and scalpel and updates the light / gives feedback to the user.
+ */
+/obj/item/scalpel/advanced/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ if(active)
tool_behaviour = TOOL_SAW
- balloon_alert(user, "enabled bone-cutting mode")
set_light_range(2)
- force += 1 //we don't want to ruin sharpened stuff
- icon_state = "saw_a"
else
tool_behaviour = TOOL_SCALPEL
- balloon_alert(user, "disabled bone-cutting mode")
set_light_range(1)
- force -= 1
- icon_state = "scalpel_a"
+
+ balloon_alert(user, "[active ? "enabled" : "disabled"] bone-cutting mode")
+ playsound(user ? user : src, 'sound/machines/click.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/scalpel/advanced/examine()
. = ..()
- . += " It's set to [tool_behaviour == TOOL_SCALPEL ? "scalpel" : "saw"] mode."
+ . += span_notice("It's set to [tool_behaviour == TOOL_SCALPEL ? "scalpel" : "saw"] mode.")
/obj/item/retractor/advanced
name = "mechanical pinches"
desc = "An agglomerate of rods and gears."
icon = 'icons/obj/surgery.dmi'
- icon_state = "retractor_a"
+ icon_state = "adv_retractor"
toolspeed = 0.7
-/obj/item/retractor/advanced/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, TRUE)
- if(tool_behaviour == TOOL_RETRACTOR)
- tool_behaviour = TOOL_HEMOSTAT
- balloon_alert(user, "gears set to clamp")
- icon_state = "hemostat_a"
- else
- tool_behaviour = TOOL_RETRACTOR
- balloon_alert(user, "gears set to retract")
- icon_state = "retractor_a"
+/obj/item/retractor/advanced/Initialize()
+ . = ..()
+ AddComponent(/datum/component/transforming, \
+ force_on = force, \
+ throwforce_on = throwforce, \
+ hitsound_on = hitsound, \
+ w_class_on = w_class, \
+ clumsy_check = FALSE)
+ RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
+
+/*
+ * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
+ *
+ * Toggles between retractor and hemostat and gives feedback to the user.
+ */
+/obj/item/retractor/advanced/proc/on_transform(obj/item/source, mob/user, active)
+ SIGNAL_HANDLER
+
+ tool_behaviour = (active ? TOOL_HEMOSTAT : TOOL_RETRACTOR)
+ balloon_alert(user, "gears set to [active ? "clamp" : "retract"]")
+ playsound(user ? user : src, 'sound/items/change_drill.ogg', 50, TRUE)
+ return COMPONENT_NO_DEFAULT_MESSAGE
/obj/item/retractor/advanced/examine()
. = ..()
- . += " It resembles a [tool_behaviour == TOOL_RETRACTOR ? "retractor" : "hemostat"]."
+ . += span_notice("It resembles a [tool_behaviour == TOOL_RETRACTOR ? "retractor" : "hemostat"].")
/obj/item/shears
name = "amputation shears"
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index baa84431bd6..1baddb9f4b2 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -342,7 +342,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Bananium Energy Sword"
desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \
impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it."
- item = /obj/item/melee/transforming/energy/sword/bananium
+ item = /obj/item/melee/energy/sword/bananium
cost = 3
surplus = 0
purchasable_from = UPLINK_CLOWN_OPS
@@ -415,7 +415,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Energy Sword"
desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \
pocketed when inactive. Activating it produces a loud, distinctive noise."
- item = /obj/item/melee/transforming/energy/sword/saber
+ item = /obj/item/melee/energy/sword/saber
cost = 8
purchasable_from = ~UPLINK_CLOWN_OPS
@@ -2035,4 +2035,3 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 1
purchasable_from = UPLINK_CLOWN_OPS
illegal_tech = FALSE
-
diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi
index 97110a4c1b0..848aeb13fd6 100644
Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ
diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi
index f5024467798..5aa54e694c7 100644
Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ
diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi
index 9061d87a3e4..be49e1eb0eb 100644
Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ
diff --git a/icons/mob/inhands/equipment/shields_lefthand.dmi b/icons/mob/inhands/equipment/shields_lefthand.dmi
index f3eccfa321b..5edcaef0261 100644
Binary files a/icons/mob/inhands/equipment/shields_lefthand.dmi and b/icons/mob/inhands/equipment/shields_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/shields_righthand.dmi b/icons/mob/inhands/equipment/shields_righthand.dmi
index 92ad9ed3ff4..af80dfeccc3 100644
Binary files a/icons/mob/inhands/equipment/shields_righthand.dmi and b/icons/mob/inhands/equipment/shields_righthand.dmi differ
diff --git a/icons/mob/inhands/equipment/tools_lefthand.dmi b/icons/mob/inhands/equipment/tools_lefthand.dmi
index 7d6bd6fa3b7..aa47817fc26 100644
Binary files a/icons/mob/inhands/equipment/tools_lefthand.dmi and b/icons/mob/inhands/equipment/tools_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/tools_righthand.dmi b/icons/mob/inhands/equipment/tools_righthand.dmi
index 3af63b59e6e..41b6b151a7f 100644
Binary files a/icons/mob/inhands/equipment/tools_righthand.dmi and b/icons/mob/inhands/equipment/tools_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/axes_lefthand.dmi b/icons/mob/inhands/weapons/axes_lefthand.dmi
index 447f6116576..566180fe5ff 100644
Binary files a/icons/mob/inhands/weapons/axes_lefthand.dmi and b/icons/mob/inhands/weapons/axes_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/axes_righthand.dmi b/icons/mob/inhands/weapons/axes_righthand.dmi
index d8801bf75bd..94008a727a0 100644
Binary files a/icons/mob/inhands/weapons/axes_righthand.dmi and b/icons/mob/inhands/weapons/axes_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/melee_lefthand.dmi b/icons/mob/inhands/weapons/melee_lefthand.dmi
index 36b3abfeddc..d255bf1e854 100644
Binary files a/icons/mob/inhands/weapons/melee_lefthand.dmi and b/icons/mob/inhands/weapons/melee_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/melee_righthand.dmi b/icons/mob/inhands/weapons/melee_righthand.dmi
index be564b93f9e..4ca3e77b672 100644
Binary files a/icons/mob/inhands/weapons/melee_righthand.dmi and b/icons/mob/inhands/weapons/melee_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi
index 293976209ea..2d3bf918871 100644
Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi
index a7bd228ad0d..12e85cfe08d 100644
Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ
diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi
index 19e2e2c7a24..57befb675a1 100644
Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 7a81325d0b8..a19e15b20df 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi
index 589c5ee0a27..dd65e49104f 100644
Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ
diff --git a/icons/obj/shields.dmi b/icons/obj/shields.dmi
index 47bdc940d28..c0a2d6a2993 100644
Binary files a/icons/obj/shields.dmi and b/icons/obj/shields.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 9d62d4cc580..e1a163b930c 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi
index ebc2ec637a5..8bfdd660691 100644
Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ
diff --git a/icons/obj/transforming_energy.dmi b/icons/obj/transforming_energy.dmi
index 2fd2b7ec401..04e9b3e168a 100644
Binary files a/icons/obj/transforming_energy.dmi and b/icons/obj/transforming_energy.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index c86eb7b825e..a175b92d5a6 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -598,6 +598,7 @@
#include "code\datums\components\tether.dm"
#include "code\datums\components\thermite.dm"
#include "code\datums\components\tippable.dm"
+#include "code\datums\components\transforming.dm"
#include "code\datums\components\trapdoor.dm"
#include "code\datums\components\twohanded.dm"
#include "code\datums\components\udder.dm"
@@ -1347,7 +1348,6 @@
#include "code\game\objects\items\implants\implantuplink.dm"
#include "code\game\objects\items\melee\energy.dm"
#include "code\game\objects\items\melee\misc.dm"
-#include "code\game\objects\items\melee\transforming.dm"
#include "code\game\objects\items\robot\ai_upgrades.dm"
#include "code\game\objects\items\robot\robot_items.dm"
#include "code\game\objects\items\robot\robot_parts.dm"