diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 2a8d20fb2d3..846c35b171b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -483,11 +483,11 @@ Turf and target are seperate in case you want to teleport some distance from a t if(!ckey) include_link = 0 - + if(key) if(include_link) . += "" - + if(C && C.holder && C.holder.fakekey && !include_name) . += "Administrator" else @@ -865,7 +865,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 @@ -1025,8 +1026,8 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0) 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 mobs += M for(var/mob/M in mobs) diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 7cca20dfac0..46bdb150325 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -9,124 +9,143 @@ 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 = 0 + required_enemies = 0 + + 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 - - //Controls expansion via game controller - var/autoexpand = 0 - var/expanding = 0 + var/players_per_core = 26 var/blob_count = 0 var/blobnukecount = 300//Might be a bit low - var/blobwincount = 700//Still needs testing + var/blobwincount = 600//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) + + blobnukecount = initial(blobnukecount) * cores_to_spawn + blobwincount = initial(blobwincount) * cores_to_spawn - announce() - world << "The current game mode is - Blob!" - world << "A dangerous alien organism is rapidly spreading throughout the station!" - 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 << "The current game mode is - Blob!" + world << "A dangerous alien organism is rapidly spreading throughout the station!" + 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 << "\red You are infected by the Blob!" + blob.current << "Your body is ready to give spawn to a new blob core which will eat this station." + blob.current << "Find a good location to spawn the core and then take control and overwhelm the station!" + blob.current << "When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process." + blob.current << "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." + return + +/datum/game_mode/blob/post_setup() + + for(var/datum/mind/blob in infected_crew) + greet_blob(blob) + + if(emergency_shuttle) + emergency_shuttle.always_fake_recall = 1 + + spawn(10) + start_state = new /datum/station_state() + start_state.count() + + spawn(0) + + sleep(rand(waittime_l, waittime_h)) + + send_intercept(0) - proc/expandBlob()//Currently disabled - if(expanding) return - if(!blobs.len) return - expanding = 1 + sleep(rand(waittime_l, waittime_h)) - 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() + for(var/datum/mind/blob in infected_crew) + blob.current << "You feel like you are about to burst." - expanding = 0 - return + sleep(rand(waittime_l, waittime_h)) + + 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/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]" + if(blob_client && location) + new /obj/effect/blob/core(location, 200, blob_client) - stage = -1 - // next stage 1 minute later - spawn(600) - stage = 1 - return + // Stage 0 + sleep(40) + stage(0) - 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 + // Stage 1 + sleep(4000) + stage(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 + ..() + +/datum/game_mode/blob/proc/stage(var/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]" + 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 diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm index 8cdc9ffd1ff..868cd62a5f6 100644 --- a/code/game/gamemodes/blob/blob_finish.dm +++ b/code/game/gamemodes/blob/blob_finish.dm @@ -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 << "The blob has taken over the station!" world << "The entire station was eaten by the Blob" @@ -32,7 +22,7 @@ world << "Partial Win: The station has been destroyed!" world << "Directive 7-12 has been successfully carried out preventing the Blob from spreading." - else + else if(!blob_cores.len) feedback_set_details("round_end_result","win - blob eliminated") world << "The staff has won!" world << "The alien organism has been eradicated from the station" @@ -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 = "The blob[(blob_mode.infected_crew.len > 1 ? "s were" : " was")]:" + + for(var/datum/mind/blob in blob_mode.infected_crew) + text += "
[blob.key] was [blob.name]" + world << text + return 1 /datum/game_mode/blob/proc/check_quarantine() var/numDead = 0 diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index 731ac0ea396..6e35a9b2661 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -4,6 +4,9 @@ var/intercepttext = "" var/interceptname = "Error" switch(report) + if(0) + ..() + return if(1) interceptname = "Biohazard Alert" intercepttext += "NanoTrasen Update: Biohazard Alert.
" diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index f0a24001ba3..2d2c8a41e6e 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -5,69 +5,93 @@ 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 - - New(loc, var/h = 200) - blobs += src + New(loc, var/h = 200, var/client/new_overmind = null) blob_cores += src processing_objects.Add(src) + if(!overmind) + create_overmind(new_overmind) ..(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(2) + 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(10)) + 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 -*/ \ No newline at end of file + + 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 + + B << "You are the overmind!" + B << "You are the overmind and can control the blob by placing new blob pieces such as..." + B << "Normal Blob will expand your reach and allow you to upgrade into special blobs that perform certain functions." + B << "Shield Blob 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." + B << "Resource Blob 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." + B << "Node Blob 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." + B << "Factory Blob 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." + + return 1 + return 0 + diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm index d25a4e4383f..6ba4bd026cb 100644 --- a/code/game/gamemodes/blob/blobs/factory.dm +++ b/code/game/gamemodes/blob/blobs/factory.dm @@ -1,24 +1,28 @@ /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 @@ -30,10 +34,10 @@ icon_state = "blobpod" icon_living = "blobpod" pass_flags = PASSBLOB - health = 20 - maxHealth = 20 - melee_damage_lower = 4 - melee_damage_upper = 8 + health = 15 + maxHealth = 15 + 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 +53,17 @@ minbodytemp = 0 maxbodytemp = 360 + fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + ..() + adjustBruteLoss(Clamp(0.01 * exposed_temperature, 1, 5)) New(loc, var/obj/effect/blob/factory/linked_node) - ..() if(istype(linked_node)) factory = linked_node factory.spores += src - ..(loc) - return - Die() ..() + + Die() if(factory) factory.spores -= src ..() - del(src) - diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm index c9ffaf96f13..2e22668d4b6 100644 --- a/code/game/gamemodes/blob/blobs/node.dm +++ b/code/game/gamemodes/blob/blobs/node.dm @@ -8,11 +8,12 @@ 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 +21,17 @@ ..() return + Life() + for(var/i = 1; i < 8; i += i) + Pulse(5, i) 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 \ No newline at end of file diff --git a/code/game/gamemodes/blob/blobs/resource.dm b/code/game/gamemodes/blob/blobs/resource.dm new file mode 100644 index 00000000000..a0f5722282d --- /dev/null +++ b/code/game/gamemodes/blob/blobs/resource.dm @@ -0,0 +1,27 @@ +/obj/effect/blob/resource + name = "resource blob" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_resource" + health = 30 + brute_resist = 1 + 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 + 10 // 1 second + + if(overmind) + overmind.add_points(1) + return 1 + diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm index 4c77520846a..3eb6f03e126 100644 --- a/code/game/gamemodes/blob/blobs/shield.dm +++ b/code/game/gamemodes/blob/blobs/shield.dm @@ -14,10 +14,12 @@ 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 diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm new file mode 100644 index 00000000000..dcfc59e1e72 --- /dev/null +++ b/code/game/gamemodes/blob/overmind.dm @@ -0,0 +1,48 @@ +/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_LEVEL_TWO + 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/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 diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm new file mode 100644 index 00000000000..b0b86cfacee --- /dev/null +++ b/code/game/gamemodes/blob/powers.dm @@ -0,0 +1,231 @@ +// Point controlling procs + +/mob/camera/blob/proc/can_buy(var/cost = 15) + if(blob_points < cost) + src << "You cannot afford this." + 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 = "Return 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 your core." + + 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(3)) + src << "There is a resource blob nearby, move more than 3 tiles away from it!" + return + + if(!can_buy(40)) + return + + + B.change_to(/obj/effect/blob/resource) + var/obj/effect/blob/resource/R = locate(/obj/effect/blob/resource) + 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(4)) + src << "There is another node nearby, move more than 4 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(6)) + src << "There is a factory blob nearby, move more than 6 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 (0)" + 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 \ No newline at end of file diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index ff935981cac..d52ba53d6d7 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -2,30 +2,20 @@ /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) return @@ -44,22 +34,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 +79,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)) return if(!T) var/list/dirs = list(1,2,4,8) for(var/i = 1 to 4) @@ -105,12 +92,15 @@ 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 @@ -131,19 +121,6 @@ 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) ..() switch(Proj.damage_type) @@ -172,50 +149,29 @@ 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 + 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" - 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() - ..() - - + if(health <= 15) + icon_state = "blob_damaged" + return \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 7e7c81c8798..de9c5745d86 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -655,4 +655,4 @@ var/list/datum/dna/hivemind_bank = list() changeling.absorbed_dna |= T.dna feedback_add_details("changeling_powers","ED") - return 1 + return 1 diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 0a789b2cf21..f0ef6f1907b 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -91,6 +91,7 @@ return /obj/machinery/camera/blob_act() + del(src) return /obj/machinery/camera/proc/setViewRange(var/num = 7) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 6f3190f9ee1..ff0e2a25da4 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -456,10 +456,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) @@ -472,7 +468,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 centcom diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 259b64cb277..0bd187a53f6 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -609,6 +609,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 diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 888c2e126f2..3b1f70d7199 100644 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -34,10 +34,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) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 9429c1b5e23..1a3a13a5ed0 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -103,7 +103,6 @@ var/global/floorIsLava = 0 body += "
Make AI | " body += "Make Robot | " body += "Make Alien | " - body += "Make Blob Fragment | " body += "Make Slime " //Simple Animals @@ -467,7 +466,6 @@ var/global/floorIsLava = 0 Egalitarian Station Mode
Break all lights
Fix all lights
- Best Friend AI
The floor is lava! (DANGEROUS: extremely lame)
"} diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index b33ab909c70..54d78e0df39 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -231,9 +231,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") @@ -1046,18 +1043,6 @@ message_admins("\blue [key_name_admin(usr)] attempting to corgize [key_name_admin(H)]", 1) H.corgize() - else if(href_list["makeblob"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makeblob"]) - if(!istype(H)) - usr << "This can only be used on instances of type /mob/living/carbon/human" - return - - log_admin("[key_name(usr)] attempting to blobize [key_name(H)]") - message_admins("\blue [key_name_admin(usr)] attempting to blobize [key_name_admin(H)]", 1) - H.blobize() - else if(href_list["forcespeech"]) if(!check_rights(R_FUN)) return @@ -1915,19 +1900,6 @@ message_admins("[key_name_admin(usr)] fixed all lights", 1) for(var/obj/machinery/light/L in world) L.fix() - 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("floorlava") if(floorIsLava) usr << "The floor is lava already." diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm new file mode 100644 index 00000000000..054fb163a4f --- /dev/null +++ b/code/modules/mob/camera/camera.dm @@ -0,0 +1,14 @@ +// 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 + +/mob/camera/experience_pressure_difference() + return \ No newline at end of file diff --git a/code/modules/mob/living/blob/blob.dm b/code/modules/mob/living/blob/blob.dm deleted file mode 100644 index 52edf14bdba..00000000000 --- a/code/modules/mob/living/blob/blob.dm +++ /dev/null @@ -1,258 +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" - - - 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 << "You are now a blob fragment." - 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) - - - - diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 2d94a20f913..a838e80042d 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -33,7 +33,7 @@ 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) & ~(CHUNK_SIZE - 1) var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1) diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index 9bb9c9bd043..1d11b225226 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -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 @@ -105,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) @@ -119,7 +119,7 @@ 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 diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 776ef22d8ed..d692d5cba21 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -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 diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 576f88a534d..0a83d7aa5d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -64,7 +64,7 @@ stop_automated_movement = 1 stance_step++ if(stance_step >= 10) //rests for 10 ticks - if(target_mob && target_mob in ListTargets()) + 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 @@ -72,15 +72,15 @@ if(HOSTILE_STANCE_ALERT) stop_automated_movement = 1 var/found_mob = 0 - if(target_mob && target_mob in ListTargets()) - 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) @@ -105,14 +105,14 @@ 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) @@ -128,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/limb/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 diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 267a263742c..3da3cecb760 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -64,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)) @@ -82,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) @@ -107,7 +107,7 @@ 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 @@ -149,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) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 568c8c71d1c..f8262ce8832 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -1,7 +1,7 @@ /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 @@ -32,63 +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 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()) + 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())) + 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 /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() @@ -125,7 +130,8 @@ if(!stat) switch(stance) if(HOSTILE_STANCE_IDLE) - target_mob = FindTarget() + var/new_target = FindTarget() + GiveTarget(new_target) if(HOSTILE_STANCE_ATTACK) DestroySurroundings() @@ -135,8 +141,8 @@ 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 [src] fires at [target]!", 1) var/tturf = get_turf(target) @@ -159,7 +165,7 @@ new casingtype stance = HOSTILE_STANCE_IDLE - target_mob = null + target = null return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index dd9c173010e..d85986a0cfd 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -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) @@ -441,13 +446,13 @@ /mob/living/simple_animal/adjustBruteLoss(damage) health = Clamp(health - damage, 0, maxHealth) -/mob/living/simple_animal/proc/SA_attackable(target_mob) - if (isliving(target_mob)) - var/mob/living/L = 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_mob,/obj/mecha)) - var/obj/mecha/M = target_mob + return 0 + if (istype(target,/obj/mecha)) + var/obj/mecha/M = target if (M.occupant) - return (0) - return (1) \ No newline at end of file + return 0 + return 1 \ No newline at end of file diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index c63e10f6ac2..10bec1b2123 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -135,6 +135,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. //The last mob/living/carbon to push/drag/grab this mob (mostly used by slimes friend recognition) var/mob/living/carbon/LAssailant = null diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 273c8c2f049..7ed169f0088 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -211,16 +211,16 @@ return 0 //This is sota the goto stop mobs from moving var if(mob.control_object) return Move_object(direct) - if(isobserver(mob)) - return mob.Move(n,direct) - if(moving) - return 0 if(world.time < move_delay) return 0 - if(mob.stat == DEAD) - return 0 if(isAI(mob)) return AIMove(n,direct,mob) + if(!isliving(mob)) + return mob.Move(n,direct) + if(moving) + return 0 + if(mob.stat == DEAD) + return 0 if(isliving(mob)) var/mob/living/L = mob if(L.incorporeal_move) //Move though walls diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index a7004485f31..d5841d9fc30 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -389,27 +389,6 @@ . = new_corgi del(src) -/mob/living/carbon/human/proc/blobize() // Oh boy, this is for you Int - Summoner - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - for(var/t in organs) - del(t) - - var/mob/living/blob/new_blob = new /mob/living/blob (loc) - new_blob.a_intent = "harm" - new_blob.key = key - - new_blob << "You are now a Blob Fragment. You can now sacrifice yourself to spawn blobs!" - . = new_blob - del(src) - /mob/living/carbon/human/Animalize() var/list/mobtypes = typesof(/mob/living/simple_animal) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 0eabed3c341..055e62d9ca0 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -140,8 +140,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) diff --git a/config/game_options.txt b/config/game_options.txt index f21858ca48d..4a7cf3cbf3b 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -83,7 +83,7 @@ PROBABILITY CULT 2 PROBABILITY CHANGELING 2 PROBABILITY WIZARD 4 PROBABILITY MALFUNCTION 1 -PROBABILITY BLOB 0 +PROBABILITY BLOB 2 PROBABILITY METEOR 0 PROBABILITY EXTENDED 0 diff --git a/html/changelog.html b/html/changelog.html index cff50a0caa8..6ea1d1b4eee 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -51,7 +51,16 @@ should be listed in the changelog upon commit tho. Thanks. --> -
+ +
+

7 July 2013

+

Giacom updated:

+ +
+ +

27 June 2013

Ikarrus updated: