Roundstart blob removal attempt 3 (#20403)

This commit is contained in:
GDN
2023-03-23 11:27:22 +00:00
committed by GitHub
parent 5c9d20f65f
commit 22efb88e45
22 changed files with 102 additions and 361 deletions
+1 -13
View File
@@ -412,22 +412,10 @@
dat += "<tr><td><i>Head not found!</i></td></tr>"
dat += "</table>"
if(GAMEMODE_IS_BLOB)
var/datum/game_mode/blob/mode = SSticker.mode
dat += "<br><table cellspacing=5><tr><td><B>Blob</B></td><td></td><td></td></tr>"
dat += "<tr><td><i>Progress: [GLOB.blobs.len]/[mode.blobwincount]</i></td></tr>"
for(var/datum/mind/blob in mode.infected_crew)
var/mob/M = blob.current
if(M)
dat += "<tr><td>[ADMIN_PP(M,"[M.real_name]")][M.client ? "" : " <i>(ghost)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.client?.ckey]'>PM</A> [ADMIN_FLW(M, "FLW")]</td>"
else
dat += "<tr><td><i>Blob not found!</i></td></tr>"
dat += "</table>"
if(SSticker.mode.blob_overminds.len)
dat += check_role_table("Blob Overminds", SSticker.mode.blob_overminds)
dat += "<i>Blob Tiles: [length(GLOB.blobs)]</i>"
if(SSticker.mode.changelings.len)
dat += check_role_table("Changelings", SSticker.mode.changelings)
+234
View File
@@ -0,0 +1,234 @@
////////////////
// BASE TYPE //
////////////////
//Do not spawn
/mob/living/simple_animal/hostile/blob
icon = 'icons/mob/blob.dmi'
pass_flags = PASSBLOB
status_flags = NONE //No throwing blobspores into deep space to despawn, or throwing blobbernaughts, which are bigger than you.
faction = list(ROLE_BLOB)
bubble_icon = "blob"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 360
universal_speak = TRUE //So mobs can understand them when a blob uses Blob Broadcast
sentience_type = SENTIENCE_OTHER
gold_core_spawnable = NO_SPAWN
can_be_on_fire = TRUE
fire_damage = 3
var/mob/camera/blob/overmind = null
/mob/living/simple_animal/hostile/blob/proc/adjustcolors(a_color)
if(a_color)
color = a_color
/mob/living/simple_animal/hostile/blob/blob_act()
if(stat != DEAD && health < maxHealth)
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
if(H.color == COMPLEMENTARY_COLOR_RIPPING_TENDRILS) //the colour define for ripping tendrils
H.color = COLOR_HEALING_GREEN //bye red cross
else
H.color = COLOR_BLACK
adjustHealth(-maxHealth * 0.0125)
/mob/living/simple_animal/hostile/blob/Process_Spacemove(movement_dir = 0)
// Use any nearby blob structures to allow space moves.
for(var/obj/structure/blob/B in range(1, src))
return TRUE
return ..()
////////////////
// BLOB SPORE //
////////////////
/mob/living/simple_animal/hostile/blob/blobspore
name = "blob"
desc = "Some blob thing."
icon_state = "blobpod"
icon_living = "blobpod"
health = 40
maxHealth = 40
melee_damage_lower = 2
melee_damage_upper = 4
obj_damage = 20
environment_smash = ENVIRONMENT_SMASH_STRUCTURES
attacktext = "hits"
attack_sound = 'sound/weapons/genhit1.ogg'
flying = TRUE
speak_emote = list("pulses")
var/obj/structure/blob/factory/factory = null
var/list/human_overlays = list()
var/mob/living/carbon/human/oldguy
var/is_zombie = FALSE
/mob/living/simple_animal/hostile/blob/blobspore/CanPass(atom/movable/mover, turf/target, height=0)
if(istype(mover, /obj/structure/blob))
return 1
return ..()
/mob/living/simple_animal/hostile/blob/blobspore/Initialize(mapload, obj/structure/blob/factory/linked_node)
. = ..()
if(istype(linked_node))
factory = linked_node
factory.spores += src
/mob/living/simple_animal/hostile/blob/blobspore/Life(seconds, times_fired)
if(!is_zombie && isturf(src.loc))
for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
Zombify(H)
break
..()
/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H)
if(!H.check_death_method())
H.death()
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor.getRating(MELEE))
maxHealth += A.armor.getRating(MELEE) //That zombie's got armor, I want armor!
maxHealth += 40
health = maxHealth
name = "blob zombie"
desc = "A shambling corpse animated by the blob."
mob_biotypes |= MOB_HUMANOID
melee_damage_lower = 10
melee_damage_upper = 15
icon = H.icon
speak_emote = list("groans")
icon_state = "zombie2_s"
if(head_organ && !(NO_HAIR in H.dna.species.species_traits))
head_organ.h_style = null
H.update_hair()
human_overlays = H.overlays
update_icons()
H.forceMove(src)
oldguy = H
visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
// Only execute the below if we successfuly died
. = ..()
if(!.)
return FALSE
// On death, create a small smoke of harmful gas (s-Acid)
var/datum/effect_system/smoke_spread/chem/S = new
var/turf/location = get_turf(src)
// Create the reagents to put into the air
create_reagents(8)
if(overmind && overmind.blob_reagent_datum)
reagents.add_reagent(overmind.blob_reagent_datum.id, 8)
else
reagents.add_reagent("spore", 8)
// Setup up the smoke spreader and start it.
S.set_up(reagents, location, TRUE)
S.start()
qdel(src)
/mob/living/simple_animal/hostile/blob/blobspore/Destroy()
if(factory)
factory.spores -= src
factory = null
if(oldguy)
oldguy.forceMove(get_turf(src))
oldguy = null
return ..()
/mob/living/simple_animal/hostile/blob/blobspore/update_icons()
..()
adjustcolors(overmind?.blob_reagent_datum?.complementary_color)
/mob/living/simple_animal/hostile/blob/blobspore/adjustcolors(a_color)
color = a_color
if(is_zombie)
overlays.Cut()
overlays = human_overlays
var/image/I = image('icons/mob/blob.dmi', icon_state = "blob_head")
I.color = color
overlays += I
/////////////////
// BLOBBERNAUT //
/////////////////
/mob/living/simple_animal/hostile/blob/blobbernaut
name = "blobbernaut"
desc = "Some HUGE blob thing."
icon_state = "blobbernaut"
icon_living = "blobbernaut"
icon_dead = "blobbernaut_dead"
health = 200
maxHealth = 200
melee_damage_lower = 10
melee_damage_upper = 15
obj_damage = 60
attacktext = "hits"
attack_sound = 'sound/effects/blobattack.ogg'
speak_emote = list("gurgles")
minbodytemp = 0
maxbodytemp = 360
force_threshold = 10
mob_size = MOB_SIZE_LARGE
environment_smash = ENVIRONMENT_SMASH_STRUCTURES
pressure_resistance = 50
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
move_resist = MOVE_FORCE_OVERPOWERING
a_intent = INTENT_HARM
/mob/living/simple_animal/hostile/blob/blobbernaut/Life(seconds, times_fired)
if(stat != DEAD && (getBruteLoss() || getFireLoss())) // Heal on blob structures
if(locate(/obj/structure/blob) in get_turf(src))
adjustBruteLoss(-0.25)
adjustFireLoss(-0.25)
if(on_fire)
adjust_fire_stacks(-1) // Slowly extinguish the flames
else
adjustBruteLoss(0.2) // If you are at full health, you won't lose health. You'll need it. However the moment anybody sneezes on you, the decaying will begin.
adjustFireLoss(0.2)
..()
/mob/living/simple_animal/hostile/blob/blobbernaut/Initialize(mapload)
. = ..()
if(name == "blobbernaut")
name = text("blobbernaut ([rand(1, 1000)])")
/mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
flick("blobbernaut_death", src)
/mob/living/simple_animal/hostile/blob/blobbernaut/verb/communicate_overmind()
set category = "Blobbernaut"
set name = "Blob Telepathy"
set desc = "Send a message to the Overmind"
if(stat != DEAD)
blob_talk()
/mob/living/simple_animal/hostile/blob/blobbernaut/proc/blob_talk()
var/message = input(src, "Announce to the overmind", "Blob Telepathy")
var/rendered
var/follow_text
if(message)
for(var/mob/M in GLOB.mob_list)
follow_text = isobserver(M) ? " ([ghost_follow_link(src, ghost = M)])" : ""
rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]([overmind])</span>[follow_text] <span class='message'>states, \"[message]\"</span></span></i></font>"
if(isovermind(M) || isobserver(M) || istype(M, /mob/living/simple_animal/hostile/blob/blobbernaut))
M.show_message(rendered, EMOTE_AUDIBLE)
+494
View File
@@ -0,0 +1,494 @@
// Point controlling procs
/mob/camera/blob/proc/can_buy(cost = 15)
if(blob_points < cost)
to_chat(src, "<span class='warning'>You cannot afford this!</span>")
return 0
add_points(-cost)
return 1
// Power verbs
/mob/camera/blob/verb/transport_core()
set category = "Blob"
set name = "Jump to Core"
set desc = "Transport back to your core."
if(blob_core)
src.loc = blob_core.loc
/mob/camera/blob/verb/jump_to_node()
set category = "Blob"
set name = "Jump to Node"
set desc = "Transport back to a selected node."
if(GLOB.blob_nodes.len)
var/list/nodes = list()
for(var/i = 1; i <= GLOB.blob_nodes.len; i++)
var/obj/structure/blob/node/B = GLOB.blob_nodes[i]
nodes["Blob Node #[i] ([get_location_name(B)])"] = 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)
src.loc = chosen_node.loc
/mob/camera/blob/verb/toggle_node_req()
set category = "Blob"
set name = "Toggle Node Requirement"
set desc = "Toggle requiring nodes to place resource and factory blobs."
nodes_required = !nodes_required
if(nodes_required)
to_chat(src, "<span class='warning'>You now require a nearby node or core to place factory and resource blobs.</span>")
else
to_chat(src, "<span class='warning'>You no longer require a nearby node or core to place factory and resource blobs.</span>")
/mob/camera/blob/verb/create_shield_power()
set category = "Blob"
set name = "Create/Upgrade Shield Blob (15)"
set desc = "Create/Upgrade a shield blob. Using this on an existing shield blob turns it into a reflective blob, capable of reflecting most energy projectiles but making it much weaker than usual to brute attacks."
var/turf/T = get_turf(src)
create_shield(T)
/mob/camera/blob/proc/create_shield(turf/T)
var/obj/structure/blob/B = locate(/obj/structure/blob) in T
var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T
if(!S)
if(!B)//We are on a blob
to_chat(src, "There is no blob here!")
return
else if(!istype(B, /obj/structure/blob/normal))
to_chat(src, "Unable to use this blob, find a normal one.")
return
else if(!can_buy(15))
return
B.color = blob_reagent_datum.color
B.change_to(/obj/structure/blob/shield)
else
if(istype(S, /obj/structure/blob/shield/reflective))
to_chat(src, "<span class='warning'>There's already a reflector blob here!</span>")
return
else if(S.obj_integrity < S.max_integrity * 0.5)
to_chat(src, "<span class='warning'>This shield blob is too damaged to be modified properly!</span>")
return
else if (!can_buy(15))
return
to_chat(src, "<span class='warning'>You secrete a reflective ooze over the shield blob, allowing it to reflect energy projectiles at the cost of reduced intregrity.</span>")
S.change_to(/obj/structure/blob/shield/reflective)
S.color = blob_reagent_datum.color
return
/mob/camera/blob/verb/create_resource()
set category = "Blob"
set name = "Create Resource Blob (40)"
set desc = "Create a resource tower which will generate points for you."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/structure/blob/B = (locate(/obj/structure/blob) in T)
if(!B)//We are on a blob
to_chat(src, "There is no blob here!")
return
if(!istype(B, /obj/structure/blob/normal))
to_chat(src, "Unable to use this blob, find a normal one.")
return
for(var/obj/structure/blob/resource/blob in orange(4, T))
to_chat(src, "There is a resource blob nearby, move more than 4 tiles away from it!")
return
if(nodes_required)
if(!(locate(/obj/structure/blob/node) in orange(3, T)) && !(locate(/obj/structure/blob/core) in orange(4, T)))
to_chat(src, "<span class='warning'>You need to place this blob closer to a node or core!</span>")
return //handholdotron 2000
if(!can_buy(40))
return
B.color = blob_reagent_datum.color
B.change_to(/obj/structure/blob/resource)
var/obj/structure/blob/resource/R = locate() in T
if(R)
R.overmind = src
return
/mob/camera/blob/verb/create_node()
set category = "Blob"
set name = "Create Node Blob (60)"
set desc = "Create a Node."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/structure/blob/B = (locate(/obj/structure/blob) in T)
if(!B)//We are on a blob
to_chat(src, "There is no blob here!")
return
if(!istype(B, /obj/structure/blob/normal))
to_chat(src, "Unable to use this blob, find a normal one.")
return
for(var/obj/structure/blob/node/blob in orange(5, T))
to_chat(src, "There is another node nearby, move more than 5 tiles away from it!")
return
if(!can_buy(60))
return
B.change_to(/obj/structure/blob/node)
var/obj/structure/blob/node/R = locate() in T
if(R)
R.adjustcolors(blob_reagent_datum.color)
R.overmind = src
return
/mob/camera/blob/verb/create_factory()
set category = "Blob"
set name = "Create Factory Blob (60)"
set desc = "Create a Spore producing blob."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/structure/blob/B = locate(/obj/structure/blob) in T
if(!B)
to_chat(src, "You must be on a blob!")
return
if(!istype(B, /obj/structure/blob/normal))
to_chat(src, "Unable to use this blob, find a normal one.")
return
for(var/obj/structure/blob/factory/blob in orange(7, T))
to_chat(src, "There is a factory blob nearby, move more than 7 tiles away from it!")
return
if(nodes_required)
if(!(locate(/obj/structure/blob/node) in orange(3, T)) && !(locate(/obj/structure/blob/core) in orange(4, T)))
to_chat(src, "<span class='warning'>You need to place this blob closer to a node or core!</span>")
return //handholdotron 2000
if(!can_buy(60))
return
B.change_to(/obj/structure/blob/factory)
B.color = blob_reagent_datum.color
var/obj/structure/blob/factory/R = locate() in T
if(R)
R.overmind = src
return
/mob/camera/blob/verb/create_blobbernaut()
set category = "Blob"
set name = "Create Blobbernaut (60)"
set desc = "Create a powerful blob-being, a Blobbernaut"
var/turf/T = get_turf(src)
if(!T)
return
var/obj/structure/blob/B = locate(/obj/structure/blob) in T
if(!B)
to_chat(src, "You must be on a blob!")
return
if(!istype(B, /obj/structure/blob/factory))
to_chat(src, "Unable to use this blob, find a factory blob.")
return
if(!can_buy(60))
return
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut (get_turf(B))
if(blobber)
qdel(B)
add_mob_to_overmind(blobber)
blobber.AIStatus = AI_OFF
blobber.LoseTarget()
spawn()
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blobbernaut?", ROLE_BLOB, TRUE, 10 SECONDS, source = blobber, role_cleanname = "blobbernaut")
if(length(candidates) && !QDELETED(blobber))
var/mob/C = pick(candidates)
if(C)
blobber.key = C.key
to_chat(blobber, "<span class='biggerdanger'>You are a blobbernaut! You must assist all blob lifeforms in their mission to consume everything!</span>")
to_chat(blobber, "<span class='danger'>You heal while standing on blob structures, however you will decay slowly if you are damaged outside of the blob.</span>")
if(!blobber.ckey)
blobber.AIStatus = AI_ON
return
/mob/camera/blob/verb/relocate_core()
set category = "Blob"
set name = "Relocate Core (80)"
set desc = "Relocates your core to the node you are on, your old core will be turned into a node."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/structure/blob/node/B = locate(/obj/structure/blob/node) in T
if(!B)
to_chat(src, "You must be on a blob node!")
return
if(!can_buy(80))
return
// The old switcharoo.
var/turf/old_turf = blob_core.loc
blob_core.loc = T
B.loc = old_turf
return
/mob/camera/blob/verb/revert()
set category = "Blob"
set name = "Remove Blob"
set desc = "Removes a blob. You will receive 30% cost refund for special Blob structures."
var/turf/T = get_turf(src)
remove_blob(T)
/mob/camera/blob/proc/remove_blob(turf/T)
var/obj/structure/blob/B = locate(/obj/structure/blob) in T
if(!T)
return
if(!B)
to_chat(src, "<span class='warning'>There is no blob there!</span>")
return
if(B.point_return < 0)
to_chat(src, "<span class='warning'>Unable to remove this blob.</span>")
return
if(max_blob_points < B.point_return + blob_points)
to_chat(src, "<span class='warning'>You have too many resources to remove this blob!</span>")
return
if(B.point_return)
add_points(B.point_return)
to_chat(src, "<span class='notice'>Gained [B.point_return] resources from removing \the [B].</span>")
qdel(B)
return
/mob/camera/blob/verb/expand_blob_power()
set category = "Blob"
set name = "Expand/Attack Blob (5)"
set desc = "Attempts to create a new blob in this tile. If the tile isn't clear we will attack it, which might clear it."
var/turf/T = get_turf(src)
expand_blob(T)
/mob/camera/blob/proc/expand_blob(turf/T)
if(!T)
return
if(!can_attack())
return
var/obj/structure/blob/B = locate() in T
if(B)
var/mob/living/M = locate() in T
if(M)
if(!can_buy(5))
return
to_chat(src, "You attack [M]!")
blob_core.chemical_attack(T)
return
to_chat(src, "There is a blob here!")
return
var/obj/structure/blob/OB = locate() in circlerange(T, 1)
if(!OB)
var/obj/structure/blob/DB = locate() in range(T, 1)
if(!DB)
to_chat(src, "There is no blob adjacent to you.")
return
if(!can_buy(5))
return
DB.double_expand(T, 0, blob_reagent_datum.color, src)
DB.color = blob_reagent_datum.color
return
if(!can_buy(5))
return
last_attack = world.time
OB.expand(T, 0, blob_reagent_datum.color, src)
blob_core.chemical_attack(T)
OB.color = blob_reagent_datum.color
return
/mob/camera/blob/verb/rally_spores_power()
set category = "Blob"
set name = "Rally Spores"
set desc = "Rally the spores to move to your location."
var/turf/T = get_turf(src)
rally_spores(T)
/mob/camera/blob/proc/rally_spores(turf/T)
to_chat(src, "You rally your spores.")
var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z))
if(!surrounding_turfs.len)
return
for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in GLOB.alive_mob_list)
if(isturf(BS.loc) && get_dist(BS, T) <= 35)
BS.LoseTarget()
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
return
/mob/camera/blob/verb/split_consciousness()
set category = "Blob"
set name = "Split consciousness (100) (One use)"
set desc = "Expend resources to attempt to produce another sentient overmind."
var/turf/T = get_turf(src)
if(!T)
return
if(split_used)
to_chat(src, "<span class='warning'>You have already produced an offspring.</span>")
return
if(is_offspring)
to_chat(src, "<span class='warning'>You cannot split as an offspring of another Blob.</span>")
return
var/obj/structure/blob/N = (locate(/obj/structure/blob) in T)
if(!N)
to_chat(src, "<span class='warning'>A node is required to birth your offspring.</span>")
return
if(!istype(N, /obj/structure/blob/node))
to_chat(src, "<span class='warning'>A node is required to birth your offspring.</span>")
return
if(!can_buy(100))
return
split_used = TRUE
new /obj/structure/blob/core(get_turf(N), null, blob_core.point_rate, TRUE)
qdel(N)
/mob/camera/blob/verb/blob_broadcast()
set category = "Blob"
set name = "Blob Broadcast"
set desc = "Speak with your blob spores and blobbernauts as your mouthpieces. This action is free."
var/speak_text = clean_input("What would you like to say with your minions?", "Blob Broadcast", null)
if(!speak_text)
return
else
to_chat(usr, "You broadcast with your minions, <B>[speak_text]</B>")
for(var/mob/living/simple_animal/hostile/blob_minion in blob_mobs)
if(blob_minion.stat == CONSCIOUS)
blob_minion.say(speak_text)
return
/mob/camera/blob/verb/create_storage()
set category = "Blob"
set name = "Create Storage Blob (40)"
set desc = "Create a storage tower which will store extra resources for you. This increases your max resource cap by 50."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/structure/blob/B = (locate(/obj/structure/blob) in T)
if(!B)//We are on a blob
to_chat(src, "There is no blob here!")
return
if(!istype(B, /obj/structure/blob/normal))
to_chat(src, "Unable to use this blob, find a normal one.")
return
for(var/obj/structure/blob/storage/blob in orange(3, T))
to_chat(src, "There is a storage blob nearby, move more than 4 tiles away from it!")
return
if(!can_buy(40))
return
B.color = blob_reagent_datum.color
B.change_to(/obj/structure/blob/storage)
var/obj/structure/blob/storage/R = locate() in T
if(R)
R.overmind = src
R.update_max_blob_points(50)
return
/mob/camera/blob/verb/chemical_reroll()
set category = "Blob"
set name = "Reactive Chemical Adaptation (50)"
set desc = "Replaces your chemical with a random, different one."
if(!can_buy(50))
return
var/datum/reagent/blob/B = pick((subtypesof(/datum/reagent/blob) - blob_reagent_datum.type))
blob_reagent_datum = new B
color = blob_reagent_datum.complementary_color
for(var/obj/structure/blob/BL in GLOB.blobs)
BL.adjustcolors(blob_reagent_datum.color)
for(var/mob/living/simple_animal/hostile/blob/BLO)
BLO.adjustcolors(blob_reagent_datum.complementary_color)
to_chat(src, "Your reagent is now: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> - [blob_reagent_datum.description]")
/mob/camera/blob/verb/blob_help()
set category = "Blob"
set name = "*Blob Help*"
set desc = "Help on how to blob."
to_chat(src, "<b>As the overmind, you can control the blob!</b>")
to_chat(src, "Your blob reagent is: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> - [blob_reagent_datum.description]")
to_chat(src, "<b>You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.</b>")
to_chat(src, "<i>Normal Blobs</i> will expand your reach and can be upgraded into special blobs that perform certain functions.")
to_chat(src, "<b>You can upgrade normal blobs into the following types of blob:</b>")
to_chat(src, "<i>Shield Blobs</i> are strong and expensive blobs which take more damage. In additon, they are fireproof and can block air, use these to protect yourself from station fires. Upgrading them again will result in a <i>Reflective blob</i>, capable of reflecting laser projectiles at the cost of the strong blob's extra health.")
to_chat(src, "<i>Resource Blobs</i> are blobs which produce more resources for you, build as many of these as possible to consume the station. This type of blob must be placed near node blobs or your core to work.")
to_chat(src, "<i>Factory Blobs</i> are blobs that spawn blob spores which will attack nearby enemies. This type of blob must be placed near node blobs or your core to work.")
to_chat(src, "<i>Blobbernauts</i> can be produced from factories for a cost, and are hard to kill, powerful, but ultimately dumb. The factory used to create one will be destroyed in the process.")
to_chat(src, "<i>Storage Blobs</i> are storage towers which will store extra resources for you. This increases your max resource cap by 50.")
to_chat(src, "<i>Node Blobs</i> are blobs which grow, like the core. Like the core it can activate resource and factory blobs.")
to_chat(src, "<b>In addition to the buttons on your HUD, there are a few click shortcuts to speed up expansion and defense.</b>")
to_chat(src, "<b>Shortcuts:</b> Click = Expand Blob <b>|</b> CTRL Click = Create Shield Blob <b>|</b> Middle Mouse Click = Rally Spores <b>|</b> Alt Click = Remove Blob")
to_chat(src, "Attempting to talk will send a message to all other <b>overminds</b>, allowing you to coordinate with them.")
@@ -0,0 +1,144 @@
/obj/structure/blob/core
name = "blob core"
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
max_integrity = 400
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 75, ACID = 90)
fire_resist = 2
point_return = -1
var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 5 minutes
var/resource_delay = 0
var/point_rate = 2
var/is_offspring = null
var/selecting = 0
/obj/structure/blob/core/Initialize(mapload, client/new_overmind = null, new_rate = 2, offspring)
. = ..()
GLOB.blob_cores += src
START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
adjustcolors(color) //so it atleast appears
if(offspring)
is_offspring = TRUE
if(overmind)
adjustcolors(overmind.blob_reagent_datum.color)
if(!overmind)
create_overmind(new_overmind)
point_rate = new_rate
/obj/structure/blob/core/adjustcolors(a_color)
overlays.Cut()
color = null
var/image/I = new('icons/mob/blob.dmi', "blob")
I.color = a_color
overlays += I
var/image/C = new('icons/mob/blob.dmi', "blob_core_overlay")
overlays += C
/obj/structure/blob/core/Destroy()
GLOB.blob_cores -= src
if(overmind)
overmind.blob_core = null
overmind = null
STOP_PROCESSING(SSobj, src)
GLOB.poi_list.Remove(src)
return ..()
/obj/structure/blob/core/ex_act(severity)
var/damage = 50 - 10 * severity //remember, the core takes half brute damage, so this is 20/15/10 damage based on severity
take_damage(damage, BRUTE, BOMB, 0)
/obj/structure/blob/core/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir, overmind_reagent_trigger = 1)
. = ..()
if(obj_integrity > 0)
if(overmind) //we should have an overmind, but...
overmind.update_health_hud()
/obj/structure/blob/core/RegenHealth()
return // Don't regen, we handle it in Life()
/obj/structure/blob/core/Life(seconds, times_fired)
if(!overmind)
create_overmind()
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 + 1)
if(overmind)
overmind.update_health_hud()
if(overmind)
for(var/i = 1; i < 8; i += i)
Pulse(0, i, overmind.blob_reagent_datum.color)
else
for(var/i = 1; i < 8; i += i)
Pulse(0, i, color)
for(var/b_dir in GLOB.alldirs)
if(!prob(5))
continue
var/obj/structure/blob/normal/B = locate() in get_step(src, b_dir)
if(B)
B.change_to(/obj/structure/blob/shield/core)
if(B && overmind)
B.color = overmind.blob_reagent_datum.color
else
B.color = color
color = null
..()
/obj/structure/blob/core/proc/create_overmind(client/new_overmind, override_delay)
if(overmind_get_delay > world.time && !override_delay)
return
overmind_get_delay = world.time + 5 MINUTES
if(overmind)
qdel(overmind)
INVOKE_ASYNC(src, PROC_REF(get_new_overmind), new_overmind)
/obj/structure/blob/core/proc/get_new_overmind(client/new_overmind)
var/mob/C = null
var/list/candidates = list()
if(!new_overmind)
// sendit
if(is_offspring)
candidates = SSghost_spawns.poll_candidates("Do you want to play as a blob offspring?", ROLE_BLOB, TRUE, 10 SECONDS, source = src)
else
candidates = SSghost_spawns.poll_candidates("Do you want to play as a blob?", ROLE_BLOB, TRUE, 10 SECONDS, source = src)
if(length(candidates))
C = pick(candidates)
else
C = new_overmind
if(C && !QDELETED(src))
var/mob/camera/blob/B = new(loc)
B.is_offspring = is_offspring
B.key = C.key
B.blob_core = src
overmind = B
color = overmind.blob_reagent_datum.color
if(B.mind && !B.mind.special_role)
B.mind.make_Overmind()
/obj/structure/blob/core/proc/lateblobtimer()
addtimer(CALLBACK(src, PROC_REF(lateblobcheck)), 50)
/obj/structure/blob/core/proc/lateblobcheck()
if(overmind)
overmind.add_points(60)
if(overmind.mind)
overmind.mind.make_Overmind()
else
log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks a overmind.mind.")
else
log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks an overmind.")
/obj/structure/blob/core/onTransitZ(old_z, new_z)
if(overmind && is_station_level(new_z))
overmind.forceMove(get_turf(src))
return ..()
@@ -0,0 +1,28 @@
/obj/structure/blob/captured_nuke //alternative to blob just straight up destroying nukes
name = "blob captured nuke"
icon_state = "blob"
desc = "A Nuclear Warhead tangled in blob tendrils pulsating with a horrific green glow."
max_integrity = 100
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 65, ACID = 90)
point_return = 0
/obj/structure/blob/captured_nuke/Initialize(mapload, obj/machinery/nuclearbomb/N)
. = ..()
START_PROCESSING(SSobj, src)
N?.forceMove(src)
update_icon(UPDATE_OVERLAYS)
/obj/structure/blob/captured_nuke/update_overlays()
. = ..()
var/image/nuke_overlay = image('icons/mob/blob.dmi', "blob_nuke_overlay")
nuke_overlay.appearance_flags = RESET_COLOR
. += nuke_overlay
/obj/structure/blob/captured_nuke/Destroy()
for(var/obj/machinery/nuclearbomb/O in contents)
O.forceMove(loc)
STOP_PROCESSING(SSobj, src)
return ..()
/obj/structure/blob/captured_nuke/Life(seconds, times_fired)
obj_integrity = min(max_integrity, obj_integrity + 1)
@@ -0,0 +1,27 @@
/obj/structure/blob/factory
name = "factory blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_factory"
max_integrity = 200
point_return = 18
var/list/spores = list()
var/max_spores = 3
var/spore_delay = 0
/obj/structure/blob/factory/Destroy()
for(var/mob/living/simple_animal/hostile/blob/blobspore/spore in spores)
if(spore.factory == src)
spore.factory = null
spores = null
return ..()
/obj/structure/blob/factory/run_action()
if(spores.len >= max_spores)
return
if(spore_delay > world.time)
return
flick("blob_factory_glow", src)
spore_delay = world.time + 100 // 10 seconds
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src)
if(overmind)
overmind.add_mob_to_overmind(BS)
@@ -0,0 +1,36 @@
/obj/structure/blob/node
name = "blob node"
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
max_integrity = 200
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 65, ACID = 90)
point_return = 18
/obj/structure/blob/node/Initialize(mapload)
. = ..()
GLOB.blob_nodes += src
START_PROCESSING(SSobj, src)
/obj/structure/blob/node/adjustcolors(a_color)
overlays.Cut()
color = null
var/image/I = new('icons/mob/blob.dmi', "blob")
I.color = a_color
src.overlays += I
var/image/C = new('icons/mob/blob.dmi', "blob_node_overlay")
src.overlays += C
/obj/structure/blob/node/Destroy()
GLOB.blob_nodes -= src
STOP_PROCESSING(SSobj, src)
return ..()
/obj/structure/blob/node/Life(seconds, times_fired)
if(overmind)
for(var/i = 1; i < 8; i += i)
Pulse(5, i, overmind.blob_reagent_datum.color)
else
for(var/i = 1; i < 8; i += i)
Pulse(5, i, color)
obj_integrity = min(max_integrity, obj_integrity + 1)
color = null
@@ -0,0 +1,15 @@
/obj/structure/blob/resource
name = "resource blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
max_integrity = 60
point_return = 12
var/resource_delay = 0
/obj/structure/blob/resource/run_action()
if(resource_delay > world.time)
return
flick("blob_resource_glow", src)
resource_delay = world.time + 40 // 4 seconds
if(overmind)
overmind.add_points(1)
@@ -0,0 +1,76 @@
/obj/structure/blob/shield
name = "strong blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_shield"
desc = "Some blob creature thingy"
max_integrity = 150
brute_resist = 0.25
explosion_block = 3
atmosblock = TRUE
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 90, ACID = 90)
/obj/structure/blob/shield/core
point_return = 0
/obj/structure/blob/shield/check_integrity()
var/old_compromised_integrity = compromised_integrity
if(obj_integrity < max_integrity * 0.5)
compromised_integrity = TRUE
else
compromised_integrity = FALSE
if(old_compromised_integrity != compromised_integrity)
update_state()
update_appearance(UPDATE_NAME|UPDATE_DESC|UPDATE_ICON_STATE)
/obj/structure/blob/shield/update_state()
if(compromised_integrity)
atmosblock = FALSE
else
atmosblock = TRUE
air_update_turf(1)
/obj/structure/blob/shield/update_name()
. = ..()
if(compromised_integrity)
name = "weakened [initial(name)]"
else
name = initial(name)
/obj/structure/blob/shield/update_desc()
. = ..()
if(compromised_integrity)
desc = "A wall of twitching tendrils."
else
desc = initial(desc)
/obj/structure/blob/shield/update_icon_state()
if(compromised_integrity)
icon_state = "[initial(icon_state)]_damaged"
else
icon_state = initial(icon_state)
/obj/structure/blob/shield/CanPass(atom/movable/mover, turf/target, height=0)
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
return 0
/obj/structure/blob/shield/reflective
name = "reflective blob"
desc = "A solid wall of slightly twitching tendrils with a reflective glow."
icon_state = "blob_glow"
max_integrity = 100
brute_resist = 0.5
explosion_block = 2
point_return = 9
flags_2 = CHECK_RICOCHET_2
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
var/turf/p_turf = get_turf(P)
var/face_direction = get_dir(src, p_turf)
var/face_angle = dir2angle(face_direction)
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180))
if(abs(incidence_s) > 90 && abs(incidence_s) < 270)
return FALSE
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
P.set_angle(new_angle_s)
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
return TRUE
@@ -0,0 +1,16 @@
/obj/structure/blob/storage
name = "storage blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
max_integrity = 30
fire_resist = 2
point_return = 12
/obj/structure/blob/storage/obj_destruction(damage_flag)
if(overmind)
overmind.max_blob_points -= 50
..()
/obj/structure/blob/storage/proc/update_max_blob_points(new_point_increase)
if(overmind)
overmind.max_blob_points += new_point_increase
+123
View File
@@ -0,0 +1,123 @@
/mob/camera/blob
name = "Blob Overmind"
real_name = "Blob Overmind"
icon = 'icons/mob/blob.dmi'
icon_state = "marker"
see_in_dark = 8
invisibility = INVISIBILITY_OBSERVER
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
pass_flags = PASSBLOB
faction = list(ROLE_BLOB)
var/obj/structure/blob/core/blob_core = null // The blob overmind's core
var/blob_points = 0
var/max_blob_points = 100
var/last_attack = 0
var/nodes_required = TRUE //if the blob needs nodes to place resource and factory blobs
var/split_used = FALSE
var/is_offspring = FALSE
var/datum/reagent/blob/blob_reagent_datum = new/datum/reagent/blob()
var/list/blob_mobs = list()
/mob/camera/blob/New()
var/new_name = "[initial(name)] ([rand(1, 999)])"
name = new_name
real_name = new_name
last_attack = world.time
var/list/possible_reagents = list()
for(var/type in subtypesof(/datum/reagent/blob))
possible_reagents.Add(new type)
blob_reagent_datum = pick(possible_reagents)
if(blob_core)
blob_core.adjustcolors(blob_reagent_datum.color)
color = blob_reagent_datum.complementary_color
..()
START_PROCESSING(SSobj, src)
/mob/camera/blob/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/mob/camera/blob/process()
if(!blob_core)
qdel(src)
/mob/camera/blob/Login()
..()
sync_mind()
blob_help()
update_health_hud()
/mob/camera/blob/update_health_hud()
if(blob_core && hud_used)
hud_used.blobhealthdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font face='Small Fonts' color='#e36600'>[round(blob_core.obj_integrity)]</font></div>"
/mob/camera/blob/proc/add_points(points)
if(points != 0)
blob_points = clamp(blob_points + points, 0, max_blob_points)
if(hud_used)
hud_used.blobpwrdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font face='Small Fonts' color='#82ed00'>[round(src.blob_points)]</font></div>"
/mob/camera/blob/say(message)
if(!message)
return
if(src.client)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "You cannot send IC messages (muted).")
return
if(src.client.handle_spam_prevention(message, MUTE_IC))
return
if(stat)
return
blob_talk(message)
/mob/camera/blob/proc/add_mob_to_overmind(mob/living/simple_animal/hostile/blob/B)
B.color = blob_reagent_datum?.complementary_color
B.overmind = src
blob_mobs += B
RegisterSignal(B, COMSIG_PARENT_QDELETING, PROC_REF(on_blob_mob_death))
/mob/camera/blob/proc/on_blob_mob_death(mob/living/simple_animal/hostile/blob/B)
blob_mobs -= B
/mob/camera/blob/proc/blob_talk(message)
log_say("(BLOB) [message]", src)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message)
return
var/rendered
var/follow_text
for(var/mob/M in GLOB.mob_list)
follow_text = isobserver(M) ? " ([ghost_follow_link(src, ghost=M)])" : ""
rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]([blob_reagent_datum.name])</span>[follow_text] <span class='message'>states, \"[message]\"</span></span></i></font>"
if(isovermind(M) || isobserver(M) || istype(M, /mob/living/simple_animal/hostile/blob/blobbernaut))
M.show_message(rendered, EMOTE_AUDIBLE)
/mob/camera/blob/blob_act(obj/structure/blob/B)
return
/mob/camera/blob/Stat()
..()
if(statpanel("Status"))
if(blob_core)
stat(null, "Core Health: [blob_core.obj_integrity]")
stat(null, "Power Stored: [blob_points]/[max_blob_points]")
/mob/camera/blob/Move(NewLoc, Dir = 0)
var/obj/structure/blob/B = locate() in range("3x3", NewLoc)
if(B)
loc = NewLoc
else
return 0
/mob/camera/blob/proc/can_attack()
return (world.time > (last_attack + CLICK_CD_RANGE))
+312
View File
@@ -0,0 +1,312 @@
//I will need to recode parts of this but I am way too tired atm
GLOBAL_LIST_EMPTY(blobs)
GLOBAL_LIST_EMPTY(blob_cores)
GLOBAL_LIST_EMPTY(blob_nodes)
/obj/structure/blob
name = "blob"
icon = 'icons/mob/blob.dmi'
light_range = 3
desc = "Some blob creature thingy"
density = FALSE
opacity = FALSE
anchored = TRUE
max_integrity = 30
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 80, ACID = 70)
flags_2 = CRITICAL_ATOM_2
var/point_return = 0 //How many points the blob gets back when it removes a blob of that type. If less than 0, blob cannot be removed.
var/health_timestamp = 0
var/brute_resist = 0.5 //multiplies brute damage by this
var/fire_resist = 1 //multiplies burn damage by this
var/atmosblock = FALSE //if the blob blocks atmos and heat spread
/// If a threshold is reached, resulting in shifting variables
var/compromised_integrity = FALSE
var/mob/camera/blob/overmind
/obj/structure/blob/Initialize(mapload)
. = ..()
GLOB.blobs += src
setDir(pick(GLOB.cardinal))
check_integrity()
if(atmosblock)
air_update_turf(TRUE)
ConsumeTile()
/obj/structure/blob/Destroy()
if(atmosblock)
atmosblock = FALSE
air_update_turf(1)
GLOB.blobs -= src
overmind = null // let us not have gc issues
if(isturf(loc)) //Necessary because Expand() is screwed up and spawns a blob and then deletes it
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
return ..()
/obj/structure/blob/BlockSuperconductivity()
return atmosblock
/obj/structure/blob/CanPass(atom/movable/mover, turf/target, height=0)
if(height==0)
return 1
if(istype(mover) && mover.checkpass(PASSBLOB))
return 1
return 0
/obj/structure/blob/CanAtmosPass(turf/T)
return !atmosblock
/obj/structure/blob/CanPathfindPass(obj/item/card/id/ID, dir, caller, no_id = FALSE)
. = 0
if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSBLOB)
/obj/structure/blob/process()
Life()
return
/obj/structure/blob/blob_act(obj/structure/blob/B)
return
/obj/structure/blob/proc/Life()
return
/obj/structure/blob/proc/check_integrity()
return
/obj/structure/blob/proc/update_state()
return
/obj/structure/blob/proc/RegenHealth()
// All blobs heal over time when pulsed, but it has a cool down
if(health_timestamp > world.time)
return 0
var/turf/T = get_turf(src)
chemical_attack(T)
if(obj_integrity < max_integrity)
obj_integrity = min(max_integrity, obj_integrity + 1)
check_integrity()
health_timestamp = world.time + 10 // 1 seconds
/obj/structure/blob/proc/chemical_attack(turf/T)
for(var/mob/living/L in T)
if(ROLE_BLOB in L.faction) //no friendly/dead fire
continue
if(!overmind)
continue
var/mob_protection = L.get_permeability_protection()
overmind.blob_reagent_datum.reaction_mob(L, REAGENT_TOUCH, 25, 1, mob_protection)
overmind.blob_reagent_datum.send_message(L)
L.blob_act(src)
/obj/structure/blob/proc/Pulse(pulse = 0, origin_dir = 0, a_color)//Todo: Fix spaceblob expand
RegenHealth()
if(run_action())//If we can do something here then we dont need to pulse more
return
if(pulse > 30)
return//Inf loop check
//Looking for another blob to pulse
var/list/dirs = list(1,2,4,8)
dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us
for(var/i = 1 to 4)
if(!dirs.len) break
var/dirn = pick(dirs)
dirs.Remove(dirn)
var/turf/T = get_step(src, dirn)
var/obj/structure/blob/B = (locate(/obj/structure/blob) in T)
if(!B)
expand(T, 1, a_color, overmind)//No blob here so try and expand
return
B.adjustcolors(a_color)
B.Pulse((pulse+1),get_dir(src.loc,T), a_color)
return
return
/obj/structure/blob/proc/run_action()
return 0
/obj/structure/blob/proc/ConsumeTile()
for(var/atom/A in loc)
A.blob_act(src)
if(iswallturf(loc))
loc.blob_act(src) //don't ask how a wall got on top of the core, just eat it
/obj/structure/blob/proc/expand(turf/T = null, prob = 1, a_color, _overmind = null, turf/double_target = null)
if(prob && !prob(obj_integrity))
return
if(isspaceturf(T) && prob(75)) return
if(!T)
var/list/dirs = list(1,2,4,8)
for(var/i = 1 to 4)
var/dirn = pick(dirs)
dirs.Remove(dirn)
T = get_step(src, dirn)
if(!(locate(/obj/structure/blob) in T)) break
else T = null
if(!T) return 0
var/obj/structure/blob/normal/B = new /obj/structure/blob/normal(src.loc, min(obj_integrity, 30))
B.color = a_color
B.density = TRUE
B.overmind = _overmind
if(T.Enter(B,src))//Attempt to move into the tile
B.density = initial(B.density)
B.loc = T
if(double_target)
if(!overmind.can_buy(5))
overmind.last_attack = world.time
return
B.expand(double_target, 0, overmind.blob_reagent_datum.color, overmind)
overmind.blob_core.chemical_attack(T)
overmind.last_attack = world.time
else
T.blob_act()//If we cant move in hit the turf
B.loc = null //So we don't play the splat sound, see Destroy()
qdel(B)
for(var/atom/A in T)//Hit everything in the turf
if(isliving(A) && !A.density && overmind) // Crawling mob / small mob? Extra damage.
var/mob/living/M = A
var/mob_protection = M.get_permeability_protection()
overmind.blob_reagent_datum.reaction_mob(M, REAGENT_TOUCH, 25, 1, mob_protection)
overmind.blob_reagent_datum.send_message(M)
A.blob_act(src)
return 1
/obj/structure/blob/proc/double_expand(turf/T = null, prob = 1, a_color, _overmind = null)
for(var/turf/adjacent in circlerange(T, 1))
if(adjacent in circlerange(src, 1))
expand(adjacent, 0, overmind.blob_reagent_datum.color, overmind, T)
overmind.blob_core.chemical_attack(adjacent)
color = overmind.blob_reagent_datum.color
return
/obj/structure/blob/Crossed(mob/living/L, oldloc)
..()
L.blob_act(src)
/obj/structure/blob/zap_act(power, zap_flags)
take_damage(power * 0.0025, BURN, ENERGY)
power -= power * 0.0025 //You don't get to do it for free
return ..() //You don't get to do it for free
/obj/structure/blob/hulk_damage()
return 15
/obj/structure/blob/attack_animal(mob/living/simple_animal/M)
if(ROLE_BLOB in M.faction) //sorry, but you can't kill the blob as a blobbernaut
return
..()
/obj/structure/blob/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
if(damage_amount)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, TRUE)
else
playsound(src, 'sound/weapons/tap.ogg', 50, TRUE)
if(BURN)
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)
/obj/structure/blob/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
switch(damage_type)
if(BRUTE)
damage_amount *= brute_resist
if(BURN)
damage_amount *= fire_resist
if(CLONE)
else
return 0
var/armor_protection = 0
if(damage_flag)
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)
return damage_amount
/obj/structure/blob/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
if(. && obj_integrity > 0)
check_integrity()
/obj/structure/blob/proc/change_to(type)
if(!ispath(type))
error("[type] is an invalid type for the blob.")
var/obj/structure/blob/B = new type(src.loc)
if(!istype(type, /obj/structure/blob/core) || !istype(type, /obj/structure/blob/node))
B.color = color
else
B.adjustcolors(color)
qdel(src)
/obj/structure/blob/proc/adjustcolors(a_color)
if(a_color)
color = a_color
/obj/structure/blob/examine(mob/user)
. = ..()
. += "It looks like it's made of [get_chem_name()]."
. += "It looks like this chemical does: [get_chem_desc()]"
/obj/structure/blob/proc/get_chem_name()
for(var/mob/camera/blob/B in GLOB.mob_list)
if(lowertext(B.blob_reagent_datum.color) == lowertext(src.color)) // Goddamit why we use strings for these
return B.blob_reagent_datum.name
return "unknown"
/obj/structure/blob/proc/get_chem_desc()
for(var/mob/camera/blob/B in GLOB.mob_list)
if(lowertext(B.blob_reagent_datum.color) == lowertext(src.color)) // Goddamit why we use strings for these
return B.blob_reagent_datum.description
return "something unknown"
/obj/structure/blob/normal
icon_state = "blob"
light_range = 0
obj_integrity = 21 //doesn't start at full health
max_integrity = 25
brute_resist = 0.25
/obj/structure/blob/normal/check_integrity()
var/old_compromised_integrity = compromised_integrity
if(obj_integrity <= 15)
compromised_integrity = TRUE
else
compromised_integrity = FALSE
if(old_compromised_integrity != compromised_integrity)
update_state()
update_appearance(UPDATE_NAME|UPDATE_DESC|UPDATE_ICON_STATE)
/obj/structure/blob/normal/update_state()
if(compromised_integrity)
brute_resist = 0.5
else
brute_resist = 0.25
/obj/structure/blob/normal/update_name()
. = ..()
if(compromised_integrity)
name = "fragile blob"
else
name = "[overmind ? "blob" : "dead blob"]"
/obj/structure/blob/normal/update_desc()
. = ..()
if(compromised_integrity)
desc = "A thin lattice of slightly twitching tendrils."
else
desc = "A thick wall of [overmind ? "writhing" : "lifeless"] tendrils."
/obj/structure/blob/normal/update_icon_state()
if(compromised_integrity)
icon_state = "blob_damaged"
else
icon_state = "blob"
+5 -1
View File
@@ -26,10 +26,14 @@
var/mob/M = pick(candidates)
B.key = M.key
B.mind.special_role = SPECIAL_ROLE_BLOB
SSticker.mode.update_blob_icons_added(B.mind)
B.forceMove(vent)
B.add_ventcrawl(vent)
// Mark it on antag HUD
var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_BLOB]
antaghud.join_hud(B.mind.current)
set_antag_hud(B.mind.current, "hudblob")
to_chat(B, "<span class='userdanger'>You are now a mouse, infected with blob spores. Find somewhere isolated... before you burst and become the blob! Use ventcrawl (alt-click on vents) to move around.</span>")
to_chat(B, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Blob)</span>")
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B, action = NOTIFY_FOLLOW)