The Big Blob update, Part 1 (#9735)

* blab

* blib

* blub

* bleb

* blob

* bloarb

* blyuiob

* blargarbelb

* changeblob

* oh fuck you travis

* oh are you fucking kidding me

* well duh

* fix spacemove

* damge overlay updates
This commit is contained in:
DeityLink
2016-04-29 15:08:46 +02:00
committed by sood
parent dda10db3b3
commit b7d5338a90
37 changed files with 653 additions and 123 deletions

View File

@@ -441,6 +441,10 @@ its easier to just keep the beam vertical.
return ex_act(severity, child)
/atom/proc/blob_act()
//DEBUG to_chat(pick(player_list),"blob_act() on [src] ([src.type])")
if(flags & INVULNERABLE)
return
anim(target = loc, a_icon = 'icons/mob/blob.dmi', flick_anim = "blob_act", sleeptime = 15, lay = 12)
return
/*

View File

@@ -499,6 +499,9 @@
. = ..()
verbs.len = 0
/atom/movable/overlay/blob_act()
return
/atom/movable/overlay/attackby(a, b, c)
if (src.master)
return src.master.attackby(a, b, c)

View File

@@ -4,6 +4,7 @@
var/list/blobs = list()
var/list/blob_cores = list()
var/list/blob_nodes = list()
var/list/blob_resources = list()
/datum/game_mode/blob
@@ -91,12 +92,16 @@ You must kill it all while minimizing the damage to the station."})
if(iscarbon(blob.current))
var/mob/living/carbon/C = blob.current
for(var/obj/item/W in C)
C.drop_from_inventory(W)
if(directory[ckey(blob.key)])
blob_client = directory[ckey(blob.key)]
location = get_turf(C)
if(location.z != 1 || istype(location, /turf/space))
location = null
C.gib()
qdel(C)
if(blob_client && location)

View File

@@ -1,8 +1,8 @@
/obj/effect/blob/core
name = "blob core"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_core"
icon_state = "core"
health = 200
maxhealth = 200
fire_resist = 2
custom_process=1
var/mob/camera/blob/overmind = null // the blob core's overmind
@@ -10,20 +10,36 @@
var/resource_delay = 0
var/point_rate = 2
var/mob/camera/blob/creator = null
layer = 7
layer_new = 7
icon_new = "core"
icon_classic = "blob_core"
/obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, var/mob/camera/blob/C = null)
/obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, var/mob/camera/blob/C = null,newlook = "new")
looks = newlook
blob_cores += src
processing_objects.Add(src)
creator = C
if(blob_looks[looks] == 64)
if(new_overmind)
flick("core_spawn",src)
else
flick("morph_core",src)
playsound(src, get_sfx("gib"),50,1)
if(!overmind)
create_overmind(new_overmind)
point_rate = new_rate
..(loc, h)
..(loc, newlook)
/obj/effect/blob/core/Destroy()
blob_cores -= src
if(overmind)
for(var/obj/effect/blob/resource/R in blob_resources)
if(R.overmind == overmind)
R.overmind = null
R.update_icon()
qdel(overmind)
overmind = null
processing_objects.Remove(src)
@@ -32,8 +48,9 @@
/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
/obj/effect/blob/core/update_icon()
/obj/effect/blob/core/update_health()
if(health <= 0)
dying = 1
playsound(get_turf(src), 'sound/effects/blobkill.ogg', 50, 1)
Delete()
return
@@ -48,19 +65,32 @@
if(resource_delay <= world.time)
resource_delay = world.time + 10 // 1 second
overmind.add_points(point_rate)
health = min(initial(health), health + 1)
var/turf/T = get_turf(overmind) //The overmind's mind can expand the blob
var/obj/effect/blob/O = locate() in T //As long as it is 'thinking' about a blob already
for(var/i = 1; i < 8; i += i)
Pulse(0, i)
if(istype(O))
O.Pulse(0,i)
for(var/b_dir in alldirs)
if(!prob(5))
continue
var/obj/effect/blob/normal/B = locate() in get_step(src, b_dir)
if(B)
B.change_to(/obj/effect/blob/shield)
if(health < maxhealth)
health = min(maxhealth, health + 1)
update_icon()
if(!spawning)//no expanding on the first Life() tick
if(blob_looks[looks] == 64)
anim(target = loc, a_icon = icon, flick_anim = "corepulse", sleeptime = 15, lay = 12, offX = -16, offY = -16, alph = 200)
for(var/mob/M in viewers(src))
M.playsound_local(loc, 'sound/effects/blob_pulse.ogg', 50, 0, null, FALLOFF_SOUNDS, 0)
var/turf/T = get_turf(overmind) //The overmind's mind can expand the blob
var/obj/effect/blob/O = locate() in T //As long as it is 'thinking' about a blob already
for(var/i = 1; i < 8; i += i)
Pulse(0, i)
if(istype(O))
O.Pulse(0,i)
for(var/b_dir in alldirs)
if(!prob(5))
continue
var/obj/effect/blob/normal/B = locate() in get_step(src, b_dir)
if(B)
B.change_to(/obj/effect/blob/shield)
else
spawning = 0
..()
@@ -69,8 +99,6 @@
/obj/effect/blob/core/proc/create_overmind(var/client/new_overmind)
if(overmind_get_delay > world.time)
return
@@ -95,10 +123,33 @@
B.key = C.key
B.blob_core = src
src.overmind = B
if(!B.blob_core.creator)
if(!B.blob_core.creator)//If this core is the first of its lineage (created by game mode/event/admins, instead of another overmind) it gets to choose its looks.
B.verbs += /mob/camera/blob/proc/create_core
spawn()
var/chosen = input(B,"Select a blob looks", "Blob Looks", blob_looks[1]) as null|anything in blob_looks
if(chosen)
for(var/obj/effect/blob/nearby_blob in range(src,5))
nearby_blob.looks = chosen
nearby_blob.update_looks(1)
if(istype(ticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/mode = ticker.mode
mode.infected_crew += B.mind
return 1
return 0
/obj/effect/blob/core/update_icon(var/spawnend = 0)
if(blob_looks[looks] == 64)
spawn(1)
overlays.len = 0
overlays += image(icon,"roots", layer = 3)
if(!spawning)
for(var/obj/effect/blob/B in orange(src,1))
overlays += image(icon,"coreconnect",dir = get_dir(src,B), layer = layer+0.1)
if(spawnend)
spawn(10)
update_icon()
..()

View File

@@ -1,15 +1,28 @@
/obj/effect/blob/factory
name = "factory blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_factory"
icon_state = "factory"
health = 100
maxhealth = 100
fire_resist = 2
var/list/spores = list()
var/max_spores = 2
var/spore_delay = 50
spawning = 0
layer = 6.6
/obj/effect/blob/factory/update_icon()
layer_new = 6.6
icon_new = "factory"
icon_classic = "blob_factory"
/obj/effect/blob/factory/New(loc,newlook = "new")
..()
if(blob_looks[looks] == 64)
flick("morph_factory",src)
spore_delay = world.time + (2 SECONDS)
/obj/effect/blob/factory/update_health()
if(health <= 0)
dying = 1
playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1)
qdel(src)
return
@@ -21,7 +34,15 @@
if(spore_delay > world.time)
return 0
spore_delay = world.time + (40 SECONDS) // 30 seconds
new/mob/living/simple_animal/hostile/blobspore(src.loc, src)
if(blob_looks[looks] == 64)
flick("factorypulse",src)
anim(target = loc, a_icon = icon, flick_anim = "sporepulse", sleeptime = 15, lay = 7.2, offX = -16, offY = -16, alph = 220)
spawn(10)
new/mob/living/simple_animal/hostile/blobspore(src.loc, src)
else
new/mob/living/simple_animal/hostile/blobspore(src.loc, src)
return 1
/obj/effect/blob/factory/Destroy()
@@ -30,6 +51,24 @@
S.Die()
..()
/obj/effect/blob/factory/update_icon(var/spawnend = 0)
if(blob_looks[looks] == 64)
spawn(1)
overlays.len = 0
overlays += image(icon,"roots", layer = 3)
if(!spawning)
for(var/obj/effect/blob/B in orange(src,1))
overlays += image(icon,"factoryconnect",dir = get_dir(src,B), layer = layer+0.1)
if(spawnend)
spawn(10)
update_icon()
..()
/////////////BLOB SPORE///////////////////////////////////////////////////////////////////////////////////////////////
/mob/living/simple_animal/hostile/blobspore
name = "Blob Spore"
desc = "A form of blob antibodies that attack foreign entities."
@@ -51,6 +90,7 @@
max_co2 = 0
minbodytemp = 0
maxbodytemp = 360
layer = 7.2
/mob/living/simple_animal/hostile/blobspore/New(loc, var/obj/effect/blob/factory/linked_node)
if(istype(linked_node))
@@ -78,4 +118,4 @@
/mob/living/simple_animal/hostile/blobspore/Destroy()
if(factory)
factory.spores -= src
..()
..()

View File

@@ -1,16 +1,24 @@
/obj/effect/blob/node
name = "blob node"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_node"
icon_state = "node"
health = 100
maxhealth = 100
fire_resist = 2
custom_process=1
layer = 6.8
spawning = 0
layer_new = 6.8
icon_new = "node"
icon_classic = "blob_node"
/obj/effect/blob/node/New(loc, var/h = 100)
/obj/effect/blob/node/New(loc,newlook = "new")
blob_nodes += src
processing_objects.Add(src)
..(loc, h)
..(loc, newlook)
if(blob_looks[looks] == 64)
flick("morph_node",src)
/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
@@ -23,12 +31,21 @@
/obj/effect/blob/node/Life()
if(timestopped) return 0 //under effects of time magick
if(blob_looks[looks] == 64)
anim(target = loc, a_icon = icon, flick_anim = "nodepulse", sleeptime = 15, lay = 12, offX = -16, offY = -16, alph = 150)
for(var/mob/M in viewers(src))
M.playsound_local(loc, 'sound/effects/blob_pulse.ogg', 50, 0, null, FALLOFF_SOUNDS, 0)
for(var/i = 1; i < 8; i += i)
Pulse(5, i)
health = min(initial(health), health + 1)
/obj/effect/blob/node/update_icon()
if(health < maxhealth)
health = min(maxhealth, health + 1)
update_icon()
/obj/effect/blob/node/update_health()
if(health <= 0)
dying = 1
playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1)
Delete()
return
@@ -36,3 +53,21 @@
/obj/effect/blob/node/run_action()
return 0
/obj/effect/blob/node/update_icon(var/spawnend = 0)
if(blob_looks[looks] == 64)
spawn(1)
overlays.len = 0
overlays += image(icon,"roots", layer = 3)
if(!spawning)
for(var/obj/effect/blob/B in orange(src,1))
overlays += image(icon,"nodeconnect",dir = get_dir(src,B), layer = layer+0.1)
if(spawnend)
spawn(10)
update_icon()
..()

View File

@@ -1,19 +1,45 @@
/obj/effect/blob/resource
name = "resource blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
icon_state = "resource"
health = 30
maxhealth = 30
fire_resist = 2
var/mob/camera/blob/overmind = null
var/resource_delay = 0
spawning = 0
layer = 6.4
/obj/effect/blob/resource/update_icon()
layer_new = 6.4
icon_new = "resource"
icon_classic = "blob_resource"
/obj/effect/blob/resource/New(loc,newlook = "new")
..()
blob_resources += src
if(blob_looks[looks] == 64)
flick("morph_resource",src)
/obj/effect/blob/resource/Destroy()
blob_resources -= src
..()
/obj/effect/blob/resource/update_health()
if(health <= 0)
dying = 1
playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1)
qdel(src)
return
return
/obj/effect/blob/resource/Pulse(var/pulse = 0, var/origin_dir = 0)
if(!overmind)
var/mob/camera/blob/B = (locate() in range(src,1))
if(B)
overmind = B
update_icon()
..()
/obj/effect/blob/resource/run_action()
if(resource_delay > world.time)
return 0
@@ -21,5 +47,29 @@
resource_delay = world.time + (4 SECONDS)
if(overmind)
if(blob_looks[looks] == 64)
anim(target = loc, a_icon = icon, flick_anim = "resourcepulse", sleeptime = 15, lay = 7.2, offX = -16, offY = -16, alph = 220)
overmind.add_points(1)
return 1
/obj/effect/blob/resource/update_icon(var/spawnend = 0)
spawn(1)
if(overmind)
color = null
else
color = "#888888"
if(blob_looks[looks] == 64)
spawn(1)
overlays.len = 0
overlays += image(icon,"roots", layer = 3)
if(!spawning)
for(var/obj/effect/blob/B in orange(src,1))
overlays += image(icon,"resourceconnect",dir = get_dir(src,B), layer = layer+0.1)
if(spawnend)
spawn(10)
update_icon()
..()

View File

@@ -1,14 +1,24 @@
/obj/effect/blob/shield
name = "strong blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_idle"
icon_state = "strong"
desc = "Some blob creature thingy"
health = 75
maxhealth = 75
fire_resist = 2
layer = 6.2
spawning = 0
layer_new = 6.2
icon_new = "strong"
icon_classic = "blob_idle"
/obj/effect/blob/shield/update_icon()
/obj/effect/blob/shield/New(loc,newlook = "new")
..()
flick("morph_strong",src)
/obj/effect/blob/shield/update_health()
if(health <= 0)
dying = 1
playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1)
qdel(src)
return
@@ -27,3 +37,32 @@
health += 10
return 1
/obj/effect/blob/shield/Pulse(var/pulse = 0, var/origin_dir = 0)
..()
if(blob_looks[looks] == 64)
anim(target = loc, a_icon = 'icons/mob/blob_64x64.dmi', flick_anim = "strongpulse", sleeptime = 15, lay = 12, offX = -16, offY = -16, alph = 51)
/obj/effect/blob/shield/update_icon(var/spawnend = 0)
if(blob_looks[looks] == 64)
spawn(1)
overlays.len = 0
overlays += image(icon,"roots", layer = 3)
if(!spawning)
for(var/obj/effect/blob/B in orange(src,1))
overlays += image(icon,"strongconnect",dir = get_dir(src,B), layer = layer+0.1)
/*
if(B.spawning)
anim(target = loc, a_icon = 'icons/mob/blob_64x64.dmi', flick_anim = "connect_spawn", sleeptime = 15, direction = get_dir(src,B), lay = layer+0.2, offX = -16, offY = -16)
spawn(8)
update_icon()
else if(!B.dying)
overlays += image(icon,"strongconnect",dir = get_dir(src,B), layer = layer+0.2)
*/
if(spawnend)
spawn(10)
update_icon()
..()

View File

@@ -11,6 +11,8 @@
pass_flags = PASSBLOB
faction = "blob"
layer = 15
var/obj/effect/blob/core/blob_core = null // The blob overmind's core
var/blob_points = 0
var/max_blob_points = 100
@@ -93,9 +95,27 @@
/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null)
return
/mob/camera/blob/ex_act()
return
/mob/camera/blob/singularity_act()
return
/mob/camera/blob/cultify()
return
/mob/camera/blob/singuloCanEat()
return 0
/mob/camera/blob/singularity_pull()
return
/mob/camera/blob/blob_act()
return
/mob/camera/blob/Process_Spacemove(var/check_drift = 0)
return 1
/mob/camera/blob/Stat()
..()
if (statpanel("Blob Status"))

