mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-14 08:34:16 +01:00
Merge pull request #1499 from Fox-McCloud/blob-update
[Ready To Merge!]Blob Mode Major Overhaul
This commit is contained in:
@@ -62,4 +62,6 @@ var/score_richestkey = null
|
||||
var/score_dmgestname = null // who had the most damage on the shuttle (but was still alive)
|
||||
var/score_dmgestjob = null
|
||||
var/score_dmgestdamage = 0
|
||||
var/score_dmgestkey = null
|
||||
var/score_dmgestkey = null
|
||||
|
||||
var/TAB = " "
|
||||
@@ -673,7 +673,7 @@
|
||||
id = "people"
|
||||
|
||||
whitelist = null
|
||||
blacklist = list(/mob/camera,/mob/new_player,/mob/living/simple_animal/hostile/blobspore,/mob/living/simple_animal/hostile/creature,
|
||||
blacklist = list(/mob/camera,/mob/new_player,/mob/living/simple_animal/hostile/blob/blobspore,/mob/living/simple_animal/hostile/creature,
|
||||
/mob/living/simple_animal/hostile/spaceWorm,/mob/living/simple_animal/shade,/mob/living/simple_animal/hostile/faithless,/mob/dead)
|
||||
universal = 1
|
||||
mobcheck = 1
|
||||
|
||||
@@ -10,21 +10,23 @@ var/list/blob_nodes = list()
|
||||
name = "blob"
|
||||
config_tag = "blob"
|
||||
|
||||
required_players = 15
|
||||
required_players_secret = 15
|
||||
required_players = 30
|
||||
required_players_secret = 30
|
||||
required_enemies = 1
|
||||
recommended_enemies = 1
|
||||
restricted_jobs = list("Cyborg", "AI")
|
||||
|
||||
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
|
||||
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
|
||||
|
||||
var/declared = 0
|
||||
var/burst = 0
|
||||
|
||||
var/cores_to_spawn = 1
|
||||
var/players_per_core = 20
|
||||
var/players_per_core = 30
|
||||
var/blob_point_rate = 3
|
||||
|
||||
var/blobwincount = 700
|
||||
var/stage_2_threshold = 0.60
|
||||
var/blobwincount = 350
|
||||
|
||||
var/list/infected_crew = list()
|
||||
|
||||
@@ -56,12 +58,37 @@ var/list/blob_nodes = list()
|
||||
|
||||
return 1
|
||||
|
||||
/datum/game_mode/blob/proc/get_nuke_code()
|
||||
var/nukecode = "ERROR"
|
||||
for(var/obj/machinery/nuclearbomb/bomb in world)
|
||||
if(bomb && bomb.r_code && (bomb.z in config.station_levels))
|
||||
nukecode = bomb.r_code
|
||||
return nukecode
|
||||
/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") && (player.client.prefs.be_special & BE_BLOB))
|
||||
candidates += player
|
||||
return candidates
|
||||
|
||||
|
||||
/datum/game_mode/blob/proc/blobize(var/mob/living/carbon/human/blob)
|
||||
var/datum/mind/blobmind = blob.mind
|
||||
if(!istype(blobmind))
|
||||
return 0
|
||||
infected_crew += blobmind
|
||||
blobmind.special_role = "Blob"
|
||||
log_game("[blob.key] (ckey) has been selected as a Blob")
|
||||
greet_blob(blobmind)
|
||||
blob << "<span class='userdanger'>You feel very tired and bloated! You don't have long before you burst!</span>"
|
||||
spawn(600)
|
||||
burst_blob(blobmind)
|
||||
return 1
|
||||
|
||||
/datum/game_mode/blob/proc/make_blobs(var/count)
|
||||
var/list/candidates = get_blob_candidates()
|
||||
var/mob/living/carbon/human/blob = null
|
||||
count=min(count, candidates.len)
|
||||
for(var/i = 0, i < count, i++)
|
||||
blob = pick(candidates)
|
||||
candidates -= blob
|
||||
blobize(blob)
|
||||
return count
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/blob/announce()
|
||||
@@ -71,7 +98,7 @@ var/list/blob_nodes = list()
|
||||
|
||||
|
||||
/datum/game_mode/blob/proc/greet_blob(var/datum/mind/blob)
|
||||
blob.current << "<B>\red You are infected by the Blob!</B>"
|
||||
blob.current << "<span class='userdanger'>You are infected by the Blob!</span>"
|
||||
blob.current << "<b>Your body is ready to give spawn to a new blob core which will eat this station.</b>"
|
||||
blob.current << "<b>Find a good location to spawn the core and then take control and overwhelm the station!</b>"
|
||||
blob.current << "<b>When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process.</b>"
|
||||
@@ -84,27 +111,40 @@ var/list/blob_nodes = list()
|
||||
|
||||
/datum/game_mode/blob/proc/burst_blobs()
|
||||
for(var/datum/mind/blob in infected_crew)
|
||||
burst_blob(blob)
|
||||
|
||||
var/client/blob_client = null
|
||||
var/turf/location = null
|
||||
/datum/game_mode/blob/proc/burst_blob(var/datum/mind/blob, var/warned=0)
|
||||
var/client/blob_client = null
|
||||
var/turf/location = null
|
||||
|
||||
if(iscarbon(blob.current))
|
||||
var/mob/living/carbon/C = blob.current
|
||||
if(directory[ckey(blob.key)])
|
||||
blob_client = directory[ckey(blob.key)]
|
||||
location = get_turf(C)
|
||||
if(!(location.z in config.station_levels) || istype(location, /turf/space))
|
||||
location = null
|
||||
if(iscarbon(blob.current))
|
||||
var/mob/living/carbon/C = blob.current
|
||||
if(directory[ckey(blob.key)])
|
||||
blob_client = directory[ckey(blob.key)]
|
||||
location = get_turf(C)
|
||||
if(location.z != ZLEVEL_STATION || istype(location, /turf/space))
|
||||
if(!warned)
|
||||
C << "<span class='userdanger'>You feel ready to burst, but this isn't an appropriate place! You must return to the station!</span>"
|
||||
message_admins("[key_name(C)] was in space when the blobs burst, and will die if he doesn't return to the station.")
|
||||
spawn(300)
|
||||
burst_blob(blob, 1)
|
||||
else
|
||||
burst ++
|
||||
log_admin("[key_name(C)] was in space when attempting to burst as a blob.")
|
||||
message_admins("[key_name(C)] was in space when attempting to burst as a blob.")
|
||||
C.gib()
|
||||
make_blobs(1)
|
||||
check_finished() //Still needed in case we can't make any blobs
|
||||
|
||||
else if(blob_client && location)
|
||||
burst ++
|
||||
C.gib()
|
||||
|
||||
|
||||
if(blob_client && location)
|
||||
var/obj/effect/blob/core/core = new(location, 200, blob_client, blob_point_rate)
|
||||
if(core.overmind && core.overmind.mind)
|
||||
core.overmind.mind.name = blob.name
|
||||
infected_crew -= blob
|
||||
infected_crew += core.overmind.mind
|
||||
|
||||
var/obj/effect/blob/core/core = new(location, 200, blob_client, blob_point_rate)
|
||||
if(core.overmind && core.overmind.mind)
|
||||
core.overmind.mind.name = blob.name
|
||||
infected_crew -= blob
|
||||
infected_crew += core.overmind.mind
|
||||
core.overmind.mind.special_role = "Blob Overmind"
|
||||
|
||||
/datum/game_mode/blob/post_setup()
|
||||
|
||||
@@ -114,18 +154,6 @@ var/list/blob_nodes = list()
|
||||
if(emergency_shuttle)
|
||||
emergency_shuttle.auto_recall = 1
|
||||
|
||||
/*// Disable the blob event for this round.
|
||||
if(events)
|
||||
var/datum/round_event_control/blob/B = locate() in events.control
|
||||
if(B)
|
||||
B.max_occurrences = 0 // disable the event
|
||||
else
|
||||
error("Events variable is null in blob gamemode post setup.")*/
|
||||
|
||||
spawn(10)
|
||||
start_state = new /datum/station_state()
|
||||
start_state.count()
|
||||
|
||||
spawn(0)
|
||||
|
||||
var/wait_time = rand(waittime_l, waittime_h)
|
||||
@@ -136,30 +164,29 @@ var/list/blob_nodes = list()
|
||||
|
||||
sleep(100)
|
||||
|
||||
show_message("<span class='alert'>You feel tired and bloated.</span>")
|
||||
show_message("<span class='userdanger'>You feel tired and bloated.</span>")
|
||||
|
||||
sleep(wait_time)
|
||||
|
||||
show_message("<span class='alert'>You feel like you are about to burst.</span>")
|
||||
show_message("<span class='userdanger'>You feel like you are about to burst.</span>")
|
||||
|
||||
sleep(wait_time / 2)
|
||||
|
||||
burst_blobs()
|
||||
|
||||
// Stage 0
|
||||
sleep(40)
|
||||
sleep(wait_time)
|
||||
stage(0)
|
||||
|
||||
// Stage 1
|
||||
sleep(2000)
|
||||
sleep(wait_time)
|
||||
stage(1)
|
||||
|
||||
// Stage 2
|
||||
while(blobs.len < blobwincount*stage_2_threshold)
|
||||
sleep(10)
|
||||
sleep(30000)
|
||||
stage(2)
|
||||
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/blob/proc/stage(var/stage)
|
||||
|
||||
@@ -167,27 +194,11 @@ var/list/blob_nodes = list()
|
||||
if (0)
|
||||
send_intercept(1)
|
||||
declared = 1
|
||||
for (var/mob/living/silicon/ai/aiPlayer in player_list)
|
||||
if (aiPlayer.client)
|
||||
var/law = "The station is under quarantine, prevent biological entities from leaving the station at all costs while minimizing collateral damage."
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
aiPlayer << "\red <b>You have detected a change in your laws information:</b>"
|
||||
aiPlayer << "Laws Updated: [law]"
|
||||
return
|
||||
|
||||
if (1)
|
||||
command_announcement.Announce("Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
|
||||
return
|
||||
command_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
|
||||
|
||||
if (2)
|
||||
command_announcement.Announce("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert", new_sound = 'sound/effects/siren.ogg')
|
||||
set_security_level("gamma")
|
||||
var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world
|
||||
if(V && (V.z in config.station_levels))
|
||||
V.locked = 0
|
||||
V.update_icon()
|
||||
send_intercept(2)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -1,78 +1,42 @@
|
||||
/datum/game_mode/blob/check_finished()
|
||||
if(!declared)//No blobs have been spawned yet
|
||||
if(infected_crew.len > burst)//Some blobs have yet to burst
|
||||
return 0
|
||||
if(blobwincount <= blobs.len)//Blob took over
|
||||
return 1
|
||||
if(!blob_cores.len) // blob is dead
|
||||
return 1
|
||||
if(station_was_nuked)//Nuke went off
|
||||
return 1
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/game_mode/blob/declare_completion()
|
||||
if(blobwincount <= blobs.len)
|
||||
feedback_set_details("round_end_result","loss - blob took over")
|
||||
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>"
|
||||
check_quarantine()
|
||||
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","win - blob eliminated")
|
||||
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>"
|
||||
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
var/percent = round( 100.0 * start_state.score(end_state), 0.1)
|
||||
world << "<B>The station is [percent]% intact.</B>"
|
||||
log_game("Blob mode was won with station [percent]% intact.")
|
||||
world << "\blue Rebooting in 30s"
|
||||
log_game("Blob mode completed with a crew victory.")
|
||||
world << "<span class='notice'>Rebooting in 30s</span>"
|
||||
..()
|
||||
return 1
|
||||
|
||||
datum/game_mode/proc/auto_declare_completion_blob()
|
||||
/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.infected_crew.len)
|
||||
var/text = "<FONT size = 2><B>The blob[(blob_mode.infected_crew.len > 1 ? "s were" : " was")]:</B></FONT>"
|
||||
|
||||
for(var/datum/mind/blob in blob_mode.infected_crew)
|
||||
text += "<br>[blob.key] was [blob.name]"
|
||||
text += "<br><b>[blob.key]</b> was <b>[blob.name]</b>"
|
||||
world << text
|
||||
return 1
|
||||
|
||||
/datum/game_mode/blob/proc/check_quarantine()
|
||||
var/numDead = 0
|
||||
var/numAlive = 0
|
||||
var/numSpace = 0
|
||||
var/numOffStation = 0
|
||||
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
|
||||
for(var/mob/living/carbon/human/M in mob_list)
|
||||
if ((M != aiPlayer && M.client))
|
||||
if (M.stat == 2)
|
||||
numDead += 1
|
||||
else
|
||||
var/T = M.loc
|
||||
if (istype(T, /turf/space))
|
||||
numSpace += 1
|
||||
else if(istype(T, /turf))
|
||||
if (!(M.z in config.station_levels))
|
||||
numOffStation += 1
|
||||
else
|
||||
numAlive += 1
|
||||
if (numSpace==0 && numOffStation==0)
|
||||
world << "<FONT size = 3><B>The AI has won!</B></FONT>"
|
||||
world << "<B>The AI successfully maintained the quarantine - no players were in space or were off-station (as far as we can tell).</B>"
|
||||
log_game("AI won at Blob mode despite overall loss.")
|
||||
else
|
||||
world << "<FONT size = 3><B>The AI has lost!</B></FONT>"
|
||||
world << text("<B>The AI failed to maintain the quarantine - [] were in space and [] were off-station (as far as we can tell).</B>", numSpace, numOffStation)
|
||||
log_game("AI lost at Blob mode.")
|
||||
log_game("Blob mode was lost.")
|
||||
return 1
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
|
||||
/datum/game_mode/blob/send_intercept(var/report = 1)
|
||||
var/intercepttext = ""
|
||||
var/interceptname = "Error"
|
||||
var/interceptname = ""
|
||||
switch(report)
|
||||
if(0)
|
||||
..()
|
||||
return
|
||||
if(1)
|
||||
interceptname = "Biohazard Alert"
|
||||
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 7 biohazard. Its origin is unknown.<BR>"
|
||||
intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown.<BR>"
|
||||
intercepttext += "Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.<BR>"
|
||||
intercepttext += "Orders for all [station_name()] personnel follows:<BR>"
|
||||
intercepttext += " 1. Do not leave the quarantine area.<BR>"
|
||||
@@ -21,20 +20,25 @@
|
||||
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12.<BR>"
|
||||
intercepttext += "Message ends."
|
||||
if(2)
|
||||
interceptname = "Directive 7-12"
|
||||
var/nukecode = rand(10000, 99999)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in world)
|
||||
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 += "Directive 7-12 has been issued for [station_name()].<BR>"
|
||||
intercepttext += "The biohazard has grown out of control and will soon reach critical mass.<BR>"
|
||||
intercepttext += "Your orders are as follows:<BR>"
|
||||
intercepttext += "1. Secure the Nuclear Authentication Disk.<BR>"
|
||||
intercepttext += "2. Detonate the Nuke located in the Station's Vault.<BR>"
|
||||
intercepttext += "Nuclear Authentication Code: [get_nuke_code()] <BR>"
|
||||
intercepttext += "Nuclear Authentication Code: [nukecode] <BR>"
|
||||
intercepttext += "Message ends."
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in player_list)
|
||||
if (aiPlayer.client)
|
||||
var/law = "The station is under quarantine, prevent biological entities from leaving the station at all costs. The nuclear failsafe must be activated at any cost, the code is: [get_nuke_code()]."
|
||||
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 << "\red <b>You have detected a change in your laws information:</b>"
|
||||
aiPlayer << "Laws Updated: [law]"
|
||||
|
||||
for(var/obj/machinery/computer/communications/comm in world)
|
||||
@@ -42,13 +46,12 @@
|
||||
comm.messagetext.Add(intercepttext)
|
||||
if(!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
|
||||
var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
|
||||
intercept.name = "paper- [interceptname]"
|
||||
intercept.name = "Classified Central Command Update"
|
||||
intercept.info = intercepttext
|
||||
world << sound('sound/AI/commandreport.ogg')
|
||||
command_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
|
||||
return
|
||||
|
||||
|
||||
|
||||
/datum/station_state
|
||||
var/floor = 0
|
||||
var/wall = 0
|
||||
@@ -59,33 +62,29 @@
|
||||
var/mach = 0
|
||||
|
||||
|
||||
proc/count()
|
||||
for(var/turf/T in world)
|
||||
if(!(T.z in config.station_levels))
|
||||
continue
|
||||
/datum/station_state/proc/count()
|
||||
for(var/turf/T in block(locate(1,1,1), locate(world.maxx,world.maxy,1)))
|
||||
|
||||
if(istype(T,/turf/simulated/floor))
|
||||
if(!(T:burnt))
|
||||
src.floor += 12
|
||||
else
|
||||
src.floor += 1
|
||||
if(istype(T,/turf/simulated/floor))
|
||||
if(!(T:burnt))
|
||||
src.floor += 12
|
||||
else
|
||||
src.floor += 1
|
||||
|
||||
if(istype(T, /turf/simulated/wall))
|
||||
if(T:intact)
|
||||
src.wall += 2
|
||||
else
|
||||
src.wall += 1
|
||||
if(istype(T, /turf/simulated/wall))
|
||||
if(T:intact)
|
||||
src.wall += 2
|
||||
else
|
||||
src.wall += 1
|
||||
|
||||
if(istype(T, /turf/simulated/wall/r_wall))
|
||||
if(T:intact)
|
||||
src.r_wall += 2
|
||||
else
|
||||
src.r_wall += 1
|
||||
if(istype(T, /turf/simulated/wall/r_wall))
|
||||
if(T:intact)
|
||||
src.r_wall += 2
|
||||
else
|
||||
src.r_wall += 1
|
||||
|
||||
for(var/obj/O in world)
|
||||
if(!(O.z in config.station_levels))
|
||||
continue
|
||||
|
||||
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))
|
||||
@@ -94,17 +93,15 @@
|
||||
src.door += 1
|
||||
else if(istype(O, /obj/machinery))
|
||||
src.mach += 1
|
||||
return
|
||||
|
||||
|
||||
proc/score(var/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)
|
||||
/datum/station_state/proc/score(var/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)
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
|
||||
////////////////
|
||||
// BASE TYPE //
|
||||
////////////////
|
||||
|
||||
//Do not spawn
|
||||
/mob/living/simple_animal/hostile/blob
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
pass_flags = PASSBLOB
|
||||
faction = list("blob")
|
||||
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 = 1 //So mobs can understand them when a blob uses Blob Broadcast
|
||||
var/mob/camera/blob/overmind = null
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/proc/adjustcolors(var/a_color)
|
||||
if(a_color)
|
||||
color = a_color
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blob_act()
|
||||
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
|
||||
attacktext = "hits"
|
||||
attack_sound = 'sound/weapons/genhit1.ogg'
|
||||
speak_emote = list("pulses")
|
||||
var/obj/effect/blob/factory/factory = null
|
||||
var/list/human_overlays = list()
|
||||
var/is_zombie = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
..()
|
||||
adjustBruteLoss(Clamp(0.01 * exposed_temperature, 1, 5))
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if(istype(mover, /obj/effect/blob))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/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 oview(src,1)) //Only for corpse right next to/on same tile
|
||||
if(H.stat == DEAD)
|
||||
Zombify(H)
|
||||
break
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(var/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 = 10
|
||||
melee_damage_upper = 15
|
||||
icon = H.icon
|
||||
speak_emote = list("groans")
|
||||
icon_state = "zombie2_s"
|
||||
H.h_style = null
|
||||
H.update_hair()
|
||||
human_overlays = H.overlays
|
||||
update_icons()
|
||||
H.loc = src
|
||||
loc.visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/Die()
|
||||
// On death, create a small smoke of harmful gas (s-Acid)
|
||||
var/datum/effect/effect/system/chem_smoke_spread/S = new
|
||||
var/turf/location = get_turf(src)
|
||||
|
||||
// Create the reagents to put into the air
|
||||
create_reagents(25)
|
||||
|
||||
if(overmind && overmind.blob_reagent_datum)
|
||||
reagents.add_reagent(overmind.blob_reagent_datum.id, 25)
|
||||
else
|
||||
reagents.add_reagent("spore", 25)
|
||||
|
||||
// Attach the smoke spreader and setup/start it.
|
||||
S.attach(location)
|
||||
S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud
|
||||
S.start()
|
||||
|
||||
ghostize()
|
||||
qdel(src)
|
||||
|
||||
/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 = get_turf(src)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/update_icons()
|
||||
..()
|
||||
|
||||
if(overmind && overmind.blob_reagent_datum)
|
||||
adjustcolors(overmind.blob_reagent_datum.color)
|
||||
else
|
||||
adjustcolors(color) //to ensure zombie/other overlays update
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/adjustcolors(var/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
|
||||
color = initial(color)//looks better.
|
||||
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 = 240
|
||||
maxHealth = 240
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
attacktext = "hits"
|
||||
attack_sound = 'sound/effects/blobattack.ogg'
|
||||
speak_emote = list("gurgles")
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 360
|
||||
force_threshold = 10
|
||||
environment_smash = 3
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/blob_act()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Die()
|
||||
flick("blobbernaut_death", src)
|
||||
@@ -1,93 +1,123 @@
|
||||
/obj/effect/blob/core
|
||||
name = "blob core"
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blob_core"
|
||||
icon_state = "blank_blob"
|
||||
health = 200
|
||||
fire_resist = 2
|
||||
var/mob/camera/blob/overmind = null // the blob core's overmind
|
||||
var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 30 seconds
|
||||
var/resource_delay = 0
|
||||
var/point_rate = 2
|
||||
var/mob/camera/blob/creator = null
|
||||
var/is_offspring = null
|
||||
|
||||
New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, var/mob/camera/blob/C = null)
|
||||
blob_cores += src
|
||||
processing_objects.Add(src)
|
||||
creator = C
|
||||
if(!overmind)
|
||||
create_overmind(new_overmind)
|
||||
point_rate = new_rate
|
||||
..(loc, h)
|
||||
/obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, offspring)
|
||||
blob_cores += src
|
||||
processing_objects.Add(src)
|
||||
adjustcolors(color) //so it atleast appears
|
||||
if(!overmind)
|
||||
create_overmind(new_overmind)
|
||||
if(overmind)
|
||||
adjustcolors(overmind.blob_reagent_datum.color)
|
||||
if(offspring)
|
||||
is_offspring = 1
|
||||
point_rate = new_rate
|
||||
..(loc, h)
|
||||
|
||||
|
||||
Destroy()
|
||||
blob_cores -= src
|
||||
if(overmind)
|
||||
qdel(overmind)
|
||||
processing_objects.Remove(src)
|
||||
return ..()
|
||||
/obj/effect/blob/core/adjustcolors(var/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
|
||||
|
||||
update_icon()
|
||||
if(health <= 0)
|
||||
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
||||
Delete()
|
||||
return
|
||||
|
||||
/obj/effect/blob/core/Destroy()
|
||||
blob_cores -= src
|
||||
if(overmind)
|
||||
overmind.blob_core = null
|
||||
overmind = null
|
||||
processing_objects.Remove(src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/obj/effect/blob/core/update_icon()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
// update_icon is called when health changes so... call update_health in the overmind
|
||||
if(overmind)
|
||||
overmind.update_health()
|
||||
return
|
||||
|
||||
/obj/effect/blob/core/RegenHealth()
|
||||
return // Don't regen, we handle it in Life()
|
||||
|
||||
/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(initial(health), health + 1)
|
||||
if(overmind)
|
||||
overmind.update_health()
|
||||
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 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(B && overmind)
|
||||
B.color = overmind.blob_reagent_datum.color
|
||||
else
|
||||
B.color = color
|
||||
color = null
|
||||
..()
|
||||
|
||||
|
||||
/obj/effect/blob/core/proc/create_overmind(var/client/new_overmind, var/override_delay)
|
||||
|
||||
if(overmind_get_delay > world.time && !override_delay)
|
||||
return
|
||||
|
||||
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(initial(health), health + 1)
|
||||
for(var/i = 1; i < 8; i += i)
|
||||
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)
|
||||
..()
|
||||
overmind_get_delay = world.time + 300 // 30 seconds
|
||||
|
||||
if(overmind)
|
||||
qdel(overmind)
|
||||
|
||||
run_action()
|
||||
return 0
|
||||
var/client/C = null
|
||||
var/list/candidates = list()
|
||||
|
||||
if(!new_overmind)
|
||||
candidates = get_candidates(BE_BLOB)
|
||||
if(candidates.len)
|
||||
C = pick(candidates)
|
||||
else
|
||||
C = new_overmind
|
||||
|
||||
proc/create_overmind(var/client/new_overmind)
|
||||
|
||||
if(overmind_get_delay > world.time)
|
||||
return
|
||||
|
||||
overmind_get_delay = world.time + 300 // 30 seconds
|
||||
|
||||
if(overmind)
|
||||
qdel(overmind)
|
||||
|
||||
var/client/C = null
|
||||
var/list/candidates = list()
|
||||
|
||||
if(!new_overmind)
|
||||
candidates = get_candidates(BE_BLOB)
|
||||
if(candidates.len)
|
||||
C = pick(candidates)
|
||||
else
|
||||
C = new_overmind
|
||||
|
||||
if(C)
|
||||
respawnable_list -= C
|
||||
var/mob/camera/blob/B = new(src.loc)
|
||||
B.key = C.key
|
||||
B.blob_core = src
|
||||
src.overmind = B
|
||||
if(!B.blob_core.creator)
|
||||
B.verbs += /mob/camera/blob/proc/create_core
|
||||
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
|
||||
if(C)
|
||||
var/mob/camera/blob/B = new(src.loc)
|
||||
B.key = C.key
|
||||
B.blob_core = src
|
||||
src.overmind = B
|
||||
color = overmind.blob_reagent_datum.color
|
||||
if(B.mind && !B.mind.special_role)
|
||||
B.mind.special_role = "Blob Overmind"
|
||||
spawn(0)
|
||||
if(is_offspring)
|
||||
B.verbs -= /mob/camera/blob/verb/split_consciousness
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@@ -7,123 +7,34 @@
|
||||
var/list/spores = list()
|
||||
var/max_spores = 3
|
||||
var/spore_delay = 0
|
||||
var/mob/camera/blob/overmind
|
||||
|
||||
update_icon()
|
||||
if(health <= 0)
|
||||
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
||||
Delete()
|
||||
return
|
||||
return
|
||||
/obj/effect/blob/factory/update_icon()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
|
||||
|
||||
run_action()
|
||||
if(spores.len >= max_spores)
|
||||
return 0
|
||||
if(spore_delay > world.time)
|
||||
return 0
|
||||
spore_delay = world.time + 100 // 10 seconds
|
||||
new/mob/living/simple_animal/hostile/blobspore(src.loc, src)
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blobspore
|
||||
name = "blob"
|
||||
desc = "Some blob thing."
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blobpod"
|
||||
icon_living = "blobpod"
|
||||
pass_flags = PASSBLOB
|
||||
health = 40
|
||||
maxHealth = 40
|
||||
melee_damage_lower = 2
|
||||
melee_damage_upper = 4
|
||||
attacktext = "hits"
|
||||
attack_sound = 'sound/weapons/genhit1.ogg'
|
||||
var/obj/effect/blob/factory/factory = null
|
||||
var/is_zombie = 0
|
||||
faction = list("blob")
|
||||
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
|
||||
|
||||
fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
..()
|
||||
adjustBruteLoss(Clamp(0.01 * exposed_temperature, 1, 5))
|
||||
|
||||
blob_act()
|
||||
return
|
||||
|
||||
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(istype(mover, /obj/effect/blob))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
New(loc, var/obj/effect/blob/factory/linked_node)
|
||||
if(istype(linked_node))
|
||||
factory = linked_node
|
||||
factory.spores += src
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blobspore/Life()
|
||||
|
||||
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)
|
||||
Zombify(H)
|
||||
break
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blobspore/proc/Zombify(var/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 = 10
|
||||
melee_damage_upper = 15
|
||||
icon = H.icon
|
||||
speak_emote = list("groans")
|
||||
icon_state = "zombie2_s"
|
||||
H.h_style = null
|
||||
H.update_hair()
|
||||
overlays = H.overlays
|
||||
overlays += image('icons/mob/blob.dmi', icon_state = "blob_head")
|
||||
H.loc = src
|
||||
loc.visible_message("<span class='warning'> The corpse of [H.name] suddenly rises!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/blobspore/Die()
|
||||
// On death, create a small smoke of harmful gas (s-Acid)
|
||||
var/datum/effect/effect/system/chem_smoke_spread/S = new
|
||||
var/turf/location = get_turf(src)
|
||||
|
||||
// Create the reagents to put into the air, s-acid is yellow and stings a little
|
||||
create_reagents(25)
|
||||
|
||||
reagents.add_reagent("spores", 25)
|
||||
|
||||
// Attach the smoke spreader and setup/start it.
|
||||
S.attach(location)
|
||||
S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud
|
||||
S.start()
|
||||
|
||||
qdel(src)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blobspore/Destroy()
|
||||
if(factory)
|
||||
factory.spores -= src
|
||||
if(contents)
|
||||
for(var/mob/M in contents)
|
||||
M.loc = src.loc
|
||||
/obj/effect/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/effect/blob/factory/PulseAnimation(var/activate = 0)
|
||||
if(activate)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/effect/blob/factory/run_action()
|
||||
if(spores.len >= max_spores)
|
||||
return 0
|
||||
if(spore_delay > world.time)
|
||||
return 0
|
||||
spore_delay = world.time + 100 // 10 seconds
|
||||
PulseAnimation(1)
|
||||
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src)
|
||||
BS.color = color
|
||||
BS.overmind = overmind
|
||||
overmind.blob_mobs.Add(BS)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1,33 +1,45 @@
|
||||
/obj/effect/blob/node
|
||||
name = "blob node"
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blob_node"
|
||||
icon_state = "blank_blob"
|
||||
health = 100
|
||||
fire_resist = 2
|
||||
var/mob/camera/blob/overmind
|
||||
|
||||
/obj/effect/blob/node/New(loc, var/h = 100)
|
||||
blob_nodes += src
|
||||
processing_objects.Add(src)
|
||||
..(loc, h)
|
||||
|
||||
New(loc, var/h = 100)
|
||||
blob_nodes += src
|
||||
processing_objects.Add(src)
|
||||
..(loc, h)
|
||||
/obj/effect/blob/node/adjustcolors(var/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
|
||||
|
||||
Destroy()
|
||||
blob_nodes -= src
|
||||
processing_objects.Remove(src)
|
||||
return ..()
|
||||
/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
Life()
|
||||
/obj/effect/blob/node/Destroy()
|
||||
blob_nodes -= src
|
||||
processing_objects.Remove(src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/blob/node/Life()
|
||||
if(overmind)
|
||||
for(var/i = 1; i < 8; i += i)
|
||||
Pulse(5, i)
|
||||
health = min(initial(health), health + 1)
|
||||
Pulse(5, i, overmind.blob_reagent_datum.color)
|
||||
else
|
||||
for(var/i = 1; i < 8; i += i)
|
||||
Pulse(5, i, color)
|
||||
health = min(initial(health), health + 1)
|
||||
color = null
|
||||
|
||||
update_icon()
|
||||
if(health <= 0)
|
||||
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
||||
Delete()
|
||||
return
|
||||
/obj/effect/blob/node/update_icon()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
run_action()
|
||||
return 0
|
||||
return
|
||||
@@ -7,20 +7,25 @@
|
||||
var/mob/camera/blob/overmind = null
|
||||
var/resource_delay = 0
|
||||
|
||||
update_icon()
|
||||
if(health <= 0)
|
||||
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
||||
Delete()
|
||||
return
|
||||
return
|
||||
/obj/effect/blob/resource/update_icon()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
|
||||
run_action()
|
||||
if(resource_delay > world.time)
|
||||
return 0
|
||||
/obj/effect/blob/resource/PulseAnimation(var/activate = 0)
|
||||
if(activate)
|
||||
..()
|
||||
return
|
||||
|
||||
resource_delay = world.time + 40 // 4 seconds
|
||||
/obj/effect/blob/resource/run_action()
|
||||
|
||||
if(overmind)
|
||||
overmind.add_points(1)
|
||||
return 1
|
||||
if(resource_delay > world.time)
|
||||
return 0
|
||||
|
||||
PulseAnimation(1)
|
||||
|
||||
resource_delay = world.time + 40 // 4 seconds
|
||||
|
||||
if(overmind)
|
||||
overmind.add_points(1)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -3,18 +3,19 @@
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blob_idle"
|
||||
desc = "Some blob creature thingy"
|
||||
health = 60
|
||||
brute_resist = 4
|
||||
health = 75
|
||||
fire_resist = 2
|
||||
|
||||
|
||||
update_icon()
|
||||
if(health <= 0)
|
||||
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
||||
Delete()
|
||||
return
|
||||
/obj/effect/blob/shield/update_icon()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
return
|
||||
|
||||
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
|
||||
return 0
|
||||
/obj/effect/blob/shield/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/obj/effect/blob/shield/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
|
||||
return 0
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/obj/effect/blob/storage
|
||||
name = "storage blob"
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blob_resource"
|
||||
health = 30
|
||||
fire_resist = 2
|
||||
var/mob/camera/blob/overmind = null
|
||||
|
||||
/obj/effect/blob/storage/update_icon()
|
||||
if(health <= 0)
|
||||
overmind.max_blob_points -= 50
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/blob/storage/PulseAnimation(var/activate = 0)
|
||||
if(activate)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/effect/blob/storage/proc/update_max_blob_points(var/new_point_increase)
|
||||
if(overmind)
|
||||
overmind.max_blob_points += new_point_increase
|
||||
@@ -1,17 +0,0 @@
|
||||
/datum/hud/proc/blob_hud(ui_style = 'icons/mob/screen1_Midnight.dmi')
|
||||
|
||||
blobpwrdisplay = new /obj/screen()
|
||||
blobpwrdisplay.name = "blob power"
|
||||
blobpwrdisplay.icon_state = "block"
|
||||
blobpwrdisplay.screen_loc = ui_health
|
||||
blobpwrdisplay.layer = 20
|
||||
|
||||
blobhealthdisplay = new /obj/screen()
|
||||
blobhealthdisplay.name = "blob health"
|
||||
blobhealthdisplay.icon_state = "block"
|
||||
blobhealthdisplay.screen_loc = ui_internal
|
||||
blobhealthdisplay.layer = 20
|
||||
|
||||
mymob.client.screen = null
|
||||
|
||||
mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay)
|
||||
@@ -14,17 +14,31 @@
|
||||
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/ghostimage = null
|
||||
|
||||
/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 (typesof(/datum/reagent/blob) - /datum/reagent/blob))
|
||||
possible_reagents.Add(new type)
|
||||
blob_reagent_datum = pick(possible_reagents)
|
||||
if(blob_core)
|
||||
blob_core.adjustcolors(blob_reagent_datum.color)
|
||||
|
||||
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)
|
||||
qdel(src)
|
||||
..()
|
||||
|
||||
/mob/camera/blob/Destroy()
|
||||
@@ -38,8 +52,8 @@
|
||||
/mob/camera/blob/Login()
|
||||
..()
|
||||
sync_mind()
|
||||
|
||||
src << "<span class='notice'>You are the overmind!</span>"
|
||||
src << "Your randomly chosen reagent is: <b>[blob_reagent_datum.name]</b>!"
|
||||
src << "You are the overmind and can control the blob! You can expand, which will attack people, and place new blob pieces such as..."
|
||||
src << "<b>Normal Blob</b> will expand your reach and allow you to upgrade into special blobs that perform certain functions."
|
||||
src << "<b>Shield Blob</b> is a strong and expensive blob which can take more damage. It is fireproof and can block air, use this to protect yourself from station fires."
|
||||
@@ -51,14 +65,12 @@
|
||||
|
||||
/mob/camera/blob/proc/update_health()
|
||||
if(blob_core)
|
||||
hud_used.blobhealthdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font color='#e36600'>[blob_core.health]</font></div>"
|
||||
hud_used.blobhealthdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#e36600'>[round(blob_core.health)]</font></div>"
|
||||
|
||||
/mob/camera/blob/proc/add_points(var/points)
|
||||
if(points != 0)
|
||||
blob_points = Clamp(blob_points + points, 0, max_blob_points)
|
||||
//sanity for manual spawned blob cameras
|
||||
if(hud_used)
|
||||
hud_used.blobpwrdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font color='#82ed00'>[src.blob_points]</font></div>"
|
||||
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(var/message)
|
||||
if (!message)
|
||||
@@ -79,21 +91,16 @@
|
||||
/mob/camera/blob/proc/blob_talk(message)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
|
||||
message = trim(sanitize(copytext(message, 1, MAX_MESSAGE_LEN)))
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
if (!message)
|
||||
return
|
||||
|
||||
var/verb = "states,"
|
||||
var/rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]</span> <span class='message'>[verb] \"[message]\"</span></span></i></font>"
|
||||
var/rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]([blob_reagent_datum.name])</span> <span class='message'>[verb] \"[message]\"</span></span></i></font>"
|
||||
|
||||
for (var/mob/camera/blob/S in world)
|
||||
if(istype(S))
|
||||
S.show_message(rendered, 2)
|
||||
|
||||
for (var/mob/M in dead_mob_list)
|
||||
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping
|
||||
rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]</span> ([ghost_follow_link(src, ghost=M)]) <span class='message'>[verb] \"[message]\"</span></span></i></font>"
|
||||
for (var/mob/M in mob_list)
|
||||
if(isovermind(M) || isobserver(M))
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null)
|
||||
@@ -103,14 +110,11 @@
|
||||
return
|
||||
|
||||
/mob/camera/blob/Stat()
|
||||
|
||||
statpanel("Status")
|
||||
..()
|
||||
if (client.statpanel == "Status")
|
||||
if(statpanel("Status"))
|
||||
if(blob_core)
|
||||
stat(null, "Core Health: [blob_core.health]")
|
||||
stat(null, "Power Stored: [blob_points]/[max_blob_points]")
|
||||
return
|
||||
|
||||
/mob/camera/blob/Move(var/NewLoc, var/Dir = 0)
|
||||
var/obj/effect/blob/B = locate() in range("3x3", NewLoc)
|
||||
@@ -119,5 +123,5 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/camera/experience_pressure_difference()
|
||||
return 0
|
||||
/mob/camera/blob/proc/can_attack()
|
||||
return (world.time > (last_attack + CLICK_CD_RANGE))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/mob/camera/blob/proc/can_buy(var/cost = 15)
|
||||
if(blob_points < cost)
|
||||
src << "<span class='warning'>You cannot afford this.</span>"
|
||||
src << "<span class='warning'>You cannot afford this!</span>"
|
||||
return 0
|
||||
add_points(-cost)
|
||||
return 1
|
||||
@@ -54,8 +54,9 @@
|
||||
if(!can_buy(10))
|
||||
return
|
||||
|
||||
|
||||
B.color = blob_reagent_datum.color
|
||||
B.change_to(/obj/effect/blob/shield)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -88,7 +89,7 @@
|
||||
if(!can_buy(40))
|
||||
return
|
||||
|
||||
|
||||
B.color = blob_reagent_datum.color
|
||||
B.change_to(/obj/effect/blob/resource)
|
||||
var/obj/effect/blob/resource/R = locate() in T
|
||||
if(R)
|
||||
@@ -96,39 +97,6 @@
|
||||
|
||||
return
|
||||
|
||||
/mob/camera/blob/proc/create_core()
|
||||
set category = "Blob"
|
||||
set name = "Create Core Blob (100)"
|
||||
set desc = "Create another Core Blob to aid in the station takeover"
|
||||
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
|
||||
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
|
||||
|
||||
if(!B)//We are on a blob
|
||||
src << "There is no blob here!"
|
||||
return
|
||||
|
||||
if(!istype(B, /obj/effect/blob/normal))
|
||||
src << "Unable to use this blob, find a normal one."
|
||||
return
|
||||
|
||||
for(var/obj/effect/blob/core/blob in orange(15))
|
||||
src << "There is another core blob nearby, move more than 15 tiles away from it!"
|
||||
return
|
||||
|
||||
if(!can_buy(100))
|
||||
return
|
||||
|
||||
|
||||
B.change_to(/obj/effect/blob/core, src)
|
||||
|
||||
return
|
||||
|
||||
/mob/camera/blob/verb/create_node()
|
||||
set category = "Blob"
|
||||
set name = "Create Node Blob (60)"
|
||||
@@ -157,8 +125,11 @@
|
||||
if(!can_buy(60))
|
||||
return
|
||||
|
||||
|
||||
B.change_to(/obj/effect/blob/node)
|
||||
var/obj/effect/blob/node/R = locate() in T
|
||||
if(R)
|
||||
R.adjustcolors(blob_reagent_datum.color)
|
||||
R.overmind = src
|
||||
return
|
||||
|
||||
|
||||
@@ -190,6 +161,67 @@
|
||||
return
|
||||
|
||||
B.change_to(/obj/effect/blob/factory)
|
||||
B.color = blob_reagent_datum.color
|
||||
var/obj/effect/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 (20)"
|
||||
set desc = "Create a powerful blob-being, a Blobbernaut"
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
|
||||
var/obj/effect/blob/B = locate(/obj/effect/blob) in T
|
||||
if(!B)
|
||||
src << "You must be on a blob!"
|
||||
return
|
||||
|
||||
if(!istype(B, /obj/effect/blob/factory))
|
||||
src << "Unable to use this blob, find a factory blob."
|
||||
return
|
||||
|
||||
if(!can_buy(20))
|
||||
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)
|
||||
blobber.color = blob_reagent_datum.color
|
||||
blobber.overmind = src
|
||||
blob_mobs.Add(blobber)
|
||||
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/effect/blob/node/B = locate(/obj/effect/blob/node) in T
|
||||
if(!B)
|
||||
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
|
||||
|
||||
|
||||
@@ -211,7 +243,7 @@
|
||||
src << "Unable to remove this blob."
|
||||
return
|
||||
|
||||
B.Delete()
|
||||
qdel(B)
|
||||
return
|
||||
|
||||
|
||||
@@ -227,6 +259,8 @@
|
||||
if(!T)
|
||||
return
|
||||
|
||||
if(!can_attack())
|
||||
return
|
||||
var/obj/effect/blob/B = locate() in T
|
||||
if(B)
|
||||
src << "There is a blob here!"
|
||||
@@ -237,14 +271,14 @@
|
||||
src << "There is no blob adjacent to you."
|
||||
return
|
||||
|
||||
for (var/mob/living/M in T.contents)
|
||||
if(M && !(M.stat))
|
||||
src << "You can't expand to a tile containing a living entity."
|
||||
return
|
||||
|
||||
if(!can_buy(5))
|
||||
return
|
||||
OB.expand(T, 0)
|
||||
last_attack = world.time
|
||||
OB.expand(T, 0, blob_reagent_datum.color)
|
||||
for(var/mob/living/L in T)
|
||||
blob_reagent_datum.reaction_mob(L, TOUCH, 25)
|
||||
blob_reagent_datum.send_message(L)
|
||||
OB.color = blob_reagent_datum.color
|
||||
return
|
||||
|
||||
|
||||
@@ -267,8 +301,107 @@
|
||||
if(!surrounding_turfs.len)
|
||||
return
|
||||
|
||||
for(var/mob/living/simple_animal/hostile/blobspore/BS in living_mob_list)
|
||||
for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in living_mob_list)
|
||||
if(isturf(BS.loc) && get_dist(BS, T) <= 35)
|
||||
BS.LoseTarget()
|
||||
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
|
||||
return
|
||||
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"
|
||||
|
||||
if(!blob_nodes || !blob_nodes.len)
|
||||
src << "<span class='warning'>A node is required to birth your offspring...</span>"
|
||||
return
|
||||
var/obj/effect/blob/node/N = locate(/obj/effect/blob) in blob_nodes
|
||||
if(!N)
|
||||
src << "<span class='warning'>A node is required to birth your offspring...</span>"
|
||||
return
|
||||
|
||||
if(!can_buy(100))
|
||||
return
|
||||
|
||||
verbs -= /mob/camera/blob/verb/split_consciousness //we've used our split_consciousness
|
||||
new /obj/effect/blob/core/ (get_turf(N), 200, null, blob_core.point_rate, "offspring")
|
||||
qdel(N)
|
||||
|
||||
if(ticker && ticker.mode.name == "blob")
|
||||
var/datum/game_mode/blob/BL = ticker.mode
|
||||
BL.blobwincount = initial(BL.blobwincount) * 2
|
||||
|
||||
|
||||
/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 = input(usr, "What would you like to say with your minions?", "Blob Broadcast", null) as text
|
||||
|
||||
if(!speak_text)
|
||||
return
|
||||
else
|
||||
usr << "You broadcast with your minions, <B>[speak_text]</B>"
|
||||
for(var/mob/living/simple_animal/hostile/blob_minion in blob_mobs)
|
||||
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/effect/blob/B = (locate(/obj/effect/blob) in T)
|
||||
|
||||
if(!B)//We are on a blob
|
||||
src << "There is no blob here!"
|
||||
return
|
||||
|
||||
if(!istype(B, /obj/effect/blob/normal))
|
||||
src << "Unable to use this blob, find a normal one."
|
||||
return
|
||||
|
||||
for(var/obj/effect/blob/storage/blob in orange(3, T))
|
||||
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/effect/blob/storage)
|
||||
var/obj/effect/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 different one"
|
||||
|
||||
if(!can_buy(50))
|
||||
return
|
||||
|
||||
var/list/excluded = list(/datum/reagent/blob, blob_reagent_datum.type) //guaranteed new chemical
|
||||
var/datum/reagent/blob/B = pick((typesof(/datum/reagent/blob) - excluded))
|
||||
blob_reagent_datum = new B
|
||||
|
||||
for(var/obj/effect/blob/BL in blobs)
|
||||
BL.adjustcolors(blob_reagent_datum.color)
|
||||
|
||||
for(var/mob/living/simple_animal/hostile/blob/BLO)
|
||||
BLO.adjustcolors(blob_reagent_datum.color)
|
||||
|
||||
src << "Your reagent is now: <b>[blob_reagent_datum.name]</b>!"
|
||||
+193
-146
@@ -2,7 +2,7 @@
|
||||
/obj/effect/blob
|
||||
name = "blob"
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
light_range = 0
|
||||
light_range = 3
|
||||
desc = "Some blob creature thingy"
|
||||
density = 0
|
||||
opacity = 0
|
||||
@@ -13,176 +13,223 @@
|
||||
var/fire_resist = 1
|
||||
|
||||
|
||||
New(loc)
|
||||
blobs += src
|
||||
src.dir = pick(1, 2, 4, 8)
|
||||
src.update_icon()
|
||||
..(loc)
|
||||
for(var/atom/A in loc)
|
||||
A.blob_act()
|
||||
return
|
||||
/obj/effect/blob/New(loc)
|
||||
blobs += src
|
||||
src.dir = pick(1, 2, 4, 8)
|
||||
src.update_icon()
|
||||
..(loc)
|
||||
for(var/atom/A in loc)
|
||||
A.blob_act()
|
||||
return
|
||||
|
||||
|
||||
Destroy()
|
||||
blobs -= src
|
||||
return ..()
|
||||
/obj/effect/blob/Destroy()
|
||||
blobs -= src
|
||||
if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it
|
||||
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
return ..()
|
||||
|
||||
|
||||
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || (height==0)) return 1
|
||||
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
|
||||
/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/process()
|
||||
Life()
|
||||
return
|
||||
|
||||
/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/proc/Life()
|
||||
return
|
||||
|
||||
/obj/effect/blob/proc/PulseAnimation()
|
||||
if(!istype(src, /obj/effect/blob/core) || !istype(src, /obj/effect/blob/node))
|
||||
flick("[icon_state]_glow", src)
|
||||
return
|
||||
|
||||
/obj/effect/blob/proc/RegenHealth()
|
||||
// All blobs heal over time when pulsed, but it has a cool down
|
||||
if(health_timestamp > world.time)
|
||||
return 0
|
||||
if(health < initial(health))
|
||||
health++
|
||||
update_icon()
|
||||
health_timestamp = world.time + 10 // 1 seconds
|
||||
|
||||
|
||||
process()
|
||||
Life()
|
||||
/obj/effect/blob/proc/Pulse(var/pulse = 0, var/origin_dir = 0, var/a_color)//Todo: Fix spaceblob expand
|
||||
|
||||
set background = BACKGROUND_ENABLED
|
||||
|
||||
PulseAnimation()
|
||||
|
||||
RegenHealth()
|
||||
|
||||
if(run_action())//If we can do something here then we dont need to pulse more
|
||||
return
|
||||
|
||||
fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
..()
|
||||
var/damage = Clamp(0.03 * exposed_temperature / fire_resist, 0, 7 - fire_resist)
|
||||
if(damage)
|
||||
health -= damage
|
||||
update_icon()
|
||||
if(pulse > 30)
|
||||
return//Inf loop check
|
||||
|
||||
proc/Life()
|
||||
for(var/atom/A in src.loc)//Hit everything in the turf
|
||||
A.blob_act()
|
||||
return
|
||||
|
||||
|
||||
proc/Pulse(var/pulse = 0, var/origin_dir = 0)//Todo: Fix spaceblob expand
|
||||
|
||||
//set background = 1
|
||||
|
||||
if(run_action())//If we can do something here then we dont need to pulse more
|
||||
//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/effect/blob/B = (locate(/obj/effect/blob) in T)
|
||||
if(!B)
|
||||
expand(T,1,a_color)//No blob here so try and expand
|
||||
return
|
||||
B.adjustcolors(a_color)
|
||||
|
||||
if(pulse > 20)
|
||||
return//Inf loop check
|
||||
B.Pulse((pulse+1),get_dir(src.loc,T), a_color)
|
||||
return
|
||||
return
|
||||
|
||||
//Looking for another blob to pulse
|
||||
|
||||
/obj/effect/blob/proc/run_action()
|
||||
return 0
|
||||
|
||||
|
||||
/obj/effect/blob/proc/expand(var/turf/T = null, var/prob = 1, var/a_color)
|
||||
if(prob && !prob(health)) return
|
||||
if(istype(T, /turf/space) && prob(75)) return
|
||||
if(!T)
|
||||
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/effect/blob/B = (locate(/obj/effect/blob) in T)
|
||||
if(!B)
|
||||
expand(T)//No blob here so try and expand
|
||||
return
|
||||
B.Pulse((pulse+1),get_dir(src.loc,T))
|
||||
return
|
||||
T = get_step(src, dirn)
|
||||
if(!(locate(/obj/effect/blob) in T)) break
|
||||
else T = null
|
||||
|
||||
if(!T) return 0
|
||||
var/obj/effect/blob/normal/B = new /obj/effect/blob/normal(src.loc, min(src.health, 30))
|
||||
B.color = a_color
|
||||
B.density = 1
|
||||
if(T.Enter(B,src))//Attempt to move into the tile
|
||||
B.density = initial(B.density)
|
||||
B.loc = T
|
||||
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
|
||||
A.blob_act()
|
||||
return 1
|
||||
|
||||
/obj/effect/blob/ex_act(severity)
|
||||
..()
|
||||
var/damage = 150 - 20 * severity
|
||||
take_damage(damage, BRUTE)
|
||||
|
||||
/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj)
|
||||
..()
|
||||
take_damage(Proj.damage, Proj.damage_type)
|
||||
return 0
|
||||
|
||||
/obj/effect/blob/Crossed(var/mob/living/L)
|
||||
..()
|
||||
L.blob_act()
|
||||
|
||||
|
||||
/obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/living/user, params)
|
||||
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 [W]!</span>")
|
||||
if(W.damtype == BURN)
|
||||
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
|
||||
take_damage(W.force, W.damtype)
|
||||
|
||||
/obj/effect/blob/attack_animal(mob/living/simple_animal/M as mob)
|
||||
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, BRUTE)
|
||||
return
|
||||
|
||||
/obj/effect/blob/attack_alien(mob/living/carbon/alien/humanoid/M as mob)
|
||||
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)
|
||||
return
|
||||
|
||||
/obj/effect/blob/proc/take_damage(damage, damage_type)
|
||||
if(!damage || damage_type == STAMINA) // Avoid divide by zero errors
|
||||
return
|
||||
switch(damage_type)
|
||||
if(BRUTE)
|
||||
damage /= max(brute_resist, 1)
|
||||
if(BURN)
|
||||
damage /= max(fire_resist, 1)
|
||||
health -= damage
|
||||
update_icon()
|
||||
|
||||
/obj/effect/blob/proc/change_to(var/type)
|
||||
if(!ispath(type))
|
||||
error("[type] is an invalid type for the blob.")
|
||||
var/obj/effect/blob/B = new type(src.loc)
|
||||
if(!istype(type, /obj/effect/blob/core) || !istype(type, /obj/effect/blob/node))
|
||||
B.color = color
|
||||
else
|
||||
B.adjustcolors(color)
|
||||
qdel(src)
|
||||
|
||||
proc/run_action()
|
||||
return 0
|
||||
/obj/effect/blob/proc/adjustcolors(var/a_color)
|
||||
if(a_color)
|
||||
color = a_color
|
||||
return
|
||||
|
||||
/obj/effect/blob/examine(mob/user)
|
||||
..()
|
||||
user << "It looks like it's of a [get_chem_name()] kind."
|
||||
return
|
||||
|
||||
proc/expand(var/turf/T = null, var/prob = 1)
|
||||
if(prob && !prob(health)) return
|
||||
if(istype(T, /turf/space) && 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/effect/blob) in T)) break
|
||||
else T = null
|
||||
|
||||
if(!T) return 0
|
||||
var/obj/effect/blob/normal/B = new /obj/effect/blob/normal(src.loc, min(src.health, 30))
|
||||
B.density = 1
|
||||
if(T.Enter(B,src))//Attempt to move into the tile
|
||||
B.density = initial(B.density)
|
||||
B.loc = T
|
||||
else
|
||||
T.blob_act()//If we cant move in hit the turf
|
||||
B.Delete()
|
||||
|
||||
for(var/atom/A in T)//Hit everything in the turf
|
||||
A.blob_act()
|
||||
return 1
|
||||
|
||||
|
||||
ex_act(severity)
|
||||
var/damage = 150
|
||||
health -= ((damage/brute_resist) - (severity * 5))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
attackby(var/obj/item/weapon/W, var/mob/living/user, params)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src)
|
||||
playsound(get_turf(src), 'sound/effects/attackblob.ogg', 50, 1)
|
||||
src.visible_message("\red <B>The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]")
|
||||
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/items/Welder.ogg', 100, 1)
|
||||
if("brute")
|
||||
damage = (W.force / max(src.brute_resist,1))
|
||||
|
||||
health -= damage
|
||||
update_icon()
|
||||
return
|
||||
|
||||
attack_animal(mob/living/simple_animal/M as mob)
|
||||
M.changeNext_move(CLICK_CD_MELEE)
|
||||
M.do_attack_animation(src)
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
|
||||
src.visible_message("<span class='danger'>The [src.name] has been attacked by \the [M]!</span>")
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(!damage) // Avoid divide by zero errors
|
||||
return
|
||||
damage /= max(src.brute_resist, 1)
|
||||
health -= damage
|
||||
update_icon()
|
||||
return
|
||||
|
||||
proc/change_to(var/type)
|
||||
if(!ispath(type))
|
||||
error("[type] is an invalid type for the blob.")
|
||||
new type(src.loc)
|
||||
Delete()
|
||||
return
|
||||
|
||||
proc/Delete()
|
||||
qdel(src)
|
||||
/obj/effect/blob/proc/get_chem_name()
|
||||
for(var/mob/camera/blob/B in 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/effect/blob/normal
|
||||
icon_state = "blob"
|
||||
luminosity = 0
|
||||
light_range = 0
|
||||
health = 21
|
||||
|
||||
Delete()
|
||||
src.loc = null
|
||||
blobs -= src
|
||||
/obj/effect/blob/normal/update_icon()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
else if(health <= 15)
|
||||
icon_state = "blob_damaged"
|
||||
else
|
||||
icon_state = "blob"
|
||||
|
||||
update_icon()
|
||||
if(health <= 0)
|
||||
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
||||
Delete()
|
||||
return
|
||||
if(health <= 15)
|
||||
icon_state = "blob_damaged"
|
||||
return
|
||||
/* // Used to create the glow sprites. Remember to set the animate loop to 1, instead of infinite!
|
||||
|
||||
var/datum/blob_colour/B = new()
|
||||
|
||||
/datum/blob_colour/New()
|
||||
..()
|
||||
var/icon/I = 'icons/mob/blob.dmi'
|
||||
I += rgb(35, 35, 0)
|
||||
if(isfile("icons/mob/blob_result.dmi"))
|
||||
fdel("icons/mob/blob_result.dmi")
|
||||
fcopy(I, "icons/mob/blob_result.dmi")
|
||||
|
||||
*/
|
||||
|
||||
@@ -115,6 +115,8 @@ Implants;
|
||||
// if(revdata)
|
||||
// feedback_set_details("revision","[revdata.revision]")
|
||||
feedback_set_details("server_ip","[world.internet_address]:[world.port]")
|
||||
start_state = new /datum/station_state()
|
||||
start_state.count()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -264,7 +266,6 @@ Implants;
|
||||
feedback_set("escaped_on_pod_5",escaped_on_pod_5)
|
||||
|
||||
send2mainirc("A round of [src.name] has ended - [surviving_total] survivors, [ghosts] ghosts.")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -465,6 +465,16 @@ var/global/datum/controller/gameticker/ticker
|
||||
|
||||
/datum/controller/gameticker/proc/declare_completion()
|
||||
|
||||
//Round statistics report
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
var/station_integrity = min(round( 100.0 * start_state.score(end_state), 0.1), 100.0)
|
||||
|
||||
world << "<BR>[TAB]Shift Duration: <B>[round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]</B>"
|
||||
world << "<BR>[TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>"
|
||||
world << "<BR>"
|
||||
|
||||
//Silicon laws report
|
||||
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
|
||||
if (aiPlayer.stat != 2)
|
||||
world << "<b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws at the end of the game were:</b>"
|
||||
|
||||
@@ -189,8 +189,8 @@
|
||||
return
|
||||
|
||||
/turf/simulated/wall/blob_act()
|
||||
take_damage(rand(75, 125))
|
||||
return
|
||||
if(prob(50))
|
||||
dismantle_wall()
|
||||
|
||||
/turf/simulated/wall/mech_melee_attack(obj/mecha/M)
|
||||
if(M.damtype == "brute")
|
||||
|
||||
@@ -493,6 +493,20 @@
|
||||
dat += "in [flag_loc.loc] at ([flag_loc.x], [flag_loc.y], [flag_loc.z])</td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
if(istype(ticker.mode, /datum/game_mode/blob))
|
||||
var/datum/game_mode/blob/mode = ticker.mode
|
||||
dat += "<br><table cellspacing=5><tr><td><B>Blob</B></td><td></td><td></td></tr>"
|
||||
dat += "<tr><td><i>Progress: [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><a href='?_src_=holder;adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(ghost)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
|
||||
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
|
||||
else
|
||||
dat += "<tr><td><i>Blob not found!</i></td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
if(ticker.mode.changelings.len)
|
||||
dat += check_role_table("Changelings", ticker.mode.changelings, src)
|
||||
|
||||
|
||||
@@ -1,73 +1,24 @@
|
||||
/datum/event/blob
|
||||
announceWhen = 120
|
||||
noAutoEnd = 1
|
||||
var/nuke_announced = 0
|
||||
|
||||
announceWhen = 12
|
||||
endWhen = 120
|
||||
var/obj/effect/blob/core/Blob
|
||||
|
||||
|
||||
/datum/event/blob/announce()
|
||||
command_announcement.Announce("Confirmed outbreak of level 7 biohazard aboard [station_name()]. Nanotrasen has issued a directive 7-10. The station is to be considered quarantined.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
|
||||
command_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in player_list)
|
||||
if (aiPlayer.client)
|
||||
var/law = "The station is under quarantine, prevent biological entities from leaving the station at all costs while minimizing collateral damage."
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
aiPlayer << "\red <b>You have detected a change in your laws information:</b>"
|
||||
aiPlayer << "Laws Updated: [law]"
|
||||
|
||||
/datum/event/blob/start()
|
||||
var/turf/T = pick(blobstart)
|
||||
if(!T)
|
||||
kill()
|
||||
return
|
||||
return kill()
|
||||
Blob = new /obj/effect/blob/core(T, 200)
|
||||
for(var/i = 1; i < rand(3, 6), i++)
|
||||
Blob.process()
|
||||
|
||||
|
||||
/datum/event/blob/tick()
|
||||
if(Blob && IsMultiple(activeFor, 3))
|
||||
Blob.process()
|
||||
if(blobs.len > 700*0.6 && !nuke_announced)
|
||||
announce_nuke()
|
||||
nuke_announced = 1
|
||||
if(!Blob && !blob_cores.len)
|
||||
if(!Blob)
|
||||
kill()
|
||||
return
|
||||
|
||||
/datum/event/blob/proc/announce_nuke()
|
||||
var/nukecode = "ERROR"
|
||||
for(var/obj/machinery/nuclearbomb/bomb in world)
|
||||
if(bomb && bomb.r_code && (bomb.z in config.station_levels))
|
||||
nukecode = bomb.r_code
|
||||
|
||||
command_announcement.Announce("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [nukecode] ", "Biohazard Alert")
|
||||
set_security_level("gamma")
|
||||
|
||||
var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world
|
||||
if(V && (V.z in config.station_levels))
|
||||
V.locked = 0
|
||||
V.update_icon()
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in player_list)
|
||||
if (aiPlayer.client)
|
||||
var/law = "The station is under quarantine, prevent biological entities from leaving the station at all costs. The nuclear failsafe must be activated at any cost, the code is: [nukecode]."
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
aiPlayer << "\red <b>You have detected a change in your laws information:</b>"
|
||||
aiPlayer << "Laws Updated: [law]"
|
||||
|
||||
spawn(10)
|
||||
world << sound('sound/effects/siren.ogg')
|
||||
|
||||
/datum/event/blob/kill()
|
||||
spawn(10)
|
||||
if(Blob || blob_cores.len)
|
||||
return
|
||||
command_announcement.Announce("The level 7 biohazard aboard [station_name()] has been eliminated. Directive 7-10 has been lifted, and the station is no longer quarantined.", "Biohazard Update")
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in player_list)
|
||||
if (aiPlayer.client)
|
||||
aiPlayer.clear_zeroth_law()
|
||||
aiPlayer << "\red <b>You have detected a change in your laws information:</b>"
|
||||
aiPlayer << "Laws Updated: Zeroth law removed."
|
||||
..()
|
||||
if(IsMultiple(activeFor, 3))
|
||||
Blob.process()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
/mob/camera
|
||||
name = "camera mob"
|
||||
density = 0
|
||||
anchored = 1
|
||||
status_flags = GODMODE // You can't damage it.
|
||||
mouse_opacity = 0
|
||||
see_in_dark = 7
|
||||
@@ -10,3 +11,9 @@
|
||||
|
||||
move_on_shuttle = 0
|
||||
|
||||
/mob/camera/experience_pressure_difference()
|
||||
return
|
||||
|
||||
/mob/camera/Destroy()
|
||||
..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
@@ -110,21 +110,6 @@
|
||||
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/alien/humanoid/blob_act()
|
||||
if (stat == 2)
|
||||
return
|
||||
var/shielded = 0
|
||||
var/damage = null
|
||||
if (stat != 2)
|
||||
damage = rand(30,40)
|
||||
|
||||
if(shielded)
|
||||
damage /= 4
|
||||
|
||||
show_message("<span class='userdanger'>The blob attacks!</span>")
|
||||
adjustFireLoss(damage)
|
||||
return
|
||||
|
||||
/mob/living/carbon/alien/humanoid/attack_slime(mob/living/carbon/slime/M as mob)
|
||||
if (!ticker)
|
||||
M << "You cannot attack people before the game has started."
|
||||
|
||||
@@ -101,30 +101,6 @@
|
||||
|
||||
updatehealth()
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/alien/larva/blob_act()
|
||||
if (stat == 2)
|
||||
return
|
||||
var/shielded = 0
|
||||
|
||||
var/damage = null
|
||||
if (stat != 2)
|
||||
damage = rand(10,30)
|
||||
|
||||
if(shielded)
|
||||
damage /= 4
|
||||
|
||||
//paralysis += 1
|
||||
|
||||
show_message("<span class='userdanger'>The blob attacks you!</span>")
|
||||
|
||||
adjustFireLoss(damage)
|
||||
|
||||
updatehealth()
|
||||
return
|
||||
|
||||
|
||||
//can't equip anything
|
||||
/mob/living/carbon/alien/larva/attack_ui(slot_id)
|
||||
return
|
||||
|
||||
@@ -60,5 +60,8 @@
|
||||
/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
|
||||
return
|
||||
|
||||
/mob/living/carbon/brain/blob_act()
|
||||
return
|
||||
|
||||
/mob/living/carbon/brain/binarycheck()
|
||||
return istype(loc, /obj/item/device/mmi/posibrain)
|
||||
@@ -20,6 +20,13 @@ mob/living
|
||||
if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
|
||||
germ_level++
|
||||
|
||||
/mob/living/carbon/blob_act()
|
||||
if (stat == DEAD)
|
||||
return
|
||||
else
|
||||
show_message("<span class='userdanger'>The blob attacks!</span>")
|
||||
adjustBruteLoss(10)
|
||||
|
||||
/mob/living/carbon/Move(NewLoc, direct)
|
||||
. = ..()
|
||||
if(.)
|
||||
|
||||
@@ -381,11 +381,11 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/blob_act()
|
||||
if(stat == 2) return
|
||||
show_message("\red The blob attacks you!")
|
||||
if(stat == DEAD) return
|
||||
show_message("<span class='userdanger'>The blob attacks you!</span>")
|
||||
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
|
||||
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
|
||||
apply_damage(rand(20,30), BRUTE, affecting, run_armor_check(affecting, "melee"))
|
||||
apply_damage(5, BRUTE, affecting, run_armor_check(affecting, "melee"))
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M as mob)
|
||||
|
||||
@@ -212,23 +212,8 @@
|
||||
|
||||
|
||||
/mob/living/carbon/slime/blob_act()
|
||||
if (stat == 2)
|
||||
return
|
||||
var/shielded = 0
|
||||
|
||||
var/damage = null
|
||||
if (stat != 2)
|
||||
damage = rand(10,30)
|
||||
|
||||
if(shielded)
|
||||
damage /= 4
|
||||
|
||||
//paralysis += 1
|
||||
|
||||
show_message("<span class='userdanger'> The blob attacks you!</span>")
|
||||
|
||||
adjustFireLoss(damage)
|
||||
|
||||
adjustBruteLoss(20)
|
||||
updatehealth()
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
// These can only be applied by blobs. They are what blobs are made out of.
|
||||
// The 4 damage
|
||||
/datum/reagent/blob
|
||||
var/message = "The blob strikes you" //message sent to any mob hit by the blob
|
||||
var/message_living = null //extension to first mob sent to only living mobs i.e. silicons have no skin to be burnt
|
||||
|
||||
/datum/reagent/blob/boiling_oil
|
||||
name = "Boiling Oil"
|
||||
id = "boiling_oil"
|
||||
description = ""
|
||||
color = "#B68D00"
|
||||
message = "The blob splashes you with burning oil"
|
||||
|
||||
/datum/reagent/blob/boiling_oil/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(15*ratio, BURN)
|
||||
M.adjust_fire_stacks(2*ratio)
|
||||
M.IgniteMob()
|
||||
if(isliving(M))
|
||||
M.emote("scream")
|
||||
|
||||
/datum/reagent/blob/toxic_goop
|
||||
name = "Toxic Goop"
|
||||
id = "toxic_goop"
|
||||
description = ""
|
||||
color = "#008000"
|
||||
message_living = ", and you feel sick and nauseated"
|
||||
|
||||
/datum/reagent/blob/toxic_goop/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(20*ratio, TOX)
|
||||
|
||||
/datum/reagent/blob/skin_ripper
|
||||
name = "Skin Ripper"
|
||||
id = "skin_ripper"
|
||||
description = ""
|
||||
color = "#FF4C4C"
|
||||
message_living = ", and you feel your skin ripping and tearing off"
|
||||
|
||||
/datum/reagent/blob/skin_ripper/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(20*ratio, BRUTE)
|
||||
if(iscarbon(M))
|
||||
M.emote("scream")
|
||||
|
||||
// Combo Reagents
|
||||
|
||||
/datum/reagent/blob/skin_melter
|
||||
name = "Skin Melter"
|
||||
id = "skin_melter"
|
||||
description = ""
|
||||
color = "#7F0000"
|
||||
message_living = ", and you feel your skin char and melt"
|
||||
|
||||
/datum/reagent/blob/skin_melter/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(10*ratio, BRUTE)
|
||||
M.apply_damage(10*ratio, BURN)
|
||||
M.adjust_fire_stacks(2*ratio)
|
||||
M.IgniteMob()
|
||||
if(iscarbon(M))
|
||||
M.emote("scream")
|
||||
|
||||
/datum/reagent/blob/lung_destroying_toxin
|
||||
name = "Lung Destroying Toxin"
|
||||
id = "lung_destroying_toxin"
|
||||
description = ""
|
||||
color = "#00FFC5"
|
||||
message_living = ", and your lungs feel heavy and weak"
|
||||
|
||||
/datum/reagent/blob/lung_destroying_toxin/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(20* ratio, OXY)
|
||||
M.losebreath += 15*ratio
|
||||
M.apply_damage(20*ratio, TOX)
|
||||
|
||||
// Special Reagents
|
||||
|
||||
/datum/reagent/blob/radioactive_liquid
|
||||
name = "Radioactive Liquid"
|
||||
id = "radioactive_liquid"
|
||||
description = ""
|
||||
color = "#00EE00"
|
||||
message_living = ", and your skin feels papery and everything hurts"
|
||||
|
||||
/datum/reagent/blob/radioactive_liquid/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(10*ratio, BRUTE)
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
M.apply_effect(40*ratio,IRRADIATE,0)
|
||||
if(prob(33*ratio))
|
||||
randmuti(M)
|
||||
if(prob(98))
|
||||
randmutb(M)
|
||||
domutcheck(M, null)
|
||||
M.UpdateAppearance()
|
||||
|
||||
/datum/reagent/blob/dark_matter
|
||||
name = "Dark Matter"
|
||||
id = "dark_matter"
|
||||
description = ""
|
||||
color = "#61407E"
|
||||
message = "You feel a thrum as the blob strikes you, and everything flies at you"
|
||||
|
||||
/datum/reagent/blob/dark_matter/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(15*ratio, BRUTE)
|
||||
reagent_vortex(M, 0)
|
||||
|
||||
|
||||
/datum/reagent/blob/b_sorium
|
||||
name = "Sorium"
|
||||
id = "b_sorium"
|
||||
description = ""
|
||||
color = "#808000"
|
||||
message = "The blob slams into you, and sends you flying"
|
||||
|
||||
/datum/reagent/blob/b_sorium/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.apply_damage(15*ratio, BRUTE)
|
||||
reagent_vortex(M, 1)
|
||||
|
||||
|
||||
/datum/reagent/blob/explosive // I'm gonna burn in hell for this one
|
||||
name = "Explosive Gelatin"
|
||||
id = "explosive"
|
||||
description = ""
|
||||
color = "#FFA500"
|
||||
message = "The blob strikes you, and its tendrils explode"
|
||||
|
||||
/datum/reagent/blob/explosive/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
if(prob(75*ratio))
|
||||
explosion(M.loc, 0, 0, 1, 0, 0)
|
||||
|
||||
/datum/reagent/blob/omnizine
|
||||
name = "Omnizine"
|
||||
id = "b_omnizine"
|
||||
description = ""
|
||||
color = "#C8A5DC"
|
||||
message = "The blob squirts something at you"
|
||||
message_living = ", and you feel great"
|
||||
|
||||
/datum/reagent/blob/omnizine/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.reagents.add_reagent("omnizine", 11*ratio)
|
||||
|
||||
/datum/reagent/blob/spacedrugs
|
||||
name = "Space drugs"
|
||||
id = "b_space_drugs"
|
||||
description = ""
|
||||
color = "#60A584"
|
||||
message = "The blob squirts something at you"
|
||||
message_living = ", and you feel funny"
|
||||
|
||||
/datum/reagent/blob/spacedrugs/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
var/ratio = volume/25
|
||||
M.hallucination += 20*ratio
|
||||
M.reagents.add_reagent("space_drugs", 15*ratio)
|
||||
M.apply_damage(10*ratio, TOX)
|
||||
|
||||
|
||||
/datum/reagent/blob/proc/reagent_vortex(var/mob/living/M as mob, var/setting_type)
|
||||
var/turf/pull = get_turf(M)
|
||||
for(var/atom/movable/X in range(4,pull))
|
||||
if(istype(X, /atom/movable))
|
||||
if((X) && !X.anchored)
|
||||
if(setting_type)
|
||||
step_away(X,pull)
|
||||
step_away(X,pull)
|
||||
step_away(X,pull)
|
||||
step_away(X,pull)
|
||||
else
|
||||
X.throw_at(pull)
|
||||
|
||||
/datum/reagent/blob/proc/send_message(var/mob/living/M as mob)
|
||||
var/totalmessage = message
|
||||
if(message_living && !issilicon(M))
|
||||
totalmessage += message_living
|
||||
totalmessage += "!"
|
||||
M << "<span class='userdanger'>[totalmessage]</span>"
|
||||
Reference in New Issue
Block a user