initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
//Few global vars to track the blob
var/list/blobs = list() //complete list of all blobs made.
var/list/blob_cores = list()
var/list/overminds = list()
var/list/blob_nodes = list()
var/list/blobs_legit = list() //used for win-score calculations, contains only blobs counted for win condition
#define BLOB_NO_PLACE_TIME 1800 //time, in deciseconds, blobs are prevented from bursting in the gamemode
/datum/game_mode/blob
name = "blob"
config_tag = "blob"
antag_flag = ROLE_BLOB
required_players = 25
required_enemies = 1
recommended_enemies = 1
round_ends_with_antag_death = 1
var/burst = 0
var/cores_to_spawn = 1
var/players_per_core = 25
var/blob_point_rate = 3
var/blobwincount = 350
var/messagedelay_low = 2400 //in deciseconds
var/messagedelay_high = 3600 //blob report will be sent after a random value between these (minimum 4 minutes, maximum 6 minutes)
var/list/blob_overminds = list()
/datum/game_mode/blob/pre_setup()
cores_to_spawn = max(round(num_players()/players_per_core, 1), 1)
blobwincount = initial(blobwincount) * cores_to_spawn
for(var/j = 0, j < cores_to_spawn, j++)
if (!antag_candidates.len)
break
var/datum/mind/blob = pick(antag_candidates)
blob_overminds += blob
blob.assigned_role = "Blob"
blob.special_role = "Blob"
log_game("[blob.key] (ckey) has been selected as a Blob")
antag_candidates -= blob
if(!blob_overminds.len)
return 0
return 1
/datum/game_mode/blob/proc/get_blob_candidates()
var/list/candidates = list()
for(var/mob/living/carbon/human/player in player_list)
if(!player.stat && player.mind && !player.mind.special_role && !jobban_isbanned(player, "Syndicate") && (ROLE_BLOB in player.client.prefs.be_special))
if(age_check(player.client))
candidates += player
return candidates
/datum/game_mode/blob/announce()
world << "<B>The current game mode is - <font color='green'>Blob</font>!</B>"
world << "<B>A dangerous alien organism is rapidly spreading throughout the station!</B>"
world << "You must kill it all while minimizing the damage to the station."
/datum/game_mode/blob/proc/show_message(message)
for(var/datum/mind/blob in blob_overminds)
blob.current << message
/datum/game_mode/blob/post_setup()
for(var/datum/mind/blob in blob_overminds)
var/mob/camera/blob/B = blob.current.become_overmind(1)
var/turf/T = pick(blobstart)
B.loc = T
B.base_point_rate = blob_point_rate
SSshuttle.emergencyNoEscape = 1
// Disable the blob event for this round.
var/datum/round_event_control/blob/B = locate() in SSevent.control
if(B)
B.max_occurrences = 0 // disable the event
spawn(0)
var/message_delay = rand(messagedelay_low, messagedelay_high) //between 4 and 6 minutes with 2400 low and 3600 high.
sleep(message_delay)
send_intercept(1)
sleep(24000) //40 minutes, plus burst_delay*3(minimum of 6 minutes, maximum of 8)
send_intercept(2) //if the blob has been alive this long, it's time to bomb it
return ..()
+50
View File
@@ -0,0 +1,50 @@
/datum/game_mode/blob/check_finished()
if(blobwincount <= blobs_legit.len)//Blob took over
return 1
if(overminds.len)
return 0
if(!blob_cores.len) //blob is dead
if(config.continuous["blob"])
continuous_sanity_checked = 1 //Nonstandard definition of "alive" gets past the check otherwise
SSshuttle.emergencyNoEscape = 0
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
priority_announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority")
return ..()
return 1
return ..()
/datum/game_mode/blob/declare_completion()
if(round_converted) //So badmin blobs later don't step on the dead natural blobs metaphorical toes
..()
if(blobwincount <= blobs_legit.len)
feedback_set_details("round_end_result","win - blob took over")
world << "<FONT size = 3><B>The blob has taken over the station!</B></FONT>"
world << "<B>The entire station was eaten by the Blob</B>"
log_game("Blob mode completed with a blob victory.")
else if(station_was_nuked)
feedback_set_details("round_end_result","halfwin - nuke")
world << "<FONT size = 3><B>Partial Win: The station has been destroyed!</B></FONT>"
world << "<B>Directive 7-12 has been successfully carried out preventing the Blob from spreading.</B>"
log_game("Blob mode completed with a tie (station destroyed).")
else if(!blob_cores.len)
feedback_set_details("round_end_result","loss - blob eliminated")
world << "<FONT size = 3><B>The staff has won!</B></FONT>"
world << "<B>The alien organism has been eradicated from the station</B>"
log_game("Blob mode completed with a crew victory.")
..()
return 1
/datum/game_mode/proc/auto_declare_completion_blob()
if(istype(ticker.mode,/datum/game_mode/blob) )
var/datum/game_mode/blob/blob_mode = src
if(blob_mode.blob_overminds.len)
var/text = "<FONT size = 2><B>The blob[(blob_mode.blob_overminds.len > 1 ? "s were" : " was")]:</B></FONT>"
for(var/datum/mind/blob in blob_mode.blob_overminds)
text += printplayer(blob)
world << text
return 1
+111
View File
@@ -0,0 +1,111 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/datum/game_mode/blob/send_intercept(report = 0)
var/intercepttext = ""
switch(report)
if(1)
intercepttext += "<FONT size = 3><b>NanoTrasen Update</b>: Biohazard Alert.</FONT><HR>"
intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle.<BR>"
intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. The origin of the biohazard is unknown.<BR>"
intercepttext += "<b>Biohazard Response Procedure 5-6</b> has been issued for [station_name()].<BR>"
intercepttext += "Orders for all [station_name()] personnel are as follows:<BR>"
intercepttext += " 1. Locate any outbreaks of the organism on the station.<BR>"
intercepttext += " 2. If found, use any neccesary means to contain and destroy the organism.<BR>"
intercepttext += " 3. Avoid damage to the capital infrastructure of the station.<BR>"
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, <b>Biohazard Response Procedure 5-12</b> may be issued.<BR>"
print_command_report(intercepttext,"Level 5-6 Biohazard Response Procedures")
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
if(2)
var/nukecode = rand(10000, 99999)
for(var/obj/machinery/nuclearbomb/bomb in machines)
if(bomb && bomb.r_code)
if(bomb.z == ZLEVEL_STATION)
bomb.r_code = nukecode
intercepttext += "<FONT size = 3><b>NanoTrasen Update</b>: Biohazard Alert.</FONT><HR>"
intercepttext += "Reports indicate that the biohazard has grown out of control and will soon reach critical mass.<BR>"
intercepttext += "<b>Biohazard Response Procedure 5-12</b> has been issued for [station_name()].<BR>"
intercepttext += "Orders for all [station_name()] personnel are as follows:<BR>"
intercepttext += "1. Secure the Nuclear Authentication Disk.<BR>"
intercepttext += "2. Detonate the Nuke located in the vault.<BR>"
intercepttext += "Nuclear Authentication Code: [nukecode] <BR>"
print_command_report(intercepttext,"Classified [command_name()] Update")
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
for(var/mob/living/silicon/ai/aiPlayer in player_list)
if (aiPlayer.client)
var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard laws 1-3 if necessary to prevent, by any means necessary, anyone from leaving. The nuclear failsafe must be activated at any cost, the code is: [nukecode]."
aiPlayer.set_zeroth_law(law)
aiPlayer << "Laws Updated: [law]"
else
..()
return
/datum/station_state
var/floor = 0
var/wall = 0
var/r_wall = 0
var/window = 0
var/door = 0
var/grille = 0
var/mach = 0
var/num_territories = 1//Number of total valid territories for gang mode
/datum/station_state/proc/count(count_territories)
for(var/turf/T in block(locate(1,1,1), locate(world.maxx,world.maxy,1)))
if(istype(T,/turf/open/floor))
if(!(T:burnt))
src.floor += 12
else
src.floor += 1
if(istype(T, /turf/closed/wall))
if(T:intact)
src.wall += 2
else
src.wall += 1
if(istype(T, /turf/closed/wall/r_wall))
if(T:intact)
src.r_wall += 2
else
src.r_wall += 1
for(var/obj/O in T.contents)
if(istype(O, /obj/structure/window))
src.window += 1
else if(istype(O, /obj/structure/grille) && (!O:destroyed))
src.grille += 1
else if(istype(O, /obj/machinery/door))
src.door += 1
else if(istype(O, /obj/machinery))
src.mach += 1
if(count_territories)
var/list/valid_territories = list()
for(var/area/A in world) //First, collect all area types on the station zlevel
if(A.z == ZLEVEL_STATION)
if(!(A.type in valid_territories) && A.valid_territory)
valid_territories |= A.type
if(valid_territories.len)
num_territories = valid_territories.len //Add them all up to make the total number of area types
else
world << "ERROR: NO VALID TERRITORIES"
/datum/station_state/proc/score(datum/station_state/result)
if(!result)
return 0
var/output = 0
output += (result.floor / max(floor,1))
output += (result.r_wall/ max(r_wall,1))
output += (result.wall / max(wall,1))
output += (result.window / max(window,1))
output += (result.door / max(door,1))
output += (result.grille / max(grille,1))
output += (result.mach / max(mach,1))
return (output/7)
+282
View File
@@ -0,0 +1,282 @@
////////////////
// BASE TYPE //
////////////////
//Do not spawn
/mob/living/simple_animal/hostile/blob
icon = 'icons/mob/blob.dmi'
pass_flags = PASSBLOB
faction = list("blob")
bubble_icon = "blob"
speak_emote = null //so we use verb_yell/verb_say/etc
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
unique_name = 1
a_intent = "harm"
var/mob/camera/blob/overmind = null
var/obj/effect/blob/factory/factory = null
/mob/living/simple_animal/hostile/blob/update_icons()
if(overmind)
color = overmind.blob_reagent_datum.color
else
color = initial(color)
/mob/living/simple_animal/hostile/blob/Destroy()
if(overmind)
overmind.blob_mobs -= src
return ..()
/mob/living/simple_animal/hostile/blob/blob_act(obj/effect/blob/B)
if(stat != DEAD && health < maxHealth)
for(var/i in 1 to 2)
var/obj/effect/overlay/temp/heal/H = PoolOrNew(/obj/effect/overlay/temp/heal, get_turf(src)) //hello yes you are being healed
if(overmind)
H.color = overmind.blob_reagent_datum.complementary_color
else
H.color = "#000000"
adjustHealth(-maxHealth*0.0125)
/mob/living/simple_animal/hostile/blob/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
adjustFireLoss(Clamp(0.01 * exposed_temperature, 1, 5))
/mob/living/simple_animal/hostile/blob/CanPass(atom/movable/mover, turf/target, height = 0)
if(istype(mover, /obj/effect/blob))
return 1
return ..()
/mob/living/simple_animal/hostile/blob/Process_Spacemove(movement_dir = 0)
for(var/obj/effect/blob/B in range(1, src))
return 1
return ..()
/mob/living/simple_animal/hostile/blob/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_BINARY)
blob_chat(message)
return ITALICS | REDUCE_RANGE
else
..()
/mob/living/simple_animal/hostile/blob/proc/blob_chat(msg)
var/spanned_message = say_quote(msg, get_spans())
var/rendered = "<font color=\"#EE4000\"><b>\[Blob Telepathy\] [real_name]</b> [spanned_message]</font>"
for(var/M in mob_list)
if(isovermind(M) || istype(M, /mob/living/simple_animal/hostile/blob))
M << rendered
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
M << "[link] [rendered]"
////////////////
// BLOB SPORE //
////////////////
/mob/living/simple_animal/hostile/blob/blobspore
name = "blob spore"
desc = "A floating, fragile spore."
icon_state = "blobpod"
icon_living = "blobpod"
health = 40
maxHealth = 40
verb_say = "psychically pulses"
verb_ask = "psychically probes"
verb_exclaim = "psychically yells"
verb_yell = "psychically screams"
melee_damage_lower = 2
melee_damage_upper = 4
attacktext = "hits"
attack_sound = 'sound/weapons/genhit1.ogg'
flying = 1
del_on_death = 1
deathmessage = "explodes into a cloud of gas!"
var/death_cloud_size = 1 //size of cloud produced from a dying spore
var/list/human_overlays = list()
var/is_zombie = 0
gold_core_spawnable = 1
/mob/living/simple_animal/hostile/blob/blobspore/New(loc, var/obj/effect/blob/factory/linked_node)
if(istype(linked_node))
factory = linked_node
factory.spores += src
..()
/mob/living/simple_animal/hostile/blob/blobspore/Life()
if(!is_zombie && isturf(src.loc))
for(var/mob/living/carbon/human/H in view(src,1)) //Only for corpse right next to/on same tile
if(H.stat == DEAD)
Zombify(H)
break
if(factory && z != factory.z)
death()
..()
/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H)
is_zombie = 1
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor["melee"])
maxHealth += A.armor["melee"] //That zombie's got armor, I want armor!
maxHealth += 40
health = maxHealth
name = "blob zombie"
desc = "A shambling corpse animated by the blob."
melee_damage_lower += 8
melee_damage_upper += 11
flying = 0
death_cloud_size = 0
icon = H.icon
icon_state = "zombie_s"
H.hair_style = null
H.update_hair()
human_overlays = H.overlays
update_icons()
H.forceMove(src)
visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
// 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(10)
if(overmind && overmind.blob_reagent_datum)
reagents.add_reagent(overmind.blob_reagent_datum.id, 10)
else
reagents.add_reagent("spore", 10)
// Attach the smoke spreader and setup/start it.
S.attach(location)
S.set_up(reagents, death_cloud_size, location, silent=1)
S.start()
if(factory)
factory.spore_delay = world.time + factory.spore_cooldown //put the factory on cooldown
..()
/mob/living/simple_animal/hostile/blob/blobspore/Destroy()
if(factory)
factory.spores -= src
factory = null
if(contents)
for(var/mob/M in contents)
M.loc = src.loc
return ..()
/mob/living/simple_animal/hostile/blob/blobspore/update_icons()
..()
if(is_zombie)
cut_overlays()
overlays = human_overlays
var/image/I = image('icons/mob/blob.dmi', icon_state = "blob_head")
if(overmind)
I.color = overmind.blob_reagent_datum.color
color = initial(color)//looks better.
add_overlay(I)
/mob/living/simple_animal/hostile/blob/blobspore/weak
name = "fragile blob spore"
health = 20
maxHealth = 20
melee_damage_lower = 1
melee_damage_upper = 2
death_cloud_size = 0
/////////////////
// BLOBBERNAUT //
/////////////////
/mob/living/simple_animal/hostile/blob/blobbernaut
name = "blobbernaut"
desc = "A hulking, mobile chunk of blobmass."
icon_state = "blobbernaut"
icon_living = "blobbernaut"
icon_dead = "blobbernaut_dead"
health = 200
maxHealth = 200
damage_coeff = list(BRUTE = 0.5, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
next_move_modifier = 1.5 //slow-ass attack speed, 3 times higher than how fast the blob can attack
melee_damage_lower = 20
melee_damage_upper = 20
attacktext = "slams"
attack_sound = 'sound/effects/blobattack.ogg'
verb_say = "gurgles"
verb_ask = "demands"
verb_exclaim = "roars"
verb_yell = "bellows"
force_threshold = 10
pressure_resistance = 40
mob_size = MOB_SIZE_LARGE
see_invisible = SEE_INVISIBLE_MINIMUM
see_in_dark = 8
var/independent = FALSE
/mob/living/simple_animal/hostile/blob/blobbernaut/New()
..()
if(!independent) //no pulling people deep into the blob
verbs -= /mob/living/verb/pulled
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
if(..())
if(independent)
return // strong independent blobbernaut that don't need no blob
var/damagesources = 0
if(!(locate(/obj/effect/blob) in range(2, src)))
damagesources++
if(!factory)
damagesources++
if(damagesources)
for(var/i in 1 to damagesources)
adjustHealth(maxHealth*0.025) //take 2.5% maxhealth as damage when not near the blob or if the naut has no factory, 5% if both
var/list/viewing = list()
for(var/mob/M in viewers(src))
if(M.client)
viewing += M.client
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
flick_overlay(I, viewing, 8)
/mob/living/simple_animal/hostile/blob/blobbernaut/adjustHealth(amount)
. = ..()
update_health_hud()
/mob/living/simple_animal/hostile/blob/blobbernaut/update_health_hud()
if(hud_used)
hud_used.healths.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#e36600'>[round((health / maxHealth) * 100, 0.5)]%</font></div>"
/mob/living/simple_animal/hostile/blob/blobbernaut/AttackingTarget()
if(isliving(target))
if(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.
if(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
else
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
attacktext = initial(attacktext)
/mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed)
..(gibbed)
if(factory)
factory.naut = null //remove this naut from its factory
factory.maxhealth = initial(factory.maxhealth)
flick("blobbernaut_death", src)
/mob/living/simple_animal/hostile/blob/blobbernaut/independent
independent = TRUE
gold_core_spawnable = 1
+109
View File
@@ -0,0 +1,109 @@
/obj/effect/blob/core
name = "blob core"
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
desc = "A huge, pulsating yellow mass."
health = 400
maxhealth = 400
explosion_block = 6
point_return = -1
atmosblock = 1
health_regen = 0 //we regen in Life() instead of when pulsed
var/core_regen = 2
var/overmind_get_delay = 0 //we don't want to constantly try to find an overmind, this var tracks when we'll try to get an overmind again
var/resource_delay = 0
var/point_rate = 2
/obj/effect/blob/core/New(loc, client/new_overmind = null, new_rate = 2, placed = 0)
blob_cores += src
START_PROCESSING(SSobj, src)
poi_list |= src
update_icon() //so it atleast appears
if(!placed && !overmind)
create_overmind(new_overmind)
if(overmind)
update_icon()
point_rate = new_rate
..()
/obj/effect/blob/core/scannerreport()
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
/obj/effect/blob/core/update_icon()
cut_overlays()
color = null
var/image/I = new('icons/mob/blob.dmi', "blob")
if(overmind)
I.color = overmind.blob_reagent_datum.color
add_overlay(I)
var/image/C = new('icons/mob/blob.dmi', "blob_core_overlay")
add_overlay(C)
/obj/effect/blob/core/Destroy()
blob_cores -= src
if(overmind)
overmind.blob_core = null
overmind = null
STOP_PROCESSING(SSobj, src)
poi_list -= src
return ..()
/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
/obj/effect/blob/core/ex_act(severity, target)
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)
/obj/effect/blob/core/check_health()
..()
if(overmind) //we should have an overmind, but...
overmind.update_health_hud()
/obj/effect/blob/core/Life()
if(!overmind)
create_overmind()
else
if(resource_delay <= world.time)
resource_delay = world.time + 10 // 1 second
overmind.add_points(point_rate)
health = min(maxhealth, health+core_regen)
if(overmind)
overmind.update_health_hud()
Pulse_Area(overmind, 12, 4, 3)
for(var/obj/effect/blob/normal/B in range(1, src))
if(prob(5))
B.change_to(/obj/effect/blob/shield/core, overmind)
..()
/obj/effect/blob/core/proc/create_overmind(client/new_overmind, override_delay)
if(overmind_get_delay > world.time && !override_delay)
return
overmind_get_delay = world.time + 150 //if this fails, we'll try again in 15 seconds
if(overmind)
qdel(overmind)
var/client/C = null
var/list/candidates = list()
if(!new_overmind)
candidates = get_candidates(ROLE_BLOB)
if(candidates.len)
C = pick(candidates)
else
C = new_overmind
if(C)
var/mob/camera/blob/B = new(src.loc, 1)
B.key = C.key
B.blob_core = src
src.overmind = B
update_icon()
if(B.mind && !B.mind.special_role)
B.mind.special_role = "Blob Overmind"
return 1
return 0
+47
View File
@@ -0,0 +1,47 @@
/obj/effect/blob/factory
name = "factory blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_factory"
desc = "A thick spire of tendrils."
health = 200
maxhealth = 200
health_regen = 1
point_return = 25
var/list/spores = list()
var/mob/living/simple_animal/hostile/blob/blobbernaut/naut = null
var/max_spores = 3
var/spore_delay = 0
var/spore_cooldown = 80 //8 seconds between spores and after spore death
/obj/effect/blob/factory/scannerreport()
if(naut)
return "It is currently sustaining a blobbernaut, making it fragile and unable to produce blob spores."
return "Will produce a blob spore every few seconds."
/obj/effect/blob/factory/Destroy()
for(var/mob/living/simple_animal/hostile/blob/blobspore/spore in spores)
if(spore.factory == src)
spore.factory = null
if(naut)
naut.factory = null
naut << "<span class='userdanger'>Your factory was destroyed! You feel yourself dying!</span>"
naut.throw_alert("nofactory", /obj/screen/alert/nofactory)
spores = null
return ..()
/obj/effect/blob/factory/Be_Pulsed()
. = ..()
if(naut)
return
if(spores.len >= max_spores)
return
if(spore_delay > world.time)
return
flick("blob_factory_glow", src)
spore_delay = world.time + spore_cooldown
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src)
if(overmind) //if we don't have an overmind, we don't need to do anything but make a spore
BS.overmind = overmind
BS.update_icons()
overmind.blob_mobs.Add(BS)
+41
View File
@@ -0,0 +1,41 @@
/obj/effect/blob/node
name = "blob node"
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
desc = "A large, pulsating yellow mass."
health = 200
maxhealth = 200
health_regen = 3
point_return = 25
atmosblock = 1
/obj/effect/blob/node/New(loc, var/h = 100)
blob_nodes += src
START_PROCESSING(SSobj, src)
..(loc, h)
/obj/effect/blob/node/scannerreport()
return "Gradually expands and sustains nearby blob spores and blobbernauts."
/obj/effect/blob/node/update_icon()
cut_overlays()
color = null
var/image/I = new('icons/mob/blob.dmi', "blob")
if(overmind)
I.color = overmind.blob_reagent_datum.color
src.add_overlay(I)
var/image/C = new('icons/mob/blob.dmi', "blob_node_overlay")
src.add_overlay(C)
/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
/obj/effect/blob/node/Destroy()
blob_nodes -= src
STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/blob/node/Life()
Pulse_Area(overmind, 10, 3, 2)
color = null
@@ -0,0 +1,32 @@
/obj/effect/blob/resource
name = "resource blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
desc = "A thin spire of slightly swaying tendrils."
health = 60
maxhealth = 60
point_return = 15
var/resource_delay = 0
/obj/effect/blob/resource/scannerreport()
return "Gradually supplies the blob with resources, increasing the rate of expansion."
/obj/effect/blob/resource/creation_action()
if(overmind)
overmind.resource_blobs += src
/obj/effect/blob/resource/Destroy()
if(overmind)
overmind.resource_blobs -= src
return ..()
/obj/effect/blob/resource/Be_Pulsed()
. = ..()
if(resource_delay > world.time)
return
flick("blob_resource_glow", src)
if(overmind)
overmind.add_points(1)
resource_delay = world.time + 40 + overmind.resource_blobs.len * 2.5 //4 seconds plus a quarter second for each resource blob the overmind has
else
resource_delay = world.time + 40
+21
View File
@@ -0,0 +1,21 @@
/obj/effect/blob/shield
name = "strong blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_idle"
desc = "A solid wall of slightly twitching tendrils."
health = 150
maxhealth = 150
brute_resist = 0.1
explosion_block = 3
point_return = 4
atmosblock = 1
/obj/effect/blob/shield/scannerreport()
return "Will prevent the spread of atmospheric changes."
/obj/effect/blob/shield/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
/obj/effect/blob/shield/core
point_return = 0
+175
View File
@@ -0,0 +1,175 @@
/mob/camera/blob
name = "Blob Overmind"
real_name = "Blob Overmind"
icon = 'icons/mob/blob.dmi'
icon_state = "marker"
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
invisibility = INVISIBILITY_OBSERVER
pass_flags = PASSBLOB
faction = list("blob")
var/obj/effect/blob/core/blob_core = null // The blob overmind's core
var/blob_points = 0
var/max_blob_points = 100
var/last_attack = 0
var/datum/reagent/blob/blob_reagent_datum = new/datum/reagent/blob()
var/list/blob_mobs = list()
var/list/resource_blobs = list()
var/ghostimage = null
var/free_chem_rerolls = 1 //one free chemical reroll
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
/mob/camera/blob/New(loc, pre_placed = 0, mode_made = 0)
if(pre_placed) //we already have a core!
manualplace_min_time = 0
autoplace_max_time = 0
placed = 1
else
if(mode_made)
manualplace_min_time = world.time + BLOB_NO_PLACE_TIME
else
manualplace_min_time += world.time
autoplace_max_time += world.time
overminds += src
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.update_icon()
ghostimage = image(src.icon,src,src.icon_state)
ghost_darkness_images |= ghostimage //so ghosts can see the blob cursor when they disable darkness
updateallghostimages()
..()
/mob/camera/blob/Life()
if(!blob_core)
if(!placed)
if(manualplace_min_time && world.time >= manualplace_min_time)
src << "<b><span class='big'><font color=\"#EE4000\">You may now place your blob core.</font></span></b>"
src << "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [round((autoplace_max_time - world.time)/600, 0.5)] minutes.</font></span>"
manualplace_min_time = 0
if(autoplace_max_time && world.time >= autoplace_max_time)
place_blob_core(base_point_rate, 1)
else
qdel(src)
..()
/mob/camera/blob/Destroy()
for(var/BL in blobs)
var/obj/effect/blob/B = BL
if(B.overmind == src)
B.overmind = null
B.update_icon() //reset anything that was ours
for(var/BLO in blob_mobs)
var/mob/living/simple_animal/hostile/blob/BM = BLO
BM.overmind = null
BM.update_icons()
overminds -= src
if(ghostimage)
ghost_darkness_images -= ghostimage
qdel(ghostimage)
ghostimage = null;
updateallghostimages()
return ..()
/mob/camera/blob/Login()
..()
sync_mind()
src << "<span class='notice'>You are the overmind!</span>"
blob_help()
update_health_hud()
/mob/camera/blob/update_health_hud()
if(blob_core)
hud_used.healths.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#e36600'>[round(blob_core.health)]</font></div>"
for(var/mob/living/simple_animal/hostile/blob/blobbernaut/B in blob_mobs)
if(B.hud_used && B.hud_used.blobpwrdisplay)
B.hud_used.blobpwrdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#82ed00'>[round(blob_core.health)]</font></div>"
/mob/camera/blob/proc/add_points(points)
if(points != 0)
blob_points = Clamp(blob_points + points, 0, max_blob_points)
hud_used.blobpwrdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#82ed00'>[round(src.blob_points)]</font></div>"
/mob/camera/blob/say(message)
if (!message)
return
if (src.client)
if(client.prefs.muted & MUTE_IC)
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/blob_talk(message)
log_say("[key_name(src)] : [message]")
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if (!message)
return
var/message_a = say_quote(message, get_spans())
var/rendered = "<span class='big'><font color=\"#EE4000\"><b>\[Blob Telepathy\] [name](<font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</font>)</b> [message_a]</font></span>"
for(var/mob/M in mob_list)
if(isovermind(M) || istype(M, /mob/living/simple_animal/hostile/blob))
M << rendered
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
M << "[link] [rendered]"
/mob/camera/blob/emote(act,m_type=1,message = null)
return
/mob/camera/blob/blob_act(obj/effect/blob/B)
return
/mob/camera/blob/Stat()
..()
if(statpanel("Status"))
if(blob_core)
stat(null, "Core Health: [blob_core.health]")
stat(null, "Power Stored: [blob_points]/[max_blob_points]")
if(free_chem_rerolls)
stat(null, "You have [free_chem_rerolls] Free Chemical 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)]")
stat(null, "Time Before Automatic Placement: [max(round((autoplace_max_time - world.time)*0.1, 0.1), 0)]")
/mob/camera/blob/Move(NewLoc, Dir = 0)
if(placed)
var/obj/effect/blob/B = locate() in range("3x3", NewLoc)
if(B)
loc = NewLoc
else
return 0
else
var/area/A = get_area(NewLoc)
if(istype(NewLoc, /turf/open/space) || istype(A, /area/shuttle)) //if unplaced, can't go on shuttles or space tiles
return 0
loc = NewLoc
return 1
/mob/camera/blob/proc/can_attack()
return (world.time > (last_attack + CLICK_CD_RANGE))
+332
View File
@@ -0,0 +1,332 @@
/mob/camera/blob/proc/can_buy(cost = 15)
if(blob_points < cost)
src << "<span class='warning'>You cannot afford this, you need at least [cost] resources!</span>"
return 0
add_points(-cost)
return 1
// Power verbs
/mob/camera/blob/proc/place_blob_core(point_rate, placement_override)
if(placed && placement_override != -1)
return 1
if(!placement_override)
for(var/mob/living/M in range(7, src))
if("blob" in M.faction)
continue
if(M.client)
src << "<span class='warning'>There is someone too close to place your blob core!</span>"
return 0
for(var/mob/living/M in view(13, src))
if("blob" in M.faction)
continue
if(M.client)
src << "<span class='warning'>Someone could see your blob core from here!</span>"
return 0
var/turf/T = get_turf(src)
if(T.density)
src << "<span class='warning'>This spot is too dense to place a blob core on!</span>"
return 0
for(var/obj/O in T)
if(istype(O, /obj/effect/blob))
if(istype(O, /obj/effect/blob/normal))
qdel(O)
else
src << "<span class='warning'>There is already a blob here!</span>"
return 0
if(O.density)
src << "<span class='warning'>This spot is too dense to place a blob core on!</span>"
return 0
if(world.time <= manualplace_min_time && world.time <= autoplace_max_time)
src << "<span class='warning'>It is too early to place your blob core!</span>"
return 0
else if(placement_override == 1)
var/turf/T = pick(blobstart)
loc = T //got overrided? you're somewhere random, motherfucker
if(placed && blob_core)
blob_core.forceMove(loc)
else
var/obj/effect/blob/core/core = new(get_turf(src), null, point_rate, 1)
core.overmind = src
blob_core = core
core.update_icon()
update_health_hud()
placed = 1
return 1
/mob/camera/blob/verb/transport_core()
set category = "Blob"
set name = "Jump to Core"
set desc = "Move your camera 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 = "Move your camera to a selected node."
if(blob_nodes.len)
var/list/nodes = list()
for(var/i = 1; i <= blob_nodes.len; i++)
nodes["Blob Node #[i]"] = blob_nodes[i]
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
var/obj/effect/blob/node/chosen_node = nodes[node_name]
if(chosen_node)
src.loc = chosen_node.loc
/mob/camera/blob/proc/createSpecial(price, blobType, nearEquals, needsNode, turf/T)
if(!T)
T = get_turf(src)
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)
src << "<span class='warning'>There is no blob here!</span>"
return
if(!istype(B, /obj/effect/blob/normal))
src << "<span class='warning'>Unable to use this blob, find a normal one.</span>"
return
if(needsNode && nodes_required)
if(!(locate(/obj/effect/blob/node) in orange(3, T)) && !(locate(/obj/effect/blob/core) in orange(4, T)))
src << "<span class='warning'>You need to place this blob closer to a node or core!</span>"
return //handholdotron 2000
if(nearEquals)
for(var/obj/effect/blob/L in orange(nearEquals, T))
if(L.type == blobType)
src << "<span class='warning'>There is a similar blob nearby, move more than [nearEquals] tiles away from it!</span>"
return
if(!can_buy(price))
return
var/obj/effect/blob/N = B.change_to(blobType, src)
return N
/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)
src << "<span class='warning'>You now require a nearby node or core to place factory and resource blobs.</span>"
else
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 Shield Blob (10)"
set desc = "Create a shield blob, which will block fire and is hard to kill."
create_shield()
/mob/camera/blob/proc/create_shield(turf/T)
createSpecial(10, /obj/effect/blob/shield, 0, 0, T)
/mob/camera/blob/verb/create_resource()
set category = "Blob"
set name = "Create Resource Blob (40)"
set desc = "Create a resource tower which will generate resources for you."
createSpecial(40, /obj/effect/blob/resource, 4, 1)
/mob/camera/blob/verb/create_node()
set category = "Blob"
set name = "Create Node Blob (60)"
set desc = "Create a node, which will power nearby factory and resource blobs."
createSpecial(60, /obj/effect/blob/node, 5, 0)
/mob/camera/blob/verb/create_factory()
set category = "Blob"
set name = "Create Factory Blob (60)"
set desc = "Create a spore tower that will spawn spores to harass your enemies."
createSpecial(60, /obj/effect/blob/factory, 7, 1)
/mob/camera/blob/verb/create_blobbernaut()
set category = "Blob"
set name = "Create Blobbernaut (40)"
set desc = "Create a powerful blobbernaut which is mildly smart and will attack enemies."
var/turf/T = get_turf(src)
var/obj/effect/blob/factory/B = locate(/obj/effect/blob/factory) in T
if(!B)
src << "<span class='warning'>You must be on a factory blob!</span>"
return
if(B.naut) //if it already made a blobbernaut, it can't do it again
src << "<span class='warning'>This factory blob is already sustaining a blobbernaut.</span>"
return
if(B.health < B.maxhealth * 0.5)
src << "<span class='warning'>This factory blob is too damaged to sustain a blobbernaut.</span>"
return
if(!can_buy(40))
return
B.maxhealth = initial(B.maxhealth) * 0.25 //factories that produced a blobbernaut have much lower health
B.check_health()
B.visible_message("<span class='warning'><b>The blobbernaut [pick("rips", "tears", "shreds")] its way out of the factory blob!</b></span>")
playsound(B.loc, 'sound/effects/splat.ogg', 50, 1)
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut(get_turf(B))
flick("blobbernaut_produce", blobber)
B.naut = blobber
blobber.factory = B
blobber.overmind = src
blobber.update_icons()
blobber.notransform = 1 //stop the naut from moving around
blobber.adjustHealth(blobber.maxHealth * 0.5)
blob_mobs += blobber
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [blob_reagent_datum.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly
var/client/C = null
if(candidates.len) //if we got at least one candidate, they're a blobbernaut now.
C = pick(candidates)
blobber.notransform = 0
blobber.key = C.key
blobber << 'sound/effects/blobattack.ogg'
blobber << 'sound/effects/attackblob.ogg'
blobber << "<b>You are a blobbernaut!</b>"
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."
blobber << "You can communicate with other blobbernauts and overminds via <b>:b</b>"
blobber << "Your overmind's blob reagent is: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!"
blobber << "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.shortdesc ? "[blob_reagent_datum.shortdesc]" : "[blob_reagent_datum.description]"]"
else
blobber.notransform = 0 //otherwise, just let it move
/mob/camera/blob/verb/relocate_core()
set category = "Blob"
set name = "Relocate Core (80)"
set desc = "Swaps the locations of your core and the selected node."
var/turf/T = get_turf(src)
var/obj/effect/blob/node/B = locate(/obj/effect/blob/node) in T
if(!B)
src << "<span class='warning'>You must be on a blob node!</span>"
return
if(!can_buy(80))
return
var/turf/old_turf = blob_core.loc
blob_core.loc = T
B.loc = old_turf
/mob/camera/blob/verb/revert()
set category = "Blob"
set name = "Remove Blob"
set desc = "Removes a blob, giving you back some resources."
var/turf/T = get_turf(src)
remove_blob(T)
/mob/camera/blob/proc/remove_blob(turf/T)
var/obj/effect/blob/B = locate() in T
if(!B)
src << "<span class='warning'>There is no blob there!</span>"
return
if(B.point_return < 0)
src << "<span class='warning'>Unable to remove this blob.</span>"
return
if(max_blob_points < B.point_return + blob_points)
src << "<span class='warning'>You have too many resources to remove this blob!</span>"
return
if(B.point_return)
add_points(B.point_return)
src << "<span class='notice'>Gained [B.point_return] resources from removing \the [B].</span>"
qdel(B)
/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, instead attacks it, damaging mobs and objects."
var/turf/T = get_turf(src)
expand_blob(T)
/mob/camera/blob/proc/expand_blob(turf/T)
if(!can_attack())
return
var/obj/effect/blob/OB = locate() in circlerange(T, 1)
if(!OB)
src << "<span class='warning'>There is no blob adjacent to the target tile!</span>"
return
if(can_buy(5))
var/attacksuccess = FALSE
last_attack = world.time
for(var/mob/living/L in T)
if("blob" in L.faction) //no friendly/dead fire
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)
var/obj/effect/blob/B = locate() in T
if(B)
if(attacksuccess) //if we successfully attacked a turf with a blob on it, don't refund shit
B.blob_attack_animation(T, src)
else
src << "<span class='warning'>There is a blob there!</span>"
add_points(5) //otherwise, refund all of the cost
return
else
OB.expand(T, src)
/mob/camera/blob/verb/rally_spores_power()
set category = "Blob"
set name = "Rally Spores"
set desc = "Rally your spores to move to a target location."
var/turf/T = get_turf(src)
rally_spores(T)
/mob/camera/blob/proc/rally_spores(turf/T)
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 blob_mobs)
if(isturf(BS.loc) && get_dist(BS, T) <= 35)
BS.LoseTarget()
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
/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."
var/speak_text = input(src, "What would you like to say with your minions?", "Blob Broadcast", null) as text
if(!speak_text)
return
else
src << "You broadcast with your minions, <B>[speak_text]</B>"
for(var/BLO in blob_mobs)
var/mob/living/simple_animal/hostile/blob/BM = BLO
if(BM.stat == CONSCIOUS)
BM.say(speak_text)
/mob/camera/blob/verb/chemical_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--
/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
for(var/BL in blobs)
var/obj/effect/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!
BM << "Your overmind's blob reagent is now: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!"
BM << "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.shortdesc ? "[blob_reagent_datum.shortdesc]" : "[blob_reagent_datum.description]"]"
src << "Your reagent is now: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!"
src << "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.description]"
/mob/camera/blob/verb/blob_help()
set category = "Blob"
set name = "*Blob Help*"
set desc = "Help on how to blob."
src << "<b>As the overmind, you can control the blob!</b>"
src << "Your blob reagent is: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!"
src << "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.description]"
src << "<b>You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.</b>"
src << "<i>Normal Blobs</i> will expand your reach and can be upgraded into special blobs that perform certain functions."
src << "<b>You can upgrade normal blobs into the following types of blob:</b>"
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."
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."
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."
src << "<i>Blobbernauts</i> can be produced from factories for a cost, and are hard to kill, powerful, and moderately smart. The factory used to create one will become fragile and briefly unable to produce spores."
src << "<i>Node Blobs</i> are blobs which grow, like the core. Like the core it can activate resource and factory blobs."
src << "<b>In addition to the buttons on your HUD, there are a few click shortcuts to speed up expansion and defense.</b>"
src << "<b>Shortcuts:</b> Click = Expand Blob <b>|</b> Middle Mouse Click = Rally Spores <b>|</b> Ctrl Click = Create Shield Blob <b>|</b> Alt Click = Remove Blob"
src << "Attempting to talk will send a message to all other overminds, allowing you to coordinate with them."
if(!placed && autoplace_max_time <= world.time)
src << "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [round((autoplace_max_time - world.time)/600, 0.5)] minutes.</font></span>"
src << "<span class='big'><font color=\"#EE4000\">You [manualplace_min_time ? "will be able to":"can"] manually place your blob core by pressing the button in the bottom right corner of the screen.</font></span>"
+360
View File
@@ -0,0 +1,360 @@
//I will need to recode parts of this but I am way too tired atm //I don't know who left this comment but they never did come back
/obj/effect/blob
name = "blob"
icon = 'icons/mob/blob.dmi'
luminosity = 1
desc = "A thick wall of writhing tendrils."
density = 0 //this being 0 causes two bugs, being able to attack blob tiles behind other blobs and being unable to move on blob tiles in no gravity, but turning it to 1 causes the blob mobs to be unable to path through blobs, which is probably worse.
opacity = 0
anchored = 1
explosion_block = 1
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 = 30
var/maxhealth = 30
var/health_regen = 2 //how much health this blob regens when pulsed
var/pulse_timestamp = 0 //we got pulsed/healed when?
var/brute_resist = 0.5 //multiplies brute damage by this
var/fire_resist = 1 //multiplies burn damage by this
var/atmosblock = 0 //if the blob blocks atmos and heat spread
var/mob/camera/blob/overmind
/obj/effect/blob/New(loc)
var/area/Ablob = get_area(loc)
if(Ablob.blob_allowed) //Is this area allowed for winning as blob?
blobs_legit += src
blobs += src //Keep track of the blob in the normal list either way
src.setDir(pick(1, 2, 4, 8))
src.update_icon()
..(loc)
ConsumeTile()
if(atmosblock)
air_update_turf(1)
return
/obj/effect/blob/proc/creation_action() //When it's created by the overmind, do this.
return
/obj/effect/blob/Destroy()
if(atmosblock)
atmosblock = 0
air_update_turf(1)
blobs_legit -= src //if it was in the legit blobs list, it isn't now
blobs -= src //it's no longer in the all blobs list either
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) //Expand() is no longer broken, no check necessary.
return ..()
/obj/effect/blob/Adjacent(var/atom/neighbour)
. = ..()
if(.)
var/result = 0
var/direction = get_dir(src, neighbour)
var/list/dirs = list("[NORTHWEST]" = list(NORTH, WEST), "[NORTHEAST]" = list(NORTH, EAST), "[SOUTHEAST]" = list(SOUTH, EAST), "[SOUTHWEST]" = list(SOUTH, WEST))
for(var/A in dirs)
if(direction == text2num(A))
for(var/B in dirs[A])
var/C = locate(/obj/effect/blob) in get_step(src, B)
if(C)
result++
. -= result - 1
/obj/effect/blob/CanAtmosPass(turf/T)
return !atmosblock
/obj/effect/blob/BlockSuperconductivity()
return atmosblock
/obj/effect/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/effect/blob/CanAStarPass(ID, dir, caller)
. = 0
if(ismovableatom(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSBLOB)
/obj/effect/blob/proc/check_health(cause)
health = Clamp(health, 0, maxhealth)
if(health <= 0)
if(overmind)
overmind.blob_reagent_datum.death_reaction(src, cause)
qdel(src) //we dead now
return
return
/obj/effect/blob/update_icon() //Updates color based on overmind color if we have an overmind.
if(overmind)
color = overmind.blob_reagent_datum.color
else
color = null
return
/obj/effect/blob/process()
Life()
return
/obj/effect/blob/proc/Life()
return
/obj/effect/blob/proc/Pulse_Area(pulsing_overmind = overmind, claim_range = 10, pulse_range = 3, expand_range = 2)
src.Be_Pulsed()
if(claim_range)
for(var/obj/effect/blob/B in urange(claim_range, src, 1))
if(!B.overmind && !istype(B, /obj/effect/blob/core) && prob(30))
B.overmind = pulsing_overmind //reclaim unclaimed, non-core blobs.
B.update_icon()
if(pulse_range)
for(var/obj/effect/blob/B in orange(pulse_range, src))
B.Be_Pulsed()
if(expand_range)
if(prob(85))
src.expand()
for(var/obj/effect/blob/B in orange(expand_range, src))
if(prob(max(13 - get_dist(get_turf(src), get_turf(B)) * 4, 1))) //expand falls off with range but is faster near the blob causing the expansion
B.expand()
return
/obj/effect/blob/proc/Be_Pulsed()
if(pulse_timestamp <= world.time)
ConsumeTile()
health = min(maxhealth, health+health_regen)
update_icon()
pulse_timestamp = world.time + 10
return 1 //we did it, we were pulsed!
return 0 //oh no we failed
/obj/effect/blob/proc/ConsumeTile()
for(var/atom/A in loc)
A.blob_act(src)
if(istype(loc, /turf/closed/wall))
loc.blob_act(src) //don't ask how a wall got on top of the core, just eat it
/obj/effect/blob/proc/blob_attack_animation(atom/A = null, controller) //visually attacks an atom
var/obj/effect/overlay/temp/blob/O = PoolOrNew(/obj/effect/overlay/temp/blob, src.loc)
if(controller)
var/mob/camera/blob/BO = controller
O.color = BO.blob_reagent_datum.color
O.alpha = 200
else if(overmind)
O.color = overmind.blob_reagent_datum.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.
/obj/effect/blob/proc/expand(turf/T = null, controller = null, expand_reaction = 1)
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/effect/blob) in T))
break
else
T = null
if(!T)
return 0
var/make_blob = TRUE //can we make a blob?
if(istype(T, /turf/open/space) && !(locate(/obj/structure/lattice) in T) && prob(80))
make_blob = FALSE
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) //Let's give some feedback that we DID try to spawn in space, since players are used to it
ConsumeTile() //hit the tile we're in, making sure there are no border objects blocking us
if(!T.CanPass(src, T, 5)) //is the target turf impassable
make_blob = FALSE
T.blob_act(src) //hit the turf if it is
for(var/atom/A in T)
if(!A.CanPass(src, T, 5)) //is anything in the turf impassable
make_blob = FALSE
A.blob_act(src) //also hit everything in the turf
if(make_blob) //well, can we?
var/obj/effect/blob/B = new /obj/effect/blob/normal(src.loc)
if(controller)
B.overmind = controller
else
B.overmind = overmind
B.density = 1
if(T.Enter(B,src)) //NOW we can attempt to move into the tile
B.density = initial(B.density)
B.loc = T
B.update_icon()
if(B.overmind && expand_reaction)
B.overmind.blob_reagent_datum.expand_reaction(src, B, T)
return B
else
blob_attack_animation(T, controller)
T.blob_act(src) //if we can't move in hit the turf again
qdel(B) //we should never get to this point, since we checked before moving in. destroy the blob so we don't have two blobs on one tile
return null
else
blob_attack_animation(T, controller) //if we can't, animate that we attacked
return null
/obj/effect/blob/ex_act(severity, target)
..()
var/damage = 150 - 20 * severity
take_damage(damage, BRUTE)
/obj/effect/blob/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/damage = Clamp(0.01 * exposed_temperature, 0, 4)
take_damage(damage, BURN)
/obj/effect/blob/emp_act(severity)
if(severity > 0)
if(overmind)
overmind.blob_reagent_datum.emp_reaction(src, severity)
if(prob(100 - severity * 30))
PoolOrNew(/obj/effect/overlay/temp/emp, get_turf(src))
/obj/effect/blob/tesla_act(power)
..()
if(overmind)
if(overmind.blob_reagent_datum.tesla_reaction(src, power))
take_damage(power/400, BURN)
else
take_damage(power/400, BURN)
/obj/effect/blob/extinguish()
..()
if(overmind)
overmind.blob_reagent_datum.extinguish_reaction(src)
/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj)
..()
take_damage(Proj.damage, Proj.damage_type, Proj)
return 0
/obj/effect/blob/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/device/analyzer))
user.changeNext_move(CLICK_CD_MELEE)
user << "<b>The analyzer beeps once, then reports:</b><br>"
user << 'sound/machines/ping.ogg'
chemeffectreport(user)
typereport(user)
else
return ..()
/obj/effect/blob/proc/chemeffectreport(mob/user)
if(overmind)
user << "<b>Material: <font color=\"[overmind.blob_reagent_datum.color]\">[overmind.blob_reagent_datum.name]</font><span class='notice'>.</span></b>"
user << "<b>Material Effects:</b> <span class='notice'>[overmind.blob_reagent_datum.analyzerdescdamage]</span>"
user << "<b>Material Properties:</b> <span class='notice'>[overmind.blob_reagent_datum.analyzerdesceffect]</span><br>"
else
user << "<b>No Material Detected!</b><br>"
/obj/effect/blob/proc/typereport(mob/user)
user << "<b>Blob Type:</b> <span class='notice'>[uppertext(initial(name))]</span>"
user << "<b>Health:</b> <span class='notice'>[health]/[maxhealth]</span>"
user << "<b>Effects:</b> <span class='notice'>[scannerreport()]</span>"
/obj/effect/blob/attacked_by(obj/item/I, mob/living/user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("<span class='danger'>[user] has attacked the [src.name] with \the [I]!</span>")
if(I.damtype == BURN)
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
take_damage(I.force, I.damtype, user)
/obj/effect/blob/attack_animal(mob/living/simple_animal/M)
if("blob" in M.faction) //sorry, but you can't kill the blob as a blobbernaut
return
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("<span class='danger'>\The [M] has attacked the [src.name]!</span>")
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
take_damage(damage, M.melee_damage_type, M)
return
/obj/effect/blob/attack_alien(mob/living/carbon/alien/humanoid/M)
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("<span class='danger'>[M] has slashed the [src.name]!</span>")
var/damage = rand(15, 30)
take_damage(damage, BRUTE, M)
return
/obj/effect/blob/proc/take_damage(damage, damage_type, cause = null, overmind_reagent_trigger = 1)
switch(damage_type) //blobs only take brute and burn damage
if(BRUTE)
damage = max(damage * brute_resist, 0)
if(BURN)
damage = max(damage * fire_resist, 0)
if(CLONE) //this is basically a marker for 'don't modify the damage'
else
damage = 0
if(overmind && overmind_reagent_trigger)
damage = overmind.blob_reagent_datum.damage_reaction(src, health, damage, damage_type, cause) //pass the blob, its health before damage, the damage being done, the type of damage being done, and the cause.
health -= damage
update_icon()
check_health(cause)
/obj/effect/blob/proc/change_to(type, controller)
if(!ispath(type))
throw EXCEPTION("change_to(): invalid type for blob")
return
var/obj/effect/blob/B = new type(src.loc)
if(controller)
B.overmind = controller
B.creation_action()
B.update_icon()
qdel(src)
return B
/obj/effect/blob/examine(mob/user)
..()
var/datum/atom_hud/hud_to_check = huds[DATA_HUD_MEDICAL_ADVANCED]
if(user.research_scanner || (user in hud_to_check.hudusers))
user << "<b>Your HUD displays an extensive report...</b><br>"
chemeffectreport(user)
typereport(user)
else
user << "It seems to be made of [get_chem_name()]."
/obj/effect/blob/proc/scannerreport()
return "A generic blob. Looks like someone forgot to override this proc, adminhelp this."
/obj/effect/blob/proc/get_chem_name()
if(overmind)
return overmind.blob_reagent_datum.name
return "an unknown variant"
/obj/effect/blob/normal
name = "normal blob"
icon_state = "blob"
luminosity = 0
health = 21
maxhealth = 25
health_regen = 1
brute_resist = 0.25
/obj/effect/blob/normal/scannerreport()
if(health <= 10)
return "Currently weak to brute damage."
return "N/A"
/obj/effect/blob/normal/update_icon()
..()
if(health <= 10)
icon_state = "blob_damaged"
name = "fragile blob"
desc = "A thin lattice of slightly twitching tendrils."
brute_resist = 0.5
else
icon_state = "blob"
name = "blob"
desc = "A thick wall of writhing tendrils."
brute_resist = 0.25