Merge branch 'blobrevamp' of https://github.com/Giacomand/vgstation13 into Bleeding-Edge

Conflicts:
	html/changelog.html
This commit is contained in:
Giacomand
2013-08-25 02:55:15 +01:00
50 changed files with 929 additions and 806 deletions

View File

@@ -52,8 +52,8 @@
#define FILE_DIR "sound/violin"
#define FILE_DIR "sound/voice"
#define FILE_DIR "sound/voice/Serithi"
#define FILE_DIR "sound/weapons"
#define FILE_DIR "sound/vox"
#define FILE_DIR "sound/weapons"
// END_FILE_DIR
// BEGIN_PREFERENCES
#define DEBUG
@@ -222,10 +222,13 @@
#include "code\game\gamemodes\blob\blob.dm"
#include "code\game\gamemodes\blob\blob_finish.dm"
#include "code\game\gamemodes\blob\blob_report.dm"
#include "code\game\gamemodes\blob\overmind.dm"
#include "code\game\gamemodes\blob\powers.dm"
#include "code\game\gamemodes\blob\theblob.dm"
#include "code\game\gamemodes\blob\blobs\core.dm"
#include "code\game\gamemodes\blob\blobs\factory.dm"
#include "code\game\gamemodes\blob\blobs\node.dm"
#include "code\game\gamemodes\blob\blobs\resource.dm"
#include "code\game\gamemodes\blob\blobs\shield.dm"
#include "code\game\gamemodes\changeling\changeling.dm"
#include "code\game\gamemodes\changeling\changeling_powers.dm"
@@ -866,6 +869,7 @@
#include "code\modules\mob\screen.dm"
#include "code\modules\mob\transform_procs.dm"
#include "code\modules\mob\update_icons.dm"
#include "code\modules\mob\camera\camera.dm"
#include "code\modules\mob\dead\death.dm"
#include "code\modules\mob\dead\observer\hud.dm"
#include "code\modules\mob\dead\observer\logout.dm"
@@ -878,7 +882,6 @@
#include "code\modules\mob\living\login.dm"
#include "code\modules\mob\living\logout.dm"
#include "code\modules\mob\living\say.dm"
#include "code\modules\mob\living\blob\blob.dm"
#include "code\modules\mob\living\carbon\carbon.dm"
#include "code\modules\mob\living\carbon\carbon_defines.dm"
#include "code\modules\mob\living\carbon\give.dm"

View File

@@ -95,10 +95,10 @@
/mob/living/simple_animal/hostile/panther/AttackTarget()
..()
if(stance == HOSTILE_STANCE_ATTACKING && get_dist(src, target_mob))
if(stance == HOSTILE_STANCE_ATTACKING && get_dist(src, target))
stalk_tick_delay -= 1
if(stalk_tick_delay <= 0)
src.loc = get_step_towards(src, target_mob)
src.loc = get_step_towards(src, target)
stalk_tick_delay = 3
//*******//
@@ -151,8 +151,8 @@
/mob/living/simple_animal/hostile/snake/AttackTarget()
..()
if(stance == HOSTILE_STANCE_ATTACKING && get_dist(src, target_mob))
if(stance == HOSTILE_STANCE_ATTACKING && get_dist(src, target))
stalk_tick_delay -= 1
if(stalk_tick_delay <= 0)
src.loc = get_step_towards(src, target_mob)
src.loc = get_step_towards(src, target)
stalk_tick_delay = 3

View File

@@ -72,7 +72,8 @@
for(var/mob/M in T)
if(!istype(M,/mob) || istype(M, /mob/aiEye)) continue // If we need to check for more mobs, I'll add a variable
if(!M.move_on_shuttle)
continue // If we need to check for more mobs, I'll add a variable
mobs += M
for(var/mob/M in mobs)

View File

@@ -429,6 +429,6 @@ zone/proc/movables()
. = list()
for(var/turf/T in contents)
for(var/atom/A in T)
if(istype(A, /obj/effect) || istype(A, /mob/aiEye))
if(istype(A, /obj/effect) || istype(A, /mob/camera))
continue
. += A

View File

@@ -350,6 +350,13 @@ var/list/DummyCache = list()
i++
return candidates
/proc/get_candidates(be_special_flag=0)
. = list()
for(var/mob/dead/observer/G in player_list)
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
if(!G.client.is_afk() && (G.client.prefs.be_special & be_special_flag))
. += G.client
/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
if(!isobj(O)) O = new /obj/screen/text()
O.maptext = maptext
@@ -366,4 +373,4 @@ var/list/DummyCache = list()
if(delay)
spawn(delay)
for(var/client/C in group)
C.screen -= O
C.screen -= O

View File

@@ -956,7 +956,8 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
if(!istype(O,/obj)) continue
O.loc = X
for(var/mob/M in T)
if(!istype(M,/mob) || istype(M, /mob/aiEye)) continue // If we need to check for more mobs, I'll add a variable
if(!M.move_on_shuttle)
continue
M.loc = X
// var/area/AR = X.loc
@@ -1117,7 +1118,8 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
for(var/mob/M in T)
if(!istype(M,/mob) || istype(M, /mob/aiEye)) continue // If we need to check for more mobs, I'll add a variable
if(!M.move_on_shuttle)
continue
mobs += M
for(var/mob/M in mobs)

View File

@@ -1142,18 +1142,21 @@ datum/mind
/mob/proc/sync_mind()
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
mind.active = 1 //indicates that the mind is currently synced with a client
//Initialisation procs
/mob/living/proc/mind_initialize()
/mob/proc/mind_initialize()
if(mind)
mind.key = key
else
mind = new /datum/mind(key)
mind.original = src
if(ticker)
ticker.minds += mind
else
world.log << "## DEBUG: mind_initialize(): No ticker ready yet! Please inform Carn"
error("mind_initialize(): No ticker ready yet! Please inform Carn")
if(!mind.name) mind.name = real_name
mind.current = src
@@ -1212,6 +1215,11 @@ datum/mind
mind.assigned_role = "pAI"
mind.special_role = ""
//BLOB
/mob/camera/overmind/mind_initialize()
..()
mind.special_role = "Blob"
//Animals
/mob/living/simple_animal/mind_initialize()
..()
@@ -1240,5 +1248,3 @@ datum/mind
mind.assigned_role = "Juggernaut"
mind.special_role = "Cultist"

View File

