diff --git a/code/game/objects/structures/props/nest.dm b/code/game/objects/structures/props/nest.dm
new file mode 100644
index 00000000000..3b49d304a9b
--- /dev/null
+++ b/code/game/objects/structures/props/nest.dm
@@ -0,0 +1,67 @@
+/obj/structure/prop/nest
+ name = "diyaab den"
+ desc = "A den of some creature."
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "bonfire"
+ density = TRUE
+ anchored = TRUE
+ interaction_message = "You feel like you shouldn't be sticking your nose into a wild animal's den."
+
+ var/disturbance_spawn_chance = 20
+ var/last_spawn
+ var/spawn_delay = 150
+ var/randomize_spawning = FALSE
+ var/creature_types = list(/mob/living/simple_animal/retaliate/diyaab)
+ var/list/den_mobs
+ var/den_faction //The faction of any spawned creatures.
+ var/max_creatures = 3 //Maximum number of living creatures this nest can have at one time.
+
+ var/tally = 0 //The counter referenced against total_creature_max, or just to see how many mobs it has spawned.
+ var/total_creature_max //If set, it can spawn this many creatures, total, ever.
+
+/obj/structure/prop/nest/initialize()
+ ..()
+ den_mobs = list()
+ processing_objects |= src
+ last_spawn = world.time
+ if(randomize_spawning) //Not the biggest shift in spawntime, but it's here.
+ var/delayshift_clamp = spawn_delay / 10
+ var/delayshift = rand(delayshift_clamp, -1 * delayshift_clamp)
+ spawn_delay += delayshift
+
+/obj/structure/prop/nest/Destroy()
+ den_mobs = null
+ processing_objects -= src
+ ..()
+
+/obj/structure/prop/nest/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything.
+ ..()
+ if(user && prob(disturbance_spawn_chance))
+ spawn_creature(get_turf(src))
+
+/obj/structure/prop/nest/process()
+ update_creatures()
+ if(world.time > last_spawn + spawn_delay)
+ spawn_creature(get_turf(src))
+
+/obj/structure/prop/nest/proc/spawn_creature(var/turf/spawnpoint)
+ update_creatures() //Paranoia.
+ if(total_creature_max && tally >= total_creature_max)
+ return
+ if(istype(spawnpoint) && den_mobs.len < max_creatures)
+ last_spawn = world.time
+ var/spawn_choice = pick(creature_types)
+ var/mob/living/L = new spawn_choice
+ if(den_faction)
+ L.faction = den_faction
+ visible_message("\The [L] crawls out of \the [src].")
+ den_mobs += L
+ tally++
+
+/obj/structure/prop/nest/proc/remove_creature(var/mob/target)
+ den_mobs -= target
+
+/obj/structure/prop/nest/proc/update_creatures()
+ for(var/mob/living/L in den_mobs)
+ if(L.stat == 2)
+ remove_creature(L)
diff --git a/code/modules/blob2/blobs/base_blob.dm b/code/modules/blob2/blobs/base_blob.dm
index 19461e68c81..e70587c5a3a 100644
--- a/code/modules/blob2/blobs/base_blob.dm
+++ b/code/modules/blob2/blobs/base_blob.dm
@@ -51,6 +51,15 @@ var/list/blobs = list()
return TRUE
if(istype(mover) && mover.checkpass(PASSBLOB))
return TRUE
+ else if(istype(mover, /mob/living))
+ var/mob/living/L = mover
+ if(L.faction == "blob")
+ return TRUE
+ else if(istype(mover, /obj/item/projectile))
+ var/obj/item/projectile/P = mover
+ if(P.firer && P.firer.faction == "blob")
+ return TRUE
+ return FALSE
else
return FALSE
// return ..()
@@ -248,6 +257,9 @@ var/list/blobs = list()
if(!P)
return
+ if(P.firer && P.firer.faction == "blob")
+ return
+
var/damage = P.get_structure_damage() // So tasers don't hurt the blob.
if(!damage)
return
diff --git a/code/modules/blob2/blobs/core.dm b/code/modules/blob2/blobs/core.dm
index 7e2fe741cfa..fc4cbc79673 100644
--- a/code/modules/blob2/blobs/core.dm
+++ b/code/modules/blob2/blobs/core.dm
@@ -38,6 +38,9 @@ var/list/blob_cores = list()
/obj/structure/blob/core/grey_goo
desired_blob_type = /datum/blob_type/grey_goo
+/obj/structure/blob/core/fabrication_swarm
+ desired_blob_type = /datum/blob_type/fabrication_swarm
+
/obj/structure/blob/core/electromagnetic_web
desired_blob_type = /datum/blob_type/electromagnetic_web
@@ -71,6 +74,9 @@ var/list/blob_cores = list()
/obj/structure/blob/core/radioactive_ooze
desired_blob_type = /datum/blob_type/radioactive_ooze
+/obj/structure/blob/core/volatile_alluvium
+ desired_blob_type = /datum/blob_type/volatile_alluvium
+
/obj/structure/blob/core/classic
desired_blob_type = /datum/blob_type/classic
diff --git a/code/modules/blob2/blobs/factory.dm b/code/modules/blob2/blobs/factory.dm
index 6cd8bfa0f2e..9577f3c14e8 100644
--- a/code/modules/blob2/blobs/factory.dm
+++ b/code/modules/blob2/blobs/factory.dm
@@ -16,8 +16,10 @@
/obj/structure/blob/factory/Destroy()
for(var/mob/living/simple_animal/hostile/blob/spore/spore in spores)
- if(spore.factory == src)
+ if(istype(spore) && spore.factory == src)
spore.factory = null
+ else
+ spore.nest = null
spores = null
return ..()
@@ -32,6 +34,21 @@
var/mob/living/simple_animal/hostile/blob/spore/S = null
if(overmind)
S = new overmind.blob_type.spore_type(src.loc, src)
- S.overmind = overmind
+ S.faction = "blob"
+ if(istype(S))
+ S.overmind = overmind
+ overmind.blob_mobs.Add(S)
+ if(overmind.blob_type.ranged_spores)
+ S.ranged = TRUE
+ S.projectiletype = overmind.blob_type.spore_projectile
+ S.projectilesound = overmind.blob_type.spore_firesound
+ S.shoot_range = overmind.blob_type.spore_range
+ else //Other mobs don't add themselves in New. Ew.
+ S.nest = src
+ spores += S
S.update_icons()
- overmind.blob_mobs.Add(S)
\ No newline at end of file
+
+/obj/structure/blob/factory/sluggish // Capable of producing MORE spores, but quite a bit slower than normal.
+ name = "sluggish factory blob"
+ max_spores = 4
+ spore_cooldown = 16 SECONDS
diff --git a/code/modules/blob2/blobs/resource.dm b/code/modules/blob2/blobs/resource.dm
index f8ff4e48e41..189abfd520d 100644
--- a/code/modules/blob2/blobs/resource.dm
+++ b/code/modules/blob2/blobs/resource.dm
@@ -7,6 +7,7 @@
max_integrity = 40
point_return = 15
var/resource_delay = 0
+ var/resource_cooldown = 4 SECONDS
/obj/structure/blob/resource/New(var/newloc, var/new_overmind)
..(newloc, new_overmind)
@@ -25,6 +26,12 @@
flick("blob_resource_glow", src)
if(overmind)
overmind.add_points(1)
- resource_delay = world.time + 4 SECONDS + (overmind.resource_blobs.len * 2.5) //4 seconds plus a quarter second for each resource blob the overmind has
+ resource_delay = world.time + resource_cooldown + (overmind.resource_blobs.len * 2.5) //4 seconds plus a quarter second for each resource blob the overmind has
else
- resource_delay = world.time + 4 SECONDS
\ No newline at end of file
+ resource_delay = world.time + resource_cooldown
+
+/obj/structure/blob/resource/sluggish // Tankier, but really slow.
+ name = "sluggish resource blob"
+ desc = "A thin spire of occasionally convulsing tendrils."
+ max_integrity = 80
+ resource_cooldown = 8 SECONDS
diff --git a/code/modules/blob2/overmind/overmind.dm b/code/modules/blob2/overmind/overmind.dm
index 9b12c4c873c..8ba73eb1e64 100644
--- a/code/modules/blob2/overmind/overmind.dm
+++ b/code/modules/blob2/overmind/overmind.dm
@@ -94,4 +94,4 @@ var/list/overminds = list()
if(blob_points >= 100)
if(!auto_factory() && !auto_resource())
- auto_node()
\ No newline at end of file
+ auto_node()
diff --git a/code/modules/blob2/overmind/powers.dm b/code/modules/blob2/overmind/powers.dm
index 35a6a9e9c75..360bfbb10b2 100644
--- a/code/modules/blob2/overmind/powers.dm
+++ b/code/modules/blob2/overmind/powers.dm
@@ -45,7 +45,7 @@
create_shield()
/mob/observer/blob/proc/create_shield(turf/T)
- createSpecial(15, /obj/structure/blob/shield, 0, 0, T)
+ createSpecial(15, blob_type.shield_type, 0, 0, T)
/mob/observer/blob/verb/create_resource()
set category = "Blob"
@@ -55,7 +55,7 @@
if(!blob_type.can_build_resources)
return FALSE
- createSpecial(40, /obj/structure/blob/resource, 4, 1)
+ createSpecial(40, blob_type.resource_type, 4, 1)
/mob/observer/blob/verb/auto_resource()
set category = "Blob"
@@ -85,7 +85,7 @@
if(B)
forceMove(B.loc)
- return createSpecial(40, /obj/structure/blob/resource, 4, 1, B.loc)
+ return createSpecial(40, blob_type.resource_type, 4, 1, B.loc)
/mob/observer/blob/verb/create_factory()
@@ -96,7 +96,7 @@
if(!blob_type.can_build_factories)
return FALSE
- createSpecial(60, /obj/structure/blob/factory, 7, 1)
+ createSpecial(60, blob_type.factory_type, 7, 1)
/mob/observer/blob/verb/auto_factory()
set category = "Blob"
@@ -126,7 +126,7 @@
if(B)
forceMove(B.loc)
- return createSpecial(60, /obj/structure/blob/factory, 7, 1, B.loc)
+ return createSpecial(60, blob_type.factory_type, 7, 1, B.loc)
@@ -138,7 +138,7 @@
if(!blob_type.can_build_nodes)
return FALSE
- createSpecial(100, /obj/structure/blob/node, 5, 0)
+ createSpecial(100, blob_type.node_type, 5, 0)
/mob/observer/blob/verb/auto_node()
set category = "Blob"
@@ -166,7 +166,7 @@
if(B)
forceMove(B.loc)
- return createSpecial(100, /obj/structure/blob/node, 5, 0, B.loc)
+ return createSpecial(100, blob_type.node_type, 5, 0, B.loc)
diff --git a/code/modules/blob2/overmind/types.dm b/code/modules/blob2/overmind/types.dm
index 0cc36834894..c8aca03cf67 100644
--- a/code/modules/blob2/overmind/types.dm
+++ b/code/modules/blob2/overmind/types.dm
@@ -33,6 +33,15 @@
var/can_build_nodes = TRUE // Ditto, for nodes.
var/spore_type = /mob/living/simple_animal/hostile/blob/spore
+ var/ranged_spores = FALSE // For proper spores of the type above.
+ var/spore_firesound = 'sound/effects/slime_squish.ogg'
+ var/spore_range = 7 // The range the spore can fire.
+ var/spore_projectile = /obj/item/projectile/energy/blob
+
+ var/factory_type = /obj/structure/blob/factory
+ var/resource_type = /obj/structure/blob/resource
+ var/node_type = /obj/structure/blob/node
+ var/shield_type = /obj/structure/blob/shield
// Called when a blob receives damage. This needs to return the final damage or blobs will be immortal.
/datum/blob_type/proc/on_received_damage(var/obj/structure/blob/B, damage, damage_type)
@@ -82,13 +91,49 @@
slow_spread_with_size = FALSE
ai_aggressiveness = 80
can_build_resources = TRUE
- attack_message = "The tide tries to shallow you"
+ attack_message = "The tide tries to swallow you"
attack_message_living = ", and you feel your skin dissolve"
attack_message_synth = ", and your external plating dissolves"
/datum/blob_type/grey_goo/on_emp(obj/structure/blob/B, severity)
B.adjust_integrity(-(20 / severity))
+// Slow, tanky blobtype which uses not spores, but hivebots, as its soldiers.
+/datum/blob_type/fabrication_swarm
+ name = "iron tide"
+ desc = "A swarm of self replicating construction nanites. Incredibly illegal, but only mildly dangerous."
+ effect_desc = "Slow-spreading, but incredibly resiliant. It has a chance to harden itself against attacks automatically for no resource cost, and uses cheaply-constructed hivebots as soldiers."
+ ai_desc = "defensive"
+ difficulty = BLOB_DIFFICULTY_MEDIUM // Emitters are okay, EMP is great.
+ color = "#666666"
+ complementary_color = "#B7410E"
+ spread_modifier = 0.2
+ can_build_factories = TRUE
+ can_build_resources = TRUE
+ attack_message = "The tide tries to shove you away"
+ attack_message_living = ", and your skin itches"
+ attack_message_synth = ", and your external plating dulls"
+ attack_verb = "shoves"
+ armor_pen = 40
+ damage_lower = 10
+ damage_upper = 25
+ brute_multiplier = 0.25
+ burn_multiplier = 0.6
+ ai_aggressiveness = 50 //Really doesn't like you near it.
+ spore_type = /mob/living/simple_animal/hostile/hivebot/swarm
+
+/datum/blob_type/fabrication_swarm/on_received_damage(var/obj/structure/blob/B, damage, damage_type, mob/living/attacker)
+ if(istype(B, /obj/structure/blob/normal))
+ if(damage > 0)
+ var/reinforce_probability = min(damage, 70)
+ if(prob(reinforce_probability))
+ B.visible_message("The [name] quakes, before rapidly hardening!")
+ new/obj/structure/blob/shield(get_turf(B), B.overmind)
+ qdel(B)
+ return ..()
+
+/datum/blob_type/fabrication_swarm/on_emp(obj/structure/blob/B, severity)
+ B.adjust_integrity(-(30 / severity))
// A blob meant to be fought like a fire.
/datum/blob_type/blazing_oil
@@ -218,17 +263,23 @@
/datum/blob_type/fulminant_organism/on_expand(var/obj/structure/blob/B, var/obj/structure/blob/new_B, var/turf/T, var/mob/observer/blob/O)
if(prob(10)) // 10% chance to make a weak spore when expanding.
var/mob/living/simple_animal/hostile/blob/S = new spore_type(T)
- S.overmind = O
+ if(istype(S))
+ S.overmind = O
+ O.blob_mobs.Add(S)
+ else
+ S.faction = "blob"
S.update_icons()
- O.blob_mobs.Add(S)
/datum/blob_type/fulminant_organism/on_death(obj/structure/blob/B)
if(prob(33)) // 33% chance to make a spore when dying.
var/mob/living/simple_animal/hostile/blob/S = new spore_type(get_turf(B))
- B.visible_message("A spore floats free from the [name]!")
- S.overmind = B.overmind
+ B.visible_message("\The [S] floats free from the [name]!")
+ if(istype(S))
+ S.overmind = B.overmind
+ B.overmind.blob_mobs.Add(S)
+ else
+ S.faction = "blob"
S.update_icons()
- B.overmind.blob_mobs.Add(S)
// Auto-retaliates against melee attacks. Weak to projectiles.
@@ -542,4 +593,52 @@
attack_verb = "splashes"
/datum/blob_type/radioactive_ooze/on_pulse(var/obj/structure/blob/B)
- radiation_repository.radiate(B, 200)
\ No newline at end of file
+ radiation_repository.radiate(B, 200)
+
+/datum/blob_type/volatile_alluvium
+ name = "volatile alluvium"
+ desc = "A churning, earthy mass that moves in waves."
+ ai_desc = "earthen"
+ effect_desc = "Moves slowly, producing weak ranged spores to defend itself, and inflicts brute attacks. Attempts to disarm nearby attackers. Weak to water."
+ difficulty = BLOB_DIFFICULTY_HARD //Slow-starting, but can be overwhelming if left alone.
+ color = "#6B481E"
+ complementary_color = "#7F471F"
+ damage_lower = 10
+ damage_upper = 20
+ armor_pen = 40
+ brute_multiplier = 0.7
+ burn_multiplier = 0.5
+ spread_modifier = 0.5
+ ai_aggressiveness = 50
+ attack_message = "The alluvium crashes against you"
+ attack_verb = "crashes against"
+ can_build_factories = TRUE
+ can_build_resources = TRUE
+ spore_type = /mob/living/simple_animal/hostile/blob/spore/weak
+ ranged_spores = TRUE
+ spore_range = 3
+ spore_projectile = /obj/item/projectile/energy/blob/splattering
+ factory_type = /obj/structure/blob/factory/sluggish
+ resource_type = /obj/structure/blob/resource/sluggish
+
+/datum/blob_type/volatile_alluvium/on_received_damage(var/obj/structure/blob/B, damage, damage_type, mob/living/attacker)
+ if(damage > 0 && attacker && get_dist(B, attacker) <= 2 && prob(min(damage, 70)) && istype(attacker, /mob/living/carbon/human)) // Melee weapons of any type carried by a human will have a high chance of being stolen.
+ var/mob/living/carbon/human/H = attacker
+ var/obj/item/I = H.get_active_hand()
+ H.drop_item()
+ if(I)
+ if((I.sharp || I.edge) && !istype(I, /obj/item/weapon/gun))
+ I.forceMove(get_turf(B)) // Disarmed entirely.
+ B.visible_message("The [name] heaves, \the [attacker]'s weapon becoming stuck in the churning mass!")
+ else
+ I.throw_at(B, 2, 4) // Just yoinked.
+ B.visible_message("The [name] heaves, pulling \the [attacker]'s weapon from their hands!")
+ B.blob_attack_animation(attacker, B.overmind)
+ return ..()
+
+/datum/blob_type/volatile_alluvium/on_water(obj/structure/blob/B, amount)
+ spawn(1)
+ var/damage = amount * 2
+ B.adjust_integrity(-(damage))
+ if(B && prob(damage))
+ B.visible_message("The [name] begins to crumble!")
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index d6c2bc0405f..8535718130a 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -1,3 +1,11 @@
/mob/living/death()
clear_fullscreens()
- . = ..()
\ No newline at end of file
+ if(nest) //Ew.
+ if(istype(nest, /obj/structure/prop/nest))
+ var/obj/structure/prop/nest/N = nest
+ N.remove_creature(src)
+ if(istype(nest, /obj/structure/blob/factory))
+ var/obj/structure/blob/factory/F = nest
+ F.spores -= src
+ nest = null
+ . = ..()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 612765a776a..7cbf94e1b7e 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -19,6 +19,14 @@
/mob/living/Destroy()
dsoverlay.loc = null //I'll take my coat with me
dsoverlay = null
+ if(nest) //Ew.
+ if(istype(nest, /obj/structure/prop/nest))
+ var/obj/structure/prop/nest/N = nest
+ N.remove_creature(src)
+ if(istype(nest, /obj/structure/blob/factory))
+ var/obj/structure/blob/factory/F = nest
+ F.spores -= src
+ nest = null
if(buckled)
buckled.unbuckle_mob(src, TRUE)
return ..()
@@ -177,6 +185,11 @@ default behaviour is:
return
return
+/mob/living/CanPass(atom/movable/mover, turf/target)
+ if(istype(mover, /obj/structure/blob) && faction == "blob") //Blobs should ignore things on their faction.
+ return TRUE
+ return ..()
+
/mob/living/verb/succumb()
set hidden = 1
if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable
@@ -942,40 +955,41 @@ default behaviour is:
else
to_chat(src, "You feel nauseous...")
- if(!skip_wait)
- sleep(150) //15 seconds until second warning
- to_chat(src, "You feel like you are about to throw up!")
- sleep(100) //and you have 10 more for mad dash to the bucket
+ spawn()
+ if(!skip_wait)
+ sleep(150) //15 seconds until second warning
+ to_chat(src, "You feel like you are about to throw up!")
+ sleep(100) //and you have 10 more for mad dash to the bucket
- //Damaged livers cause you to vomit blood.
- if(!blood_vomit)
- if(ishuman(src))
- var/mob/living/carbon/human/H = src
- if(!H.isSynthetic())
- var/obj/item/organ/internal/liver/L = H.internal_organs_by_name["liver"]
- if(L.is_broken())
- blood_vomit = 1
+ //Damaged livers cause you to vomit blood.
+ if(!blood_vomit)
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ if(!H.isSynthetic())
+ var/obj/item/organ/internal/liver/L = H.internal_organs_by_name["liver"]
+ if(L.is_broken())
+ blood_vomit = 1
- Stun(5)
- src.visible_message("[src] throws up!","You throw up!")
- playsound(loc, 'sound/effects/splat.ogg', 50, 1)
+ Stun(5)
+ src.visible_message("[src] throws up!","You throw up!")
+ playsound(loc, 'sound/effects/splat.ogg', 50, 1)
+
+ var/turf/simulated/T = get_turf(src) //TODO: Make add_blood_floor remove blood from human mobs
+ if(istype(T))
+ if(blood_vomit)
+ T.add_blood_floor(src)
+ else
+ T.add_vomit_floor(src, 1)
- var/turf/simulated/T = get_turf(src) //TODO: Make add_blood_floor remove blood from human mobs
- if(istype(T))
if(blood_vomit)
- T.add_blood_floor(src)
+ if(getBruteLoss() < 50)
+ adjustBruteLoss(3)
else
- T.add_vomit_floor(src, 1)
+ nutrition -= 40
+ adjustToxLoss(-3)
- if(blood_vomit)
- if(getBruteLoss() < 50)
- adjustBruteLoss(3)
- else
- nutrition -= 40
- adjustToxLoss(-3)
-
- sleep(350)
- lastpuke = 0
+ spawn(350)
+ lastpuke = 0
/mob/living/update_canmove()
if(!resting && cannot_stand() && can_stand_overridden())
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 581e33452c0..08d35e5de29 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -163,7 +163,7 @@
..()
/mob/living/blob_act(var/obj/structure/blob/B)
- if(stat == DEAD)
+ if(stat == DEAD || faction == "blob")
return
var/damage = rand(30, 40)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 1ee86da6ef8..c856e8d8309 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -56,6 +56,8 @@
var/see_invisible_default = SEE_INVISIBLE_LIVING
+ var/nest //Not specific, because a Nest may be the prop nest, or blob factory in this case.
+
var/list/hud_list //Holder for health hud, status hud, wanted hud, etc (not like inventory slots)
var/has_huds = FALSE //Whether or not we should bother initializing the above list
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index ac1ce46f42c..ddedd18b182 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -1361,6 +1361,8 @@
// if (!istype(target, /turf))
// qdel(A)
// return
+
+ A.firer = src
A.launch(target)
return
diff --git a/code/modules/projectiles/projectile/blob.dm b/code/modules/projectiles/projectile/blob.dm
new file mode 100644
index 00000000000..926c78a0a03
--- /dev/null
+++ b/code/modules/projectiles/projectile/blob.dm
@@ -0,0 +1,63 @@
+/obj/item/projectile/energy/blob //Not super strong.
+ name = "spore"
+ icon_state = "declone"
+ damage = 3
+ armor_penetration = 40
+ damage_type = BRUTE
+ check_armour = "melee"
+ pass_flags = PASSTABLE | PASSBLOB
+ fire_sound = 'sound/effects/slime_squish.ogg'
+ var/splatter = FALSE // Will this make a cloud of reagents?
+ var/splatter_volume = 5 // The volume of its chemical container, for said cloud of reagents.
+ var/list/my_chems = list("mold")
+
+/obj/item/projectile/energy/blob/splattering
+ splatter = TRUE
+
+/obj/item/projectile/energy/blob/New()
+ if(splatter)
+ create_reagents(splatter_volume)
+ ready_chemicals()
+ ..()
+
+/obj/item/projectile/energy/blob/Destroy()
+ qdel(reagents)
+ reagents = null
+ ..()
+
+/obj/item/projectile/energy/blob/on_impact(var/atom/A)
+ var/turf/location = get_turf(src)
+ var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem
+ S.attach(location)
+ S.set_up(reagents, splatter_volume, 0, location)
+ playsound(location, 'sound/effects/slime_squish.ogg', 30, 1, -3)
+ spawn(0)
+ S.start()
+ ..()
+
+/obj/item/projectile/energy/blob/proc/ready_chemicals()
+ if(reagents)
+ var/reagent_vol = (round((splatter_volume / my_chems.len) * 100) / 100) //Cut it at the hundreds place, please.
+ for(var/reagent in my_chems)
+ reagents.add_reagent(reagent, reagent_vol)
+
+/obj/item/projectile/energy/blob/toxic
+ damage_type = TOX
+ check_armour = "bio"
+ my_chems = list("amatoxin")
+
+/obj/item/projectile/energy/blob/toxic/splattering
+ splatter = TRUE
+
+/obj/item/projectile/energy/blob/acid
+ damage_type = BURN
+ check_armour = "bio"
+ my_chems = list("sacid", "mold")
+
+/obj/item/projectile/energy/blob/acid/splattering
+ splatter = TRUE
+
+/obj/item/projectile/energy/blob/combustible
+ splatter = TRUE
+ flammability = 0.25
+ my_chems = list("fuel", "mold")
diff --git a/polaris.dme b/polaris.dme
index 5962661c843..f1ab4919b8e 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -1134,6 +1134,7 @@
#include "code\game\objects\structures\ghost_pods\silicon.dm"
#include "code\game\objects\structures\props\alien_props.dm"
#include "code\game\objects\structures\props\beam_prism.dm"
+#include "code\game\objects\structures\props\nest.dm"
#include "code\game\objects\structures\props\projectile_lock.dm"
#include "code\game\objects\structures\props\prop.dm"
#include "code\game\objects\structures\props\puzzledoor.dm"
@@ -2179,6 +2180,7 @@
#include "code\modules\projectiles\projectile\animate.dm"
#include "code\modules\projectiles\projectile\arc.dm"
#include "code\modules\projectiles\projectile\beams.dm"
+#include "code\modules\projectiles\projectile\blob.dm"
#include "code\modules\projectiles\projectile\bullets.dm"
#include "code\modules\projectiles\projectile\change.dm"
#include "code\modules\projectiles\projectile\energy.dm"