diff --git a/citadel.dme b/citadel.dme
index cf7c93cc8b7..3f9d20ee800 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -702,6 +702,8 @@
#include "code\controllers\subsystem\sound\_sound.dm"
#include "code\controllers\subsystem\sound\channel_manager.dm"
#include "code\controllers\subsystem\sound\soundbyte_manager.dm"
+#include "code\controllers\subsystem\spatial_effects\spatial_effects.dm"
+#include "code\controllers\subsystem\spatial_effects\effects\concussion_blast.dm"
#include "code\controllers\toml_config\toml_config_entry.dm"
#include "code\controllers\toml_config\toml_configuration.dm"
#include "code\controllers\toml_config\entries\backend-logging-toggles.dm"
@@ -1765,6 +1767,18 @@
#include "code\game\objects\items\devices\tape_recorder\cassette_tape.dm"
#include "code\game\objects\items\devices\tape_recorder\tape_iterator.dm"
#include "code\game\objects\items\devices\tape_recorder\tape_recorder.dm"
+#include "code\game\objects\items\grenade\grenade.dm"
+#include "code\game\objects\items\grenade\subtypes\simple.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\antiphoton.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\chemical.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\concussion.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\emp.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\explosive.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\flashbang.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\shooter.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\smokebomb.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\spawner.dm"
+#include "code\game\objects\items\grenade\subtypes\simple\supermatter.dm"
#include "code\game\objects\items\id_cards\cards.dm"
#include "code\game\objects\items\id_cards\contractor_ids.dm"
#include "code\game\objects\items\id_cards\emag.dm"
@@ -1895,18 +1909,6 @@
#include "code\game\objects\items\weapons\trays.dm"
#include "code\game\objects\items\weapons\weaponry.dm"
#include "code\game\objects\items\weapons\weldbackpack.dm"
-#include "code\game\objects\items\weapons\grenades\anti_photon_grenade.dm"
-#include "code\game\objects\items\weapons\grenades\chem_grenade.dm"
-#include "code\game\objects\items\weapons\grenades\concussion.dm"
-#include "code\game\objects\items\weapons\grenades\emgrenade.dm"
-#include "code\game\objects\items\weapons\grenades\explosive.dm"
-#include "code\game\objects\items\weapons\grenades\flashbang.dm"
-#include "code\game\objects\items\weapons\grenades\grenade.dm"
-#include "code\game\objects\items\weapons\grenades\projectile.dm"
-#include "code\game\objects\items\weapons\grenades\smokebomb.dm"
-#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"
-#include "code\game\objects\items\weapons\grenades\spawnergrenade_vr.dm"
-#include "code\game\objects\items\weapons\grenades\supermatter.dm"
#include "code\game\objects\items\weapons\implants\implant.dm"
#include "code\game\objects\items\weapons\implants\implantaugment.dm"
#include "code\game\objects\items\weapons\implants\implantcase.dm"
@@ -2388,8 +2390,8 @@
#include "code\modules\artwork\structures\poster.dm"
#include "code\modules\artwork\structures\sculpting_block.dm"
#include "code\modules\assembly\assembly.dm"
+#include "code\modules\assembly\assembly_holder.dm"
#include "code\modules\assembly\helpers.dm"
-#include "code\modules\assembly\holder.dm"
#include "code\modules\assembly\igniter.dm"
#include "code\modules\assembly\infrared.dm"
#include "code\modules\assembly\mousetrap.dm"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 51ba6f4d5a8..c968b9d8872 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -1,4 +1,5 @@
// These get to go at the top, because they're special
+
//You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects)
/* eg:
/mob/living/carbon/human/death()
@@ -11,8 +12,8 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define THIS_PROC_TYPE_STR_WITH_ARGS "[THIS_PROC_TYPE]([args.Join(",")])"
/// This one is WEIRD, in some cases (When used in certain defines? (eg: ASSERT)) THIS_PROC_TYPE will fail to work, but THIS_PROC_TYPE_WEIRD will work instead
#define THIS_PROC_TYPE_WEIRD ......
-//define THIS_PROC_TYPE_WEIRD_STR "[THIS_PROC_TYPE_WEIRD]" //Included for completeness
-//define THIS_PROC_TYPE_WEIRD_STR_WITH_ARGS "[THIS_PROC_TYPE_WEIRD]([args.Join(",")])" //Ditto
+#define THIS_PROC_TYPE_WEIRD_STR "[THIS_PROC_TYPE_WEIRD]"
+#define THIS_PROC_TYPE_WEIRD_STR_WITH_ARGS "[THIS_PROC_TYPE_WEIRD]([args.Join(",")])"
/// Invisibility constants. These should only be used for TRUE invisibility, AKA nothing living players touch
///
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index be6d5fc3afa..0ab23cb327e 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -317,7 +317,7 @@
// For objects below the top level who still want to hear.
for(var/obj/O in global.listening_objects)
- if(get_turf(O) in hearturfs)
+ if(get_turf(O) in hear)
objs |= O
return list("mobs" = mobs, "objs" = objs)
diff --git a/code/__HELPERS/lists/clone.dm b/code/__HELPERS/lists/clone.dm
index 3e81d400c62..1cdca2e970f 100644
--- a/code/__HELPERS/lists/clone.dm
+++ b/code/__HELPERS/lists/clone.dm
@@ -3,6 +3,7 @@
*
* * Any datum-types in the list must have clone() implemented.
* * This is somewhat expensive. Use sparingly.
+ * * Null is passed back as null.
*
* Valid datatypes that can be cloned:
*
@@ -12,7 +13,7 @@
* * datums with clone() implemented
*/
/proc/deep_clone_list(list/L)
- var/list/copy = L.Copy()
+ var/list/copy = L?.Copy()
for(var/i in 1 to length(copy))
var/key = copy[i]
var/value = copy[key]
diff --git a/code/controllers/subsystem/spatial_effects/effects/concussion_blast.dm b/code/controllers/subsystem/spatial_effects/effects/concussion_blast.dm
new file mode 100644
index 00000000000..520fff1f6ee
--- /dev/null
+++ b/code/controllers/subsystem/spatial_effects/effects/concussion_blast.dm
@@ -0,0 +1,52 @@
+/datum/controller/subsystem/spatial_effects/proc/run_concussion_blast(turf/location, radius)
+ // -- book-keeping --
+ log_effect_invocation("concussion_blast", args)
+ // -- end --
+
+ if(is_below_sound_pressure(location))
+ location.visible_message("Whump.")
+ return
+ playsound(location, 'sound/effects/bang.ogg', 75, 1, -3)
+ for(var/mob/living/L in orange(location, radius))
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ to_chat(H, "WHUMP.")
+
+ var/ear_safety = 0
+
+ H.get_ear_protection()
+
+ var/bang_effectiveness = H.species.sound_mod
+
+ if((get_dist(H, location) <= round(radius * 0.3 * bang_effectiveness) || location == H.loc || location == H))
+ if(ear_safety > 0)
+ H.Confuse(2)
+ else
+ H.Confuse(8)
+ H.afflict_paralyze(20 * 1)
+ if ((prob(14) || (H == location && prob(70))))
+ H.ear_damage += rand(1, 10)
+ else
+ H.ear_damage += rand(0, 5)
+ H.ear_deaf = max(H.ear_deaf,15)
+
+ else if(get_dist(H, location) <= round(radius * 0.5 * bang_effectiveness))
+ if(!ear_safety)
+ H.Confuse(6)
+ H.ear_damage += rand(0, 3)
+ H.ear_deaf = max(H.ear_deaf,10)
+
+
+ else if(!ear_safety && get_dist(H, location) <= (radius * bang_effectiveness))
+ H.Confuse(4)
+ H.ear_damage += rand(0, 1)
+ H.ear_deaf = max(H.ear_deaf,5)
+
+ if(H.ear_damage >= 15)
+ to_chat(H, "Your ears start to ring badly!")
+
+ if(prob(H.ear_damage - 5))
+ to_chat(H, "You can't hear anything!")
+ H.sdisabilities |= SDISABILITY_DEAF
+ else if(H.ear_damage >= 5)
+ to_chat(H, "Your ears start to ring!")
diff --git a/code/controllers/subsystem/spatial_effects/spatial_effects.dm b/code/controllers/subsystem/spatial_effects/spatial_effects.dm
new file mode 100644
index 00000000000..62afd3027c8
--- /dev/null
+++ b/code/controllers/subsystem/spatial_effects/spatial_effects.dm
@@ -0,0 +1,15 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2025 Citadel Station Developers *//
+
+/**
+ * A handler for things like explosions, EMPs, concussive blasts, sharpnel, etc
+ */
+SUBSYSTEM_DEF(spatial_effects)
+ name = "Spatial Effects"
+ subsystem_flags = SS_NO_FIRE | SS_NO_INIT
+
+/**
+ * All procs should call this at the top.
+ */
+/datum/controller/subsystem/spatial_effects/proc/log_effect_invocation(effect_type, list/effect_params)
+ // TODO: logging
diff --git a/code/datums/callback.dm b/code/datums/callback.dm
index 476b309cb05..b7bcd9963cb 100644
--- a/code/datums/callback.dm
+++ b/code/datums/callback.dm
@@ -65,6 +65,10 @@
delegate = proctocall
if (length(args) > 2)
arguments = args.Copy(3)
+ // todo: this is silly and admin proccall guards like this
+ // need to be re-evaluated. this will force a push-usr
+ // through things like grenade activations with a 'usr'
+ // not only is that costly but it can result in unexpected behavior
if(usr)
user = WEAKREF(usr)
diff --git a/code/datums/event_args/actor.dm b/code/datums/event_args/actor.dm
index bcc69fbbf0f..0225259951b 100644
--- a/code/datums/event_args/actor.dm
+++ b/code/datums/event_args/actor.dm
@@ -38,9 +38,8 @@
/datum/event_args/actor/proc/actor_log_string()
return performer == initiator ? key_name(performer) : "[key_name(performer)] (via [key_name(initiator)])"
-//* Feedback (//)
+//* Feedback *(//
-// todo: reowrk these awful ass feedback/message procs wtf
/datum/event_args/actor/proc/chat_feedback(msg, atom/target)
performer.action_feedback(msg, target)
@@ -52,6 +51,12 @@
if(performer != initiator)
initiator.bubble_action_feedback(msg, target)
+// todo: rework these awful ass feedback/message procs wtf
+
+// proposal:
+// visible_feedback(visible, audible, self, range, target)
+// visible_proximity_feedback(visible_far, visible_near, audible_far, audible_near, self, range_far, range_near, target)
+
/**
* It is highly recommended to use named parameters with this.
*/
diff --git a/code/datums/outfits/spec_op.dm b/code/datums/outfits/spec_op.dm
index a83c6b13de0..80ac5fb2efc 100644
--- a/code/datums/outfits/spec_op.dm
+++ b/code/datums/outfits/spec_op.dm
@@ -78,7 +78,7 @@
belt = /obj/item/nullrod
head = /obj/item/clothing/head/helmet/para
back = /obj/item/storage/backpack/ert/para
- l_pocket = /obj/item/grenade/chem_grenade/holy
+ l_pocket = /obj/item/grenade/simple/chemical/premade/holy
l_hand = /obj/item/clothing/accessory/holster/holy
id_slot = SLOT_ID_WORN_ID
diff --git a/code/datums/outfits/tournament.dm b/code/datums/outfits/tournament.dm
index 8f8ba35a599..8afe513a9b2 100644
--- a/code/datums/outfits/tournament.dm
+++ b/code/datums/outfits/tournament.dm
@@ -5,7 +5,7 @@
suit = /obj/item/clothing/suit/armor/vest
l_hand = /obj/item/material/knife
r_hand = /obj/item/gun/projectile/energy/nt_pulse/rifle
- r_pocket = /obj/item/grenade/smokebomb
+ r_pocket = /obj/item/grenade/simple/smoke
shoes = /obj/item/clothing/shoes/black
/datum/outfit/tournament_gear/red
@@ -40,8 +40,8 @@
back = /obj/item/storage/backpack
r_hand = /obj/item/mop
l_hand = /obj/item/reagent_containers/glass/bucket
- l_pocket = /obj/item/grenade/chem_grenade/cleaner
- r_pocket = /obj/item/grenade/chem_grenade/cleaner
+ l_pocket = /obj/item/grenade/simple/chemical/premade/cleaner
+ r_pocket = /obj/item/grenade/simple/chemical/premade/cleaner
backpack_contents = list(/obj/item/stack/tile/floor = 6)
/datum/outfit/tournament_gear/janitor/post_equip(var/mob/living/carbon/human/H)
diff --git a/code/datums/recipe/crafting_recipes/recipes_primal.dm b/code/datums/recipe/crafting_recipes/recipes_primal.dm
index 0348f8c51e3..2a12b2c4823 100644
--- a/code/datums/recipe/crafting_recipes/recipes_primal.dm
+++ b/code/datums/recipe/crafting_recipes/recipes_primal.dm
@@ -646,7 +646,7 @@
/datum/crafting_recipe/heaven_shaker
name = "Heaven Shaker"
- result = /obj/item/grenade/explosive/ashlander
+ result = /obj/item/grenade/simple/explosive/ashlander
time = 300
reqs = list(/obj/item/reagent_containers/glass/bucket/sandstone = 1,
/obj/item/condensedphlogiston = 3,
@@ -656,7 +656,7 @@
/datum/crafting_recipe/heaven_shaker_frag
name = "Heaven Shaker (fragmentation)"
- result = /obj/item/grenade/explosive/ashlander/fragmentation
+ result = /obj/item/grenade/simple/explosive/ashlander/fragmentation
time = 300
reqs = list(/obj/item/reagent_containers/glass/bucket/sandstone = 1,
/obj/item/condensedphlogiston = 3,
diff --git a/code/datums/recipe/crafting_recipes/recipes_weapon_and_ammo.dm b/code/datums/recipe/crafting_recipes/recipes_weapon_and_ammo.dm
index df7df341c93..963fa0a36b8 100644
--- a/code/datums/recipe/crafting_recipes/recipes_weapon_and_ammo.dm
+++ b/code/datums/recipe/crafting_recipes/recipes_weapon_and_ammo.dm
@@ -246,9 +246,9 @@
reqs = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/grenade/plastic/c4 = 1,
- /obj/item/grenade/chem_grenade = 2
+ /obj/item/grenade/simple/chemical = 2
)
- parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2)
+ parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/simple/chemical = 2)
time = 30
category = CAT_WEAPONRY
subcategory = CAT_OTHER
@@ -259,9 +259,9 @@
reqs = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/gibtonite = 1,
- /obj/item/grenade/chem_grenade = 2
+ /obj/item/grenade/simple/chemical = 2
)
- parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2)
+ parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/simple/chemical = 2)
time = 50
category = CAT_WEAPONRY
subcategory = CAT_OTHER
@@ -290,7 +290,7 @@
/datum/crafting_recipe/IED
name = "IED"
- result = /obj/item/grenade/explosive/ied
+ result = /obj/item/grenade/simple/explosive/ied
reqs = list(/datum/reagent/fuel = 50,
/obj/item/stack/cable_coil = 1,
/obj/item/assembly/igniter = 1,
@@ -503,7 +503,7 @@
/datum/crafting_recipe/improvisedslug
name = "Improvised Shotgun Shell"
result = /obj/item/ammo_casing/a12g/improvised
- reqs = list(/obj/item/grenade/chem_grenade = 1,
+ reqs = list(/obj/item/grenade/simple/chemical = 1,
/obj/item/stack/material/steel = 1,
/obj/item/stack/cable_coil = 1,
/datum/reagent/fuel = 10)
diff --git a/code/datums/uplink/grenades.dm b/code/datums/uplink/grenades.dm
index 99c3187ce10..f7f29ae589b 100644
--- a/code/datums/uplink/grenades.dm
+++ b/code/datums/uplink/grenades.dm
@@ -12,7 +12,7 @@
/datum/uplink_item/item/grenades/anti_photon_singular
name = "1xPhoton Disruption Grenade"
item_cost = 2
- path = /obj/item/grenade/anti_photon
+ path = /obj/item/grenade/simple/antiphoton
/datum/uplink_item/item/grenades/metalfoam
name = "7xMetal Foam Grenades"
@@ -22,7 +22,7 @@
/datum/uplink_item/item/grenades/metalfoam_singular
name = "1xMetal Foam Grenade"
item_cost = 2
- path = /obj/item/grenade/chem_grenade/metalfoam
+ path = /obj/item/grenade/simple/chemical/premade/metalfoam
/datum/uplink_item/item/grenades/smoke
name = "7xSmoke Grenades"
@@ -32,7 +32,7 @@
/datum/uplink_item/item/grenades/smoke_singular
name = "1xSmoke Grenade"
item_cost = 2
- path = /obj/item/grenade/smokebomb
+ path = /obj/item/grenade/simple/smoke
/datum/uplink_item/item/grenades/emp
name = "7xEMP Grenades"
@@ -42,7 +42,7 @@
/datum/uplink_item/item/grenades/emp_singular
name = "1xEMP Grenade"
item_cost = 10
- path = /obj/item/grenade/empgrenade
+ path = /obj/item/grenade/simple/emp
/datum/uplink_item/item/grenades/frags
name = "7xFrag Grenades"
@@ -57,7 +57,7 @@
/datum/uplink_item/item/grenades/frags_singular
name = "1x Frag Grenade"
item_cost = 15
- path = /obj/item/grenade/explosive
+ path = /obj/item/grenade/simple/explosive
/datum/uplink_item/item/grenades/flashbangs
name = "7xFlashbangs"
diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm
index eb2c98ed961..36e5e331e8e 100644
--- a/code/game/antagonist/outsider/raider.dm
+++ b/code/game/antagonist/outsider/raider.dm
@@ -291,9 +291,9 @@ var/datum/antagonist/raider/raiders
return
if(istype(gun, /obj/item/gun/launcher/grenade))
var/list/grenades = list(
- /obj/item/grenade/empgrenade,
- /obj/item/grenade/smokebomb,
- /obj/item/grenade/flashbang
+ /obj/item/grenade/simple/emp,
+ /obj/item/grenade/simple/smoke,
+ /obj/item/grenade/simple/flashbang
)
var/obj/item/storage/box/ammobox = new(get_turf(player.loc))
for(var/i in 1 to 7)
diff --git a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/contraband.dm b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/contraband.dm
index 545cb5c37a4..bf0444f2b09 100644
--- a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/contraband.dm
+++ b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/contraband.dm
@@ -30,8 +30,8 @@
name = "Special Ops supplies"
contains = list(
/obj/item/storage/box/emps,
- /obj/item/grenade/smokebomb = 4,
- /obj/item/grenade/chem_grenade/incendiary,
+ /obj/item/grenade/simple/smoke = 4,
+ /obj/item/grenade/simple/chemical/premade/incendiary,
)
container_type = /obj/structure/closet/crate
container_name = "Special Ops crate"
diff --git a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/hydroponics.dm b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/hydroponics.dm
index 77465a3b306..5f186b9ab66 100644
--- a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/hydroponics.dm
+++ b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/hydroponics.dm
@@ -54,7 +54,7 @@
/obj/item/material/knife/machete/hatchet = 2,
/obj/item/reagent_containers/spray/plantbgone = 4,
/obj/item/clothing/mask/gas = 2,
- /obj/item/grenade/chem_grenade/antiweed = 2,
+ /obj/item/grenade/simple/chemical/premade/antiweed = 2,
/obj/item/material/twohanded/fireaxe/scythe,
)
worth = 125
diff --git a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/munitions.dm b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/munitions.dm
index f193cd2f901..a3a75b34add 100644
--- a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/munitions.dm
+++ b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/munitions.dm
@@ -209,7 +209,7 @@
contains = list(
/obj/item/gun/projectile/ballistic/apinae_stinger = 1,
/obj/item/gun/projectile/ballistic/apinae_pistol = 2,
- /obj/item/grenade/spawnergrenade/manhacks/apidean = 3,
+ /obj/item/grenade/simple/spawner/manhacks/apidean = 3,
)
worth = 750
container_type = /obj/structure/closet/crate/secure/gear
diff --git a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/security.dm b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/security.dm
index f463dc6790e..c0ce69e8925 100644
--- a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/security.dm
+++ b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/security.dm
@@ -402,7 +402,7 @@
/obj/item/storage/belt/security,
/obj/item/flash,
/obj/item/reagent_containers/spray/pepper,
- /obj/item/grenade/flashbang,
+ /obj/item/grenade/simple/flashbang,
/obj/item/melee/baton/loaded,
/obj/item/clothing/glasses/sunglasses/sechud,
/obj/item/barrier_tape_roll/police,
diff --git a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/supplies.dm b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/supplies.dm
index 4546acbee50..fbe96842ddb 100644
--- a/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/supplies.dm
+++ b/code/game/content/factions/corporations/nanotrasen/nanotrasen-supply/supplies.dm
@@ -46,7 +46,7 @@
/obj/item/reagent_containers/spray/cleaner,
/obj/item/reagent_containers/glass/rag,
/obj/item/reagent_containers/spray/pestbgone,
- /obj/item/grenade/chem_grenade/cleaner = 3,
+ /obj/item/grenade/simple/chemical/premade/cleaner = 3,
/obj/structure/mopbucket,
)
worth = 350 // i like our service players and will not grief them with high prices
@@ -131,7 +131,7 @@
contains = list(
/obj/item/melee/thermalcutter = 1,
/obj/item/pickaxe/tyrmalin = 2,
- /obj/item/grenade/explosive/ied/tyrmalin = 2,
+ /obj/item/grenade/simple/explosive/ied/tyrmalin = 2,
)
worth = 250
container_type = /obj/structure/closet/crate/secure/gear
@@ -143,7 +143,7 @@
/datum/supply_pack/nanotrasen/misc/mining_charges_smallbulk_tyrmalin
name = "Tyrmalin Mining Charge Crate"
contains = list(
- /obj/item/grenade/explosive/ied/tyrmalin = 5,
+ /obj/item/grenade/simple/explosive/ied/tyrmalin = 5,
)
container_type = /obj/structure/closet/crate/secure/gear
container_name = "Tyrmalin Mining Charge crate"
@@ -154,7 +154,7 @@
/datum/supply_pack/nanotrasen/misc/mining_charges_largebulk_tyrmalin
name = "Bulkpurchase Tyrmalin Mining Charge Crate"
contains = list(
- /obj/item/grenade/explosive/ied/tyrmalin = 10,
+ /obj/item/grenade/simple/explosive/ied/tyrmalin = 10,
)
container_type = /obj/structure/closet/crate/secure/gear
container_name = "Tyrmalin Mining Charge crate Bulkbuy!!!"
diff --git a/code/game/machinery/computer/arcade/claw_machine.dm b/code/game/machinery/computer/arcade/claw_machine.dm
index 30b76f6a3f6..dff31de2a09 100644
--- a/code/game/machinery/computer/arcade/claw_machine.dm
+++ b/code/game/machinery/computer/arcade/claw_machine.dm
@@ -219,7 +219,7 @@
gameprice = 1
emagged = FALSE
winscreen = "You won...?"
- var/obj/item/grenade/G = new /obj/item/grenade/explosive(get_turf(src)) /// YEAAAAAAAAAAAAAAAAAAH!!!!!!!!!!
+ var/obj/item/grenade/G = new /obj/item/grenade/simple/explosive(get_turf(src)) /// YEAAAAAAAAAAAAAAAAAAH!!!!!!!!!!
G.activate()
G.throw_at_old(get_turf(usr),10,10) /// Play stupid games, win stupid prizes.
diff --git a/code/game/machinery/point_redemption_vendor/types/mining.dm b/code/game/machinery/point_redemption_vendor/types/mining.dm
index 90d944b4b3e..d17cc064b15 100644
--- a/code/game/machinery/point_redemption_vendor/types/mining.dm
+++ b/code/game/machinery/point_redemption_vendor/types/mining.dm
@@ -81,9 +81,9 @@
new /datum/point_redemption_item("Injector (L) - Panacea",/obj/item/reagent_containers/hypospray/autoinjector/biginjector/purity, 500),
new /datum/point_redemption_item("Injector (L) - Trauma",/obj/item/reagent_containers/hypospray/autoinjector/biginjector/brute, 500),
new /datum/point_redemption_item("Nanopaste Tube", /obj/item/stack/nanopaste, 1000),
- new /datum/point_redemption_item("Defense Equipment - Smoke Bomb",/obj/item/grenade/smokebomb, 100),
- new /datum/point_redemption_item("Defense Equipment - Razor Drone Deployer",/obj/item/grenade/spawnergrenade/manhacks/station/locked, 1000),
- new /datum/point_redemption_item("Defense Equipment - Sentry Drone Deployer",/obj/item/grenade/spawnergrenade/ward, 1500),
+ new /datum/point_redemption_item("Defense Equipment - Smoke Bomb",/obj/item/grenade/simple/smoke, 100),
+ new /datum/point_redemption_item("Defense Equipment - Razor Drone Deployer",/obj/item/grenade/simple/spawner/manhacks/station/locked, 1000),
+ new /datum/point_redemption_item("Defense Equipment - Sentry Drone Deployer",/obj/item/grenade/simple/spawner/ward, 1500),
new /datum/point_redemption_item("Defense Equipment - Plasteel Machete", /obj/item/clothing/accessory/holster/machete/occupied, 500),
new /datum/point_redemption_item("Defense Equipment - Kinetic Dagger", /obj/item/kinetic_crusher/dagger, 1200),
new /datum/point_redemption_item("Bar Shelter Capsule", /obj/item/survivalcapsule/luxurybar, 10000)
diff --git a/code/game/machinery/point_redemption_vendor/types/survey.dm b/code/game/machinery/point_redemption_vendor/types/survey.dm
index 0aad3e4616a..910a38ee595 100644
--- a/code/game/machinery/point_redemption_vendor/types/survey.dm
+++ b/code/game/machinery/point_redemption_vendor/types/survey.dm
@@ -14,7 +14,7 @@
new /datum/point_redemption_item("1 Marker Beacon", /obj/item/stack/marker_beacon, 1),
new /datum/point_redemption_item("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 10),
new /datum/point_redemption_item("GPS Device", /obj/item/gps/explorer, 10),
- new /datum/point_redemption_item("Defense Equipment - Smoke Bomb",/obj/item/grenade/smokebomb, 10),
+ new /datum/point_redemption_item("Defense Equipment - Smoke Bomb",/obj/item/grenade/simple/smoke, 10),
new /datum/point_redemption_item("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 10),
new /datum/point_redemption_item("Absinthe", /obj/item/reagent_containers/food/drinks/bottle/absinthe, 10),
new /datum/point_redemption_item("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 15),
@@ -43,10 +43,10 @@
new /datum/point_redemption_item("Nanopaste Tube", /obj/item/stack/nanopaste, 100),
new /datum/point_redemption_item("Binoculars", /obj/item/binoculars, 100),
new /datum/point_redemption_item("100 Thalers", /obj/item/spacecash/c100, 100),
- new /datum/point_redemption_item("Defense Equipment - Razor Drone Deployer", /obj/item/grenade/spawnergrenade/manhacks/station/locked, 100),
+ new /datum/point_redemption_item("Defense Equipment - Razor Drone Deployer", /obj/item/grenade/simple/spawner/manhacks/station/locked, 100),
new /datum/point_redemption_item("Mini-Translocator", /obj/item/perfect_tele/one_beacon, 120),
new /datum/point_redemption_item("Extraction Equipment - Fulton Pack", /obj/item/extraction_pack, 125),
- new /datum/point_redemption_item("Defense Equipment - Sentry Drone Deployer", /obj/item/grenade/spawnergrenade/ward, 150),
+ new /datum/point_redemption_item("Defense Equipment - Sentry Drone Deployer", /obj/item/grenade/simple/spawner/ward, 150),
new /datum/point_redemption_item("Holy Crusade Pack", /obj/item/storage/lockbox/crusade, 200),
new /datum/point_redemption_item("Maniple Pack", /obj/item/storage/lockbox/maniple, 200),
new /datum/point_redemption_item("Jump Boots", /obj/item/clothing/shoes/bhop, 250),
diff --git a/code/game/machinery/vending/security.dm b/code/game/machinery/vending/security.dm
index ca707959db6..d4617556ae0 100644
--- a/code/game/machinery/vending/security.dm
+++ b/code/game/machinery/vending/security.dm
@@ -7,7 +7,7 @@
req_access = list(ACCESS_SECURITY_EQUIPMENT)
products = list(
/obj/item/handcuffs = 8,
- /obj/item/grenade/flashbang = 4,
+ /obj/item/grenade/simple/flashbang = 4,
/obj/item/flash = 5,
/obj/item/reagent_containers/spray/pepper = 6,
/obj/item/reagent_containers/food/snacks/donut/normal = 12,
diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm
index 340a1466e02..0e7d682ddc0 100644
--- a/code/game/objects/empulse.dm
+++ b/code/game/objects/empulse.dm
@@ -1,3 +1,4 @@
+// TODO: put into SSspatial_effects
/**
* Legacy EMP pulses
*
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index ad70f1b30b0..51fbf1f372d 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -1,3 +1,4 @@
+// TODO: put into SSspatial_effects
//TODO: Flash range does nothing currently
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN, shaped)
diff --git a/code/game/objects/items/contraband.dm b/code/game/objects/items/contraband.dm
index eb2af8e3a75..74198de47de 100644
--- a/code/game/objects/items/contraband.dm
+++ b/code/game/objects/items/contraband.dm
@@ -112,9 +112,9 @@
/obj/item/card/id/syndicate,
/obj/item/poster,
/obj/item/disposable_teleporter,
- /obj/item/grenade/flashbang/clusterbang,
- /obj/item/grenade/flashbang/clusterbang,
- /obj/item/grenade/spawnergrenade/spesscarp,
+ /obj/item/grenade/simple/flashbang/clusterbang,
+ /obj/item/grenade/simple/flashbang/clusterbang,
+ /obj/item/grenade/simple/spawner/spesscarp,
/obj/item/melee/transforming/energy/sword/ionic_rapier,
/obj/item/clothing/shoes/syndigaloshes,
/obj/item/storage/backpack/dufflebag/syndie,
@@ -220,9 +220,9 @@
/obj/item/card/emag,
/obj/item/card/id/syndicate,
/obj/item/disposable_teleporter,
- /obj/item/grenade/flashbang/clusterbang,
- /obj/item/grenade/flashbang/clusterbang,
- /obj/item/grenade/spawnergrenade/spesscarp,
+ /obj/item/grenade/simple/flashbang/clusterbang,
+ /obj/item/grenade/simple/flashbang/clusterbang,
+ /obj/item/grenade/simple/spawner/spesscarp,
/obj/item/melee/transforming/energy/sword,
/obj/item/melee/telebaton,
/obj/item/pen/reagent/paralysis,
diff --git a/code/game/objects/items/gifts.dm b/code/game/objects/items/gifts.dm
index af41f9f6049..2437371a716 100644
--- a/code/game/objects/items/gifts.dm
+++ b/code/game/objects/items/gifts.dm
@@ -59,7 +59,7 @@ GLOBAL_LIST_EMPTY(possible_gifts)
/obj/item/pickaxe/diamond,
/obj/item/pen/invisible,
/obj/item/lipstick/random,
- /obj/item/grenade/smokebomb,
+ /obj/item/grenade/simple/smoke,
/obj/item/book/manual/chef_recipes,
/obj/item/bikehorn,
/obj/item/paicard,
diff --git a/code/game/objects/items/grenade/grenade.dm b/code/game/objects/items/grenade/grenade.dm
new file mode 100644
index 00000000000..0d4903f361b
--- /dev/null
+++ b/code/game/objects/items/grenade/grenade.dm
@@ -0,0 +1,48 @@
+/**
+ * A thing you can throw that goes boom. Simple, really, but not always.
+ *
+ * TODO: /datum/grenade_effect, much like reagent / projectile effects for composition-based
+ * grenades
+ */
+/obj/item/grenade
+ name = "grenade"
+ desc = "A hand held grenade, with an adjustable timer."
+ w_class = WEIGHT_CLASS_SMALL
+ icon = 'icons/obj/grenade.dmi'
+ icon_state = "grenade"
+ item_state = "grenade"
+ throw_speed = 4
+ throw_range = 20
+ slot_flags = SLOT_MASK|SLOT_BELT
+
+ // todo: legacy var
+ var/loadable = TRUE
+
+/obj/item/grenade/on_attack_self(datum/event_args/actor/e_args)
+ . = ..()
+ if(.)
+ return
+ if(activate_inhand(e_args))
+ return CLICKCHAIN_DID_SOMETHING
+
+/**
+ * @return TRUE to stop further inhand actions
+ */
+/obj/item/grenade/proc/activate_inhand(datum/event_args/actor/actor)
+ on_activate_inhand(actor)
+ return TRUE
+
+/obj/item/grenade/proc/on_activate_inhand(datum/event_args/actor/actor)
+ activate(actor)
+
+/obj/item/grenade/proc/activate_shot_from_gun(obj/item/gun/gun, datum/gun_firing_cycle/cycle)
+ on_activate_shot_from_gun(gun, cycle)
+
+/obj/item/grenade/proc/on_activate_shot_from_gun(obj/item/gun/gun, datum/gun_firing_cycle/cycle)
+ activate(cycle.firing_actor)
+
+/obj/item/grenade/proc/activate(datum/event_args/actor/actor)
+ on_activate(actor)
+
+/obj/item/grenade/proc/on_activate(datum/event_args/actor/actor)
+ SHOULD_CALL_PARENT(TRUE)
diff --git a/code/game/objects/items/grenade/subtypes/simple.dm b/code/game/objects/items/grenade/subtypes/simple.dm
new file mode 100644
index 00000000000..f0e27d07ec4
--- /dev/null
+++ b/code/game/objects/items/grenade/subtypes/simple.dm
@@ -0,0 +1,159 @@
+/**
+ * Simple grenade
+ *
+ * Blows up.
+ * That's it.
+ */
+/obj/item/grenade/simple
+ /// has been activated
+ var/activated = FALSE
+
+ /// you don't really have a reason to use this most of the time but it's here if you somehow do
+ /// * if this is set you have to qdel self as needed manually!
+ var/detonation_delete_self = TRUE
+ /// sound to play on detonate
+ var/detonation_sound
+
+ /// automatic detonation handling; prime once activated for [activation_detonate_delay] then detonate()
+ var/activation_detonate = TRUE
+ /// time to detonate once activated
+ /// * 0 is instant
+ var/activation_detonate_delay = 5 SECONDS
+ /// append state when active
+ var/activation_state_append = "-active"
+ /// sound to play when activated
+ var/activation_sound = 'sound/weapons/armbomb.ogg'
+
+ /// allow modifying activation delay
+ var/simple_activation_delay_tweak = TRUE
+ /// get allowed delay notches for modification
+ /// * this will be typelisted so don't edit after init!
+ var/list/simple_activation_delay_notches = list(
+ 0 SECONDS,
+ 1 SECONDS,
+ 3 SECONDS,
+ 5 SECONDS,
+ 7 SECONDS,
+ 10 SECONDS,
+ )
+
+ /// chance to automatically activate on atom_break
+ /// * only rolled if we don't self-detonate immediately
+ var/damage_failure_activation_chance = 60
+ /// chance to immediately detonate on atom_break
+ var/damage_failure_detonation_chance = 30
+
+/obj/item/grenade/simple/Initialize(mapload)
+ . = ..()
+ if(simple_activation_delay_notches)
+ simple_activation_delay_notches = typelist(NAMEOF(src, simple_activation_delay_notches), simple_activation_delay_notches)
+
+/obj/item/grenade/simple/update_overlays()
+ . = ..()
+ if(activated && activation_state_append)
+ . += "[base_icon_state || initial(icon_state)][activation_state_append]"
+
+/obj/item/grenade/simple/atom_break()
+ ..()
+ if(prob(damage_failure_detonation_chance) && !activated)
+ detonate()
+ else if(prob(damage_failure_activation_chance))
+ activate()
+
+/obj/item/grenade/simple/examine(mob/user, dist)
+ . = ..()
+ . += SPAN_NOTICE("It's set to detonate after [activation_detonate_delay * 0.1] seconds.")
+ if(should_simple_delay_adjust(new /datum/event_args/actor(user)))
+ . += SPAN_NOTICE("Use a screwdriver on this to change the fuse time.")
+
+/obj/item/grenade/simple/activate(datum/event_args/actor/actor)
+ if(activated)
+ return
+ activated = TRUE
+ return ..()
+
+/obj/item/grenade/simple/dynamic_tool_query(obj/item/I, datum/event_args/actor/clickchain/e_args)
+ if(!should_simple_delay_adjust(e_args))
+ return ..()
+ . = list(
+ TOOL_SCREWDRIVER = list(
+ "adjust fuse" = dyntool_image_neutral(TOOL_SCREWDRIVER),
+ ),
+ )
+ return merge_double_lazy_assoc_list(..(), .)
+
+/obj/item/grenade/simple/screwdriver_act(obj/item/I, datum/event_args/actor/clickchain/e_args, flags, hint)
+ . = ..()
+ if(.)
+ return
+ if(!should_simple_delay_adjust(e_args))
+ return
+ if(!use_screwdriver(I, e_args, flags, 0))
+ return TRUE
+ do_simple_delay_adjust(e_args)
+ return TRUE
+
+/obj/item/grenade/simple/proc/should_simple_delay_adjust(datum/event_args/actor/actor)
+ return simple_activation_delay_tweak
+
+/obj/item/grenade/simple/on_activate(datum/event_args/actor/actor)
+ ..()
+ if(actor)
+ msg_admin_attack("[actor.performer] primed \a [src] ([type]).")
+ if(activation_detonate)
+ if(activation_detonate_delay)
+ actor?.chat_feedback(
+ SPAN_WARNING("You prime \the [src]![activation_detonate_delay > 0 ? " [CEILING(activation_detonate_delay * 0.1, world.tick_lag)] seconds!" : ""]"),
+ target = src,
+ )
+ addtimer(CALLBACK(src, PROC_REF(detonate)), activation_detonate_delay)
+ else
+ actor?.chat_feedback(
+ SPAN_WARNING("You prime \the [src]!"),
+ target = src,
+ )
+ // TODO: this & throw mode should only happen on clickchain activation
+ add_fingerprint(actor.performer)
+ if(actor?.performer?.get_active_held_item() == src)
+ actor.performer.throw_mode_on()
+ update_icon()
+ if(activation_sound)
+ playsound(src, activation_sound, 75, TRUE, -3)
+
+/obj/item/grenade/simple/proc/detonate()
+ SHOULD_NOT_OVERRIDE(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+
+ var/turf/location = get_turf(src)
+ if(location)
+ on_detonate(location, loc)
+
+ if(detonation_delete_self)
+ qdel(src)
+
+/**
+ * perform detonation effects here
+ *
+ * * do not delete the grenade, detonate() handles this
+ */
+/obj/item/grenade/simple/proc/on_detonate(turf/location, atom/grenade_location)
+ SHOULD_CALL_PARENT(TRUE)
+
+ if(detonation_sound)
+ playsound(src, detonation_sound, 75, TRUE, 3)
+ location.hotspot_expose(700,125)
+
+/obj/item/grenade/simple/proc/do_simple_delay_adjust(datum/event_args/actor/actor)
+ if(!length(simple_activation_delay_notches))
+ return
+ var/current_index = simple_activation_delay_notches.Find(activation_detonate_delay) || round(length(simple_activation_delay_notches) / 1) || 1
+ var/new_index = current_index + 1
+ if(new_index > length(simple_activation_delay_notches))
+ new_index = 1
+ activation_detonate_delay = simple_activation_delay_notches[new_index]
+ actor?.chat_feedback(
+ SPAN_NOTICE("You set \the [src] for [activation_detonate_delay ? "[activation_detonate_delay * 0.1] second detonation time" : "instant detonation"]."),
+ target = src,
+ )
+
+ // TODO: log
diff --git a/code/game/objects/items/grenade/subtypes/simple/antiphoton.dm b/code/game/objects/items/grenade/subtypes/simple/antiphoton.dm
new file mode 100644
index 00000000000..c0c56158946
--- /dev/null
+++ b/code/game/objects/items/grenade/subtypes/simple/antiphoton.dm
@@ -0,0 +1,15 @@
+/obj/item/grenade/simple/antiphoton
+ desc = "An experimental device for temporarily removing light in a limited area."
+ name = "photon disruption grenade"
+ icon = 'icons/obj/grenade.dmi'
+ icon_state = "emp"
+ origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4)
+ activation_detonate_delay = 2 SECONDS
+ detonation_delete_self = TRUE
+ detonation_sound = 'sound/effects/phasein.ogg'
+
+/obj/item/grenade/simple/antiphoton/on_detonate(turf/location, atom/grenade_location)
+ . = ..()
+ var/extra_delay = rand(0, 9 SECONDS)
+ QDEL_IN(src, extra_delay)
+ set_light(10, -10, "#FFFFFF")
diff --git a/code/game/objects/items/grenade/subtypes/simple/chemical.dm b/code/game/objects/items/grenade/subtypes/simple/chemical.dm
new file mode 100644
index 00000000000..96860d70563
--- /dev/null
+++ b/code/game/objects/items/grenade/subtypes/simple/chemical.dm
@@ -0,0 +1,529 @@
+/obj/item/grenade/simple/chemical
+ name = "grenade casing"
+ desc = "A hand made chemical grenade."
+ icon = 'icons/items/grenade/chemical.dmi'
+ icon_state = "grenade"
+ base_icon_state = "grenade"
+ inhand_state = "grenade"
+ worn_render_flags = NONE
+ w_class = WEIGHT_CLASS_SMALL
+
+ detonation_sound = 'sound/effects/bamf.ogg'
+ activation_state_append = "-primed"
+
+ /// secured?
+ /// * once secured, things cannot be put in / taken out
+ /// * must be secured to activate
+ var/secured = FALSE
+ /// wired?
+ /// * all grenades must be wired
+ /// * wired grenades can be readied without a detonator for default timing logic
+ var/wired = FALSE
+ /// allowed number of reagent containers
+ var/beakers_max = 2
+ /// reagent containers
+ /// * all of these will be mixed inside us; technically they don't have to be beakers.
+ var/list/atom/movable/beakers = list()
+
+ // todo: legacy, assembly holders need a refactor and are shitcode
+ var/obj/item/assembly_holder/detonator
+ // todo: legacy, have a proper class system like magazines do
+ var/list/allowed_containers = list(
+ /obj/item/reagent_containers/glass/beaker,
+ /obj/item/reagent_containers/glass/bottle,
+ )
+ // todo: legacy, do it based on amount
+ var/affected_area = 3
+ // todo: need a starts with system as we don't want /chemical/large/premade vs /chemical/premade so
+ // starting with beakers logic needs to be on base /chemical
+
+/obj/item/grenade/simple/chemical/Destroy()
+ QDEL_NULL(detonator)
+ QDEL_LIST_NULL(beakers)
+ return ..()
+
+/obj/item/grenade/simple/chemical/examine(mob/user, dist)
+ . = ..()
+ if(detonator)
+ . += SPAN_NOTICE("It has a [detonator] attached to its assembly.")
+ if(secured)
+ . += SPAN_NOTICE("This one is secured. Open its panel with a screwdriver to access the internals.")
+ return
+ if(wired)
+ . += SPAN_NOTICE("It's wired and ready for assembly.")
+ else
+ . += SPAN_WARNING("It's missing a detonation mechanism. Use some wires to fix that.")
+ . += SPAN_NOTICE("It has [length(beakers)] containers inserted, with room for [beakers_max - length(beakers)] more.")
+
+/obj/item/grenade/simple/chemical/update_icon_state()
+ icon_state = "[base_icon_state || initial(icon_state)][wired ? (secured ? "-locked" : "-wired") : ""]"
+ return ..()
+
+/obj/item/grenade/simple/chemical/update_name()
+ name = "[secured ? "" : "unsecured "]grenade"
+ return ..()
+
+/obj/item/grenade/simple/chemical/should_simple_delay_adjust(datum/event_args/actor/actor)
+ return secured && ..()
+
+/obj/item/grenade/simple/chemical/context_query(datum/event_args/actor/e_args)
+ . = ..()
+ if(!detonator && !activated)
+ .["adjust-fuse"] = atom_context_tuple(
+ name = "adjust fuse",
+ I = dyntool_image_neutral(TOOL_SCREWDRIVER),
+ mobility = MOBILITY_CAN_USE,
+ )
+ if(secured)
+ .["unlock-assembly"] = atom_context_tuple(
+ name = "unlock grenade",
+ I = image(
+ /obj/item/tool/screwdriver::icon,
+ /obj/item/tool/screwdriver::icon_state,
+ ),
+ mobility = MOBILITY_CAN_USE,
+ )
+
+/obj/item/grenade/simple/chemical/context_act(datum/event_args/actor/e_args, key)
+ . = ..()
+ if(.)
+ return
+ switch(key)
+ if("adjust-fuse")
+ if(activated)
+ return TRUE
+ do_simple_delay_adjust(e_args)
+ return TRUE
+ if("unlock-assembly")
+ if(!secured)
+ return TRUE
+ if(!use_screwdriver(e_args.performer.get_active_held_item(), e_args, NONE, 0))
+ e_args?.chat_feedback(
+ SPAN_WARNING("You must be holding a screwdriver in your active hand to unsecure [src]."),
+ target = src,
+ )
+ return TRUE
+ secured = FALSE
+ e_args?.visible_feedback(
+ target = src,
+ visible = SPAN_NOTICE("[e_args.performer] [secured ? "secures" : "unsecures"] the cover of [src]."),
+ otherwise_self = SPAN_NOTICE("You [secured ? "secure" : "unsecure"] [src]'s cover."),
+ audible = SPAN_NOTICE("You hear something being [secured ? "fastened" : "unfastened"]."),
+ range = MESSAGE_RANGE_ITEM_SOFT,
+ )
+ update_appearance()
+ return TRUE
+
+/obj/item/grenade/simple/chemical/on_activate_inhand(datum/event_args/actor/actor)
+ if(!is_ready_to_activate())
+ return FALSE
+ if(detonator)
+ detonator.attack_self(actor.performer, actor)
+ return TRUE
+ if(!wired)
+ actor?.chat_feedback(
+ SPAN_WARNING("You press the activation mechanism of [src], but nothing happens."),
+ target = src,
+ )
+ return TRUE
+ return ..()
+
+/obj/item/grenade/simple/chemical/activate(datum/event_args/actor/actor)
+ if(!is_ready_to_activate())
+ return FALSE
+ if(!wired)
+ return FALSE
+ return ..()
+
+/obj/item/grenade/simple/chemical/proc/is_ready_to_activate()
+ return secured
+
+/obj/item/grenade/simple/chemical/on_attack_hand(datum/event_args/actor/clickchain/e_args)
+ if(secured)
+ return ..()
+ if(!e_args.performer.is_holding_inactive(src))
+ return ..()
+ if(detonator)
+ e_args.performer.grab_item_from_interacted_with(detonator, src)
+ e_args.chat_feedback(SPAN_NOTICE("You remove [detonator] from [src]."), src)
+ detonator = null
+ return CLICKCHAIN_DID_SOMETHING
+ else if(length(beakers))
+ var/obj/item/removed
+ for(var/obj/item/removable in beakers)
+ removed = removable
+ break
+ if(!removed)
+ e_args.chat_feedback(SPAN_WARNING("There's no removable reagent container in [src]."), target = src)
+ return CLICKCHAIN_DID_SOMETHING
+ e_args.performer.grab_item_from_interacted_with(removed, src)
+ e_args.chat_feedback(SPAN_NOTICE("You remove [removed] from [src]."), src)
+ return CLICKCHAIN_DID_SOMETHING
+ else
+ e_args.chat_feedback(SPAN_WARNING("[src] is empty."), target = src)
+ return CLICKCHAIN_DID_SOMETHING
+
+/obj/item/grenade/simple/chemical/using_item_on(obj/item/using, datum/event_args/actor/clickchain/e_args, clickchain_flags, datum/callback/reachability_check)
+ . = ..()
+ if(.)
+ return
+ if(istype(using, /obj/item/stack/cable_coil))
+ if(activated)
+ e_args.chat_feedback(
+ SPAN_WARNING("[src] is already primed! Are you crazy?"),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(wired)
+ e_args.chat_feedback(
+ SPAN_WARNING("[src] is already wired."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(secured)
+ e_args.chat_feedback(
+ SPAN_WARNING("You can't do anything to [src] while it's secured."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ var/obj/item/stack/cable_coil/casted_coil = using
+ if(!casted_coil.use(5))
+ e_args.chat_feedback(
+ SPAN_WARNING("[casted_coil] doesn't have enough cable. (need 5)"),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ wired = TRUE
+ e_args.chat_feedback(
+ SPAN_NOTICE("You wire [src]."),
+ target = src,
+ )
+ // TODO: logging
+ update_appearance()
+ return CLICKCHAIN_DID_SOMETHING
+ if(istype(using, /obj/item/assembly_holder))
+ if(activated)
+ e_args.chat_feedback(
+ SPAN_WARNING("[src] is already primed! Are you crazy?"),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(detonator)
+ e_args.chat_feedback(
+ SPAN_WARNING("[src] already has a detonator assembly attached."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(secured)
+ e_args.chat_feedback(
+ SPAN_WARNING("You can't do anything to [src] while it's secured."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ var/obj/item/assembly_holder/casted_assembly_holder = using
+ if(!casted_assembly_holder.secured)
+ e_args.chat_feedback(
+ SPAN_WARNING("[casted_assembly_holder] must be secured before insertion."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(!e_args.performer.attempt_insert_item_for_installation(using, src))
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ detonator = using
+ e_args.visible_feedback(
+ target = src,
+ range = MESSAGE_RANGE_ITEM_SOFT,
+ visible = SPAN_WARNING("[e_args.performer] slots [using] into [src]'s casing, wiring it up to the detonation mechanism."),
+ audible = SPAN_WARNING("You hear something being slotted in."),
+ otherwise_self = SPAN_WARNING("You insert [using] into [src] and wire it into the detonation mechanism."),
+ )
+ playsound(src, 'sound/items/Screwdriver2.ogg', 25, TRUE, -3)
+ // TODO: logging
+ update_appearance()
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(is_type_in_list(using, allowed_containers))
+ if(activated)
+ e_args.chat_feedback(
+ SPAN_WARNING("[src] is already primed! Are you crazy?"),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(secured)
+ e_args.chat_feedback(
+ SPAN_WARNING("You can't do anything to [src] while it's secured."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(length(beakers) > beakers_max)
+ e_args.chat_feedback(
+ SPAN_WARNING("[src] cannot hold more reagent containers."),
+ target = src,
+ )
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ if(!e_args.performer.attempt_insert_item_for_installation(using, src))
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+ e_args.visible_feedback(
+ target = src,
+ range = MESSAGE_RANGE_ITEM_SOFT,
+ visible = SPAN_WARNING("[e_args.performer] inserts [using] into [src]."),
+ audible = SPAN_WARNING("You hear something being slotted in."),
+ otherwise_self = SPAN_WARNING("You insert [using] into [src]."),
+ )
+ beakers += using
+ playsound(src, 'sound/items/Screwdriver2.ogg', 25, TRUE, -3)
+ // TODO: logging
+ update_appearance()
+ return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
+
+/obj/item/grenade/simple/chemical/screwdriver_act(obj/item/I, datum/event_args/actor/clickchain/e_args, flags, hint)
+ . = ..()
+ if(.)
+ return
+ . = TRUE
+ if(activated)
+ e_args?.chat_feedback(
+ SPAN_WARNING("[src] is already primed! Are you crazy?"),
+ target = src,
+ )
+ return
+ if(!use_screwdriver(I, e_args, flags, 0))
+ return
+ secured = !secured
+ e_args?.visible_feedback(
+ target = src,
+ visible = SPAN_NOTICE("[e_args.performer] [secured ? "secures" : "unsecures"] the cover of [src]."),
+ otherwise_self = SPAN_NOTICE("You [secured ? "secure" : "unsecure"] [src]'s cover."),
+ audible = SPAN_NOTICE("You hear something being [secured ? "fastened" : "unfastened"]."),
+ range = MESSAGE_RANGE_ITEM_SOFT,
+ )
+ update_appearance()
+
+/obj/item/grenade/simple/chemical/on_detonate(turf/location, atom/grenade_location)
+ ..()
+ // what could go wrong?
+ create_reagents(1000000)
+ load_reaction_chamber_with_ratio_of_maximum(1)
+ if(reagents.total_volume)
+ var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
+ steam.set_up(10, 0, get_turf(src))
+ steam.attach(src)
+ steam.start()
+
+ for(var/turf/spraying_turf in view(affected_area, get_turf(src)))
+ reagents.perform_uniform_contact(spraying_turf, 1)
+/**
+ * Ratio is of total beaker. 0.2 of a 100 unit will pull 20u of a total volume of 30,
+ * even if you'd expect it to pull 6.
+ */
+/obj/item/grenade/simple/chemical/proc/load_reaction_chamber_with_ratio_of_maximum(ratio)
+ for(var/atom/movable/pull_from as anything in beakers)
+ if(!pull_from.reagents)
+ continue
+ pull_from.reagents.transfer_to_holder(reagents, amount = pull_from.reagents.maximum_volume * ratio)
+
+/obj/item/grenade/simple/chemical/large
+ name = "large chem grenade"
+ desc = "An oversized grenade that affects a larger area."
+ icon_state = "grenade-large"
+ base_icon_state = "grenade-large"
+ allowed_containers = list(/obj/item/reagent_containers/glass)
+ origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
+ affected_area = 4
+
+//* presets below *//
+
+/obj/item/grenade/simple/chemical/premade
+ icon_state = "grenade-locked"
+ secured = TRUE
+ wired = TRUE
+
+/obj/item/grenade/simple/chemical/premade/metalfoam
+ name = "metal-foam grenade"
+ desc = "Used for emergency sealing of air breaches."
+
+/obj/item/grenade/simple/chemical/premade/metalfoam/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("aluminum", 30)
+ B2.reagents.add_reagent("foaming_agent", 10)
+ B2.reagents.add_reagent("pacid", 10)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/incendiary
+ name = "incendiary grenade"
+ desc = "Used for clearing rooms of living things."
+ worth_intrinsic = 150
+
+/obj/item/grenade/simple/chemical/premade/incendiary/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("aluminum", 15)
+ B1.reagents.add_reagent("fuel",20)
+ B2.reagents.add_reagent("phoron", 15)
+ B2.reagents.add_reagent("sacid", 15)
+ B1.reagents.add_reagent("fuel",20)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/antiweed
+ name = "weedkiller grenade"
+ desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents."
+
+/obj/item/grenade/simple/chemical/premade/antiweed/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("plantbgone", 25)
+ B1.reagents.add_reagent("potassium", 25)
+ B2.reagents.add_reagent("phosphorus", 25)
+ B2.reagents.add_reagent("sugar", 25)
+
+ beakers += B1
+ beakers += B2
+ icon_state = "grenade"
+
+/obj/item/grenade/simple/chemical/premade/cleaner
+ name = "cleaner grenade"
+ desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
+
+/obj/item/grenade/simple/chemical/premade/cleaner/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("fluorosurfactant", 40)
+ B2.reagents.add_reagent("water", 40)
+ B2.reagents.add_reagent("cleaner", 10)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/teargas
+ name = "tear gas grenade"
+ desc = "Concentrated Capsaicin. Contents under pressure. Use with caution."
+
+/obj/item/grenade/simple/chemical/premade/teargas/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/large/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/large/B2 = new(src)
+
+ B1.reagents.add_reagent("phosphorus", 40)
+ B1.reagents.add_reagent("potassium", 40)
+ B1.reagents.add_reagent("condensedcapsaicin", 40)
+ B2.reagents.add_reagent("sugar", 40)
+ B2.reagents.add_reagent("condensedcapsaicin", 80)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/holy
+ name = "PARA disruptor grenade"
+ desc = "These modified PMD grenades utilize a similar formula to the standard cleaning grenade, with one important substitution: holy water."
+
+/obj/item/grenade/simple/chemical/premade/holy/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("fluorosurfactant", 30)
+ B1.reagents.add_reagent("cleaner", 30)
+ B2.reagents.add_reagent("water", 30)
+ B2.reagents.add_reagent("holywater", 30)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/lube
+ name = "lubricant grenade"
+ desc = "Originally exported from Columbina, the popularity of this gag item quickly faded."
+
+/obj/item/grenade/simple/chemical/premade/lube/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("fluorosurfactant", 40)
+ B2.reagents.add_reagent("lube", 10)
+ B2.reagents.add_reagent("water", 40)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/lube_tactical
+ name = "tactical lubricant grenade"
+ desc = "Utilized by Cloumbina Commandos, this variant of the lubricant grenade delivers a more focused payload."
+
+/obj/item/grenade/simple/chemical/premade/lube_tactical/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("fluorosurfactant", 40)
+ B2.reagents.add_reagent("lube", 40)
+ B2.reagents.add_reagent("water", 10)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/chlorine_gas
+ name = "chlorine gas grenade"
+ desc = "Chlorine is a powerful corrosive. When deployed in gas form it may often be used for area denial or clearing trenches."
+
+/obj/item/grenade/simple/chemical/premade/chlorine_gas/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/large/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/large/B2 = new(src)
+
+ B1.reagents.add_reagent("phosphorus", 40)
+ B1.reagents.add_reagent("chlorine", 80)
+ B2.reagents.add_reagent("potassium", 40)
+ B2.reagents.add_reagent("sugar", 40)
+
+ beakers += B1
+ beakers += B2
+
+//Nanite Cloud Warcrimes!!!
+
+/obj/item/grenade/simple/chemical/premade/nanite_shredder
+ name = "shredder nanite grenade"
+ desc = "Weaponized nanites are banned by all galactic major powers. On the frontier however there is little authority to stop wannabee \
+ Oppenheimers from making weapons such as this."
+
+/obj/item/grenade/simple/chemical/premade/nanite_shredder/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent(/datum/reagent/phosphorus, 30)
+ B1.reagents.add_reagent(/datum/reagent/nanite/shredding, 30)
+ B2.reagents.add_reagent(/datum/reagent/potassium, 30)
+ B2.reagents.add_reagent(/datum/reagent/sugar, 30)
+
+ beakers += B1
+ beakers += B2
+
+/obj/item/grenade/simple/chemical/premade/nanite_neurophage
+ name = "neurophage nanite grenade"
+ desc = "Weaponized nanites are banned by all galactic major powers. On the frontier however there is little authority to stop wannabee \
+ Oppenheimers and other mad scientists from making weapons such as this."
+
+/obj/item/grenade/simple/chemical/premade/nanite_neurophage/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent(/datum/reagent/phosphorus, 30)
+ B1.reagents.add_reagent(/datum/reagent/nanite/neurophage, 30)
+ B2.reagents.add_reagent(/datum/reagent/potassium, 30)
+ B2.reagents.add_reagent(/datum/reagent/sugar, 30)
+
+ beakers += B1
+ beakers += B2
diff --git a/code/game/objects/items/grenade/subtypes/simple/concussion.dm b/code/game/objects/items/grenade/subtypes/simple/concussion.dm
new file mode 100644
index 00000000000..0a3cc2f26ed
--- /dev/null
+++ b/code/game/objects/items/grenade/subtypes/simple/concussion.dm
@@ -0,0 +1,24 @@
+/obj/item/grenade/simple/concussion
+ name = "concussion grenade"
+ desc = "A polymer concussion grenade, optimized for disorienting personnel without causing large amounts of injury."
+ icon_state = "concussion"
+ item_state = "grenade"
+
+ var/blast_radius = 5
+
+/obj/item/grenade/simple/concussion/on_detonate(turf/location, atom/grenade_location)
+ ..()
+ SSspatial_effects.run_concussion_blast(location, blast_radius)
+
+/obj/item/grenade/simple/concussion/frag
+ name = "concussion-frag grenade"
+ desc = "A polymer and steel concussion grenade, optimized for disorienting personnel and being accused of war crimes."
+ icon_state = "conc-frag"
+
+ var/fragment_types = list(/obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong, /obj/projectile/bullet/pellet/fragment/rubber, /obj/projectile/bullet/pellet/fragment/rubber/strong)
+ var/num_fragments = 40 //total number of fragments produced by the grenade
+ var/spread_range = 5 // for above and below, see code\game\objects\items\weapons\grenades\explosive.dm
+
+/obj/item/grenade/simple/concussion/frag/on_detonate(turf/location, atom/grenade_location)
+ ..()
+ shrapnel_explosion(num_fragments, spread_range, fragment_types)
diff --git a/code/game/objects/items/weapons/grenades/emgrenade.dm b/code/game/objects/items/grenade/subtypes/simple/emp.dm
similarity index 69%
rename from code/game/objects/items/weapons/grenades/emgrenade.dm
rename to code/game/objects/items/grenade/subtypes/simple/emp.dm
index 47f1133a941..159051e4fe2 100644
--- a/code/game/objects/items/weapons/grenades/emgrenade.dm
+++ b/code/game/objects/items/grenade/subtypes/simple/emp.dm
@@ -1,21 +1,20 @@
-/obj/item/grenade/empgrenade
+/obj/item/grenade/simple/emp
name = "emp grenade"
icon_state = "emp"
item_state = "empgrenade"
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3)
worth_intrinsic = 70
+
var/emp_heavy = 2
var/emp_med = 4
var/emp_light = 7
var/emp_long = 10
-/obj/item/grenade/empgrenade/detonate()
+/obj/item/grenade/simple/emp/on_detonate(turf/location, atom/grenade_location)
..()
- if(empulse(src, emp_heavy, emp_med, emp_light, emp_long))
- qdel(src)
- return
+ empulse(location, emp_heavy, emp_med, emp_light, emp_long)
-/obj/item/grenade/empgrenade/low_yield
+/obj/item/grenade/simple/emp/low_yield
name = "low yield emp grenade"
desc = "A weaker variant of the EMP grenade"
icon_state = "lyemp"
diff --git a/code/game/objects/items/weapons/grenades/explosive.dm b/code/game/objects/items/grenade/subtypes/simple/explosive.dm
similarity index 62%
rename from code/game/objects/items/weapons/grenades/explosive.dm
rename to code/game/objects/items/grenade/subtypes/simple/explosive.dm
index c750cac6162..bee74fd7ab9 100644
--- a/code/game/objects/items/weapons/grenades/explosive.dm
+++ b/code/game/objects/items/grenade/subtypes/simple/explosive.dm
@@ -1,127 +1,112 @@
-
-/obj/item/grenade/explosive
+/obj/item/grenade/simple/explosive
name = "fragmentation grenade"
desc = "A fragmentation grenade, optimized for harming personnel without causing massive structural damage."
- icon_state = "frggrenade"
- item_state = "grenade"
+ icon_state = "frag"
+ worn_state = "grenade"
+
+ var/ex_size_1 = 0
+ var/ex_size_2 = 0
+ var/ex_size_3 = 2
+ var/ex_size_flash = 1
var/fragment_types = list(/obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong)
- var/num_fragments = 63 //total number of fragments produced by the grenade
- var/explosion_size = 2 //size of the center explosion
-
- //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
+ /// total number of fragments produced by the grenade
+ var/num_fragments = 63
+ /// The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
var/spread_range = 7
loadable = null
-/obj/item/grenade/explosive/detonate()
+/obj/item/grenade/simple/explosive/on_detonate(turf/location)
..()
-
- var/turf/O = get_turf(src)
- if(!O) return
-
- if(explosion_size)
- on_explosion(O)
shrapnel_explosion(num_fragments, spread_range, fragment_types)
- qdel(src)
-
-/obj/item/grenade/explosive/proc/on_explosion(var/turf/O)
- if(explosion_size)
- explosion(O, -1, -1, explosion_size, round(explosion_size/2), 0)
+ explosion(location, ex_size_1, ex_size_2, ex_size_3, ex_size_flash)
// Waaaaay more pellets
-/obj/item/grenade/explosive/frag
+/obj/item/grenade/simple/explosive/frag
name = "fragmentation grenade"
desc = "A military fragmentation grenade, designed to explode in a deadly shower of fragments."
- icon_state = "frag"
+ icon_state = "frag2"
loadable = null
fragment_types = list(/obj/projectile/bullet/pellet/fragment)
num_fragments = 200 //total number of fragments produced by the grenade
-/obj/item/grenade/explosive/mini
+/obj/item/grenade/simple/explosive/mini
name = "mini fragmentation grenade"
desc = "A miniaturized fragmentation grenade, this one poses relatively little threat on its own."
icon_state = "minifrag"
fragment_types = list(/obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong)
+ ex_size_3 = 1
num_fragments = 20
spread_range = 3
- explosion_size = 1
-/obj/item/grenade/explosive/ied
+/obj/item/grenade/simple/explosive/ied
name = "improvised explosive device"
desc = "A crude explosive device made out of common household materials, designed to rupture and send shrapnel out in a wide radius."
icon_state = "ied"
fragment_types = list(/obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong)
+ ex_size_3 = 1
num_fragments = 20
spread_range = 3
- explosion_size = 1
- det_time = 20
- var/range = 3
- var/list/times
+ activation_detonate_delay = 20
-/obj/item/grenade/explosive/ied/Initialize(mapload)
+/obj/item/grenade/simple/explosive/ied/Initialize(mapload)
. = ..()
- times = list("5" = 10, "-1" = 20, "[rand(30,80)]" = 50, "[rand(65,180)]" = 20)// "Premature, Dud, Short Fuse, Long Fuse"=[weighting value]
- det_time = text2num(pickweight(times))
- if(det_time < 0) //checking for 'duds'
- range = 1
- det_time = rand(30,80)
+ var/list/times = list("5" = 10, "-1" = 20, "[rand(30,80)]" = 50, "[rand(65,180)]" = 20)// "Premature, Dud, Short Fuse, Long Fuse"=[weighting value]
+ activation_detonate_delay = text2num(pickweight(times))
+ if(activation_detonate_delay < 0) //checking for 'duds'
+ ex_size_3 = 1
+ activation_detonate_delay = rand(30,80)
else
- range = pick(2,2,2,3,3,3,4)
+ ex_size_3 = pick(2,2,2,3,3,3,4)
-/obj/item/grenade/explosive/ied/tyrmalin
+/obj/item/grenade/simple/explosive/ied/tyrmalin
name = "\improper Tyrmalin mining charge"
desc = "A stick of dynamite with a crude blasting cap and timer assembly attached. These volatile explosives are frequently used by Tyrmalin for blast mining. It does not look safe."
icon_state = "goblincharge"
+ ex_size_2 = 2
+ ex_size_3 = 4
+ ex_size_flash = 7
fragment_types = list(/obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/strong)
num_fragments = 10
spread_range = 3
- explosion_size = 1
- det_time = 20
- range = 3
+ activation_detonate_delay = 20
worth_intrinsic = 75
-/obj/item/grenade/explosive/ied/tyrmalin/on_explosion(var/turf/O)
- if(explosion_size)
- explosion(O, 0, 2, 4, 0)
-
-/obj/item/grenade/explosive/ied/tyrmalin/large
+/obj/item/grenade/simple/explosive/ied/tyrmalin/large
name = "\improper Tyrmalin heavy-duty mining charge"
desc = "A hefty bundle of hastily rigged dynamite. These bulky explosives are preferred for Tyrmalin blast mining operations. It does not look safe."
icon_state = "goblincharge_big"
+ ex_size_1 = 3
+ ex_size_2 = 5
+ ex_size_3 = 7
+ ex_size_flash = 11
fragment_types = list(/obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/strong, /obj/projectile/bullet/pellet/fragment/strong)
num_fragments = 30
spread_range = 5
- explosion_size = 2
- det_time = 20
- range = 3
-
-/obj/item/grenade/explosive/ied/tyrmalin/large/on_explosion(var/turf/O)
- if(explosion_size)
- explosion(O, 3, 5, explosion_size, round(explosion_size/2), 0)
+ activation_detonate_delay = 20
//Ashlander Frag Grenade
-/obj/item/grenade/explosive/ashlander
+/obj/item/grenade/simple/explosive/ashlander
name = "\improper heaven shaker"
desc = "A clay ball packed with alchemical solution. A small fleck of elderstone protrudes from the sphere - it looks like it can be depressed."
icon_state = "ashlandercharge"
+ ex_size_1 = 1
+ ex_size_2 = 3
+ ex_size_3 = 5
+ ex_size_flash = 7
fragment_types = list(/obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/weak, /obj/projectile/bullet/pellet/fragment/strong)
num_fragments = 5
spread_range = 3
- explosion_size = 1
- det_time = 40
+ activation_detonate_delay = 40
-/obj/item/grenade/explosive/ashlander/on_explosion(var/turf/O)
- if(explosion_size)
- explosion(O, 1, 3, explosion_size, round(explosion_size/2), 0)
-
-/obj/item/grenade/explosive/ashlander/fragmentation
+/obj/item/grenade/simple/explosive/ashlander/fragmentation
name = "\improper heaven shaker (fragmentation)"
desc = "A scored clay ball packed with alchemical solution. A small fleck of elderstone protrudes from the sphere - it looks like it can be depressed."
+ ex_size_1 = 0
+ ex_size_2 = 1
+ ex_size_3 = 3
+ ex_size_flash = 7
fragment_types = list(/obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong, /obj/projectile/bullet/pellet/fragment/strong)
num_fragments = 150
spread_range = 3
-
-/obj/item/grenade/explosive/ashlander/fragmentation/on_explosion(var/turf/O)
- if(explosion_size)
- explosion(O, 0, 1, explosion_size, round(explosion_size/2), 0)
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/grenade/subtypes/simple/flashbang.dm
similarity index 69%
rename from code/game/objects/items/weapons/grenades/flashbang.dm
rename to code/game/objects/items/grenade/subtypes/simple/flashbang.dm
index 1a447da35f2..e0ae4f650db 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/grenade/subtypes/simple/flashbang.dm
@@ -1,4 +1,4 @@
-/obj/item/grenade/flashbang
+/obj/item/grenade/simple/flashbang
name = "flashbang"
icon_state = "flashbang"
item_state = "flashbang"
@@ -7,30 +7,28 @@
var/max_range = 10 //The maximum range possible, including species effect mods. Cuts off at 7 for normal humans. Should be 3 higher than your intended target range for affecting normal humans.
var/banglet = 0
-/obj/item/grenade/flashbang/detonate()
+/obj/item/grenade/simple/flashbang/on_detonate(turf/location, atom/grenade_location)
..()
- for(var/obj/structure/closet/L in hear(max_range, get_turf(src)))
- if(locate(/mob/living/carbon/, L))
+ for(var/obj/structure/closet/L in hear(max_range, location))
+ if(locate(/mob/living/carbon, L))
for(var/mob/living/carbon/M in L)
- bang(get_turf(src), M)
+ bang(location, M)
- for(var/mob/living/carbon/M in hear(max_range, get_turf(src)))
- bang(get_turf(src), M)
+ for(var/mob/living/carbon/M in hear(max_range, location))
+ bang(location, M)
- for(var/obj/structure/blob/B in hear(max_range - 2,get_turf(src))) //Blob damage here
- var/damage = round(30/(get_dist(B,get_turf(src))+1))
+ for(var/obj/structure/blob/B in hear(max_range - 2,location)) //Blob damage here
+ var/damage = round(30 / (get_dist(B, location) + 1))
if(B.overmind)
damage *= B.overmind.blob_type.burn_multiplier
B.adjust_integrity_blob(-damage)
- new/obj/effect/particle_effect/sparks(src.loc)
- new/obj/effect/particle_effect/smoke/illumination(src.loc, 5, 30, 30, "#FFFFFF")
+ new /obj/effect/particle_effect/sparks(location)
+ new /obj/effect/particle_effect/smoke/illumination(location, 5, 30, 30, "#FFFFFF")
- qdel(src)
-
-/obj/item/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
+/obj/item/grenade/simple/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
to_chat(M, "BANG") // Called during the loop that bangs people in lockers/containers and when banging
- playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
+ playsound(T, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
// -- Polymorph
//Checking for protections
@@ -82,43 +80,45 @@
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
if (E && E.damage >= E.min_bruised_damage)
to_chat(M, "Your eyes start to burn badly!")
- if(!banglet && !(istype(src , /obj/item/grenade/flashbang/clusterbang)))
+ if(!banglet && !(istype(src , /obj/item/grenade/simple/flashbang/clusterbang)))
if (E.damage >= E.min_broken_damage)
to_chat(M, "You can't see anything!")
if (M.ear_damage >= 15)
to_chat(M, "Your ears start to ring badly!")
- if(!banglet && !(istype(src , /obj/item/grenade/flashbang/clusterbang)))
+ if(!banglet && !(istype(src , /obj/item/grenade/simple/flashbang/clusterbang)))
if (prob(M.ear_damage - 10 + 5))
to_chat(M, "You can't hear anything!")
M.sdisabilities |= SDISABILITY_DEAF
else if(M.ear_damage >= 5)
to_chat(M, "Your ears start to ring!")
-/obj/item/grenade/flashbang/Destroy()
+/obj/item/grenade/simple/flashbang/Destroy()
walk(src, 0) // Because we might have called walk_away, we must stop the walk loop or BYOND keeps an internal reference to us forever.
return ..()
-/obj/item/grenade/flashbang/stingbang
+/obj/item/grenade/simple/flashbang/on_inv_pickup(mob/wearer, datum/inventory/inventory, inv_op_flags, datum/event_args/actor/actor)
+ . = ..()
+ walk(src, NONE)
+
+/obj/item/grenade/simple/flashbang/stingbang
name = "stingbang"
desc = "A hand held grenade, with an adjustable timer, perfect for stopping riots and playing morally unthinkable pranks."
icon_state = "timeg"
+
var/fragment_types = list(/obj/projectile/bullet/pellet/fragment/rubber, /obj/projectile/bullet/pellet/fragment/rubber/strong)
var/num_fragments = 45 //total number of fragments produced by the grenade
var/spread_range = 6 // for above and below, see code\game\objects\items\weapons\grenades\explosive.dm
-/obj/item/grenade/flashbang/stingbang/detonate()
- var/turf/O = get_turf(src)
- if(!O)
- return
- shrapnel_explosion(num_fragments, spread_range, fragment_types)
+/obj/item/grenade/simple/flashbang/stingbang/on_detonate(turf/location, atom/grenade_location)
..()
+ shrapnel_explosion(num_fragments, spread_range, fragment_types)
-/obj/item/grenade/flashbang/stingbang/shredbang
+/obj/item/grenade/simple/flashbang/stingbang/shredbang
name = "shredbang"
desc = "A hand held grenade, with an adjustable timer, perfect for handling unruly citizens and getting detained by government officials."
fragment_types = list(/obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong, /obj/projectile/bullet/pellet/fragment)
-/obj/item/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
+/obj/item/grenade/simple/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
desc = "Use of this weapon may constiute a war crime in your area, consult your local Facility Director."
name = "clusterbang"
icon = 'icons/obj/grenade.dmi'
@@ -127,7 +127,8 @@
var/min_banglets = 4
var/max_banglets = 8
-/obj/item/grenade/flashbang/clusterbang/detonate()
+/obj/item/grenade/simple/flashbang/clusterbang/on_detonate(turf/location, atom/grenade_location)
+ ..()
var/numspawned = rand(min_banglets, max_banglets)
var/again = 0
@@ -138,16 +139,14 @@
numspawned--
for(var/do_spawn = numspawned, do_spawn > 0, do_spawn--)
- new /obj/item/grenade/flashbang/cluster(src.loc)//Launches flashbangs
- playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ new /obj/item/grenade/simple/flashbang/cluster(location)//Launches flashbangs
+ playsound(location, 'sound/weapons/armbomb.ogg', 75, 1, -3)
for(var/do_again = again, do_again > 0, do_again--)
- new /obj/item/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs
- playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
- qdel(src)
- return
+ new /obj/item/grenade/simple/flashbang/clusterbang/segment(location)//Creates a 'segment' that launches a few more flashbangs
+ playsound(location, 'sound/weapons/armbomb.ogg', 75, 1, -3)
-/obj/item/grenade/flashbang/clusterbang/segment
+/obj/item/grenade/simple/flashbang/clusterbang/segment
desc = "A smaller segment of a clusterbang. Better run."
name = "clusterbang segment"
icon = 'icons/obj/grenade.dmi'
@@ -155,7 +154,7 @@
can_repeat = FALSE
banglet = TRUE
-/obj/item/grenade/flashbang/clusterbang/segment/Initialize(mapload)
+/obj/item/grenade/simple/flashbang/clusterbang/segment/Initialize(mapload)
. = ..()
icon_state = "clusterbang_segment_active"
@@ -168,10 +167,10 @@
spawn(dettime)
detonate()
-/obj/item/grenade/flashbang/cluster
+/obj/item/grenade/simple/flashbang/cluster
banglet = TRUE
-/obj/item/grenade/flashbang/cluster/Initialize(mapload)
+/obj/item/grenade/simple/flashbang/cluster/Initialize(mapload)
. = ..()
icon_state = "flashbang_active"
diff --git a/code/game/objects/items/weapons/grenades/projectile.dm b/code/game/objects/items/grenade/subtypes/simple/shooter.dm
similarity index 80%
rename from code/game/objects/items/weapons/grenades/projectile.dm
rename to code/game/objects/items/grenade/subtypes/simple/shooter.dm
index 2621d12150b..8368e0cdaba 100644
--- a/code/game/objects/items/weapons/grenades/projectile.dm
+++ b/code/game/objects/items/grenade/subtypes/simple/shooter.dm
@@ -1,4 +1,4 @@
-/obj/item/grenade/shooter
+/obj/item/grenade/simple/shooter
name = "projectile grenade" // I have no idea what else to call this, but the base type should never be used
icon_state = "frggrenade"
item_state = "grenade"
@@ -11,37 +11,31 @@
loadable = FALSE
-/obj/item/grenade/shooter/detonate()
+/obj/item/grenade/simple/shooter/on_detonate(turf/location, atom/grenade_location)
..()
-
- var/turf/O = get_turf(src)
- if(!O)
- return
-
shrapnel_explosion(total_pellets, spread_range, projectile_types)
- qdel(src)
-/obj/item/grenade/shooter/rubber
+/obj/item/grenade/simple/shooter/rubber
name = "rubber pellet grenade"
desc = "An anti-riot grenade that fires a cloud of rubber projectiles upon detonation."
projectile_types = list(/obj/projectile/bullet/pistol/rubber)
// Exists mostly so I don't have to copy+paste the sprite vars to a billion things
-/obj/item/grenade/shooter/energy
+/obj/item/grenade/simple/shooter/energy
icon_state = "flashbang"
item_state = "flashbang"
spread_range = 3 // Because dear god
-/obj/item/grenade/shooter/energy/laser
+/obj/item/grenade/simple/shooter/energy/laser
name = "laser grenade"
desc = "A horrifically dangerous rave in a can."
projectile_types = list(/obj/projectile/beam/midlaser)
-/obj/item/grenade/shooter/energy/flash
+/obj/item/grenade/simple/shooter/energy/flash
name = "flash grenade"
desc = "A grenade that creates a large number of flashes upon detonation."
projectile_types = list(/obj/projectile/energy/flash)
-/obj/item/grenade/shooter/energy/tesla
+/obj/item/grenade/simple/shooter/energy/tesla
name = "tesla grenade"
projectile_types = list(/obj/projectile/beam/chain_lightning/lesser)
diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/grenade/subtypes/simple/smokebomb.dm
similarity index 63%
rename from code/game/objects/items/weapons/grenades/smokebomb.dm
rename to code/game/objects/items/grenade/subtypes/simple/smokebomb.dm
index 764e4e6aa75..8c0cf6fe078 100644
--- a/code/game/objects/items/weapons/grenades/smokebomb.dm
+++ b/code/game/objects/items/grenade/subtypes/simple/smokebomb.dm
@@ -1,9 +1,9 @@
-/obj/item/grenade/smokebomb
+/obj/item/grenade/simple/smoke
desc = "It is set to detonate in 2 seconds. These high-tech grenades can have their color adapted on the fly with a multitool!"
name = "smoke bomb"
icon = 'icons/obj/grenade.dmi'
icon_state = "flashbang"
- det_time = 20
+ activation_detonate_delay = 20
item_state = "flashbang"
slot_flags = SLOT_BELT
worth_intrinsic = 50
@@ -11,28 +11,25 @@
var/smoke_color
var/smoke_strength = 8
-/obj/item/grenade/smokebomb/Initialize(mapload)
+/obj/item/grenade/simple/smoke/Initialize(mapload)
. = ..()
src.smoke = new /datum/effect_system/smoke_spread/bad()
src.smoke.attach(src)
-/obj/item/grenade/smokebomb/Destroy()
- qdel(smoke)
- smoke = null
+/obj/item/grenade/simple/smoke/Destroy()
+ QDEL_NULL(smoke)
return ..()
-/obj/item/grenade/smokebomb/detonate()
- playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
- src.smoke.set_up(10, 0, usr.loc)
- spawn(0)
+/obj/item/grenade/simple/smoke/on_detonate(turf/location, atom/grenade_location)
+ ..()
+ playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
+ src.smoke.set_up(10, 0, location)
+ spawn()
for(var/i = 1 to smoke_strength)
src.smoke.start(smoke_color)
sleep(10)
- qdel(src)
- return
-
-/obj/item/grenade/smokebomb/attackby(obj/item/I as obj, mob/user as mob)
+/obj/item/grenade/simple/smoke/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I,/obj/item/multitool))
var/new_smoke_color = input(user, "Choose a color for the smoke:", "Smoke Color", smoke_color) as color|null
if(new_smoke_color)
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/grenade/subtypes/simple/spawner.dm
similarity index 57%
rename from code/game/objects/items/weapons/grenades/spawnergrenade.dm
rename to code/game/objects/items/grenade/subtypes/simple/spawner.dm
index 5a7bcbf2734..b566479907a 100644
--- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/grenade/subtypes/simple/spawner.dm
@@ -1,79 +1,106 @@
-/obj/item/grenade/spawnergrenade
+/obj/item/grenade/simple/spawner
desc = "It is set to detonate in 5 seconds. It will unleash unleash an unspecified anomaly into the vicinity."
name = "delivery grenade"
icon = 'icons/obj/grenade.dmi'
icon_state = "delivery"
item_state = "flashbang"
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4)
- var/banglet = 0
var/spawner_type = null // must be an object path
var/deliveryamt = 1 // amount of type to deliver
// Detonate now just handles the two loops that query for people in lockers and people who can see it.
-/obj/item/grenade/spawnergrenade/detonate()
+/obj/item/grenade/simple/spawner/on_detonate(turf/location, atom/grenade_location)
+ ..()
if(spawner_type && deliveryamt)
// Make a quick flash
- var/turf/T = get_turf(src)
- playsound(T, 'sound/effects/phasein.ogg', 100, 1)
- for(var/mob/living/carbon/human/M in viewers(T, null))
+ playsound(location, 'sound/effects/phasein.ogg', 100, 1)
+ for(var/mob/living/carbon/human/M in viewers(location, null))
if(M.eyecheck() <= 0)
M.flash_eyes()
// Spawn some hostile syndicate critters
for(var/i=1, i<=deliveryamt, i++)
- var/atom/movable/x = new spawner_type(T)
+ var/atom/movable/x = new spawner_type(location)
if(prob(50))
for(var/j = 1, j <= rand(1, 3), j++)
step(x, pick(NORTH,SOUTH,EAST,WEST))
- qdel(src)
- return
-/obj/item/grenade/spawnergrenade/manhacks
+/obj/item/grenade/simple/spawner/manhacks
name = "manhack delivery grenade"
spawner_type = /mob/living/simple_mob/mechanical/viscerator
deliveryamt = 5
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
-/obj/item/grenade/spawnergrenade/manhacks/mercenary
+/obj/item/grenade/simple/spawner/manhacks/mercenary
spawner_type = /mob/living/simple_mob/mechanical/viscerator/mercenary
-/obj/item/grenade/spawnergrenade/manhacks/raider
+/obj/item/grenade/simple/spawner/manhacks/raider
spawner_type = /mob/living/simple_mob/mechanical/viscerator/raider
-/obj/item/grenade/spawnergrenade/manhacks/station
+/obj/item/grenade/simple/spawner/manhacks/station
desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones."
deliveryamt = 3
spawner_type = /mob/living/simple_mob/mechanical/viscerator/station
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ILLEGAL = 1)
-/obj/item/grenade/spawnergrenade/manhacks/apidean
+/obj/item/grenade/simple/spawner/manhacks/station/locked
+ desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones. This one has a safety interlock that prevents release if used while in proximity to the facility."
+ req_access = list(ACCESS_SECURITY_ARMORY) //for toggling safety
+ var/locked = 1
+
+/obj/item/grenade/simple/spawner/manhacks/station/locked/activate(datum/event_args/actor/actor)
+ if(locked)
+ var/turf/T = get_turf(src)
+ if(T.z in (LEGACY_MAP_DATUM).map_levels)
+ icon_state = initial(icon_state)
+ return TRUE
+ return ..()
+
+/obj/item/grenade/simple/spawner/manhacks/station/locked/attackby(obj/item/I, mob/user)
+ var/obj/item/card/id/id = I.GetID()
+ if(istype(id))
+ if(check_access(id))
+ locked = !locked
+ to_chat(user, "You [locked ? "enable" : "disable"] the safety lock on \the [src].")
+ else
+ to_chat(user, "Access denied.")
+ user.visible_message("[user] swipes \the [I] against \the [src].")
+ else
+ return ..()
+
+/obj/item/grenade/simple/spawner/manhacks/station/locked/emag_act(var/remaining_charges,var/mob/user)
+ ..()
+ locked = !locked
+ to_chat(user, "You [locked ? "enable" : "disable"] the safety lock on \the [src]!")
+
+/obj/item/grenade/simple/spawner/manhacks/apidean
name = "\improper Apidean drone grenade"
desc = "Contains hibernating eggs of fast growing, organic kill-drones, used by Apidaen Enforcers to sweep ships and tunnels of deviants and intruders."
icon_state = "beenade"
spawner_type = /mob/living/simple_mob/mechanical/viscerator/apidean
-/obj/item/grenade/spawnergrenade/ward
+/obj/item/grenade/simple/spawner/ward
name = "sentry delivery grenade"
desc = "It is set to detonate in 5 seconds. It will deploy a single thermal-optic sentry drone."
spawner_type = /mob/living/simple_mob/mechanical/ward/monitor/crew
deliveryamt = 1
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_BLUESPACE = 2)
-/obj/item/grenade/spawnergrenade/spesscarp
+/obj/item/grenade/simple/spawner/spesscarp
name = "carp delivery grenade"
spawner_type = /mob/living/simple_mob/animal/space/carp
deliveryamt = 5
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
-/obj/item/grenade/spawnergrenade/spider
+/obj/item/grenade/simple/spawner/spider
name = "spider delivery grenade"
spawner_type = /mob/living/simple_mob/animal/giant_spider/hunter
deliveryamt = 3
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
//Sometimes you just need a sudden influx of spiders.
-/obj/item/grenade/spawnergrenade/spider/briefcase
+/obj/item/grenade/simple/spawner/spider/briefcase
name = "briefcase"
desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional."
icon_state = "briefcase"
diff --git a/code/game/objects/items/grenade/subtypes/simple/supermatter.dm b/code/game/objects/items/grenade/subtypes/simple/supermatter.dm
new file mode 100644
index 00000000000..d192a031b63
--- /dev/null
+++ b/code/game/objects/items/grenade/subtypes/simple/supermatter.dm
@@ -0,0 +1,39 @@
+/obj/item/grenade/simple/supermatter
+ name = "supermatter grenade"
+ icon_state = "banana"
+ item_state = "emergency_engi"
+ origin_tech = list(TECH_BLUESPACE = 5, TECH_MAGNET = 4, TECH_ENGINEERING = 5)
+ activation_sound = 'sound/effects/3.wav'
+ detonation_delete_self = FALSE
+
+ var/imploding = FALSE
+ var/implosion_delay = 10 SECONDS
+
+/obj/item/grenade/simple/supermatter/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/grenade/simple/supermatter/on_detonate(turf/location)
+ ..()
+ START_PROCESSING(SSobj, src)
+ addtimer(CALLBACK(src, PROC_REF(implode)), implosion_delay)
+ imploding = TRUE
+ playsound(src, 'sound/weapons/wave.ogg', 100)
+ update_icon()
+
+/obj/item/grenade/simple/supermatter/update_overlays()
+ . = ..()
+ . += image(
+ icon = 'icons/rust.dmi',
+ icon_state = "emfield_s1",
+ )
+
+/obj/item/grenade/simple/supermatter/process(delta_time)
+ if(!isturf(loc) && get_turf(src))
+ forceMove(get_turf(src))
+ playsound(src, 'sound/effects/supermatter.ogg', 100)
+ supermatter_pull(src, world.view, STAGE_THREE)
+
+/obj/item/grenade/simple/supermatter/proc/implode()
+ explosion(src, 1, 3, 5, 4)
+ qdel(src)
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index 4315f0701cd..9fc1a67a0f8 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -237,7 +237,7 @@
name = "box of flashbangs (WARNING)"
desc = "WARNING: These devices are extremely dangerous and can cause blindness or deafness in repeated use."
icon_state = "flashbang"
- starts_with = list(/obj/item/grenade/flashbang = 7)
+ starts_with = list(/obj/item/grenade/simple/flashbang = 7)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -245,7 +245,7 @@
name = "box of emp grenades"
desc = "A box containing 5 military grade EMP grenades.
WARNING: Do not use near unshielded electronics or biomechanical augmentations, death or permanent paralysis may occur."
icon_state = "emp"
- starts_with = list(/obj/item/grenade/empgrenade = 7)
+ starts_with = list(/obj/item/grenade/simple/emp = 7)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -253,7 +253,7 @@
name = "box of low yield emp grenades"
desc = "A box containing 5 low yield EMP grenades.
WARNING: Do not use near unshielded electronics or biomechanical augmentations, death or permanent paralysis may occur."
icon_state = "emp"
- starts_with = list(/obj/item/grenade/empgrenade/low_yield = 7)
+ starts_with = list(/obj/item/grenade/simple/emp/low_yield = 7)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -261,7 +261,7 @@
name = "box of smoke bombs"
desc = "A box containing 7 smoke bombs."
icon_state = "flashbang"
- starts_with = list(/obj/item/grenade/smokebomb = 7)
+ starts_with = list(/obj/item/grenade/simple/smoke = 7)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -269,7 +269,7 @@
name = "box of anti-photon grenades"
desc = "A box containing 7 experimental photon disruption grenades."
icon_state = "flashbang"
- starts_with = list(/obj/item/grenade/anti_photon = 7)
+ starts_with = list(/obj/item/grenade/simple/antiphoton = 7)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -277,7 +277,7 @@
name = "box of fragmentation grenades (WARNING)"
desc = "A box containing 7 military grade fragmentation grenades.
WARNING: These devices are extremely dangerous and can cause limb loss or death in repeated use."
icon_state = "frag"
- starts_with = list(/obj/item/grenade/explosive = 7)
+ starts_with = list(/obj/item/grenade/simple/explosive = 7)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -285,7 +285,7 @@
name = "box of fragmentation grenades (WARNING)"
desc = "A box containing 4 military grade fragmentation grenades.
WARNING: These devices are extremely dangerous and can cause limb loss or death in repeated use."
icon_state = "frag"
- starts_with = list(/obj/item/grenade/explosive = 4)
+ starts_with = list(/obj/item/grenade/simple/explosive = 4)
drop_sound = 'sound/items/drop/ammobox.ogg'
pickup_sound = 'sound/items/pickup/ammobox.ogg'
@@ -293,13 +293,13 @@
name = "box of metal foam grenades."
desc = "A box containing 7 metal foam grenades."
icon_state = "flashbang"
- starts_with = list(/obj/item/grenade/chem_grenade/metalfoam = 7)
+ starts_with = list(/obj/item/grenade/simple/chemical/premade/metalfoam = 7)
/obj/item/storage/box/teargas
name = "box of teargas grenades"
desc = "A box containing 7 teargas grenades."
icon_state = "flashbang"
- starts_with = list(/obj/item/grenade/chem_grenade/teargas = 7)
+ starts_with = list(/obj/item/grenade/simple/chemical/premade/teargas = 7)
/obj/item/storage/box/flare
name = "box of flares"
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index 5d80dd66d8a..b53a9e973df 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -78,7 +78,7 @@
name = "lockbox of clusterbangs"
desc = "You have a bad feeling about opening this."
req_access = list(ACCESS_SECURITY_EQUIPMENT)
- starts_with = list(/obj/item/grenade/flashbang/clusterbang)
+ starts_with = list(/obj/item/grenade/simple/flashbang/clusterbang)
/obj/item/storage/lockbox/medal
name = "lockbox of medals"
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index 06243540671..ec1b33e2206 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -89,7 +89,7 @@
/obj/item/pickaxe/silver,
/obj/item/pen/invisible,
/obj/item/lipstick/random,
- /obj/item/grenade/smokebomb,
+ /obj/item/grenade/simple/smoke,
/obj/item/corncob,
/obj/item/poster,
/obj/item/book/manual/barman_recipes,
@@ -204,7 +204,7 @@
/obj/item/clothing/mask/gas/skeleton,
/obj/fiftyspawner/bananium,
/obj/item/storage/backpack/holding,
- /obj/item/grenade/smokebomb,
+ /obj/item/grenade/simple/smoke,
/obj/item/toy/crossbow,
/obj/item/gun/projectile/ballistic/revolver/capgun,
/obj/item/toy/katana,
diff --git a/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm b/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm
deleted file mode 100644
index d09b46adbf9..00000000000
--- a/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm
+++ /dev/null
@@ -1,22 +0,0 @@
-/obj/item/grenade/anti_photon
- desc = "An experimental device for temporarily removing light in a limited area."
- name = "photon disruption grenade"
- icon = 'icons/obj/grenade.dmi'
- icon_state = "emp"
- det_time = 20
- origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4)
-
-/obj/item/grenade/anti_photon/detonate()
- playsound(src.loc, 'sound/effects/phasein.ogg', 50, 1, 5)
- set_light(10, -10, "#FFFFFF")
-
- var/extra_delay = rand(0,90)
-
- spawn(extra_delay)
- spawn(200)
- if(prob(10+extra_delay))
- set_light(10, 10, "#[num2hex(rand(64,255))][num2hex(rand(64,255))][num2hex(rand(64,255))]")
- spawn(210)
- ..()
- playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 5)
- qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
deleted file mode 100644
index 6454de2a994..00000000000
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ /dev/null
@@ -1,439 +0,0 @@
-/obj/item/grenade/chem_grenade
- name = "grenade casing"
- icon_state = "chemg"
- item_state = "grenade"
- desc = "A hand made chemical grenade."
- w_class = WEIGHT_CLASS_SMALL
- damage_force = 2.0
- det_time = 50
-
- var/stage = 0
- var/state = 0
- var/path = 0
- var/obj/item/assembly_holder/detonator = null
- var/list/beakers = new/list()
- var/list/allowed_containers = list(/obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle)
- var/affected_area = 3
-
-/obj/item/grenade/chem_grenade/Initialize(mapload)
- . = ..()
- create_reagents(1000)
-
-/obj/item/grenade/chem_grenade/Destroy()
- QDEL_NULL(detonator)
- QDEL_LIST_NULL(beakers)
- return ..()
-
-/obj/item/grenade/chem_grenade/attack_self(mob/user, datum/event_args/actor/actor)
- . = ..()
- if(.)
- return
- if(!stage || stage==1)
- if(detonator)
-// detonator.loc=src.loc
- detonator.detached()
- usr.put_in_hands_or_drop(detonator)
- detonator=null
- det_time = null
- stage=0
- icon_state = initial(icon_state)
- else if(beakers.len)
- for(var/obj/B in beakers)
- if(istype(B))
- beakers -= B
- user.put_in_hands_or_drop(B)
- name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
- if(stage > 1 && !active && clown_check(user))
- to_chat(user, "You prime \the [name]!")
-
- msg_admin_attack("[key_name_admin(user)] primed \a [src]")
-
- activate()
- add_fingerprint(user)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.throw_mode_on()
-
-/obj/item/grenade/chem_grenade/attackby(obj/item/W as obj, mob/user as mob)
- if(istype(W,/obj/item/assembly_holder) && (!stage || stage==1) && path != 2)
- var/obj/item/assembly_holder/det = W
- if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right)))
- to_chat(user, "Assembly must contain one igniter.")
- return
- if(!det.secured)
- to_chat(user, "Assembly must be secured with screwdriver.")
- return
- if(!user.attempt_insert_item_for_installation(det, src))
- return
- path = 1
- to_chat(user, "You add [W] to the metal casing.")
- playsound(src, 'sound/items/Screwdriver2.ogg', 25, -3)
- detonator = det
- if(istimer(detonator.a_left))
- var/obj/item/assembly/timer/T = detonator.a_left
- det_time = 10*T.time
- if(istimer(detonator.a_right))
- var/obj/item/assembly/timer/T = detonator.a_right
- det_time = 10*T.time
- icon_state = initial(icon_state) +"_ass"
- name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
- stage = 1
- else if(W.is_screwdriver() && path != 2)
- if(stage == 1)
- path = 1
- if(beakers.len)
- to_chat(user, "You lock the assembly.")
- name = "grenade"
- else
-// to_chat(user, "You need to add at least one beaker before locking the assembly.")
- to_chat(user, "You lock the empty assembly.")
- name = "fake grenade"
- playsound(src, W.tool_sound, 50, 1)
- icon_state = initial(icon_state) +"_locked"
- stage = 2
- else if(stage == 2)
- if(active && prob(95))
- to_chat(user, "You trigger the assembly!")
- detonate()
- return
- else
- to_chat(user, "You unlock the assembly.")
- playsound(src.loc, W.tool_sound, 50, -3)
- name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
- icon_state = initial(icon_state) + (detonator?"_ass":"")
- stage = 1
- active = 0
- else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2)
- path = 1
- if(beakers.len == 2)
- to_chat(user, "The grenade can not hold more containers.")
- return
- else
- if(W.reagents.total_volume)
- if(!user.attempt_insert_item_for_installation(W, src))
- return
- to_chat(user, "You add \the [W] to the assembly.")
- beakers += W
- stage = 1
- name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
- else
- to_chat(user, "\The [W] is empty.")
-
-/obj/item/grenade/chem_grenade/examine(mob/user, dist)
- . = ..()
- if(detonator)
- . += "With attached [detonator.name]"
-
-/obj/item/grenade/chem_grenade/activate(mob/user as mob)
- . = ..()
- if(detonator)
- if(!isigniter(detonator.a_left))
- detonator.a_left.activate()
- active = 1
- if(!isigniter(detonator.a_right))
- detonator.a_right.activate()
- active = 1
-
-
-/obj/item/grenade/chem_grenade/proc/primed(var/primed = 1)
- if(active)
- icon_state = initial(icon_state) + (primed?"_primed":"_active")
-
-/obj/item/grenade/chem_grenade/detonate()
- if(!stage || stage<2) return
-
- var/has_reagents = 0
- for(var/obj/item/reagent_containers/glass/G in beakers)
- if(G.reagents.total_volume) has_reagents = 1
-
- active = 0
- if(!has_reagents)
- icon_state = initial(icon_state) +"_locked"
- playsound(src.loc, 'sound/items/Screwdriver2.ogg', 50, 1)
- spawn(0) //Otherwise det_time is erroneously set to 0 after this
- if(istimer(detonator.a_left)) //Make sure description reflects that the timer has been reset
- var/obj/item/assembly/timer/T = detonator.a_left
- det_time = 10*T.time
- if(istimer(detonator.a_right))
- var/obj/item/assembly/timer/T = detonator.a_right
- det_time = 10*T.time
- return
-
- playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
-
- for(var/obj/item/reagent_containers/glass/G in beakers)
- G.reagents.trans_to_obj(src, G.reagents.total_volume)
-
- if(src.reagents.total_volume) //The possible reactions didnt use up all reagents.
- var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
- steam.set_up(10, 0, get_turf(src))
- steam.attach(src)
- steam.start()
-
- for(var/turf/spraying_turf in view(affected_area, get_turf(src)))
- reagents.perform_uniform_contact(spraying_turf, 1)
-
- if(istype(loc, /mob/living/carbon)) //drop dat grenade if it goes off in your hand
- var/mob/living/carbon/C = loc
- C.drop_item_to_ground(src, INV_OP_FORCE)
- C.throw_mode_off()
-
- invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
- spawn(50) //To make sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
-
-
-/obj/item/grenade/chem_grenade/large
- name = "large chem grenade"
- desc = "An oversized grenade that affects a larger area."
- icon_state = "large_grenade"
- allowed_containers = list(/obj/item/reagent_containers/glass)
- origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
- affected_area = 4
-
-/obj/item/grenade/chem_grenade/metalfoam
- name = "metal-foam grenade"
- desc = "Used for emergency sealing of air breaches."
- path = 1
- stage = 2
-
-/obj/item/grenade/chem_grenade/metalfoam/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("aluminum", 30)
- B2.reagents.add_reagent("foaming_agent", 10)
- B2.reagents.add_reagent("pacid", 10)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/incendiary
- name = "incendiary grenade"
- desc = "Used for clearing rooms of living things."
- path = 1
- stage = 2
- worth_intrinsic = 150
-
-/obj/item/grenade/chem_grenade/incendiary/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("aluminum", 15)
- B1.reagents.add_reagent("fuel",20)
- B2.reagents.add_reagent("phoron", 15)
- B2.reagents.add_reagent("sacid", 15)
- B1.reagents.add_reagent("fuel",20)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/antiweed
- name = "weedkiller grenade"
- desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents."
- path = 1
- stage = 2
-
-/obj/item/grenade/chem_grenade/antiweed/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("plantbgone", 25)
- B1.reagents.add_reagent("potassium", 25)
- B2.reagents.add_reagent("phosphorus", 25)
- B2.reagents.add_reagent("sugar", 25)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = "grenade"
-
-/obj/item/grenade/chem_grenade/cleaner
- name = "cleaner grenade"
- desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/cleaner/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("fluorosurfactant", 40)
- B2.reagents.add_reagent("water", 40)
- B2.reagents.add_reagent("cleaner", 10)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/teargas
- name = "tear gas grenade"
- desc = "Concentrated Capsaicin. Contents under pressure. Use with caution."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/teargas/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/large/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/large/B2 = new(src)
-
- B1.reagents.add_reagent("phosphorus", 40)
- B1.reagents.add_reagent("potassium", 40)
- B1.reagents.add_reagent("condensedcapsaicin", 40)
- B2.reagents.add_reagent("sugar", 40)
- B2.reagents.add_reagent("condensedcapsaicin", 80)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/holy
- name = "PARA disruptor grenade"
- desc = "These modified PMD grenades utilize a similar formula to the standard cleaning grenade, with one important substitution: holy water."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/holy/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("fluorosurfactant", 30)
- B1.reagents.add_reagent("cleaner", 30)
- B2.reagents.add_reagent("water", 30)
- B2.reagents.add_reagent("holywater", 30)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/lube
- name = "lubricant grenade"
- desc = "Originally exported from Columbina, the popularity of this gag item quickly faded."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/lube/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("fluorosurfactant", 40)
- B2.reagents.add_reagent("lube", 10)
- B2.reagents.add_reagent("water", 40)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/lube_tactical
- name = "tactical lubricant grenade"
- desc = "Utilized by Cloumbina Commandos, this variant of the lubricant grenade delivers a more focused payload."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/lube_tactical/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent("fluorosurfactant", 40)
- B2.reagents.add_reagent("lube", 40)
- B2.reagents.add_reagent("water", 10)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/chlorine_gas
- name = "chlorine gas grenade"
- desc = "Chlorine is a powerful corrosive. When deployed in gas form it may often be used for area denial or clearing trenches."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/chlorine_gas/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/large/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/large/B2 = new(src)
-
- B1.reagents.add_reagent("phosphorus", 40)
- B1.reagents.add_reagent("chlorine", 80)
- B2.reagents.add_reagent("potassium", 40)
- B2.reagents.add_reagent("sugar", 40)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-
-
-//Nanite Cloud Warcrimes!!!
-
-/obj/item/grenade/chem_grenade/nanite_shredder
- name = "shredder nanite grenade"
- desc = "Weaponized nanites are banned by all galactic major powers. On the frontier however there is little authority to stop wannabee \
- Oppenheimers from making weapons such as this."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/nanite_shredder/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent(/datum/reagent/phosphorus, 30)
- B1.reagents.add_reagent(/datum/reagent/nanite/shredding, 30)
- B2.reagents.add_reagent(/datum/reagent/potassium, 30)
- B2.reagents.add_reagent(/datum/reagent/sugar, 30)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
-
-/obj/item/grenade/chem_grenade/nanite_neurophage
- name = "neurophage nanite grenade"
- desc = "Weaponized nanites are banned by all galactic major powers. On the frontier however there is little authority to stop wannabee \
- Oppenheimers and other mad scientists from making weapons such as this."
- stage = 2
- path = 1
-
-/obj/item/grenade/chem_grenade/nanite_neurophage/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
- var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
-
- B1.reagents.add_reagent(/datum/reagent/phosphorus, 30)
- B1.reagents.add_reagent(/datum/reagent/nanite/neurophage, 30)
- B2.reagents.add_reagent(/datum/reagent/potassium, 30)
- B2.reagents.add_reagent(/datum/reagent/sugar, 30)
-
- detonator = new/obj/item/assembly_holder/timer_igniter(src)
-
- beakers += B1
- beakers += B2
- icon_state = initial(icon_state) +"_locked"
diff --git a/code/game/objects/items/weapons/grenades/concussion.dm b/code/game/objects/items/weapons/grenades/concussion.dm
deleted file mode 100644
index c3ea4db24d4..00000000000
--- a/code/game/objects/items/weapons/grenades/concussion.dm
+++ /dev/null
@@ -1,88 +0,0 @@
-//Concussion, or 'dizzyness' grenades.
-
-/obj/item/grenade/concussion
- name = "concussion grenade"
- desc = "A polymer concussion grenade, optimized for disorienting personnel without causing large amounts of injury."
- icon_state = "concussion"
- item_state = "grenade"
-
- var/blast_radius = 5
-
-/obj/item/grenade/concussion/detonate()
- ..()
- concussion_blast(get_turf(src), blast_radius)
- qdel(src)
- return
-
-/obj/proc/concussion_blast(atom/target, var/radius = 5)
- var/turf/T = get_turf(target)
- if(is_below_sound_pressure(T))
- visible_message("Whump.")
- return
- playsound(src.loc, 'sound/effects/bang.ogg', 75, 1, -3)
- if(istype(T))
- for(var/mob/living/L in orange(T, radius))
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- to_chat(H, "WHUMP.")
-
- var/ear_safety = 0
-
- H.get_ear_protection()
-
- var/bang_effectiveness = H.species.sound_mod
-
- if((get_dist(H, T) <= round(radius * 0.3 * bang_effectiveness) || src.loc == H.loc || src.loc == H))
- if(ear_safety > 0)
- H.Confuse(2)
- else
- H.Confuse(8)
- H.afflict_paralyze(20 * 1)
- if ((prob(14) || (H == src.loc && prob(70))))
- H.ear_damage += rand(1, 10)
- else
- H.ear_damage += rand(0, 5)
- H.ear_deaf = max(H.ear_deaf,15)
-
- else if(get_dist(H, T) <= round(radius * 0.5 * bang_effectiveness))
- if(!ear_safety)
- H.Confuse(6)
- H.ear_damage += rand(0, 3)
- H.ear_deaf = max(H.ear_deaf,10)
-
-
- else if(!ear_safety && get_dist(H, T) <= (radius * bang_effectiveness))
- H.Confuse(4)
- H.ear_damage += rand(0, 1)
- H.ear_deaf = max(H.ear_deaf,5)
-
- if(H.ear_damage >= 15)
- to_chat(H, "Your ears start to ring badly!")
-
- if(prob(H.ear_damage - 5))
- to_chat(H, "You can't hear anything!")
- H.sdisabilities |= SDISABILITY_DEAF
- else if(H.ear_damage >= 5)
- to_chat(H, "Your ears start to ring!")
- /* Until someone can come up with a better thing to have happen to borgs like a stun or something this is getting commented out
- if(istype(L, /mob/living/silicon/robot))
- var/mob/living/silicon/robot/R = L
- if(L.client)
- to_chat(R, "Gyroscopic failure.")
- */
- return
-
-/obj/item/grenade/concussion/frag
- name = "concussion-frag grenade"
- desc = "A polymer and steel concussion grenade, optimized for disorienting personnel and being accused of war crimes."
- icon_state = "conc-frag"
- var/fragment_types = list(/obj/projectile/bullet/pellet/fragment, /obj/projectile/bullet/pellet/fragment/strong, /obj/projectile/bullet/pellet/fragment/rubber, /obj/projectile/bullet/pellet/fragment/rubber/strong)
- var/num_fragments = 40 //total number of fragments produced by the grenade
- var/spread_range = 5 // for above and below, see code\game\objects\items\weapons\grenades\explosive.dm
-
-/obj/item/grenade/concussion/frag/detonate()
- var/turf/O = get_turf(src)
- if(!O)
- return
- shrapnel_explosion(num_fragments, spread_range, fragment_types)
- ..()
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
deleted file mode 100644
index 838dc3ec7d3..00000000000
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ /dev/null
@@ -1,117 +0,0 @@
-/obj/item/grenade
- name = "grenade"
- desc = "A hand held grenade, with an adjustable timer."
- w_class = WEIGHT_CLASS_SMALL
- icon = 'icons/obj/grenade.dmi'
- icon_state = "grenade"
- item_state = "grenade"
- throw_speed = 4
- throw_range = 20
- slot_flags = SLOT_MASK|SLOT_BELT
-
- var/active = 0
- var/det_time = 50
- var/loadable = TRUE
- var/arm_sound = 'sound/weapons/armbomb.ogg'
-
-/obj/item/grenade/proc/clown_check(var/mob/living/user)
- if((MUTATION_CLUMSY in user.mutations) && prob(50))
- to_chat(user, "Huh? How does this thing work?")
-
- activate(user)
- add_fingerprint(user)
- spawn(5)
- detonate()
- return 0
- return 1
-
-
-/*/obj/item/grenade/afterattack(atom/target, mob/user, clickchain_flags, list/params)
- if (istype(target, /obj/item/storage)) return ..() // Trying to put it in a full container
- if (istype(target, /obj/item/gun/grenadelauncher)) return ..()
- if((user.get_active_held_item() == src) && (!active) && (clown_check(user)) && target.loc != src.loc)
- to_chat(user, "You prime the [name]! [det_time/10] seconds!")
- active = 1
- icon_state = initial(icon_state) + "_active"
- playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
- spawn(det_time)
- detonate()
- return
- user.setDir(get_dir(user, target))
- user.drop_item()
- var/t = (isturf(target) ? target : target.loc)
- walk_towards(src, t, 3)
- return*/
-
-
-/obj/item/grenade/examine(mob/user, dist)
- . = ..()
- if(det_time > 1)
- . += "The timer is set to [det_time/10] seconds."
- return
- if(det_time == null)
- . += "The [src] is set for instant detonation."
-
-
-/obj/item/grenade/attack_self(mob/user, datum/event_args/actor/actor)
- . = ..()
- if(.)
- return
- if(!active)
- if(clown_check(user))
- to_chat(user, "You prime \the [name]! [det_time/10] seconds!")
-
- activate(user)
- add_fingerprint(user)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.throw_mode_on()
- return
-
-
-/obj/item/grenade/proc/activate(mob/user as mob)
- if(active)
- return
-
- if(user)
- msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
-
- icon_state = initial(icon_state) + "_active"
- active = 1
- playsound(loc, arm_sound, 75, 1, -3)
-
- spawn(det_time)
- detonate()
- return
-
-
-/obj/item/grenade/proc/detonate()
-// playsound(loc, 'sound/items/Welder2.ogg', 25, 1)
- var/turf/T = get_turf(src)
- if(T)
- T.hotspot_expose(700,125)
-
-
-/obj/item/grenade/attackby(obj/item/W as obj, mob/user as mob)
- if(W.is_screwdriver())
- switch(det_time)
- if (1)
- det_time = 10
- to_chat(user, "You set the [name] for 1 second detonation time.")
- if (10)
- det_time = 30
- to_chat(user, "You set the [name] for 3 second detonation time.")
- if (30)
- det_time = 50
- to_chat(user, "You set the [name] for 5 second detonation time.")
- if (50)
- det_time = 1
- to_chat(user, "You set the [name] for instant detonation.")
- add_fingerprint(user)
- ..()
- return
-
-/obj/item/grenade/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
- walk(src, null, null)
- ..()
- return
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade_vr.dm b/code/game/objects/items/weapons/grenades/spawnergrenade_vr.dm
deleted file mode 100644
index 53862420345..00000000000
--- a/code/game/objects/items/weapons/grenades/spawnergrenade_vr.dm
+++ /dev/null
@@ -1,30 +0,0 @@
-/obj/item/grenade/spawnergrenade/manhacks/station/locked
- desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones. This one has a safety interlock that prevents release if used while in proximity to the facility."
- req_access = list(ACCESS_SECURITY_ARMORY) //for toggling safety
- var/locked = 1
-
-/obj/item/grenade/spawnergrenade/manhacks/station/locked/detonate()
- if(locked)
- var/turf/T = get_turf(src)
- if(T.z in (LEGACY_MAP_DATUM).map_levels)
- icon_state = initial(icon_state)
- active = 0
- return 0
- return ..()
-
-/obj/item/grenade/spawnergrenade/manhacks/station/locked/attackby(obj/item/I, mob/user)
- var/obj/item/card/id/id = I.GetID()
- if(istype(id))
- if(check_access(id))
- locked = !locked
- to_chat(user, "You [locked ? "enable" : "disable"] the safety lock on \the [src].")
- else
- to_chat(user, "Access denied.")
- user.visible_message("[user] swipes \the [I] against \the [src].")
- else
- return ..()
-
-/obj/item/grenade/spawnergrenade/manhacks/station/locked/emag_act(var/remaining_charges,var/mob/user)
- ..()
- locked = !locked
- to_chat(user, "You [locked ? "enable" : "disable"] the safety lock on \the [src]!")
diff --git a/code/game/objects/items/weapons/grenades/supermatter.dm b/code/game/objects/items/weapons/grenades/supermatter.dm
deleted file mode 100644
index cc194536a67..00000000000
--- a/code/game/objects/items/weapons/grenades/supermatter.dm
+++ /dev/null
@@ -1,34 +0,0 @@
-/obj/item/grenade/supermatter
- name = "supermatter grenade"
- icon_state = "banana"
- item_state = "emergency_engi"
- origin_tech = list(TECH_BLUESPACE = 5, TECH_MAGNET = 4, TECH_ENGINEERING = 5)
- arm_sound = 'sound/effects/3.wav'
- var/implode_at
-
-/obj/item/grenade/supermatter/Destroy()
- if(implode_at)
- STOP_PROCESSING(SSobj, src)
- . = ..()
-
-/obj/item/grenade/supermatter/detonate()
- ..()
- START_PROCESSING(SSobj, src)
- implode_at = world.time + 10 SECONDS
- update_icon()
- playsound(src, 'sound/weapons/wave.ogg', 100)
-
-/obj/item/grenade/supermatter/update_icon()
- cut_overlays()
- . = ..()
- if(implode_at)
- add_overlay(image(icon = 'icons/rust.dmi', icon_state = "emfield_s1"))
-
-/obj/item/grenade/supermatter/process(delta_time)
- if(!isturf(loc))
- forceMove(get_turf(src))
- playsound(src, 'sound/effects/supermatter.ogg', 100)
- supermatter_pull(src, world.view, STAGE_THREE)
- if(world.time > implode_at)
- explosion(loc, 1, 3, 5, 4)
- qdel(src)
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index 04f2e305426..af2fb5c2870 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -164,7 +164,7 @@
reach = 2 // Spears are long.
attackspeed = 20
weight = ITEM_WEIGHT_MELEE_SPEAR
- var/obj/item/grenade/explosive = null
+ var/obj/item/grenade/simple/explosive = null
var/war_cry = "AAAAARGH!!!"
/obj/item/material/twohanded/spear/Initialize(mapload, material_key)
diff --git a/code/game/objects/random/maintenance.dm b/code/game/objects/random/maintenance.dm
index 244aa5293f5..ba46933ca03 100644
--- a/code/game/objects/random/maintenance.dm
+++ b/code/game/objects/random/maintenance.dm
@@ -133,7 +133,7 @@ something, make sure it's not in one of the other lists.*/
prob(1);/obj/item/storage/backpack/dufflebag/syndie/med,
prob(2);/obj/item/storage/box/swabs,
prob(2);/obj/item/storage/belt/security,
- prob(1);/obj/item/grenade/flashbang,
+ prob(1);/obj/item/grenade/simple/flashbang,
prob(1);/obj/item/melee/baton,
prob(1);/obj/item/reagent_containers/spray/pepper,
prob(3);/obj/item/clothing/shoes/boots/jackboots,
diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm
index 5397efdbd08..d23d084412f 100644
--- a/code/game/objects/random/mapping.dm
+++ b/code/game/objects/random/mapping.dm
@@ -716,9 +716,9 @@
/obj/item/lightreplacer,
/obj/item/reagent_containers/spray/cleaner,
/obj/item/reagent_containers/glass/rag,
- /obj/item/grenade/chem_grenade/cleaner,
- /obj/item/grenade/chem_grenade/cleaner,
- /obj/item/grenade/chem_grenade/cleaner,
+ /obj/item/grenade/simple/chemical/premade/cleaner,
+ /obj/item/grenade/simple/chemical/premade/cleaner,
+ /obj/item/grenade/simple/chemical/premade/cleaner,
/obj/structure/closet/crate/corporate/galaksi //GALAKSI JANITOR SUPPLIES
),
prob(5);list(
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 461742fe05f..170ffa11551 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -238,7 +238,7 @@
/obj/item/storage/belt/security,
/obj/item/flash,
/obj/item/reagent_containers/spray/pepper,
- /obj/item/grenade/flashbang,
+ /obj/item/grenade/simple/flashbang,
/obj/item/melee/baton/loaded,
/obj/item/clothing/glasses/sunglasses/sechud,
/obj/item/barrier_tape_roll/police,
@@ -391,7 +391,7 @@ GLOBAL_LIST_BOILERPLATE(all_brig_closets, /obj/structure/closet/secure_closet/br
/obj/item/storage/belt/security,
/obj/item/flash,
/obj/item/reagent_containers/spray/pepper,
- /obj/item/grenade/flashbang,
+ /obj/item/grenade/simple/flashbang,
/obj/item/melee/baton/loaded,
/obj/item/clothing/glasses/sunglasses/sechud,
/obj/item/barrier_tape_roll/police,
diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm
index 28571b94f91..8dc8e34b857 100644
--- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm
+++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm
@@ -133,5 +133,5 @@
/obj/item/bananapeel,
/obj/item/card/id/syndicate,
/obj/item/assembly/mousetrap/armed,
- /obj/item/grenade/chem_grenade/lube_tactical,
+ /obj/item/grenade/simple/chemical/premade/lube_tactical,
/obj/item/clothing/shoes/clown_shoes)
diff --git a/code/game/objects/structures/trash_pile.dm b/code/game/objects/structures/trash_pile.dm
index 42f2d062aa4..158123b55a5 100644
--- a/code/game/objects/structures/trash_pile.dm
+++ b/code/game/objects/structures/trash_pile.dm
@@ -239,7 +239,7 @@
prob(2);/obj/item/storage/pill_bottle/kelotane,
prob(2);/obj/item/handcuffs/fuzzy,
prob(2);/obj/item/storage/box/syndie_kit/spy,
- prob(2);/obj/item/grenade/anti_photon,
+ prob(2);/obj/item/grenade/simple/antiphoton,
prob(1);/obj/item/nif/bad,
prob(1);/obj/item/clothing/suit/storage/vest/heavy/merc,
prob(1);/obj/item/clothing/head/helmet/medieval/crusader,
diff --git a/code/modules/assembly/README.md b/code/modules/assembly/README.md
new file mode 100644
index 00000000000..52d00a926b3
--- /dev/null
+++ b/code/modules/assembly/README.md
@@ -0,0 +1,3 @@
+# Assembly System
+
+A simple assembly system made out of connected devices.
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/assembly_holder.dm
similarity index 75%
rename from code/modules/assembly/holder.dm
rename to code/modules/assembly/assembly_holder.dm
index b8587accaec..e0f928655eb 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/assembly_holder.dm
@@ -118,7 +118,10 @@
if(!a_left || !a_right)
to_chat(user, " BUG:Assembly part missing, please report this!")
return
- if(istype(a_left,a_right.type))//If they are the same type it causes issues due to window code
+ // WARNING: DO NOT REMOVE IGNITER TYPECHECKS
+ // If you do, grenades will INSTANTLY BLOW UP ON THE USER WHEN USED
+ // IN HAND!!
+ if(istype(a_left,a_right.type) && !istype(a_left, /obj/item/assembly/igniter))//If they are the same type it causes issues due to window code
switch(alert("Which side would you like to use?",,"Left","Right"))
if("Left") a_left.attack_self(user)
if("Right") a_right.attack_self(user)
@@ -160,6 +163,7 @@
a_right.hear_talk(M,msg,verb,speaking)
if(a_left)
a_left.hear_talk(M,msg,verb,speaking)
+
/obj/item/assembly_holder/timer_igniter
name = "timer-igniter assembly"
@@ -180,39 +184,3 @@
secured = 1
update_icon()
name = initial(name) + " ([tmr.time] secs)"
-
- add_obj_verb(src, /obj/item/assembly_holder/timer_igniter/verb/configure)
-
-/obj/item/assembly_holder/timer_igniter/detached()
- remove_obj_verb(src, /obj/item/assembly_holder/timer_igniter/verb/configure)
- ..()
-
-/obj/item/assembly_holder/timer_igniter/verb/configure()
- set name = "Set Timer"
- set category = VERB_CATEGORY_OBJECT
- set src in usr
-
- if ( !(usr.stat || usr.restrained()) )
- var/obj/item/assembly_holder/holder
- if(istype(src,/obj/item/grenade/chem_grenade))
- var/obj/item/grenade/chem_grenade/gren = src
- holder=gren.detonator
- var/obj/item/assembly/timer/tmr = holder.a_left
- if(!istype(tmr,/obj/item/assembly/timer))
- tmr = holder.a_right
- if(!istype(tmr,/obj/item/assembly/timer))
- to_chat(usr, "This detonator has no timer.")
- return
-
- if(tmr.timing)
- to_chat(usr, "Clock is ticking already.")
- else
- var/ntime = input("Enter desired time in seconds", "Time", "5") as num
- if (ntime>0 && ntime<1000)
- tmr.time = ntime
- name = initial(name) + "([tmr.time] secs)"
- to_chat(usr, "Timer set to [tmr.time] seconds.")
- else
- to_chat(usr, "Timer can't be [ntime<=0?"negative":"more than 1000 seconds"].")
- else
- to_chat(usr, "You cannot do this while [usr.stat?"unconscious/dead":"restrained"].")
diff --git a/code/modules/assembly/igniter.dm b/code/modules/assembly/igniter.dm
index fb4f1040224..3659133a37a 100644
--- a/code/modules/assembly/igniter.dm
+++ b/code/modules/assembly/igniter.dm
@@ -12,8 +12,8 @@
if(!..())
return FALSE
- if(holder && istype(holder.loc,/obj/item/grenade/chem_grenade))
- var/obj/item/grenade/chem_grenade/grenade = holder.loc
+ if(holder && istype(holder.loc,/obj/item/grenade/simple/chemical))
+ var/obj/item/grenade/simple/chemical/grenade = holder.loc
grenade.detonate()
else
var/turf/location = get_turf(loc)
@@ -28,16 +28,12 @@
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
-
return TRUE
-
/obj/item/assembly/igniter/attack_self(mob/user, datum/event_args/actor/actor)
- . = ..()
- if(.)
- return
activate()
add_fingerprint(user)
+ return TRUE
/obj/item/assembly/igniter/is_hot()
return TRUE
diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm
index 73bee405191..af06c3601d1 100644
--- a/code/modules/assembly/proximity.dm
+++ b/code/modules/assembly/proximity.dm
@@ -93,9 +93,6 @@
LAZYADD(attached_overlays, "prox_scanning")
if(holder)
holder.update_icon()
- if(holder && istype(holder.loc,/obj/item/grenade/chem_grenade))
- var/obj/item/grenade/chem_grenade/grenade = holder.loc
- grenade.primed(scanning)
/obj/item/assembly/prox_sensor/Move()
..()
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 9c960a39736..d0fcb9a1b84 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -2,6 +2,7 @@
name = "voice analyzer"
desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated."
icon_state = "voice"
+ atom_flags = ATOM_HEAR
origin_tech = list(TECH_MAGNET = 1)
materials_base = list(MAT_STEEL = 500, MAT_GLASS = 50)
var/listening = 0
@@ -26,11 +27,6 @@
/obj/item/assembly/voice/attack_self(mob/user, datum/event_args/actor/actor)
- . = ..()
- if(.)
- return
- if(!user)
- return FALSE
activate()
return TRUE
diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture-share.dm b/code/modules/atmospherics/gasmixtures/gas_mixture-share.dm
index e4a16b590a5..626bcf6dd78 100644
--- a/code/modules/atmospherics/gasmixtures/gas_mixture-share.dm
+++ b/code/modules/atmospherics/gasmixtures/gas_mixture-share.dm
@@ -23,7 +23,8 @@
ASSERT(ratio > 0 && ratio <= 1)
#endif
#ifdef CF_ATMOS_XGM_UPDATE_VALUES_ASSERTIONS
- ASSERT(gas ~= debug_gas_archive)
+ if(!(gas ~= debug_gas_archive))
+ stack_trace("gas did not match archive, [json_encode(gas)] vs archived [json_encode(debug_gas_archive)]")
#endif
// if both of us are empty, bail or division by zero's happen later
// this proc can handle up to one empty mixture after this check, as this check
@@ -84,7 +85,7 @@
other.temperature = other.temperature * (their_remaining_capacity / their_new_capacity) + average_temperature * (their_injected_capacity / their_new_capacity)
// update
- update_values()
+ src.update_values()
other.update_values()
// return if we equalized fully
diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm
index ae102ce213d..c3cdba1c1a1 100644
--- a/code/modules/clothing/under/accessories/storage.dm
+++ b/code/modules/clothing/under/accessories/storage.dm
@@ -197,7 +197,7 @@
/obj/item/reagent_containers/glass/stone,
/obj/item/stack/medical/poultice_brute,
/obj/item/stack/medical/poultice_burn,
- /obj/item/grenade/explosive/ashlander,
+ /obj/item/grenade/simple/explosive/ashlander,
/obj/item/bitterash,
/obj/item/flame/lighter,
)
diff --git a/code/modules/hardsuits/modules/combat.dm b/code/modules/hardsuits/modules/combat.dm
index 00fbfb5095d..17649359c49 100644
--- a/code/modules/hardsuits/modules/combat.dm
+++ b/code/modules/hardsuits/modules/combat.dm
@@ -31,9 +31,9 @@
var/fire_distance = 10
charges = list(
- list("flashbang", "flashbang", /obj/item/grenade/flashbang, 3),
- list("smoke bomb", "smoke bomb", /obj/item/grenade/smokebomb, 3),
- list("EMP grenade", "EMP grenade", /obj/item/grenade/empgrenade, 3),
+ list("flashbang", "flashbang", /obj/item/grenade/simple/flashbang, 3),
+ list("smoke bomb", "smoke bomb", /obj/item/grenade/simple/smoke, 3),
+ list("EMP grenade", "EMP grenade", /obj/item/grenade/simple/emp, 3),
)
/obj/item/hardsuit_module/grenade_launcher/accepts_item(var/obj/item/input_device, var/mob/living/user)
@@ -88,7 +88,7 @@
charge.charges--
var/obj/item/grenade/new_grenade = new charge.product_type(get_turf(H))
H.visible_message("[H] launches \a [new_grenade]!")
- new_grenade.activate(H)
+ new_grenade.activate(new /datum/event_args/actor(H))
new_grenade.throw_at_old(target,fire_force,fire_distance)
/obj/item/hardsuit_module/grenade_launcher/smoke
@@ -101,7 +101,7 @@
fire_force = 15
charges = list(
- list("smoke bomb", "smoke bomb", /obj/item/grenade/smokebomb, 6)
+ list("smoke bomb", "smoke bomb", /obj/item/grenade/simple/smoke, 6)
)
/obj/item/hardsuit_module/grenade_launcher/holy
@@ -114,7 +114,7 @@
fire_force = 15
charges = list(
- list("PARA disruptor grenade", "PARA disruptor grenade", /obj/item/grenade/chem_grenade/holy, 6)
+ list("PARA disruptor grenade", "PARA disruptor grenade", /obj/item/grenade/simple/chemical/premade/holy, 6)
)
/obj/item/hardsuit_module/mounted
diff --git a/code/modules/hardsuits/modules/combat_vr.dm b/code/modules/hardsuits/modules/combat_vr.dm
index 72f2e1e3be7..7513591a226 100644
--- a/code/modules/hardsuits/modules/combat_vr.dm
+++ b/code/modules/hardsuits/modules/combat_vr.dm
@@ -8,5 +8,5 @@
fire_force = 15
charges = list(
- list("cleaner grenade", "cleaner grenade", /obj/item/grenade/chem_grenade/cleaner, 6)
+ list("cleaner grenade", "cleaner grenade", /obj/item/grenade/simple/chemical/premade/cleaner, 6)
)
diff --git a/code/modules/hardsuits/modules/utility.dm b/code/modules/hardsuits/modules/utility.dm
index 3e62aca8196..56c4876bed5 100644
--- a/code/modules/hardsuits/modules/utility.dm
+++ b/code/modules/hardsuits/modules/utility.dm
@@ -481,7 +481,7 @@
var/fire_distance = 10
charges = list(
- list("cleaner grenade", "cleaner grenade", /obj/item/grenade/chem_grenade/cleaner, 9),
+ list("cleaner grenade", "cleaner grenade", /obj/item/grenade/simple/chemical/premade/cleaner, 9),
)
/obj/item/hardsuit_module/cleaner_launcher/accepts_item(var/obj/item/input_device, var/mob/living/user)
@@ -535,7 +535,7 @@
charge.charges--
var/obj/item/grenade/new_grenade = new charge.product_type(get_turf(H))
H.visible_message("[H] launches \a [new_grenade]!")
- new_grenade.activate(H)
+ new_grenade.activate(new /datum/event_args/actor(H))
new_grenade.throw_at_old(target,fire_force,fire_distance)
/obj/item/hardsuit_module/device/paperdispenser
diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm
index 0f1189b13b7..9cd1a2a5004 100644
--- a/code/modules/integrated_electronics/subtypes/manipulation.dm
+++ b/code/modules/integrated_electronics/subtypes/manipulation.dm
@@ -978,7 +978,7 @@
activators = list("prime grenade" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
- var/obj/item/grenade/attached_grenade
+ var/obj/item/grenade/simple/attached_grenade
var/pre_attached_grenade_type
/obj/item/integrated_circuit/manipulation/grenade/Initialize(mapload)
@@ -988,17 +988,15 @@
attach_grenade(grenade)
/obj/item/integrated_circuit/manipulation/grenade/Destroy()
- if(attached_grenade && !attached_grenade.active)
- attached_grenade.dropInto(loc)
- detach_grenade()
- . =..()
+ QDEL_NULL(attached_grenade)
+ return ..()
/obj/item/integrated_circuit/manipulation/grenade/proc/ask_for_input(mob/living/user, obj/item/I, a_intent)
if(!isobj(I))
return FALSE
attackby_react(I, user, a_intent)
-/obj/item/integrated_circuit/manipulation/grenade/attackby_react(var/obj/item/grenade/G, var/mob/user)
+/obj/item/integrated_circuit/manipulation/grenade/attackby_react(var/obj/item/grenade/simple/G, var/mob/user)
if(istype(G))
. = CLICKCHAIN_DO_NOT_PROPAGATE
if(attached_grenade)
@@ -1025,10 +1023,10 @@
return ..()
/obj/item/integrated_circuit/manipulation/grenade/do_work()
- if(attached_grenade && !attached_grenade.active)
+ if(attached_grenade && !attached_grenade.activated)
var/datum/integrated_io/detonation_time = inputs[1]
if(isnum(detonation_time.data) && detonation_time.data > 0)
- attached_grenade.det_time = between(1, detonation_time.data, 12) SECONDS
+ attached_grenade.activation_detonate_delay = between(1, detonation_time.data, 12) SECONDS
attached_grenade.activate()
var/atom/holder = loc
log_and_message_admins("activated a grenade assembly. Last touches: Assembly: [holder.fingerprintslast] Circuit: [fingerprintslast] Grenade: [attached_grenade.fingerprintslast]")
diff --git a/code/modules/materials/definitions/metals/steel.dm b/code/modules/materials/definitions/metals/steel.dm
index da0d73625da..af67469b4e2 100644
--- a/code/modules/materials/definitions/metals/steel.dm
+++ b/code/modules/materials/definitions/metals/steel.dm
@@ -233,7 +233,7 @@ DECLARE_MATERIAL(/steel)
)
. += create_stack_recipe_datum(
category = "weapons",
- product = /obj/item/grenade/chem_grenade,
+ product = /obj/item/grenade/simple/chemical,
name = "grenade casing",
cost = 2,
)
diff --git a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm
index d0275e768bd..cb9ac614ef7 100644
--- a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm
+++ b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm
@@ -127,8 +127,8 @@
to_wear_gloves = null
to_wear_shoes = /obj/item/clothing/shoes/boots/combat/changeling
to_wear_belt = /obj/item/storage/belt/utility/full
- to_wear_l_pocket = /obj/item/grenade/explosive/mini
- to_wear_r_pocket = /obj/item/grenade/explosive/mini
+ to_wear_l_pocket = /obj/item/grenade/simple/explosive/mini
+ to_wear_r_pocket = /obj/item/grenade/simple/explosive/mini
to_wear_back = /obj/item/radio/electropack
to_wear_id_type = /obj/item/card/id
to_wear_id_job = "Experiment"
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index d809959ee59..d9bc2179b75 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -103,10 +103,9 @@
if(INTENT_HARM)
if(L.zone_sel.selecting == "mouth" && wear_mask && istype(wear_mask, /obj/item/grenade))
- var/obj/item/grenade/G = wear_mask
- if(!G.active)
+ var/obj/item/grenade/simple/G = wear_mask
+ if(istype(G) && !G.activated && G.activate_inhand(e_args))
visible_message("\The [L] pulls the pin from \the [src]'s [G.name]!")
- G.activate(L)
update_inv_wear_mask()
else
to_chat(L, "\The [G] is already primed! Run!")
diff --git a/code/modules/mob/living/simple_mob/subtypes/humanoid/clown.dm b/code/modules/mob/living/simple_mob/subtypes/humanoid/clown.dm
index 35639408016..a815d60ba50 100644
--- a/code/modules/mob/living/simple_mob/subtypes/humanoid/clown.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/humanoid/clown.dm
@@ -108,7 +108,7 @@
say_list_type = /datum/say_list/clownop
// Grenade special attack vars
- var/grenade_type = /obj/item/grenade/chem_grenade/lube_tactical
+ var/grenade_type = /obj/item/grenade/simple/chemical/premade/lube_tactical
var/grenade_timer = 50
special_attack_cooldown = 45 SECONDS
special_attack_min_range = 2
@@ -160,11 +160,11 @@
set waitfor = FALSE
set_AI_busy(TRUE)
- var/obj/item/grenade/G = new grenade_type(get_turf(src))
+ var/obj/item/grenade/simple/G = new grenade_type(get_turf(src))
if(istype(G))
G.throw_at_old(A, G.throw_range, G.throw_speed, src)
- G.det_time = grenade_timer
- G.activate(src)
+ G.activation_detonate_delay = grenade_timer
+ G.activate_inhand(new /datum/event_args/actor(src))
special_attack_charges = max(special_attack_charges-1, 0)
set_AI_busy(FALSE)
diff --git a/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm b/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm
index cd3fea40627..bfc6be5d87d 100644
--- a/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm
@@ -78,7 +78,7 @@
say_list_type = /datum/say_list/merc
// Grenade special attack vars
- var/grenade_type = /obj/item/grenade/concussion
+ var/grenade_type = /obj/item/grenade/simple/concussion
var/grenade_timer = 50
special_attack_cooldown = 45 SECONDS
special_attack_min_range = 2
@@ -110,11 +110,11 @@
set waitfor = FALSE
set_AI_busy(TRUE)
- var/obj/item/grenade/G = new grenade_type(get_turf(src))
+ var/obj/item/grenade/simple/G = new grenade_type(get_turf(src))
if(istype(G))
G.throw_at_old(A, G.throw_range, G.throw_speed, src)
- G.det_time = grenade_timer
- G.activate(src)
+ G.activation_detonate_delay = grenade_timer
+ G.activate(new /datum/event_args/actor(src))
special_attack_charges = max(special_attack_charges-1, 0)
set_AI_busy(FALSE)
@@ -513,7 +513,7 @@
loot_list = list() // oh, you killed him?
corpse = null // well, sorry, buddy, he doesn't drop shit
catalogue_data = list(/datum/category_item/catalogue/fauna/mercenary/human/space/suppressor)
-// var/deathnade_path = /obj/item/grenade/flashbang/stingbang
+// var/deathnade_path = /obj/item/grenade/simple/flashbang/stingbang
/* far too fun for the codebase at the moment
/mob/living/simple_mob/humanoid/merc/ranged/space/suppressor/death()
@@ -533,9 +533,9 @@
icon_living = "syndi-ranged-space-sup-elite"
armor_legacy_mob = list(melee = 80, bullet = 70, laser = 55, energy = 15, bomb = 80, bio = 100, rad = 100) // see code for military hardsuit
projectiletype = /obj/projectile/bullet/pistol/medium/ap/suppressor/turbo // fuck it, fast bullets
- grenade_type = /obj/item/grenade/shooter/rubber // don't group up
+ grenade_type = /obj/item/grenade/simple/shooter/rubber // don't group up
grenade_timer = 30 // well, look what you've done, you've grouped up
-// deathnade_path = /obj/item/grenade/flashbang/stingbang/shredbang // REALLY don't group up
+// deathnade_path = /obj/item/grenade/simple/flashbang/stingbang/shredbang // REALLY don't group up
// being Actual Professionals, they have better (read: player-level) blocking chances
/mob/living/simple_mob/humanoid/merc/ranged/space/suppressor/attackby(var/obj/item/O, var/mob/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/humanoid/possessed.dm b/code/modules/mob/living/simple_mob/subtypes/humanoid/possessed.dm
index a8c87264302..21c50d73c1d 100644
--- a/code/modules/mob/living/simple_mob/subtypes/humanoid/possessed.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/humanoid/possessed.dm
@@ -53,13 +53,11 @@
// Will eventually leave a full corpse with an activated RIG on it. But not yet.
//Miasma Cloud "Item"
-/obj/item/grenade/chem_grenade/miasma
+/obj/item/grenade/simple/chemical/premade/miasma
name = "Miasma Bomb"
desc = "You probably shouldn't be able to see this."
- stage = 2
- path = 1
-/obj/item/grenade/chem_grenade/miasma/Initialize(mapload)
+/obj/item/grenade/simple/chemical/miasma/Initialize(mapload)
. = ..()
var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
@@ -74,8 +72,6 @@
icon_state = null
- detonate()
-
//Has a chance to play one of the listed sounds when it moves.
/mob/living/simple_mob/humanoid/possessed/Moved()
. = ..()
@@ -111,7 +107,8 @@
else
new rig2(droploc)
new /obj/effect/decal/remains/human(droploc)
- new /obj/item/grenade/chem_grenade/miasma(droploc)
+ var/obj/item/grenade/simple/chemical/this_is_stupid = new /obj/item/grenade/simple/chemical/miasma(droploc)
+ this_is_stupid.detonate()
/*Broken smoke spawn code. Above line is a bandaid.
var/datum/reagent_holder/R = new/datum/reagent_holder(30)
reagents.add_reagent("miasma", 30)
diff --git a/code/modules/projectiles/projectile/helpers.dm b/code/modules/projectiles/projectile/helpers.dm
index 3469a09b6a6..9a5f7e541b1 100644
--- a/code/modules/projectiles/projectile/helpers.dm
+++ b/code/modules/projectiles/projectile/helpers.dm
@@ -1,10 +1,10 @@
//* This file is explicitly licensed under the MIT license. *//
//* Copyright (c) 2024 Citadel Station Developers *//
+// TODO: put into SSspatial_effects
/**
* Creates a shrapnel explosion
*
- * todo: should this be in a single file with procs like explosion(), emp_pulse(), and other blast-like effects?
* todo: /pellet shouldn't be /bullet/pellet
* todo: there has to be a better way to set vars on every cloud than passing them in as args
*
diff --git a/code/modules/random_map/drop/drop_types.dm b/code/modules/random_map/drop/drop_types.dm
index 0fd32cfbc01..e5748a70f35 100644
--- a/code/modules/random_map/drop/drop_types.dm
+++ b/code/modules/random_map/drop/drop_types.dm
@@ -86,14 +86,14 @@ var/global/list/datum/supply_drop_loot/supply_drop
/obj/item/ammo_magazine/a7_62mm/ap,
/obj/item/ammo_magazine/a7_62mm,
/obj/item/shield/transforming/energy,
- /obj/item/grenade/explosive/frag,
- /obj/item/grenade/explosive/frag,
- /obj/item/grenade/smokebomb,
- /obj/item/grenade/smokebomb,
- /obj/item/grenade/flashbang,
- /obj/item/grenade/flashbang,
- /obj/item/grenade/empgrenade,
- /obj/item/grenade/empgrenade,
+ /obj/item/grenade/simple/explosive/frag,
+ /obj/item/grenade/simple/explosive/frag,
+ /obj/item/grenade/simple/smoke,
+ /obj/item/grenade/simple/smoke,
+ /obj/item/grenade/simple/flashbang,
+ /obj/item/grenade/simple/flashbang,
+ /obj/item/grenade/simple/emp,
+ /obj/item/grenade/simple/emp,
/obj/item/material/knife/tacknife/combatknife)
/datum/supply_drop_loot/riot
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index f0614b65c89..de9b9ae4111 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -33,7 +33,7 @@
/obj/item/storage,
/obj/machinery/atmospherics/component/unary/cryo_cell,
/obj/machinery/dna_scannernew,
- /obj/item/grenade/chem_grenade,
+ /obj/item/grenade/simple/chemical,
/mob/living/bot/medibot,
/obj/item/storage/secure/safe,
/obj/machinery/iv_drip,
diff --git a/code/modules/research/designs/weapons.dm b/code/modules/research/designs/weapons.dm
index 9c60f207206..ad61ab4a76a 100644
--- a/code/modules/research/designs/weapons.dm
+++ b/code/modules/research/designs/weapons.dm
@@ -325,7 +325,7 @@
id = "large_Grenade"
req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2)
materials_base = list(MAT_STEEL = 3000)
- build_path = /obj/item/grenade/chem_grenade/large
+ build_path = /obj/item/grenade/simple/chemical/large
/datum/prototype/design/science/weapon/energy/netgun
design_name = "\'Retiarius\' capture gun"
diff --git a/code/modules/vehicles/sealed/mecha/modules/weapons/explosive/grenade.dm b/code/modules/vehicles/sealed/mecha/modules/weapons/explosive/grenade.dm
index 72b39342363..754f11fa7f7 100644
--- a/code/modules/vehicles/sealed/mecha/modules/weapons/explosive/grenade.dm
+++ b/code/modules/vehicles/sealed/mecha/modules/weapons/explosive/grenade.dm
@@ -2,7 +2,7 @@
name = "\improper SGL-6 grenade launcher"
desc = "A grenade launcher produced for SWAT use; fires flashbangs."
icon_state = "mecha_grenadelnchr"
- projectile = /obj/item/grenade/flashbang
+ projectile = /obj/item/grenade/simple/flashbang
fire_sound = 'sound/effects/bang.ogg'
projectiles = 6
missile_speed = 1.5
@@ -19,16 +19,16 @@
det_time = 25
/obj/item/vehicle_module/weapon/ballistic/missile_rack/grenade/Fire(atom/movable/AM, atom/target, turf/aimloc)
- var/obj/item/grenade/G = AM
+ var/obj/item/grenade/simple/G = AM
if(istype(G))
- G.det_time = det_time
- G.activate(chassis.occupant_legacy) //Grenades actually look primed and dangerous, handle their own stuff.
+ G.activation_detonate_delay = det_time
+ G.activate(new /datum/event_args/actor(chassis.occupant_legacy))
AM.throw_at_old(target,missile_range, missile_speed, chassis)
/obj/item/vehicle_module/weapon/ballistic/missile_rack/grenade/clusterbang//Because I am a heartless bastard -Sieve
name = "\improper SOP-6 grenade launcher"
desc = "A grenade launcher produced for use by government uprising subjugation forces, or that's what you might guess; fires matryoshka flashbangs."
- projectile = /obj/item/grenade/flashbang/clusterbang
+ projectile = /obj/item/grenade/simple/flashbang/clusterbang
origin_tech = list(TECH_COMBAT= 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3)
@@ -42,7 +42,7 @@
name = "\improper SGL-9 grenade launcher"
desc = "A military-grade grenade launcher that fires disorienting concussion grenades."
icon_state = "mecha_grenadelnchr"
- projectile = /obj/item/grenade/concussion
+ projectile = /obj/item/grenade/simple/concussion
missile_speed = 1
projectile_energy_cost = 900
equip_cooldown = 50
@@ -54,7 +54,7 @@
name = "\improper HEP-I 5 grenade launcher"
desc = "A military-grade grenade launcher that fires anti-personnel fragmentation grenades."
icon_state = "mecha_fraglnchr"
- projectile = /obj/item/grenade/explosive
+ projectile = /obj/item/grenade/simple/explosive
projectiles = 4
missile_speed = 1
@@ -63,7 +63,7 @@
/obj/item/vehicle_module/weapon/ballistic/missile_rack/grenade/frag/mini
name = "\improper HEP-MI 6 grenade launcher"
desc = "A military-grade grenade launcher that fires miniaturized anti-personnel fragmentation grenades."
- projectile = /obj/item/grenade/explosive/mini
+ projectile = /obj/item/grenade/simple/explosive/mini
projectile_energy_cost = 500
equip_cooldown = 25
diff --git a/code/modules/xenoarcheaology/artifacts/replicator.dm b/code/modules/xenoarcheaology/artifacts/replicator.dm
index 726c86594f6..d5004b05d60 100644
--- a/code/modules/xenoarcheaology/artifacts/replicator.dm
+++ b/code/modules/xenoarcheaology/artifacts/replicator.dm
@@ -62,8 +62,8 @@
/obj/item/tool/wirecutters,
/obj/item/tool/wrench,
/obj/item/tool/screwdriver,
- /obj/item/grenade/chem_grenade/cleaner,
- /obj/item/grenade/chem_grenade/metalfoam,
+ /obj/item/grenade/simple/chemical/premade/cleaner,
+ /obj/item/grenade/simple/chemical/premade/metalfoam,
/obj/structure/closet/crate/mimic/
)
diff --git a/icons/items/grenade/chemical.dmi b/icons/items/grenade/chemical.dmi
new file mode 100644
index 00000000000..659ecd93beb
Binary files /dev/null and b/icons/items/grenade/chemical.dmi differ
diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi
index 32e07b2336c..7d2c36c3e4d 100644
Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ
diff --git a/maps/away_missions/archive/spacebattle.dmm b/maps/away_missions/archive/spacebattle.dmm
index 741ad85307f..e3c7a315092 100644
--- a/maps/away_missions/archive/spacebattle.dmm
+++ b/maps/away_missions/archive/spacebattle.dmm
@@ -59,7 +59,7 @@
/area/awaymission/spacebattle/syndicate2)
"as" = (
/obj/structure/table/reinforced,
-/obj/item/grenade/empgrenade,
+/obj/item/grenade/simple/emp,
/turf/simulated/floor,
/area/awaymission/spacebattle/syndicate2)
"au" = (
@@ -249,7 +249,7 @@
/area/awaymission/spacebattle/syndicate1)
"br" = (
/obj/structure/table/reinforced,
-/obj/item/grenade/spawnergrenade/manhacks,
+/obj/item/grenade/simple/spawner/manhacks,
/turf/simulated/floor,
/area/awaymission/spacebattle/syndicate1)
"bs" = (
diff --git a/maps/away_missions/snow_outpost_140/levels/snow_outpost.dmm b/maps/away_missions/snow_outpost_140/levels/snow_outpost.dmm
index f0c90db26c1..bca1e768466 100644
--- a/maps/away_missions/snow_outpost_140/levels/snow_outpost.dmm
+++ b/maps/away_missions/snow_outpost_140/levels/snow_outpost.dmm
@@ -1070,7 +1070,7 @@
/area/awaymission/snow_outpost/powered)
"ex" = (
/obj/structure/table/steel,
-/obj/item/grenade/smokebomb,
+/obj/item/grenade/simple/smoke,
/turf/simulated/floor/tiled/steel_grid,
/area/awaymission/snow_outpost/powered)
"ey" = (
@@ -2056,7 +2056,7 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/awaymission/snow_outpost/dark)
"hS" = (
-/obj/item/grenade/spawnergrenade/spider,
+/obj/item/grenade/simple/spawner/spider,
/turf/simulated/mineral/floor/ignore_mapgen,
/area/awaymission/snow_outpost/dark)
"hT" = (
diff --git a/maps/away_missions/snowfield_140/levels/snowfield.dmm b/maps/away_missions/snowfield_140/levels/snowfield.dmm
index ab0100dfde6..d646db7e938 100644
--- a/maps/away_missions/snowfield_140/levels/snowfield.dmm
+++ b/maps/away_missions/snowfield_140/levels/snowfield.dmm
@@ -446,9 +446,9 @@
/turf/simulated/floor/tiled/hydro,
/area/awaymission/snowfield/base)
"bn" = (
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/item/reagent_containers/spray/cleaner,
/obj/structure/table/steel,
/obj/item/storage/box/mousetraps,
diff --git a/maps/away_missions/zoo_197x305/levels/zoo.dmm b/maps/away_missions/zoo_197x305/levels/zoo.dmm
index 6ad9f52cfc0..ece81becd2c 100644
--- a/maps/away_missions/zoo_197x305/levels/zoo.dmm
+++ b/maps/away_missions/zoo_197x305/levels/zoo.dmm
@@ -8494,9 +8494,9 @@
/obj/item/spacecash/c1000,
/obj/item/card/emag,
/obj/item/beartrap,
-/obj/item/grenade/spawnergrenade/spesscarp,
-/obj/item/grenade/spawnergrenade/spesscarp,
-/obj/item/grenade/spawnergrenade/spesscarp,
+/obj/item/grenade/simple/spawner/spesscarp,
+/obj/item/grenade/simple/spawner/spesscarp,
+/obj/item/grenade/simple/spawner/spesscarp,
/obj/item/clothing/glasses/thermal/plain/monocle,
/obj/item/stolenpackage,
/obj/item/stolenpackage,
diff --git a/maps/endeavour/levels/deck2.dmm b/maps/endeavour/levels/deck2.dmm
index 198f2f69d92..bad31dced64 100644
--- a/maps/endeavour/levels/deck2.dmm
+++ b/maps/endeavour/levels/deck2.dmm
@@ -19464,9 +19464,9 @@
/obj/structure/closet/crate{
name = "Grenade Crate"
},
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
@@ -33398,9 +33398,9 @@
/area/medical/virology)
"xUZ" = (
/obj/structure/closet/crate,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
diff --git a/maps/endeavour/levels/flagship.dmm b/maps/endeavour/levels/flagship.dmm
index f84ff808bec..60744b921f2 100644
--- a/maps/endeavour/levels/flagship.dmm
+++ b/maps/endeavour/levels/flagship.dmm
@@ -2388,12 +2388,12 @@
/obj/item/clothing/glasses/welding/superior,
/obj/structure/table/steel_reinforced,
/obj/item/clothing/glasses/welding/superior,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/unsimulated/floor{
icon_state = "dark"
},
@@ -8084,7 +8084,7 @@
},
/area/centcom/medical)
"yW" = (
-/obj/item/grenade/supermatter,
+/obj/item/grenade/simple/supermatter,
/obj/structure/table/rack/steel,
/obj/machinery/door/window/brigdoor{
req_access = list(109)
diff --git a/maps/euthenia/levels/deck3.dmm b/maps/euthenia/levels/deck3.dmm
index 2c85154fb8b..35d8b1d8c70 100644
--- a/maps/euthenia/levels/deck3.dmm
+++ b/maps/euthenia/levels/deck3.dmm
@@ -16168,9 +16168,9 @@
/obj/structure/closet/crate{
name = "Grenade Crate"
},
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
diff --git a/maps/rift/levels/rift-04-surface1.dmm b/maps/rift/levels/rift-04-surface1.dmm
index 880d511ef71..383470cb7bc 100644
--- a/maps/rift/levels/rift-04-surface1.dmm
+++ b/maps/rift/levels/rift-04-surface1.dmm
@@ -8423,9 +8423,9 @@
/area/library)
"fBk" = (
/obj/structure/closet/crate,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
diff --git a/maps/rift/levels/rift-05-surface2.dmm b/maps/rift/levels/rift-05-surface2.dmm
index 499468168fe..1a4720e88e2 100644
--- a/maps/rift/levels/rift-05-surface2.dmm
+++ b/maps/rift/levels/rift-05-surface2.dmm
@@ -669,7 +669,7 @@
/turf/simulated/floor/wood,
/area/crew_quarters/bar/lounge)
"axz" = (
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"axE" = (
@@ -19032,10 +19032,10 @@
/obj/structure/closet/crate{
name = "Grenade Crate"
},
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
diff --git a/maps/rift/levels/rift-11-orbital.dmm b/maps/rift/levels/rift-11-orbital.dmm
index 8897e67d2a6..0cbefa87628 100644
--- a/maps/rift/levels/rift-11-orbital.dmm
+++ b/maps/rift/levels/rift-11-orbital.dmm
@@ -6347,12 +6347,12 @@
/obj/item/clothing/glasses/welding/superior,
/obj/structure/table/steel_reinforced,
/obj/item/clothing/glasses/welding/superior,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/unsimulated/floor/dark,
/area/centcom/specops)
"un" = (
diff --git a/maps/sectors/admin_planets_192/andromeda.dmm b/maps/sectors/admin_planets_192/andromeda.dmm
index 4ff63500461..44c89628651 100644
--- a/maps/sectors/admin_planets_192/andromeda.dmm
+++ b/maps/sectors/admin_planets_192/andromeda.dmm
@@ -16370,9 +16370,9 @@
/area/admin_planet/andromeda/engi_equipment)
"YT" = (
/obj/structure/closet/crate,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
diff --git a/maps/sectors/admin_planets_192/fey_map.dmm b/maps/sectors/admin_planets_192/fey_map.dmm
index b481a9233b8..0f729313e0b 100644
--- a/maps/sectors/admin_planets_192/fey_map.dmm
+++ b/maps/sectors/admin_planets_192/fey_map.dmm
@@ -2493,7 +2493,7 @@
/area/admin_planet/fey_forest/wilds)
"Xu" = (
/obj/effect/debris/cleanable/blood,
-/obj/item/grenade/concussion{
+/obj/item/grenade/simple/concussion{
pixel_x = 16;
pixel_y = 13
},
diff --git a/maps/sectors/delerict_casino/levels/delerict_casino.dmm b/maps/sectors/delerict_casino/levels/delerict_casino.dmm
index ad292f13bd8..dec5fa89db9 100644
--- a/maps/sectors/delerict_casino/levels/delerict_casino.dmm
+++ b/maps/sectors/delerict_casino/levels/delerict_casino.dmm
@@ -7550,11 +7550,11 @@
/area/sector/delerictcasino/maintenance)
"JN" = (
/obj/structure/table/steel_reinforced,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/obj/machinery/atmospherics/component/unary/vent_pump/on{
dir = 4
},
diff --git a/maps/sectors/miaphus/levels/miaphus_beach.dmm b/maps/sectors/miaphus/levels/miaphus_beach.dmm
index bf832e78fec..568d3f28154 100644
--- a/maps/sectors/miaphus/levels/miaphus_beach.dmm
+++ b/maps/sectors/miaphus/levels/miaphus_beach.dmm
@@ -4746,12 +4746,12 @@
/area/sector/miaphus/beach/desalinator)
"Ob" = (
/obj/structure/closet/crate/miningcar,
-/obj/item/grenade/explosive/ied/tyrmalin,
-/obj/item/grenade/explosive/ied/tyrmalin,
-/obj/item/grenade/explosive/ied/tyrmalin,
-/obj/item/grenade/explosive/ied/tyrmalin,
-/obj/item/grenade/explosive/ied/tyrmalin,
-/obj/item/grenade/explosive/ied/tyrmalin,
+/obj/item/grenade/simple/explosive/ied/tyrmalin,
+/obj/item/grenade/simple/explosive/ied/tyrmalin,
+/obj/item/grenade/simple/explosive/ied/tyrmalin,
+/obj/item/grenade/simple/explosive/ied/tyrmalin,
+/obj/item/grenade/simple/explosive/ied/tyrmalin,
+/obj/item/grenade/simple/explosive/ied/tyrmalin,
/obj/random/multiple/ores,
/turf/simulated/mineral/floor/cave{
name = "dirt"
diff --git a/maps/sectors/nebula_tradeport/levels/nebula_tradeport.dmm b/maps/sectors/nebula_tradeport/levels/nebula_tradeport.dmm
index d01b2ed214b..b1a8497f354 100644
--- a/maps/sectors/nebula_tradeport/levels/nebula_tradeport.dmm
+++ b/maps/sectors/nebula_tradeport/levels/nebula_tradeport.dmm
@@ -7783,11 +7783,11 @@
/area/tradeport/pads)
"auJ" = (
/obj/structure/table/steel_reinforced,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/obj/machinery/atmospherics/component/unary/vent_pump/on{
dir = 4
},
@@ -17008,17 +17008,17 @@
dir = 1
},
/obj/structure/closet/l3closet/janitor,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/machinery/atmospherics/pipe/simple/visible/red{
dir = 4
},
@@ -17622,12 +17622,12 @@
name = "weedkiller crate";
req_access = list(160)
},
-/obj/item/grenade/chem_grenade/antiweed,
-/obj/item/grenade/chem_grenade/antiweed,
-/obj/item/grenade/chem_grenade/antiweed,
-/obj/item/grenade/chem_grenade/antiweed,
-/obj/item/grenade/chem_grenade/antiweed,
-/obj/item/grenade/chem_grenade/antiweed,
+/obj/item/grenade/simple/chemical/premade/antiweed,
+/obj/item/grenade/simple/chemical/premade/antiweed,
+/obj/item/grenade/simple/chemical/premade/antiweed,
+/obj/item/grenade/simple/chemical/premade/antiweed,
+/obj/item/grenade/simple/chemical/premade/antiweed,
+/obj/item/grenade/simple/chemical/premade/antiweed,
/obj/item/material/knife/machete/hatchet,
/obj/item/material/knife/machete/hatchet,
/obj/item/material/twohanded/fireaxe/scythe,
diff --git a/maps/submaps/level_specific/class_h/AuxiliaryResearchFacility.dmm b/maps/submaps/level_specific/class_h/AuxiliaryResearchFacility.dmm
index 2e4c9c70907..5aef6d67601 100644
--- a/maps/submaps/level_specific/class_h/AuxiliaryResearchFacility.dmm
+++ b/maps/submaps/level_specific/class_h/AuxiliaryResearchFacility.dmm
@@ -129,9 +129,9 @@
"cx" = (
/obj/structure/table/rack,
/obj/effect/debris/cleanable/dirt,
-/obj/item/grenade/concussion/frag,
-/obj/item/grenade/concussion/frag,
-/obj/item/grenade/concussion/frag,
+/obj/item/grenade/simple/concussion/frag,
+/obj/item/grenade/simple/concussion/frag,
+/obj/item/grenade/simple/concussion/frag,
/turf/simulated/floor/tiled/steel,
/area/class_h/POIs/AuxiliaryResearchFacility)
"cA" = (
@@ -977,10 +977,10 @@
/area/class_h/POIs/AuxiliaryResearchFacility)
"wo" = (
/obj/structure/table/rack,
-/obj/item/grenade/spawnergrenade/manhacks/mercenary,
-/obj/item/grenade/spawnergrenade/manhacks/mercenary,
-/obj/item/grenade/spawnergrenade/manhacks/mercenary,
-/obj/item/grenade/spawnergrenade/manhacks/mercenary,
+/obj/item/grenade/simple/spawner/manhacks/mercenary,
+/obj/item/grenade/simple/spawner/manhacks/mercenary,
+/obj/item/grenade/simple/spawner/manhacks/mercenary,
+/obj/item/grenade/simple/spawner/manhacks/mercenary,
/obj/effect/floor_decal/corner/red/border{
dir = 1
},
diff --git a/maps/submaps/level_specific/class_p/HeadscientistHQ.dmm b/maps/submaps/level_specific/class_p/HeadscientistHQ.dmm
index 358ede97b89..77bc105193b 100644
--- a/maps/submaps/level_specific/class_p/HeadscientistHQ.dmm
+++ b/maps/submaps/level_specific/class_p/HeadscientistHQ.dmm
@@ -448,7 +448,7 @@
/turf/simulated/shuttle/floor/red,
/area/submap/HeadscientistHQ)
"uq" = (
-/obj/item/grenade/spawnergrenade/manhacks/mercenary,
+/obj/item/grenade/simple/spawner/manhacks/mercenary,
/turf/simulated/shuttle/floor/red,
/area/submap/HeadscientistHQ)
"uz" = (
diff --git a/maps/submaps/level_specific/debrisfield/derelict.dmm b/maps/submaps/level_specific/debrisfield/derelict.dmm
index 774d20ec77e..f8c0891a557 100644
--- a/maps/submaps/level_specific/debrisfield/derelict.dmm
+++ b/maps/submaps/level_specific/debrisfield/derelict.dmm
@@ -133,7 +133,7 @@
/area/debrisfield/derelict)
"aQ" = (
/obj/machinery/vr_sleeper/alien,
-/obj/item/grenade/empgrenade,
+/obj/item/grenade/simple/emp,
/turf/simulated/floor/tiled/asteroid_steel/airless,
/area/debrisfield/derelict)
"aR" = (
@@ -708,9 +708,9 @@
/turf/simulated/floor/plating/outdoors,
/area/debrisfield/derelict)
"Zu" = (
-/obj/item/grenade/empgrenade,
-/obj/item/grenade/empgrenade,
-/obj/item/grenade/empgrenade,
+/obj/item/grenade/simple/emp,
+/obj/item/grenade/simple/emp,
+/obj/item/grenade/simple/emp,
/turf/simulated/floor/plating/outdoors,
/area/debrisfield/derelict)
diff --git a/maps/submaps/level_specific/debrisfield_vr/derelict.dmm b/maps/submaps/level_specific/debrisfield_vr/derelict.dmm
index f2dc7edf466..e8c71ec8f8a 100644
--- a/maps/submaps/level_specific/debrisfield_vr/derelict.dmm
+++ b/maps/submaps/level_specific/debrisfield_vr/derelict.dmm
@@ -155,7 +155,7 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/item/grenade/empgrenade,
+/obj/item/grenade/simple/emp,
/turf/simulated/floor/bluegrid,
/area/submap/debrisfield_vr/derelict/interior)
"aB" = (
@@ -501,9 +501,9 @@
/turf/simulated/floor/tiled/steel_dirty,
/area/submap/debrisfield_vr/derelict/interior)
"bO" = (
-/obj/item/grenade/empgrenade,
-/obj/item/grenade/empgrenade,
-/obj/item/grenade/empgrenade,
+/obj/item/grenade/simple/emp,
+/obj/item/grenade/simple/emp,
+/obj/item/grenade/simple/emp,
/turf/space,
/area/space)
"bP" = (
diff --git a/maps/submaps/level_specific/virgo2/Rockybase.dmm b/maps/submaps/level_specific/virgo2/Rockybase.dmm
index 6c68c4bfbb3..3665766b8ef 100644
--- a/maps/submaps/level_specific/virgo2/Rockybase.dmm
+++ b/maps/submaps/level_specific/virgo2/Rockybase.dmm
@@ -192,9 +192,9 @@
/area/submap/virgo2/Rockybase)
"aM" = (
/obj/structure/table/standard,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/machinery/light{
dir = 4
},
@@ -434,7 +434,7 @@
/area/submap/virgo2/Rockybase)
"bB" = (
/obj/structure/table/standard,
-/obj/item/grenade/spawnergrenade/manhacks,
+/obj/item/grenade/simple/spawner/manhacks,
/turf/simulated/floor/tiled/techfloor/virgo2,
/area/submap/virgo2/Rockybase)
"bC" = (
diff --git a/maps/submaps/mountains/Scave1.dmm b/maps/submaps/mountains/Scave1.dmm
index 5fd45174285..2a0e8a281f6 100644
--- a/maps/submaps/mountains/Scave1.dmm
+++ b/maps/submaps/mountains/Scave1.dmm
@@ -37,7 +37,7 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/cave/Scave1)
"j" = (
-/obj/item/grenade/spawnergrenade/spider,
+/obj/item/grenade/simple/spawner/spider,
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/cave/Scave1)
"k" = (
diff --git a/maps/submaps/plains/Thiefc_vr.dmm b/maps/submaps/plains/Thiefc_vr.dmm
index b7fc35c88a9..6c7acfe7c79 100644
--- a/maps/submaps/plains/Thiefc_vr.dmm
+++ b/maps/submaps/plains/Thiefc_vr.dmm
@@ -123,7 +123,7 @@
/obj/structure/closet/crate,
/obj/item/storage/box/shotgunammo,
/obj/item/storage/box/practiceshells,
-/obj/item/grenade/spawnergrenade/manhacks/station,
+/obj/item/grenade/simple/spawner/manhacks/station,
/turf/simulated/floor/outdoors/dirt{
outdoors = 0
},
diff --git a/maps/submaps/wilderness/Blackshuttledown.dmm b/maps/submaps/wilderness/Blackshuttledown.dmm
index ab427a6bec4..42df9ce61e9 100644
--- a/maps/submaps/wilderness/Blackshuttledown.dmm
+++ b/maps/submaps/wilderness/Blackshuttledown.dmm
@@ -263,7 +263,7 @@
/area/submap/Blackshuttledown)
"aR" = (
/obj/structure/table/steel,
-/obj/item/grenade/smokebomb,
+/obj/item/grenade/simple/smoke,
/turf/simulated/floor/tiled/steel_grid,
/area/submap/Blackshuttledown)
"aS" = (
diff --git a/maps/submaps/wilderness/Blueshuttledown.dmm b/maps/submaps/wilderness/Blueshuttledown.dmm
index ce60524c8c4..70b4ef1ec5f 100644
--- a/maps/submaps/wilderness/Blueshuttledown.dmm
+++ b/maps/submaps/wilderness/Blueshuttledown.dmm
@@ -265,7 +265,7 @@
/area/submap/Blackshuttledown)
"aR" = (
/obj/structure/table/steel,
-/obj/item/grenade/smokebomb,
+/obj/item/grenade/simple/smoke,
/turf/simulated/floor/tiled/steel_grid,
/area/submap/Blackshuttledown)
"aS" = (
diff --git a/maps/submaps/wilderness/Rockybase.dmm b/maps/submaps/wilderness/Rockybase.dmm
index 557db9ae73f..0cfbf027111 100644
--- a/maps/submaps/wilderness/Rockybase.dmm
+++ b/maps/submaps/wilderness/Rockybase.dmm
@@ -7,7 +7,7 @@
/turf/template_noop,
/area/template_noop)
"ac" = (
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/template_noop,
/area/template_noop)
"ad" = (
@@ -275,9 +275,9 @@
/area/submap/Rockybase)
"bb" = (
/obj/structure/table/standard,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/machinery/light{
dir = 4
},
@@ -630,7 +630,7 @@
/area/submap/Rockybase)
"ci" = (
/obj/structure/table/standard,
-/obj/item/grenade/spawnergrenade/manhacks,
+/obj/item/grenade/simple/spawner/manhacks,
/turf/simulated/floor/tiled,
/area/submap/Rockybase)
"cj" = (
diff --git a/maps/templates/admin/dhael_centcom.dmm b/maps/templates/admin/dhael_centcom.dmm
index f83d133e8fc..3b6d676bea9 100644
--- a/maps/templates/admin/dhael_centcom.dmm
+++ b/maps/templates/admin/dhael_centcom.dmm
@@ -949,12 +949,12 @@
/obj/item/clothing/glasses/welding/superior,
/obj/structure/table/steel_reinforced,
/obj/item/clothing/glasses/welding/superior,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/unsimulated/floor{
icon_state = "dark"
},
diff --git a/maps/templates/admin/ert.dmm b/maps/templates/admin/ert.dmm
index 6e870a39a38..e03230e48f7 100644
--- a/maps/templates/admin/ert.dmm
+++ b/maps/templates/admin/ert.dmm
@@ -4948,12 +4948,12 @@
/obj/item/stack/cable_coil,
/obj/item/stack/cable_coil,
/obj/item/stack/cable_coil,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/obj/machinery/light,
/turf/simulated/floor/tiled/techfloor,
/area/ship/ert/eng_storage)
diff --git a/maps/templates/admin/ert_base.dmm b/maps/templates/admin/ert_base.dmm
index 0ba99c67ca3..1c5fad8951f 100644
--- a/maps/templates/admin/ert_base.dmm
+++ b/maps/templates/admin/ert_base.dmm
@@ -1552,12 +1552,12 @@
/obj/item/stack/cable_coil,
/obj/item/stack/cable_coil,
/obj/item/stack/cable_coil,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/simulated/shuttle/floor/black,
/area/shuttle/specops/centcom)
"dm" = (
diff --git a/maps/templates/admin/mercbase.dmm b/maps/templates/admin/mercbase.dmm
index 800d7cb89b0..99996e8ec7e 100644
--- a/maps/templates/admin/mercbase.dmm
+++ b/maps/templates/admin/mercbase.dmm
@@ -2464,9 +2464,9 @@
name = "Grenade Crate";
opened = 1
},
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
diff --git a/maps/templates/admin/skipjack.dmm b/maps/templates/admin/skipjack.dmm
index a8babef2e72..8d05df28845 100644
--- a/maps/templates/admin/skipjack.dmm
+++ b/maps/templates/admin/skipjack.dmm
@@ -1271,9 +1271,9 @@
/area/shuttle/skipjack)
"dc" = (
/obj/structure/table/rack,
-/obj/item/grenade/empgrenade,
-/obj/item/grenade/flashbang,
-/obj/item/grenade/spawnergrenade/manhacks,
+/obj/item/grenade/simple/emp,
+/obj/item/grenade/simple/flashbang,
+/obj/item/grenade/simple/spawner/manhacks,
/turf/simulated/shuttle/floor/darkred,
/area/shuttle/skipjack)
"dd" = (
diff --git a/maps/templates/shuttles/overmaps/generic/abductor.dmm b/maps/templates/shuttles/overmaps/generic/abductor.dmm
index 0142243a405..afc63b4ac50 100644
--- a/maps/templates/shuttles/overmaps/generic/abductor.dmm
+++ b/maps/templates/shuttles/overmaps/generic/abductor.dmm
@@ -81,8 +81,8 @@
"fQ" = (
/obj/item/storage/box/flashbangs,
/obj/item/storage/box/teargas,
-/obj/item/grenade/flashbang/clusterbang,
-/obj/item/grenade/flashbang/clusterbang,
+/obj/item/grenade/simple/flashbang/clusterbang,
+/obj/item/grenade/simple/flashbang/clusterbang,
/obj/item/storage/box/metalfoam,
/obj/item/clothing/mask/gas/plaguedoctor,
/obj/item/clothing/mask/gas,
diff --git a/maps/templates/shuttles/overmaps/generic/cruiser.dmm b/maps/templates/shuttles/overmaps/generic/cruiser.dmm
index c6564cabd02..eec6b02c608 100644
--- a/maps/templates/shuttles/overmaps/generic/cruiser.dmm
+++ b/maps/templates/shuttles/overmaps/generic/cruiser.dmm
@@ -4132,10 +4132,10 @@
/obj/item/reagent_containers/glass/bucket,
/obj/item/reagent_containers/spray/cleaner,
/obj/item/reagent_containers/spray/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/item/soap/nanotrasen,
/obj/item/soap/deluxe,
/obj/item/soap,
diff --git a/maps/templates/shuttles/overmaps/generic/mercenarybase.dmm b/maps/templates/shuttles/overmaps/generic/mercenarybase.dmm
index 66203f1b21c..8b45d502c45 100644
--- a/maps/templates/shuttles/overmaps/generic/mercenarybase.dmm
+++ b/maps/templates/shuttles/overmaps/generic/mercenarybase.dmm
@@ -2351,7 +2351,7 @@
/obj/item/clothing/accessory/armor/legguards/combat,
/obj/item/clothing/head/helmet/redcombat,
/obj/item/gun/projectile/energy/gun,
-/obj/item/grenade/flashbang,
+/obj/item/grenade/simple/flashbang,
/turf/simulated/floor/tiled/dark,
/area/mercbase/eqroom)
"lR" = (
@@ -2391,7 +2391,7 @@
/obj/item/clothing/accessory/armor/legguards/combat,
/obj/item/clothing/head/helmet/redcombat,
/obj/item/gun/projectile/energy/gun,
-/obj/item/grenade/flashbang,
+/obj/item/grenade/simple/flashbang,
/turf/simulated/floor/tiled/dark,
/area/mercbase/eqroom)
"lT" = (
@@ -3142,7 +3142,7 @@
/obj/item/clothing/accessory/armor/legguards/combat,
/obj/item/clothing/head/helmet/redcombat,
/obj/item/gun/projectile/energy/gun,
-/obj/item/grenade/flashbang,
+/obj/item/grenade/simple/flashbang,
/turf/simulated/floor/tiled/dark,
/area/mercbase/eqroom)
"oo" = (
@@ -3182,7 +3182,7 @@
/obj/item/clothing/accessory/armor/legguards/combat,
/obj/item/clothing/head/helmet/redcombat,
/obj/item/gun/projectile/energy/gun,
-/obj/item/grenade/flashbang,
+/obj/item/grenade/simple/flashbang,
/turf/simulated/floor/tiled/dark,
/area/mercbase/eqroom)
"os" = (
diff --git a/maps/templates/shuttles/overmaps/generic/shelter_6.dmm b/maps/templates/shuttles/overmaps/generic/shelter_6.dmm
index 9e3ea9bb659..6cee29e5539 100644
--- a/maps/templates/shuttles/overmaps/generic/shelter_6.dmm
+++ b/maps/templates/shuttles/overmaps/generic/shelter_6.dmm
@@ -573,10 +573,10 @@
/obj/item/reagent_containers/glass/bucket,
/obj/item/reagent_containers/spray/cleaner,
/obj/item/reagent_containers/spray/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/item/soap/nanotrasen,
/obj/item/soap/deluxe,
/obj/item/soap,
diff --git a/maps/tether/levels/surface1.dmm b/maps/tether/levels/surface1.dmm
index 1af01c2f2fc..e6eee6f1c4d 100644
--- a/maps/tether/levels/surface1.dmm
+++ b/maps/tether/levels/surface1.dmm
@@ -29861,9 +29861,9 @@
/area/rnd/outpost/heating)
"qad" = (
/obj/structure/closet/crate,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
diff --git a/maps/tether/levels/surface2.dmm b/maps/tether/levels/surface2.dmm
index 214c2b6c58c..e53926c948e 100644
--- a/maps/tether/levels/surface2.dmm
+++ b/maps/tether/levels/surface2.dmm
@@ -14905,10 +14905,10 @@
dir = 4
},
/obj/structure/table/steel,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
-/obj/item/grenade/chem_grenade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
+/obj/item/grenade/simple/chemical/premade/cleaner,
/obj/item/storage/box/mousetraps,
/obj/item/storage/box/lights/mixed,
/obj/item/storage/box/lights/mixed,
@@ -21663,10 +21663,10 @@
/turf/simulated/floor/tiled/techmaint,
/area/engineering/drone_fabrication)
"pUA" = (
-/obj/item/grenade/chem_grenade/cleaner{
+/obj/item/grenade/simple/chemical/premade/cleaner{
pixel_x = -10
},
-/obj/item/grenade/anti_photon,
+/obj/item/grenade/simple/antiphoton,
/turf/simulated/floor/plating,
/area/tether/surfacebase/funny/hideyhole)
"pUD" = (
diff --git a/maps/tether/levels/surface3.dmm b/maps/tether/levels/surface3.dmm
index d21deefa255..eff3cae7461 100644
--- a/maps/tether/levels/surface3.dmm
+++ b/maps/tether/levels/surface3.dmm
@@ -28688,9 +28688,9 @@
/obj/structure/closet/crate{
name = "Grenade Crate"
},
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
/obj/item/assembly/timer,
diff --git a/maps/triumph/levels/deck3.dmm b/maps/triumph/levels/deck3.dmm
index ac765c5d996..ea9ec29db92 100644
--- a/maps/triumph/levels/deck3.dmm
+++ b/maps/triumph/levels/deck3.dmm
@@ -25334,9 +25334,9 @@
/obj/structure/closet/crate{
name = "Grenade Crate"
},
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
-/obj/item/grenade/chem_grenade,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
+/obj/item/grenade/simple/chemical,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
/obj/item/assembly/igniter,
diff --git a/maps/triumph/levels/flagship.dmm b/maps/triumph/levels/flagship.dmm
index 85b960993dc..dbafa32e6e1 100644
--- a/maps/triumph/levels/flagship.dmm
+++ b/maps/triumph/levels/flagship.dmm
@@ -2388,12 +2388,12 @@
/obj/item/clothing/glasses/welding/superior,
/obj/structure/table/steel_reinforced,
/obj/item/clothing/glasses/welding/superior,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
-/obj/item/grenade/chem_grenade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
+/obj/item/grenade/simple/chemical/premade/metalfoam,
/turf/unsimulated/floor{
icon_state = "dark"
},
@@ -8084,7 +8084,7 @@
},
/area/centcom/medical)
"yW" = (
-/obj/item/grenade/supermatter,
+/obj/item/grenade/simple/supermatter,
/obj/structure/table/rack/steel,
/obj/machinery/door/window/brigdoor{
req_access = list(109)