@@ -9,124 +9,158 @@ var/list/blob_nodes = list()
/datum/game_mode/blob
name = "blob"
config_tag = "blob"
required_players = 0
var/const/waittime_l = 1800 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 3600 //upper bound on time before intercept arrives (in tenths of seconds)
required_players = 30
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/stage = 0
var/cores_to_spawn = 1
var/players_per_core = 16
var/players_per_core = 30
var/blob_point_rate = 3
//Controls expansion via game controller
var/autoexpand = 0
var/expanding = 0
var/blobwincount = 350
var/blob_count = 0
var/blobnukecount = 300//Might be a bit low
var/blobwincount = 700//Still needs testing
var/list/infected_crew = list()
/datum/game_mode/blob/pre_setup()
var/list/possible_blobs = get_players_for_role(BE_ALIEN)
// stop setup if no possible traitors
if(!possible_blobs.len)
return 0
cores_to_spawn = max(round(num_players()/players_per_core, 1), 1)
blobwincount = initial(blobwincount) * cores_to_spawn
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."
for(var/j = 0, j < cores_to_spawn, j++)
if (!possible_blobs.len)
break
var/datum/mind/blob = pick(possible_blobs)
infected_crew += blob
blob.special_role = "Blob"
log_game("[blob.key] (ckey) has been selected as a Blob")
possible_blobs -= blob
if(!infected_crew.len)
return 0
return 1
post_setup()
spawn(10)
start_state = new /datum/station_state()
start_state.count()
spawn(rand(waittime_l, waittime_h))//3-5 minutes currently
message_admins("Blob spawned and expanding, report created")
if(!kill_air)
kill_air = 1
message_admins("Kill air has been set to true by Blob, testing to see how laggy it is without the extra processing from hullbreaches. Note: the blob is fireproof so plasma does not help anyways")
if(ticker && ticker.minds && ticker.minds.len)
var/player_based_cores = round(ticker.minds.len/players_per_core, 1)
if(player_based_cores > cores_to_spawn)
cores_to_spawn = player_based_cores
blobs = list()
for(var/i = 0 to cores_to_spawn)
var/turf/location = pick(blobstart)
if(location && !locate(/obj/effect/blob in location))
blobstart -= location
new/obj/effect/blob/core(location)
spawn(40)
autoexpand = 1
declared = 1
..()
/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."
process()
if(!declared) return
stage()
// if(!autoexpand) return
// spawn(0)
// expandBlob()
return
/datum/game_mode/blob/proc/greet_blob(var/datum/mind/blob)
blob.current << "<B>\red You are infected by the Blob!</B>"
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>"
blob.current << "<b>If you go outside of the station level, or in space, then you will die; make sure your location has lots of ground to cover.</b>"
return
/datum/game_mode/blob/proc/show_message(var/message)
for(var/datum/mind/blob in infected_crew)
blob.current << message
/datum/game_mode/blob/proc/burst_blobs()
for(var/datum/mind/blob in infected_crew)
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 != 1 || istype(location, /turf/space))
location = null
C.gib()
proc/expandBlob()//Currently disabled
if(expanding) return
if(!blobs.len) return
expanding = 1
for(var/i = 1 to 2)
sleep(-1)
if(!blobs.len) break
var/obj/effect/blob/B = pick(blobs)
if(B.z != 1)
continue
B.Life()
expanding = 0
return
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
proc/stage()
switch(stage)
if (0)
send_intercept(1)
for (var/mob/living/silicon/ai/aiPlayer in living_mob_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. NanoTrasen will not send an emergency shuttle under any circumstances."
//var/law = "The station is under quarantine. The biohazard must be destroyed at all costs and must not be allowed to spread. Anyone using a space suit for any reason other than to destroy the biohazard is to be terminated. NanoTrasen will not send an emergency shuttle under any circumstances."
aiPlayer.set_zeroth_law(law)
aiPlayer << "Laws Updated: [law]"
/datum/game_mode/blob/post_setup()
stage = -1
// next stage 1 minute later
spawn(600)
stage = 1
return
for(var/datum/mind/blob in infected_crew)
greet_blob(blob)
if (1)
command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << sound('sound/AI/outbreak5.ogg')
autoexpand = 0//No more extra pulses
stage = -1
//next stage in 4-5 minutes
spawn(600*rand(4,5))
stage = 2
return
if(emergency_shuttle)
emergency_shuttle.always_fake_recall = 1
if (2)
if((blobs.len > blobnukecount) && (declared == 1))
command_alert("Uncontrolled spread of the biohazard onboard the station. We have issued directive 7-12 for [station_name()]. Any living Heads of Staff are ordered to enact directive 7-12 at any cost, a print out with detailed instructions has been sent to your communications computers.", "Biohazard Alert")
send_intercept(2)
declared = 2
spawn(20)
set_security_level("delta")
if(blobs.len > blobwincount)
stage = 3
return
/*// 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)
sleep(wait_time)
send_intercept(0)
sleep(100)
show_message("<span class='alert'>You feel tired and bloated.</span>")
sleep(wait_time)
show_message("<span class='alert'>You feel like you are about to burst.</span>")
sleep(wait_time / 2)
burst_blobs()
// Stage 0
sleep(40)
stage(0)
// Stage 1
sleep(2000)
stage(1)
..()
/datum/game_mode/blob/proc/stage(var/stage)
switch(stage)
if (0)
send_intercept(1)
declared = 1
return
if (1)
command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << sound('sound/AI/outbreak5.ogg')
return
return

View File

@@ -1,27 +1,17 @@
/datum/game_mode/blob/check_finished()
if(!declared)//No blobs have been spawned yet
return 0
if(stage >= 3)//Blob took over
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
for(var/obj/effect/blob/B in blob_cores)
if(B && B.z != 1) continue
return 0
var/nodes = 0
for(var/obj/effect/blob/B in blob_nodes)
if(B && B.z != 1) continue
nodes++
if(nodes > 4)//Perhapse make a new core with a low prob
return 0
return 1
return 0
/datum/game_mode/blob/declare_completion()
if(stage >= 3)
if(blobwincount <= blobs.len)
feedback_set_details("round_end_result","loss - 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>"
@@ -32,7 +22,7 @@
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>"
else
else if(!blob_cores.len)
feedback_set_details("round_end_result","win - 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>"
@@ -46,6 +36,16 @@
..()
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.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]"
world << text
return 1
/datum/game_mode/blob/proc/check_quarantine()
var/numDead = 0

View File

@@ -4,6 +4,9 @@
var/intercepttext = ""
var/interceptname = "Error"
switch(report)
if(0)
..()
return
if(1)
interceptname = "Biohazard Alert"
intercepttext += "<FONT size = 3><B>NanoTrasen Update</B>: Biohazard Alert.</FONT><HR>"

View File

@@ -3,71 +3,87 @@
icon = 'icons/mob/blob.dmi'
icon_state = "blob_core"
health = 200
brute_resist = 2
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
New(loc, var/h = 200)
blobs += src
New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2)
blob_cores += src
processing_objects.Add(src)
if(!overmind)
create_overmind(new_overmind)
point_rate = new_rate
..(loc, h)
Del()
blob_cores -= src
if(overmind)
del(overmind)
processing_objects.Remove(src)
..()
return
fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
update_icon()
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
del(src)
Delete()
return
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)
..()
run_action()
Pulse(0,1)
Pulse(0,2)
Pulse(0,4)
Pulse(0,8)
//Should have the fragments in here somewhere
return 1
return 0
proc/create_fragments(var/wave_size = 1)
var/list/candidates = list()
for(var/mob/dead/observer/G in player_list)
if(G.client.prefs.be_special & BE_ALIEN)
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
candidates += G.key
proc/create_overmind(var/client/new_overmind)
if(candidates.len)
for(var/i = 0 to wave_size)
var/mob/living/blob/B = new/mob/living/blob(src.loc)
B.key = pick(candidates)
candidates -= B.key
/*
Pulse(var/pulse = 0, var/origin_dir = 0)//Todo: Fix spaceblob expand
set background = 1
if(pulse > 20) return
//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)//No blob here so try and expand
return
B.Pulse((pulse+1),get_dir(src.loc,T))
if(overmind_get_delay > world.time)
return
return
*/
overmind_get_delay = world.time + 300 // 30 seconds
if(overmind)
del(overmind)
var/client/C = null
var/list/candidates = list()
if(!new_overmind)
candidates = get_candidates(BE_ALIEN)
if(candidates.len)
C = pick(candidates)
else
C = new_overmind
if(C)
var/mob/camera/blob/B = new(src.loc)
B.key = C.key
B.blob_core = src
src.overmind = B
return 1
return 0

View File

@@ -1,24 +1,27 @@
/obj/effect/blob/factory
name = "porous blob"
name = "factory blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_factory"
health = 100
brute_resist = 1
fire_resist = 2
var/list/spores = list()
var/max_spores = 4
var/max_spores = 3
var/spore_delay = 0
update_icon()
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
del(src)
Delete()
return
return
run_action()
if(spores.len >= max_spores) return 0
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
@@ -26,14 +29,14 @@
/mob/living/simple_animal/hostile/blobspore
name = "blob"
desc = "Some blob thing."
icon = 'icons/mob/critter.dmi'
icon_state = "blobsquiggle"
icon_living = "blobsquiggle"
icon = 'icons/mob/blob.dmi'
icon_state = "blobpod"
icon_living = "blobpod"
pass_flags = PASSBLOB
health = 20
maxHealth = 20
melee_damage_lower = 4
melee_damage_upper = 8
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
@@ -49,18 +52,28 @@
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
..(loc)
return
Die()
..()
Die()
del(src)
Del()
if(factory)
factory.spores -= src
..()
del(src)

View File

@@ -3,16 +3,16 @@
icon = 'icons/mob/blob.dmi'
icon_state = "blob_node"
health = 100
brute_resist = 1
fire_resist = 2
New(loc, var/h = 100)
blobs += src
blob_nodes += src
processing_objects.Add(src)
..(loc, h)
fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
Del()
blob_nodes -= src
@@ -20,15 +20,18 @@
..()
return
Life()
for(var/i = 1; i < 8; i += i)
Pulse(5, i)
health = min(initial(health), health + 1)
update_icon()
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
del(src)
Delete()
return
return
run_action()
Pulse(0,0)
return 0

View File

@@ -0,0 +1,26 @@
/obj/effect/blob/resource
name = "resource blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
health = 30
fire_resist = 2
var/mob/camera/blob/overmind = null
var/resource_delay = 0
update_icon()
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
Delete()
return
return
run_action()
if(resource_delay > world.time)
return 0
resource_delay = world.time + 40 // 4 seconds
if(overmind)
overmind.add_points(1)
return 1

View File

@@ -3,21 +3,19 @@
icon = 'icons/mob/blob.dmi'
icon_state = "blob_idle"
desc = "Some blob creature thingy"
density = 1
opacity = 0
anchored = 1
health = 100
brute_resist = 1
health = 75
fire_resist = 2
update_icon()
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
del(src)
Delete()
return
return
fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1

View File

@@ -0,0 +1,17 @@
/datum/hud/proc/blob_hud(ui_style = 'icons/mob/screen_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)

View File

@@ -0,0 +1,66 @@
/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 = "blob"
var/obj/effect/blob/core/blob_core = null // The blob overmind's core
var/blob_points = 0
var/max_blob_points = 100
/mob/camera/blob/New()
var/new_name = "[initial(name)] ([rand(1, 999)])"
name = new_name
real_name = new_name
..()
/mob/camera/blob/Login()
..()
sync_mind()
src << "<span class='notice'>You are the overmind!</span>"
src << "You are the overmind and can control the blob by placing 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."
src << "<b>Resource Blob</b> is a blob which will collect more resources for you, try to build these earlier to get a strong income. It will benefit from being near your core or multiple nodes, by having an increased resource rate; put it alone and it won't create resources at all."
src << "<b>Node Blob</b> is a blob which will grow, like the core. Unlike the core it won't give you a small income but it can power resource and factory blobs to increase their rate."
src << "<b>Factory Blob</b> is a blob which will spawn blob spores which will attack nearby food. Putting this nearby nodes and your core will increase the spawn rate; put it alone and it will not spawn any spores."
mob/camera/blob/Life()
//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.blobhealthdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font color='#e36600'>[blob_core.health]</font></div>"
return
/mob/camera/blob/say(var/message)
return//No talking for you
/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null)
return
/mob/camera/blob/blob_act()
return
/mob/camera/blob/Stat()
statpanel("Status")
..()
if (client.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)
if(B)
loc = NewLoc
else
return 0

View File

@@ -0,0 +1,231 @@
// Point controlling procs
/mob/camera/blob/proc/can_buy(var/cost = 15)
if(blob_points < cost)
src << "<span class='warning'>You cannot afford this.</span>"
return 0
blob_points -= cost
return 1
/mob/camera/blob/proc/add_points(var/points = 0)
if(points)
blob_points = min(max_blob_points, blob_points + points)
// Power verbs
/mob/camera/blob/verb/transport_core()
set category = "Blob"
set name = "Jump to Core"
set desc = "Transport back to your core."
if(blob_core)
src.loc = blob_core.loc
/mob/camera/blob/verb/jump_to_node()
set category = "Blob"
set name = "Jump to Node"
set desc = "Transport back to a selected node."
if(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/verb/create_shield()
set category = "Blob"
set name = "Create Shield Blob (10)"
set desc = "Create a shield blob."
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
if(!can_buy(10))
return
B.change_to(/obj/effect/blob/shield)
return
/mob/camera/blob/verb/create_resource()
set category = "Blob"
set name = "Create Resource Blob (40)"
set desc = "Create a resource tower which will generate points for you."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/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/resource/blob in orange(4))
src << "There is a resource blob nearby, move more than 4 tiles away from it!"
return
if(!can_buy(40))
return
B.change_to(/obj/effect/blob/resource)
var/obj/effect/blob/resource/R = locate() in T
if(R)
R.overmind = src
return
/mob/camera/blob/verb/create_node()
set category = "Blob"
set name = "Create Node Blob (60)"
set desc = "Create a Node."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/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/node/blob in orange(5))
src << "There is another node nearby, move more than 5 tiles away from it!"
return
if(!can_buy(60))
return
B.change_to(/obj/effect/blob/node)
return
/mob/camera/blob/verb/create_factory()
set category = "Blob"
set name = "Create Factory Blob (60)"
set desc = "Create a Spore producing blob."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/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/normal))
src << "Unable to use this blob, find a normal one."
return
for(var/obj/effect/blob/factory/blob in orange(7))
src << "There is a factory blob nearby, move more than 7 tiles away from it!"
return
if(!can_buy(60))
return
B.change_to(/obj/effect/blob/factory)
return
/mob/camera/blob/verb/revert()
set category = "Blob"
set name = "Remove Blob"
set desc = "Removes a blob."
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/core))
src << "Unable to remove this blob."
return
B.Delete()
return
/mob/camera/blob/verb/spawn_blob()
set category = "Blob"
set name = "Expand Blob (5)"
set desc = "Attempts to create a new blob in this tile. If the tile isn't clear we will attack it, which might clear it."
var/turf/T = get_turf(src)
if(!T)
return
var/obj/effect/blob/B = locate() in T
if(B)
src << "There is a blob here!"
return
var/obj/effect/blob/OB = locate() in circlerange(src, 1)
if(!OB)
src << "There is no blob adjacent to you."
return
if(!can_buy(5))
return
OB.expand(T, 0)
return
/mob/camera/blob/verb/rally_spores()
set category = "Blob"
set name = "Rally Spores (5)"
set desc = "Rally the spores to move to your location."
if(!can_buy(5))
return
var/list/surrounding_turfs = block(locate(x - 1, y - 1, z), locate(x + 1, y + 1, z))
if(!surrounding_turfs.len)
return
for(var/mob/living/simple_animal/hostile/blobspore/BS in living_mob_list)
if(isturf(BS.loc) && get_dist(BS, src) <= 20)
BS.LoseTarget()
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
return

