From 22f035f9e82add27c17709732b8828193b783e97 Mon Sep 17 00:00:00 2001
From: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Date: Tue, 7 May 2024 11:50:19 -0400
Subject: [PATCH] Standardizes & documents Attack Chain. Telekinesis cleanup
(#10903)
* https://github.com/tgstation/tgstation/pull/46391
* https://github.com/tgstation/tgstation/pull/49471
* https://github.com/tgstation/tgstation/pull/54475
* https://github.com/tgstation/tgstation/pull/54589
* https://github.com/tgstation/tgstation/pull/54642
* cleanup
* 515
* woops
---
beestation.dme | 5 +-
.../{ => signals_atom}/signals_atom.dm | 26 ---
.../signals_atom/signals_atom_attack.dm | 27 ++++
.../dcs/signals/signals_mob/signals_human.dm | 2 -
.../dcs/signals/signals_mob/signals_mob.dm | 6 -
.../signals/signals_mob/signals_mobattack.dm | 20 +++
.../signals_obj/signals_item/signals_item.dm | 8 -
.../signals_item/signals_itemattack.dm | 19 +++
code/_onclick/click.dm | 149 +++++++++---------
code/_onclick/item_attack.dm | 100 ++++++++----
code/_onclick/observer.dm | 2 +-
code/_onclick/other_mobs.dm | 14 +-
code/_onclick/telekinesis.dm | 79 ++++++----
code/datums/components/buffer.dm | 4 +-
code/datums/components/butchering.dm | 6 +-
code/datums/components/deployable.dm | 2 +-
code/datums/components/embedded.dm | 2 +-
code/datums/components/storage/storage.dm | 10 +-
code/datums/components/uplink.dm | 2 +-
code/game/machinery/cell_charger.dm | 1 +
code/game/objects/items/RPD.dm | 2 +-
code/game/objects/items/robot/ai_upgrades.dm | 19 +--
code/game/objects/items/teleportation.dm | 2 +-
code/game/objects/items/theft_tools.dm | 4 +-
.../objects/structures/beds_chairs/chair.dm | 6 +-
code/game/objects/structures/bedsheet_bin.dm | 1 +
.../structures/crates_lockers/closets.dm | 3 +-
code/game/objects/structures/extinguisher.dm | 7 +-
code/game/objects/structures/fireaxe.dm | 7 +-
code/game/objects/structures/tables_racks.dm | 4 +-
code/game/objects/structures/window.dm | 1 +
code/game/turfs/turf.dm | 2 +-
.../antagonists/wizard/equipment/artefact.dm | 22 +--
code/modules/hydroponics/hydroitemdefines.dm | 22 +--
code/modules/mining/equipment/resonator.dm | 2 +-
.../mob/living/silicon/silicon_defense.dm | 2 +-
.../living/simple_animal/hostile/hostile.dm | 3 +-
code/modules/mob/mob.dm | 3 +
code/modules/paperwork/filingcabinet.dm | 6 +-
code/modules/power/lighting/light.dm | 4 +-
.../modules/power/lighting/light_construct.dm | 13 +-
code/modules/power/singularity/boh_tear.dm | 12 +-
code/modules/power/singularity/singularity.dm | 60 +++++--
code/modules/power/supermatter/supermatter.dm | 15 +-
code/modules/power/tesla/energy_ball.dm | 17 +-
code/modules/research/stock_parts.dm | 2 +-
46 files changed, 442 insertions(+), 283 deletions(-)
rename code/__DEFINES/dcs/signals/{ => signals_atom}/signals_atom.dm (87%)
create mode 100644 code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
create mode 100644 code/__DEFINES/dcs/signals/signals_mob/signals_mobattack.dm
create mode 100644 code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_itemattack.dm
diff --git a/beestation.dme b/beestation.dme
index c7f5f129a5834..99c4fe7ff66d5 100644
--- a/beestation.dme
+++ b/beestation.dme
@@ -196,7 +196,8 @@
#include "code\__DEFINES\dcs\helpers.dm"
#include "code\__DEFINES\dcs\signals.dm"
#include "code\__DEFINES\dcs\signals\signals_area.dm"
-#include "code\__DEFINES\dcs\signals\signals_atom.dm"
+#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom.dm"
+#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_attack.dm"
#include "code\__DEFINES\dcs\signals\signals_global.dm"
#include "code\__DEFINES\dcs\signals\signals_lighting.dm"
#include "code\__DEFINES\dcs\signals\signals_movable.dm"
@@ -212,6 +213,7 @@
#include "code\__DEFINES\dcs\signals\signals_mob\signals_human.dm"
#include "code\__DEFINES\dcs\signals\signals_mob\signals_living.dm"
#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob.dm"
+#include "code\__DEFINES\dcs\signals\signals_mob\signals_mobattack.dm"
#include "code\__DEFINES\dcs\signals\signals_mob\signals_silicon.dm"
#include "code\__DEFINES\dcs\signals\signals_mob\signals_simplemob.dm"
#include "code\__DEFINES\dcs\signals\signals_mob\signals_xenobiology.dm"
@@ -223,6 +225,7 @@
#include "code\__DEFINES\dcs\signals\signals_obj\signals_item\signals_food.dm"
#include "code\__DEFINES\dcs\signals\signals_obj\signals_item\signals_grenade.dm"
#include "code\__DEFINES\dcs\signals\signals_obj\signals_item\signals_implant.dm"
+#include "code\__DEFINES\dcs\signals\signals_obj\signals_item\signals_itemattack.dm"
#include "code\__DEFINES\dcs\signals\signals_obj\signals_item\signals_item.dm"
#include "code\__DEFINES\dcs\signals\signals_obj\signals_item\signals_organs.dm"
#include "code\__DEFINES\dcs\signals\signals_obj\signals_machine\signals_airlock.dm"
diff --git a/code/__DEFINES/dcs/signals/signals_atom.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom.dm
similarity index 87%
rename from code/__DEFINES/dcs/signals/signals_atom.dm
rename to code/__DEFINES/dcs/signals/signals_atom/signals_atom.dm
index 18c0e97b8ed38..74d1457ccd7ce 100644
--- a/code/__DEFINES/dcs/signals/signals_atom.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom.dm
@@ -5,12 +5,6 @@
// /atom signals
///from base of atom/proc/Initialize(mapload): sent any time a new atom is created
#define COMSIG_ATOM_CREATED "atom_created"
-///! from base of atom/attackby(): (/obj/item, /mob/living, params)
-#define COMSIG_PARENT_ATTACKBY "atom_attackby"
- ///! Return this in response if you don't want afterattack to be called
- #define COMPONENT_NO_AFTERATTACK 1
-///! from base of atom/attack_hulk(): (/mob/living/carbon/human)
-#define COMSIG_ATOM_HULK_ATTACK "hulk_attack"
/// from base of atom/examine(): (/mob, list/examine_text)
#define COMSIG_PARENT_EXAMINE "atom_examine"
/// from base of atom/get_examine_name(): (/mob, list/overrides)
@@ -20,8 +14,6 @@
#define EXAMINE_POSITION_BEFORE (1<<1)
//End positions
#define COMPONENT_EXNAME_CHANGED (1<<0)
-//from base of atom/attack_basic_mob(): (/mob/user)
-#define COMSIG_ATOM_ATTACK_BASIC_MOB "attack_basic_mob"
/// from base of [/atom/proc/update_appearance]: (updates)
#define COMSIG_ATOM_UPDATE_APPEARANCE "atom_update_appearance"
@@ -133,24 +125,6 @@
/// called when an atom stops orbiting another atom: (atom)
#define COMSIG_ATOM_ORBIT_STOP "atom_orbit_stop"
-/////////////////
-/* Attack signals. They should share the returned flags, to standardize the attack chain. */
-/// tool_act -> pre_attack -> target.attackby (item.attack) -> afterattack
- ///Ends the attack chain. If sent early might cause posterior attacks not to happen.
- #define COMPONENT_CANCEL_ATTACK_CHAIN (1<<0)
- ///Skips the specific attack step, continuing for the next one to happen.
- #define COMPONENT_SKIP_ATTACK (1<<1)
-
-///! from base of atom/attack_ghost(): (mob/dead/observer/ghost)
-#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost"
-///! from base of atom/attack_hand(): (mob/user)
-#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand"
-///! from base of atom/attack_paw(): (mob/user)
-#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw"
- //works on all 3.
- #define COMPONENT_NO_ATTACK_HAND 1
-///! from base of atom/animal_attack(): (/mob/user)
-#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal"
///This signal return value bitflags can be found in __DEFINES/misc.dm
///called for each movable in a turf contents on /turf/attempt_z_impact(): (atom/movable/A, levels)
#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact"
diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
new file mode 100644
index 0000000000000..91094391ed1d1
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
@@ -0,0 +1,27 @@
+// Atom attack signals. Format:
+// When the signal is called: (signal arguments)
+// All signals send the source datum of the signal as the first argument
+
+///from base of atom/attackby(): (/obj/item, /mob/living, params)
+#define COMSIG_PARENT_ATTACKBY "atom_attackby"
+///Return this in response if you don't want afterattack to be called
+ #define COMPONENT_NO_AFTERATTACK (1<<0)
+///from base of atom/attack_hulk(): (/mob/living/carbon/human)
+#define COMSIG_ATOM_HULK_ATTACK "hulk_attack"
+///from base of atom/animal_attack(): (/mob/user)
+#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal"
+//from base of atom/attack_basic_mob(): (/mob/user)
+#define COMSIG_ATOM_ATTACK_BASIC_MOB "attack_basic_mob"
+
+/* Attack signals. They should share the returned flags, to standardize the attack chain. */
+/// tool_act -> pre_attack -> target.attackby (item.attack) -> afterattack
+ ///Ends the attack chain. If sent early might cause posterior attacks not to happen.
+ #define COMPONENT_CANCEL_ATTACK_CHAIN (1<<0)
+ ///Skips the specific attack step, continuing for the next one to happen.
+ #define COMPONENT_SKIP_ATTACK (1<<1)
+///from base of atom/attack_ghost(): (mob/dead/observer/ghost)
+#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost"
+///from base of atom/attack_hand(): (mob/user)
+#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand"
+///from base of atom/attack_paw(): (mob/user)
+#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw"
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_human.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_human.dm
index 4d951dcbfe563..9c57150679f92 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_human.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_human.dm
@@ -3,8 +3,6 @@
// All signals send the source datum of the signal as the first argument
// /mob/living/carbon/human signals
-#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //! from mob/living/carbon/human/UnarmedAttack(): (atom/target)
-#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //! from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //! Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
#define COMSIG_HUMAN_ATTACKED "carbon_attacked" //hit by something that checks shields.
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob.dm
index aa45c9cd1ce71..0ef03a089e156 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob.dm
@@ -34,17 +34,11 @@
#define COMSIG_MOB_RECEIVE_ARTIFACT "mob_receive_artifact" //
#define COMPONENT_BLOCK_ARTIFACT 1
#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //! from base of mob/create_mob_hud(): ()
-#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //! from base of
#define COMSIG_MOB_ATTACK_HAND_TURF "mob_attack_hand_turf" //! from base of turf/attack_hand
#define COMSIG_MOB_HAND_ATTACKED "mob_hand_attacked" //! from base of
-#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" //! from base of /obj/item/attack(): (mob/M, mob/user)
- #define COMPONENT_ITEM_NO_ATTACK 1
-#define COMSIG_MOB_ITEM_ATTACKBY "mob_item_attackby" //! from base of /obj/item/attack(): (mob/user, src)
#define COMSIG_MOB_EQUIPPED_ITEM "mob_equipped_item" //! from base of /item/equipped(): (/mob/user, /obj/item, slot)
#define COMSIG_MOB_DROPPED_ITEM "mob_dropped_item" //! from base of /item/dropped(): (/mob/user, /obj/item, loc)
#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" //! from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone)
-#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //! from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
-#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //! from base of mob/RangedAttack(): (atom/A, params)
#define COMSIG_MOB_THROW "mob_throw" //! from base of /mob/throw_item(): (atom/target)
#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //! from base of /mob/update_sight(): ()
#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/target)
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mobattack.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mobattack.dm
new file mode 100644
index 0000000000000..3748b57a5271d
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mobattack.dm
@@ -0,0 +1,20 @@
+// Format:
+// When the signal is called: (signal arguments)
+// All signals send the source datum of the signal as the first argument
+
+/* Attack signals. They should share the returned flags, to standardize the attack chain. */
+
+///from base of atom/attack_hand(): (mob/user)
+#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand"
+///from base of /obj/item/attack(): (mob/M, mob/user)
+#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack"
+///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
+#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack"
+///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proxiumity_flag, click_parameters)
+#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted"
+///from base of mob/RangedAttack(): (atom/A, params)
+#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged"
+///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
+#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack"
+///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
+#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack"
diff --git a/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_item.dm b/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_item.dm
index fbed54f2b0d97..2f74eb1b263fa 100644
--- a/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_item.dm
+++ b/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_item.dm
@@ -3,14 +3,6 @@
// All signals send the source datum of the signal as the first argument
// /obj/item signals
-#define COMSIG_ITEM_ATTACK "item_attack" //! from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
-#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //! from base of obj/item/attack_self(): (/mob)
- #define COMPONENT_NO_INTERACT 1
-#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //! from base of obj/item/attack_obj(): (/obj, /mob)
- #define COMPONENT_NO_ATTACK_OBJ 1
-#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //! from base of obj/item/pre_attack(): (atom/target, mob/user, params)
- #define COMPONENT_NO_ATTACK 1
-#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //! from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, params)
///from base of obj/item/equipped(): (/mob/equipper, slot)
#define COMSIG_ITEM_EQUIPPED "item_equip"
///from base of obj/item/on_grind(): ())
diff --git a/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_itemattack.dm b/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_itemattack.dm
new file mode 100644
index 0000000000000..dc127a0a0714f
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_obj/signals_item/signals_itemattack.dm
@@ -0,0 +1,19 @@
+// Format:
+// When the signal is called: (signal arguments)
+// All signals send the source datum of the signal as the first argument
+
+/* Attack signals. They should share the returned flags, to standardize the attack chain. */
+///from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
+#define COMSIG_ITEM_ATTACK "item_attack"
+
+#define COMSIG_MOB_ITEM_ATTACKBY "item_attackby"
+///from base of obj/item/attack_self(): (/mob)
+#define COMSIG_ITEM_ATTACK_SELF "item_attack_self"
+///from base of obj/item/attack_obj(): (/obj, /mob)
+#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj"
+///from base of obj/item/pre_attack(): (atom/target, mob/user, params)
+#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack"
+///from base of obj/item/afterattack(): (atom/target, mob/user, params)
+#define COMSIG_ITEM_AFTERATTACK "item_afterattack"
+///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, params)
+#define COMSIG_ITEM_ATTACK_QDELETED "item_attack_qdeleted"
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 37ea04ee9d918..a13f706c0df79 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -29,15 +29,15 @@
adj += S.nextmove_adjust()
next_move = world.time + ((num + adj)*mod)
-/*
- Before anything else, defer these calls to a per-mobtype handler. This allows us to
- remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
-
- Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however,
- that's a lot of code duplication and is hard to maintain.
-
- Note that this proc can be overridden, and is in the case of screen objects.
-*/
+/**
+ * Before anything else, defer these calls to a per-mobtype handler. This allows us to
+ * remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
+ *
+ * Alternately, you could hardcode every mob's variation in a flat [/mob/proc/ClickOn] proc; however,
+ * that's a lot of code duplication and is hard to maintain.
+ *
+ * Note that this proc can be overridden, and is in the case of screen objects.
+ */
/atom/Click(location,control,params)
if(flags_1 & INITIALIZED_1)
SEND_SIGNAL(src, COMSIG_CLICK, location, control, params, usr)
@@ -51,19 +51,19 @@
if(flags_1 & INITIALIZED_1)
usr.MouseWheelOn(src, delta_x, delta_y, params)
-/*
- Standard mob ClickOn()
- Handles exceptions: Buildmode, middle click, modified clicks, mech actions
-
- After that, mostly just check your state, check whether you're holding an item,
- check whether you're adjacent to the target, then pass off the click to whoever
- is receiving it.
- The most common are:
- * mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves
- * atom/attackby(item,user) - used only when adjacent
- * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent
- * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
-*/
+/**
+ * Standard mob ClickOn()
+ * Handles exceptions: Buildmode, middle click, modified clicks, mech actions
+ *
+ * After that, mostly just check your state, check whether you're holding an item,
+ * check whether you're adjacent to the target, then pass off the click to whoever
+ * is receiving it.
+ * The most common are:
+ * * [mob/proc/UnarmedAttack] (atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves
+ * * [atom/proc/attackby] (item,user) - used only when adjacent
+ * * [obj/item/proc/afterattack] (atom,user,adjacent,params) - used both ranged and adjacent
+ * * [mob/proc/RangedAttack] (atom,params) - used only ranged, only used for tk and laser eyes but could be changed
+ */
/mob/proc/ClickOn( atom/A, params )
if(world.time <= next_click)
return
@@ -161,7 +161,7 @@
else
RangedAttack(A,params)
-//Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it
+/// Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it
/atom/proc/IsObscured()
SHOULD_BE_PURE(TRUE)
if(!isturf(loc)) //This only makes sense for things directly on turfs for now
@@ -180,9 +180,11 @@
return TRUE
return FALSE
+/**
+ * A backwards depth-limited breadth-first-search to see if the target is
+ * logically "in" anything adjacent to us.
+ */
/atom/movable/proc/CanReach(atom/ultimate_target, obj/item/tool, view_only = FALSE)
- // A backwards depth-limited breadth-first-search to see if the target is
- // logically "in" anything adjacent to us.
var/list/direct_access = DirectAccess()
var/depth = 1 + (view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH)
@@ -247,60 +249,61 @@
return
qdel(dummy)
-// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
+/// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
return
-/*
- Translates into attack_hand, etc.
-
- Note: proximity_flag here is used to distinguish between normal usage (flag=1),
- and usage when clicking on things telekinetically (flag=0). This proc will
- not be called at ranged except with telekinesis.
-
- proximity_flag is not currently passed to attack_hand, and is instead used
- in human click code to allow glove touches only at melee range.
-*/
+/**
+ * Translates into [atom/proc/attack_hand], etc.
+ *
+ * Note: proximity_flag here is used to distinguish between normal usage (flag=1),
+ * and usage when clicking on things telekinetically (flag=0). This proc will
+ * not be called at ranged except with telekinesis.
+ *
+ * proximity_flag is not currently passed to attack_hand, and is instead used
+ * in human click code to allow glove touches only at melee range.
+ */
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
return
-/*
- Ranged unarmed attack:
-
- This currently is just a default for all mobs, involving
- laser eyes and telekinesis. You could easily add exceptions
- for things like ranged glove touches, spitting alien acid/neurotoxin,
- animals lunging, etc.
-*/
+/**
+ * Ranged unarmed attack:
+ *
+ * This currently is just a default for all mobs, involving
+ * laser eyes and telekinesis. You could easily add exceptions
+ * for things like ranged glove touches, spitting alien acid/neurotoxin,
+ * animals lunging, etc.
+ */
/mob/proc/RangedAttack(atom/A, params)
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_RANGED, A, params)
-/*
- Restrained ClickOn
- Used when you are handcuffed and click things.
- Not currently used by anything but could easily be.
-*/
+/**
+ * Restrained ClickOn
+ *
+ * Used when you are handcuffed and click things.
+ * Not currently used by anything but could easily be.
+ */
/mob/proc/RestrainedClickOn(atom/A)
return
/**
- * Middle click
- * *Mainly used for swapping hands
- */
+ * Middle click
+ * Mainly used for swapping hands
+ */
/mob/proc/MiddleClickOn(atom/A)
. = SEND_SIGNAL(src, COMSIG_MOB_MIDDLECLICKON, A)
if(. & COMSIG_MOB_CANCEL_CLICKON)
return
swap_hand()
-/*
- Shift click
- For most mobs, examine.
- This is overridden in ai.dm
-*/
+/**
+ * Shift click
+ * For most mobs, examine.
+ * This is overridden in ai.dm
+ */
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
@@ -310,11 +313,10 @@
user.examinate(src)
return
-/*
- Ctrl click
- For most objects, pull
-*/
-
+/**
+ * Ctrl click
+ * For most objects, pull
+ */
/mob/proc/CtrlClickOn(atom/A)
A.CtrlClick(src)
return
@@ -343,10 +345,10 @@
A.CtrlClick(src) // this assumes you did CtrlClick instead of MiddleClick
return
-/*
- Alt click
- Unused except for AI
-*/
+/**
+ * Alt click
+ * Unused except for AI
+ */
/mob/proc/AltClickOn(atom/A)
. = SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, A)
if(. & COMSIG_MOB_CANCEL_CLICKON)
@@ -360,7 +362,7 @@
user.listed_turf = T
user.set_stat_tab(T.name)
-// Use this instead of /mob/proc/AltClickOn(atom/A) where you only want turf content listing without additional atom alt-click interaction
+/// Use this instead of [/mob/proc/AltClickOn] where you only want turf content listing without additional atom alt-click interaction
/atom/proc/AltClickNoInteract(mob/user, atom/A)
var/turf/T = get_turf(A)
if(T && user.TurfAdjacent(T))
@@ -370,10 +372,10 @@
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
-/*
- Control+Shift click
- Used for AI and Give code
-*/
+/**
+ * Control+Shift click
+ * Used for AI and Give code
+ */
/mob/proc/CtrlShiftClickOn(atom/A)
A.CtrlShiftClick(src)
return
@@ -408,7 +410,7 @@
LE.preparePixelProjectile(A, src, params)
LE.fire()
-// Simple helper to face what you clicked on, in case it should be needed in more than one place
+/// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(atom/A)
if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y )
return
@@ -481,8 +483,7 @@
click_turf.Click(click_turf, control, list2params(modifiers))
. = 1
-/* MouseWheelOn */
-
+/// MouseWheelOn
/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params)
SEND_SIGNAL(src, COMSIG_MOB_MOUSE_SCROLL_ON, A, delta_x, delta_y, params)
if (!client)
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 4f6d538f0b9ef..1478721cd627f 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -1,31 +1,59 @@
-
+/**
+ * This is the proc that handles the order of an item_attack.
+ *
+ * The order of procs called is:
+ * * [/atom/proc/tool_act] on the target. If it returns TRUE, the chain will be stopped.
+ * * [/obj/item/proc/pre_attack] on src. If this returns TRUE, the chain will be stopped.
+ * * [/atom/proc/attackby] on the target. If it returns TRUE, the chain will be stopped.
+ * * [/obj/item/proc/afterattack]. The return value does not matter.
+ */
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
- if(!tool_attack_chain(user, target) && pre_attack(target, user, params))
- // Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
- var/resolved = target.attackby(src, user, params)
- if(!resolved && target && !QDELETED(src))
- afterattack(target, user, 1, params)
-
-//Checks if the item can work as a tool, calling the appropriate tool behavior on the target
-/obj/item/proc/tool_attack_chain(mob/user, atom/target)
- if(!tool_behaviour)
- return FALSE
-
- return target.tool_act(user, src, tool_behaviour)
+ if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
+ return TRUE
+ if(pre_attack(target, user, params))
+ return TRUE
+ if(target.attackby(src,user, params))
+ return TRUE
+ if(QDELETED(src))
+ stack_trace("An item got deleted while performing an item attack and did not stop melee_attack_chain.")
+ return TRUE
+ if(QDELETED(target))
+ stack_trace("The target of an item attack got deleted and melee_attack_chain was not stopped.")
+ return TRUE
+ return afterattack(target, user, TRUE, params)
-// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
+/// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
- if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT)
- return
+ if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return TRUE
interact(user)
+/**
+ * Called on the item before it hits something
+ *
+ * Arguments:
+ * * atom/A - The atom about to be hit
+ * * mob/living/user - The mob doing the htting
+ * * params - click params such as alt/shift etc
+ *
+ * See: [/obj/item/proc/melee_attack_chain]
+ */
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
- if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK)
- return FALSE
- return TRUE //return FALSE to avoid calling attackby after this proc does stuff
-
-// No comment
+ if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return TRUE
+ return FALSE //return TRUE to avoid calling attackby after this proc does stuff
+
+/**
+ * Called on an object being hit by an item
+ *
+ * Arguments:
+ * * obj/item/W - The item hitting this atom
+ * * mob/user - The wielder of this item
+ * * params - click params such as alt/shift etc
+ *
+ * See: [/obj/item/proc/melee_attack_chain]
+ */
/atom/proc/attackby(obj/item/W, mob/user, params)
if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
@@ -52,10 +80,20 @@
return
return I.attack(src, user)
-
+/**
+ * Called from [/mob/living/attackby]
+ *
+ * Arguments:
+ * * mob/living/M - The mob being hit by this item
+ * * mob/living/user - The mob hitting with this item
+ */
/obj/item/proc/attack(mob/living/M, mob/living/user)
- if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
+ var/signal_return = SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user)
+ if(signal_return & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return TRUE
+ if(signal_return & COMPONENT_SKIP_ATTACK)
return
+
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
SEND_SIGNAL(M, COMSIG_MOB_ITEM_ATTACKBY, user, src)
@@ -100,9 +138,9 @@
add_fingerprint(user)
-//the equivalent of the standard version of attack() but for object targets.
+/// The equivalent of the standard version of [/obj/item/proc/attack] but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user)
- if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
+ if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return
if(item_flags & NOBLUDGEON)
return
@@ -110,6 +148,7 @@
user.do_attack_animation(O)
O.attacked_by(src, user)
+/// Called from [/obj/item/proc/attack_obj] and [/obj/item/proc/attack] if the attack succeeds
/atom/proc/attacked_by()
return
@@ -150,8 +189,15 @@
else
return ..()
-// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
-// Click parameters is the params string from byond Click() code, see that documentation.
+/**
+ * Last proc in the [/obj/item/proc/melee_attack_chain]
+ *
+ * Arguments:
+ * * atom/target - The thing that was hit
+ * * mob/user - The mob doing the hitting
+ * * proximity_flag - is 1 if this afterattack was called on something adjacent, in your square, or on your person.
+ * * click_parameters - is the params string from byond [/atom/proc/Click] code, see that documentation.
+ */
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, src, proximity_flag, click_parameters)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index deb9ec5137160..899255956d71c 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -47,7 +47,7 @@
// Oh by the way this didn't work with old click code which is why clicking shit didn't spam you
/atom/proc/attack_ghost(mob/dead/observer/user)
- if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_GHOST, user) & COMPONENT_NO_ATTACK_HAND)
+ if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_GHOST, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
if(user.client)
if(user.gas_scan && atmosanalyzer_scan(user, src))
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index e2a4f96ce9e32..21bd7205bf3f4 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -28,12 +28,12 @@
SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A)
A.attack_hand(src)
-//Return TRUE to cancel other attack hand effects that respect it.
+/// Return TRUE to cancel other attack hand effects that respect it.
/atom/proc/attack_hand(mob/user)
. = FALSE
if(!(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND))
add_fingerprint(user)
- if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_NO_ATTACK_HAND)
+ if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
. = TRUE
if(interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND)
. = _try_interact(user)
@@ -95,14 +95,16 @@
/mob/living/carbon/human/RangedAttack(atom/A, mouseparams)
. = ..()
+ if(.)
+ return
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
- return
+ return TRUE
if(isturf(A) && get_dist(src,A) <= 1)
- src.Move_Pulled(A)
- return
+ Move_Pulled(A)
+ return TRUE
/*
Animals & All Unspecified
@@ -134,7 +136,7 @@
A.attack_paw(src)
/atom/proc/attack_paw(mob/user)
- if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user) & COMPONENT_NO_ATTACK_HAND)
+ if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
return FALSE
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 095fc5bb1f8ef..3d21335141266 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -4,52 +4,68 @@
This needs more thinking out, but I might as well.
*/
-/*
- Telekinetic attack:
-
- By default, emulate the user's unarmed attack
-*/
-
#define TK_MAXRANGE 15
+/**
+ * Telekinesis attack act, happens when the TK user clicks on a non-adjacent target in range.
+ *
+ * * By default, emulates the user's unarmed attack.
+ * * Called indirectly by the `COMSIG_MOB_ATTACK_RANGED` signal.
+ * * Returns `COMPONENT_CANCEL_ATTACK_CHAIN` when it performs any action, to further acts on the attack chain.
+ */
/atom/proc/attack_tk(mob/user)
if(user.stat || !tkMaxRangeCheck(user, src))
return
new /obj/effect/temp_visual/telekinesis(get_turf(src))
- user.UnarmedAttack(src,0) // attack_hand, attack_paw, etc
add_hiddenprint(user)
- return
+ user.UnarmedAttack(src, FALSE) // attack_hand, attack_paw, etc
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/attack_tk(mob/user)
if(user.stat)
return
if(anchored)
return ..()
- attack_tk_grab(user)
+ return attack_tk_grab(user)
+/obj/item/attack_tk(mob/user)
+ if(user.stat)
+ return
+ return attack_tk_grab(user)
+
+/**
+ * Telekinesis object grab act.
+ *
+ * * Called by `/obj/attack_tk()`.
+ * * Returns `COMPONENT_CANCEL_ATTACK_CHAIN` when it performs any action, to further acts on the attack chain.
+ */
/obj/proc/attack_tk_grab(mob/user)
var/obj/item/tk_grab/O = new(src)
O.tk_user = user
- if(O.focus_object(src))
- user.put_in_active_hand(O)
- add_hiddenprint(user)
+ if(!O.focus_object(src))
+ return
+ user.put_in_active_hand(O)
+ add_hiddenprint(user)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/mob/attack_tk(mob/user)
return
-/*
- This is similar to item attack_self, but applies to anything
- that you can grab with a telekinetic grab.
-
- It is used for manipulating things at range, for example, opening and closing closets.
- There are not a lot of defaults at this time, add more where appropriate.
-*/
-
+/**
+ * Telekinesis item attack_self act.
+ *
+ * * This is similar to item attack_self, but applies to anything that you can grab with a telekinetic grab.
+ * * It is used for manipulating things at range, for example, opening and closing closets..
+ * * Defined at the `/atom` level but only used at the `/obj/item` one.
+ * * Returns `COMPONENT_CANCEL_ATTACK_CHAIN` when it performs any action, to further acts on the attack chain.
+ */
/atom/proc/attack_self_tk(mob/user)
return
+
/obj/item/attack_self_tk(mob/user)
- attack_self(user)
+ if(attack_self(user))
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/*
@@ -109,25 +125,31 @@
/obj/item/tk_grab/attack_self(mob/user)
if(!focus)
return
- if(QDELETED(focus))
+ if(QDELING(focus))
qdel(src)
return
- focus.attack_self_tk(user)
+ if(focus.attack_self_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ . = TRUE
update_icon()
/obj/item/tk_grab/afterattack(atom/target, mob/living/carbon/user, proximity, params)//TODO: go over this
. = ..()
+ if(.)
+ return
+
if(!target || !user)
return
if(!focus)
focus_object(target)
- return
- else if(!check_if_focusable(focus))
+ return TRUE
+
+ if(!check_if_focusable(focus))
return
if(target == focus)
- target.attack_self_tk(user)
+ if(target.attack_self_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ . = TRUE
update_icon()
return
@@ -142,16 +164,17 @@
if(!isturf(target) && isitem(focus) && target.Adjacent(focus))
apply_focus_overlay()
var/obj/item/I = focus
- I.melee_attack_chain(tk_user, target, params) //isn't copying the attack chain fun. we should do it more often.
+ . = I.melee_attack_chain(tk_user, target, params) //isn't copying the attack chain fun. we should do it more often.
if(check_if_focusable(focus))
focus.do_attack_animation(target, null, focus)
else
-
+ . = TRUE
apply_focus_overlay()
focus.throw_at(target, 10, 1,user)
user.changeNext_move(CLICK_CD_MELEE)
update_icon()
+
/proc/tkMaxRangeCheck(mob/user, atom/target)
var/d = get_dist(user, target)
if(d > TK_MAXRANGE)
diff --git a/code/datums/components/buffer.dm b/code/datums/components/buffer.dm
index 09855e9dcac07..a5b4052792a3d 100644
--- a/code/datums/components/buffer.dm
+++ b/code/datums/components/buffer.dm
@@ -27,7 +27,7 @@
/datum/component/buffer/proc/intercept_attack(datum/source, atom/attack_target, mob/user, params)
SIGNAL_HANDLER
if ((SEND_SIGNAL(attack_target, COMSIG_PARENT_RECIEVE_BUFFER, user, target, parent) & COMPONENT_BUFFER_RECIEVED))
- return COMPONENT_NO_ATTACK
+ return COMPONENT_CANCEL_ATTACK_CHAIN
return NONE
/datum/component/buffer/proc/examine(datum/source, mob/user, list/examine_list)
@@ -42,7 +42,7 @@
flush_buffer()
if (user)
to_chat(user, "You flush the buffer of [source]!")
- return COMPONENT_NO_INTERACT
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/buffer/proc/populate_buffer(datum/source, datum/buffer_entity)
SIGNAL_HANDLER
diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm
index ced03d367abaa..d281865081aa4 100644
--- a/code/datums/components/butchering.dm
+++ b/code/datums/components/butchering.dm
@@ -34,16 +34,16 @@
if(user.a_intent == INTENT_HARM && M.stat == DEAD && (M.butcher_results || M.guaranteed_butcher_results)) //can we butcher it?
if(butchering_enabled && (can_be_blunt || source.is_sharp()))
INVOKE_ASYNC(src, PROC_REF(startButcher), source, M, user)
- return COMPONENT_ITEM_NO_ATTACK
+ return COMPONENT_CANCEL_ATTACK_CHAIN
if(user.a_intent == INTENT_GRAB && ishuman(M) && source.is_sharp())
var/mob/living/carbon/human/H = M
if(H.has_status_effect(/datum/status_effect/neck_slice))
user.show_message("[H]'s neck has already been already cut, you can't make the bleeding any worse!", 1, \
"Their neck has already been already cut, you can't make the bleeding any worse!")
- return COMPONENT_ITEM_NO_ATTACK
+ return COMPONENT_CANCEL_ATTACK_CHAIN
if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping())) // Only sleeping, neck grabbed, or crit, can be sliced.
INVOKE_ASYNC(src, PROC_REF(startNeckSlice), source, H, user)
- return COMPONENT_ITEM_NO_ATTACK
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/butchering/proc/startButcher(obj/item/source, mob/living/M, mob/living/user)
to_chat(user, "You begin to butcher [M]...")
diff --git a/code/datums/components/deployable.dm b/code/datums/components/deployable.dm
index f2b031c58b8c5..5202dbae3701c 100644
--- a/code/datums/components/deployable.dm
+++ b/code/datums/components/deployable.dm
@@ -58,7 +58,7 @@
/datum/component/deployable/proc/on_attack_self(datum/source, mob/user)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(try_deploy), user, user.loc)
- return COMPONENT_NO_INTERACT
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/deployable/proc/on_afterattack(datum/source, atom/movable/target, mob/user, proximity_flag, params)
SIGNAL_HANDLER
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 5bc4612806422..a8969ec2fecd2 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -251,7 +251,7 @@
return
INVOKE_ASYNC(src, PROC_REF(pluckOut), user, 1, 2, "pulling out")
- return COMPONENT_NO_ATTACK_HAND
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/embedded/proc/checkRemoval(mob/living/carbon/victim, obj/item/I, mob/user)
SIGNAL_HANDLER
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index 53bba3c18a93a..b4ed7cb592bb4 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -185,7 +185,7 @@
if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE))
return FALSE
- . = COMPONENT_NO_ATTACK
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
if(locked)
var/atom/host = parent
host.balloon_alert(M, "[host] is locked.")
@@ -779,7 +779,7 @@
if(user.active_storage == src && A.loc == user) //if you're already looking inside the storage item
user.active_storage.close(user)
close(user)
- . = COMPONENT_NO_ATTACK_HAND
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
return
if(rustle_sound)
@@ -788,18 +788,18 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.l_store == A && !H.get_active_held_item()) //Prevents opening if it's in a pocket.
- . = COMPONENT_NO_ATTACK_HAND
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
INVOKE_ASYNC(H, TYPE_PROC_REF(/mob, put_in_hands), A)
H.l_store = null
return
if(H.r_store == A && !H.get_active_held_item())
- . = COMPONENT_NO_ATTACK_HAND
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
INVOKE_ASYNC(H, TYPE_PROC_REF(/mob, put_in_hands), A)
H.r_store = null
return
if(A.loc == user)
- . = COMPONENT_NO_ATTACK_HAND
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
if(locked)
var/atom/host = parent
host.balloon_alert(user, "[host] is locked.")
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index dc317f773a8db..85c49f68d8b67 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -141,7 +141,7 @@
if(user)
INVOKE_ASYNC(src, PROC_REF(ui_interact), user)
// an unlocked uplink blocks also opening the PDA or headset menu
- return COMPONENT_NO_INTERACT
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/uplink/ui_state(mob/user)
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index 7b21dff633dfa..bd0a164f12229 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -101,6 +101,7 @@
to_chat(user, "You telekinetically remove [charging] from [src].")
removecell()
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/machinery/cell_charger/attack_ai(mob/user)
return
diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm
index 2e1094c979931..00e48c6a8dba5 100644
--- a/code/game/objects/items/RPD.dm
+++ b/code/game/objects/items/RPD.dm
@@ -469,7 +469,7 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
attack_target = get_turf(attack_target)
var/can_make_pipe = (isturf(attack_target) || is_type_in_typecache(attack_target, rpd_whitelist))
- . = FALSE
+ . = TRUE
if((mode & DESTROY_MODE) && is_type_in_typecache(A, rpd_targets))
to_chat(user, "You start destroying a pipe...")
diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm
index 296af65198de6..322a4eefeb7a1 100644
--- a/code/game/objects/items/robot/ai_upgrades.dm
+++ b/code/game/objects/items/robot/ai_upgrades.dm
@@ -9,10 +9,10 @@
icon_state = "datadisk3"
-/obj/item/malf_upgrade/afterattack(mob/living/silicon/ai/AI, mob/user)
- . = ..()
- if(!istype(AI))
- return
+/obj/item/malf_upgrade/pre_attack(atom/A, mob/living/user)
+ if(!isAI(A))
+ return ..()
+ var/mob/living/silicon/ai/AI = A
if(AI.malf_picker)
AI.malf_picker.processing_time += 50
to_chat(AI, "[user] has attempted to upgrade you with combat software that you already possess. You gain 50 points to spend on Malfunction Modules instead.")
@@ -24,7 +24,7 @@
message_admins("[ADMIN_LOOKUPFLW(user)] has upgraded [ADMIN_LOOKUPFLW(AI)] with a [src].")
to_chat(user, "You upgrade [AI]. [src] is consumed in the process.")
qdel(src)
-
+ return TRUE
//Lipreading
/obj/item/surveillance_upgrade
@@ -33,10 +33,10 @@
icon = 'icons/obj/module.dmi'
icon_state = "datadisk3"
-/obj/item/surveillance_upgrade/afterattack(mob/living/silicon/ai/AI, mob/user)
- . = ..()
- if(!istype(AI))
- return
+/obj/item/surveillance_upgrade/pre_attack(atom/A, mob/living/user)
+ if(!isAI(A))
+ return ..()
+ var/mob/living/silicon/ai/AI = A
if(AI.eyeobj)
AI.eyeobj.set_relay_speech(TRUE)
to_chat(AI, "[user] has upgraded you with surveillance software!")
@@ -45,3 +45,4 @@
log_game("[key_name(user)] has upgraded [key_name(AI)] with a [src].")
message_admins("[ADMIN_LOOKUPFLW(user)] has upgraded [ADMIN_LOOKUPFLW(AI)] with a [src].")
qdel(src)
+ return TRUE
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index 9f67d17f582b5..d62d696dd7bcb 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -123,7 +123,7 @@
/obj/item/hand_tele/pre_attack(atom/target, mob/user, params)
if(try_dispel_portal(target, user))
- return FALSE
+ return TRUE
return ..()
/obj/item/hand_tele/proc/try_dispel_portal(obj/effect/portal/target, mob/user)
diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm
index e92289f30efa1..4e579bfddd7b9 100644
--- a/code/game/objects/items/theft_tools.dm
+++ b/code/game/objects/items/theft_tools.dm
@@ -127,8 +127,8 @@
item_state = "supermattersliver"
pulseicon = "supermatter_sliver_pulse"
-/obj/item/nuke_core/supermatter_sliver/attack_tk() // no TK dusting memes
- return FALSE
+/obj/item/nuke_core/supermatter_sliver/attack_tk(mob/user) // no TK dusting memes
+ return
/obj/item/nuke_core/supermatter_sliver/can_be_pulled(user) // no drag memes
return FALSE
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index b8cf038e37951..4c93ddb74d010 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -94,9 +94,9 @@
/obj/structure/chair/attack_tk(mob/user)
if(!anchored || has_buckled_mobs() || !isturf(user.loc))
- ..()
- else
- setDir(turn(dir,-90))
+ return ..()
+ setDir(turn(dir,-90))
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/structure/chair/proc/handle_rotation(direction)
handle_layer()
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index b26314ec37c13..9648e4d4358a3 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -105,6 +105,7 @@
hidden = null
add_fingerprint(user)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/structure/bedsheetbin/attack_tk(mob/user)
if(amount >= 1)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index e9fd7f1bbf230..71d88db88d179 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -461,7 +461,8 @@
// tk grab then use on self
/obj/structure/closet/attack_self_tk(mob/user)
- return attack_hand(user)
+ if(attack_hand(user))
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/structure/closet/verb/verb_toggleopen()
set src in view(1)
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 7c43db431012a..c8aa218581b37 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -93,15 +93,16 @@
/obj/structure/extinguisher_cabinet/attack_tk(mob/user)
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
if(stored_extinguisher)
stored_extinguisher.forceMove(loc)
to_chat(user, "You telekinetically remove [stored_extinguisher] from [src].")
stored_extinguisher = null
- opened = 1
+ opened = TRUE
playsound(loc, 'sound/machines/click.ogg', 15, 1, -3)
update_icon()
- else
- toggle_cabinet(user)
+ return
+ toggle_cabinet(user)
/obj/structure/extinguisher_cabinet/attack_paw(mob/user)
diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm
index 599157471090a..669026f47062d 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -133,13 +133,12 @@
return
/obj/structure/fireaxecabinet/attack_tk(mob/user)
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
if(locked)
to_chat(user, "The [name] won't budge!")
return
- else
- open = !open
- update_appearance()
- return
+ open = !open
+ update_icon()
/obj/structure/fireaxecabinet/update_icon()
cut_overlays()
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 115276a9dd3a8..ed8dec679fa57 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -114,8 +114,8 @@
user.stop_pulling()
return ..()
-/obj/structure/table/attack_tk()
- return FALSE
+/obj/structure/table/attack_tk(mob/user)
+ return
/obj/structure/table/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 9c7374d0cec66..a033bd4b51f8b 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -150,6 +150,7 @@
user.visible_message("Something knocks on [src].")
add_fingerprint(user)
playsound(src, 'sound/effects/Glassknock.ogg', 50, 1)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/structure/window/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(!can_be_reached(user))
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 760a3a6e2a0fe..7f4be91b18acf 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -204,7 +204,7 @@ GLOBAL_LIST_EMPTY(created_baseturf_lists)
else if(allow_z_travel)
to_chat(user, "You can't float up and down when there is gravity!")
. = ..()
- if(SEND_SIGNAL(user, COMSIG_MOB_ATTACK_HAND_TURF, src) & COMPONENT_NO_ATTACK_HAND)
+ if(SEND_SIGNAL(user, COMSIG_MOB_ATTACK_HAND_TURF, src) & COMPONENT_CANCEL_ATTACK_CHAIN)
. = TRUE
if(.)
return
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index d34b0c0bee522..d5f5c07d10eff 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -131,16 +131,18 @@
)
/obj/tear_in_reality/attack_tk(mob/user)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- var/datum/component/mood/insaneinthemembrane = C.GetComponent(/datum/component/mood)
- if(insaneinthemembrane.sanity < 15)
- return //they've already seen it and are about to die, or are just too insane to care
- to_chat(C, "OH GOD! NONE OF IT IS REAL! NONE OF IT IS REEEEEEEEEEEEEEEEEEEEEEEEAL!")
- insaneinthemembrane.sanity = 0
- for(var/lore in typesof(/datum/brain_trauma/severe))
- C.gain_trauma(lore)
- addtimer(CALLBACK(src, PROC_REF(deranged), C), 100)
+ if(!iscarbon(user))
+ return
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
+ var/mob/living/carbon/jedi = user
+ var/datum/component/mood/insaneinthemembrane = jedi.GetComponent(/datum/component/mood)
+ if(insaneinthemembrane.sanity < 15)
+ return //they've already seen it and are about to die, or are just too insane to care
+ to_chat(jedi, "OH GOD! NONE OF IT IS REAL! NONE OF IT IS REEEEEEEEEEEEEEEEEEEEEEEEAL!")
+ insaneinthemembrane.sanity = 0
+ for(var/lore in typesof(/datum/brain_trauma/severe))
+ jedi.gain_trauma(lore)
+ addtimer(CALLBACK(src, PROC_REF(deranged), jedi), 10 SECONDS)
/obj/tear_in_reality/proc/deranged(mob/living/carbon/C)
if(!C || C.stat == DEAD)
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 33852058545f3..c736d09979cc2 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -131,17 +131,17 @@
/obj/item/scythe/pre_attack(atom/A, mob/living/user, params)
if(swiping || !istype(A, /obj/structure/spacevine) || get_turf(A) == get_turf(user))
return ..()
- else
- var/turf/user_turf = get_turf(user)
- var/dir_to_target = get_dir(user_turf, get_turf(A))
- swiping = TRUE
- var/static/list/scythe_slash_angles = list(0, 45, 90, -45, -90)
- for(var/i in scythe_slash_angles)
- var/turf/T = get_step(user_turf, turn(dir_to_target, i))
- for(var/obj/structure/spacevine/V in T)
- if(user.Adjacent(V))
- melee_attack_chain(user, V)
- swiping = FALSE
+ var/turf/user_turf = get_turf(user)
+ var/dir_to_target = get_dir(user_turf, get_turf(A))
+ swiping = TRUE
+ var/static/list/scythe_slash_angles = list(0, 45, 90, -45, -90)
+ for(var/i in scythe_slash_angles)
+ var/turf/T = get_step(user_turf, turn(dir_to_target, i))
+ for(var/obj/structure/spacevine/V in T)
+ if(user.Adjacent(V))
+ melee_attack_chain(user, V)
+ swiping = FALSE
+ return TRUE
// *************************************
// Nutrient defines for hydroponics
diff --git a/code/modules/mining/equipment/resonator.dm b/code/modules/mining/equipment/resonator.dm
index b5588e772ba9d..150ae9fdcab7e 100644
--- a/code/modules/mining/equipment/resonator.dm
+++ b/code/modules/mining/equipment/resonator.dm
@@ -56,7 +56,7 @@
/obj/item/resonator/pre_attack(atom/target, mob/user, params)
if(check_allowed_items(target, 1))
CreateResonance(target, user)
- return TRUE
+ . = ..()
//resonance field, crushes rock, damages mobs
/obj/effect/temp_visual/resonance
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index f07099a5fa73b..3fbe8f1a1bc92 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -67,7 +67,7 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/attack_hand(mob/living/carbon/human/M)
. = FALSE
- if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, M) & COMPONENT_NO_ATTACK_HAND)
+ if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, M) & COMPONENT_CANCEL_ATTACK_CHAIN)
. = TRUE
switch(M.a_intent)
if ("help")
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index c4adc619b768c..b64402066fbed 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -507,8 +507,7 @@
if(ranged && ranged_cooldown <= world.time)
GiveTarget(A)
OpenFire(A)
- ..()
-
+ return ..()
////// AI Status ///////
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 1b60348ca4ba4..c16509a666297 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -963,6 +963,9 @@
/mob/proc/can_interact_with(atom/A, treat_mob_as_adjacent)
if(IsAdminGhost(src))
return TRUE
+ var/datum/dna/mob_dna = has_dna()
+ if(mob_dna?.check_mutation(TK) && tkMaxRangeCheck(src, A))
+ return TRUE
if(treat_mob_as_adjacent && src == A.loc)
return TRUE
return Adjacent(A)
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index ba160f639105a..60e03f12459c5 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -81,11 +81,11 @@
/obj/structure/filingcabinet/attack_tk(mob/user)
if(anchored)
- attack_self_tk(user)
- else
- ..()
+ return attack_self_tk(user)
+ return ..()
/obj/structure/filingcabinet/attack_self_tk(mob/user)
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
if(contents.len)
if(prob(40 + contents.len * 5))
var/obj/item/I = pick(contents)
diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm
index c9e9e1c2d2815..9e82edabda40a 100644
--- a/code/modules/power/lighting/light.dm
+++ b/code/modules/power/lighting/light.dm
@@ -621,8 +621,8 @@
to_chat(user, "You telekinetically remove the light [fitting].")
// create a light tube/bulb item and put it in the user's hand
- var/obj/item/light/L = drop_light_tube()
- L.attack_tk(user)
+ var/obj/item/light/light_tube = drop_light_tube()
+ return light_tube.attack_tk(user)
// break the light and make sparks if was on
diff --git a/code/modules/power/lighting/light_construct.dm b/code/modules/power/lighting/light_construct.dm
index fa5f81ca18724..96c23c8e7aaf4 100644
--- a/code/modules/power/lighting/light_construct.dm
+++ b/code/modules/power/lighting/light_construct.dm
@@ -54,11 +54,14 @@
add_fingerprint(user)
/obj/structure/light_construct/attack_tk(mob/user)
- if(cell)
- to_chat(user, "You telekinetically remove [cell].")
- cell.forceMove(drop_location())
- cell.attack_tk(user)
- remove_cell()
+ if(!cell)
+ return
+ to_chat(user, "You telekinetically remove [cell].")
+ var/obj/item/stock_parts/cell/cell_reference = cell
+ cell = null
+ cell_reference.forceMove(drop_location())
+ remove_cell()
+ return cell_reference.attack_tk(user)
/obj/structure/light_construct/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
diff --git a/code/modules/power/singularity/boh_tear.dm b/code/modules/power/singularity/boh_tear.dm
index 18b6b6e477614..ec5ef44fe2ddc 100644
--- a/code/modules/power/singularity/boh_tear.dm
+++ b/code/modules/power/singularity/boh_tear.dm
@@ -75,12 +75,14 @@
investigate_log("was created at [AREACOORD(T)].", INVESTIGATE_ENGINES)
/obj/boh_tear/attack_tk(mob/living/user)
- if(!istype(user))
+ if(!isliving(user))
return
- to_chat(user, "You don't feel like you are real anymore.")
- user.dust_animation()
- user.spawn_dust()
- addtimer(CALLBACK(src, PROC_REF(consume), user), 5)
+ var/mob/living/jedi = user
+ to_chat(jedi, "You don't feel like you are real anymore.")
+ jedi.dust_animation()
+ jedi.spawn_dust()
+ addtimer(CALLBACK(src, PROC_REF(consume), jedi), 0.5 SECONDS)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
#undef BOH_TEAR_CONSUME_RANGE
#undef BOH_TEAR_GRAV_PULL
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 2b85a17b9475f..e7d57f1962e6a 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -62,18 +62,58 @@
return ..()
/obj/anomaly/singularity/attack_tk(mob/user)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.visible_message("[C]'s head begins to collapse in on itself!", "Your head feels like it's collapsing in on itself! This was really not a good idea!", "You hear something crack and explode in gore.")
- var/turf/T = get_turf(C)
- for(var/i in 1 to 3)
- C.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
- new /obj/effect/gibspawner/generic(T, C)
- sleep(1)
- C.ghostize()
- var/obj/item/bodypart/head/rip_u = C.get_bodypart(BODY_ZONE_HEAD)
+ if(!iscarbon(user))
+ return
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
+ var/mob/living/carbon/jedi = user
+ jedi.visible_message(
+ "[jedi]'s head begins to collapse in on itself!",
+ "Your head feels like it's collapsing in on itself! This was really not a good idea!",
+ "You hear something crack and explode in gore."
+ )
+ jedi.Stun(3 SECONDS)
+ new /obj/effect/gibspawner/generic(get_turf(jedi), jedi)
+ jedi.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
+ if(QDELETED(jedi))
+ return // damage was too much
+ if(jedi.stat == DEAD)
+ jedi.ghostize()
+ var/obj/item/bodypart/head/rip_u = jedi.get_bodypart(BODY_ZONE_HEAD)
rip_u.dismember(BURN) //nice try jedi
qdel(rip_u)
+ return
+ addtimer(CALLBACK(src, PROC_REF(carbon_tk_part_two), jedi), 0.1 SECONDS)
+
+
+/obj/anomaly/singularity/proc/carbon_tk_part_two(mob/living/carbon/jedi)
+ if(QDELETED(jedi))
+ return
+ new /obj/effect/gibspawner/generic(get_turf(jedi), jedi)
+ jedi.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
+ if(QDELETED(jedi))
+ return // damage was too much
+ if(jedi.stat == DEAD)
+ jedi.ghostize()
+ var/obj/item/bodypart/head/rip_u = jedi.get_bodypart(BODY_ZONE_HEAD)
+ if(rip_u)
+ rip_u.dismember(BURN)
+ qdel(rip_u)
+ return
+ addtimer(CALLBACK(src, PROC_REF(carbon_tk_part_three), jedi), 0.1 SECONDS)
+
+
+/obj/anomaly/singularity/proc/carbon_tk_part_three(mob/living/carbon/jedi)
+ if(QDELETED(jedi))
+ return
+ new /obj/effect/gibspawner/generic(get_turf(jedi), jedi)
+ jedi.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
+ if(QDELETED(jedi))
+ return // damage was too much
+ jedi.ghostize()
+ var/obj/item/bodypart/head/rip_u = jedi.get_bodypart(BODY_ZONE_HEAD)
+ if(rip_u)
+ rip_u.dismember(BURN)
+ qdel(rip_u)
/obj/anomaly/singularity/ex_act(severity, target)
switch(severity)
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index f9a76a0002bfb..e26fb9848c3cd 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -652,13 +652,16 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
Consume(B)
/obj/machinery/power/supermatter_crystal/attack_tk(mob/user)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- to_chat(C, "That was a really dense idea.")
- C.ghostize()
- var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
- rip_u.Remove(C)
+ if(!iscarbon(user))
+ return
+ var/mob/living/carbon/jedi = user
+ to_chat(jedi, "That was a really dense idea.")
+ jedi.ghostize()
+ var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in jedi.internal_organs
+ if(rip_u)
+ rip_u.Remove(jedi)
qdel(rip_u)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/machinery/power/supermatter_crystal/attack_paw(mob/user)
dust_mob(user, cause = "monkey attack")
diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm
index 17485bfb998de..f1a2d9f89c515 100644
--- a/code/modules/power/tesla/energy_ball.dm
+++ b/code/modules/power/tesla/energy_ball.dm
@@ -147,14 +147,17 @@
dust_mobs(AM)
/obj/anomaly/energy_ball/attack_tk(mob/user)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- to_chat(C, "That was a shockingly dumb idea.")
- var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
- C.ghostize(FALSE)
+ if(!iscarbon(user))
+ return
+ var/mob/living/carbon/jedi = user
+ to_chat(jedi, "That was a shockingly dumb idea.")
+ var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in jedi.internal_organs
+ jedi.ghostize(jedi)
+ if(rip_u)
qdel(rip_u)
- C.investigate_log("had [C.p_their()] brain dusted by touching [src] with telekinesis.", INVESTIGATE_DEATHS)
- C.death()
+ jedi.investigate_log("had [jedi.p_their()] brain dusted by touching [src] with telekinesis.", INVESTIGATE_DEATHS)
+ jedi.death()
+ return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/anomaly/energy_ball/proc/dust_mobs(atom/A)
if(isliving(A))
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index e16979c4ced27..d3d0d4224b9a5 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -31,7 +31,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
if(works_from_distance)
user.Beam(attacked_machinery, icon_state = "rped_upgrade", time = 5)
attacked_machinery.exchange_parts(user, src)
- return FALSE
+ return TRUE
var/obj/structure/frame/machine/attacked_frame = attacked_object