diff --git a/citadel.dme b/citadel.dme
index 837642e1522..8f4774d717d 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -1837,6 +1837,7 @@
#include "code\game\objects\items\gifts.dm"
#include "code\game\objects\items\glassjar.dm"
#include "code\game\objects\items\godfigures.dm"
+#include "code\game\objects\items\gripper.dm"
#include "code\game\objects\items\gunbox.dm"
#include "code\game\objects\items\holosign_creator.dm"
#include "code\game\objects\items\inducer.dm"
@@ -4347,7 +4348,6 @@
#include "code\modules\mob\living\silicon\robot\items\robot_upgrade\sizeshift.dm"
#include "code\modules\mob\living\silicon\robot\items\robot_upgrade\syndicate.dm"
#include "code\modules\mob\living\silicon\robot\items\robot_upgrade\vtec.dm"
-#include "code\modules\mob\living\silicon\robot\legacy_items\gripper.dm"
#include "code\modules\mob\living\silicon\robot\legacy_items\robot_items.dm"
#include "code\modules\mob\living\silicon\robot\legacy_items\robot_parts.dm"
#include "code\modules\mob\living\silicon\robot\modules\cybersun.dm"
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 7846e51504f..8dc6961e681 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -113,16 +113,4 @@
/obj/machinery/computer/attackby(obj/item/I, mob/living/user, params, clickchain_flags, damage_multiplier)
if(computer_deconstruction_screwdriver(user, I))
return
- else
- if(istype(I,/obj/item/gripper)) //Behold, Grippers and their horribleness. If ..() is called by any computers' attackby() now or in the future, this should let grippers work with them appropriately.
- var/obj/item/gripper/B = I //B, for Borg.
- if(!B.get_item())
- to_chat(user, "\The [B] is not holding anything.")
- return
- else
- var/B_held = B.get_item()
- to_chat(user, "You use \the [B] to use \the [B_held] with \the [src].")
- playsound(src, "keyboard", 100, 1, 0)
- attackby(B.get_item(), user, params, clickchain_flags, damage_multiplier)
- return
- return ..()
+ return ..()
diff --git a/code/modules/mob/living/silicon/robot/legacy_items/gripper.dm b/code/game/objects/items/gripper.dm
similarity index 78%
rename from code/modules/mob/living/silicon/robot/legacy_items/gripper.dm
rename to code/game/objects/items/gripper.dm
index 20f46c36d14..7b7c15c3041 100644
--- a/code/modules/mob/living/silicon/robot/legacy_items/gripper.dm
+++ b/code/game/objects/items/gripper.dm
@@ -1,7 +1,9 @@
-// todo: this shouldn't be a robot item, this is generic.
-
-//Simple borg hand.
-//Limited use.
+/**
+ * Dynamic way to allow holding another item in an inventory slot / hand slot
+ * with a single static item of the item itself.
+ *
+ * Useful for cyborgs and rigsuits and more.
+ */
/obj/item/gripper
name = "magnetic gripper"
desc = "A simple grasping tool specialized in construction and engineering work."
@@ -11,22 +13,8 @@
icon_state = "gripper"
item_flags = ITEM_NO_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
- //Has a list of items that it can hold.
- var/list/can_hold = list(
- /obj/item/cell,
- /obj/item/airlock_electronics,
- /obj/item/tracker_electronics,
- /obj/item/module/power_control,
- /obj/item/stock_parts,
- /obj/item/frame,
- /obj/item/camera_assembly,
- /obj/item/tank,
- /obj/item/circuitboard,
- /obj/item/smes_coil,
- /obj/item/fuelrod/,
- /obj/item/fuel_assembly/
- )
-
+ /// Has a list of items that it can hold.
+ var/list/can_hold
/// currently held item
VAR_PRIVATE/obj/item/wrapped
@@ -42,6 +30,56 @@
remove_item(drop_location())
return ..()
+/**
+ * Checks if an item should be able to be held in here.
+ */
+/obj/item/gripper/proc/can_hold(obj/item/item)
+ for(var/typepath in can_hold)
+ if(istype(item,typepath))
+ return TRUE
+ return FALSE
+
+/obj/item/gripper/inv_slot_attached()
+ if(wrapped)
+ return list(wrapped, src)
+ return src
+
+//! WARNING WARNING GRIPPERS ARE STILL SHITCODE !//
+//! This exact combination of hooks will make it work as expected. !//
+//! It's realistically still pretty shitty. !//
+
+/obj/item/gripper/pickup(...)
+ . = ..()
+ wrapped?.pickup(arglist(args))
+
+/obj/item/gripper/dropped(...)
+ . = ..()
+ wrapped?.dropped(arglist(args))
+
+/obj/item/gripper/equipped(...)
+ . = ..()
+ wrapped?.equipped(arglist(args))
+
+/obj/item/gripper/unequipped(...)
+ . = ..()
+ wrapped?.unequipped(arglist(args))
+
+/obj/item/gripper/on_inv_equipped(...)
+ . = ..()
+ wrapped?.on_inv_equipped(arglist(args))
+
+/obj/item/gripper/on_inv_unequipped(...)
+ . = ..()
+ wrapped?.on_inv_unequipped(arglist(args))
+
+/obj/item/gripper/on_inv_pickup(...)
+ . = ..()
+ wrapped?.on_inv_pickup(arglist(args))
+
+/obj/item/gripper/on_inv_dropped(...)
+ . = ..()
+ wrapped?.on_inv_dropped(arglist(args))
+
/obj/item/gripper/proc/insert_item(obj/item/I)
if(QDELETED(I))
return
@@ -49,6 +87,11 @@
remove_item(drop_location())
wrapped = I
I.forceMove(src)
+ // forcemove will have removed them from inv if they were inside
+ if(worn_slot)
+ I.pickup(inv_inside.owner, NONE, null)
+ I.equipped(inv_inside.owner, isnum(inv_slot_or_index) ? SLOT_ID_HANDS : inv_slot_or_index, NONE)
+ I.on_inv_equipped(inv_inside.owner, inv_inside, inv_slot_or_index, NONE, null)
RegisterSignals(I, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED), PROC_REF(unwrap_hook))
/**
@@ -60,6 +103,8 @@
var/obj/item/old = wrapped
UnregisterSignal(wrapped, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
wrapped = null
+ // in theory the below should pull it out of inventory properly
+ // as worn_slot is set, which allows inventory hooks to fire.
switch(newloc)
if(null)
old.moveToNullspace()
@@ -84,7 +129,6 @@
return
if(wrapped)
return wrapped.attack_self(user)
- return ..()
/obj/item/gripper/attackby(obj/item/I, mob/living/user, list/params, clickchain_flags, damage_multiplier)
// todo: items should have a melee_receive_chain or something that
@@ -125,11 +169,7 @@
return
//Check if the item is blacklisted.
- var/grab = 0
- for(var/typepath in can_hold)
- if(istype(I,typepath))
- grab = 1
- break
+ var/grab = can_hold(I)
//We can grab the item, finally.
if(grab)
@@ -171,11 +211,28 @@
desc = "A strange grasping tool that can hold anything a human can, but still maintains the limitations of application its more limited cousins have."
icon_state = "gripper-omni"
- can_hold = list(/obj/item) // Testing and Event gripper.
+/obj/item/gripper/omni/can_hold(obj/item/item)
+ return TRUE
/obj/item/gripper/omni/no_attack
conf_inject_clickchain_flags = CLICKCHAIN_DO_NOT_ATTACK
+/obj/item/gripper/engineering
+ can_hold = list(
+ /obj/item/cell,
+ /obj/item/airlock_electronics,
+ /obj/item/tracker_electronics,
+ /obj/item/module/power_control,
+ /obj/item/stock_parts,
+ /obj/item/frame,
+ /obj/item/camera_assembly,
+ /obj/item/tank,
+ /obj/item/circuitboard,
+ /obj/item/smes_coil,
+ /obj/item/fuelrod,
+ /obj/item/fuel_assembly,
+ )
+
// VEEEEERY limited version for mining borgs. Basically only for swapping cells and upgrading the drills.
/obj/item/gripper/miner
name = "drill maintenance gripper"
@@ -183,8 +240,8 @@
icon_state = "gripper-mining"
can_hold = list(
- /obj/item/cell,
- /obj/item/stock_parts
+ /obj/item/cell,
+ /obj/item/stock_parts,
)
/obj/item/gripper/security
@@ -193,14 +250,14 @@
icon_state = "gripper-sec"
can_hold = list(
- /obj/item/paper,
- /obj/item/paper_bundle,
- /obj/item/pen,
- /obj/item/sample,
- /obj/item/forensics/sample_kit,
- /obj/item/tape_recorder,
- /obj/item/barrier_tape_roll,
- /obj/item/uv_light
+ /obj/item/paper,
+ /obj/item/paper_bundle,
+ /obj/item/pen,
+ /obj/item/sample,
+ /obj/item/forensics/sample_kit,
+ /obj/item/tape_recorder,
+ /obj/item/barrier_tape_roll,
+ /obj/item/uv_light,
)
/obj/item/gripper/paperwork
@@ -213,8 +270,8 @@
/obj/item/paper_bundle,
/obj/item/card/id,
/obj/item/book,
- /obj/item/newspaper
- )
+ /obj/item/newspaper,
+ )
/obj/item/gripper/medical
name = "medical gripper"
@@ -227,8 +284,8 @@
/obj/item/reagent_containers/blood,
/obj/item/stack/material/phoron,
/obj/item/implant,
- /obj/item/nif
- )
+ /obj/item/nif,
+ )
/obj/item/gripper/research //A general usage gripper, used for toxins/robotics/xenobio/etc
name = "scientific gripper"
@@ -253,9 +310,8 @@
/obj/item/slimepotion,
/obj/item/slime_extract,
/obj/item/reagent_containers/food/snacks/monkeycube,
- /obj/item/nif
-
- )
+ /obj/item/nif,
+ )
/obj/item/gripper/circuit
name = "circuit assembly gripper"
@@ -274,9 +330,8 @@
/obj/item/clothing/ears/circuitry,
/obj/item/clothing/suit/circuitry,
/obj/item/implant/integrated_circuit,
- /obj/item/integrated_circuit
-
- )
+ /obj/item/integrated_circuit,
+ )
/obj/item/gripper/service //Used to handle food, drinks, and seeds.
name = "service gripper"
@@ -292,8 +347,8 @@
/obj/item/plantspray,
/obj/item/reagent_containers/glass,
/obj/item/reagent_containers/food/drinks,
- /obj/item/storage/box/wings
- )
+ /obj/item/storage/box/wings,
+ )
/obj/item/gripper/gravekeeper //Used for handling grave things, flowers, etc.
name = "grave gripper"
@@ -303,8 +358,22 @@
can_hold = list(
/obj/item/seeds,
/obj/item/grown,
- /obj/item/material/gravemarker
- )
+ /obj/item/material/gravemarker,
+ )
+
+/obj/item/gripper/no_use //Used when you want to hold and put items in other things, but not able to 'use' the item
+
+/obj/item/gripper/no_use/attack_self(mob/user, datum/event_args/actor/actor)
+ return
+
+/obj/item/gripper/no_use/organ
+ name = "organ gripper"
+ icon_state = "gripper-flesh"
+ desc = "A specialized grasping tool used to preserve and manipulate organic material."
+
+ can_hold = list(
+ /obj/item/organ,
+ )
/obj/item/gripper/no_use/organ/Entered(var/atom/movable/AM)
..()
@@ -318,11 +387,6 @@
var/obj/item/organ/O = AM
O.unpreserve(GRIPPER_TRAIT)
-/obj/item/gripper/no_use //Used when you want to hold and put items in other things, but not able to 'use' the item
-
-/obj/item/gripper/no_use/attack_self(mob/user, datum/event_args/actor/actor)
- return
-
/obj/item/gripper/no_use/organ/robotics
name = "robotics organ gripper"
icon_state = "gripper-flesh"
@@ -332,8 +396,8 @@
/obj/item/organ/external,
/obj/item/organ/internal/brain, //to insert into MMIs,
/obj/item/organ/internal/cell,
- /obj/item/organ/internal/eyes/robot
- )
+ /obj/item/organ/internal/eyes/robot,
+ )
/obj/item/gripper/no_use/mech
name = "exosuit gripper"
@@ -344,8 +408,8 @@
/obj/item/vehicle_part,
/obj/item/vehicle_part/micro,
/obj/item/vehicle_module,
- /obj/item/vehicle_tracking_beacon
- )
+ /obj/item/vehicle_tracking_beacon,
+ )
/obj/item/gripper/no_use/loader //This is used to disallow building with metal.
name = "sheet loader"
@@ -353,14 +417,5 @@
icon_state = "gripper-sheet"
can_hold = list(
- /obj/item/stack/material
- )
-
-/obj/item/gripper/no_use/organ
- name = "organ gripper"
- icon_state = "gripper-flesh"
- desc = "A specialized grasping tool used to preserve and manipulate organic material."
-
- can_hold = list(
- /obj/item/organ
- )
+ /obj/item/stack/material,
+ )
diff --git a/code/game/rendering/actor_huds/huds/robot_inventory-screen_object.dm b/code/game/rendering/actor_huds/huds/robot_inventory-screen_object.dm
index 48c02cecb14..dfdf6ffbd5c 100644
--- a/code/game/rendering/actor_huds/huds/robot_inventory-screen_object.dm
+++ b/code/game/rendering/actor_huds/huds/robot_inventory-screen_object.dm
@@ -154,6 +154,7 @@
name = "drawer"
icon = 'icons/screen/hud/styles/common/storage.dmi'
icon_state = "block"
+ vis_flags = VIS_INHERIT_LAYER | VIS_INHERIT_PLANE
mouse_opacity = MOUSE_OPACITY_ICON
var/atom/movable/screen/actor_hud/robot_inventory/robot_drawer_backplate/backplate
var/obj/item/masquarading_as
diff --git a/code/modules/economy/machines/mint.dm b/code/modules/economy/machines/mint.dm
index daacc66ee43..48d0559e938 100644
--- a/code/modules/economy/machines/mint.dm
+++ b/code/modules/economy/machines/mint.dm
@@ -439,17 +439,6 @@
if(P.contents.len > 0)
to_chat(user, "Some items are refused.")
- else if(istype(O, /obj/item/gripper)) // Grippers. ~Mechoid.
- var/obj/item/gripper/B = O //B, for Borg.
- if(!B.get_item())
- to_chat(user, "\The [B] is not holding anything.")
- return
- else
- var/B_held = B.get_item()
- to_chat(user, "You use \the [B] to put \the [B_held] into \the [src] slot.")
- attackby(B_held, user)
- return
-
else
to_chat(user, "\The [O] doesn't fit into the [src] slot.")
return 1
diff --git a/code/modules/food/machinery/smartfridge.dm b/code/modules/food/machinery/smartfridge.dm
index d75dd5222df..325a02f60dd 100644
--- a/code/modules/food/machinery/smartfridge.dm
+++ b/code/modules/food/machinery/smartfridge.dm
@@ -160,17 +160,6 @@
if(P.contents.len > 0)
to_chat(user, "Some items are refused.")
- else if(istype(O, /obj/item/gripper)) // Grippers. ~Mechoid.
- var/obj/item/gripper/B = O //B, for Borg.
- if(!B.get_item())
- to_chat(user, "\The [B] is not holding anything.")
- return
- else
- var/B_held = B.get_item()
- to_chat(user, "You use \the [B] to put \the [B_held] into \the [src].")
- attackby(B_held, user)
- return
-
else
to_chat(user, "\The [src] smartly refuses [O].")
return 1
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index 8c6ce141314..ebc2cd69ec7 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -12,9 +12,9 @@
/mob/living/silicon/robot/death(gibbed)
if(camera)
camera.status = 0
- var/obj/item/gripper/G = locate(/obj/item/gripper) in contents
- if(G)
- G.drop_item()
+ // drop all gripper items
+ for(var/obj/item/gripper/gripper in get_equipped_items())
+ gripper.drop_item()
var/obj/item/robot_builtin/dog_sleeper/S = locate(/obj/item/robot_builtin/dog_sleeper) in contents
if(S)
S.go_out()
diff --git a/code/modules/mob/living/silicon/robot/modules/drone.dm b/code/modules/mob/living/silicon/robot/modules/drone.dm
index e36f29f9a45..e98297a857a 100644
--- a/code/modules/mob/living/silicon/robot/modules/drone.dm
+++ b/code/modules/mob/living/silicon/robot/modules/drone.dm
@@ -34,7 +34,7 @@
/obj/item/tool/wirecutters/cyborg,
/obj/item/multitool,
/obj/item/lightreplacer,
- /obj/item/gripper,
+ /obj/item/gripper/engineering,
/obj/item/mop,
/obj/item/gripper/no_use/loader,
/obj/item/extinguisher,
diff --git a/code/modules/mob/living/silicon/robot/modules/nanotrasen/engineering.dm b/code/modules/mob/living/silicon/robot/modules/nanotrasen/engineering.dm
index ab7418d7162..fd8ffe40569 100644
--- a/code/modules/mob/living/silicon/robot/modules/nanotrasen/engineering.dm
+++ b/code/modules/mob/living/silicon/robot/modules/nanotrasen/engineering.dm
@@ -81,7 +81,7 @@ GENERATE_ROBOT_MODULE_PRESET(/nanotrasen/engineering)
/obj/item/geiger_counter/cyborg,
/obj/item/pipe_painter,
/obj/item/floor_painter,
- /obj/item/gripper,
+ /obj/item/gripper/engineering,
/obj/item/gripper/no_use/loader,
/obj/item/pipe_dispenser,
/obj/item/gripper/circuit,
diff --git a/code/modules/mob/living/silicon/robot/robot-composition.dm b/code/modules/mob/living/silicon/robot/robot-composition.dm
index b3397b224ea..3e8aa925e99 100644
--- a/code/modules/mob/living/silicon/robot/robot-composition.dm
+++ b/code/modules/mob/living/silicon/robot/robot-composition.dm
@@ -136,7 +136,7 @@
if(module_provisioning)
QDEL_NULL(module_provisioning)
if(module_legacy)
- module_legacy.Reset()
+ module_legacy.Reset(src)
QDEL_NULL(module_legacy)
// set
src.module = module
diff --git a/code/modules/mob/living/silicon/robot/robot-inventory.dm b/code/modules/mob/living/silicon/robot/robot-inventory.dm
index a9341d835de..b3ea3c8b95b 100644
--- a/code/modules/mob/living/silicon/robot/robot-inventory.dm
+++ b/code/modules/mob/living/silicon/robot/robot-inventory.dm
@@ -7,10 +7,3 @@
/mob/living/silicon/robot/should_allow_pickup(obj/item/item, datum/event_args/actor/actor, silent)
return item in robot_inventory?.provided_items
-
-/mob/living/silicon/robot/is_in_inventory(obj/item/item)
- return ..() || is_in_inventory_robot(item)
-
-/mob/living/silicon/robot/proc/is_in_inventory_robot(obj/item/item)
- // Bespoke check that an item is in gripper, as grippers don't count as an inventory slot.
- return istype(item.loc, /obj/item/gripper) && item.loc.loc == src
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index abc71d65092..487c460677c 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -957,7 +957,7 @@
cleaned_human.clean_blood(1)
to_chat(cleaned_human, "[src] cleans your face!")
- for(var/obj/item/storage/bag/ore/ore_bag in inventory.get_held_items())
+ for(var/obj/item/storage/bag/ore/ore_bag in inventory?.get_held_items())
if(ore_bag)
if(isturf(loc))
var/turf/tile = loc
@@ -997,6 +997,11 @@
state = 1
lockdown = state
lockcharge = state
+ if(lockdown)
+ // we still need a better way of prying shit out of these guys
+ // but for now this is fine
+ for(var/obj/item/gripper/gripper in get_equipped_items())
+ gripper.drop_item()
update_mobility()
/mob/living/silicon/robot/proc/sensor_mode() //Medical/Security HUD controller for borgs
diff --git a/code/modules/reagents/chemistry/machinery.dm b/code/modules/reagents/chemistry/machinery.dm
index e01cb659e1f..80d91f73fb1 100644
--- a/code/modules/reagents/chemistry/machinery.dm
+++ b/code/modules/reagents/chemistry/machinery.dm
@@ -127,18 +127,6 @@
src.updateUsrDialog()
return 0
- if(istype(O,/obj/item/gripper))
- var/obj/item/gripper/B = O //B, for Borg.
- if(!B.get_item())
- to_chat(user, "\The [B] is not holding anything.")
- return 0
- else
- var/B_held = B.get_item()
- to_chat(user, "You use \the [B] to load \the [src] with \the [B_held].")
- attackby(B_held, user)
-
- return 0
-
if(!sheet_reagents[O.type] && (!O.reagents || !O.reagents.total_volume))
to_chat(user, "\The [O] is not suitable for blending.")
return 1