diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 53072d7e82c..7cfd8bbec45 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -192,7 +192,7 @@ var/global/list/image/splatter_cache = list()
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
- noclear = TRUE
+ no_clear = TRUE
var/fleshcolor = "#FFFFFF"
/obj/effect/decal/cleanable/blood/gibs/update_icon()
@@ -221,18 +221,11 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/gibs/core
random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-
-/obj/effect/decal/cleanable/blood/gibs/Initialize()
- . = ..()
- reagents.add_reagent("liquidgibs", 5)
+ scoop_reagents = list("liquidgibs" = 5)
/obj/effect/decal/cleanable/blood/gibs/cleangibs //most ironic name ever...
-
-/obj/effect/decal/cleanable/blood/gibs/cleangibs/Initialize() //no reagent!
- . = ..()
- reagents.remove_reagent("liquidgibs",5)
-
+ scoop_reagents = null
/obj/effect/decal/cleanable/blood/gibs/proc/streak(var/list/directions)
set waitfor = 0
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index d601283a703..7b5f255fcfb 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -15,10 +15,7 @@
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
anchored = TRUE
-
-/obj/effect/decal/cleanable/ash/Initialize()
- . = ..()
- reagents.add_reagent("ash", 10)
+ scoop_reagents = list("ash" = 10)
/obj/effect/decal/cleanable/dirt
name = "dirt"
@@ -40,11 +37,8 @@
/obj/effect/decal/cleanable/dirt/blackpowder
name = "black powder"
mouse_opacity = TRUE
- noscoop = TRUE
-
-/obj/effect/decal/cleanable/dirt/blackpowder/Initialize()
- . = ..()
- reagents.add_reagent("blackpowder", 40) // size 2 explosion when activated
+ no_scoop = TRUE
+ scoop_reagents = list("blackpowder" = 40) // size 2 explosion when activated
/obj/effect/decal/cleanable/flour
name = "flour"
@@ -127,22 +121,15 @@
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
- noclear = TRUE
-
-/obj/effect/decal/cleanable/vomit/Initialize()
- . = ..()
- reagents.add_reagent("vomit", 5)
+ no_clear = TRUE
+ scoop_reagents = list("vomit" = 5)
/obj/effect/decal/cleanable/vomit/green
name = "green vomit"
desc = "It's all gummy. Ew."
icon_state = "gvomit_1"
random_icon_states = list("gvomit_1", "gvomit_2", "gvomit_3", "gvomit_4")
-
-/obj/effect/decal/cleanable/vomit/green/Initialize()
- . = ..()
- reagents.remove_reagent("vomit", 5)
- reagents.add_reagent("green_vomit", 5)
+ scoop_reagents = list("green_vomit" = 5)
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
@@ -189,10 +176,7 @@
icon = 'icons/effects/effects.dmi'
icon_state = "flour"
color = "#D5820B"
-
-/obj/effect/decal/cleanable/fungus/Initialize()
- . = ..()
- reagents.add_reagent("fungus", 10)
+ scoop_reagents = list("fungus" = 10)
/obj/effect/decal/cleanable/confetti //PARTY TIME!
name = "confetti"
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 52ec24df16c..461273bccdb 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,8 +1,6 @@
/obj/effect/decal/cleanable
anchored = TRUE
var/list/random_icon_states = list()
- var/noscoop = FALSE //if it has this, don't let it be scooped up
- var/noclear = FALSE //if it has this, don't delete it when its' scooped up
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
return FALSE
@@ -10,7 +8,6 @@
/obj/effect/decal/cleanable/New()
if(random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
- create_reagents(100)
if(smooth)
queue_smooth(src)
queue_smooth_neighbors(src)
@@ -19,25 +16,4 @@
/obj/effect/decal/cleanable/Destroy()
if(smooth)
queue_smooth_neighbors(src)
- return ..()
-
-/obj/effect/decal/cleanable/attackby(obj/item/W as obj, mob/user as mob,)
- if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
- if(src.reagents && W.reagents && !noscoop)
- if(!src.reagents.total_volume)
- to_chat(user, "There isn't enough [src] to scoop up!")
- return
- if(W.reagents.total_volume >= W.reagents.maximum_volume)
- to_chat(user, "[W] is full!")
- return
- to_chat(user, "You scoop the [src] into [W]!")
- reagents.trans_to(W, reagents.total_volume)
- if(!reagents.total_volume && !noclear) //scooped up all of it
- qdel(src)
- return
-
-/obj/effect/decal/cleanable/ex_act()
- if(reagents)
- for(var/datum/reagent/R in reagents.reagent_list)
- R.on_ex_act()
- ..()
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 52ad55c48a4..64561630d06 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -54,3 +54,16 @@
/obj/effect/decal/straw/edge
icon_state = "strawscatterededge"
+
+/obj/effect/decal/ants
+ name = "space ants"
+ desc = "A bunch of space ants."
+ icon = 'icons/goonstation/effects/effects.dmi'
+ icon_state = "spaceants"
+ scoop_reagents = list("ants" = 20)
+
+/obj/effect/decal/ants/Initialize(mapload)
+ . = ..()
+ var/scale = (rand(2, 10) / 10) + (rand(0, 5) / 100)
+ transform = matrix(transform, scale, scale, MATRIX_SCALE)
+ setDir(pick(NORTH, SOUTH, EAST, WEST))
\ No newline at end of file
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 21b9759df62..07c7137d719 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -13,4 +13,38 @@
return
/obj/effect/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
- return FALSE
\ No newline at end of file
+ return FALSE
+
+/obj/effect/decal
+ var/no_scoop = FALSE //if it has this, don't let it be scooped up
+ var/no_clear = FALSE //if it has this, don't delete it when its' scooped up
+ var/list/scoop_reagents = null
+
+/obj/effect/decal/Initialize(mapload)
+ . = ..()
+ if(scoop_reagents)
+ create_reagents(100)
+ reagents.add_reagent_list(scoop_reagents)
+
+/obj/effect/decal/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks))
+ scoop(I, user)
+
+/obj/effect/decal/proc/scoop(obj/item/I, mob/user)
+ if(reagents && I.reagents && !no_scoop)
+ if(!reagents.total_volume)
+ to_chat(user, "There isn't enough [src] to scoop up!")
+ return
+ if(I.reagents.total_volume >= I.reagents.maximum_volume)
+ to_chat(user, "[I] is full!")
+ return
+ to_chat(user, "You scoop [src] into [I]!")
+ reagents.trans_to(I, reagents.total_volume)
+ if(!reagents.total_volume && !no_clear) //scooped up all of it
+ qdel(src)
+
+/obj/effect/decal/ex_act()
+ if(reagents)
+ for(var/datum/reagent/R in reagents.reagent_list)
+ R.on_ex_act()
+ ..()
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index 52a4a9dcd35..785231a588d 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -11,6 +11,7 @@
possible_transfer_amounts = list(5,10,15,20,25,30,50)
volume = 50
burn_state = FIRE_PROOF
+ antable = FALSE
/obj/item/reagent_containers/food/drinks/New()
..()
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index 0ecff55cba0..e931db813cf 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -13,10 +13,42 @@
var/transfer_efficiency = 1.0
var/instant_application = 0 //if we want to bypass the forcedfeed delay
var/taste = TRUE//whether you can taste eating from this
+ var/antable = TRUE // Will ants come near it?
+ var/ant_location = null
+ var/ant_timer = null
burn_state = FLAMMABLE
container_type = INJECTABLE
-/obj/item/reagent_containers/food/New()
- ..()
+/obj/item/reagent_containers/food/Initialize(mapload)
+ . = ..()
pixel_x = rand(-5, 5) //Randomizes postion
pixel_y = rand(-5, 5)
+ if(antable)
+ ant_location = get_turf(src)
+ ant_timer = addtimer(CALLBACK(src, .proc/check_for_ants), 3000, TIMER_STOPPABLE)
+
+/obj/item/reagent_containers/food/Destroy()
+ ant_location = null
+ if(ant_timer)
+ deltimer(ant_timer)
+ return ..()
+
+/obj/item/reagent_containers/food/proc/check_for_ants()
+ if(!antable)
+ return
+ var/turf/T = get_turf(src)
+ if(isturf(loc) && !locate(/obj/structure/table) in T)
+ if(ant_location == T)
+ if(prob(15))
+ if(!locate(/obj/effect/decal/ants) in T)
+ new /obj/effect/decal/ants(T)
+ antable = FALSE
+ desc += " It appears to be infested with ants. Yuck!"
+ reagents.add_reagent("ants", 1) // Don't eat things with ants in i you weirdo.
+ if(ant_timer)
+ deltimer(ant_timer)
+ else
+ ant_location = T
+ if(ant_timer)
+ deltimer(ant_timer)
+ ant_timer = addtimer(CALLBACK(src, .proc/check_for_ants), 3000, TIMER_STOPPABLE)
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm
index 7ba6ed01667..76be206f35f 100644
--- a/code/modules/reagents/chemistry/reagents/toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/toxins.dm
@@ -1049,6 +1049,11 @@
update_flags |= M.adjustToxLoss(1, FALSE)
return ..() | update_flags
+/datum/reagent/pestkiller/reaction_obj(obj/O, volume)
+ if(istype(O, /obj/effect/decal/ants))
+ O.visible_message("The ants die.")
+ qdel(O)
+
/datum/reagent/pestkiller/reaction_mob(mob/living/M, method=TOUCH, volume)
if(iscarbon(M))
var/mob/living/carbon/C = M
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index cc866f7a2c7..4bd5d25ed3c 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -113,7 +113,7 @@
to_chat(user, "You cannot fill [target] while it is sealed.")
return
- else if(istype(target, /obj/effect/decal/cleanable)) //stops splashing while scooping up fluids
+ else if(istype(target, /obj/effect/decal)) //stops splashing while scooping up fluids
return
else if(reagents.total_volume)
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 54a9867be60..4b66482cf1d 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -11,6 +11,7 @@
volume = 100
consume_sound = null
taste = FALSE
+ antable = FALSE
/obj/item/reagent_containers/food/pill/New()
..()
diff --git a/icons/goonstation/effects/effects.dmi b/icons/goonstation/effects/effects.dmi
new file mode 100644
index 00000000000..8f38e42718e
Binary files /dev/null and b/icons/goonstation/effects/effects.dmi differ