View File

@@ -2,32 +2,23 @@
/obj/effect/blob
name = "blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob"
luminosity = 3
desc = "Some blob creature thingy"
density = 1
density = 0
opacity = 0
anchored = 1
var/active = 1
var/health = 30
var/brute_resist = 4
var/fire_resist = 1
var/blob_type = "blob"
/*Types
Blob
Node
Core
Factory
Shield
*/
New(loc, var/h = 30)
New(loc)
blobs += src
src.health = h
src.dir = pick(1,2,4,8)
src.dir = pick(1, 2, 4, 8)
src.update_icon()
..(loc)
for(var/atom/A in loc)
A.blob_act()
return
@@ -44,22 +35,30 @@
process()
spawn(-1)
Life()
Life()
return
fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/damage = Clamp(0.01 * exposed_temperature / fire_resist, 0, 4 - fire_resist)
if(damage)
health -= damage
update_icon()
proc/Life()
return
proc/Pulse(var/pulse = 0, var/origin_dir = 0)//Todo: Fix spaceblob expand
set background = 1
if(!istype(src,/obj/effect/blob/core) && !istype(src,/obj/effect/blob/node))//Ill put these in the children later
if(run_action())//If we can do something here then we dont need to pulse more
return
if(!istype(src,/obj/effect/blob/shield) && !istype(src,/obj/effect/blob/core) && !istype(src,/obj/effect/blob/node) && (pulse <= 2) && (prob(30)))
change_to("Shield")
set background = 1
if(run_action())//If we can do something here then we dont need to pulse more
return
if(pulse > 20) return//Inf loop check
if(pulse > 30)
return//Inf loop check
//Looking for another blob to pulse
var/list/dirs = list(1,2,4,8)
dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us
@@ -81,20 +80,9 @@
return 0
proc/Life()
update_icon()
if(run_action())
return 1
return 0
/* temperature_expose(datum/gas_mixture/air, temperature, volume) Blob is currently fireproof
if(temperature > T0C+200)
health -= 0.01 * temperature
update()
*/
proc/expand(var/turf/T = null)
if(!prob(health)) 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)
@@ -105,47 +93,29 @@
else T = null
if(!T) return 0
var/obj/effect/blob/B = new /obj/effect/blob(src.loc, min(src.health, 30))
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
del(B)
B.Delete()
for(var/atom/A in T)//Hit everything in the turf
A.blob_act()
return 1
ex_act(severity)
var/damage = 50
switch(severity)
if(1)
src.health -= rand(100,120)
if(2)
src.health -= rand(60,100)
if(3)
src.health -= rand(20,60)
health -= (damage/brute_resist)
var/damage = 150
health -= ((damage/brute_resist) - (severity * 5))
update_icon()
return
update_icon()//Needs to be updated with the types
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
del(src)
return
if(health <= 15)
icon_state = "blob_damaged"
return
// if(health <= 20)
// icon_state = "blob_damaged2"
// return
bullet_act(var/obj/item/projectile/Proj)
if(!Proj) return
..()
switch(Proj.damage_type)
if(BRUTE)
health -= (Proj.damage/brute_resist)
@@ -172,50 +142,30 @@
update_icon()
return
proc/change_to(var/type = "Normal")
switch(type)
if("Normal")
new/obj/effect/blob(src.loc,src.health)
if("Node")
new/obj/effect/blob/node(src.loc,src.health*2)
if("Factory")
new/obj/effect/blob/factory(src.loc,src.health)
if("Shield")
new/obj/effect/blob/shield(src.loc,src.health*2)
del(src)
proc/change_to(var/type)
if(!ispath(type))
error("[type] is an invalid type for the blob.")
new type(src.loc)
Delete()
return
//////////////////////////////****IDLE BLOB***/////////////////////////////////////
proc/Delete()
del(src)
/obj/effect/blob/idle
name = "blob"
desc = "it looks... tasty"
icon_state = "blobidle0"
/obj/effect/blob/normal
icon_state = "blob"
luminosity = 0
health = 21
Delete()
src.loc = null
blobs -= src
New(loc, var/h = 10)
src.health = h
src.dir = pick(1,2,4,8)
src.update_idle()
proc/update_idle()
if(health<=0)
del(src)
update_icon()
if(health <= 0)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
Delete()
return
if(health<4)
icon_state = "blobc0"
if(health <= 15)
icon_state = "blob_damaged"
return
if(health<10)
icon_state = "blobb0"
return
icon_state = "blobidle0"
Del()
var/obj/effect/blob/B = new /obj/effect/blob( src.loc )
spawn(30)
B.Life()
..()