View File

@@ -94,7 +94,6 @@
var/obj/effect/blob/resource/R = locate() in T
if(R)
R.overmind = src
return
/mob/camera/blob/proc/create_core()

View File

@@ -1,22 +1,80 @@
//I will need to recode parts of this but I am way too tired atm
//I will need to recode parts of this but I am way too tired atm <- whoever said this, I've got your back -Deity Link
/* Contents
/obj/effect/blob
/obj/effect/blob/blob_act()
/obj/effect/blob/New(turf/loc,newlook = "new")
/obj/effect/blob/Destroy()
/obj/effect/blob/projectile_check()
/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
/obj/effect/blob/beam_connect(var/obj/effect/beam/B)
/obj/effect/blob/beam_disconnect(var/obj/effect/beam/B)
/obj/effect/blob/apply_beam_damage(var/obj/effect/beam/B)
/obj/effect/blob/handle_beams()
/obj/effect/blob/process()
/obj/effect/blob/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
/obj/effect/blob/ex_act(severity)
/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj)
/obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/user)
/obj/effect/blob/update_icon(var/spawnend = 0)
/obj/effect/blob/proc/update_looks()
var/list/blob_looks
/obj/effect/blob/proc/Life()
/obj/effect/blob/proc/aftermove()
/obj/effect/blob/proc/Pulse(var/pulse = 0, var/origin_dir = 0)
/obj/effect/blob/proc/run_action()
/obj/effect/blob/proc/expand(var/turf/T = null, var/prob = 1)
/obj/effect/blob/proc/change_to(var/type, var/mob/camera/blob/M = null)
/obj/effect/blob/proc/Delete()
/obj/effect/blob/proc/update_health()
/obj/effect/blob/normal
/obj/effect/blob/normal/Delete()
/obj/effect/blob/normal/Pulse(var/pulse = 0, var/origin_dir = 0)
/obj/effect/blob/normal/update_icon(var/spawnend = 0)
*/
/obj/effect/blob
name = "blob"
icon = 'icons/mob/blob.dmi'
luminosity = 3
icon = 'icons/mob/blob_64x64.dmi'
icon_state = "center"
luminosity = 2
desc = "Some blob creature thingy"
density = 0
opacity = 0
anchored = 1
penetration_dampening = 17
var/health = 20
var/maxhealth = 20
var/health_timestamp = 0
var/brute_resist = 4
var/fire_resist = 1
pixel_x = -16
pixel_y = -16
layer = 6
var/spawning = 2
var/dying = 0
var/looks = "new"
// A note to the beam processing shit.
var/custom_process=0
/obj/effect/blob/New(loc)
var/time_since_last_pulse
var/layer_new = 6
var/icon_new = "center"
var/icon_classic = "blob"
/obj/effect/blob/blob_act()
return
/obj/effect/blob/New(turf/loc,newlook = "new")
looks = newlook
update_looks()
blobs += src
if(istype(ticker.mode,/datum/game_mode/blob))
var/datum/game_mode/blob/blobmode = ticker.mode
@@ -24,7 +82,18 @@
blobmode.stage(2)
blobmode.nuclear = 1
src.dir = pick(cardinal)
src.update_icon()
time_since_last_pulse = world.time
if(blob_looks[looks] == 64)
if(spawning)
icon_state = initial(icon_state) + "_spawn"
spawn(10)
spawning = 0//for sprites
icon_state = initial(icon_state)
src.update_icon(1)
else
update_icon()
..(loc)
for(var/atom/A in loc)
A.blob_act()
@@ -32,7 +101,18 @@
/obj/effect/blob/Destroy()
dying = 1
blobs -= src
if(blob_looks[looks] == 64)
for(var/atom/movable/overlay/O in loc)
returnToPool(O)
for(var/obj/effect/blob/B in orange(loc,1))
B.update_icon()
if(!spawning)
anim(target = B.loc, a_icon = icon, flick_anim = "connect_die", sleeptime = 50, direction = get_dir(B,src), lay = layer+0.3, offX = -16, offY = -16, col = "red")
..()
/obj/effect/blob/projectile_check()
@@ -55,6 +135,7 @@
..()
apply_beam_damage(B)
last_beamchecks.Remove("\ref[B]") // RIP
update_health()
update_icon()
if(beams.len == 0)
if(!custom_process && src in processing_objects)
@@ -76,6 +157,7 @@
// New beam damage code (per-tick)
for(var/obj/effect/beam/B in beams)
apply_beam_damage(B)
update_health()
update_icon()
/obj/effect/blob/process()
@@ -88,17 +170,124 @@
var/damage = Clamp(0.01 * exposed_temperature / fire_resist, 0, 4 - fire_resist)
if(damage)
health -= damage
update_health()
update_icon()
/obj/effect/blob/ex_act(severity)
var/damage = 150
health -= ((damage/brute_resist) - (severity * 5))
update_health()
update_icon()
return
/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj)
..()
switch(Proj.damage_type)
if(BRUTE)
health -= (Proj.damage/brute_resist)
if(BURN)
health -= (Proj.damage/fire_resist)
update_health()
update_icon()
return 0
/obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/user)
user.delayNextAttack(10)
playsound(get_turf(src), 'sound/effects/attackblob.ogg', 50, 1)
src.visible_message("<span class='warning'><B>The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]</span>")
var/damage = 0
switch(W.damtype)
if("fire")
damage = (W.force / max(src.fire_resist,1))
if(istype(W, /obj/item/weapon/weldingtool) || istype(W, /obj/item/weapon/pickaxe/plasmacutter))
playsound(get_turf(src), 'sound/effects/blobweld.ogg', 100, 1)
if("brute")
damage = (W.force / max(src.brute_resist,1))
health -= damage
update_health()
update_icon()
return
/obj/effect/blob/update_icon(var/spawnend = 0)
if(blob_looks[looks] == 64)
if(health < maxhealth)
var/hurt_percentage = round((health * 100) / maxhealth)
var/hurt_icon
switch(hurt_percentage)
if(0 to 25)
hurt_icon = "hurt_100"
if(26 to 50)
hurt_icon = "hurt_75"
if(51 to 75)
hurt_icon = "hurt_50"
else
hurt_icon = "hurt_25"
overlays += image(icon,hurt_icon, layer = layer+0.15)
/obj/effect/blob/proc/update_looks(var/right_now = 0)
switch(blob_looks[looks])
if(64)
icon_state = icon_new
pixel_x = -16
pixel_y = -16
layer = layer_new
if(right_now)
spawning = 0
if(32)
icon_state = icon_classic
pixel_x = 0
pixel_y = 0
layer = 3
overlays.len = 0
switch(looks)
if("new")
icon = 'icons/mob/blob_64x64.dmi'
if("classic")
icon = 'icons/mob/blob.dmi'
//<----------------------------------------------------------------------------DEAR SPRITERS, THIS IS WHERE YOU ADD YOUR NEW BLOB DMIs
/*EXAMPLES
if("fleshy")
icon = 'icons/mob/blob_fleshy.dmi'
if("machineblob")
icon = 'icons/mob/blob_machine.dmi'
*/
if(right_now)
update_icon()
var/list/blob_looks = list(
"new" = 64,
"classic" = 32,
)
//<---------------------------------------ALSO ADD THE NAME OF YOUR BLOB LOOKS HERE, AS WELL AS THE RESOLUTION OF THE DMIS (64 or 32)
/obj/effect/blob/proc/Life()
return
/obj/effect/blob/proc/aftermove()
for(var/obj/effect/blob/B in loc)
if(B != src)
qdel(src)
return
update_icon()
for(var/obj/effect/blob/B in orange(src,1))
B.update_icon()
/obj/effect/blob/proc/Pulse(var/pulse = 0, var/origin_dir = 0)//Todo: Fix spaceblob expand
/*
if(time_since_last_pulse >= world.time)
return
*/
time_since_last_pulse = world.time
//set background = 1
for(var/mob/M in loc)
M.blob_act()
if(run_action())//If we can do something here then we dont need to pulse more
return
@@ -116,7 +305,8 @@
if(!B)
expand(T)//No blob here so try and expand
return
B.Pulse((pulse+1),get_dir(src.loc,T))
spawn(2)
B.Pulse((pulse+1),get_dir(src.loc,T))
return
return
@@ -124,7 +314,6 @@
/obj/effect/blob/proc/run_action()
return 0
/obj/effect/blob/proc/expand(var/turf/T = null, var/prob = 1)
if(prob && !prob(health))
return
@@ -139,11 +328,25 @@
else T = null
if(!T) return 0
var/obj/effect/blob/normal/B = new(src.loc, min(src.health, 30))
var/obj/effect/blob/normal/B = new(src.loc, newlook = looks)
B.density = 1
if(blob_looks[looks] == 64)
if(istype(src,/obj/effect/blob/normal))
var/num = rand(1,100)
num /= 10000
B.layer = layer - num
if(T.Enter(B,src))//Attempt to move into the tile
B.density = initial(B.density)
B.loc = T
if(blob_looks[looks] == 64)
spawn(1)
B.forceMove(T)
B.aftermove()
if(B.spawning > 1)
B.spawning = 1
else
B.forceMove(T)
else
T.blob_act()//If we cant move in hit the turf
B.Delete()
@@ -153,69 +356,74 @@
return 1
/obj/effect/blob/ex_act(severity)
var/damage = 150
health -= ((damage/brute_resist) - (severity * 5))
update_icon()
return
/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj)
..()
switch(Proj.damage_type)
if(BRUTE)
health -= (Proj.damage/brute_resist)
if(BURN)
health -= (Proj.damage/fire_resist)
update_icon()
return 0
/obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/user)
user.delayNextAttack(10)
playsound(get_turf(src), 'sound/effects/attackblob.ogg', 50, 1)
src.visible_message("<span class='warning'><B>The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]</span>")
var/damage = 0
switch(W.damtype)
if("fire")
damage = (W.force / max(src.fire_resist,1))
if(istype(W, /obj/item/weapon/weldingtool))
playsound(get_turf(src), 'sound/effects/blobweld.ogg', 100, 1)
if("brute")
damage = (W.force / max(src.brute_resist,1))
health -= damage
update_icon()
return
/obj/effect/blob/proc/change_to(var/type, var/mob/camera/blob/M = null)
if(!ispath(type))
error("[type] is an invalid type for the blob.")
if("[type]" == "/obj/effect/blob/core")
new type(src.loc, 200, null, 1, M)
new type(src.loc, 200, null, 1, M, newlook = looks)
else
new type(src.loc)
new type(src.loc, newlook = looks)
spawning = 1//so we don't show red severed connections
Delete()
return
/obj/effect/blob/proc/Delete()
qdel(src)
/obj/effect/blob/proc/update_health()
if(health <= 0)
dying = 1
playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1)
Delete()
return
//////////////////NORMAL BLOBS/////////////////////////////////
/obj/effect/blob/normal
icon_state = "blob"
luminosity = 0
luminosity = 2
health = 21
/obj/effect/blob/normal/Delete()
src.loc = null
blobs -= src
..()
/obj/effect/blob/normal/update_icon()
if(health <= 0)
playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1)
Delete()
return
if(health <= 15)
icon_state = "blob_damaged"
return
/obj/effect/blob/normal/Pulse(var/pulse = 0, var/origin_dir = 0)
..()
if(blob_looks[looks] == 64)
anim(target = loc, a_icon = icon, flick_anim = "pulse", sleeptime = 15, direction = dir, lay = 12, offX = -16, offY = -16, alph = 51)
/obj/effect/blob/normal/update_icon(var/spawnend = 0)
if(blob_looks[looks] == 64)
spawn(1)
overlays.len = 0
overlays += image(icon,"roots", layer = 3)
if(!spawning)
for(var/obj/effect/blob/B in orange(src,1))
if(B.spawning == 1)
anim(target = loc, a_icon = icon, flick_anim = "connect_spawn", sleeptime = 15, direction = get_dir(src,B), lay = layer+0.1, offX = -16, offY = -16)
spawn(8)
update_icon()
else if(!B.dying && !B.spawning)
if(spawnend)
anim(target = loc, a_icon = icon, flick_anim = "connect_spawn", sleeptime = 15, direction = get_dir(src,B), lay = layer+0.1, offX = -16, offY = -16)
else
if(istype(B,/obj/effect/blob/core))
overlays += image(icon,"connect",dir = get_dir(src,B), layer = layer)
else
var/num = rand(1,100)
num /= 10000
overlays += image(icon,"connect",dir = get_dir(src,B), layer = layer+0.1-num)
if(spawnend)
spawn(10)
update_icon()
..()
else
if(health <= 15)
icon_state = "blob_damaged"
return

