diff --git a/code/datums/action.dm b/code/datums/action.dm
index 5ea5ba4044c0..b10b3e9da5d2 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -253,8 +253,8 @@
/datum/action/item_action/toggle_mister
name = "Toggle Mister"
-/datum/action/item_action/toggle_grinder
- name = "Toggle Grinder"
+/datum/action/item_action/toggle_attachment
+ name = "Toggle Attachment"
/datum/action/item_action/activate_injector
name = "Activate Injector"
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 1eab00069a0d..a62780aad05a 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -22,6 +22,9 @@
qdel(src)
/obj/structure/frame/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if(I.use_tool(src, user, 3 SECONDS, volume=0))
to_chat(user, "You cut apart \the [src].", "You cut apart \the [src].")
deconstruct()
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 15455242f5b3..5e4f9838aed8 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -80,11 +80,11 @@
return ..()
/obj/structure/barricade/wooden/deconstruct_act(mob/living/user, obj/item/I)
- if(I.use_tool(src, user, 3 SECONDS, volume=0))
- deconstruct()
. = ..()
- if (I.use_tool(src, user, 1 SECONDS, volume=0))
- to_chat(user, "You cut apart the railing.")
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
+ if (I.use_tool(src, user, 2 SECONDS, volume=0))
+ to_chat(user, "You cut apart [src].")
deconstruct()
return TRUE
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 606fc8ca42ee..5d3d9d3d9088 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1244,6 +1244,9 @@
INVOKE_ASYNC(src, (density ? PROC_REF(open) : PROC_REF(close)), 2)
/obj/machinery/door/airlock/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
var/decon_time = 5 SECONDS
if(welded)
decon_time += 5 SECONDS
diff --git a/code/game/objects/items/gear_packs.dm b/code/game/objects/items/gear_packs.dm
new file mode 100644
index 000000000000..182e6ed94c32
--- /dev/null
+++ b/code/game/objects/items/gear_packs.dm
@@ -0,0 +1,285 @@
+/obj/item/gear_pack
+ name = "gear pack"
+ desc = "A large backpack that usually holds things"
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "waterbackpack"
+ item_state = "waterbackpack"
+ lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi'
+ w_class = WEIGHT_CLASS_HUGE
+ slot_flags = ITEM_SLOT_BACK
+ item_flags = SLOWS_WHILE_IN_HAND
+ max_integrity = 300
+ slowdown = 1
+ drag_slowdown = 1
+ actions_types = list(/datum/action/item_action/toggle_attachment)
+ max_integrity = 200
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
+ resistance_flags = FIRE_PROOF
+ var/on = FALSE
+ var/obj/item/stock_parts/cell/cell
+ var/preload_cell_type = /obj/item/stock_parts/cell/high
+ var/powered = FALSE
+ var/activate_sound = "sparks"
+ var/obj/item/attachment/attachment_type = /obj/item/attachment
+ var/obj/item/attachment/attachment
+
+/obj/item/gear_pack/get_cell()
+ return cell
+
+/obj/item/gear_pack/Initialize()
+ . = ..()
+ drag_slowdown = slowdown
+ attachment = new attachment_type(src)
+ cell = new(src)
+ update_power()
+ return
+
+/obj/item/gear_pack/examine(mob/user)
+ . = ..()
+ . += "It is [ on ? "currently" : "not"] active."
+ if(cell)
+ . += "A small readout reports [PERCENT(cell.charge / cell.maxcharge)]% charge."
+
+/obj/item/gear_pack/fire_act(exposed_temperature, exposed_volume)
+ . = ..()
+ if(attachment?.loc == src)
+ attachment.fire_act(exposed_temperature, exposed_volume)
+
+/obj/item/gear_pack/extinguish()
+ . = ..()
+ if(attachment?.loc == src)
+ attachment.extinguish()
+
+/obj/item/gear_pack/proc/update_power()
+ if(!QDELETED(cell))
+ if(QDELETED(attachment) || cell.charge < attachment.usecost)
+ powered = FALSE
+ else
+ powered = TRUE
+ else
+ powered = FALSE
+ update_icon()
+
+/obj/item/gear_pack/update_overlays()
+ . = ..()
+
+ if(powered)
+ . += "[initial(icon_state)]-powered"
+ if(!QDELETED(cell))
+ var/ratio = cell.charge / cell.maxcharge
+ ratio = CEILING(ratio*4, 1) * 25
+ . += "[initial(icon_state)]-charge[ratio]"
+ if(!cell)
+ . += "[initial(icon_state)]-nocell"
+ if(!on)
+ . += "[initial(icon_state)]-attachment"
+
+/obj/item/gear_pack/CheckParts(list/parts_list)
+ ..()
+ cell = locate(/obj/item/stock_parts/cell) in contents
+ update_power()
+
+/obj/item/gear_pack/ui_action_click()
+ toggle_attachment()
+
+//ATTACK HAND IGNORING PARENT RETURN VALUE
+/obj/item/gear_pack/attack_hand(mob/user)
+ if(loc == user)
+ if(slot_flags == ITEM_SLOT_BACK)
+ if(user.get_item_by_slot(ITEM_SLOT_BACK) == src)
+ ui_action_click()
+ else
+ to_chat(user, "Put the [src] on your back first!")
+
+ else if(slot_flags == ITEM_SLOT_BELT)
+ if(user.get_item_by_slot(ITEM_SLOT_BELT) == src)
+ ui_action_click()
+ else
+ to_chat(user, "Strap the [src]'s belt on first!")
+ return
+ return ..()
+
+/obj/item/gear_pack/MouseDrop(obj/over_object)
+ . = ..()
+ if(ismob(loc))
+ var/mob/M = loc
+ if(!M.incapacitated() && istype(over_object, /atom/movable/screen/inventory/hand))
+ var/atom/movable/screen/inventory/hand/H = over_object
+ M.putItemFromInventoryInHandIfPossible(src, H.held_index)
+
+/obj/item/gear_pack/attackby(obj/item/W, mob/user, params)
+ if(W == attachment)
+ toggle_attachment()
+ else if(istype(W, /obj/item/stock_parts/cell))
+ var/obj/item/stock_parts/cell/C = W
+ if(cell)
+ to_chat(user, "[src] already has a cell!")
+ else
+ if(C.maxcharge < attachment.usecost)
+ to_chat(user, "[src] requires a higher capacity cell.")
+ return
+ if(!user.transferItemToLoc(W, src))
+ return
+ cell = W
+ to_chat(user, "You install a cell in [src].")
+ update_power()
+
+ else if(W.tool_behaviour == TOOL_SCREWDRIVER)
+ if(cell)
+ cell.update_icon()
+ cell.forceMove(get_turf(src))
+ cell = null
+ to_chat(user, "You remove the cell from [src].")
+ update_power()
+ else
+ return ..()
+
+/obj/item/gear_pack/emp_act(severity)
+ . = ..()
+ if(cell && !(. & EMP_PROTECT_CONTENTS))
+ deductcharge(1000 / severity)
+ if(. & EMP_PROTECT_SELF)
+ return
+ update_power()
+
+/obj/item/gear_pack/proc/toggle_attachment()
+ set name = "Toggle Attachment"
+ set category = "Object"
+ on = !on
+
+ var/mob/living/carbon/user = usr
+ if(on)
+ //Detach the attachment into the user's hands
+ playsound(src, 'sound/items/handling/multitool_pickup.ogg', 100)
+ if(!usr.put_in_hands(attachment))
+ on = FALSE
+ to_chat(user, "You need a free hand to hold the [attachment]!")
+ update_power()
+ return
+ else
+ //Remove from their hands and back onto the gear pack
+ remove_attachment(user)
+
+ update_power()
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+
+
+/obj/item/gear_pack/equipped(mob/user, slot)
+ ..()
+ if((slot_flags == ITEM_SLOT_BACK && slot != ITEM_SLOT_BACK) || (slot_flags == ITEM_SLOT_BELT && slot != ITEM_SLOT_BELT))
+ remove_attachment(user)
+ update_power()
+
+/obj/item/gear_pack/item_action_slot_check(slot, mob/user)
+ if(slot == user.getBackSlot())
+ return 1
+
+/obj/item/gear_pack/proc/remove_attachment(mob/user)
+ if(ismob(attachment.loc))
+ var/mob/M = attachment.loc
+ M.dropItemToGround(attachment, TRUE)
+ return
+
+/obj/item/gear_pack/Destroy()
+ if(on)
+ var/M = get(attachment, /mob)
+ remove_attachment(M)
+ QDEL_NULL(attachment)
+ QDEL_NULL(cell)
+ return ..()
+
+/obj/item/gear_pack/proc/deductcharge(chrgdeductamt)
+ if(cell)
+ if(cell.charge < (attachment.usecost+chrgdeductamt))
+ powered = FALSE
+ update_power()
+ if(cell.use(chrgdeductamt))
+ update_power()
+ return TRUE
+ else
+ return FALSE
+
+/obj/item/attachment
+
+ name = "attachment"
+ desc = "The Attachment."
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "mister"
+ item_state = "mister"
+ lefthand_file = 'icons/mob/inhands/equipment/mister_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/mister_righthand.dmi'
+
+ force = 0
+ throwforce = 6
+ w_class = WEIGHT_CLASS_BULKY
+ resistance_flags = INDESTRUCTIBLE
+ base_icon_state = "mister"
+
+ var/req_pack = TRUE
+ var/usecost = 1000
+ var/obj/item/gear_pack/pack
+
+/obj/item/attachment/Initialize()
+ . = ..()
+ ADD_TRAIT(src, TRAIT_NO_STORAGE_INSERT, GENERIC_ITEM_TRAIT)
+ if (!loc || !istype(loc, /obj/item/gear_pack))
+ return INITIALIZE_HINT_QDEL
+ if(!req_pack)
+ return
+ pack = loc
+ update_icon()
+
+/obj/item/attachment/Destroy()
+ pack = null
+ return ..()
+
+/obj/item/attachment/equipped(mob/user, slot)
+ . = ..()
+ if(!req_pack)
+ return
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_range))
+
+/obj/item/attachment/Moved()
+ . = ..()
+ check_range()
+
+
+/obj/item/attachment/fire_act(exposed_temperature, exposed_volume)
+ . = ..()
+ if((req_pack && pack) && loc != pack)
+ pack.fire_act(exposed_temperature, exposed_volume)
+
+/obj/item/attachment/proc/check_range()
+ SIGNAL_HANDLER
+
+ if(!req_pack ||!pack)
+ return
+ if(!in_range(src,pack))
+ var/mob/living/L = loc
+ if(istype(L))
+ to_chat(L, "[pack]'s [src] overextends and comes out of your hands!")
+ else
+ visible_message("[src] snaps back into [pack].")
+ snap_back()
+
+/obj/item/attachment/dropped(mob/user)
+ . = ..()
+ if(!req_pack)
+ return ..()
+ if(user)
+ UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
+ if(user != loc)
+ to_chat(user, "[src] snap back into the main unit.")
+ snap_back()
+ return
+
+/obj/item/attachment/proc/snap_back()
+ if(!pack)
+ return
+ playsound()
+ pack.on = FALSE
+ forceMove(pack)
+ pack.update_power()
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index 871d17342faf..43052f1f0dbb 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -334,6 +334,9 @@
qdel(src)
/obj/structure/door_assembly/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if (I.use_tool(src, user, 3 SECONDS, volume=100))
to_chat(user, "You slice [src] apart.")
deconstruct(FALSE)
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 9771fb403f42..a81f9676eae1 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -222,6 +222,9 @@
return ..()
/obj/structure/girder/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if(I.use_tool(src, user, 3 SECONDS, volume=0))
to_chat(user, "You cut apart \the [src].", "You cut apart \the [src].")
deconstruct()
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index b4998d948530..b1897ee661d4 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -228,6 +228,9 @@
..()
/obj/structure/grille/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if (I.use_tool(src, user, 1 SECONDS, volume=100))
to_chat(user, "You slice [src] apart.")
deconstruct(FALSE)
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index 3740d09c9873..711db683cfec 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -43,7 +43,10 @@
var/turf/T = get_turf(src)
return T.attackby(C, user) //hand this off to the turf instead (for building plating, catwalks, etc)
-/obj/structure/frame/deconstruct_act(mob/living/user, obj/item/I)
+/obj/structure/lattice/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if(I.use_tool(src, user, 1 SECONDS, volume=0))
to_chat(user, "You cut apart \the [src].", "You cut apart \the [src].")
deconstruct()
diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm
index 9d0dac848376..d8f5c543a168 100644
--- a/code/game/objects/structures/railings.dm
+++ b/code/game/objects/structures/railings.dm
@@ -66,6 +66,9 @@
return TRUE
/obj/structure/railing/deconstruct_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if (I.use_tool(src, user, 3 SECONDS, volume=0))
to_chat(user, "You cut apart the railing.")
deconstruct()
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 6479fa444675..ff785e034dbe 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -229,6 +229,8 @@
/obj/structure/table/deconstruct_act(mob/living/user, obj/item/I)
. = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
if (I.use_tool(src, user, 1 SECONDS, volume=0))
to_chat(user, "You cut [src] into sheets.")
deconstruct(wrench_disassembly = TRUE)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index a250bbf85999..17b77550eaa2 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -27,6 +27,7 @@
var/real_explosion_block //ignore this, just use explosion_block
var/breaksound = "shatter"
var/hitsound = 'sound/effects/Glasshit.ogg'
+ var/decon_time = 5 SECONDS
flags_ricochet = RICOCHET_HARD
ricochet_chance_mod = 0.4
@@ -287,7 +288,10 @@
update_nearby_icons()
/obj/structure/window/deconstruct_act(mob/living/user, obj/item/I)
- if (I.use_tool(src, user, 5 SECONDS, volume=100))
+ . = ..()
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
+ if (I.use_tool(src, user, decon_time, volume=100))
to_chat(user, "You shatter [src] with the [I].")
deconstruct(FALSE)
return TRUE
@@ -402,6 +406,7 @@
glass_type = /obj/item/stack/sheet/rglass
rad_insulation = RAD_HEAVY_INSULATION
ricochet_chance_mod = 0.8
+ decon_time = 20 SECONDS
//this is shitcode but all of construction is shitcode and needs a refactor, it works for now
//If you find this like 4 years later and construction still hasn't been refactored, I'm so sorry for this
@@ -477,12 +482,6 @@
if(RWINDOW_BARS_CUT)
. += "The main pane can be easily moved out of the way to reveal some bolts holding the frame in."
-/obj/structure/window/reinforced/deconstruct_act(mob/living/user, obj/item/I)
- if (I.use_tool(src, user, 20 SECONDS, volume=100))
- to_chat(user, "You shatter [src] with the [I].")
- deconstruct(FALSE)
- return TRUE
-
/obj/structure/window/reinforced/spawner/east
dir = EAST
@@ -540,6 +539,7 @@
damage_deflection = 11 //WS Edit - Weakens R-Windows
explosion_block = 2
glass_type = /obj/item/stack/sheet/plasmarglass
+ decon_time = 25 SECONDS
//entirely copypasted code
//take this out when construction is made a component or otherwise modularized in some way
@@ -603,12 +603,6 @@
if(RWINDOW_BARS_CUT)
. += "The main pane can be easily moved out of the way to reveal some bolts holding the frame in."
-/obj/structure/window/plasma/reinforced/deconstruct_act(mob/living/user, obj/item/I)
- if (I.use_tool(src, user, 40 SECONDS, volume=100))
- to_chat(user, "You shatter [src] with the [I].")
- deconstruct(FALSE)
- return TRUE
-
/obj/structure/window/plasma/reinforced/spawner/east
dir = EAST
@@ -761,17 +755,12 @@
glass_type = /obj/item/stack/sheet/plastitaniumglass
glass_amount = 2
rad_insulation = RAD_HEAVY_INSULATION
+ decon_time = 30 SECONDS
/obj/structure/window/plasma/reinforced/plastitanium/unanchored
anchored = FALSE
state = WINDOW_OUT_OF_FRAME
-/obj/structure/window/plasma/reinforced/plastitanium/deconstruct_act(mob/living/user, obj/item/I)
- if (I.use_tool(src, user, 50 SECONDS, volume=100))
- to_chat(user, "You shatter [src] with the [I].")
- deconstruct(FALSE)
- return TRUE
-
/obj/structure/window/paperframe
name = "paper frame"
desc = "A fragile separator made of thin wood and paper."
diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm
index 553231eba416..101ba2e3a4b2 100644
--- a/code/game/turfs/closed/wall/reinf_walls.dm
+++ b/code/game/turfs/closed/wall/reinf_walls.dm
@@ -18,6 +18,7 @@
girder_type = /obj/structure/girder/reinforced
explosion_block = 2
rad_insulation = RAD_HEAVY_INSULATION
+ decon_time = 10 SECONDS
///Dismantled state, related to deconstruction.
var/d_state = INTACT
@@ -209,12 +210,6 @@
return 1
return 0
-/turf/closed/wall/r_wall/deconstruct_act(mob/living/user, obj/item/I)
- if (I.use_tool(src, user, 10 SECONDS, volume=100))
- to_chat(user, "You cut apart the wall.")
- dismantle_wall()
- return TRUE
-
/turf/closed/wall/r_wall/update_icon()
. = ..()
QUEUE_SMOOTH_NEIGHBORS(src)
diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm
index b25ec4d140c3..138bf3eaad4f 100644
--- a/code/game/turfs/closed/walls.dm
+++ b/code/game/turfs/closed/walls.dm
@@ -26,6 +26,7 @@
var/sheet_amount = 2
var/obj/girder_type = /obj/structure/girder
var/break_sound = 'sound/items/welder.ogg'
+ var/decon_time = 2 SECONDS
var/list/dent_decals
@@ -248,7 +249,9 @@
/turf/closed/wall/deconstruct_act(mob/living/user, obj/item/I)
. = ..()
- if (I.use_tool(src, user, 2 SECONDS, volume=100))
+ if(!I.tool_start_check(user, amount=0))
+ return FALSE
+ if (I.use_tool(src, user, decon_time, volume=100))
to_chat(user, "You cut apart the wall.")
dismantle_wall()
return TRUE
diff --git a/code/modules/cargo/packs/tools.dm b/code/modules/cargo/packs/tools.dm
index 78bdd3a2db4f..0458864d5918 100644
--- a/code/modules/cargo/packs/tools.dm
+++ b/code/modules/cargo/packs/tools.dm
@@ -109,7 +109,7 @@
name = "Angle Grinder"
desc = "Contains one angle grinder pack, a tool used for quick structure deconstruction and salvaging"
cost = 2000
- contains = list(/obj/item/anglegrinderpack)
+ contains = list(/obj/item/gear_pack/anglegrinder)
crate_name = "Angle Grinder"
/*
diff --git a/code/modules/mining/equipment/angle_grinder.dm b/code/modules/mining/equipment/angle_grinder.dm
index 067dfa716852..4b2ec53a67ef 100644
--- a/code/modules/mining/equipment/angle_grinder.dm
+++ b/code/modules/mining/equipment/angle_grinder.dm
@@ -1,161 +1,23 @@
-/obj/item/anglegrinderpack
+/obj/item/gear_pack/anglegrinder
name = "grinder pack"
desc = "Supplies the high voltage needed to run the attached grinder."
- icon = 'icons/obj/mining.dmi'
+ icon = 'icons/obj/item/gear_packs.dmi'
item_state = "anglegrinderpack"
icon_state = "anglegrinderpack"
lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi'
- w_class = WEIGHT_CLASS_BULKY
- slot_flags = ITEM_SLOT_BACK
- slowdown = 1
- actions_types = list(/datum/action/item_action/toggle_grinder)
- max_integrity = 200
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
- resistance_flags = FIRE_PROOF
- var/obj/item/anglegrinder/grinder
- var/obj/item/stock_parts/cell/cell
- var/preload_cell_type = /obj/item/stock_parts/cell/high
- var/power_cost = 5
-
-/obj/item/anglegrinderpack/Initialize()
- . = ..()
- grinder = make_grinder()
- if(preload_cell_type)
- if(!ispath(preload_cell_type,/obj/item/stock_parts/cell))
- log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
- else
- cell = new preload_cell_type(src)
-
-/obj/item/anglegrinderpack/Destroy()
- QDEL_NULL(grinder)
- return ..()
-
-/obj/item/anglegrinderpack/ui_action_click(mob/user)
- toggle_grinder(user)
-
-/obj/item/anglegrinder/item_action_slot_check(slot, mob/user)
- if(slot == user.getBackSlot())
- return 1
-
-/obj/item/anglegrinderpack/proc/toggle_grinder(mob/living/user)
- if(!istype(user))
- return
- if(user.get_item_by_slot(user.getBackSlot()) != src)
- to_chat(user, "[src] must be worn properly to use!")
- return
- if(user.incapacitated())
- return
- if(!cell || !cell.charge)
- return
-
- if(QDELETED(grinder))
- grinder = make_grinder()
- if(grinder in src)
- //Detach the grinder into the user's hands
- if(!user.put_in_hands(grinder))
- to_chat(user, "You need a free hand to hold the grinder!")
- return
- else
- //Remove from their hands and put back "into" the pack
- remove_grinder()
-
-/obj/item/anglegrinderpack/verb/toggle_grinder_verb()
- set name = "Toggle Angle Grinder"
- set category = "Object"
- toggle_grinder(usr)
-
-/obj/item/anglegrinderpack/proc/make_grinder()
- return new /obj/item/anglegrinder(src)
-
-/obj/item/anglegrinderpack/equipped(mob/user, slot)
- ..()
- if(slot != ITEM_SLOT_BACK)
- remove_grinder()
-
-/obj/item/anglegrinderpack/proc/remove_grinder()
- if(!QDELETED(grinder))
- if(ismob(grinder.loc))
- var/mob/M = grinder.loc
- M.temporarilyRemoveItemFromInventory(grinder, TRUE)
- grinder.forceMove(src)
-
-/obj/item/anglegrinderpack/attack_hand(mob/user)
- if (user.get_item_by_slot(user.getBackSlot()) == src)
- toggle_grinder(user)
- else
- return ..()
-
-/obj/item/anglegrinderpack/MouseDrop(obj/over_object)
- var/mob/M = loc
- if(istype(M) && istype(over_object, /atom/movable/screen/inventory/hand))
- var/atom/movable/screen/inventory/hand/H = over_object
- M.putItemFromInventoryInHandIfPossible(src, H.held_index)
- return ..()
-
-/obj/item/anglegrinderpack/attackby(obj/item/W, mob/user, params)
- if(W == grinder)
- remove_grinder()
- return 1
- else
- return ..()
+ attachment_type = /obj/item/attachment/anglegrinder
-/obj/item/anglegrinderpack/dropped(mob/user)
- ..()
- remove_grinder()
-
-/obj/item/anglegrinderpack/proc/consume_charge(cost = power_cost)
- if(!cell)
- remove_grinder()
- return
- if(cell.charge >= cost)
- cell.charge -= cost
- return TRUE
- else
- cell.charge = 0
- remove_grinder()
- return FALSE
-
-/obj/item/anglegrinderpack/attackby(obj/item/I, mob/living/user, params)
- if(I.tool_behaviour == TOOL_SCREWDRIVER)
- cell.update_appearance()
- cell.forceMove(get_turf(src))
- cell = null
- to_chat(user, "You remove the cell from [src].")
- return
- if(istype(I, /obj/item/stock_parts/cell))
- var/obj/item/stock_parts/cell/newcell = I
- if(cell)
- to_chat(user, "[src] already has a cell!")
- return
- else
- if(newcell.maxcharge < power_cost)
- to_chat(user, "[src] requires a higher capacity cell.")
- return
- if(!user.transferItemToLoc(I, src))
- return
- cell = I
- to_chat(user, "You install [cell] in [src].")
- return
-
-/obj/item/anglegrinderpack/examine(mob/user)
- . = ..()
- if(!cell)
- . += "The cell is missing!"
- else
- . += "[src] is [round(cell.percent())]% charged."
- . += "You could remove the cell with a screwdriver."
-
-/obj/item/anglegrinder
+/obj/item/attachment/anglegrinder
name = "angle grinder"
desc = "A powerful salvage tool used to cut apart walls and airlocks. A hazard sticker recommends ear and eye protection."
- icon = 'icons/obj/mining.dmi'
+ icon = 'icons/obj/item/gear_packs.dmi'
icon_state = "anglegrinder_off"
lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
flags_1 = CONDUCT_1
force = 13
- w_class = WEIGHT_CLASS_HUGE
+ w_class = WEIGHT_CLASS_BULKY
item_flags = ABSTRACT
attack_verb = list("sliced", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/anglegrinder.ogg'
@@ -163,38 +25,41 @@
sharpness = IS_SHARP
tool_behaviour = null // is set to TOOL_DECONSTRUCT once wielded
toolspeed = 1
+ usecost = 5
+ pack = /obj/item/gear_pack/anglegrinder
var/wielded = FALSE // track wielded status on item
- var/obj/item/anglegrinderpack/pack
-// Trick to make the deconstruction that need a lit welder work. (bypassing fuel test)
-/obj/item/anglegrinder/tool_use_check(mob/living/user, amount)
+/obj/item/attachment/anglegrinder/tool_start_check(mob/living/user, amount)
+ if(!pack)
+ to_chat(user, "how do you not have a pack for this. what.")
+ return FALSE
if(!pack.cell)
+ to_chat(user, "You need a cell to start!")
return FALSE
- if(pack.consume_charge())
+ var/obj/item/stock_parts/cell/cell = pack.get_cell()
+ if(cell.charge < usecost)
+ to_chat(user, "You need more charge to complete this task!")
+ return FALSE
+ return TRUE
+
+/obj/item/attachment/anglegrinder/tool_use_check(mob/living/user, amount)
+ if(!pack.cell)
+ return FALSE
+ if(pack.deductcharge(usecost))
return TRUE
else
to_chat(user, "You need more charge to complete this task!")
return FALSE
-/obj/item/anglegrinder/use(used)
+/obj/item/attachment/anglegrinder/use(used)
return TRUE
-/obj/item/anglegrinder/Initialize()
+/obj/item/attachment/anglegrinder/Initialize()
. = ..()
- pack = loc
- if(!istype(pack))
- return INITIALIZE_HINT_QDEL
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield))
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield))
-/obj/item/anglegrinder/doMove(atom/destination)
- if(destination && (destination != pack.loc || !ismob(destination)))
- if (loc != pack)
- to_chat(pack.loc, "[src] snaps back onto [pack].")
- destination = pack
- ..()
-
-/obj/item/anglegrinder/ComponentInitialize()
+/obj/item/attachment/anglegrinder/ComponentInitialize()
. = ..()
AddComponent(/datum/component/butchering, 30, 100, 0, 'sound/weapons/anglegrinder.ogg', TRUE)
AddComponent(/datum/component/two_handed)
@@ -202,7 +67,7 @@
AddElement(/datum/element/tool_bang, 2)
/// triggered on wield of two handed item
-/obj/item/anglegrinder/proc/on_wield(obj/item/source, mob/user)
+/obj/item/attachment/anglegrinder/proc/on_wield(obj/item/source, mob/user)
SIGNAL_HANDLER
playsound(src, 'sound/weapons/chainsawhit.ogg', 100, TRUE)
@@ -211,18 +76,18 @@
wielded = TRUE
/// triggered on unwield of two handed item
-/obj/item/anglegrinder/proc/on_unwield(obj/item/source, mob/user)
+/obj/item/attachment/anglegrinder/proc/on_unwield(obj/item/source, mob/user)
SIGNAL_HANDLER
force = 13
tool_behaviour = null
wielded = FALSE
-/obj/item/anglegrinder/get_dismemberment_chance()
+/obj/item/attachment/anglegrinder/get_dismemberment_chance()
if(wielded)
. = ..()
-/obj/item/anglegrinder/use_tool(atom/target, mob/living/user, delay, amount=1, volume=0, datum/callback/extra_checks)
+/obj/item/attachment/anglegrinder/use_tool(atom/target, mob/living/user, delay, amount=1, volume=0, datum/callback/extra_checks)
target.add_overlay(GLOB.cutting_effect)
. = ..()
target.cut_overlay(GLOB.cutting_effect)
diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm
index 128294707dad..f7a00f480600 100644
--- a/code/modules/surgery/organic_steps.dm
+++ b/code/modules/surgery/organic_steps.dm
@@ -152,7 +152,7 @@
implements = list(
TOOL_SAW = 100,
/obj/item/fireaxe = 50,
- /obj/item/anglegrinder = 50,
+ /obj/item/attachment/anglegrinder = 50,
/obj/item/melee/arm_blade = 40,
/obj/item/hatchet = 40,
/obj/item/kitchen/knife/butcher = 33,
@@ -160,7 +160,7 @@
time = 5.4 SECONDS
preop_sound = list(
/obj/item/circular_saw = 'sound/surgery/saw.ogg',
- /obj/item/anglegrinder = 'sound/surgery/saw.ogg',
+ /obj/item/attachment/anglegrinder = 'sound/surgery/saw.ogg',
/obj/item/melee/arm_blade = 'sound/surgery/scalpel1.ogg',
/obj/item/fireaxe = 'sound/surgery/scalpel1.ogg',
/obj/item/hatchet = 'sound/surgery/scalpel1.ogg',
diff --git a/icons/obj/item/gear_packs.dmi b/icons/obj/item/gear_packs.dmi
new file mode 100644
index 000000000000..536b64df8a7f
Binary files /dev/null and b/icons/obj/item/gear_packs.dmi differ
diff --git a/shiptest.dme b/shiptest.dme
index 7dccdf84aa12..5c83427fc062 100644
--- a/shiptest.dme
+++ b/shiptest.dme
@@ -1154,6 +1154,7 @@
#include "code\game\objects\items\extinguisher.dm"
#include "code\game\objects\items\fireaxe.dm"
#include "code\game\objects\items\flamethrower.dm"
+#include "code\game\objects\items\gear_packs.dm"
#include "code\game\objects\items\gift.dm"
#include "code\game\objects\items\granters.dm"
#include "code\game\objects\items\handcuffs.dm"