View File

@@ -89,6 +89,7 @@
return
/obj/machinery/camera/blob_act()
del(src)
return
/obj/machinery/camera/proc/setViewRange(var/num = 7)

View File

@@ -443,10 +443,6 @@
user << "The emergency shuttle is already on its way."
return
if(ticker.mode.name == "blob")
user << "Under directive 7-10, [station_name()] is quarantined until further notice."
return
emergency_shuttle.incall()
log_game("[key_name(user)] has called the shuttle.")
message_admins("[key_name_admin(user)] has called the shuttle.", 1)
@@ -485,7 +481,7 @@
//New version pretends to call the shuttle but cause the shuttle to return after a random duration.
emergency_shuttle.fake_recall = rand(300,500)
if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic")
if(ticker.mode.name == "epidemic")
user << "Under directive 7-10, [station_name()] is quarantined until further notice."
return
@@ -500,7 +496,7 @@
/proc/cancel_call_proc(var/mob/user)
if ((!( ticker ) || emergency_shuttle.location || emergency_shuttle.direction == 0 || emergency_shuttle.timeleft() < 300))
return
if((ticker.mode.name == "blob")||(ticker.mode.name == "meteor"))
if(ticker.mode.name == "meteor")
return
if(emergency_shuttle.direction != -1 && emergency_shuttle.online) //check that shuttle isn't already heading to centcomm

View File

@@ -262,6 +262,7 @@
if(istype(south)) air_master.tiles_to_update += south
if(istype(east)) air_master.tiles_to_update += east
if(istype(west)) air_master.tiles_to_update += west
update_freelok_sight()
return 1
/obj/machinery/door/proc/update_heat_protection(var/turf/simulated/source)

View File

@@ -610,6 +610,10 @@
return
*/
/obj/mecha/blob_act()
take_damage(30, "brute")
return
//TODO
/obj/mecha/meteorhit()
return ex_act(rand(1,3))//should do for now

View File

@@ -59,7 +59,7 @@
return
/obj/item/blob_act()
return
del(src)
//user: The mob that is suiciding
//damagetype: The type of damage the item will inflict on the user

View File

@@ -51,10 +51,6 @@ AI MODULES
usr << "You haven't selected an AI to transmit laws to!"
return
if(ticker && ticker.mode && ticker.mode.name == "blob")
usr << "Law uploads have been disabled by NanoTrasen!"
return
if (comp.current.stat == 2 || comp.current.control_disabled == 1)
usr << "Upload failed. No signal is being detected from the AI."
else if (comp.current.see_in_dark == 0)

View File

@@ -581,7 +581,6 @@ var/global/floorIsLava = 0
<A href='?src=\ref[src];secretsfun=moveminingshuttle'>Move Mining Shuttle</A><BR>
<A href='?src=\ref[src];secretsfun=blackout'>Break all lights</A><BR>
<A href='?src=\ref[src];secretsfun=whiteout'>Fix all lights</A><BR>
<A href='?src=\ref[src];secretsfun=friendai'>Best Friend AI</A><BR>
<A href='?src=\ref[src];secretsfun=floorlava'>The floor is lava! (DANGEROUS: extremely lame)</A><BR>
"}
@@ -1116,4 +1115,4 @@ proc/formatLocation(var/location)
return "[A.name] - [loc.x],[loc.y],[loc.z]"
proc/formatPlayerPanel(var/mob/U,var/text="PP")
return "<A HREF='?_src_=holder;adminplayeropts=\ref[U]'>[text]</A>"
return "<A HREF='?_src_=holder;adminplayeropts=\ref[U]'>[text]</A>"

View File

@@ -499,6 +499,20 @@
dat += "<tr><td><i>Traitor not found!</i></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>(logged out)</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>"
dat += "</body></html>"
usr << browse(dat, "window=roundstatus;size=400x500")
else

View File

@@ -202,10 +202,6 @@
else if(href_list["call_shuttle"])
if(!check_rights(R_ADMIN)) return
if( ticker.mode.name == "blob" )
alert("You can't call the shuttle during blob!")
return
switch(href_list["call_shuttle"])
if("1")
if ((!( ticker ) || emergency_shuttle.location))
@@ -1960,19 +1956,6 @@
for(var/obj/machinery/light/L in world)
L.fix()
message_admins("[key_name_admin(usr)] fixed all lights", 1)
if("friendai")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","FA")
for(var/mob/aiEye/aE in mob_list)
aE.icon_state = "ai_friend"
for(var/obj/machinery/M in machines)
if(istype(M, /obj/machinery/ai_status_display))
var/obj/machinery/ai_status_display/A = M
A.emotion = "Friend Computer"
else if(istype(M, /obj/machinery/status_display))
var/obj/machinery/status_display/A = M
A.friendc = 1
message_admins("[key_name_admin(usr)] turned all AIs into best friends.", 1)
if("aliens")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","AL")

View File

@@ -0,0 +1,11 @@
// Camera mob, used by AI camera and blob.
/mob/camera
name = "camera mob"
density = 0
status_flags = GODMODE // You can't damage it.
mouse_opacity = 0
see_in_dark = 7
invisibility = 101 // No one can see us
move_on_shuttle = 0

