diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index e3b1d082623..6edc8e67ecc 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -113,9 +113,8 @@
else
reagents.add_reagent("spore", 8)
- // Attach the smoke spreader and setup/start it.
- S.attach(location)
- S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud
+ // Setup up the smoke spreader and start it.
+ S.set_up(reagents, location, TRUE)
S.start()
qdel(src)
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index 51360c7b398..d9caf977211 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -411,11 +411,9 @@
B.icon_state = null //Invisible
B.reagents.add_reagent("blindness_smoke", 10)
var/datum/effect_system/smoke_spread/chem/S = new
- S.attach(B)
if(S)
- S.set_up(B.reagents, 10, 0, B.loc)
+ S.set_up(B.reagents, B.loc, TRUE)
S.start(4)
- sleep(10)
qdel(B)
/datum/reagent/shadowling_blindness_smoke //Blinds non-shadowlings, heals shadowlings/thralls
diff --git a/code/game/objects/effects/effect_system/effects_chem_smoke.dm b/code/game/objects/effects/effect_system/effects_chem_smoke.dm
new file mode 100644
index 00000000000..d68692a03e6
--- /dev/null
+++ b/code/game/objects/effects/effect_system/effects_chem_smoke.dm
@@ -0,0 +1,122 @@
+/////////////////////////////////////////////
+// Chem smoke
+/////////////////////////////////////////////
+
+/obj/effect/particle_effect/chem_smoke
+ icon = 'icons/goonstation/effects/64x64.dmi'
+ icon_state = "smoke"
+ density = FALSE
+ opacity = FALSE
+ animate_movement = NO_STEPS
+ var/matrix/first = matrix()
+ var/matrix/second = matrix()
+ var/matrix/third = matrix()
+ var/first_scale = 0.1
+ var/second_scale = 5
+ var/third_scale = 2
+ var/spread_amount = 96
+
+/obj/effect/particle_effect/chem_smoke/New(location, chem_color)
+ ..()
+ color = chem_color
+ pixel_x += -16 + rand(-3, 3)
+ pixel_y += -16 + rand(-3, 3)
+
+ first = turn(first, rand(-90, 90))
+ first.Scale(first_scale, first_scale)
+ transform = first
+
+ second = first
+ second.Scale(second_scale, second_scale)
+
+ third.Scale(third_scale, third_scale)
+
+ animate(src,transform = second, time = 5, alpha = 200)
+ animate(transform = third, time = 20, pixel_y = rand(-spread_amount, spread_amount), pixel_x = rand(-spread_amount, spread_amount), alpha = 1)
+ QDEL_IN(src, 26)
+
+
+/obj/effect/particle_effect/chem_smoke/small
+ first_scale = 0.05
+ second_scale = 2.5
+ third_scale = 1
+ spread_amount = 48
+
+
+/datum/effect_system/smoke_spread/chem
+ var/obj/chemholder
+ var/list/smoked_atoms = list()
+
+/datum/effect_system/smoke_spread/chem/New()
+ ..()
+ chemholder = new
+ chemholder.create_reagents(1000)
+ chemholder.reagents.set_reacting(FALSE) // Just in case
+
+/datum/effect_system/smoke_spread/chem/Destroy()
+ QDEL_NULL(chemholder)
+ smoked_atoms.Cut()
+ return ..()
+
+/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, loca, silent = FALSE)
+ if(isturf(loca))
+ location = loca
+ else
+ location = get_turf(loca)
+ carry.copy_to(chemholder, carry.total_volume)
+ if(!silent)
+ var/contained = ""
+ for(var/reagent in carry.reagent_list)
+ contained += " [reagent] "
+ if(contained)
+ contained = "\[[contained]\]"
+ var/area/A = get_area(location)
+
+ var/where = "[A.name] | [location.x], [location.y]"
+ var/whereLink = "[where]"
+
+ if(carry && carry.my_atom)
+ if(carry.my_atom.fingerprintslast)
+ var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
+ var/more = ""
+ if(M)
+ more = " "
+ msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", ATKLOG_FEW)
+ log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
+ else
+ msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", ATKLOG_FEW)
+ log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
+ else
+ msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", ATKLOG_FEW)
+ log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key. CODERS: carry.my_atom may be null.")
+
+
+/datum/effect_system/smoke_spread/chem/start(effect_range = 2)
+ set waitfor = FALSE
+
+ var/color = mix_color_from_reagents(chemholder.reagents.reagent_list)
+
+ for(var/x in 0 to 99)
+ for(var/i = 0, i < rand(2, 6), i++)
+ if(effect_range < 3)
+ new /obj/effect/particle_effect/chem_smoke/small(location, color)
+ else
+ new /obj/effect/particle_effect/chem_smoke(location, color)
+
+ if(x % 10 == 0) //Once every 10 ticks.
+ SmokeEm(effect_range)
+
+ sleep(1)
+ qdel(src)
+
+
+/datum/effect_system/smoke_spread/chem/proc/SmokeEm(effect_range = 2)
+ for(var/atom/A in view(effect_range, get_turf(location)))
+ if(A in smoked_atoms)
+ continue
+ smoked_atoms += A
+ chemholder.reagents.reaction(A)
+ if(iscarbon(A))
+ var/mob/living/carbon/C = A
+ if(C.can_breathe_gas())
+ chemholder.reagents.copy_to(C, chemholder.reagents.total_volume)
\ No newline at end of file
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index 1df0166260e..405a0ec46f7 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -207,99 +207,4 @@
return 1
/datum/effect_system/smoke_spread/sleeping
- effect_type = /obj/effect/particle_effect/smoke/sleeping
-
-/////////////////////////////////////////////
-// Chem smoke
-/////////////////////////////////////////////
-
-/obj/effect/particle_effect/smoke/chem
- icon = 'icons/effects/chemsmoke.dmi'
- opacity = 0
- lifetime = 10
-
-/datum/effect_system/smoke_spread/chem
- effect_type = /obj/effect/particle_effect/smoke/chem
- var/obj/chemholder
-
-/datum/effect_system/smoke_spread/chem/New()
- ..()
- chemholder = new/obj()
- var/datum/reagents/R = new/datum/reagents(500)
- chemholder.reagents = R
- R.my_atom = chemholder
-
-/datum/effect_system/smoke_spread/chem/Destroy()
- QDEL_NULL(chemholder)
- return ..()
-
-/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, n = 5, c = 0, loca, direct, silent = 0)
- if(n > 20)
- n = 20
- number = n
- cardinals = c
-
- if(isturf(loca))
- location = loca
- else
- location = get_turf(loca)
- if(direct)
- direction = direct
- carry.copy_to(chemholder, carry.total_volume)
- if(!silent)
- var/contained = ""
- for(var/reagent in carry.reagent_list)
- contained += " [reagent] "
- if(contained)
- contained = "\[[contained]\]"
- var/area/A = get_area(location)
-
- var/where = "[A.name] | [location.x], [location.y]"
- var/whereLink = "[where]"
-
- if(carry && carry.my_atom)
- if(carry.my_atom.fingerprintslast)
- var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
- var/more = ""
- if(M)
- more = " "
- msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", ATKLOG_FEW)
- log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
- else
- msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", ATKLOG_FEW)
- log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
- else
- msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", ATKLOG_FEW)
- log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key. CODERS: carry.my_atom may be null.")
-
-/datum/effect_system/smoke_spread/chem/start(effect_range = 2)
- var/color = mix_color_from_reagents(chemholder.reagents.reagent_list)
- var/obj/effect/particle_effect/smoke/chem/smokeholder = new effect_type(location)
- for(var/atom/A in view(effect_range, smokeholder))
- chemholder.reagents.reaction(A)
- if(iscarbon(A))
- var/mob/living/carbon/C = A
- if(C.can_breathe_gas())
- chemholder.reagents.copy_to(C, chemholder.reagents.total_volume)
- qdel(smokeholder)
- for(var/i=0, i=5 && created_volume < 10)
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index 2ae4e3ac828..dad2b6698ad 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -318,7 +318,7 @@
R.add_reagent(chosenchem , 15)
investigate_log("Experimentor has released [chosenchem] smoke.", "experimentor")
var/datum/effect_system/smoke_spread/chem/smoke = new
- smoke.set_up(R, 1, 0, src, 0, silent = 1)
+ smoke.set_up(R, src, TRUE)
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
smoke.start()
qdel(R)
@@ -330,7 +330,7 @@
R.my_atom = src
R.add_reagent(chosenchem , 15)
var/datum/effect_system/smoke_spread/chem/smoke = new
- smoke.set_up(R, 1, 0, src, 0, silent = 1)
+ smoke.set_up(R, src, TRUE)
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
smoke.start()
qdel(R)
@@ -417,7 +417,7 @@
R.add_reagent("frostoil" , 15)
investigate_log("Experimentor has released frostoil gas.", "experimentor")
var/datum/effect_system/smoke_spread/chem/smoke = new
- smoke.set_up(R, 1, 0, src, 0, silent = 1)
+ smoke.set_up(R, src, TRUE)
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
smoke.start()
qdel(R)
diff --git a/icons/goonstation/effects/64x64.dmi b/icons/goonstation/effects/64x64.dmi
new file mode 100644
index 00000000000..e1b168bbc11
Binary files /dev/null and b/icons/goonstation/effects/64x64.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 13808883967..4f9c776cc99 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -786,6 +786,7 @@
#include "code\game\objects\effects\decals\Cleanable\robots.dm"
#include "code\game\objects\effects\decals\Cleanable\tracks.dm"
#include "code\game\objects\effects\effect_system\effect_system.dm"
+#include "code\game\objects\effects\effect_system\effects_chem_smoke.dm"
#include "code\game\objects\effects\effect_system\effects_explosion.dm"
#include "code\game\objects\effects\effect_system\effects_foam.dm"
#include "code\game\objects\effects\effect_system\effects_other.dm"