View File

@@ -80,6 +80,9 @@ would spawn and follow the beaker, even if it is carried or thrown.
/obj/effect/canSingulothPull(var/obj/machinery/singularity/singulo)
return 0
/obj/effect/blob_act()
return
/////////////////////////////////////////////
// GENERIC STEAM SPREAD SYSTEM

View File

@@ -17,6 +17,9 @@
/obj/effect/overlay/singularity_pull()
return
/obj/effect/overlay/blob_act()
return
/obj/effect/overlay/beam//Not actually a projectile, just an effect.
name="beam"
icon='icons/effects/beam.dmi'

View File

@@ -90,6 +90,7 @@
return
/obj/item/blob_act()
..()
qdel(src)
/obj/item/proc/restock() //used for borg recharging

View File

@@ -18,6 +18,7 @@
for(var/obj/effect/blob/B in get_hear(8,flashbang_turf)) //Blob damage here
var/damage = round(15/(get_dist(B,get_turf(src))+1))
B.health -= damage
B.update_health()
B.update_icon()
qdel(src)

View File

@@ -3,6 +3,7 @@ obj/structure
penetration_dampening = 5
obj/structure/blob_act()
..()
if(prob(50))
qdel(src)

View File

@@ -281,6 +281,7 @@
..()
/obj/structure/girder/blob_act()
..()
if(prob(40))
qdel(src)