View File

@@ -1,259 +0,0 @@
/mob/living/blob
name = "blob fragment"
real_name = "blob fragment"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_spore_temp"
pass_flags = PASSBLOB
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
var/ghost_name = "Unknown"
var/creating_blob = 0
faction = "blob"
use_me = 0 //Blobs can't emote
New()
real_name += " [pick(rand(1, 99))]"
name = real_name
..()
say(var/message)
return//No talking for you
emote(var/act,var/m_type=1,var/message = null)
return
Life()
set invisibility = 0
set background = 1
clamp_values()
UpdateDamage()
if(health < 0)
src.dust()
proc/clamp_values()
AdjustStunned(0)
AdjustParalysis(0)
AdjustWeakened(0)
sleeping = 0
if(stat)
stat = CONSCIOUS
return
proc/UpdateDamage()
health = 60 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
return
death(gibbed)
if(key)
var/mob/dead/observer/ghost = new(src)
ghost.name = ghost_name
ghost.real_name = ghost_name
ghost.key = key
if (ghost.client)
ghost.client.eye = ghost
return ..(gibbed)
blob_act()
src << "The blob attempts to reabsorb you."
adjustToxLoss(20)
return
Process_Spacemove()
if(locate(/obj/effect/blob) in oview(1,src))
return 1
return (..())
/mob/living/blob/verb/create_node()
set category = "Blob"
set name = "Create Node"
set desc = "Create a Node."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)//We are on a blob
usr << "There is no blob here!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory))
usr << "Unable to use this blob, find a normal one."
creating_blob = 0
return
for(var/obj/effect/blob/node/blob in orange(5))
usr << "There is another node nearby, move more than 5 tiles away from it!"
creating_blob = 0
return
for(var/obj/effect/blob/factory/blob in orange(2))
usr << "There is a porus blob nearby, move more than 2 tiles away from it!"
creating_blob = 0
B.change_to("Node")
src.dust()
return
/mob/living/blob/verb/create_factory()
set category = "Blob"
set name = "Create Defense"
set desc = "Create a Spore producing blob."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)
usr << "You must be on a blob!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory))
usr << "Unable to use this blob, find a normal one."
creating_blob = 0
return
for(var/obj/effect/blob/blob in orange(2))//Not right next to nodes/cores
if(istype(B,/obj/effect/blob/node))
usr << "There is a node nearby, move away from it!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/core))
usr << "There is a core nearby, move away from it!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/factory))
usr << "There is another porous blob nearby, move away from it!"
creating_blob = 0
return
B.change_to("Factory")
src.dust()
return
/mob/living/blob/verb/revert()
set category = "Blob"
set name = "Purge Defense"
set desc = "Removes a porous blob."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)
usr << "You must be on a blob!"
creating_blob = 0
return
if(!istype(B,/obj/effect/blob/factory))
usr << "Unable to use this blob, find another one."
creating_blob = 0
return
B.change_to("Normal")
src.dust()
return
/mob/living/blob/verb/spawn_blob()
set category = "Blob"
set name = "Create new blob"
set desc = "Attempts to create a new blob in this tile."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(B)
usr << "There is a blob here!"
creating_blob = 0
return
new/obj/effect/blob(src.loc)
src.dust()
return
///mob/proc/Blobize()
/client/proc/Blobcount()
set category = "Debug"
set name = "blobreport"
set desc = "blob report."
set hidden = 1
if(!holder)
src << "Only administrators may use this command."
return
if(ticker && ticker.mode)
src << "blobs: [blobs.len]"
src << "cores: [blob_cores.len]"
src << "nodes: [blob_nodes.len]"
return
/client/proc/Blobize()//Mostly stolen from the respawn command
set category = "Debug"
set name = "Ghostblob"
set desc = "Ghost into blobthing."
set hidden = 1
if(!holder)
src << "Only administrators may use this command."
return
var/input = input(src, "Please specify which key will be turned into a bloby.", "Key", "")
var/mob/dead/observer/G_found
if(!input)
var/list/ghosts = list()
for(var/mob/dead/observer/G in player_list)
ghosts += G
if(ghosts.len)
G_found = pick(ghosts)
else
for(var/mob/dead/observer/G in player_list)
if(G.client&&ckey(G.key)==ckey(input))
G_found = G
break
if(!G_found)//If a ghost was not found.
alert("There is no active key like that in the game or the person is not currently a ghost. Aborting command.")
return
if(G_found.client)
G_found.client.screen.len = null
var/mob/living/blob/B = new/mob/living/blob(locate(0,0,1))//temp area also just in case should do this better but tired
if(blob_cores.len > 0)
var/obj/effect/blob/core/core = pick(blob_cores)
if(core)
B.loc = core.loc
B.ghost_name = G_found.real_name
if (G_found.client)
G_found.client.mob = B
B.verbs += /mob/living/blob/verb/create_node
B.verbs += /mob/living/blob/verb/create_factory
B << "<B>You are now a blob fragment.</B>"
B << "You are a weak bit that has temporarily broken off of the blob."
B << "If you stay on the blob for too long you will likely be reabsorbed."
B << "If you stray from the blob you will likely be killed by other organisms."
B << "You have the power to create a new blob node that will help expand the blob."
B << "To create this node you will have to be on a normal blob tile and far enough away from any other node."
B << "Check your Blob verbs and hit Create Node to build a node."
spawn(10)
del(G_found)

View File

@@ -225,7 +225,7 @@
show_message("\red The blob attacks you!")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone))
apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
apply_damage(rand(20,30), BRUTE, affecting, run_armor_check(affecting, "melee"))
return
/mob/living/carbon/human/meteorhit(O as obj)

View File

@@ -2,8 +2,7 @@
/mob/living/Login()
..()
//Mind updates
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
mind.active = 1 //indicates that the mind is currently synced with a client
sync_mind()
//Round specific stuff like hud updates
if(ticker && ticker.mode)

View File

@@ -2,6 +2,8 @@
//
// The datum containing all the chunks.
var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
var/datum/cameranet/cameranet = new()
/datum/cameranet
@@ -13,16 +15,16 @@ var/datum/cameranet/cameranet = new()
// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
x &= ~0xf
y &= ~0xf
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
var/key = "[x],[y],[z]"
return (chunks[key])
// Returns the chunk in the x, y, z.
// If there is no chunk, it creates a new chunk and returns that.
/datum/cameranet/proc/getCameraChunk(x, y, z)
x &= ~0xf
y &= ~0xf
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
var/key = "[x],[y],[z]"
if(!chunks[key])
chunks[key] = new /datum/camerachunk(null, x, y, z)
@@ -31,18 +33,18 @@ var/datum/cameranet/cameranet = new()
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(mob/aiEye/ai)
/datum/cameranet/proc/visibility(mob/camera/aiEye/ai)
// 0xf = 15
var/x1 = max(0, ai.x - 16) & ~0xf
var/y1 = max(0, ai.y - 16) & ~0xf
var/x2 = min(world.maxx, ai.x + 16) & ~0xf
var/y2 = min(world.maxy, ai.y + 16) & ~0xf
var/x1 = max(0, ai.x - 16) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, ai.x + 16) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, ai.y + 16) & ~(CHUNK_SIZE - 1)
var/list/visibleChunks = list()
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
visibleChunks += getCameraChunk(x, y, ai.z)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
visibleChunks |= getCameraChunk(x, y, ai.z)
var/list/remove = ai.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - ai.visibleCameraChunks
@@ -103,15 +105,15 @@ var/datum/cameranet/cameranet = new()
var/turf/T = get_turf(c)
if(T)
var/x1 = max(0, T.x - 8) & ~0xf
var/y1 = max(0, T.y - 8) & ~0xf
var/x2 = min(world.maxx, T.x + 8) & ~0xf
var/y2 = min(world.maxy, T.y + 8) & ~0xf
var/x1 = max(0, T.x - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, T.y - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, T.x + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
//world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]"
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
if(chunkGenerated(x, y, T.z))
var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z)
if(choice == 0)

View File

