diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index b849e272e7..7a3f872666 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -72,3 +72,8 @@
#define CAT_STRUCTURE "Structures"
#define MARTIALART_HUNTER "hunter-fu"
+
+//Blob
+/// blob gets a free reroll every X time
+#define BLOB_REROLL_TIME 2400
+#define BLOB_REFLECTOR_COST 15
\ No newline at end of file
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index ffad931cd8..04d4c2888a 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -29,7 +29,6 @@ GLOBAL_LIST_EMPTY(available_ai_shells)
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list(),list())) // One for each AI_* status define
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
GLOBAL_LIST_EMPTY(bots_list)
-GLOBAL_LIST_EMPTY(living_cameras)
GLOBAL_LIST_EMPTY(aiEyes)
GLOBAL_LIST_EMPTY(language_datum_instances)
diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm
index 8257b744d6..b9118da5f1 100644
--- a/code/_onclick/hud/blob_overmind.dm
+++ b/code/_onclick/hud/blob_overmind.dm
@@ -48,7 +48,7 @@
if(isovermind(usr))
var/mob/camera/blob/B = usr
if(!B.placed)
- B.place_blob_core(B.base_point_rate, 0)
+ B.place_blob_core(0)
B.transport_core()
/obj/screen/blob/Blobbernaut
@@ -91,26 +91,26 @@
var/mob/camera/blob/B = usr
B.create_factory()
-/obj/screen/blob/ReadaptChemical
+/obj/screen/blob/ReadaptStrain
icon_state = "ui_chemswap"
- name = "Readapt Chemical (40)"
- desc = "Randomly rerolls your chemical for 40 resources."
+ name = "Readapt Strain (40)"
+ desc = "Allows you to choose a new strain from 4 random choices for 40 resources."
-/obj/screen/blob/ReadaptChemical/MouseEntered(location,control,params)
+/obj/screen/blob/ReadaptStrain/MouseEntered(location,control,params)
if(hud && hud.mymob && isovermind(hud.mymob))
var/mob/camera/blob/B = hud.mymob
- if(B.free_chem_rerolls)
- name = "Readapt Chemical (FREE)"
- desc = "Randomly rerolls your chemical for free."
+ if(B.free_strain_rerolls)
+ name = "Readapt Strain (FREE)"
+ desc = "Randomly rerolls your strain for free."
else
name = initial(name)
desc = initial(desc)
..()
-/obj/screen/blob/ReadaptChemical/Click()
+/obj/screen/blob/ReadaptStrain/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
- B.chemical_reroll()
+ B.strain_reroll()
/obj/screen/blob/RelocateCore
icon_state = "ui_swap"
@@ -175,7 +175,7 @@
using.hud = src
static_inventory += using
- using = new /obj/screen/blob/ReadaptChemical()
+ using = new /obj/screen/blob/ReadaptStrain()
using.screen_loc = ui_storage1
using.hud = src
static_inventory += using
diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm
index 56cdf2fa03..8caf2a4623 100644
--- a/code/controllers/subsystem/mobs.dm
+++ b/code/controllers/subsystem/mobs.dm
@@ -26,18 +26,16 @@ SUBSYSTEM_DEF(mobs)
var/seconds = wait * 0.1
if (!resumed)
src.currentrun = GLOB.mob_living_list.Copy()
- if (GLOB.living_cameras.len)
- src.currentrun += GLOB.living_cameras
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
var/times_fired = src.times_fired
while(currentrun.len)
- var/mob/M = currentrun[currentrun.len]
+ var/mob/living/L = currentrun[currentrun.len]
currentrun.len--
- if(M)
- M.Life(seconds, times_fired)
+ if(L)
+ L.Life(seconds, times_fired)
else
- GLOB.mob_living_list.Remove(M)
+ GLOB.mob_living_list.Remove(L)
if (MC_TICK_CHECK)
return
diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
index 261677a74b..b720d3590e 100644
--- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
@@ -20,7 +20,7 @@
/mob/living/simple_animal/hostile/blob/update_icons()
if(overmind)
- add_atom_colour(overmind.blob_reagent_datum.color, FIXED_COLOUR_PRIORITY)
+ add_atom_colour(overmind.blobstrain.color, FIXED_COLOUR_PRIORITY)
else
remove_atom_colour(FIXED_COLOUR_PRIORITY)
@@ -34,7 +34,7 @@
for(var/i in 1 to 2)
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed
if(overmind)
- H.color = overmind.blob_reagent_datum.complementary_color
+ H.color = overmind.blobstrain.complementary_color
else
H.color = "#000000"
adjustHealth(-maxHealth*0.0125)
@@ -142,8 +142,10 @@
// Create the reagents to put into the air
create_reagents(10)
- if(overmind && overmind.blob_reagent_datum)
- reagents.add_reagent(overmind.blob_reagent_datum.type, 10)
+
+
+ if(overmind && overmind.blobstrain)
+ overmind.blobstrain.on_sporedeath(src)
else
reagents.add_reagent(/datum/reagent/toxin/spore, 10)
@@ -167,14 +169,14 @@
/mob/living/simple_animal/hostile/blob/blobspore/update_icons()
if(overmind)
- add_atom_colour(overmind.blob_reagent_datum.complementary_color, FIXED_COLOUR_PRIORITY)
+ add_atom_colour(overmind.blobstrain.complementary_color, FIXED_COLOUR_PRIORITY)
else
remove_atom_colour(FIXED_COLOUR_PRIORITY)
if(is_zombie)
copy_overlays(oldguy, TRUE)
var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/blob.dmi', "blob_head")
if(overmind)
- blob_head_overlay.color = overmind.blob_reagent_datum.complementary_color
+ blob_head_overlay.color = overmind.blobstrain.complementary_color
color = initial(color)//looks better.
add_overlay(blob_head_overlay)
@@ -243,14 +245,14 @@
adjustHealth(-maxHealth*0.1)
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed
if(overmind)
- H.color = overmind.blob_reagent_datum.complementary_color
+ H.color = overmind.blobstrain.complementary_color
else
H.color = "#000000"
if(locate(/obj/structure/blob/node) in blobs_in_area)
adjustHealth(-maxHealth*0.05)
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src))
if(overmind)
- H.color = overmind.blob_reagent_datum.complementary_color
+ H.color = overmind.blobstrain.complementary_color
else
H.color = "#000000"
if(damagesources)
@@ -259,7 +261,7 @@
var/image/I = new('icons/mob/blob.dmi', src, "nautdamage", MOB_LAYER+0.01)
I.appearance_flags = RESET_COLOR
if(overmind)
- I.color = overmind.blob_reagent_datum.complementary_color
+ I.color = overmind.blobstrain.complementary_color
flick_overlay_view(I, src, 8)
/mob/living/simple_animal/hostile/blob/blobbernaut/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
@@ -274,16 +276,14 @@
/mob/living/simple_animal/hostile/blob/blobbernaut/AttackingTarget()
. = ..()
if(. && isliving(target) && overmind)
- var/mob/living/L = target
- var/mob_protection = L.get_permeability_protection()
- overmind.blob_reagent_datum.reaction_mob(L, VAPOR, 20, 0, mob_protection, overmind)//this will do between 10 and 20 damage(reduced by mob protection), depending on chemical, plus 4 from base brute damage.
+ overmind.blobstrain.blobbernaut_attack(target)
/mob/living/simple_animal/hostile/blob/blobbernaut/update_icons()
..()
if(overmind) //if we have an overmind, we're doing chemical reactions instead of pure damage
melee_damage_lower = 4
melee_damage_upper = 4
- attacktext = overmind.blob_reagent_datum.blobbernaut_message
+ attacktext = overmind.blobstrain.blobbernaut_message
else
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
diff --git a/code/modules/antagonists/blob/blob/blobs/core.dm b/code/modules/antagonists/blob/blob/blobs/core.dm
index 58f79e1c73..38484c70b0 100644
--- a/code/modules/antagonists/blob/blob/blobs/core.dm
+++ b/code/modules/antagonists/blob/blob/blobs/core.dm
@@ -8,12 +8,8 @@
explosion_block = 6
point_return = -1
health_regen = 0 //we regen in Life() instead of when pulsed
- var/core_regen = 2
- var/resource_delay = 0
- var/point_rate = 2
-
-/obj/structure/blob/core/Initialize(mapload, client/new_overmind = null, new_rate = 2, placed = 0)
+/obj/structure/blob/core/Initialize(mapload, client/new_overmind = null, placed = 0)
GLOB.blob_cores += src
START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
@@ -22,7 +18,6 @@
return INITIALIZE_HINT_QDEL
if(overmind)
update_icon()
- point_rate = new_rate
addtimer(CALLBACK(src, .proc/generate_announcement), 1800)
. = ..()
@@ -37,7 +32,7 @@
color = null
var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob")
if(overmind)
- blob_overlay.color = overmind.blob_reagent_datum.color
+ blob_overlay.color = overmind.blobstrain.color
add_overlay(blob_overlay)
add_overlay(mutable_appearance('icons/mob/blob.dmi', "blob_core_overlay"))
@@ -60,17 +55,13 @@
if(overmind) //we should have an overmind, but...
overmind.update_health_hud()
-/obj/structure/blob/core/Life()
+/obj/structure/blob/core/process()
if(QDELETED(src))
return
if(!overmind)
qdel(src)
- else
- if(resource_delay <= world.time)
- resource_delay = world.time + 10 // 1 second
- overmind.add_points(point_rate)
- obj_integrity = min(max_integrity, obj_integrity+core_regen)
if(overmind)
+ overmind.blobstrain.core_process()
overmind.update_health_hud()
Pulse_Area(overmind, 12, 4, 3)
for(var/obj/structure/blob/normal/B in range(1, src))
diff --git a/code/modules/antagonists/blob/blob/blobs/node.dm b/code/modules/antagonists/blob/blob/blobs/node.dm
index 23f37bca29..14fbc741c0 100644
--- a/code/modules/antagonists/blob/blob/blobs/node.dm
+++ b/code/modules/antagonists/blob/blob/blobs/node.dm
@@ -22,7 +22,7 @@
color = null
var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob")
if(overmind)
- blob_overlay.color = overmind.blob_reagent_datum.color
+ blob_overlay.color = overmind.blobstrain.color
add_overlay(blob_overlay)
add_overlay(mutable_appearance('icons/mob/blob.dmi', "blob_node_overlay"))
@@ -31,6 +31,6 @@
STOP_PROCESSING(SSobj, src)
return ..()
-/obj/structure/blob/node/Life()
+/obj/structure/blob/node/process()
if(overmind)
Pulse_Area(overmind, 10, 3, 2)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blob/blobstrains/_blobstrain.dm
new file mode 100644
index 0000000000..8b6f4bd687
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/_blobstrain.dm
@@ -0,0 +1,74 @@
+GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/blobstrain/reagent, /datum/blobstrain/multiplex))
+
+/datum/blobstrain
+ var/name
+ var/description
+ var/color = "#000000"
+ var/complementary_color = "#000000" //a color that's complementary to the normal blob color
+ var/shortdesc = null //just damage and on_mob effects, doesn't include special, blob-tile only effects
+ var/effectdesc = null //any long, blob-tile specific effects
+ var/analyzerdescdamage = "Unknown. Report this bug to a coder, or just adminhelp."
+ var/analyzerdesceffect = "N/A"
+ var/blobbernaut_message = "slams" //blobbernaut attack verb
+ var/message = "The blob strikes you" //message sent to any mob hit by the blob
+ var/message_living = null //extension to first mob sent to only living mobs i.e. silicons have no skin to be burnt
+ var/core_regen = 2
+ var/resource_delay = 0
+ var/point_rate = 2
+ var/mob/camera/blob/overmind
+
+/datum/blobstrain/New(mob/camera/blob/new_overmind)
+ if (!istype(new_overmind))
+ stack_trace("blobstrain created without overmind")
+ overmind = new_overmind
+
+/datum/blobstrain/proc/on_gain()
+ overmind.color = complementary_color
+ for(var/BL in GLOB.blobs)
+ var/obj/structure/blob/B = BL
+ B.update_icon()
+ for(var/BLO in overmind.blob_mobs)
+ var/mob/living/simple_animal/hostile/blob/BM = BLO
+ BM.update_icons() //If it's getting a new strain, tell it what it does!
+ to_chat(BM, "Your overmind's blob strain is now: [name]!")
+ to_chat(BM, "The [name] strain [shortdesc ? "[shortdesc]" : "[description]"]")
+
+/datum/blobstrain/proc/on_lose()
+
+/datum/blobstrain/proc/on_sporedeath(mob/living/spore)
+
+/datum/blobstrain/proc/send_message(mob/living/M)
+ var/totalmessage = message
+ if(message_living && !issilicon(M))
+ totalmessage += message_living
+ totalmessage += "!"
+ to_chat(M, "[totalmessage]")
+
+/datum/blobstrain/proc/core_process()
+ if(resource_delay <= world.time)
+ resource_delay = world.time + 10 // 1 second
+ overmind.add_points(point_rate)
+ overmind.blob_core.obj_integrity = min(overmind.blob_core.max_integrity, overmind.blob_core.obj_integrity+core_regen)
+
+/datum/blobstrain/proc/attack_living(var/mob/living/L) // When the blob attacks people
+ send_message(L)
+
+/datum/blobstrain/proc/blobbernaut_attack(mob/living/L) // When this blob's blobbernaut attacks people
+
+/datum/blobstrain/proc/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag, coefficient = 1) //when the blob takes damage, do this
+ return coefficient*damage
+
+/datum/blobstrain/proc/death_reaction(obj/structure/blob/B, damage_flag, coefficient = 1) //when a blob dies, do this
+ return
+
+/datum/blobstrain/proc/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this
+ return
+
+/datum/blobstrain/proc/tesla_reaction(obj/structure/blob/B, power, coefficient = 1) //when the blob is hit by a tesla bolt, do this
+ return 1 //return 0 to ignore damage
+
+/datum/blobstrain/proc/extinguish_reaction(obj/structure/blob/B, coefficient = 1) //when the blob is hit with water, do this
+ return
+
+/datum/blobstrain/proc/emp_reaction(obj/structure/blob/B, severity, coefficient = 1) //when the blob is hit with an emp, do this
+ return
diff --git a/code/modules/antagonists/blob/blob/blobstrains/_reagent.dm b/code/modules/antagonists/blob/blob/blobstrains/_reagent.dm
new file mode 100644
index 0000000000..f47c3b3378
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/_reagent.dm
@@ -0,0 +1,33 @@
+/datum/blobstrain/reagent // Blobs that mess with reagents, all "legacy" ones
+ var/datum/reagent/reagent
+
+/datum/blobstrain/reagent/New(mob/camera/blob/new_overmind)
+ . = ..()
+ reagent = new reagent()
+
+
+/datum/blobstrain/reagent/attack_living(var/mob/living/L)
+ var/mob_protection = L.get_permeability_protection()
+ reagent.reaction_mob(L, VAPOR, 25, 1, mob_protection, overmind)
+ send_message(L)
+
+/datum/blobstrain/reagent/blobbernaut_attack(mob/living/L)
+ var/mob_protection = L.get_permeability_protection()
+ reagent.reaction_mob(L, VAPOR, 20, 0, mob_protection, overmind)//this will do between 10 and 20 damage(reduced by mob protection), depending on chemical, plus 4 from base brute damage.
+
+/datum/blobstrain/reagent/on_sporedeath(mob/living/spore)
+ spore.reagents.add_reagent(reagent.type, 10)
+
+// These can only be applied by blobs. They are what (reagent) blobs are made out of.
+/datum/reagent/blob
+ name = "Unknown"
+ description = "shouldn't exist and you should adminhelp immediately."
+ color = "#FFFFFF"
+ taste_description = "bad code and slime"
+ can_synth = FALSE
+
+
+/datum/reagent/blob/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ if(M.stat == DEAD || istype(M, /mob/living/simple_animal/hostile/blob))
+ return 0 //the dead, and blob mobs, don't cause reactions
+ return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume.
diff --git a/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm b/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm
new file mode 100644
index 0000000000..97b974e28f
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm
@@ -0,0 +1,41 @@
+
+//sets you on fire, does burn damage, explodes into flame when burnt, weak to water
+/datum/blobstrain/reagent/blazing_oil
+ name = "Blazing Oil"
+ description = "will do medium burn damage and set targets on fire."
+ effectdesc = "will also release bursts of flame when burnt, but takes damage from water."
+ analyzerdescdamage = "Does medium burn damage and sets targets on fire."
+ analyzerdesceffect = "Releases fire when burnt, but takes damage from water and other extinguishing liquids."
+ color = "#B68D00"
+ complementary_color = "#BE5532"
+ blobbernaut_message = "splashes"
+ message = "The blob splashes you with burning oil"
+ message_living = ", and you feel your skin char and melt"
+ reagent = /datum/reagent/blob/blazing_oil
+
+/datum/blobstrain/reagent/blazing_oil/extinguish_reaction(obj/structure/blob/B)
+ B.take_damage(1.5, BURN, "energy")
+
+/datum/blobstrain/reagent/blazing_oil/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if(damage_type == BURN && damage_flag != "energy")
+ for(var/turf/open/T in range(1, B))
+ var/obj/structure/blob/C = locate() in T
+ if(!(C && C.overmind && C.overmind.blobstrain.type == B.overmind.blobstrain.type) && prob(80))
+ new /obj/effect/hotspot(T)
+ if(damage_flag == "fire")
+ return 0
+ return ..()
+
+/datum/reagent/blob/blazing_oil
+ name = "Blazing Oil"
+ taste_description = "burning oil"
+ color = "#B68D00"
+
+/datum/reagent/blob/blazing_oil/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.adjust_fire_stacks(round(reac_volume/10))
+ M.IgniteMob()
+ if(M)
+ M.apply_damage(0.8*reac_volume, BURN)
+ if(iscarbon(M))
+ M.emote("scream")
diff --git a/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm b/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm
new file mode 100644
index 0000000000..9b8edcd0e5
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm
@@ -0,0 +1,32 @@
+//does brute, burn, and toxin damage, and cools targets down
+/datum/blobstrain/reagent/cryogenic_poison
+ name = "Cryogenic Poison"
+ description = "will inject targets with a freezing poison that does high damage over time."
+ analyzerdescdamage = "Injects targets with a freezing poison that will gradually solidify the target's internal organs."
+ color = "#8BA6E9"
+ complementary_color = "#7D6EB4"
+ blobbernaut_message = "injects"
+ message = "The blob stabs you"
+ message_living = ", and you feel like your insides are solidifying"
+ reagent = /datum/reagent/blob/cryogenic_poison
+
+/datum/reagent/blob/cryogenic_poison
+ name = "Cryogenic Poison"
+ description = "will inject targets with a freezing poison that does high damage over time."
+ color = "#8BA6E9"
+ taste_description = "brain freeze"
+
+/datum/reagent/blob/cryogenic_poison/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ if(M.reagents)
+ M.reagents.add_reagent("frostoil", 0.3*reac_volume)
+ M.reagents.add_reagent("ice", 0.3*reac_volume)
+ M.reagents.add_reagent("cryogenic_poison", 0.3*reac_volume)
+ M.apply_damage(0.2*reac_volume, BRUTE)
+
+/datum/reagent/blob/cryogenic_poison/on_mob_life(mob/living/carbon/M)
+ M.adjustBruteLoss(0.3*REAGENTS_EFFECT_MULTIPLIER, 0)
+ M.adjustFireLoss(0.3*REAGENTS_EFFECT_MULTIPLIER, 0)
+ M.adjustToxLoss(0.3*REAGENTS_EFFECT_MULTIPLIER, 0)
+ . = 1
+ ..()
diff --git a/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm b/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm
new file mode 100644
index 0000000000..0e665603c9
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm
@@ -0,0 +1,33 @@
+//does burn damage and EMPs, slightly fragile
+/datum/blobstrain/reagent/electromagnetic_web
+ name = "Electromagnetic Web"
+ color = "#83ECEC"
+ complementary_color = "#EC8383"
+ reagent = /datum/reagent/blob/electromagnetic_web
+
+/datum/blobstrain/reagent/electromagnetic_web/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if(damage_type == BRUTE) //take full brute
+ switch(B.brute_resist)
+ if(0.5)
+ return damage * 2
+ if(0.25)
+ return damage * 4
+ if(0.1)
+ return damage * 10
+ return damage * 1.25 //a laser will do 25 damage, which will kill any normal blob
+
+/datum/blobstrain/reagent/electromagnetic_web/death_reaction(obj/structure/blob/B, damage_flag)
+ if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser")
+ empulse(B.loc, 1, 3) //less than screen range, so you can stand out of range to avoid it
+
+/datum/reagent/blob/electromagnetic_web
+ name = "Electromagnetic Web"
+ taste_description = "pop rocks"
+ color = "#83ECEC"
+
+/datum/reagent/blob/electromagnetic_web/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ if(prob(reac_volume*2))
+ M.emp_act(EMP_LIGHT)
+ if(M)
+ M.apply_damage(reac_volume, BURN)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/energized_jelly.dm b/code/modules/antagonists/blob/blob/blobstrains/energized_jelly.dm
new file mode 100644
index 0000000000..66ce3c303d
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/energized_jelly.dm
@@ -0,0 +1,34 @@
+//does tons of oxygen damage and a little stamina, immune to tesla bolts, weak to EMP
+/datum/blobstrain/reagent/energized_jelly
+ name = "Energized Jelly"
+ description = "will cause low stamina and high oxygen damage, and cause targets to be unable to breathe."
+ effectdesc = "will also conduct electricity, but takes damage from EMPs."
+ analyzerdescdamage = "Does low stamina damage, high oxygen damage, and prevents targets from breathing."
+ analyzerdesceffect = "Is immune to electricity and will easily conduct it, but is weak to EMPs."
+ color = "#EFD65A"
+ complementary_color = "#00E5B1"
+ reagent = /datum/reagent/blob/energized_jelly
+
+/datum/blobstrain/reagent/energized_jelly/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && B.obj_integrity - damage <= 0 && prob(10))
+ do_sparks(rand(2, 4), FALSE, B)
+ return ..()
+
+/datum/blobstrain/reagent/energized_jelly/tesla_reaction(obj/structure/blob/B, power)
+ return 0
+
+/datum/blobstrain/reagent/energized_jelly/emp_reaction(obj/structure/blob/B, severity)
+ var/damage = rand(30, 50) - severity * rand(10, 15)
+ B.take_damage(damage, BURN, "energy")
+
+/datum/reagent/blob/energized_jelly
+ name = "Energized Jelly"
+ taste_description = "gelatin"
+ color = "#EFD65A"
+
+/datum/reagent/blob/energized_jelly/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.losebreath += round(0.2*reac_volume)
+ M.adjustStaminaLoss(0.4*reac_volume)
+ if(M)
+ M.apply_damage(0.6*reac_volume, OXY)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm
new file mode 100644
index 0000000000..f8fd2e2f0d
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm
@@ -0,0 +1,40 @@
+//does aoe brute damage when hitting targets, is immune to explosions
+/datum/blobstrain/reagent/explosive_lattice
+ name = "Explosive Lattice"
+ description = "will do brute damage in an area around targets."
+ effectdesc = "will also resist explosions, but takes increased damage from fire and other energy sources."
+ analyzerdescdamage = "Does medium brute damage and causes damage to everyone near its targets."
+ analyzerdesceffect = "Is highly resistant to explosions, but takes increased damage from fire and other energy sources."
+ color = "#8B2500"
+ complementary_color = "#00668B"
+ blobbernaut_message = "blasts"
+ message = "The blob blasts you"
+ reagent = /datum/reagent/blob/explosive_lattice
+
+/datum/blobstrain/reagent/explosive_lattice/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if(damage_flag == "bomb")
+ return 0
+ else if(damage_flag != "melee" && damage_flag != "bullet" && damage_flag != "laser")
+ return damage * 1.5
+ return ..()
+
+/datum/reagent/blob/explosive_lattice
+ name = "Explosive Lattice"
+ taste_description = "the bomb"
+ color = "#8B2500"
+
+/datum/reagent/blob/explosive_lattice/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ var/initial_volume = reac_volume
+ reac_volume = ..()
+ if(reac_volume >= 10) //if it's not a spore cloud, bad time incoming
+ var/obj/effect/temp_visual/explosion/fast/E = new /obj/effect/temp_visual/explosion/fast(get_turf(M))
+ E.alpha = 150
+ for(var/mob/living/L in orange(get_turf(M), 1))
+ if(ROLE_BLOB in L.faction) //no friendly fire
+ continue
+ var/aoe_volume = ..(L, TOUCH, initial_volume, 0, L.get_permeability_protection(), O)
+ L.apply_damage(0.4*aoe_volume, BRUTE)
+ if(M)
+ M.apply_damage(0.6*reac_volume, BRUTE)
+ else
+ M.apply_damage(0.6*reac_volume, BRUTE)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/multiplex.dm b/code/modules/antagonists/blob/blob/blobstrains/multiplex.dm
new file mode 100644
index 0000000000..191da6c51f
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/multiplex.dm
@@ -0,0 +1,40 @@
+/datum/blobstrain/multiplex
+ var/list/blobstrains
+ var/typeshare
+
+/datum/blobstrain/multiplex/New(mob/camera/blob/new_overmind, list/blobstrains)
+ . = ..()
+ for (var/bt in blobstrains)
+ if (ispath(bt, /datum/blobstrain))
+ src.blobstrains += new bt(overmind)
+ else if (istype(bt, /datum/blobstrain))
+ var/datum/blobstrain/bts = bt
+ bts.overmind = overmind
+ src.blobstrains += bt
+ typeshare = (0.8 * length(src.blobstrains)) - (length(src.blobstrains)-1) // 1 is 80%, 2 are 60% etc
+
+/datum/blobstrain/multiplex/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag, coefficient = 1) //when the blob takes damage, do this
+ for (var/datum/blobstrain/bt in blobstrains)
+ . += bt.damage_reaction(B, damage, damage_type, damage_flag, coefficient*typeshare)
+
+/datum/blobstrain/multiplex/death_reaction(obj/structure/blob/B, damage_flag, coefficient = 1) //when a blob dies, do this
+ for (var/datum/blobstrain/bt in blobstrains)
+ . += bt.death_reaction(B, damage_flag, coefficient*typeshare)
+
+/datum/blobstrain/multiplex/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this
+ for (var/datum/blobstrain/bt in blobstrains)
+ . += bt.expand_reaction(B, newB, T, O, coefficient*typeshare)
+
+/datum/blobstrain/multiplex/tesla_reaction(obj/structure/blob/B, power, coefficient = 1) //when the blob is hit by a tesla bolt, do this
+ for (var/datum/blobstrain/bt in blobstrains)
+ . += bt.tesla_reaction(B, power, coefficient*typeshare)
+ if (prob(. / length(blobstrains) * 100))
+ return 1
+
+/datum/blobstrain/multiplex/extinguish_reaction(obj/structure/blob/B, coefficient = 1) //when the blob is hit with water, do this
+ for (var/datum/blobstrain/bt in blobstrains)
+ . += bt.extinguish_reaction(B, coefficient*typeshare)
+
+/datum/blobstrain/multiplex/emp_reaction(obj/structure/blob/B, severity, coefficient = 1) //when the blob is hit with an emp, do this
+ for (var/datum/blobstrain/bt in blobstrains)
+ . += bt.emp_reaction(B, severity, coefficient*typeshare)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm b/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm
new file mode 100644
index 0000000000..fac3470c7a
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm
@@ -0,0 +1,38 @@
+//does massive brute and burn damage, but can only expand manually
+/datum/blobstrain/reagent/networked_fibers
+ name = "Networked Fibers"
+ description = "will do high brute and burn damage and will generate resources quicker, but can only expand manually."
+ shortdesc = "will do high brute and burn damage."
+ effectdesc = "will move your core when manually expanding near it."
+ analyzerdescdamage = "Does high brute and burn damage."
+ analyzerdesceffect = "Is highly mobile and generates resources rapidly."
+ color = "#CDC0B0"
+ complementary_color = "#FFF68F"
+ reagent = /datum/reagent/blob/networked_fibers
+
+/datum/blobstrain/reagent/networked_fibers/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
+ if(!O && newB.overmind)
+ if(!istype(B, /obj/structure/blob/node))
+ newB.overmind.add_points(1)
+ qdel(newB)
+ else
+ var/area/A = get_area(T)
+ if(!isspaceturf(T) && !istype(A, /area/shuttle))
+ for(var/obj/structure/blob/core/C in range(1, newB))
+ if(C.overmind == O)
+ newB.forceMove(get_turf(C))
+ C.forceMove(T)
+ C.setDir(get_dir(newB, C))
+ O.add_points(1)
+
+//does massive brute and burn damage, but can only expand manually
+/datum/reagent/blob/networked_fibers
+ name = "Networked Fibers"
+ taste_description = "efficiency"
+ color = "#CDC0B0"
+
+/datum/reagent/blob/networked_fibers/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, BRUTE)
+ if(M)
+ M.apply_damage(0.6*reac_volume, BURN)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm b/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm
new file mode 100644
index 0000000000..6a984e66a2
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm
@@ -0,0 +1,51 @@
+//does low brute damage, oxygen damage, and stamina damage and wets tiles when damaged
+/datum/blobstrain/reagent/pressurized_slime
+ name = "Pressurized Slime"
+ description = "will do low brute, oxygen, and stamina damage, and wet tiles under targets."
+ effectdesc = "will also wet tiles near blobs that are attacked or killed."
+ analyzerdescdamage = "Does low brute damage, low oxygen damage, drains stamina, and wets tiles under targets, extinguishing them."
+ analyzerdesceffect = "When attacked or killed, lubricates nearby tiles, extinguishing anything on them."
+ color = "#AAAABB"
+ complementary_color = "#BBBBAA"
+ blobbernaut_message = "emits slime at"
+ message = "The blob splashes into you"
+ message_living = ", and you gasp for breath"
+ reagent = /datum/reagent/blob/pressurized_slime
+
+/datum/blobstrain/reagent/pressurized_slime/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") || damage_type != BURN)
+ extinguisharea(B, damage)
+ return ..()
+
+/datum/blobstrain/reagent/pressurized_slime/death_reaction(obj/structure/blob/B, damage_flag)
+ if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser")
+ B.visible_message("The blob ruptures, spraying the area with liquid!")
+ extinguisharea(B, 50)
+
+/datum/blobstrain/reagent/pressurized_slime/proc/extinguisharea(obj/structure/blob/B, probchance)
+ for(var/turf/open/T in range(1, B))
+ if(prob(probchance))
+ T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
+ for(var/obj/O in T)
+ O.extinguish()
+ for(var/mob/living/L in T)
+ L.adjust_fire_stacks(-2.5)
+ L.ExtinguishMob()
+
+/datum/reagent/blob/pressurized_slime
+ name = "Pressurized Slime"
+ taste_description = "a sponge"
+ color = "#AAAABB"
+
+/datum/reagent/blob/pressurized_slime/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ var/turf/open/T = get_turf(M)
+ if(istype(T) && prob(reac_volume))
+ T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
+ M.adjust_fire_stacks(-(reac_volume / 10))
+ M.ExtinguishMob()
+ M.apply_damage(0.4*reac_volume, BRUTE)
+ if(M)
+ M.apply_damage(0.4*reac_volume, OXY)
+ if(M)
+ M.adjustStaminaLoss(0.2*reac_volume)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/reactive_spines.dm b/code/modules/antagonists/blob/blob/blobstrains/reactive_spines.dm
new file mode 100644
index 0000000000..fca56d1402
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/reactive_spines.dm
@@ -0,0 +1,30 @@
+//does brute damage through armor and bio resistance
+/datum/blobstrain/reagent/reactive_spines
+ name = "Reactive Spines"
+ description = "will do medium brute damage through armor and bio resistance."
+ effectdesc = "will also react when attacked with brute damage, attacking all near the attacked blob."
+ analyzerdescdamage = "Does medium brute damage, ignoring armor and bio resistance."
+ analyzerdesceffect = "When attacked with brute damage, will lash out, attacking everything near it."
+ color = "#9ACD32"
+ complementary_color = "#FFA500"
+ blobbernaut_message = "stabs"
+ message = "The blob stabs you"
+ reagent = /datum/reagent/blob/reactive_spines
+
+/datum/blobstrain/reagent/reactive_spines/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if(damage && damage_type == BRUTE && B.obj_integrity - damage > 0) //is there any damage, is it brute, and will we be alive
+ if(damage_flag == "melee")
+ B.visible_message("The blob retaliates, lashing out!")
+ for(var/atom/A in range(1, B))
+ A.blob_act(B)
+ return ..()
+
+/datum/reagent/blob/reactive_spines
+ name = "Reactive Spines"
+ taste_description = "rock"
+ color = "#9ACD32"
+
+/datum/reagent/blob/reactive_spines/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ if(M.stat == DEAD || istype(M, /mob/living/simple_animal/hostile/blob))
+ return 0 //the dead, and blob mobs, don't cause reactions
+ M.adjustBruteLoss(0.8*reac_volume)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/regenerative_materia.dm b/code/modules/antagonists/blob/blob/blobstrains/regenerative_materia.dm
new file mode 100644
index 0000000000..25511e01ff
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/regenerative_materia.dm
@@ -0,0 +1,33 @@
+//does toxin damage, hallucination, targets think they're not hurt at all
+/datum/blobstrain/reagent/regenerative_materia
+ name = "Regenerative Materia"
+ description = "will do toxin damage and cause targets to believe they are fully healed."
+ analyzerdescdamage = "Does toxin damage and injects a toxin that causes the target to believe they are fully healed."
+ color = "#C8A5DC"
+ complementary_color = "#CD7794"
+ message_living = ", and you feel alive"
+ reagent = /datum/reagent/blob/regenerative_materia
+
+/datum/reagent/blob/regenerative_materia
+ name = "Regenerative Materia"
+ taste_description = "heaven"
+ color = "#C8A5DC"
+
+/datum/reagent/blob/regenerative_materia/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.adjust_drugginess(reac_volume)
+ if(M.reagents)
+ M.reagents.add_reagent("regenerative_materia", 0.2*reac_volume)
+ M.reagents.add_reagent("spore", 0.2*reac_volume)
+ M.apply_damage(0.7*reac_volume, TOX)
+
+/datum/reagent/blob/regenerative_materia/on_mob_life(mob/living/carbon/C)
+ C.adjustToxLoss(1*REAGENTS_EFFECT_MULTIPLIER)
+ C.hal_screwyhud = SCREWYHUD_HEALTHY //fully healed, honest
+ ..()
+
+/datum/reagent/blob/regenerative_materia/on_mob_delete(mob/living/M)
+ if(iscarbon(M))
+ var/mob/living/carbon/N = M
+ N.hal_screwyhud = 0
+ ..()
diff --git a/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm b/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm
new file mode 100644
index 0000000000..00743c671e
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm
@@ -0,0 +1,34 @@
+/datum/blobstrain/reagent/replicating_foam
+ description = "will do medium brute damage and occasionally expand again when expanding."
+ shortdesc = "will do medium brute damage."
+ effectdesc = "will also expand when attacked with burn damage, but takes more brute damage."
+ color = "#7B5A57"
+ complementary_color = "#57787B"
+ analyzerdescdamage = "Does medium brute damage."
+ analyzerdesceffect = "Expands when attacked with burn damage, will occasionally expand again when expanding, and is fragile to brute damage."
+ reagent = /datum/reagent/blob/replicating_foam
+
+
+/datum/blobstrain/reagent/replicating_foam/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if(damage_type == BRUTE)
+ damage = damage * 2
+ else if(damage_type == BURN && damage > 0 && B.obj_integrity - damage > 0 && prob(60))
+ var/obj/structure/blob/newB = B.expand(null, null, 0)
+ if(newB)
+ newB.obj_integrity = B.obj_integrity - damage
+ newB.update_icon()
+ return ..()
+
+
+/datum/blobstrain/reagent/replicating_foam/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
+ if(prob(30))
+ newB.expand(null, null, 0) //do it again!
+
+/datum/reagent/blob/replicating_foam
+ name = "Replicating Foam"
+ taste_description = "duplication"
+ color = "#7B5A57"
+
+/datum/reagent/blob/replicating_foam/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.apply_damage(0.7*reac_volume, BRUTE)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm b/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm
new file mode 100644
index 0000000000..dbb3d6fb9b
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm
@@ -0,0 +1,35 @@
+//does brute damage, shifts away when damaged
+/datum/blobstrain/reagent/shifting_fragments
+ description = "will do medium brute damage."
+ effectdesc = "will also cause blob parts to shift away when attacked."
+ analyzerdescdamage = "Does medium brute damage."
+ analyzerdesceffect = "When attacked, may shift away from the attacker."
+ color = "#C8963C"
+ complementary_color = "#3C6EC8"
+ reagent = /datum/reagent/blob/shifting_fragments
+
+/datum/blobstrain/reagent/shifting_fragments/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
+ if(istype(B, /obj/structure/blob/normal) || (istype(B, /obj/structure/blob/shield) && prob(25)))
+ newB.forceMove(get_turf(B))
+ B.forceMove(T)
+
+/datum/blobstrain/reagent/shifting_fragments/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage > 0 && B.obj_integrity - damage > 0 && prob(60-damage))
+ var/list/blobstopick = list()
+ for(var/obj/structure/blob/OB in orange(1, B))
+ if((istype(OB, /obj/structure/blob/normal) || (istype(OB, /obj/structure/blob/shield) && prob(25))) && OB.overmind && OB.overmind.blobstrain.type == B.overmind.blobstrain.type)
+ blobstopick += OB //as long as the blob picked is valid; ie, a normal or shield blob that has the same chemical as we do, we can swap with it
+ if(blobstopick.len)
+ var/obj/structure/blob/targeted = pick(blobstopick) //randomize the blob chosen, because otherwise it'd tend to the lower left
+ var/turf/T = get_turf(targeted)
+ targeted.forceMove(get_turf(B))
+ B.forceMove(T) //swap the blobs
+ return ..()
+
+/datum/reagent/blob/shifting_fragments
+ name = "Shifting Fragments"
+ color = "#C8963C"
+
+/datum/reagent/blob/shifting_fragments/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.apply_damage(0.7*reac_volume, BRUTE)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm b/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm
new file mode 100644
index 0000000000..d58fb5b37d
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm
@@ -0,0 +1,38 @@
+//does brute damage, bonus damage for each nearby blob, and spreads damage out
+/datum/blobstrain/reagent/synchronous_mesh
+ name = "Synchronous Mesh"
+ description = "will do massively increased brute damage for each blob near the target."
+ effectdesc = "will also spread damage between each blob near the attacked blob."
+ analyzerdescdamage = "Does brute damage, increasing for each blob near the target."
+ analyzerdesceffect = "When attacked, spreads damage between all blobs near the attacked blob."
+ color = "#65ADA2"
+ complementary_color = "#AD6570"
+ blobbernaut_message = "synchronously strikes"
+ message = "The blobs strike you"
+
+/datum/blobstrain/reagent/synchronous_mesh/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") //the cause isn't fire or bombs, so split the damage
+ var/damagesplit = 1 //maximum split is 9, reducing the damage each blob takes to 11% but doing that damage to 9 blobs
+ for(var/obj/structure/blob/C in orange(1, B))
+ if(!istype(C, /obj/structure/blob/core) && !istype(C, /obj/structure/blob/node) && C.overmind && C.overmind.blobstrain.type == B.overmind.blobstrain.type) //if it doesn't have the same chemical or is a core or node, don't split damage to it
+ damagesplit += 1
+ for(var/obj/structure/blob/C in orange(1, B))
+ if(!istype(C, /obj/structure/blob/core) && !istype(C, /obj/structure/blob/node) && C.overmind && C.overmind.blobstrain.type == B.overmind.blobstrain.type) //only hurt blobs that have the same overmind chemical and aren't cores or nodes
+ C.take_damage(damage/damagesplit, CLONE, 0, 0)
+ return damage / damagesplit
+ else
+ return damage * 1.25
+
+/datum/reagent/blob/synchronous_mesh
+ name = "Synchronous Mesh"
+ taste_description = "toxic mold"
+ color = "#65ADA2"
+
+/datum/reagent/blob/synchronous_mesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.apply_damage(0.2*reac_volume, BRUTE)
+ if(M && reac_volume)
+ for(var/obj/structure/blob/B in range(1, M)) //if the target is completely surrounded, this is 2.4*reac_volume bonus damage, total of 2.6*reac_volume
+ if(M)
+ B.blob_attack_animation(M) //show them they're getting a bad time
+ M.apply_damage(0.3*reac_volume, BRUTE)
diff --git a/code/modules/antagonists/blob/blob/blobstrains/zombifying_pods.dm b/code/modules/antagonists/blob/blob/blobstrains/zombifying_pods.dm
new file mode 100644
index 0000000000..b2bb9d5115
--- /dev/null
+++ b/code/modules/antagonists/blob/blob/blobstrains/zombifying_pods.dm
@@ -0,0 +1,46 @@
+//kills sleeping targets and turns them into blob zombies, produces fragile spores when killed or on expanding
+/datum/blobstrain/reagent/zombifying_pods
+ name = "Zombifying Pods"
+ description = "will do very low toxin damage and harvest sleeping targets for additional resources and a blob zombie."
+ effectdesc = "will also produce fragile spores when killed and on expanding."
+ shortdesc = "will do very low toxin damage and harvest sleeping targets for additional resources(for your overmind) and a blob zombie."
+ analyzerdescdamage = "Does very low toxin damage and kills unconscious humans, turning them into blob zombies."
+ analyzerdesceffect = "Produces spores when expanding and when killed."
+ color = "#E88D5D"
+ complementary_color = "#823ABB"
+ message_living = ", and you feel tired"
+ reagent = /datum/reagent/blob/zombifying_pods
+
+/datum/blobstrain/reagent/zombifying_pods/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
+ if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage <= 20 && B.obj_integrity - damage <= 0 && prob(30)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 20% chance of a shitty spore.
+ B.visible_message("A spore floats free of the blob!")
+ var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc)
+ BS.overmind = B.overmind
+ BS.update_icons()
+ B.overmind.blob_mobs.Add(BS)
+ return ..()
+
+/datum/blobstrain/reagent/zombifying_pods/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
+ if(prob(10))
+ var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(T)
+ BS.overmind = B.overmind
+ BS.update_icons()
+ newB.overmind.blob_mobs.Add(BS)
+
+/datum/reagent/blob/zombifying_pods
+ name = "Zombifying Pods"
+ color = "#E88D5D"
+
+/datum/reagent/blob/zombifying_pods/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, TOX)
+ if(O && ishuman(M) && M.stat == UNCONSCIOUS)
+ M.death() //sleeping in a fight? bad plan.
+ var/points = rand(5, 10)
+ var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M))
+ BS.overmind = O
+ BS.update_icons()
+ O.blob_mobs.Add(BS)
+ BS.Zombify(M)
+ O.add_points(points)
+ to_chat(O, "Gained [points] resources from the zombification of [M].")
diff --git a/code/modules/antagonists/blob/blob/overmind.dm b/code/modules/antagonists/blob/blob/overmind.dm
index 18e13118fe..aed64e4039 100644
--- a/code/modules/antagonists/blob/blob/overmind.dm
+++ b/code/modules/antagonists/blob/blob/overmind.dm
@@ -20,25 +20,25 @@ GLOBAL_LIST_EMPTY(blob_nodes)
pass_flags = PASSBLOB
faction = list(ROLE_BLOB)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- call_life = TRUE
hud_type = /datum/hud/blob_overmind
var/obj/structure/blob/core/blob_core = null // The blob overmind's core
var/blob_points = 0
var/max_blob_points = 250
var/last_attack = 0
- var/datum/reagent/blob/blob_reagent_datum = new/datum/reagent/blob()
+ var/datum/blobstrain/blobstrain
var/list/blob_mobs = list()
var/list/resource_blobs = list()
- var/free_chem_rerolls = 1 //one free chemical reroll
+ var/free_strain_rerolls = 1 //one free strain reroll
+ var/last_reroll_time = 0 //time since we last rerolled, used to give free rerolls
var/nodes_required = 1 //if the blob needs nodes to place resource and factory blobs
var/placed = 0
- var/base_point_rate = 2 //for blob core placement
var/manualplace_min_time = 600 //in deciseconds //a minute, to get bearings
var/autoplace_max_time = 3600 //six minutes, as long as should be needed
var/list/blobs_legit = list()
var/max_count = 0 //The biggest it got before death
var/blobwincount = 400
var/victory_in_progress = FALSE
+ var/rerolling = FALSE
/mob/camera/blob/Initialize(mapload, starting_points = 60)
validate_location()
@@ -50,13 +50,14 @@ GLOBAL_LIST_EMPTY(blob_nodes)
name = new_name
real_name = new_name
last_attack = world.time
- var/datum/reagent/blob/BC = pick((subtypesof(/datum/reagent/blob)))
- blob_reagent_datum = new BC
- color = blob_reagent_datum.complementary_color
+ var/datum/blobstrain/BS = pick(GLOB.valid_blobstrains)
+ set_strain(BS)
+ color = blobstrain.complementary_color
if(blob_core)
blob_core.update_icon()
SSshuttle.registerHostileEnvironment(src)
- .= ..()
+ . = ..()
+ START_PROCESSING(SSobj, src)
/mob/camera/blob/proc/validate_location()
var/turf/T = get_turf(src)
@@ -70,13 +71,28 @@ GLOBAL_LIST_EMPTY(blob_nodes)
CRASH("No blobspawnpoints and blob spawned in nullspace.")
forceMove(T)
+/mob/camera/blob/proc/set_strain(datum/blobstrain/new_strain)
+ if (ispath(new_strain))
+ var/hadstrain = FALSE
+ if (istype(blobstrain))
+ blobstrain.on_lose()
+ qdel(blobstrain)
+ hadstrain = TRUE
+ blobstrain = new new_strain(src)
+ blobstrain.on_gain()
+ if (hadstrain)
+ to_chat(src, "Your strain is now: [blobstrain.name]!")
+ to_chat(src, "The [blobstrain.name] strain [blobstrain.description]")
+ if(blobstrain.effectdesc)
+ to_chat(src, "The [blobstrain.name] strain [blobstrain.effectdesc]")
+
/mob/camera/blob/proc/is_valid_turf(turf/T)
var/area/A = get_area(T)
if((A && !A.blob_allowed) || !T || !is_station_level(T.z) || isspaceturf(T))
return FALSE
return TRUE
-/mob/camera/blob/Life()
+/mob/camera/blob/process()
if(!blob_core)
if(!placed)
if(manualplace_min_time && world.time >= manualplace_min_time)
@@ -84,7 +100,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
to_chat(src, "You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].")
manualplace_min_time = 0
if(autoplace_max_time && world.time >= autoplace_max_time)
- place_blob_core(base_point_rate, 1)
+ place_blob_core(1)
else
qdel(src)
else if(!victory_in_progress && (blobs_legit.len >= blobwincount))
@@ -94,11 +110,12 @@ GLOBAL_LIST_EMPTY(blob_nodes)
max_blob_points = INFINITY
blob_points = INFINITY
addtimer(CALLBACK(src, .proc/victory), 450)
+ else if(!free_strain_rerolls && (last_reroll_time + BLOB_REROLL_TIMEYou have gained another free strain re-roll.")
+ free_strain_rerolls = 1
if(!victory_in_progress && max_count < blobs_legit.len)
max_count = blobs_legit.len
- ..()
-
/mob/camera/blob/proc/victory()
sound_to_playing_players('sound/machines/alarm.ogg')
@@ -129,7 +146,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
continue
if(!A.blob_allowed)
continue
- A.color = blob_reagent_datum.color
+ A.color = blobstrain.color
A.name = "blob"
A.icon = 'icons/mob/blob.dmi'
A.icon_state = "blob_shield"
@@ -162,6 +179,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
blobs_legit = null
SSshuttle.clearHostileEnvironment(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
@@ -173,9 +191,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
add_points(0)
/mob/camera/blob/examine(mob/user)
- . = ..()
- if(blob_reagent_datum)
- . += "Its chemical is [blob_reagent_datum.name]."
+ ..()
+ if(blobstrain)
+ to_chat(user, "Its strain is [blobstrain.name].")
/mob/camera/blob/update_health_hud()
if(blob_core)
@@ -214,7 +232,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
src.log_talk(message, LOG_SAY)
var/message_a = say_quote(message)
- var/rendered = "\[Blob Telepathy\] [name]([blob_reagent_datum.name]) [message_a]"
+ var/rendered = "\[Blob Telepathy\] [name]([blobstrain.name]) [message_a]"
for(var/mob/M in GLOB.mob_list)
if(isovermind(M) || istype(M, /mob/living/simple_animal/hostile/blob))
@@ -233,8 +251,8 @@ GLOBAL_LIST_EMPTY(blob_nodes)
stat(null, "Core Health: [blob_core.obj_integrity]")
stat(null, "Power Stored: [blob_points]/[max_blob_points]")
stat(null, "Blobs to Win: [blobs_legit.len]/[blobwincount]")
- if(free_chem_rerolls)
- stat(null, "You have [free_chem_rerolls] Free Chemical Reroll\s Remaining")
+ if(free_strain_rerolls)
+ stat(null, "You have [free_strain_rerolls] Free Strain Reroll\s Remaining")
if(!placed)
if(manualplace_min_time)
stat(null, "Time Before Manual Placement: [max(round((manualplace_min_time - world.time)*0.1, 0.1), 0)]")
diff --git a/code/modules/antagonists/blob/blob/powers.dm b/code/modules/antagonists/blob/blob/powers.dm
index fe492831b8..641019ef33 100644
--- a/code/modules/antagonists/blob/blob/powers.dm
+++ b/code/modules/antagonists/blob/blob/powers.dm
@@ -7,7 +7,7 @@
// Power verbs
-/mob/camera/blob/proc/place_blob_core(point_rate, placement_override , pop_override = FALSE)
+/mob/camera/blob/proc/place_blob_core(placement_override, pop_override = FALSE)
if(placed && placement_override != -1)
return 1
if(!placement_override)
@@ -47,7 +47,7 @@
if(placed && blob_core)
blob_core.forceMove(loc)
else
- var/obj/structure/blob/core/core = new(get_turf(src), src, point_rate, 1)
+ var/obj/structure/blob/core/core = new(get_turf(src), src, 1)
core.overmind = src
blobs_legit += src
blob_core = core
@@ -71,13 +71,13 @@
var/list/nodes = list()
for(var/i in 1 to GLOB.blob_nodes.len)
var/obj/structure/blob/node/B = GLOB.blob_nodes[i]
- nodes["Blob Node #[i] ([B.overmind ? "[B.overmind.blob_reagent_datum.name]":"No Chemical"])"] = B
+ nodes["Blob Node #[i] ([B.overmind ? "[B.overmind.blobstrain.name]":"No Strain"])"] = B
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
var/obj/structure/blob/node/chosen_node = nodes[node_name]
if(chosen_node)
forceMove(chosen_node.loc)
-/mob/camera/blob/proc/createSpecial(price, blobType, nearEquals, needsNode, turf/T)
+/mob/camera/blob/proc/createSpecial(price, blobstrain, nearEquals, needsNode, turf/T)
if(!T)
T = get_turf(src)
var/obj/structure/blob/B = (locate(/obj/structure/blob) in T)
@@ -93,12 +93,12 @@
return //handholdotron 2000
if(nearEquals)
for(var/obj/structure/blob/L in orange(nearEquals, T))
- if(L.type == blobType)
+ if(L.type == blobstrain)
to_chat(src, "There is a similar blob nearby, move more than [nearEquals] tiles away from it!")
return
if(!can_buy(price))
return
- var/obj/structure/blob/N = B.change_to(blobType, src)
+ var/obj/structure/blob/N = B.change_to(blobstrain, src)
return N
/mob/camera/blob/verb/toggle_node_req()
@@ -123,6 +123,7 @@
if(!can_buy(15))
return
if(S.obj_integrity < S.max_integrity * 0.5)
+ add_points(BLOB_REFLECTOR_COST)
to_chat(src, "This shield blob is too damaged to be modified properly!")
return
to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced intregrity.")
@@ -166,7 +167,9 @@
if(!can_buy(40))
return
- var/list/mob/candidates = pollGhostCandidates("Do you want to play as a [blob_reagent_datum.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly
+ B.naut = TRUE //temporary placeholder to prevent creation of more than one per factory.
+ to_chat(src, "You attempt to produce a blobbernaut.")
+ var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly
if(LAZYLEN(candidates)) //if we got at least one candidate, they're a blobbernaut now.
B.max_integrity = initial(B.max_integrity) * 0.25 //factories that produced a blobbernaut have much lower health
B.obj_integrity = min(B.obj_integrity, B.max_integrity)
@@ -188,8 +191,8 @@
to_chat(blobber, "You are a blobbernaut!")
to_chat(blobber, "You are powerful, hard to kill, and slowly regenerate near nodes and cores, but will slowly die if not near the blob or if the factory that made you is killed.")
to_chat(blobber, "You can communicate with other blobbernauts and overminds via :b")
- to_chat(blobber, "Your overmind's blob reagent is: [blob_reagent_datum.name]!")
- to_chat(blobber, "The [blob_reagent_datum.name] reagent [blob_reagent_datum.shortdesc ? "[blob_reagent_datum.shortdesc]" : "[blob_reagent_datum.description]"]")
+ to_chat(blobber, "Your overmind's blob reagent is: [blobstrain.name]!")
+ to_chat(blobber, "The [blobstrain.name] reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]")
else
to_chat(src, "You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later.")
add_points(40)
@@ -265,9 +268,7 @@
continue
if(L.stat != DEAD)
attacksuccess = TRUE
- var/mob_protection = L.get_permeability_protection()
- blob_reagent_datum.reaction_mob(L, VAPOR, 25, 1, mob_protection, src)
- blob_reagent_datum.send_message(L)
+ blobstrain.attack_living(L)
var/obj/structure/blob/B = locate() in T
if(B)
if(attacksuccess) //if we successfully attacked a turf with a blob on it, don't refund shit
@@ -331,41 +332,38 @@
if(BM.stat == CONSCIOUS)
BM.say(speak_text)
-/mob/camera/blob/verb/chemical_reroll()
+/mob/camera/blob/verb/strain_reroll()
set category = "Blob"
- set name = "Reactive Chemical Adaptation (40)"
- set desc = "Replaces your chemical with a random, different one."
- if(free_chem_rerolls || can_buy(40))
- set_chemical()
- if(free_chem_rerolls)
- free_chem_rerolls--
+ set name = "Reactive Strain Adaptation (40)"
+ set desc = "Replaces your strain with a random, different one."
+ if(!rerolling && (free_strain_rerolls || can_buy(40)))
+ rerolling = TRUE
+ reroll_strain()
+ rerolling = FALSE
+ if(free_strain_rerolls)
+ free_strain_rerolls--
+ last_reroll_time = world.time
-/mob/camera/blob/proc/set_chemical()
- var/datum/reagent/blob/BC = pick((subtypesof(/datum/reagent/blob) - blob_reagent_datum.type))
- blob_reagent_datum = new BC
- color = blob_reagent_datum.complementary_color
- for(var/BL in GLOB.blobs)
- var/obj/structure/blob/B = BL
- B.update_icon()
- for(var/BLO in blob_mobs)
- var/mob/living/simple_animal/hostile/blob/BM = BLO
- BM.update_icons() //If it's getting a new chemical, tell it what it does!
- to_chat(BM, "Your overmind's blob reagent is now: [blob_reagent_datum.name]!")
- to_chat(BM, "The [blob_reagent_datum.name] reagent [blob_reagent_datum.shortdesc ? "[blob_reagent_datum.shortdesc]" : "[blob_reagent_datum.description]"]")
- to_chat(src, "Your reagent is now: [blob_reagent_datum.name]!")
- to_chat(src, "The [blob_reagent_datum.name] reagent [blob_reagent_datum.description]")
- if(blob_reagent_datum.effectdesc)
- to_chat(src, "The [blob_reagent_datum.name] reagent [blob_reagent_datum.effectdesc]")
+/mob/camera/blob/proc/reroll_strain()
+ var/list/choices = list()
+ while (length(choices) < 4)
+ var/datum/blobstrain/bs = pick((GLOB.valid_blobstrains))
+ choices[initial(bs.name)] = bs
+
+ var/choice = input(usr, "Please choose a new strain","Strain") as anything in choices
+ if (choice && choices[choice] && !QDELETED(src))
+ var/datum/blobstrain/bs = choices[choice]
+ set_strain(bs)
/mob/camera/blob/verb/blob_help()
set category = "Blob"
set name = "*Blob Help*"
set desc = "Help on how to blob."
to_chat(src, "As the overmind, you can control the blob!")
- to_chat(src, "Your blob reagent is: [blob_reagent_datum.name]!")
- to_chat(src, "The [blob_reagent_datum.name] reagent [blob_reagent_datum.description]")
- if(blob_reagent_datum.effectdesc)
- to_chat(src, "The [blob_reagent_datum.name] reagent [blob_reagent_datum.effectdesc]")
+ to_chat(src, "Your blob reagent is: [blobstrain.name]!")
+ to_chat(src, "The [blobstrain.name] reagent [blobstrain.description]")
+ if(blobstrain.effectdesc)
+ to_chat(src, "The [blobstrain.name] reagent [blobstrain.effectdesc]")
to_chat(src, "You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.")
to_chat(src, "Normal Blobs will expand your reach and can be upgraded into special blobs that perform certain functions.")
to_chat(src, "You can upgrade normal blobs into the following types of blob:")
diff --git a/code/modules/antagonists/blob/blob/theblob.dm b/code/modules/antagonists/blob/blob/theblob.dm
index fc78f859f2..444b10684b 100644
--- a/code/modules/antagonists/blob/blob/theblob.dm
+++ b/code/modules/antagonists/blob/blob/theblob.dm
@@ -83,16 +83,10 @@
/obj/structure/blob/update_icon() //Updates color based on overmind color if we have an overmind.
if(overmind)
- add_atom_colour(overmind.blob_reagent_datum.color, FIXED_COLOUR_PRIORITY)
+ add_atom_colour(overmind.blobstrain.color, FIXED_COLOUR_PRIORITY)
else
remove_atom_colour(FIXED_COLOUR_PRIORITY)
-/obj/structure/blob/process()
- Life()
-
-/obj/structure/blob/proc/Life()
- return
-
/obj/structure/blob/proc/Pulse_Area(mob/camera/blob/pulsing_overmind, claim_range = 10, pulse_range = 3, expand_range = 2)
if(QDELETED(pulsing_overmind))
pulsing_overmind = overmind
@@ -148,10 +142,10 @@
O.setDir(dir)
if(controller)
var/mob/camera/blob/BO = controller
- O.color = BO.blob_reagent_datum.color
+ O.color = BO.blobstrain.color
O.alpha = 200
else if(overmind)
- O.color = overmind.blob_reagent_datum.color
+ O.color = overmind.blobstrain.color
if(A)
O.do_attack_animation(A) //visually attack the whatever
return O //just in case you want to do something to the animation.
@@ -192,7 +186,7 @@
B.forceMove(T)
B.update_icon()
if(B.overmind && expand_reaction)
- B.overmind.blob_reagent_datum.expand_reaction(src, B, T, controller)
+ B.overmind.blobstrain.expand_reaction(src, B, T, controller)
return B
else
blob_attack_animation(T, controller)
@@ -209,14 +203,14 @@
return
if(severity > 0)
if(overmind)
- overmind.blob_reagent_datum.emp_reaction(src, severity)
+ overmind.blobstrain.emp_reaction(src, severity)
if(prob(100 - severity * 30))
new /obj/effect/temp_visual/emp(get_turf(src))
/obj/structure/blob/tesla_act(power)
..()
if(overmind)
- if(overmind.blob_reagent_datum.tesla_reaction(src, power))
+ if(overmind.blobstrain.tesla_reaction(src, power))
take_damage(power/400, BURN, "energy")
else
take_damage(power/400, BURN, "energy")
@@ -224,7 +218,7 @@
/obj/structure/blob/extinguish()
..()
if(overmind)
- overmind.blob_reagent_datum.extinguish_reaction(src)
+ overmind.blobstrain.extinguish_reaction(src)
/obj/structure/blob/hulk_damage()
return 15
@@ -243,13 +237,13 @@
else
return ..()
-/obj/structure/blob/proc/chemeffectreport()
+/obj/structure/blob/proc/chemeffectreport(mob/user)
RETURN_TYPE(/list)
. = list()
if(overmind)
- . += "Material: [overmind.blob_reagent_datum.name]."
- . += "Material Effects: [overmind.blob_reagent_datum.analyzerdescdamage]"
- . += "Material Properties: [overmind.blob_reagent_datum.analyzerdesceffect]
"
+ to_chat(user, "Material: [overmind.blobstrain.name].")
+ to_chat(user, "Material Effects: [overmind.blobstrain.analyzerdescdamage]")
+ to_chat(user, "Material Properties: [overmind.blobstrain.analyzerdesceffect]
")
else
. += "No Material Detected!
"
@@ -288,7 +282,7 @@
armor_protection = armor.getRating(damage_flag)
damage_amount = round(damage_amount * (100 - armor_protection)*0.01, 0.1)
if(overmind && damage_flag)
- damage_amount = overmind.blob_reagent_datum.damage_reaction(src, damage_amount, damage_type, damage_flag)
+ damage_amount = overmind.blobstrain.damage_reaction(src, damage_amount, damage_type, damage_flag)
return damage_amount
/obj/structure/blob/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
@@ -298,7 +292,7 @@
/obj/structure/blob/obj_destruction(damage_flag)
if(overmind)
- overmind.blob_reagent_datum.death_reaction(src, damage_flag)
+ overmind.blobstrain.death_reaction(src, damage_flag)
..()
/obj/structure/blob/proc/change_to(type, controller)
@@ -332,8 +326,8 @@
/obj/structure/blob/proc/get_chem_name()
if(overmind)
- return overmind.blob_reagent_datum.name
- return "an unknown variant"
+ return overmind.blobstrain.name
+ return "some kind of organic tissue"
/obj/structure/blob/normal
name = "normal blob"
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index ff1d9231f7..a381cc512a 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -11,17 +11,6 @@
invisibility = INVISIBILITY_ABSTRACT // No one can see us
sight = SEE_SELF
move_on_shuttle = FALSE
- var/call_life = FALSE //TRUE if Life() should be called on this camera every tick of the mobs subystem, as if it were a living mob
-
-/mob/camera/Initialize()
- . = ..()
- if(call_life)
- GLOB.living_cameras += src
-
-/mob/camera/Destroy()
- . = ..()
- if(call_life)
- GLOB.living_cameras -= src
/mob/camera/experience_pressure_difference()
return
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 2bf17bc265..d3199d6f8b 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -1,4 +1,5 @@
-/mob/living/Life(seconds, times_fired)
+/mob/living/proc/Life(seconds, times_fired)
+ set waitfor = FALSE
set invisibility = 0
if(digitalinvis)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index e6cdf81e38..497033b3e3 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -202,9 +202,6 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
if(self_message)
show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL)
-/mob/proc/Life()
- set waitfor = FALSE
-
/mob/proc/get_item_by_slot(slot_id)
return null
diff --git a/code/modules/reagents/chemistry/reagents/blob_reagents.dm b/code/modules/reagents/chemistry/reagents/blob_reagents.dm
deleted file mode 100644
index fba0b47eb4..0000000000
--- a/code/modules/reagents/chemistry/reagents/blob_reagents.dm
+++ /dev/null
@@ -1,487 +0,0 @@
-// These can only be applied by blobs. They are what blobs are made out of.
-/datum/reagent/blob
- name = "Unknown"
- description = "shouldn't exist and you should adminhelp immediately."
- color = "#FFFFFF"
- taste_description = "bad code and slime"
- var/complementary_color = "#000000" //a color that's complementary to the normal blob color
- var/shortdesc = null //just damage and on_mob effects, doesn't include special, blob-tile only effects
- var/effectdesc = null //any long, blob-tile specific effects
- var/analyzerdescdamage = "Unknown. Report this bug to a coder, or just adminhelp."
- var/analyzerdesceffect = "N/A"
- var/blobbernaut_message = "slams" //blobbernaut attack verb
- var/message = "The blob strikes you" //message sent to any mob hit by the blob
- var/message_living = null //extension to first mob sent to only living mobs i.e. silicons have no skin to be burnt
- can_synth = FALSE
-
-/datum/reagent/blob/proc/send_message(mob/living/M)
- var/totalmessage = message
- if(message_living && !issilicon(M))
- totalmessage += message_living
- totalmessage += "!"
- to_chat(M, "[totalmessage]")
-
-/datum/reagent/blob/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- if(M.stat == DEAD || istype(M, /mob/living/simple_animal/hostile/blob))
- return 0 //the dead, and blob mobs, don't cause reactions
- return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume.
-
-/datum/reagent/blob/proc/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag) //when the blob takes damage, do this
- return damage
-
-/datum/reagent/blob/proc/death_reaction(obj/structure/blob/B, damage_flag) //when a blob dies, do this
- return
-
-/datum/reagent/blob/proc/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O) //when the blob expands, do this
- return
-
-/datum/reagent/blob/proc/tesla_reaction(obj/structure/blob/B, power) //when the blob is hit by a tesla bolt, do this
- return 1 //return 0 to ignore damage
-
-/datum/reagent/blob/proc/extinguish_reaction(obj/structure/blob/B) //when the blob is hit with water, do this
- return
-
-/datum/reagent/blob/proc/emp_reaction(obj/structure/blob/B, severity) //when the blob is hit with an emp, do this
- return
-
-//does brute damage but can replicate when damaged and has a chance of expanding again
-/datum/reagent/blob/replicating_foam
- name = "Replicating Foam"
- description = "will do medium brute damage and occasionally expand again when expanding."
- shortdesc = "will do medium brute damage."
- effectdesc = "will also expand when attacked with burn damage, but takes more brute damage."
- taste_description = "duplication"
- analyzerdescdamage = "Does medium brute damage."
- analyzerdesceffect = "Expands when attacked with burn damage, will occasionally expand again when expanding, and is fragile to brute damage."
- color = "#7B5A57"
- complementary_color = "#57787B"
-
-/datum/reagent/blob/replicating_foam/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.apply_damage(0.7*reac_volume, BRUTE)
-
-/datum/reagent/blob/replicating_foam/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if(damage_type == BRUTE)
- damage = damage * 2
- else if(damage_type == BURN && damage > 0 && B.obj_integrity - damage > 0 && prob(60))
- var/obj/structure/blob/newB = B.expand(null, null, 0)
- if(newB)
- newB.obj_integrity = B.obj_integrity - damage
- newB.update_icon()
- return ..()
-
-/datum/reagent/blob/replicating_foam/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
- if(prob(30))
- newB.expand(null, null, 0) //do it again!
-
-//does massive brute and burn damage, but can only expand manually
-/datum/reagent/blob/networked_fibers
- name = "Networked Fibers"
- description = "will do high brute and burn damage and will generate resources quicker, but can only expand manually."
- shortdesc = "will do high brute and burn damage."
- taste_description = "efficiency"
- effectdesc = "will move your core when manually expanding near it."
- analyzerdescdamage = "Does high brute and burn damage."
- analyzerdesceffect = "Is highly mobile and generates resources rapidly."
- color = "#CDC0B0"
- complementary_color = "#FFF68F"
-
-/datum/reagent/blob/networked_fibers/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.apply_damage(0.6*reac_volume, BRUTE)
- if(M)
- M.apply_damage(0.6*reac_volume, BURN)
-
-/datum/reagent/blob/networked_fibers/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
- if(!O && newB.overmind)
- if(!istype(B, /obj/structure/blob/node))
- newB.overmind.add_points(1)
- qdel(newB)
- else
- var/area/A = get_area(T)
- if(!isspaceturf(T) && !istype(A, /area/shuttle))
- for(var/obj/structure/blob/core/C in range(1, newB))
- if(C.overmind == O)
- newB.forceMove(get_turf(C))
- C.forceMove(T)
- C.setDir(get_dir(newB, C))
- O.add_points(1)
-
-//does brute damage, shifts away when damaged
-/datum/reagent/blob/shifting_fragments
- name = "Shifting Fragments"
- description = "will do medium brute damage."
- effectdesc = "will also cause blob parts to shift away when attacked."
- taste_description = "something other-dimensional"
- analyzerdescdamage = "Does medium brute damage."
- analyzerdesceffect = "When attacked, may shift away from the attacker."
- color = "#C8963C"
- complementary_color = "#3C6EC8"
-
-/datum/reagent/blob/shifting_fragments/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.apply_damage(0.7*reac_volume, BRUTE)
-
-/datum/reagent/blob/shifting_fragments/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
- if(istype(B, /obj/structure/blob/normal) || (istype(B, /obj/structure/blob/shield) && prob(25)))
- newB.forceMove(get_turf(B))
- B.forceMove(T)
-
-/datum/reagent/blob/shifting_fragments/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage > 0 && B.obj_integrity - damage > 0 && prob(60-damage))
- var/list/blobstopick = list()
- for(var/obj/structure/blob/OB in orange(1, B))
- if((istype(OB, /obj/structure/blob/normal) || (istype(OB, /obj/structure/blob/shield) && prob(25))) && OB.overmind && OB.overmind.blob_reagent_datum.type == B.overmind.blob_reagent_datum.type)
- blobstopick += OB //as long as the blob picked is valid; ie, a normal or shield blob that has the same chemical as we do, we can swap with it
- if(blobstopick.len)
- var/obj/structure/blob/targeted = pick(blobstopick) //randomize the blob chosen, because otherwise it'd tend to the lower left
- var/turf/T = get_turf(targeted)
- targeted.forceMove(get_turf(B))
- B.forceMove(T) //swap the blobs
- return ..()
-
-//sets you on fire, does burn damage, explodes into flame when burnt, weak to water
-/datum/reagent/blob/blazing_oil
- name = "Blazing Oil"
- description = "will do medium burn damage and set targets on fire."
- effectdesc = "will also release bursts of flame when burnt, but takes damage from water."
- taste_description = "burning oil"
- analyzerdescdamage = "Does medium burn damage and sets targets on fire."
- analyzerdesceffect = "Releases fire when burnt, but takes damage from water and other extinguishing liquids."
- color = "#B68D00"
- complementary_color = "#BE5532"
- blobbernaut_message = "splashes"
- message = "The blob splashes you with burning oil"
- message_living = ", and you feel your skin char and melt"
-
-/datum/reagent/blob/blazing_oil/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.adjust_fire_stacks(round(reac_volume/10))
- M.IgniteMob()
- if(M)
- M.apply_damage(0.8*reac_volume, BURN)
- if(iscarbon(M))
- M.emote("scream")
-
-/datum/reagent/blob/blazing_oil/extinguish_reaction(obj/structure/blob/B)
- B.take_damage(1.5, BURN, "energy")
-
-/datum/reagent/blob/blazing_oil/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if(damage_type == BURN && damage_flag != "energy")
- for(var/turf/open/T in range(1, B))
- var/obj/structure/blob/C = locate() in T
- if(!(C && C.overmind && C.overmind.blob_reagent_datum.type == B.overmind.blob_reagent_datum.type) && prob(80))
- new /obj/effect/hotspot(T)
- if(damage_flag == "fire")
- return 0
- return ..()
-
-//does toxin damage, hallucination, targets think they're not hurt at all
-/datum/reagent/blob/regenerative_materia
- name = "Regenerative Materia"
- description = "will do toxin damage and cause targets to believe they are fully healed."
- analyzerdescdamage = "Does toxin damage and injects a toxin that causes the target to believe they are fully healed."
- taste_description = "heaven"
- color = "#5e7842"
- complementary_color = "#CD7794"
- message_living = ", and you feel alive"
-
-/datum/reagent/blob/regenerative_materia/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.adjust_drugginess(reac_volume)
- if(M.reagents)
- M.reagents.add_reagent(/datum/reagent/blob/regenerative_materia, 0.2*reac_volume)
- M.reagents.add_reagent(/datum/reagent/toxin/spore, 0.2*reac_volume)
- M.apply_damage(0.7*reac_volume, TOX)
-
-/datum/reagent/blob/regenerative_materia/on_mob_life(mob/living/carbon/C)
- C.adjustToxLoss(1*REM)
- C.hal_screwyhud = SCREWYHUD_HEALTHY //fully healed, honest
- ..()
-
-/datum/reagent/blob/regenerative_materia/on_mob_end_metabolize(mob/living/M)
- if(iscarbon(M))
- var/mob/living/carbon/N = M
- N.hal_screwyhud = 0
- ..()
-
-//kills sleeping targets and turns them into blob zombies, produces fragile spores when killed or on expanding
-/datum/reagent/blob/zombifying_pods
- name = "Zombifying Pods"
- description = "will do very low toxin damage and harvest sleeping targets for additional resources and a blob zombie."
- effectdesc = "will also produce fragile spores when killed and on expanding."
- taste_description = "fungi"
- shortdesc = "will do very low toxin damage and harvest sleeping targets for additional resources(for your overmind) and a blob zombie."
- analyzerdescdamage = "Does very low toxin damage and kills unconscious humans, turning them into blob zombies."
- analyzerdesceffect = "Produces spores when expanding and when killed."
- color = "#E88D5D"
- complementary_color = "#823ABB"
- message_living = ", and you feel tired"
-
-/datum/reagent/blob/zombifying_pods/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.apply_damage(0.6*reac_volume, TOX)
- if(O && ishuman(M) && M.stat == UNCONSCIOUS)
- M.death() //sleeping in a fight? bad plan.
- var/points = rand(5, 10)
- var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M))
- BS.overmind = O
- BS.update_icons()
- O.blob_mobs.Add(BS)
- BS.Zombify(M)
- O.add_points(points)
- to_chat(O, "Gained [points] resources from the zombification of [M].")
-
-/datum/reagent/blob/zombifying_pods/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage <= 20 && B.obj_integrity - damage <= 0 && prob(30)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 20% chance of a shitty spore.
- B.visible_message("A spore floats free of the blob!")
- var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc)
- BS.overmind = B.overmind
- BS.update_icons()
- B.overmind.blob_mobs.Add(BS)
- return ..()
-
-/datum/reagent/blob/zombifying_pods/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
- if(prob(10))
- var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(T)
- BS.overmind = B.overmind
- BS.update_icons()
- newB.overmind.blob_mobs.Add(BS)
-
-//does tons of oxygen damage and a little stamina, immune to tesla bolts, weak to EMP
-/datum/reagent/blob/energized_jelly
- name = "Energized Jelly"
- description = "will cause low stamina and high oxygen damage, and cause targets to be unable to breathe."
- taste_description = "gelatin"
- effectdesc = "will also conduct electricity, but takes damage from EMPs."
- analyzerdescdamage = "Does low stamina damage, high oxygen damage, and prevents targets from breathing."
- analyzerdesceffect = "Is immune to electricity and will easily conduct it, but is weak to EMPs."
- color = "#EFD65A"
- complementary_color = "#00E5B1"
- message_living = ", and you feel a horrible tingling sensation"
-
-/datum/reagent/blob/energized_jelly/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.losebreath += round(0.2*reac_volume)
- M.adjustStaminaLoss(0.4*reac_volume)
- if(M)
- M.apply_damage(0.6*reac_volume, OXY)
-
-/datum/reagent/blob/energized_jelly/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && B.obj_integrity - damage <= 0 && prob(10))
- do_sparks(rand(2, 4), FALSE, B)
- return ..()
-
-/datum/reagent/blob/energized_jelly/tesla_reaction(obj/structure/blob/B, power)
- return 0
-
-/datum/reagent/blob/energized_jelly/emp_reaction(obj/structure/blob/B, severity)
- var/damage = rand(30, 50) - severity * rand(10, 15)
- B.take_damage(damage, BURN, "energy")
-
-//does aoe brute damage when hitting targets, is immune to explosions
-/datum/reagent/blob/explosive_lattice
- name = "Explosive Lattice"
- description = "will do brute damage in an area around targets."
- taste_description = "the bomb"
- effectdesc = "will also resist explosions, but takes increased damage from fire and other energy sources."
- analyzerdescdamage = "Does medium brute damage and causes damage to everyone near its targets."
- analyzerdesceffect = "Is highly resistant to explosions, but takes increased damage from fire and other energy sources."
- color = "#8B2500"
- complementary_color = "#00668B"
- blobbernaut_message = "blasts"
- message = "The blob blasts you"
-
-/datum/reagent/blob/explosive_lattice/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- var/initial_volume = reac_volume
- reac_volume = ..()
- if(reac_volume >= 10) //if it's not a spore cloud, bad time incoming
- var/obj/effect/temp_visual/explosion/fast/E = new /obj/effect/temp_visual/explosion/fast(get_turf(M))
- E.alpha = 150
- for(var/mob/living/L in orange(get_turf(M), 1))
- if(ROLE_BLOB in L.faction) //no friendly fire
- continue
- var/aoe_volume = ..(L, TOUCH, initial_volume, 0, L.get_permeability_protection(), O)
- L.apply_damage(0.4*aoe_volume, BRUTE)
- if(M)
- M.apply_damage(0.6*reac_volume, BRUTE)
- else
- M.apply_damage(0.6*reac_volume, BRUTE)
-
-/datum/reagent/blob/explosive_lattice/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if(damage_flag == "bomb")
- return 0
- else if(damage_flag != "melee" && damage_flag != "bullet" && damage_flag != "laser")
- return damage * 1.5
- return ..()
-
-//does brute, burn, and toxin damage, and cools targets down
-/datum/reagent/blob/cryogenic_poison
- name = "Cryogenic Poison"
- description = "will inject targets with a freezing poison that does high damage over time."
- analyzerdescdamage = "Injects targets with a freezing poison that will gradually solidify the target's internal organs."
- color = "#8BA6E9"
- taste_description = "brain freeze"
- complementary_color = "#7D6EB4"
- blobbernaut_message = "injects"
- message = "The blob stabs you"
- message_living = ", and you feel like your insides are solidifying"
-
-/datum/reagent/blob/cryogenic_poison/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- if(M.reagents)
- M.reagents.add_reagent(/datum/reagent/consumable/frostoil, 0.3*reac_volume)
- M.reagents.add_reagent(/datum/reagent/consumable/ice, 0.3*reac_volume)
- M.reagents.add_reagent(/datum/reagent/blob/cryogenic_poison, 0.3*reac_volume)
- M.apply_damage(0.2*reac_volume, BRUTE)
-
-/datum/reagent/blob/cryogenic_poison/on_mob_life(mob/living/carbon/M)
- M.adjustBruteLoss(0.3*REM, 0)
- M.adjustFireLoss(0.3*REM, 0)
- M.adjustToxLoss(0.3*REM, 0)
- . = 1
- ..()
-
-//does burn damage and EMPs, slightly fragile
-/datum/reagent/blob/electromagnetic_web
- name = "Electromagnetic Web"
- description = "will do high burn damage and EMP targets."
- taste_description = "pop rocks"
- effectdesc = "will also take massively increased damage and release an EMP when killed."
- analyzerdescdamage = "Does low burn damage and EMPs targets."
- analyzerdesceffect = "Is fragile to all types of damage, but takes massive damage from brute. In addition, releases a small EMP when killed."
- color = "#83ECEC"
- complementary_color = "#EC8383"
- blobbernaut_message = "lashes"
- message = "The blob lashes you"
- message_living = ", and you hear a faint buzzing"
-
-/datum/reagent/blob/electromagnetic_web/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- if(prob(reac_volume*2))
- M.emp_act(EMP_LIGHT)
- if(M)
- M.apply_damage(reac_volume, BURN)
-
-/datum/reagent/blob/electromagnetic_web/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if(damage_type == BRUTE) //take full brute
- switch(B.brute_resist)
- if(0.5)
- return damage * 2
- if(0.25)
- return damage * 4
- if(0.1)
- return damage * 10
- return damage * 1.25 //a laser will do 25 damage, which will kill any normal blob
-
-/datum/reagent/blob/electromagnetic_web/death_reaction(obj/structure/blob/B, damage_flag)
- if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser")
- empulse(B.loc, 1, 3) //less than screen range, so you can stand out of range to avoid it
-
-//does brute damage, bonus damage for each nearby blob, and spreads damage out
-/datum/reagent/blob/synchronous_mesh
- name = "Synchronous Mesh"
- description = "will do massively increased brute damage for each blob near the target."
- effectdesc = "will also spread damage between each blob near the attacked blob."
- taste_description = "toxic mold"
- analyzerdescdamage = "Does brute damage, increasing for each blob near the target."
- analyzerdesceffect = "When attacked, spreads damage between all blobs near the attacked blob."
- color = "#65ADA2"
- complementary_color = "#AD6570"
- blobbernaut_message = "synchronously strikes"
- message = "The blobs strike you"
-
-/datum/reagent/blob/synchronous_mesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- M.apply_damage(0.2*reac_volume, BRUTE)
- if(M && reac_volume)
- for(var/obj/structure/blob/B in range(1, M)) //if the target is completely surrounded, this is 2.4*reac_volume bonus damage, total of 2.6*reac_volume
- if(M)
- B.blob_attack_animation(M) //show them they're getting a bad time
- M.apply_damage(0.3*reac_volume, BRUTE)
-
-/datum/reagent/blob/synchronous_mesh/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") //the cause isn't fire or bombs, so split the damage
- var/damagesplit = 1 //maximum split is 9, reducing the damage each blob takes to 11% but doing that damage to 9 blobs
- for(var/obj/structure/blob/C in orange(1, B))
- if(!istype(C, /obj/structure/blob/core) && !istype(C, /obj/structure/blob/node) && C.overmind && C.overmind.blob_reagent_datum.type == B.overmind.blob_reagent_datum.type) //if it doesn't have the same chemical or is a core or node, don't split damage to it
- damagesplit += 1
- for(var/obj/structure/blob/C in orange(1, B))
- if(!istype(C, /obj/structure/blob/core) && !istype(C, /obj/structure/blob/node) && C.overmind && C.overmind.blob_reagent_datum.type == B.overmind.blob_reagent_datum.type) //only hurt blobs that have the same overmind chemical and aren't cores or nodes
- C.take_damage(damage/damagesplit, CLONE, 0, 0)
- return damage / damagesplit
- else
- return damage * 1.25
-
-//does brute damage through armor and bio resistance
-/datum/reagent/blob/reactive_spines
- name = "Reactive Spines"
- description = "will do medium brute damage through armor and bio resistance."
- taste_description = "rock"
- effectdesc = "will also react when attacked with brute damage, attacking all near the attacked blob."
- analyzerdescdamage = "Does medium brute damage, ignoring armor and bio resistance."
- analyzerdesceffect = "When attacked with brute damage, will lash out, attacking everything near it."
- color = "#9ACD32"
- complementary_color = "#FFA500"
- blobbernaut_message = "stabs"
- message = "The blob stabs you"
-
-/datum/reagent/blob/reactive_spines/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- if(M.stat == DEAD || istype(M, /mob/living/simple_animal/hostile/blob))
- return 0 //the dead, and blob mobs, don't cause reactions
- M.adjustBruteLoss(0.8*reac_volume)
-
-/datum/reagent/blob/reactive_spines/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if(damage && damage_type == BRUTE && B.obj_integrity - damage > 0) //is there any damage, is it brute, and will we be alive
- if(damage_flag == "melee")
- B.visible_message("The blob retaliates, lashing out!")
- for(var/atom/A in range(1, B))
- A.blob_act(B)
- return ..()
-
-//does low brute damage, oxygen damage, and stamina damage and wets tiles when damaged
-/datum/reagent/blob/pressurized_slime
- name = "Pressurized Slime"
- description = "will do low brute, oxygen, and stamina damage, and wet tiles under targets."
- effectdesc = "will also wet tiles near blobs that are attacked or killed."
- taste_description = "a sponge"
- analyzerdescdamage = "Does low brute damage, low oxygen damage, drains stamina, and wets tiles under targets, extinguishing them."
- analyzerdesceffect = "When attacked or killed, wets nearby tiles, extinguishing anything on them."
- color = "#AAAABB"
- complementary_color = "#BBBBAA"
- blobbernaut_message = "emits slime at"
- message = "The blob splashes into you"
- message_living = ", and you gasp for breath"
-
-/datum/reagent/blob/pressurized_slime/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
- reac_volume = ..()
- var/turf/open/T = get_turf(M)
- if(istype(T) && prob(reac_volume))
- T.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
- M.adjust_fire_stacks(-(reac_volume / 10))
- M.ExtinguishMob()
- M.apply_damage(0.4*reac_volume, BRUTE)
- if(M)
- M.apply_damage(0.4*reac_volume, OXY)
- if(M)
- M.adjustStaminaLoss(0.2*reac_volume)
-
-/datum/reagent/blob/pressurized_slime/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
- if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") || damage_type != BURN)
- extinguisharea(B, damage)
- return ..()
-
-/datum/reagent/blob/pressurized_slime/death_reaction(obj/structure/blob/B, damage_flag)
- if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser")
- B.visible_message("The blob ruptures, spraying the area with liquid!")
- extinguisharea(B, 50)
-
-/datum/reagent/blob/pressurized_slime/proc/extinguisharea(obj/structure/blob/B, probchance)
- for(var/turf/open/T in range(1, B))
- if(prob(probchance))
- T.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
- for(var/obj/O in T)
- O.extinguish()
- for(var/mob/living/L in T)
- L.adjust_fire_stacks(-2.5)
- L.ExtinguishMob()
diff --git a/tgstation.dme b/tgstation.dme
index 1fe4fe9ce1..cd0e1a333d 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1300,6 +1300,22 @@
#include "code\modules\antagonists\blob\blob\blobs\node.dm"
#include "code\modules\antagonists\blob\blob\blobs\resource.dm"
#include "code\modules\antagonists\blob\blob\blobs\shield.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\_blobstrain.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\_reagent.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\blazing_oil.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\cryogenic_poison.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\electromagnetic_web.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\energized_jelly.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\explosive_lattice.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\multiplex.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\networked_fibers.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\pressurized_slime.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\reactive_spines.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\regenerative_materia.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\replicating_foam.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\shifting_fragments.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\synchronous_mesh.dm"
+#include "code\modules\antagonists\blob\blob\blobstrains\zombifying_pods.dm"
#include "code\modules\antagonists\blood_contract\blood_contract.dm"
#include "code\modules\antagonists\bloodsucker\bloodsucker_flaws.dm"
#include "code\modules\antagonists\bloodsucker\bloodsucker_integration.dm"
@@ -2759,7 +2775,6 @@
#include "code\modules\reagents\chemistry\machinery\reagentgrinder.dm"
#include "code\modules\reagents\chemistry\machinery\smoke_machine.dm"
#include "code\modules\reagents\chemistry\reagents\alcohol_reagents.dm"
-#include "code\modules\reagents\chemistry\reagents\blob_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\drink_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\drug_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\food_reagents.dm"