View File

@@ -54,6 +54,7 @@
return
/obj/structure/grille/blob_act()
..()
health -= rand(initial(health)*0.8, initial(health)*3) //Grille will always be blasted, but chances of leaving things over
healthcheck(hitsound = 1)

View File

@@ -125,7 +125,7 @@
return
/obj/structure/window/blob_act()
..()
health -= rand(30, 50)
healthcheck()

View File

@@ -79,6 +79,7 @@
return dismantle_wall()
/turf/simulated/wall/blob_act()
..()
if(prob(50) || rotting)
dismantle_wall()

View File

@@ -27,7 +27,7 @@
//Does not require sleeptime, specifies for how long the animation should be allowed to exist before returning to pool
//Does not require animation direction, but you can specify
//Does not require a name
proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,flick_anim as text,sleeptime = 0,direction as num, name as text)
proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,flick_anim as text,sleeptime = 0,direction as num, name as text, lay as num, offX as num, offY as num, col as text, alph as num)
//This proc throws up either an icon or an animation for a specified amount of time.
//The variables should be apparent enough.
if(!location && target)
@@ -39,17 +39,32 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
animation.name = name
if(direction)
animation.dir = direction
if(alph)
animation.alpha = alph
animation.icon = a_icon
animation.layer = target:layer+1
animation.animate_movement = 0
animation.mouse_opacity = 0
if(!lay)
animation.layer = target:layer+1
else
animation.layer = lay
if(offX)
animation.pixel_x = offX
if(offY)
animation.pixel_y = offY
if(col)
animation.color = col
if(a_icon_state)
animation.icon_state = a_icon_state
else
animation.icon_state = "blank"
animation.master = target
flick(flick_anim, animation)
spawn(max(sleeptime, 15))
returnToPool(animation)
/*
//called when the tile is cultified
/turf/proc/cultification()

View File

@@ -118,7 +118,8 @@ var/list/admin_verbs_fun = list(
/client/proc/smissmas,
/client/proc/achievement,
/client/proc/mommi_static,
/client/proc/makepAI
/client/proc/makepAI,
/client/proc/set_blob_looks,
)
var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, // Allows us to spawn instances
@@ -1035,6 +1036,19 @@ var/list/admin_verbs_mod = list(
holder.shuttle_magic()
/client/proc/set_blob_looks()
set name = "Set Blob Looks"
set category = "Fun"
var/chosen = input("This will change the looks of every blob currently in the world.", "Blob Looks", blob_looks[1]) as null|anything in blob_looks
if(chosen)
for(var/obj/effect/blob/B in blobs)
B.looks = chosen
B.update_looks(1)
log_admin("[key_name(src)] set all blobs to use the \"[chosen]\" look.")
message_admins("<span class='notice'>[key_name_admin(src)] set all blobs to use the \"[chosen]\" look.</span>")
/datum/admins/proc/media_stop_all()
set name = "Stop All Media"

View File

@@ -142,6 +142,15 @@
/atom/movable/lighting_overlay/can_shuttle_move()
return 0
/atom/movable/lighting_overlay/singularity_act()
return
/atom/movable/lighting_overlay/singularity_pull()
return
/atom/movable/lighting_overlay/blob_act()
return
// Override here to prevent things accidentally moving around overlays.
/atom/movable/lighting_overlay/forceMove(atom/destination, var/harderforce = 0)
if(harderforce)

View File

@@ -37,4 +37,7 @@
return 0
/mob/dead/update_canmove()
return
/mob/dead/blob_act()
return

View File

@@ -49,3 +49,15 @@ var/list/stationary_hearers = list( /obj/item/device/radio/intercom,
/mob/virtualhearer/singularity_act()
return
/mob/virtualhearer/cultify()
return
/mob/virtualhearer/singuloCanEat()
return 0
/mob/virtualhearer/singularity_pull()
return
/mob/virtualhearer/blob_act()
return

View File

@@ -70,8 +70,9 @@
/mob/living/carbon/alien/humanoid/blob_act()
if(flags & INVULNERABLE)
return
if(stat == 2)
if(stat == DEAD)
return
..()
var/shielded = 0
var/damage = null
if(stat != 2)
@@ -82,6 +83,7 @@
to_chat(src, "<span class='warning'>The blob attacks you!</span>")
adjustFireLoss(damage)
return

View File

@@ -70,6 +70,7 @@
updatehealth()
/mob/living/carbon/alien/larva/blob_act()
..()
if(flags & INVULNERABLE)
return
if(stat == 2)

View File

@@ -209,18 +209,6 @@
stat("Spacepod Charge", "[istype(S.battery) ? "[(S.battery.charge / S.battery.maxcharge) * 100]" : "No cell detected"]")
stat("Spacepod Integrity", "[!S.health ? "0" : "[(S.health / initial(S.health)) * 100]"]%")
/mob/living/carbon/human/blob_act()
if(flags & INVULNERABLE)
return
if(stat == DEAD)
return
show_message("<span class='warning'>The blob attacks you!</span>")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone))
apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
return
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M as mob)
if(M.melee_damage_upper == 0)
M.emote("[M.friendly] [src]")

View File

@@ -408,9 +408,14 @@ emp_act
/mob/living/carbon/human/blob_act()
if(flags & INVULNERABLE)
return
if(stat == 2) return
show_message("<span class='warning'>The blob attacks you!</span>")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone))
apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
if(cloneloss < 120)
if(stat == DEAD)
..()
adjustCloneLoss(rand(5,25))
else
..()
show_message("<span class='warning'>The blob attacks you!</span>")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone))
apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
return

View File

@@ -679,7 +679,8 @@
/mob/living/carbon/monkey/blob_act()
if(flags & INVULNERABLE)
return
if (stat != 2)
..()
if (stat != DEAD)
adjustFireLoss(60)
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
if (prob(50))

View File

@@ -262,6 +262,7 @@
/mob/living/carbon/slime/blob_act()
..()
if(flags & INVULNERABLE)
return
if (stat == 2)

View File

@@ -292,6 +292,7 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t
/mob/living/simple_animal/blob_act()
..()
adjustBruteLoss(20)
return

View File

@@ -1 +1 @@
sandbox
sandbox

View File

@@ -0,0 +1,12 @@
author: Deity Link
delete-after: true
changes:
- rscadd: Blobs now emit a cloud of purple smoke over whatever they are affecting. So now you get a clear visual feedback when someone gets attacked by them, or they destroy something (wall or item).
- rscadd: Huge revamp of the blob's visuals. Blobs now support two kind of looks. classic ones (made from 32x32 dmi) and new ones (made from 64x64 dmi)
- rscadd: The new looks feature added overlays, animations, such as connections between the blobs, or various feedback animations (normal blob transmitting a pulse, factory producing a mob, resource producing a point, etc)
- rscadd: The new looks also features a damage overlay, letting you know approximately how much health the blob part has. In the classic look, only the normal blobs have a damaged sprite.
- rscadd: When a new blob gets created (through game mode, random event, or admin spawning), the overmind player gets to choose the blob's looks.
- rscadd: Admins can set the looks of every blobs in the world by the push of a new button under the Fun tab.
- rscadd: Resource blobs now look darker if the overmind they were connected to has died. Other overminds can hover near it to take ownership of them and re-activate them.
- tweak: Overminds are now immune to singularities, their pull, and Nar-Sie.
- rscadd: When a blob gets pulsed, it will now hurt any mob standing on their tile. Telescience teleporting you right next to the core so you can destroy it without any danger is no longer a viable strategy, unless you have a really good armor, a really powerful gun, and even then it will require some testing.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

After

Width:  |  Height:  |  Size: 256 KiB

BIN
icons/mob/blob_64x64.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.