@@ -21,7 +21,7 @@
// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/aiEye/ai)
/datum/camerachunk/proc/add(mob/camera/aiEye/ai)
if(!ai.ai)
return
ai.visibleCameraChunks += src
@@ -34,7 +34,7 @@
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/aiEye/ai)
/datum/camerachunk/proc/remove(mob/camera/aiEye/ai)
if(!ai.ai)
return
ai.visibleCameraChunks -= src
@@ -81,11 +81,14 @@
if(!c.can_use())
continue
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
if(get_dist(point, c) > 24)
var/turf/point = locate(src.x + (CHUNK_SIZE / 2), src.y + (CHUNK_SIZE / 2), src.z)
if(get_dist(point, c) > CHUNK_SIZE + (CHUNK_SIZE / 2))
continue
for(var/turf/t in c.can_see())
// Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards.
// List associations use a tree or hashmap of some sort (alongside the list itself)
// so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing)
newVisibleTurfs[t] = t
// Removes turf that isn't in turfs.
@@ -102,7 +105,7 @@
if(t.obscured)
obscured -= t.obscured
for(var/eye in seenby)
var/mob/aiEye/m = eye
var/mob/camera/aiEye/m = eye
if(!m || !m.ai)
continue
if(m.ai.client)
@@ -116,32 +119,33 @@
obscured += t.obscured
for(var/eye in seenby)
var/mob/aiEye/m = eye
var/mob/camera/aiEye/m = eye
if(!m || !m.ai)
seenby -= m
continue
if(m.ai.client)
m.ai.client.images += t.obscured
changed = 0
// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(loc, x, y, z)
// 0xf = 15
x &= ~0xf
y &= ~0xf
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
src.x = x
src.y = y
src.z = z
for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z)))
for(var/obj/machinery/camera/c in range(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z)))
if(c.can_use())
cameras += c
for(var/turf/t in range(10, locate(x + 8, y + 8, z)))
if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16)
turfs[t] = t
for(var/turf/t in block(locate(x, y, z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z)))
turfs[t] = t
for(var/camera in cameras)
var/obj/machinery/camera/c = camera
@@ -152,6 +156,9 @@
continue
for(var/turf/t in c.can_see())
// Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards.
// List associations use a tree or hashmap of some sort (alongside the list itself)
// so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing)
visibleTurfs[t] = t
// Removes turf that isn't in turfs.

View File

@@ -3,40 +3,17 @@
// An invisible (no icon) mob that the AI controls to look around the station with.
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
/mob/aiEye
/mob/camera/aiEye
name = "Inactive AI Eye"
icon = 'icons/obj/status_display.dmi' // For AI friend secret shh :o
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
density = 0
status_flags = GODMODE // You can't damage it.
mouse_opacity = 0
see_in_dark = 7
// Movement code. Returns 0 to stop air movement from moving it.
/mob/aiEye/Move()
return 0
// Hide popout menu verbs
/mob/aiEye/examine()
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/pull()
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/point()
set popup_menu = 0
set src = usr.contents
return 0
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/aiEye/proc/setLoc(var/T)
/mob/camera/aiEye/proc/setLoc(var/T)
if(ai)
if(!isturf(ai.loc))
@@ -51,13 +28,16 @@
var/obj/machinery/hologram/holopad/H = ai.current
H.move_hologram()
/mob/camera/aiEye/Move()
return 0
// AI MOVEMENT
// The AI's "eye". Described on the top of the page.
/mob/living/silicon/ai
var/mob/aiEye/eyeobj = new()
var/mob/camera/aiEye/eyeobj = new()
var/sprint = 10
var/cooldown = 0
var/acceleration = 1

View File

@@ -49,8 +49,7 @@
// DOORS
// Simply updates the visibility of the area when it opens/closes/destroyed.
/obj/machinery/door/update_nearby_tiles(need_rebuild)
. = ..(need_rebuild)
/obj/machinery/door/proc/update_freelok_sight()
// Glass door glass = 1
// don't check then?
if(!glass && cameranet)

View File

@@ -298,6 +298,9 @@
adjustBruteLoss(60)
updatehealth()
return 1
else
gib()
return 1
return 0
// this function shows information about the malf_ai gameplay type in the status screen

View File

