diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index ba3ed604e00..a4503e427d8 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -406,6 +406,128 @@
range_light = 4
range_flame = 2
+/obj/item/weapon/bombcore/chemical
+ name = "chemical payload"
+ desc = "An explosive payload designed to spread chemicals, dangerous or otherwise, across a large area. It is able to hold up to four chemical containers, and must be loaded before use."
+ origin_tech = "combat=4;materials=3"
+ icon_state = "chemcore"
+ var/list/beakers = list()
+ var/max_beakers = 1
+ var/spread_range = 5
+ var/temp_boost = 50
+ var/time_release = 0
+
+/obj/item/weapon/bombcore/chemical/detonate()
+
+ if(time_release > 0)
+ var/total_volume = 0
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ total_volume += RC.reagents.total_volume
+
+ if(total_volume < time_release) // If it's empty, the detonation is complete.
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
+ qdel(src)
+ return
+
+ var/fraction = time_release/total_volume
+ var/datum/reagents/reactants = new(time_release)
+ reactants.my_atom = src
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, 1, 1, 1)
+ chem_splash(get_turf(src), spread_range, list(reactants), temp_boost)
+
+ // Detonate it again in one second, until it's out of juice.
+ addtimer(src, "detonate", 10)
+
+ // If it's not a time release bomb, do normal explosion
+
+ var/list/reactants = list()
+
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ reactants += G.reagents
+
+ for(var/obj/item/slime_extract/S in beakers)
+ if(S.Uses)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ G.reagents.trans_to(S, G.reagents.total_volume)
+
+ if(S && S.reagents && S.reagents.total_volume)
+ reactants += S.reagents
+
+ if(!chem_splash(get_turf(src), spread_range, reactants, temp_boost))
+ playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ return // The Explosion didn't do anything. No need to log, or disappear.
+
+ if(adminlog)
+ message_admins(adminlog)
+ log_game(adminlog)
+
+ playsound(loc, 'sound/effects/bamf.ogg', 75, 1, 5)
+
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
+ qdel(src)
+
+/obj/item/weapon/bombcore/chemical/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/weapon/crowbar) && beakers.len > 0)
+ playsound(loc, I.usesound, 50, 1)
+ for (var/obj/item/B in beakers)
+ B.loc = get_turf(src)
+ beakers -= B
+ return
+ else if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker) || istype(I, /obj/item/weapon/reagent_containers/glass/bottle))
+ if(beakers.len < max_beakers)
+ if(!user.drop_item())
+ return
+ beakers += I
+ to_chat(user, "You load [src] with [I].")
+ I.loc = src
+ else
+ to_chat(user, "The [I] wont fit! The [src] can only hold up to [max_beakers] containers.")
+ return
+ ..()
+
+/obj/item/weapon/bombcore/chemical/CheckParts(list/parts_list)
+ ..()
+ // Using different grenade casings, causes the payload to have different properties.
+ var/obj/item/weapon/stock_parts/matter_bin/MB = locate(/obj/item/weapon/stock_parts/matter_bin) in src
+ if(MB)
+ max_beakers += MB.rating // max beakers = 2-5.
+ qdel(MB)
+ for(var/obj/item/weapon/grenade/chem_grenade/G in src)
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/large))
+ var/obj/item/weapon/grenade/chem_grenade/large/LG = G
+ max_beakers += 1 // Adding two large grenades only allows for a maximum of 7 beakers.
+ spread_range += 2 // Extra range, reduced density.
+ temp_boost += 50 // maximum of +150K blast using only large beakers. Not enough to self ignite.
+ for(var/obj/item/slime_extract/S in LG.beakers) // And slime cores.
+ if(beakers.len < max_beakers)
+ beakers += S
+ S.loc = src
+ else
+ S.loc = get_turf(src)
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/cryo))
+ spread_range -= 1 // Reduced range, but increased density.
+ temp_boost -= 100 // minimum of -150K blast.
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/pyro))
+ temp_boost += 150 // maximum of +350K blast, which is enough to self ignite. Which means a self igniting bomb can't take advantage of other grenade casing properties. Sorry?
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/adv_release))
+ time_release += 50 // A typical bomb, using basic beakers, will explode over 2-4 seconds. Using two will make the reaction last for less time, but it will be more dangerous overall.
+
+ for(var/obj/item/weapon/reagent_containers/glass/B in G)
+ if(beakers.len < max_beakers)
+ beakers += B
+ B.loc = src
+ else
+ B.loc = get_turf(src)
+
+ qdel(G)
+
///Syndicate Detonator (aka the big red button)///
/obj/item/device/syndicatedetonator
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index f21914a7c32..9ba1950d2a0 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -19,6 +19,9 @@
var/obj/item/device/assembly_holder/nadeassembly = null
var/label = null
var/assemblyattacher
+ var/ignition_temp = 10 // The amount of heat added to the reagents when this grenade goes off.
+ var/threatscale = 1 // Used by advanced grenades to make them slightly more worthy.
+ var/no_splash = FALSE //If the grenade deletes even if it has no reagents to splash with. Used for slime core reactions.
/obj/item/weapon/grenade/chem_grenade/New()
create_reagents(1000)
@@ -99,6 +102,7 @@
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])")
bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])"
to_chat(user, "You prime the [name]! [det_time / 10] second\s!")
+ playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
active = 1
update_icon()
if(iscarbon(user))
@@ -264,13 +268,18 @@
if(stage != READY)
return
- var/has_reagents = 0
+ var/list/datum/reagents/reactants = list()
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- if(G.reagents.total_volume)
- has_reagents = 1
+ reactants += G.reagents
- if(!has_reagents)
- playsound(loc, usesound, 50, 1)
+ if(!chem_splash(get_turf(src), affected_area, reactants, ignition_temp, threatscale) && !no_splash)
+ playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ if(beakers.len)
+ for(var/obj/O in beakers)
+ O.forceMove(get_turf(src))
+ beakers = list()
+ stage = EMPTY
+ update_icon()
return
if(nadeassembly)
@@ -281,31 +290,9 @@
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) ([admin_jump_link(M)]) and last touched by [key_name_admin(last)](?) ([admin_jump_link(last)]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
- playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
-
update_mob()
- invisibility = INVISIBILITY_MAXIMUM //kaboom
- qdel(nadeassembly) // do this now to stop infrared beams
- var/end_temp = 0
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(src, G.reagents.total_volume)
- end_temp += G.reagents.chem_temp
- reagents.chem_temp = end_temp
- if(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/atom/A in view(affected_area, loc))
- if(A == src)
- continue
- reagents.reaction(A, 1, 10)
-
-
- spawn(15) //Making sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
+ qdel(src)
/obj/item/weapon/grenade/chem_grenade/proc/CreateDefaultTrigger(var/typekey)
if(ispath(typekey,/obj/item/device/assembly))
@@ -327,64 +314,37 @@
//Large chem grenades accept slime cores and use the appropriately.
/obj/item/weapon/grenade/chem_grenade/large
name = "large grenade casing"
- desc = "For oversized grenades; fits additional contents and affects a greater area."
+ desc = "A custom made large grenade. It affects a larger area."
icon_state = "large_grenade"
bomb_state = "largebomb"
allowed_containers = list(/obj/item/weapon/reagent_containers/glass,/obj/item/weapon/reagent_containers/food/condiment,
/obj/item/weapon/reagent_containers/food/drinks)
origin_tech = "combat=3;engineering=3"
- affected_area = 4
-
+ affected_area = 5
+ ignition_temp = 25 // Large grenades are slightly more effective at setting off heat-sensitive mixtures than smaller grenades.
+ threatscale = 1.1 // 10% more effective.
/obj/item/weapon/grenade/chem_grenade/large/prime()
if(stage != READY)
return
- var/has_reagents = 0
- var/obj/item/slime_extract/valid_core = null
+ for(var/obj/item/slime_extract/S in beakers)
+ if(S.Uses)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ G.reagents.trans_to(S, G.reagents.total_volume)
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- if(!istype(G)) continue
- if(G.reagents.total_volume) has_reagents = 1
- for(var/obj/item/slime_extract/E in beakers)
- if(!istype(E)) continue
- if(E.Uses) valid_core = E
- if(E.reagents.total_volume) has_reagents = 1
+ //If there is still a core (sometimes it's used up)
+ //and there are reagents left, behave normally,
+ //otherwise drop it on the ground for timed reactions like gold.
- if(!has_reagents)
- playsound(loc, prime_sound, 50, 1)
- return
-
- playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
-
- update_mob()
-
- if(valid_core)
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(valid_core, G.reagents.total_volume)
-
- //If there is still a core (sometimes it's used up)
- //and there are reagents left, behave normally
-
- if(valid_core && valid_core.reagents && valid_core.reagents.total_volume)
- valid_core.reagents.trans_to(src,valid_core.reagents.total_volume)
- else
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(src, G.reagents.total_volume)
-
- if(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/atom/A in view(affected_area, loc))
- if( A == src ) continue
- reagents.reaction(A, 1, 10)
-
- invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
- spawn(50) //To make sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
+ if(S)
+ if(S.reagents && S.reagents.total_volume)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ S.reagents.trans_to(G, S.reagents.total_volume)
+ else
+ S.forceMove(get_turf(src))
+ no_splash = TRUE
+ ..()
//I tried to just put it in the allowed_containers list but
@@ -399,6 +359,71 @@
else
return ..()
+/obj/item/weapon/grenade/chem_grenade/cryo // Intended for rare cryogenic mixes. Cools the area moderately upon detonation.
+ name = "cryo grenade"
+ desc = "A custom made cryogenic grenade. It rapidly cools its contents upon detonation."
+ icon_state = "cryog"
+ affected_area = 2
+ ignition_temp = -100
+
+/obj/item/weapon/grenade/chem_grenade/pyro // Intended for pyrotechnical mixes. Produces a small fire upon detonation, igniting potentially flammable mixtures.
+ name = "pyro grenade"
+ desc = "A custom made pyrotechnical grenade. It heats up and ignites its contents upon detonation."
+ icon_state = "pyrog"
+ origin_tech = "combat=4;engineering=4"
+ affected_area = 3
+ ignition_temp = 500 // This is enough to expose a hotspot.
+
+/obj/item/weapon/grenade/chem_grenade/adv_release // Intended for weaker, but longer lasting effects. Could have some interesting uses.
+ name = "advanced release grenade"
+ desc = "A custom made advanced release grenade. It is able to be detonated more than once. Can be configured using a multitool."
+ icon_state = "timeg"
+ origin_tech = "combat=3;engineering=4"
+ var/unit_spread = 10 // Amount of units per repeat. Can be altered with a multitool.
+
+/obj/item/weapon/grenade/chem_grenade/adv_release/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/device/multitool))
+ switch(unit_spread)
+ if(0 to 24)
+ unit_spread += 5
+ if(25 to 99)
+ unit_spread += 25
+ else
+ unit_spread = 5
+ to_chat(user, " You set the time release to [unit_spread] units per detonation.")
+ return
+ ..()
+
+/obj/item/weapon/grenade/chem_grenade/adv_release/prime()
+ if(stage != READY)
+ return
+
+ var/total_volume = 0
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ total_volume += RC.reagents.total_volume
+ if(!total_volume)
+ qdel(src)
+ qdel(nadeassembly)
+ return
+ var/fraction = unit_spread/total_volume
+ var/datum/reagents/reactants = new(unit_spread)
+ reactants.my_atom = src
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, threatscale, 1, 1)
+ chem_splash(get_turf(src), affected_area, list(reactants), ignition_temp, threatscale)
+
+ if(nadeassembly)
+ var/mob/M = get_mob_by_ckey(assemblyattacher)
+ var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
+ var/turf/T = get_turf(src)
+ var/area/A = get_area(T)
+ message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) (FLW) and last touched by [key_name_admin(last)](?) (FLW) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
+ log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
+ else
+ addtimer(src, "prime", det_time)
+ var/turf/DT = get_turf(src)
+ var/area/DA = get_area(DT)
+ log_game("A grenade detonated at [DA.name] ([DT.x], [DT.y], [DT.z])")
/obj/item/weapon/grenade/chem_grenade/metalfoam
payload_name = "metal foam"
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 6f266c121e1..3fbcf39ed08 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -324,6 +324,30 @@
/obj/item/stack/rods = 1)
category = CAT_MISC
+/datum/crafting_recipe/chemical_payload
+ name = "Chemical Payload (C4)"
+ result = /obj/item/weapon/bombcore/chemical
+ reqs = list(
+ /obj/item/weapon/stock_parts/matter_bin = 1,
+ /obj/item/weapon/grenade/plastic/c4 = 1,
+ /obj/item/weapon/grenade/chem_grenade = 2
+ )
+ parts = list(/obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/grenade/chem_grenade = 2)
+ time = 30
+ category = CAT_WEAPON
+
+/datum/crafting_recipe/chemical_payload2
+ name = "Chemical Payload (gibtonite)"
+ result = /obj/item/weapon/bombcore/chemical
+ reqs = list(
+ /obj/item/weapon/stock_parts/matter_bin = 1,
+ /obj/item/weapon/twohanded/required/gibtonite = 1,
+ /obj/item/weapon/grenade/chem_grenade = 2
+ )
+ parts = list(/obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/grenade/chem_grenade = 2)
+ time = 50
+ category = CAT_WEAPON
+
/datum/crafting_recipe/bonfire
name = "Bonfire"
time = 60
diff --git a/code/modules/reagents/chem_splash.dm b/code/modules/reagents/chem_splash.dm
new file mode 100644
index 00000000000..7c16bf1ab9a
--- /dev/null
+++ b/code/modules/reagents/chem_splash.dm
@@ -0,0 +1,78 @@
+// Replaces chemgrenade stuff, allowing reagent explosions to be called from anywhere.
+// It should be called using a location, the range, and a list of reagents involved.
+
+// Threatscale is a multiplier for the 'threat' of the grenade. If you're increasing the affected range drastically, you might want to improve this.
+// Extra heat affects the temperature of the mixture, and may cause it to react in different ways.
+
+
+/proc/chem_splash(turf/epicenter, affected_range = 3, list/datum/reagents/reactants = list(), extra_heat = 0, threatscale = 1, adminlog = 1)
+ if(!isturf(epicenter) || !reactants.len || threatscale <= 0)
+ return
+ var/has_reagents
+ var/total_reagents
+ for(var/datum/reagents/R in reactants)
+ if(R.total_volume)
+ has_reagents = 1
+ total_reagents += R.total_volume
+
+ if(!has_reagents)
+ return
+
+ var/datum/reagents/splash_holder = new/datum/reagents(total_reagents*threatscale)
+ splash_holder.my_atom = epicenter // For some reason this is setting my_atom to null, and causing runtime errors.
+ var/total_temp = 0
+
+ for(var/datum/reagents/R in reactants)
+ R.trans_to(splash_holder, R.total_volume, threatscale, 1, 1)
+ total_temp += R.chem_temp
+ splash_holder.chem_temp = (total_temp/reactants.len) + extra_heat // Average temperature of reagents + extra heat.
+ splash_holder.handle_reactions() // React them now.
+
+ if(splash_holder.total_volume && affected_range >= 0) //The possible reactions didnt use up all reagents, so we spread it around.
+ var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
+ steam.set_up(10, 0, epicenter)
+ steam.attach(epicenter)
+ steam.start()
+
+ var/list/viewable = view(affected_range, epicenter)
+
+ var/list/accessible = list(epicenter)
+ for(var/i=1; i<=affected_range; i++)
+ var/list/turflist = list()
+ for(var/turf/T in (orange(i, epicenter) - orange(i-1, epicenter)))
+ turflist |= T
+ for(var/turf/T in turflist)
+ if( !(get_dir(T,epicenter) in cardinal) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) ))
+ turflist.Remove(T)
+ turflist.Add(T) // we move the purely diagonal turfs to the end of the list.
+ for(var/turf/T in turflist)
+ if(accessible[T])
+ continue
+ for(var/thing in T.GetAtmosAdjacentTurfs(alldir = TRUE))
+ var/turf/NT = thing
+ if(!(NT in accessible))
+ continue
+ if(!(get_dir(T,NT) in cardinal))
+ continue
+ accessible[T] = 1
+ break
+ var/list/reactable = accessible
+ for(var/turf/T in accessible)
+ for(var/atom/A in T.GetAllContents())
+ if(!(A in viewable))
+ continue
+ reactable |= A
+ if(extra_heat >= 300)
+ T.hotspot_expose(extra_heat*2, 5)
+ if(!reactable.len) //Nothing to react with. Probably means we're in nullspace.
+ return
+ for(var/thing in reactable)
+ var/atom/A = thing
+ var/distance = max(1,get_dist(A, epicenter))
+ var/fraction = 0.5/(2 ** distance) //50/25/12/6... for a 200u splash, 25/12/6/3... for a 100u, 12/6/3/1 for a 50u
+ splash_holder.reaction(A, TOUCH, fraction)
+
+ qdel(splash_holder)
+ return 1
+
+
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index c65c628353b..662843e337a 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -108,7 +108,7 @@ var/const/INGEST = 2
return the_id
-/datum/reagents/proc/trans_to(target, amount=1, multiplier=1, preserve_data=1)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred.
+/datum/reagents/proc/trans_to(target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred.
if(!target)
return
if(total_volume <= 0)
@@ -143,13 +143,14 @@ var/const/INGEST = 2
if(preserve_data)
trans_data = copy_data(current_reagent)
- R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data, chem_temp)
+ R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data, chem_temp, no_react = 1)
remove_reagent(current_reagent.id, current_reagent_transfer)
update_total()
R.update_total()
- R.handle_reactions()
- handle_reactions()
+ if(!no_react)
+ R.handle_reactions()
+ handle_reactions()
return amount
/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1, safety = 0)
@@ -537,7 +538,7 @@ var/const/INGEST = 2
var/amt = list_reagents[r_id]
add_reagent(r_id, amt, data)
-/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300)
+/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)
if(!isnum(amount))
return 1
update_total()
@@ -554,7 +555,8 @@ var/const/INGEST = 2
update_total()
my_atom.on_reagent_change()
R.on_merge(data)
- handle_reactions()
+ if(!no_react)
+ handle_reactions()
return 0
var/datum/reagent/D = chemical_reagents_list[reagent]
@@ -570,7 +572,8 @@ var/const/INGEST = 2
update_total()
my_atom.on_reagent_change()
- handle_reactions()
+ if(!no_react)
+ handle_reactions()
return 0
else
warning("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index f60efa3b784..63db086cef8 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -40,7 +40,8 @@
/obj/machinery/biogenerator,
/obj/machinery/hydroponics,
/obj/machinery/constructable_frame,
- /obj/machinery/icemachine)
+ /obj/machinery/icemachine,
+ /obj/item/weapon/bombcore/chemical)
/obj/item/weapon/reagent_containers/glass/New()
..()
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index d406dcaf0ef..eb43698d451 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -29,6 +29,7 @@
/obj/structure/reagent_dispensers/proc/boom()
visible_message("[src] ruptures!")
+ chem_splash(loc, 5, list(reagents))
qdel(src)
/obj/structure/reagent_dispensers/ex_act(severity)
@@ -53,15 +54,6 @@
desc = "A water tank."
icon_state = "water"
-/obj/structure/reagent_dispensers/watertank/boom()
- playsound(loc, 'sound/effects/spray2.ogg', 50, 1, -6)
- new /obj/effect/effect/water(loc)
- for(var/turf/simulated/T in view(5, loc))
- T.MakeSlippery()
- for(var/mob/living/L in T)
- L.adjust_fire_stacks(-20)
- ..()
-
/obj/structure/reagent_dispensers/watertank/high
name = "high-capacity water tank"
desc = "A highly-pressurized water tank made to hold gargantuan amounts of water.."
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 9391af77424..09b17748dfd 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -80,6 +80,36 @@
build_path = /obj/item/weapon/grenade/chem_grenade/large
category = list("Weapons")
+/datum/design/pyro_grenade
+ name = "Pyro Grenade"
+ desc = "An advanced grenade that is able to self ignite its mixture."
+ id = "pyro_Grenade"
+ req_tech = list("combat" = 4, "engineering" = 4)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_PLASMA = 500)
+ build_path = /obj/item/weapon/grenade/chem_grenade/pyro
+ category = list("Weapons")
+
+/datum/design/cryo_grenade
+ name = "Cryo Grenade"
+ desc = "An advanced grenade that rapidly cools its contents upon detonation."
+ id = "cryo_Grenade"
+ req_tech = list("combat" = 3, "materials" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_SILVER = 500)
+ build_path = /obj/item/weapon/grenade/chem_grenade/cryo
+ category = list("Weapons")
+
+/datum/design/adv_grenade
+ name = "Advanced Release Grenade"
+ desc = "An advanced grenade that can be detonated several times, best used with a repeating igniter."
+ id = "adv_Grenade"
+ req_tech = list("combat" = 3, "engineering" = 4)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 500)
+ build_path = /obj/item/weapon/grenade/chem_grenade/adv_release
+ category = list("Weapons")
+
/datum/design/tele_shield
name = "Telescopic Riot Shield"
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi
index ad8268ad59d..f33135baec6 100644
Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 0775e9b2577..0f7332878f4 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1948,6 +1948,7 @@
#include "code\modules\projectiles\projectile\magic.dm"
#include "code\modules\projectiles\projectile\reusable.dm"
#include "code\modules\projectiles\projectile\special.dm"
+#include "code\modules\reagents\chem_splash.dm"
#include "code\modules\reagents\reagent_containers.dm"
#include "code\modules\reagents\reagent_dispenser.dm"
#include "code\modules\reagents\chemistry\colors.dm"