@@ -14,9 +14,9 @@
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "pokes the"
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
stop_automated_movement_when_pulled = 0
maxHealth = 60
health = 60
@@ -43,25 +43,28 @@
desc = ""
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "pokes"
response_harm = "hits"
/mob/living/simple_animal/hostile/bear/Move()
..()
if(stat != DEAD)
if(loc && istype(loc,/turf/space))
icon_state = "bear"
else
icon_state = "bearfloor"
/mob/living/simple_animal/hostile/bear/Life()
. =..()
if(!.)
return
if(loc && istype(loc,/turf/space))
icon_state = "bear"
else
icon_state = "bearfloor"
switch(stance)
if(HOSTILE_STANCE_TIRED)
stop_automated_movement = 1
stance_step++
if(stance_step >= 10) //rests for 10 ticks
if(target_mob && target_mob in ListTargets(10))
if(target && target in ListTargets())
stance = HOSTILE_STANCE_ATTACK //If the mob he was chasing is still nearby, resume the attack, otherwise go idle.
else
stance = HOSTILE_STANCE_IDLE
@@ -69,15 +72,15 @@
if(HOSTILE_STANCE_ALERT)
stop_automated_movement = 1
var/found_mob = 0
if(target_mob && target_mob in ListTargets(10))
if(!(SA_attackable(target_mob)))
if(target && target in ListTargets())
if(!(SA_attackable(target)))
stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again.
stance_step++
found_mob = 1
src.dir = get_dir(src,target_mob) //Keep staring at the mob
src.dir = get_dir(src,target) //Keep staring at the mob
if(stance_step in list(1,4,7)) //every 3 ticks
var/action = pick( list( "growls at [target_mob]", "stares angrily at [target_mob]", "prepares to attack [target_mob]", "closely watches [target_mob]" ) )
var/action = pick( list( "growls at [target]", "stares angrily at [target]", "prepares to attack [target]", "closely watches [target]" ) )
if(action)
emote(action)
if(!found_mob)
@@ -102,18 +105,18 @@
if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING)
stance = HOSTILE_STANCE_ALERT
stance_step = 6
target_mob = user
target = user
..()
/mob/living/simple_animal/hostile/bear/attack_hand(mob/living/carbon/human/M as mob)
if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING)
stance = HOSTILE_STANCE_ALERT
stance_step = 6
target_mob = M
target = M
..()
/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/check_drift = 0)
return //No drifting in space for space bears!
return 1 //No drifting in space for space bears!
/mob/living/simple_animal/hostile/bear/FindTarget()
. = ..()
@@ -125,22 +128,22 @@
..(5)
/mob/living/simple_animal/hostile/bear/AttackingTarget()
emote( pick( list("slashes at [target_mob]", "bites [target_mob]") ) )
emote( pick( list("slashes at [target]", "bites [target]") ) )
var/damage = rand(20,30)
if(ishuman(target_mob))
var/mob/living/carbon/human/H = target_mob
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = H.get_organ(ran_zone(dam_zone))
H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee"))
return H
else if(isliving(target_mob))
var/mob/living/L = target_mob
else if(isliving(target))
var/mob/living/L = target
L.adjustBruteLoss(damage)
return L
else if(istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
else if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.attack_animal(src)
return M

View File

@@ -34,7 +34,7 @@
max_n2 = 0
minbodytemp = 0
break_stuff_probability = 2
//break_stuff_probability = 2
faction = "carp"

View File

@@ -17,9 +17,9 @@
turns_per_move = 5
see_in_dark = 10
meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "pokes the"
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
stop_automated_movement_when_pulled = 0
maxHealth = 200
health = 200
@@ -33,7 +33,6 @@
var/busy = 0
pass_flags = PASSTABLE
move_to_delay = 6
speed = 3
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/giant_spider/nurse
@@ -65,8 +64,8 @@
/mob/living/simple_animal/hostile/giant_spider/AttackingTarget()
..()
if(isliving(target_mob))
var/mob/living/L = target_mob
if(isliving(target))
var/mob/living/L = target
if(L.reagents)
L.reagents.add_reagent("toxin", poison_per_bite)
if(prob(poison_per_bite))
@@ -83,7 +82,7 @@
for(var/turf/T in orange(20, src))
move_targets.Add(T)*/
stop_automated_movement = 1
walk_to(src, pick(orange(20, src)), 1, move_to_delay)
Goto(pick(orange(20, src)), move_to_delay)
spawn(50)
stop_automated_movement = 0
walk(src,0)
@@ -105,10 +104,10 @@
if(!busy && prob(30))
//first, check for potential food nearby to cocoon
for(var/mob/living/C in can_see)
if(C.stat)
if(C.stat && !istype(C,/mob/living/simple_animal/hostile/giant_spider))
cocoon_target = C
busy = MOVING_TO_TARGET
walk_to(src, C, 1, move_to_delay)
Goto(C, move_to_delay)
//give up if we can't reach them after 10 seconds
GiveUp(C)
return
@@ -150,7 +149,7 @@
cocoon_target = O
busy = MOVING_TO_TARGET
stop_automated_movement = 1
walk_to(src, O, 1, move_to_delay)
Goto(O, move_to_delay)
//give up if we can't reach them after 10 seconds
GiveUp(O)

View File

@@ -1,27 +1,23 @@
/mob/living/simple_animal/hostile
faction = "hostile"
var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior
var/mob/living/target_mob
var/target
var/attack_same = 0
var/ranged = 0
var/rapid = 0
var/projectiletype
var/projectilesound
var/casingtype
var/move_to_delay = 4 //delay for the automated movement.
var/move_to_delay = 2 //delay for the automated movement.
var/list/friends = list()
var/break_stuff_probability = 10
var/vision_range = 10
stop_automated_movement_when_pulled = 0
var/destroy_surroundings = 1
/mob/living/simple_animal/hostile/proc/FindTarget()
var/atom/T = null
stop_automated_movement = 0
for(var/atom/A in ListTargets(10))
if(A == src)
continue
for(var/atom/A in ListTargets())
var/atom/F = Found(A)
if(F)
@@ -36,72 +32,68 @@
continue
else
if(!L.stat)
stance = HOSTILE_STANCE_ATTACK
T = L
break
else if(istype(A, /obj/mecha)) // Our line of sight stuff was already done in ListTargets().
var/obj/mecha/M = A
if (M.occupant)
stance = HOSTILE_STANCE_ATTACK
T = M
break
if(istype(A, /obj/machinery/bot))
var/obj/machinery/bot/B = A
if (B.health > 0)
stance = HOSTILE_STANCE_ATTACK
T = B
break
return T
/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)
target = new_target
stance = HOSTILE_STANCE_ATTACK
return
/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay)
walk_to(src, target, 1, delay)
/mob/living/simple_animal/hostile/proc/Found(var/atom/A)
return
/mob/living/simple_animal/hostile/proc/MoveToTarget()
stop_automated_movement = 1
if(!target_mob || SA_attackable(target_mob))
stance = HOSTILE_STANCE_IDLE
if(target_mob in ListTargets(10))
if(!target || SA_attackable(target))
LoseTarget()
if(target in ListTargets())
if(ranged)
if(get_dist(src, target_mob) <= 6)
OpenFire(target_mob)
if(get_dist(src, target) <= 6)
OpenFire(target)
else
walk_to(src, target_mob, 1, move_to_delay)
Goto(target, move_to_delay)
else
stance = HOSTILE_STANCE_ATTACKING
walk_to(src, target_mob, 1, move_to_delay)
Goto(target, move_to_delay)
/mob/living/simple_animal/hostile/proc/AttackTarget()
stop_automated_movement = 1
if(!target_mob || SA_attackable(target_mob))
if(!target || SA_attackable(target))
LoseTarget()
return 0
if(!(target_mob in ListTargets(10)))
if(!(target in ListTargets()))
LostTarget()
return 0
if(get_dist(src, target_mob) <= 1) //Attacking
if(get_dist(src, target) <= 1) //Attacking
AttackingTarget()
return 1
/mob/living/simple_animal/hostile/proc/AttackingTarget()
if(isliving(target_mob))
var/mob/living/L = target_mob
if(isliving(target))
var/mob/living/L = target
L.attack_animal(src)
return L
if(istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.attack_animal(src)
return M
if(istype(target_mob,/obj/machinery/bot))
var/obj/machinery/bot/B = target_mob
B.attack_animal(src)
/mob/living/simple_animal/hostile/proc/LoseTarget()
stance = HOSTILE_STANCE_IDLE
target_mob = null
target = null
walk(src, 0)
/mob/living/simple_animal/hostile/proc/LostTarget()
@@ -109,9 +101,17 @@
walk(src, 0)
/mob/living/simple_animal/hostile/proc/ListTargets(var/dist = 7)
var/list/L = hearers(src, dist)
L += mechas_list
/mob/living/simple_animal/hostile/proc/ListTargets(var/override = -1)
// Allows you to override how much the mob can see. Defaults to vision_range if none is entered.
if(override == -1)
override = vision_range
var/list/L = hearers(src, override)
for(var/obj/mecha/M in mechas_list)
// Will check the distance before checking the line of sight, if the distance is small enough.
if(get_dist(M, src) <= override && can_see(src, M, override))
L += M
return L
/mob/living/simple_animal/hostile/Die()
@@ -130,20 +130,19 @@
if(!stat)
switch(stance)
if(HOSTILE_STANCE_IDLE)
target_mob = FindTarget()
var/new_target = FindTarget()
GiveTarget(new_target)
if(HOSTILE_STANCE_ATTACK)
if(destroy_surroundings)
DestroySurroundings()
DestroySurroundings()
MoveToTarget()
if(HOSTILE_STANCE_ATTACKING)
if(destroy_surroundings)
DestroySurroundings()
DestroySurroundings()
AttackTarget()
/mob/living/simple_animal/hostile/proc/OpenFire(target_mob)
var/target = target_mob
/mob/living/simple_animal/hostile/proc/OpenFire(var/the_target)
var/target = the_target
visible_message("\red <b>[src]</b> fires at [target]!", 1)
var/tturf = get_turf(target)
@@ -166,7 +165,7 @@
new casingtype
stance = HOSTILE_STANCE_IDLE
target_mob = null
target = null
return
@@ -189,8 +188,7 @@
return
/mob/living/simple_animal/hostile/proc/DestroySurroundings()
if(prob(break_stuff_probability))
for(var/dir in cardinal) // North, South, East, West
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
obstacle.attack_animal(src)
for(var/dir in cardinal) // North, South, East, West
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
obstacle.attack_animal(src)

View File

@@ -22,7 +22,7 @@
speed = 8
projectiletype = /obj/item/projectile/beam/drone
projectilesound = 'sound/weapons/laser3.ogg'
destroy_surroundings = 0
//destroy_surroundings = 0
var/datum/effect/effect/system/ion_trail_follow/ion_trail
//the drone randomly switches between these states because it's malfunctioning

View File

@@ -3,7 +3,7 @@
icon = 'icons/mob/animal.dmi'
health = 20
maxHealth = 20
immune_to_ssd = 1
var/icon_living = ""
var/icon_dead = ""
var/icon_gib = null //We only try to show a gibbing animation if this exists.
@@ -24,9 +24,9 @@
var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it.
//Interaction
var/response_help = "You try to help"
var/response_disarm = "You try to disarm"
var/response_harm = "You try to hurt"
var/response_help = "pokes"
var/response_disarm = "shoves"
var/response_harm = "hits"
var/harm_intent_damage = 3
//Temperature effect
@@ -217,6 +217,11 @@
new meat_type(src.loc)
..()
/mob/living/simple_animal/blob_act()
adjustBruteLoss(20)
return
/mob/living/simple_animal/say_quote(var/text)
if(speak_emote && speak_emote.len)
var/emote = pick(speak_emote)
@@ -224,10 +229,14 @@
return "[emote], \"[text]\""
return "says, \"[text]\"";
/mob/living/simple_animal/emote(var/act, var/type, var/desc)
/mob/living/simple_animal/emote(var/act)
if(stat)
return
if(act)
if(act == "scream") act = "whimper" //ugly hack to stop animals screaming when crushed :P
..(act, type, desc)
if(act == "scream") act = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P
for (var/mob/O in viewers(src, null))
O.show_message("<B>[src]</B> [act].")
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob)
if(M.melee_damage_upper == 0)
@@ -236,7 +245,7 @@
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
for(var/mob/O in viewers(src, null))
O.show_message("\red <B>[M]</B> [M.attacktext] [src]!", 1)
O.show_message("\red <B>\The [M]</B> [M.attacktext] [src]!", 1)
M.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name] ([src.ckey])</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
@@ -256,15 +265,15 @@
if (health > 0)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\blue [M] [response_help] [src]")
O.show_message("\blue [M] [response_help] [src].")
if("grab")
if (M == src)
if (M == src || anchored)
return
if (!(status_flags & CANPUSH))
return
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src )
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src )
M.put_in_active_hand(G)
@@ -277,11 +286,11 @@
if ((O.client && !( O.blinded )))
O.show_message(text("\red [] has grabbed [] passively!", M, src), 1)
if("hurt", "disarm")
if("harm", "disarm")
adjustBruteLoss(harm_intent_damage)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red [M] [response_harm] [src]")
O.show_message("\red [M] [response_harm] [src]!")
return
@@ -295,12 +304,12 @@
if ((O.client && !( O.blinded )))
O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1)
if ("grab")
if(M == src)
if(M == src || anchored)
return
if(!(status_flags & CANPUSH))
return
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src )
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src )
M.put_in_active_hand(G)
@@ -313,7 +322,7 @@
if ((O.client && !( O.blinded )))
O.show_message(text("\red [] has grabbed [] passively!", M, src), 1)
if("hurt", "disarm")
if("harm", "disarm")
var/damage = rand(15, 30)
visible_message("\red <B>[M] has slashed at [src]!</B>")
adjustBruteLoss(damage)
@@ -344,7 +353,7 @@
if(M.Victim) return // can't attack while eating!
visible_message("\red <B>The [M.name] glomps [src]!</B>")
visible_message("\red <B>[M.name] glomps [src]!</B>")
var/damage = rand(1, 3)
@@ -366,22 +375,32 @@
var/obj/item/stack/medical/MED = O
if(health < maxHealth)
if(MED.amount >= 1)
adjustBruteLoss(-MED.heal_brute)
MED.amount -= 1
if(MED.amount <= 0)
del(MED)
for(var/mob/M in viewers(src, null))
if ((M.client && !( M.blinded )))
M.show_message("\blue [user] applies the [MED] on [src]")
if(MED.heal_brute >= 1)
adjustBruteLoss(-MED.heal_brute)
MED.amount -= 1
if(MED.amount <= 0)
del(MED)
for(var/mob/M in viewers(src, null))
if ((M.client && !( M.blinded )))
M.show_message("\blue [user] applies [MED] on [src]")
return
else
user << "\blue [MED] won't help at all."
return
else
user << "\blue [src] is at full health."
return
else
user << "\blue this [src] is dead, medical items won't bring it back to life."
if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead.
user << "\blue [src] is dead, medical items won't bring it back to life."
return
else if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead.
if(istype(O, /obj/item/weapon/kitchenknife) || istype(O, /obj/item/weapon/butch))
new meat_type (get_turf(src))
if(prob(95))
del(src)
return
gib()
return
else
if(O.force)
var/damage = O.force
@@ -390,12 +409,12 @@
adjustBruteLoss(damage)
for(var/mob/M in viewers(src, null))
if ((M.client && !( M.blinded )))
M.show_message("\red \b [src] has been attacked with the [O] by [user]. ")
M.show_message("\red \b "+"[src] has been attacked with [O] by [user]. ")
else
usr << "\red This weapon is ineffective, it does no damage."
for(var/mob/M in viewers(src, null))
if ((M.client && !( M.blinded )))
M.show_message("\red [user] gently taps [src] with the [O]. ")
M.show_message("\red [user] gently taps [src] with [O]. ")
@@ -438,26 +457,16 @@
/mob/living/simple_animal/adjustBruteLoss(damage)
health = Clamp(health - damage, 0, maxHealth)
if(health < 1)
Die()
/mob/living/simple_animal/proc/SA_attackable(target_mob)
if (isliving(target_mob))
var/mob/living/L = target_mob
if(!L.stat && L.health >= 0)
return (0)
if (istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
/mob/living/simple_animal/proc/SA_attackable(target)
if (isliving(target))
var/mob/living/L = target
if(!L.stat)
return 0
if (istype(target,/obj/mecha))
var/obj/mecha/M = target
if (M.occupant)
return (0)
if (istype(target_mob,/obj/machinery/bot))
var/obj/machinery/bot/B = target_mob
if(B.health > 0)
return (0)
return (1)
//Call when target overlay should be added/removed
/mob/living/simple_animal/update_targeted()
if(!targeted_by && target_locked)
del(target_locked)
overlays = null
if (targeted_by && target_locked)
overlays += target_locked
return 0
return 1

View File

@@ -156,7 +156,7 @@
var/say_message = null // When you are understood by others. Currently only used by aliens and monkeys in their say_quote procs
var/faction = "neutral" //Used for checking whether hostile simple animals will attack you, possibly more stuff later
var/move_on_shuttle = 1 // Can move on the shuttle.
//Generic list for proc holders. Only way I can see to enable certain verbs/procs. Should be modified if needed.
var/proc_holder_list[] = list()//Right now unused.

View File

@@ -226,12 +226,14 @@
if(mob.control_object) Move_object(direct)
if(isobserver(mob)) return mob.Move(n,direct)
if(world.time < move_delay) return
if(isAI(mob)) return AIMove(n,direct,mob)
if(!isliving(mob)) return mob.Move(n,direct)
if(moving) return 0
if(world.time < move_delay) return
if(!mob) return
if(locate(/obj/effect/stop/, mob.loc))
@@ -241,8 +243,6 @@
if(mob.stat==2) return
if(isAI(mob)) return AIMove(n,direct,mob)
if(mob.monkeyizing) return//This is sota the goto stop mobs from moving var
if(isliving(mob))

View File

@@ -147,8 +147,7 @@
return
/obj/item/weapon/cell/blob_act()
if(prob(75))
explode()
ex_act(1)
/obj/item/weapon/cell/proc/get_electrocute_damage()
switch (charge)

View File

@@ -78,11 +78,6 @@ proc/move_research_shuttle()
usr.machine = src
src.add_fingerprint(usr)
if(href_list["move"])
if(ticker.mode.name == "blob")
if(ticker.mode:declared)
usr << "Under directive 7-10, [station_name()] is quarantined until further notice."
return
if (!research_shuttle_moving)
usr << "\blue Shuttle recieved message and will be sent shortly."
move_research_shuttle()

View File

@@ -79,7 +79,7 @@ PROBABILITY EXTENDED 0
PROBABILITY TRAITOR 2
PROBABILITY METEOR 0
PROBABILITY MALFUNCTION 2
PROBABILITY BLOB 0
PROBABILITY BLOB 2
PROBABILITY NUCLEAR 0
PROBABILITY SANDBOX 0
PROBABILITY WIZARD 0

View File

@@ -75,6 +75,14 @@
should be listed in the changelog upon commit though. Thanks. -->
<!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here -->
<div class="commit sansserif">
<h2 class="date">2013-08-25</h2>
<h3 class="author">Giacom updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Ported /tg/'s new blob mode for you guys, enjoy! If you don't know what it is, new blob is basically player controlled blobs with RTS elements like producing cannon fodder units, resource gathering and expanding.</li>
</ul>
</div>
<div class="commit sansserif">
<h2 class="date">2013.08.22</h2>
<h3 class="author">N3X15 updated:</h3>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 229 KiB