diff --git a/baystation12.dme b/baystation12.dme index e7a6e23203..75e3fabb6c 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -117,6 +117,7 @@ #include "code\controllers\Processes\sun.dm" #include "code\controllers\Processes\supply.dm" #include "code\controllers\Processes\ticker.dm" +#include "code\controllers\Processes\turf.dm" #include "code\controllers\Processes\vote.dm" #include "code\controllers\ProcessScheduler\core\_define.dm" #include "code\controllers\ProcessScheduler\core\_stubs.dm" @@ -268,12 +269,17 @@ #include "code\game\gamemodes\cult\cult.dm" #include "code\game\gamemodes\cult\cult_items.dm" #include "code\game\gamemodes\cult\cult_structures.dm" +#include "code\game\gamemodes\cult\hell_universe.dm" #include "code\game\gamemodes\cult\ritual.dm" #include "code\game\gamemodes\cult\runes.dm" #include "code\game\gamemodes\cult\talisman.dm" #include "code\game\gamemodes\cult\cultify\mob.dm" #include "code\game\gamemodes\cult\cultify\obj.dm" #include "code\game\gamemodes\cult\cultify\turf.dm" +#include "code\game\gamemodes\endgame\endgame.dm" +#include "code\game\gamemodes\endgame\supermatter_cascade\blob.dm" +#include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm" +#include "code\game\gamemodes\endgame\supermatter_cascade\universe.dm" #include "code\game\gamemodes\events\black_hole.dm" #include "code\game\gamemodes\events\clang.dm" #include "code\game\gamemodes\events\dust.dm" @@ -1252,6 +1258,7 @@ #include "code\modules\mob\living\simple_animal\friendly\spiderbot.dm" #include "code\modules\mob\living\simple_animal\friendly\tomato.dm" #include "code\modules\mob\living\simple_animal\hostile\alien.dm" +#include "code\modules\mob\living\simple_animal\hostile\bat.dm" #include "code\modules\mob\living\simple_animal\hostile\bear.dm" #include "code\modules\mob\living\simple_animal\hostile\carp.dm" #include "code\modules\mob\living\simple_animal\hostile\creature.dm" @@ -1369,6 +1376,7 @@ #include "code\modules\power\rust\virtual_particle_catcher.dm" #include "code\modules\power\sensors\powernet_sensor.dm" #include "code\modules\power\sensors\sensor_monitoring.dm" +#include "code\modules\power\singularity\act.dm" #include "code\modules\power\singularity\collector.dm" #include "code\modules\power\singularity\containment_field.dm" #include "code\modules\power\singularity\emitter.dm" diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 45618f2ffc..bc06c3d239 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -27,6 +27,11 @@ if(A.name == N) return A return 0 + +/proc/get_area_master(const/O) + var/area/A = get_area(O) + if (isarea(A)) + return A.master /proc/in_range(source, user) if(get_dist(source, user) <= 1) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 50c08172e1..7484d016b6 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -54,6 +54,12 @@ var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg) var/list/datum/visualnet/visual_nets = list() var/datum/visualnet/camera/cameranet = new() var/datum/visualnet/cult/cultnet = new() + +// Runes +var/global/list/rune_list = new() +var/global/list/escape_list = list() +var/global/list/endgame_exits = list() +var/global/list/endgame_safespawns = list() ////////////////////////// /////Initial Building///// ////////////////////////// diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 69f46a4c9a..900e89e7e7 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -48,6 +48,11 @@ #define ui_monkey_mask "5:14,1:5" //monkey #define ui_monkey_back "6:14,1:5" //monkey +#define ui_construct_health "15:00,7:15" //same height as humans, hugging the right border +#define ui_construct_purge "15:00,6:15" +#define ui_construct_fire "14:16,8:13" //above health, slightly to the left +#define ui_construct_pull "14:28,2:10" //above the zone_sel icon + //Lower right, persistant menu #define ui_dropbutton "11:22,1:5" #define ui_drop_throw "14:28,2:7" diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 01ead8282c..466a9e2875 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -249,7 +249,11 @@ datum/hud/New(mob/owner) robot_hud() else if(isobserver(mymob)) ghost_hud() + else + mymob.instantiate_hud(src) +/mob/proc/instantiate_hud(var/datum/hud/HUD) + return //Triggered when F12 is pressed (Unless someone changed something in the DMF) /mob/verb/button_pressed_F12(var/full = 0 as null) diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index 3f785d8a83..5dd1b542cf 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -101,3 +101,59 @@ mymob.client.screen += src.adding return + +/mob/living/simple_animal/construct/instantiate_hud(var/datum/hud/HUD) + HUD.construct_hud() + +/datum/hud/proc/construct_hud() + var/constructtype + + if(istype(mymob,/mob/living/simple_animal/construct/armoured) || istype(mymob,/mob/living/simple_animal/construct/behemoth)) + constructtype = "juggernaut" + else if(istype(mymob,/mob/living/simple_animal/construct/builder)) + constructtype = "artificer" + else if(istype(mymob,/mob/living/simple_animal/construct/wraith)) + constructtype = "wraith" + else if(istype(mymob,/mob/living/simple_animal/construct/harvester)) + constructtype = "harvester" + + mymob.flash = new /obj/screen() + mymob.flash.icon = 'icons/mob/screen1.dmi' + mymob.flash.icon_state = "blank" + mymob.flash.name = "flash" + mymob.flash.screen_loc = "1,1 to 15,15" + mymob.flash.layer = 17 + + if(constructtype) + mymob.fire = new /obj/screen() + mymob.fire.icon = 'icons/mob/screen1_construct.dmi' + mymob.fire.icon_state = "fire0" + mymob.fire.name = "fire" + mymob.fire.screen_loc = ui_construct_fire + + mymob.healths = new /obj/screen() + mymob.healths.icon = 'icons/mob/screen1_construct.dmi' + mymob.healths.icon_state = "[constructtype]_health0" + mymob.healths.name = "health" + mymob.healths.screen_loc = ui_construct_health + + mymob.pullin = new /obj/screen() + mymob.pullin.icon = 'icons/mob/screen1_construct.dmi' + mymob.pullin.icon_state = "pull0" + mymob.pullin.name = "pull" + mymob.pullin.screen_loc = ui_construct_pull + + mymob.zone_sel = new /obj/screen/zone_sel() + mymob.zone_sel.icon = 'icons/mob/screen1_construct.dmi' + mymob.zone_sel.overlays.len = 0 + mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + + mymob.purged = new /obj/screen() + mymob.purged.icon = 'icons/mob/screen1_construct.dmi' + mymob.purged.icon_state = "purge0" + mymob.purged.name = "purged" + mymob.purged.screen_loc = ui_construct_purge + + mymob.client.screen = null + + mymob.client.screen += list(mymob.fire, mymob.healths, mymob.pullin, mymob.zone_sel, mymob.purged, mymob.flash) diff --git a/code/controllers/Processes/turf.dm b/code/controllers/Processes/turf.dm new file mode 100644 index 0000000000..c1efac52f9 --- /dev/null +++ b/code/controllers/Processes/turf.dm @@ -0,0 +1,9 @@ +var/global/list/processing_turfs = list() + +/datum/controller/process/turf/setup() + name = "turf" + schedule_interval = 20 // every 2 seconds + +/datum/controller/process/turf/doWork() + for(var/turf/unsimulated/wall/supermatter/SM in processing_turfs) + SM.process() diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm index efa2a226b1..6eeecef90d 100644 --- a/code/controllers/_DynamicAreaLighting_TG.dm +++ b/code/controllers/_DynamicAreaLighting_TG.dm @@ -323,6 +323,7 @@ turf/proc/shift_to_subarea() A.SetLightLevel(level, color_light) A.contents += src // move the turf into the area + universe.OnTurfTick(src) // Dedicated lighting sublevel for space turfs // helps us depower things in space, remove space fire alarms, diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm index 33dfc36f7f..4f55d3e406 100644 --- a/code/controllers/emergency_shuttle_controller.dm +++ b/code/controllers/emergency_shuttle_controller.dm @@ -114,6 +114,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle priority_announcement.Announce("The scheduled crew transfer has been cancelled.") /datum/emergency_shuttle_controller/proc/can_call() + if (!universe.OnShuttleCall(null)) + return 0 if (deny_shuttle) return 0 if (shuttle.moving_status != SHUTTLE_IDLE || !shuttle.location) //must be idle at centcom diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index 8fd4f3cd80..3f5d65d21d 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -24,6 +24,7 @@ var/datum/antagonist/cultist/cult flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE max_antags = 200 // No upper limit. max_antags_round = 200 + var/allow_narsie = 1 var/datum/mind/sacrifice_target var/list/startwords = list("blood","join","self","hell") diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index e59ad21e84..cbd3f221a3 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -2025,6 +2025,7 @@ area/space/atmosalert() luminosity = 1 lighting_use_dynamic = 0 requires_power = 0 + ambience = list() var/sound/mysound = null New() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 960a75d4fb..5944587cc7 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -229,6 +229,9 @@ its easier to just keep the beam vertical. /atom/proc/fire_act() return + +/atom/proc/melt() + return /atom/proc/hitby(atom/movable/AM as mob|obj) if (density) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 517c8728ed..185dc99ebd 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -92,6 +92,7 @@ density = 1 unacidable = 1 anchored = 1.0 + var/spawnable = null /obj/effect/gateway/Bumped(mob/M as mob|obj) spawn(0) @@ -102,3 +103,73 @@ spawn(0) return return + +/obj/effect/gateway/active + luminosity=5 + l_color="#ff0000" + spawnable=list( + /mob/living/simple_animal/hostile/scarybat, + /mob/living/simple_animal/hostile/creature, + /mob/living/simple_animal/hostile/faithless + ) + +/obj/effect/gateway/active/cult + luminosity=5 + l_color="#ff0000" + spawnable=list( + /mob/living/simple_animal/hostile/scarybat/cult, + /mob/living/simple_animal/hostile/creature/cult, + /mob/living/simple_animal/hostile/faithless/cult + ) + +/obj/effect/gateway/active/cult/cultify() + return + +/obj/effect/gateway/active/New() + spawn(rand(30,60) SECONDS) + var/t = pick(spawnable) + new t(src.loc) + qdel(src) + +/obj/effect/gateway/active/Crossed(var/atom/A) + if(!istype(A, /mob/living)) + return + + var/mob/living/M = A + + if(M.stat != DEAD) + if(M.monkeyizing) + return + if(M.has_brain_worms()) + return //Borer stuff - RR + + if(iscultist(M)) return + if(!ishuman(M) && !isrobot(M)) return + + M.monkeyizing = 1 + M.canmove = 0 + M.icon = null + M.overlays.len = 0 + M.invisibility = 101 + + if(istype(M, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/Robot = M + if(Robot.mmi) + del(Robot.mmi) + else + for(var/obj/item/W in M) + if(istype(W, /obj/item/weapon/implant)) + qdel(W) + continue + W.layer = initial(W.layer) + W.loc = M.loc + W.dropped(M) + + var/mob/living/new_mob = new /mob/living/simple_animal/corgi(A.loc) + new_mob.a_intent = I_HURT + if(M.mind) + M.mind.transfer_to(new_mob) + else + new_mob.key = M.key + + new_mob << "Your form morphs into that of a corgi." //Because we don't have cluwnes diff --git a/code/game/gamemodes/cult/cultify/mob.dm b/code/game/gamemodes/cult/cultify/mob.dm index 15233dc43b..a7d275b177 100644 --- a/code/game/gamemodes/cult/cultify/mob.dm +++ b/code/game/gamemodes/cult/cultify/mob.dm @@ -1,3 +1,8 @@ +/mob + //thou shall always be able to see the Geometer of Blood + var/image/narsimage = null + var/image/narglow = null + /mob/proc/cultify() return @@ -26,3 +31,33 @@ cult.harvested += G.mind else dust() + +/mob/proc/see_narsie(var/obj/machinery/singularity/narsie/large/N, var/dir) + if(N.chained) + if(narsimage) + del(narsimage) + del(narglow) + return + if((N.z == src.z)&&(get_dist(N,src) <= (N.consume_range+10)) && !(N in view(src))) + if(!narsimage) //Create narsimage + narsimage = image('icons/obj/narsie.dmi',src.loc,"narsie",9,1) + narsimage.mouse_opacity = 0 + if(!narglow) //Create narglow + narglow = image('icons/obj/narsie.dmi',narsimage.loc,"glow-narsie",LIGHTING_LAYER+2,1) + narglow.mouse_opacity = 0 + //Else if no dir is given, simply send them the image of narsie + var/new_x = 32 * (N.x - src.x) + N.pixel_x + var/new_y = 32 * (N.y - src.y) + N.pixel_y + narsimage.pixel_x = new_x + narsimage.pixel_y = new_y + narglow.pixel_x = new_x + narglow.pixel_y = new_y + narsimage.loc = src.loc + narglow.loc = src.loc + //Display the new narsimage to the player + src << narsimage + src << narglow + else + if(narsimage) + del(narsimage) + del(narglow) diff --git a/code/game/gamemodes/cult/cultify/obj.dm b/code/game/gamemodes/cult/cultify/obj.dm index 188f5cb5b0..bc0a723869 100644 --- a/code/game/gamemodes/cult/cultify/obj.dm +++ b/code/game/gamemodes/cult/cultify/obj.dm @@ -52,12 +52,10 @@ new I(loc) ..() -/obj/machinery/power/apc/cultify() - return - /obj/machinery/atmospherics/cultify() if(src.invisibility != INVISIBILITY_MAXIMUM) src.invisibility = INVISIBILITY_MAXIMUM + density = 0 /obj/machinery/cooking/cultify() new /obj/structure/cult/talisman(loc) @@ -84,10 +82,20 @@ del(c_animation) qdel(src) +/obj/machinery/door/firedoor/cultify() + qdel(src) + /obj/machinery/light/cultify() new /obj/structure/cult/pylon(loc) qdel(src) +/obj/machinery/mech_sensor/cultify() + qdel(src) + +/obj/machinery/power/apc/cultify() + if(src.invisibility != INVISIBILITY_MAXIMUM) + src.invisibility = INVISIBILITY_MAXIMUM + /obj/machinery/vending/cultify() new /obj/structure/cult/forge(loc) qdel(src) diff --git a/code/game/gamemodes/cult/hell_universe.dm b/code/game/gamemodes/cult/hell_universe.dm new file mode 100644 index 0000000000..2a2499bb45 --- /dev/null +++ b/code/game/gamemodes/cult/hell_universe.dm @@ -0,0 +1,101 @@ +/* + +In short: + * Random area alarms + * All areas jammed + * Random gateways spawning hellmonsters (and turn people into cluwnes if ran into) + * Broken APCs/Fire Alarms + * Scary music + * Random tiles changing to culty tiles. + +*/ +/datum/universal_state/hell + name = "Hell Rising" + desc = "OH FUCK OH FUCK OH FUCK" + + decay_rate = 5 // 5% chance of a turf decaying on lighting update/airflow (there's no actual tick for turfs) + +/datum/universal_state/hell/OnShuttleCall(var/mob/user) + return 1 + /* + if(user) + user << "All you hear on the frequency is static and panicked screaming. There will be no shuttle call today." + return 0 + */ + +/datum/universal_state/hell/DecayTurf(var/turf/T) + if(!T.holy) + T.cultify() + for(var/obj/machinery/light/L in T.contents) + new /obj/structure/cult/pylon(L.loc) + qdel(L) + return + + +/datum/universal_state/hell/OnTurfChange(var/turf/T) + var/turf/space/spess = T + if(istype(spess)) + spess.overlays += "hell01" + +// Apply changes when entering state +/datum/universal_state/hell/OnEnter() + set background = 1 + escape_list = get_area_turfs(locate(/area/hallway/secondary/exit)) + + //Separated into separate procs for profiling + AreaSet() + OverlaySet() + MiscSet() + APCSet() + KillMobs() + AmbientSet() + + runedec += 9000 //basically removing the rune cap + +/datum/universal_state/hell/proc/AreaSet() + for(var/area/ca in world) + var/area/A = ca.master + if(!istype(A,/area) || A.name=="Space") + continue + + // Reset all alarms. + A.fire = null + A.atmos = 1 + A.atmosalm = 0 + A.poweralm = 1 + A.party = null + + A.updateicon() + +/datum/universal_state/hell/proc/OverlaySet() + var/image/I = image("icon" = 'icons/turf/space.dmi', "icon_state" = "hell01", "layer" = 10) + for(var/turf/space/spess in world) + spess.overlays += I + +/datum/universal_state/hell/proc/AmbientSet() + for(var/turf/T in world) + if(istype(T, /turf/space)) continue + T.update_lumcount(1, 255, 0, 0, 0) + +/datum/universal_state/hell/proc/MiscSet() + for(var/turf/simulated/floor/T in world) + if(!T.holy && prob(1)) + new /obj/effect/gateway/active/cult(T) + + for (var/obj/machinery/firealarm/alm in machines) + if (!(alm.stat & BROKEN)) + alm.ex_act(2) + +/datum/universal_state/hell/proc/APCSet() + for (var/obj/machinery/power/apc/APC in machines) + if (!(APC.stat & BROKEN) && !istype(APC.area,/area/turret_protected/ai)) + APC.chargemode = 0 + if(APC.cell) + APC.cell.charge = 0 + APC.emagged = 1 + APC.queue_icon_update() + +/datum/universal_state/hell/proc/KillMobs() + for(var/mob/living/simple_animal/M in mob_list) + if(M && !M.client) + M.stat = DEAD diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 7024f025d3..9f99945837 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -33,6 +33,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," var/word1 var/word2 var/word3 + var/image/blood_image var/list/converting = list() // Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere. @@ -66,10 +67,21 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," // join hide technology - stun rune. Rune color: bright pink. New() ..() - var/image/blood = image(loc = src) - blood.override = 1 + blood_image = image(loc = src) + blood_image.override = 1 for(var/mob/living/silicon/ai/AI in player_list) - AI.client.images += blood + if(AI.client) + AI.client.images += blood_image + rune_list.Add(src) + + Del() + for(var/mob/living/silicon/ai/AI in player_list) + if(AI.client) + AI.client.images -= blood_image + qdel(blood_image) + blood_image = null + rune_list.Remove(src) + ..() examine(mob/user) ..() diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 46bca99bc6..6f64faca59 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -180,6 +180,9 @@ var/list/sacrificed = list() /////////////////////////////////////////FOURTH RUNE tearreality() + if(!cult.allow_narsie) + return fizzle() + var/list/cultists = new() for(var/mob/M in range(1,src)) if(iscultist(M) && !M.stat) diff --git a/code/game/gamemodes/endgame/endgame.dm b/code/game/gamemodes/endgame/endgame.dm new file mode 100644 index 0000000000..ed1167dfe7 --- /dev/null +++ b/code/game/gamemodes/endgame/endgame.dm @@ -0,0 +1,68 @@ +/********************** + * ENDGAME STUFF + **********************/ + + // Universal State + // Handles stuff like space icon_state, constants, etc. + // Essentially a policy manager. Once shit hits the fan, this changes its policies. + // Called by master controller. + + // Default shit. +/datum/universal_state + // Just for reference, for now. + // Might eventually add an observatory job. + var/name = "Normal" + var/desc = "Nothing seems awry." + + // Sets world.turf, replaces all turfs of type /turf/space. + var/space_type = /turf/space + + // Replaces all turfs of type /turf/space/transit + var/transit_space_type = /turf/space/transit + + // Chance of a floor or wall getting damaged [0-100] + // Simulates stuff getting broken due to molecular bonds decaying. + var/decay_rate = 0 + +// Actually decay the turf. +/datum/universal_state/proc/DecayTurf(var/turf/T) + if(istype(T,/turf/simulated/wall)) + var/turf/simulated/wall/W=T + W.melt() + return + if(istype(T,/turf/simulated/floor)) + var/turf/simulated/floor/F=T + // Burnt? + if(!F.burnt) + F.burn_tile() + else + F.ReplaceWithLattice() + return + +// Return 0 to cause shuttle call to fail. +/datum/universal_state/proc/OnShuttleCall(var/mob/user) + return 1 + +// Processed per tick +/datum/universal_state/proc/OnTurfTick(var/turf/T) + if(decay_rate && prob(decay_rate)) + DecayTurf(T) + +// Apply changes when exiting state +/datum/universal_state/proc/OnExit() + // Does nothing by default + +// Apply changes when entering state +/datum/universal_state/proc/OnEnter() + // Does nothing by default + +// Apply changes to a new turf. +/datum/universal_state/proc/OnTurfChange(var/turf/NT) + return + +/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1) + if(on_exit) + universe.OnExit() + universe = new newstate + if(on_enter) + universe.OnEnter() diff --git a/code/game/gamemodes/endgame/supermatter_cascade/blob.dm b/code/game/gamemodes/endgame/supermatter_cascade/blob.dm new file mode 100644 index 0000000000..139045291f --- /dev/null +++ b/code/game/gamemodes/endgame/supermatter_cascade/blob.dm @@ -0,0 +1,117 @@ +// QUALITY COPYPASTA +/turf/unsimulated/wall/supermatter + name = "Bluespace" + desc = "THE END IS right now actually." + + icon = 'icons/turf/space.dmi' + icon_state = "bluespace" + + //luminosity = 5 + //l_color="#0066FF" + layer = LIGHTING_LAYER+1 + + var/spawned=0 // DIR mask + var/next_check=0 + var/list/avail_dirs = list(NORTH,SOUTH,EAST,WEST) + +/turf/unsimulated/wall/supermatter/New() + ..() + processing_turfs.Add(src) + next_check = world.time+5 SECONDS + +/turf/unsimulated/wall/supermatter/Destroy() + processing_turfs.Remove(src) + ..() + +/turf/unsimulated/wall/supermatter/proc/process() + // Only check infrequently. + if(next_check>world.time) return + + // No more available directions? Shut down process(). + if(avail_dirs.len==0) + processing_objects.Remove(src) + return 1 + + // We're checking, reset the timer. + next_check = world.time+5 SECONDS + + // Choose a direction. + var/pdir = pick(avail_dirs) + avail_dirs -= pdir + var/turf/T=get_step(src,pdir) + + // EXPAND + if(!istype(T,type)) + // Do pretty fadeout animation for 1s. + new /obj/effect/overlay/bluespacify(T) + spawn(10) + // Nom. + for(var/atom/movable/A in T) + if(A) + if(istype(A,/mob/living)) + del(A) + else if(istype(A,/mob)) // Observers, AI cameras. + continue + qdel(A) + T.ChangeTurf(type) + + if((spawned & (NORTH|SOUTH|EAST|WEST)) == (NORTH|SOUTH|EAST|WEST)) + processing_turfs -= src + return + +/turf/unsimulated/wall/supermatter/attack_generic(mob/user as mob) + return attack_hand(user) + +/turf/unsimulated/wall/supermatter/attack_robot(mob/user as mob) + if(Adjacent(user)) + return attack_hand(user) + else + user << "What the fuck are you doing?" + return + +// /vg/: Don't let ghosts fuck with this. +/turf/unsimulated/wall/supermatter/attack_ghost(mob/user as mob) + user.examinate(src) + +/turf/unsimulated/wall/supermatter/attack_ai(mob/user as mob) + return user.examinate(src) + +/turf/unsimulated/wall/supermatter/attack_hand(mob/user as mob) + user.visible_message("\The [user] reaches out and touches \the [src]... And then blinks out of existance.",\ + "You reach out and touch \the [src]. Everything immediately goes quiet. Your last thought is \"That was not a wise decision.\"",\ + "You hear an unearthly noise.") + + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) + + Consume(user) + +/turf/unsimulated/wall/supermatter/attackby(obj/item/weapon/W as obj, mob/living/user as mob) + user.visible_message("\The [user] touches \a [W] to \the [src] as a silence fills the room...",\ + "You touch \the [W] to \the [src] when everything suddenly goes silent.\"\n\The [W] flashes into dust as you flinch away from \the [src].",\ + "Everything suddenly goes silent.") + + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) + + user.drop_from_inventory(W) + Consume(W) + + +/turf/unsimulated/wall/supermatter/Bumped(atom/AM as mob|obj) + if(istype(AM, /mob/living)) + AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.",\ + "You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\ + "You hear an unearthly noise as a wave of heat washes over you.") + else + AM.visible_message("\The [AM] smacks into \the [src] and rapidly flashes to ash.",\ + "You hear a loud crack as you are washed with a wave of heat.") + + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) + + Consume(AM) + + +/turf/unsimulated/wall/supermatter/proc/Consume(var/mob/living/user) + if(istype(user,/mob/dead/observer)) + return + + del(user) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm new file mode 100644 index 0000000000..9d3f12b021 --- /dev/null +++ b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm @@ -0,0 +1,81 @@ +/*** EXIT PORTAL ***/ + +/obj/machinery/singularity/narsie/large/exit + name = "Bluespace Rift" + desc = "NO TIME TO EXPLAIN, JUMP IN" + icon = 'icons/obj/rift.dmi' + icon_state = "rift" + + move_self = 0 + announce=0 + narnar=0 + + layer=LIGHTING_LAYER+2 // ITS SO BRIGHT + + consume_range = 6 + +/obj/machinery/singularity/narsie/large/exit/New() + ..() + processing_objects.Add(src) + +/obj/machinery/singularity/narsie/large/exit/update_icon() + overlays = 0 + +/obj/machinery/singularity/narsie/large/exit/process() + for(var/mob/M in player_list) + if(M.client) + M.see_rift(src) + eat() + +/obj/machinery/singularity/narsie/large/exit/acquire(var/mob/food) + return + +/obj/machinery/singularity/narsie/large/exit/consume(const/atom/A) + if(!(A.singuloCanEat())) + return 0 + + if (istype(A, /mob/living/)) + do_teleport(A, pick(endgame_safespawns)) //dead-on precision + else if (isturf(A)) + var/turf/T = A + var/dist = get_dist(T, src) + if (dist <= consume_range && T.density) + T.density = 0 + + for (var/atom/movable/AM in T.contents) + if (AM == src) // This is the snowflake. + continue + + if (dist <= consume_range) + consume(AM) + continue + + if (dist > consume_range) + if (101 == AM.invisibility) + continue + + spawn (0) + AM.singularity_pull(src, src.current_size) + + +/mob + //thou shall always be able to see the rift + var/image/riftimage = null + +/mob/proc/see_rift(var/obj/machinery/singularity/narsie/large/exit/R) + if((R.z == src.z) && (get_dist(R,src) <= (R.consume_range+10)) && !(R in view(src))) + if(!riftimage) + riftimage = image('icons/obj/rift.dmi',src.loc,"rift",LIGHTING_LAYER+2,1) + riftimage.mouse_opacity = 0 + + var/new_x = 32 * (R.x - src.x) + R.pixel_x + var/new_y = 32 * (R.y - src.y) + R.pixel_y + riftimage.pixel_x = new_x + riftimage.pixel_y = new_y + riftimage.loc = src.loc + + src << riftimage + + else + if(riftimage) + del(riftimage) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm new file mode 100644 index 0000000000..1b5ceb87e8 --- /dev/null +++ b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm @@ -0,0 +1,140 @@ + +/datum/universal_state/supermatter_cascade + name = "Supermatter Cascade" + desc = "Unknown harmonance affecting universal substructure, converting nearby matter to supermatter." + + decay_rate = 5 // 5% chance of a turf decaying on lighting update/airflow (there's no actual tick for turfs) + +/datum/universal_state/supermatter_cascade/OnShuttleCall(var/mob/user) + if(user) + user << "All you hear on the frequency is static and panicked screaming. There will be no shuttle call today." + return 0 + +/datum/universal_state/supermatter_cascade/OnTurfChange(var/turf/T) + var/turf/space/spess = T + if(istype(spess)) + spess.overlays += "end01" + +/datum/universal_state/supermatter_cascade/DecayTurf(var/turf/T) + if(istype(T,/turf/simulated/wall)) + var/turf/simulated/wall/W=T + W.melt() + return + if(istype(T,/turf/simulated/floor)) + var/turf/simulated/floor/F=T + // Burnt? + if(!F.burnt) + F.burn_tile() + else + if(!istype(F,/turf/simulated/floor/plating)) + F.break_tile_to_plating() + return + +// Apply changes when entering state +/datum/universal_state/supermatter_cascade/OnEnter() + set background = 1 + world << "You are blinded by a brilliant flash of energy." + + world << sound('sound/effects/cascade.ogg') + + for(var/mob/M in player_list) + flick("e_flash", M.flash) + + if(emergency_shuttle.can_recall()) + priority_announcement.Announce("The emergency shuttle has returned due to bluespace distortion.") + emergency_shuttle.recall() + + AreaSet() + OverlaySet() + MiscSet() + APCSet() + AmbientSet() + + // Disable Nar-Sie. + cult.allow_narsie = 0 + PlayerSet() + + new /obj/machinery/singularity/narsie/large/exit(pick(endgame_exits)) + spawn(rand(30,60) SECONDS) + var/txt = {" +There's been a galaxy-wide electromagnetic pulse. All of our systems are heavily damaged and many personnel are dead or dying. We are seeing increasing indications of the universe itself beginning to unravel. + +[station_name()], you are the only facility nearby a bluespace rift, which is near your research outpost. You are hereby directed to enter the rift using all means necessary, quite possibly as the last of your species alive. + +You have five minutes before the universe collapses. Good l\[\[###!!!- + +AUTOMATED ALERT: Link to [command_name()] lost."} + priority_announcement.Announce(txt,"SUPERMATTER CASCADE DETECTED") + sleep(5 MINUTES) + ticker.declare_completion() + ticker.station_explosion_cinematic(0,null) // TODO: Custom cinematic + + world << "Resetting in 30 seconds!" + + feedback_set_details("end_error","Universe ended") + + if(blackbox) + blackbox.save_all_data_to_sql() + + sleep(300) + log_game("Rebooting due to universal collapse") + world.Reboot() + return + +/datum/universal_state/supermatter_cascade/proc/AreaSet() + for(var/area/ca in world) + var/area/A=ca.master + if(A.z in config.admin_levels) + continue + if(!istype(A,/area) || istype(A,/area/space)) + continue + + // Reset all alarms. + A.fire = null + A.atmos = 1 + A.atmosalm = 0 + A.poweralm = 1 + + // Slap on random alerts + if(prob(25)) + switch(rand(1,4)) + if(1) + A.fire=1 + if(2) + A.atmosalm=1 + + A.updateicon() + +/datum/universal_state/supermatter_cascade/proc/OverlaySet() + for(var/turf/space/spess in world) + spess.overlays += "end01" + +/datum/universal_state/supermatter_cascade/proc/AmbientSet() + for(var/turf/T in world) + if(istype(T, /turf/space)) continue + if(!(T.z in config.admin_levels)) + T.update_lumcount(1, 160, 255, 0, 0) + +/datum/universal_state/supermatter_cascade/proc/MiscSet() + for (var/obj/machinery/firealarm/alm in world) + if (!(alm.stat & BROKEN)) + alm.ex_act(2) + +/datum/universal_state/supermatter_cascade/proc/APCSet() + for (var/obj/machinery/power/apc/APC in world) + if (!(APC.stat & BROKEN)) + APC.chargemode = 0 + if(APC.cell) + APC.cell.charge = 0 + APC.emagged = 1 + APC.queue_icon_update() + +/datum/universal_state/supermatter_cascade/proc/PlayerSet() + for(var/datum/mind/M in player_list) + if(!istype(M.current,/mob/living)) + continue + if(M.current.stat!=2) + M.current.Weaken(10) + flick("e_flash", M.current.flash) + + clear_antag_roles(M) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 96385b5dfc..4fc43a0259 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -428,6 +428,10 @@ if ((!( ticker ) || !emergency_shuttle.location())) return + if(!universe.OnShuttleCall(usr)) + user << "Cannot establish a bluespace connection." + return + if(deathsquad.deployed) user << "Centcom will not allow the shuttle to be called. Consider all contracts terminated." return diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index c275d8f728..d62f6c37b0 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -36,10 +36,10 @@ if(damage >= 10) if(src.density) visible_message("\The [user] forces \the [src] open!") - open() + open(1) else visible_message("\The [user] forces \the [src] closed!") - close() + close(1) else visible_message("\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].") return @@ -776,7 +776,7 @@ About the new airlock wires panel: user << "\blue The airlock's motors resist your efforts to force it." else if(locked) user << "\blue The airlock's bolts prevent it from being forced." - else if( !welded && !operating ) + else if(density) spawn(0) open(1) else @@ -825,11 +825,8 @@ About the new airlock wires panel: return /obj/machinery/door/airlock/open(var/forced=0) - if(!can_open()) + if(!can_open(forced)) return 0 - if(!forced) - if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) ) - return 0 use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people if(istype(src, /obj/machinery/door/airlock/glass)) playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1) @@ -839,7 +836,11 @@ About the new airlock wires panel: src.closeOther.close() return ..() -/obj/machinery/door/airlock/can_open() +/obj/machinery/door/airlock/can_open(var/forced=0) + if(!forced) + if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) + return 0 + if(locked || welded) return 0 return ..() diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 900b6b09f0..406ef8611e 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -388,9 +388,8 @@ return -/obj/machinery/door/proc/open() - if(!can_open()) return - if(!operating) operating = 1 +/obj/machinery/door/proc/open(var/forced = 0) + if(!can_open(forced)) return do_animate("opening") icon_state = "door0" @@ -414,8 +413,8 @@ /obj/machinery/door/proc/next_close_time() return world.time + (normalspeed ? 150 : 5) -/obj/machinery/door/proc/close() - if(!can_close()) +/obj/machinery/door/proc/close(var/forced = 0) + if(!can_close(forced)) return operating = 1 diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 28a4ad2cc2..da25e6f2cc 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -79,6 +79,14 @@ xeno_spawn += loc del(src) + if("endgame_exit") + endgame_safespawns += loc + del(src) + + if("bluespacerift") + endgame_exits += loc + del(src) + landmarks_list += src return 1 diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index a5715624bb..6dd26f7774 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -2,7 +2,7 @@ name = "overlay" unacidable = 1 var/i_attached//Added for possible image attachments to objects. For hallucinations and the like. - + /obj/effect/overlay/Destroy() PlaceInPool(src) return 1 //cancels the GCing @@ -35,4 +35,10 @@ /obj/effect/overlay/coconut name = "Coconuts" icon = 'icons/misc/beach.dmi' - icon_state = "coconuts" \ No newline at end of file + icon_state = "coconuts" + +/obj/effect/overlay/bluespacify + name = "Bluespace" + icon = 'icons/turf/space.dmi' + icon_state = "bluespacify" + layer = LIGHTING_LAYER diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 1e3f67fb07..dda21468a4 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -22,6 +22,11 @@ /obj/structure/grille/meteorhit(var/obj/M) del(src) +/obj/structure/grille/update_icon() + if(destroyed) + icon_state = "[initial(icon_state)]-b" + else + icon_state = initial(icon_state) /obj/structure/grille/Bumped(atom/user) if(ismob(user)) shock(user, 70) @@ -165,9 +170,9 @@ /obj/structure/grille/proc/healthcheck() if(health <= 0) if(!destroyed) - icon_state = "brokengrille" density = 0 destroyed = 1 + update_icon() new /obj/item/stack/rods(loc) else @@ -226,5 +231,3 @@ if(air_group) return 0 //Make sure air doesn't drain ..() - - diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 9546bf9ba1..dcecf46ad6 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -12,6 +12,8 @@ /turf/simulated/New() ..() + if(istype(loc, /area/chapel)) + holy = 1 levelupdate() /turf/simulated/proc/AddTracks(var/typepath,var/bloodDNA,var/comingdir,var/goingdir,var/bloodcolor="#A10808") diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 969b872caf..e19fadf863 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -106,6 +106,20 @@ //Damage +/turf/simulated/wall/melt() + if(mineral == "diamond") + return + + src.ChangeTurf(/turf/simulated/floor/plating) + + var/turf/simulated/floor/F = src + if(!F) + return + F.burn_tile() + F.icon_state = "wall_thermite" + visible_message("\The [src] spontaneously combusts!.") //!!OH SHIT!! + return + /turf/simulated/wall/proc/take_damage(dam) if(dam) damage = max(0, damage + dam) diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 884c5c5dbe..2fd89bb876 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -245,4 +245,7 @@ var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "5" = 10, "6" = spawn (0) if ((A && A.loc)) A.loc.Entered(A) - return \ No newline at end of file + return + +/turf/space/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0) + return ..(N, tell_universe, 1) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index c500b055c2..1bc058ef6d 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -29,6 +29,9 @@ // Flick animation var/atom/movable/overlay/c_animation = null + // holy water + var/holy = 0 + /turf/New() ..() for(var/atom/movable/AM as mob|obj in src) @@ -197,7 +200,7 @@ del L //Creates a new turf -/turf/proc/ChangeTurf(var/turf/N) +/turf/proc/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0) if (!N) return @@ -241,9 +244,9 @@ //W.Assimilate_Air() W.lighting_lumcount += old_lumcount - - if(W.lighting_lumcount) - W.UpdateAffectingLights() + if((old_lumcount != W.lighting_lumcount) || (loc.name != "Space" && force_lighting_update)) + W.lighting_changed = 1 + lighting_controller.changed_turfs += W if(old_fire) fire = old_fire @@ -251,6 +254,9 @@ if (istype(W,/turf/simulated/floor)) W.RemoveLattice() + if(tell_universe) + universe.OnTurfChange(W) + if(air_master) air_master.mark_for_update(src) @@ -268,13 +274,16 @@ var/turf/W = new N( locate(src.x, src.y, src.z) ) W.lighting_lumcount += old_lumcount - if(old_lumcount != W.lighting_lumcount) + if((old_lumcount != W.lighting_lumcount) || (loc.name != "Space" && force_lighting_update)) W.lighting_changed = 1 lighting_controller.changed_turfs += W if(old_fire) old_fire.RemoveFire() + if(tell_universe) + universe.OnTurfChange(W) + if(air_master) air_master.mark_for_update(src) diff --git a/code/global.dm b/code/global.dm index c7a1738127..0cc3d3f51c 100644 --- a/code/global.dm +++ b/code/global.dm @@ -30,6 +30,8 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called // 3: AI satellite. // 5: Empty space. +var/global/datum/universal_state/universe = new + var/global/list/global_map = null //var/global/list/global_map = list(list(1,5),list(4,3)) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 96b7a7c244..46fd659d81 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -670,6 +670,16 @@ var/global/floorIsLava = 0 if(check_rights(R_SERVER,0)) dat += "Toggle bomb cap
" + if(check_rights(R_SERVER|R_FUN,0)) + dat += {" +
+ Final Solutions
+ (Warning, these will end the round!)
+
+ Summon Nar-Sie
+ Start a Supermatter Cascade
+ "} + dat += "
" if(check_rights(R_DEBUG,0)) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 6fd38bb581..43ea750f7a 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2257,6 +2257,33 @@ feedback_add_details("admin_secrets_fun_used","OO") only_one() message_admins("[key_name_admin(usr)] has triggered a battle to the death (only one)") + + if("togglenarsie") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","NA") + var/choice = input("How do you wish for narsie to interact with her surroundings?") in list("CultStation13", "Nar-Singulo") + if(choice == "CultStation13") + message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"CultStation13\".") + narsie_behaviour = "CultStation13" + if(choice == "Nar-Singulo") + message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"Nar-Singulo\".") + narsie_behaviour = "Nar-Singulo" + if("hellonearth") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","NS") + var/choice = input("You sure you want to end the round and summon narsie at your location? Misuse of this could result in removal of flags or halarity.") in list("PRAISE SATAN", "Cancel") + if(choice == "PRAISE SATAN") + new /obj/machinery/singularity/narsie/large(get_turf(usr)) + message_admins("[key_name_admin(usr)] has summoned narsie and brought about a new realm of suffering.") + if("supermattercascade") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SC") + var/choice = input("You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or halarity.") in list("NO TIME TO EXPLAIN", "Cancel") + if(choice == "NO TIME TO EXPLAIN") + explosion(get_turf(usr), 8, 16, 24, 32, 1) + new /turf/unsimulated/wall/supermatter(get_turf(usr)) + SetUniversalState(/datum/universal_state/supermatter_cascade) + message_admins("[key_name_admin(usr)] has managed to destroy the universe with a supermatter cascade. Good job, [key_name_admin(usr)]") if(usr) log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]") if (ok) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 7b5f740135..850bd531df 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -29,6 +29,7 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images var/image/ghostimage = null //this mobs ghost image, for deleting and stuff var/ghostvision = 1 //is the ghost able to see things humans can't? var/seedarkness = 1 + incorporeal_move = 1 /mob/dead/observer/New(mob/body) sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF @@ -193,29 +194,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. announce_ghost_joinleave(ghost) - -/mob/dead/observer/Move(NewLoc, direct) - following = null - set_dir(direct) - if(NewLoc) - loc = NewLoc - for(var/obj/effect/step_trigger/S in NewLoc) - S.Crossed(src) - - return - loc = get_turf(src) //Get out of closets and such as a ghost - if((direct & NORTH) && y < world.maxy) - y++ - else if((direct & SOUTH) && y > 1) - y-- - if((direct & EAST) && x < world.maxx) - x++ - else if((direct & WEST) && x > 1) - x-- - - for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb - S.Crossed(src) - /mob/dead/observer/can_use_hands() return 0 /mob/dead/observer/is_active() return 0 @@ -316,11 +294,23 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!thearea) return var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - L+=T + var/holyblock = 0 + + if(usr.invisibility <= SEE_INVISIBLE_LIVING || (usr.mind in cult.current_antagonists)) + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.holy) + L+=T + else + holyblock = 1 + else + for(var/turf/T in get_area_turfs(thearea.type)) + L+=T if(!L || !L.len) - usr << "No area available." + if(holyblock) + usr << "This area has been entirely made into sacred grounds, you cannot enter it while you are in this plane of existence!" + else + usr << "No area available." usr.loc = pick(L) following = null @@ -336,7 +326,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp // This is the ghost's follow verb with an argument /mob/dead/observer/proc/ManualFollow(var/atom/movable/target) - if(target && target != src) + if(!target) + return + + var/turf/targetloc = get_turf(target) + if(check_holy(targetloc)) + usr << "You cannot follow a mob standing on holy grounds!" + return + if(target != src) if(following && following == target) return following = target @@ -351,6 +348,15 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp loc = T sleep(15) +/mob/proc/check_holy(var/turf/T) + return 0 + +/mob/dead/observer/check_holy(var/turf/T) + if(check_rights(R_ADMIN|R_FUN, 0, src)) + return 0 + + return (T && T.holy) && (invisibility <= SEE_INVISIBLE_LIVING || (mind in cult.current_antagonists)) + /mob/dead/observer/verb/jumptomob(target in getmobs()) //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" set name = "Jump to Mob" @@ -393,6 +399,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set hidden = 1 src << "\red You are dead! You have no mind to store memory!" +/mob/dead/observer/Post_Incorpmove() + following = null + /mob/dead/observer/verb/analyze_air() set name = "Analyze Air" set category = "Ghost" diff --git a/code/modules/mob/freelook/mask/update_triggers.dm b/code/modules/mob/freelook/mask/update_triggers.dm index a02aa864a6..d80527a2fa 100644 --- a/code/modules/mob/freelook/mask/update_triggers.dm +++ b/code/modules/mob/freelook/mask/update_triggers.dm @@ -34,7 +34,7 @@ // Arise! cultnet.updateVisibility(src, 0) -/mob/living/death() +/mob/living/death(gibbed, deathmessage="seizes up and falls limp...") if(..()) // If true, the mob went from living to dead (assuming everyone has been overriding as they should...) cultnet.updateVisibility(src) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 3771bc135e..8a01f86774 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -22,9 +22,6 @@ var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out. - //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. - var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. - var/t_phoron = null var/t_oxygen = null var/t_sl_gas = null diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index b5b6808bac..5336cd873f 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -1,9 +1,7 @@ /mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up ¬_¬ ~Carn ..() - for(var/obj/effect/rune/rune in world) - var/image/blood = image(loc = rune) - blood.override = 1 - client.images += blood + for(var/obj/effect/rune/rune in rune_list) + client.images += rune.blood_image regenerate_icons() flash = new /obj/screen() flash.icon_state = "blank" diff --git a/code/modules/mob/living/simple_animal/constructs/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm index 2aa5054dc7..43ebfd9a49 100644 --- a/code/modules/mob/living/simple_animal/constructs/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm @@ -5,8 +5,8 @@ speak_emote = list("hisses") emote_hear = list("wails","screeches") response_help = "thinks better of touching" - response_disarm = "flails at" - response_harm = "punches" + response_disarm = "flailed at" + response_harm = "punched" icon_dead = "shade_dead" speed = -1 a_intent = I_HURT @@ -14,7 +14,7 @@ status_flags = CANPUSH universal_speak = 0 universal_understand = 1 - attack_sound = 'sound/weapons/punch1.ogg' + attack_sound = 'sound/weapons/spiderlunge.ogg' min_oxy = 0 max_oxy = 0 min_tox = 0 @@ -24,7 +24,7 @@ min_n2 = 0 max_n2 = 0 minbodytemp = 0 - show_stat_health = 0 + show_stat_health = 1 faction = "cult" supernatural = 1 var/nullblock = 0 @@ -44,8 +44,9 @@ add_language("Cult") add_language("Occult") for(var/spell in construct_spells) - spell_list += new spell(src) + src.add_spell(new spell, "const_spell_ready") updateicon() + add_glow() /mob/living/simple_animal/construct/death() new /obj/item/weapon/ectoplasm (src.loc) @@ -99,7 +100,7 @@ mob_size = 20 speed = 3 environment_smash = 2 - attack_sound = 'sound/weapons/punch3.ogg' + attack_sound = 'sound/weapons/heavysmash.ogg' status_flags = 0 resistance = 10 construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) @@ -150,7 +151,7 @@ speed = -1 environment_smash = 1 see_in_dark = 7 - attack_sound = 'sound/weapons/bladeslice.ogg' + attack_sound = 'sound/weapons/rapidslice.ogg' construct_spells = list(/spell/targeted/ethereal_jaunt/shift) @@ -167,14 +168,14 @@ icon_living = "artificer" maxHealth = 50 health = 50 - response_harm = "viciously beats" + response_harm = "viciously beaten" harm_intent_damage = 5 melee_damage_lower = 5 melee_damage_upper = 5 attacktext = "rammed" speed = 0 - environment_smash = 2 - attack_sound = 'sound/weapons/punch2.ogg' + environment_smash = 1 + attack_sound = 'sound/weapons/rapidslice.ogg' construct_spells = list(/spell/aoe_turf/conjure/construct/lesser, /spell/aoe_turf/conjure/wall, /spell/aoe_turf/conjure/floor, @@ -196,14 +197,14 @@ maxHealth = 750 health = 750 speak_emote = list("rumbles") - response_harm = "harmlessly punches" + response_harm = "harmlessly punched" harm_intent_damage = 0 melee_damage_lower = 50 melee_damage_upper = 50 attacktext = "brutally crushed" speed = 5 environment_smash = 2 - attack_sound = 'sound/weapons/punch4.ogg' + attack_sound = 'sound/weapons/heavysmash.ogg' resistance = 10 var/energy = 0 var/max_energy = 1000 @@ -224,7 +225,7 @@ health = 150 melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "violently stabs" + attacktext = "violently stabbed" speed = -1 environment_smash = 1 see_in_dark = 7 @@ -235,3 +236,99 @@ /spell/aoe_turf/knock/harvester, /spell/rune_write ) + +////////////////Glow////////////////// +/mob/living/simple_animal/construct/proc/add_glow() + overlays = 0 + var/overlay_layer = LIGHTING_LAYER+1 + if(layer != MOB_LAYER) + overlay_layer=TURF_LAYER+0.2 + + overlays += image(icon,"glow-[icon_state]",overlay_layer) + +////////////////HUD////////////////////// + +/mob/living/simple_animal/construct/Life() + . = ..() + if(.) + if(fire) + if(fire_alert) fire.icon_state = "fire1" + else fire.icon_state = "fire0" + if(pullin) + if(pulling) pullin.icon_state = "pull1" + else pullin.icon_state = "pull0" + + if(purged) + if(purge > 0) purged.icon_state = "purge1" + else purged.icon_state = "purge0" + + silence_spells(purge) + +/mob/living/simple_animal/construct/armoured/Life() + ..() + if(healths) + switch(health) + if(250 to INFINITY) healths.icon_state = "juggernaut_health0" + if(208 to 249) healths.icon_state = "juggernaut_health1" + if(167 to 207) healths.icon_state = "juggernaut_health2" + if(125 to 166) healths.icon_state = "juggernaut_health3" + if(84 to 124) healths.icon_state = "juggernaut_health4" + if(42 to 83) healths.icon_state = "juggernaut_health5" + if(1 to 41) healths.icon_state = "juggernaut_health6" + else healths.icon_state = "juggernaut_health7" + + +/mob/living/simple_animal/construct/behemoth/Life() + ..() + if(healths) + switch(health) + if(750 to INFINITY) healths.icon_state = "juggernaut_health0" + if(625 to 749) healths.icon_state = "juggernaut_health1" + if(500 to 624) healths.icon_state = "juggernaut_health2" + if(375 to 499) healths.icon_state = "juggernaut_health3" + if(250 to 374) healths.icon_state = "juggernaut_health4" + if(125 to 249) healths.icon_state = "juggernaut_health5" + if(1 to 124) healths.icon_state = "juggernaut_health6" + else healths.icon_state = "juggernaut_health7" + +/mob/living/simple_animal/construct/builder/Life() + ..() + if(healths) + switch(health) + if(50 to INFINITY) healths.icon_state = "artificer_health0" + if(42 to 49) healths.icon_state = "artificer_health1" + if(34 to 41) healths.icon_state = "artificer_health2" + if(26 to 33) healths.icon_state = "artificer_health3" + if(18 to 25) healths.icon_state = "artificer_health4" + if(10 to 17) healths.icon_state = "artificer_health5" + if(1 to 9) healths.icon_state = "artificer_health6" + else healths.icon_state = "artificer_health7" + + + +/mob/living/simple_animal/construct/wraith/Life() + ..() + if(healths) + switch(health) + if(75 to INFINITY) healths.icon_state = "wraith_health0" + if(62 to 74) healths.icon_state = "wraith_health1" + if(50 to 61) healths.icon_state = "wraith_health2" + if(37 to 49) healths.icon_state = "wraith_health3" + if(25 to 36) healths.icon_state = "wraith_health4" + if(12 to 24) healths.icon_state = "wraith_health5" + if(1 to 11) healths.icon_state = "wraith_health6" + else healths.icon_state = "wraith_health7" + + +/mob/living/simple_animal/construct/harvester/Life() + ..() + if(healths) + switch(health) + if(150 to INFINITY) healths.icon_state = "harvester_health0" + if(125 to 149) healths.icon_state = "harvester_health1" + if(100 to 124) healths.icon_state = "harvester_health2" + if(75 to 99) healths.icon_state = "harvester_health3" + if(50 to 74) healths.icon_state = "harvester_health4" + if(25 to 49) healths.icon_state = "harvester_health5" + if(1 to 24) healths.icon_state = "harvester_health6" + else healths.icon_state = "harvester_health7" diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm new file mode 100644 index 0000000000..2bd3c8984a --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -0,0 +1,76 @@ +/mob/living/simple_animal/hostile/scarybat + name = "space bats" + desc = "A swarm of cute little blood sucking bats that looks pretty upset." + icon = 'icons/mob/bats.dmi' + icon_state = "bat" + icon_living = "bat" + icon_dead = "bat_dead" + icon_gib = "bat_dead" + speak_chance = 0 + turns_per_move = 3 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speed = 4 + maxHealth = 20 + health = 20 + + harm_intent_damage = 8 + melee_damage_lower = 10 + melee_damage_upper = 10 + attacktext = "bites" + attack_sound = 'sound/weapons/bite.ogg' + + //Space carp aren't affected by atmos. + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + + environment_smash = 1 + + faction = "scarybat" + var/mob/living/owner + +/mob/living/simple_animal/hostile/scarybat/New(loc, mob/living/L as mob) + ..() + if(istype(L)) + owner = L + +/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(var/check_drift = 0) + return ..() //No drifting in space for space carp! //original comments do not steal + +/mob/living/simple_animal/hostile/scarybat/FindTarget() + . = ..() + if(.) + emote("flutters towards [.]") + +/mob/living/simple_animal/hostile/scarybat/Found(var/atom/A)//This is here as a potential override to pick a specific target if available + if(istype(A) && A == owner) + return 0 + return ..() + +/mob/living/simple_animal/hostile/scarybat/AttackingTarget() + . =..() + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Stun(1) + L.visible_message("\the [src] scares \the [L]!") + +/mob/living/simple_animal/hostile/scarybat/cult + faction = "cult" + supernatural = 1 + +/mob/living/simple_animal/hostile/scarybat/cult/cultify() + return + +/mob/living/simple_animal/hostile/scarybat/cult/Life() + ..() + check_horde() diff --git a/code/modules/mob/living/simple_animal/hostile/creature.dm b/code/modules/mob/living/simple_animal/hostile/creature.dm index 07ad06619a..3ae0876903 100644 --- a/code/modules/mob/living/simple_animal/hostile/creature.dm +++ b/code/modules/mob/living/simple_animal/hostile/creature.dm @@ -13,4 +13,26 @@ attacktext = "chomped" attack_sound = 'sound/weapons/bite.ogg' faction = "creature" - speed = 4 \ No newline at end of file + speed = 4 + +/mob/living/simple_animal/hostile/creature/cult + faction = "cult" + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + + supernatural = 1 + +/mob/living/simple_animal/hostile/creature/cult/cultify() + return + +/mob/living/simple_animal/hostile/creature/cult/Life() + ..() + check_horde() diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index b1cc2067f4..44d9c5d1ac 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -47,3 +47,13 @@ if(prob(12)) L.Weaken(3) L.visible_message("\the [src] knocks down \the [L]!") + +/mob/living/simple_animal/hostile/faithless/cult + faction = "cult" + +/mob/living/simple_animal/hostile/faithless/cult/cultify() + return + +/mob/living/simple_animal/hostile/faithless/cult/Life() + ..() + check_horde() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 73ff6eab5d..bb4616bbe8 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -14,6 +14,9 @@ stop_automated_movement_when_pulled = 0 var/destroy_surroundings = 1 + var/shuttletarget = null + var/enroute = 0 + /mob/living/simple_animal/hostile/proc/FindTarget() var/atom/T = null @@ -113,11 +116,11 @@ /mob/living/simple_animal/hostile/proc/ListTargets(var/dist = 7) var/list/L = hearers(src, dist) - + for (var/obj/mecha/M in mechas_list) if (get_dist(src, M) <= dist) L += M - + return L /mob/living/simple_animal/hostile/death() @@ -206,3 +209,40 @@ 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_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext) + + +/mob/living/simple_animal/hostile/proc/check_horde() + if(emergency_shuttle.shuttle.location) + if(!enroute && !target_mob) //The shuttle docked, all monsters rush for the escape hallway + if(!shuttletarget || (get_dist(src, shuttletarget) >= 2)) + shuttletarget = pick(escape_list) + enroute = 1 + stop_automated_movement = 1 + spawn() + if(!src.stat) + horde() + + if(get_dist(src, shuttletarget) <= 2) //The monster reached the escape hallway + enroute = 0 + stop_automated_movement = 0 + +/mob/living/simple_animal/hostile/proc/horde() + var/turf/T = get_step_to(src, shuttletarget) + for(var/atom/A in T) + if(istype(A,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/D = A + D.open(1) + else if(istype(A,/obj/structure/mineral_door)) + var/obj/structure/mineral_door/D = A + if(D.density) + D.Open() + else if(istype(A,/obj/structure/cult/pylon)) + A.attack_generic(src, rand(melee_damage_lower, melee_damage_upper)) + else if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/table/rack)) + A.attack_generic(src, rand(melee_damage_lower, melee_damage_upper)) + Move(T) + FindTarget() + if(!target_mob || enroute) + spawn(10) + if(!src.stat) + horde() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 6e8c1a7257..067a9bd8fe 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -39,6 +39,7 @@ var/maxbodytemp = 350 var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp + var/fire_alert = 0 //Atmos effect - Yes, you can make creatures that require phoron or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage var/min_oxy = 5 @@ -78,6 +79,7 @@ return /mob/living/simple_animal/Life() + ..() //Health if(stat == DEAD) @@ -191,9 +193,13 @@ //Atmos effect if(bodytemperature < minbodytemp) + fire_alert = 2 adjustBruteLoss(cold_damage_per_tick) else if(bodytemperature > maxbodytemp) + fire_alert = 1 adjustBruteLoss(heat_damage_per_tick) + else + fire_alert = 0 if(!atmos_suitable) adjustBruteLoss(unsuitable_atoms_damage) @@ -313,10 +319,10 @@ if(statpanel("Status") && show_stat_health) stat(null, "Health: [round((health / maxHealth) * 100)]%") -/mob/living/simple_animal/death() +/mob/living/simple_animal/death(gibbed, deathmessage="") icon_state = icon_dead density = 0 - return ..(deathmessage = "no message") + return ..() /mob/living/simple_animal/ex_act(severity) if(!blinded) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 8e22962f21..792517c6d0 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -87,6 +87,8 @@ var/lying = 0 var/lying_prev = 0 var/canmove = 1 + //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. + var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. var/lastpuke = 0 var/unacidable = 0 var/small = 0 diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index baf1d29968..905b8d0f70 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -170,17 +170,19 @@ /client/Move(n, direct) + if(!mob) + return // Moved here to avoid nullrefs below if(mob.control_object) Move_object(direct) - if(isobserver(mob)) return mob.Move(n,direct) + if(mob.incorporeal_move) + Process_Incorpmove(direct) + return if(moving) return 0 if(world.time < move_delay) return - if(!mob) return - if(locate(/obj/effect/stop/, mob.loc)) for(var/obj/effect/stop/S in mob.loc) if(S.victim == mob) @@ -364,13 +366,15 @@ ///Allows mobs to run though walls /client/proc/Process_Incorpmove(direct) var/turf/mobloc = get_turf(mob) - if(!isliving(mob)) - return - var/mob/living/L = mob - switch(L.incorporeal_move) + + switch(mob.incorporeal_move) if(1) - L.loc = get_step(L, direct) - L.dir = direct + var/turf/T = get_step(mob, direct) + if(mob.check_holy(T)) + mob << "You cannot get past holy grounds while you are in this plane of existence!" + else + mob.loc = get_step(mob, direct) + mob.dir = direct if(2) if(prob(50)) var/locx @@ -398,21 +402,35 @@ return else return - L.loc = locate(locx,locy,mobloc.z) + mob.loc = locate(locx,locy,mobloc.z) spawn(0) var/limit = 2//For only two trailing shadows. - for(var/turf/T in getline(mobloc, L.loc)) + for(var/turf/T in getline(mobloc, mob.loc)) spawn(0) - anim(T,L,'icons/mob/mob.dmi',,"shadow",,L.dir) + anim(T,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir) limit-- if(limit<=0) break else spawn(0) - anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,L.dir) - L.loc = get_step(L, direct) - L.dir = direct + anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir) + mob.loc = get_step(mob, direct) + mob.dir = direct + // Crossed is always a bit iffy + for(var/obj/S in mob.loc) + if(istype(S,/obj/effect/step_trigger) || istype(S,/obj/effect/beam)) + S.Crossed(mob) + + var/area/A = get_area_master(mob) + if(A) + A.Entered(mob) + if(isturf(mob.loc)) + var/turf/T = mob.loc + T.Entered(mob) + mob.Post_Incorpmove() return 1 +/mob/proc/Post_Incorpmove() + return ///Process_Spacemove ///Called by /client/Move() diff --git a/code/modules/power/singularity/act.dm b/code/modules/power/singularity/act.dm new file mode 100644 index 0000000000..5b0303c9b5 --- /dev/null +++ b/code/modules/power/singularity/act.dm @@ -0,0 +1,138 @@ +#define I_SINGULO "singulo" + +/atom/proc/singularity_act() + return + +/atom/proc/singularity_pull() + return + +/mob/living/singularity_act() + investigate_log("has been consumed by a singularity", I_SINGULO) + gib() + return 20 + +/mob/living/singularity_pull(S) + step_towards(src, S) + +/mob/living/carbon/human/singularity_act() + var/gain = 20 + if(mind) + if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer")) + gain = 100 + if(mind.assigned_role == "Assistant") + gain = rand(0, 300) + investigate_log(I_SINGULO,"has been consumed by a singularity", I_SINGULO) + gib() + return gain + +/mob/living/carbon/human/singularity_pull(S, current_size) + if(current_size >= STAGE_THREE) + var/list/handlist = list(l_hand, r_hand) + for(var/obj/item/hand in handlist) + if(prob(current_size*5) && hand.w_class >= ((11-current_size)/2) && u_equip(hand)) + step_towards(hand, src) + src << "The [S] pulls \the [hand] from your grip!" + apply_effect(current_size * 3, IRRADIATE) + if(shoes) + if(shoes.flags & NOSLIP) return 0 + ..() + +/obj/singularity_act() + ex_act(1) + if(src) + spawn(0) + qdel(src) + return 2 + +/obj/singularity_pull(S, current_size) + if(anchored) + if(current_size >= STAGE_FIVE) + step_towards(src, S) + else + step_towards(src, S) + +/obj/effect/beam/singularity_pull() + return + +/obj/effect/overlay/singularity_pull() + return + +/obj/item/singularity_pull(S, current_size) + spawn(0) //this is needed or multiple items will be thrown sequentially and not simultaneously + if(current_size >= STAGE_FOUR) + //throw_at(S, 14, 3) + step_towards(src,S) + sleep(1) + step_towards(src,S) + else if(current_size > STAGE_ONE) + step_towards(src,S) + else ..() + +/obj/machinery/atmospherics/pipe/singularity_pull() + return + +/obj/machinery/power/supermatter/shard/singularity_act() + qdel(src) + return 5000 + +/obj/machinery/power/supermatter/singularity_act() + var/prints = "" + if(src.fingerprintshidden) + prints = ", all touchers : " + src.fingerprintshidden + + SetUniversalState(/datum/universal_state/supermatter_cascade) + log_admin("New super singularity made by eating a SM crystal [prints]. Last touched by [src.fingerprintslast].") + message_admins("New super singularity made by eating a SM crystal [prints]. Last touched by [src.fingerprintslast].") + spawn(0) + qdel(src) + return 50000 + +/obj/item/projectile/beam/emitter/singularity_pull() + return + +/obj/item/weapon/storage/backpack/holding/singularity_act(S, current_size) + var/dist = max((current_size - 2), 1) + explosion(src.loc,(dist),(dist*2),(dist*4)) + return 1000 + +/turf/singularity_act(S, current_size) + if(intact) + for(var/obj/O in contents) + if(O.level != 1) + continue + if(O.invisibility == 101) + O.singularity_act(src, current_size) + ChangeTurf(/turf/space) + return 2 + +/turf/simulated/wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(75)) + dismantle_wall() + return + if(current_size == STAGE_FOUR) + if(prob(30)) + dismantle_wall() + +/turf/simulated/wall/r_wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(30)) + dismantle_wall() + +/turf/space/singularity_act() + return + +/******************* +* Nar-Sie Act/Pull * +*******************/ +/atom/proc/singuloCanEat() + return 1 + +/mob/dead/singuloCanEat() + return 0 + +/mob/eye/singuloCanEat() + return 0 + +/mob/new_player/singuloCanEat() + return 0 diff --git a/code/modules/power/singularity/investigate.dm b/code/modules/power/singularity/investigate.dm index 63c54c0e54..c0c62616ed 100644 --- a/code/modules/power/singularity/investigate.dm +++ b/code/modules/power/singularity/investigate.dm @@ -1,4 +1,4 @@ /area/engineering/power_alert(var/alarming) if (alarming) investigate_log("has a power alarm!","singulo") - ..() \ No newline at end of file + ..() diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 01e671c1ec..0fc454b9fb 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -1,90 +1,285 @@ var/global/narsie_behaviour = "CultStation13" var/global/narsie_cometh = 0 var/global/list/narsie_list = list() - -/obj/machinery/singularity/narsie //Moving narsie to a child object of the singularity so it can be made to function differently. --NEO +/obj/machinery/singularity/narsie //Moving narsie to its own file for the sake of being clearer name = "Nar-Sie" desc = "Your mind begins to bubble and ooze as it tries to comprehend what it sees." - icon = 'icons/obj/magic_terror.dmi' - pixel_x = -89 - pixel_y = -85 - current_size = 9 //It moves/eats like a max-size singulo, aside from range. --NEO - contained = 0 //Are we going to move around? - dissipate = 0 //Do we lose energy over time? - move_self = 1 //Do we move on our own? + icon = 'icons/obj/narsie.dmi' + icon_state = "narsie-small" + pixel_x = -236 + pixel_y = -256 + + current_size = 9 //It moves/eats like a max-size singulo, aside from range. --NEO. + contained = 0 // Are we going to move around? + dissipate = 0 // Do we lose energy over time? grav_pull = 10 //How many tiles out do we pull? consume_range = 3 //How many tiles out do we eat - var/last_boom = 0 + + +/obj/machinery/singularity/narsie/New() + ..() + narsie_list.Add(src) + +/obj/machinery/singularity/narsie/Destroy() + narsie_list.Remove(src) + ..() /obj/machinery/singularity/narsie/large name = "Nar-Sie" icon = 'icons/obj/narsie.dmi' + icon_state = "narsie"//mobs perceive the geometer of blood through their see_narsie proc + // Pixel stuff centers Narsie. pixel_x = -236 pixel_y = -256 + luminosity = 1 + l_color = "#3e0000" + current_size = 12 - move_self = 1 //Do we move on our own? - consume_range = 12 //How many tiles out do we eat + consume_range = 12 // How many tiles out do we eat. + var/announce=1 + var/narnar = 1 /obj/machinery/singularity/narsie/large/New() ..() - narsie_list.Add(src) - world << "NAR-SIE HAS RISEN" + if(announce) + world << "[uppertext(name)] HAS RISEN" + world << sound('sound/effects/wind/wind_5_1.ogg') + if(emergency_shuttle && emergency_shuttle.can_call()) emergency_shuttle.call_evac() emergency_shuttle.launch_time = 0 // Cannot recall -/obj/machinery/singularity/narsie/large/Destroy() - narsie_list.Remove(src) - ..() + if(narnar) + SetUniversalState(/datum/universal_state/hell) + narsie_cometh = 1 /obj/machinery/singularity/narsie/process() eat() - if(!target || prob(5)) + + if (!target || prob(5)) pickcultist() + move() - if(prob(25)) + + if (prob(25)) mezzer() -/obj/machinery/singularity/narsie/consume(var/atom/A) //Has its own consume proc because it doesn't need energy and I don't want BoHs to explode it. --NEO - if(is_type_in_list(A, uneatable)) - return 0 - if (istype(A,/mob/living))//Mobs get gibbed - A:gib() - else if(istype(A,/obj)) - var/obj/O = A - machines -= O - processing_objects -= O - O.loc = null - else if(isturf(A)) - var/turf/T = A - if(T.intact) - for(var/obj/O in T.contents) - if(O.level != 1) - continue - if(O.invisibility == 101) - src.consume(O) - A:ChangeTurf(/turf/space) - if(last_boom + 100 < world.time && prob(5)) - explosion(loc, -1, -1, -1, 1, 0) //Since we're not exploding everything in consume() toss out an explosion effect every now and again - last_boom = world.time - return +/obj/machinery/singularity/narsie/large/eat() + set background = BACKGROUND_ENABLED -/obj/machinery/singularity/narsie/ex_act() //No throwing bombs at it either. --NEO + for (var/turf/A in orange(consume_range, src)) + consume(A) + +/obj/machinery/singularity/narsie/mezzer() + for(var/mob/living/carbon/M in oviewers(8, src)) + if(M.stat == CONSCIOUS) + if(M.status_flags & GODMODE) + continue + if(!iscultist(M)) + M << " You feel your sanity crumble away in an instant as you gaze upon [src.name]..." + M.apply_effect(3, STUN) + + +/obj/machinery/singularity/narsie/large/Bump(atom/A) + if(!narnar) return + if(isturf(A)) + narsiewall(A) + else if(istype(A, /obj/structure/cult)) + qdel(A) + +/obj/machinery/singularity/narsie/large/Bumped(atom/A) + if(!narnar) return + if(isturf(A)) + narsiewall(A) + else if(istype(A, /obj/structure/cult)) + qdel(A) + +/obj/machinery/singularity/narsie/move(var/force_move = 0) + if(!move_self) + return 0 + + var/movement_dir = pick(alldirs - last_failed_movement) + + if(force_move) + movement_dir = force_move + + if(target && prob(60)) + movement_dir = get_dir(src,target) + + spawn(0) + step(src, movement_dir) + spawn(1) + step(src, movement_dir) + return 1 + +/obj/machinery/singularity/narsie/large/move(var/force_move = 0) + if(!move_self) + return 0 + + var/movement_dir = pick(alldirs - last_failed_movement) + + if(force_move) + movement_dir = force_move + + if(target && prob(60)) + movement_dir = get_dir(src,target) + spawn(0) + step(src, movement_dir) + narsiefloor(get_turf(loc)) + for(var/mob/M in player_list) + if(M.client) + M.see_narsie(src,movement_dir) + spawn(10) + step(src, movement_dir) + narsiefloor(get_turf(loc)) + for(var/mob/M in player_list) + if(M.client) + M.see_narsie(src,movement_dir) + return 1 + +/obj/machinery/singularity/narsie/proc/narsiefloor(var/turf/T)//leaving "footprints" + if(!(istype(T, /turf/simulated/wall/cult)||istype(T, /turf/space))) + if(T.icon_state != "cult-narsie") + T.desc = "something that goes beyond your understanding went this way" + T.icon_state = "cult-narsie" + T.luminosity = 1 + +/obj/machinery/singularity/narsie/proc/narsiewall(var/turf/T) + T.desc = "An opening has been made on that wall, but who can say if what you seek truly lies on the other side?" + T.icon = 'icons/turf/walls.dmi' + T.icon_state = "cult-narsie" + T.opacity = 0 + T.density = 0 + luminosity = 1 + +/obj/machinery/singularity/narsie/large/consume(const/atom/A) //Has its own consume proc because it doesn't need energy and I don't want BoHs to explode it. --NEO +//NEW BEHAVIOUR + if(narsie_behaviour == "CultStation13") + //MOB PROCESSING + new_narsie(A) + +//OLD BEHAVIOUR + else if(narsie_behaviour == "Nar-Singulo") + old_narsie(A) + +/obj/machinery/singularity/narsie/proc/new_narsie(const/atom/A) + if (istype(A, /mob/) && (get_dist(A, src) <= 7)) + var/mob/M = A + + if(M.status_flags & GODMODE) + return 0 + + M.cultify() + +//ITEM PROCESSING + else if (istype(A, /obj/)) + var/obj/O = A + O.cultify() + +//TURF PROCESSING + else if (isturf(A)) + var/dist = get_dist(A, src) + + for (var/atom/movable/AM in A.contents) + if (dist <= consume_range) + consume(AM) + continue + + if (dist <= consume_range && !istype(A, /turf/space)) + var/turf/T = A + if(T.holy) + T.holy = 0 //Nar-Sie doesn't give a shit about sacred grounds. + T.cultify() + +/obj/machinery/singularity/narsie/proc/old_narsie(const/atom/A) + if(!(A.singuloCanEat())) + return 0 + + if (istype(A, /mob/living/)) + var/mob/living/C2 = A + + if(C2.status_flags & GODMODE) + return 0 + + C2.dust() // Changed from gib(), just for less lag. + + else if (istype(A, /obj/)) + qdel(A) + + if (A) + qdel(A) + else if (isturf(A)) + var/dist = get_dist(A, src) + + for (var/atom/movable/AM2 in A.contents) + if (AM2 == src) // This is the snowflake. + continue + + if (dist <= consume_range) + consume(AM2) + continue + + if (dist <= consume_range && !istype(A, /turf/space)) + var/turf/T2 = A + T2.ChangeTurf(/turf/space) + +/obj/machinery/singularity/narsie/consume(const/atom/A) //This one is for the small ones. + if(!(A.singuloCanEat())) + return 0 + + if (istype(A, /mob/living/)) + var/mob/living/C2 = A + + if(C2.status_flags & GODMODE) + return 0 + + C2.dust() // Changed from gib(), just for less lag. + + else if (istype(A, /obj/)) + qdel(A) + + if (A) + qdel(A) + else if (isturf(A)) + var/dist = get_dist(A, src) + + for (var/atom/movable/AM2 in A.contents) + if (AM2 == src) // This is the snowflake. + continue + + if (dist <= consume_range) + consume(AM2) + continue + + if (dist > consume_range) + if(!(AM2.singuloCanEat())) + continue + + if (101 == AM2.invisibility) + continue + + spawn (0) + AM2.singularity_pull(src, src.current_size) + + if (dist <= consume_range && !istype(A, /turf/space)) + var/turf/T2 = A + T2.ChangeTurf(/turf/space) + +/obj/machinery/singularity/narsie/ex_act(severity) //No throwing bombs at it either. --NEO return /obj/machinery/singularity/narsie/proc/pickcultist() //Narsie rewards his cultists with being devoured first, then picks a ghost to follow. --NEO var/list/cultists = list() - if(cult && cult.current_antagonists.len) - for(var/datum/mind/cult_nh_mind in cult.current_antagonists) - if(!cult_nh_mind.current) - continue - if(cult_nh_mind.current.stat) - continue - var/turf/pos = get_turf(cult_nh_mind.current) - if(pos.z != src.z) - continue - cultists += cult_nh_mind.current + for(var/datum/mind/cult_nh_mind in cult.current_antagonists) + if(!cult_nh_mind.current) + continue + if(cult_nh_mind.current.stat) + continue + var/turf/pos = get_turf(cult_nh_mind.current) + if(pos.z != src.z) + continue + cultists += cult_nh_mind.current if(cultists.len) acquire(pick(cultists)) return @@ -112,22 +307,51 @@ var/global/list/narsie_list = list() return //no living humans, follow a ghost instead. -/obj/machinery/singularity/narsie/proc/acquire(var/mob/food) - target << "\blue NAR-SIE HAS LOST INTEREST IN YOU" +/obj/machinery/singularity/narsie/proc/acquire(const/mob/food) + var/capname = uppertext(name) + + target << "[capname] HAS LOST INTEREST IN YOU." target = food - if(ishuman(target)) - target << "\red NAR-SIE HUNGERS FOR YOUR SOUL" + + if (ishuman(target)) + target << "[capname] HUNGERS FOR YOUR SOUL." else - target << "\red NAR-SIE HAS CHOSEN YOU TO LEAD HIM TO HIS NEXT MEAL" + target << "[capname] HAS CHOSEN YOU TO LEAD HIM TO HIS NEXT MEAL." -//Wizard narsie +/obj/machinery/singularity/narsie/on_capture() + chained = 1 + move_self = 0 + icon_state ="narsie-small-chains" +/obj/machinery/singularity/narsie/on_release() + chained = 0 + move_self = 1 + icon_state ="narsie-small" + +/obj/machinery/singularity/narsie/large/on_capture() + chained = 1 + move_self = 0 + icon_state ="narsie-chains" + for(var/mob/M in mob_list)//removing the client image of nar-sie while it is chained + if(M.client) + M.see_narsie(src) + +/obj/machinery/singularity/narsie/large/on_release() + chained = 0 + move_self = 1 + icon_state ="narsie" + +/obj/machinery/singularity/narsie/cultify() + return + +/** + * Wizard narsie. + */ /obj/machinery/singularity/narsie/wizard grav_pull = 0 /obj/machinery/singularity/narsie/wizard/eat() - set background = 1 - for(var/atom/X in orange(consume_range,src)) - if(isturf(X) || istype(X, /atom/movable)) - consume(X) - return + set background = BACKGROUND_ENABLED + + for (var/turf/T in trange(consume_range, src)) + consume(T) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index a2901ac270..aa8e85017c 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -1,10 +1,5 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 -var/global/list/uneatable = list( - /turf/space, - /obj/effect/overlay - ) - /obj/machinery/singularity/ name = "gravitational singularity" desc = "A gravitational singularity." @@ -16,6 +11,7 @@ var/global/list/uneatable = list( luminosity = 6 unacidable = 1 //Don't comment this out. use_power = 0 + var/current_size = 1 var/allowed_size = 1 var/contained = 1 //Are we going to move around? @@ -26,102 +22,108 @@ var/global/list/uneatable = list( var/dissipate_strength = 1 //How much energy do we lose? var/move_self = 1 //Do we move on our own? var/grav_pull = 4 //How many tiles out do we pull? - var/consume_range = 0 //How many tiles out do we eat - var/event_chance = 15 //Prob for event each tick - var/target = null //its target. moves towards the target if it has one - var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing - var/teleport_del = 0 + var/consume_range = 0 //How many tiles out do we eat. + var/event_chance = 15 //Prob for event each tick. + var/target = null //Its target. Moves towards the target if it has one. + var/last_failed_movement = 0 //Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing. var/last_warning + var/chained = 0//Adminbus chain-grab + /obj/machinery/singularity/New(loc, var/starting_energy = 50, var/temp = 0) //CARN: admin-alert for chuckle-fuckery. admin_investigate_setup() + energy = starting_energy + + if (temp) + spawn (temp) + qdel(src) - src.energy = starting_energy - if(temp) - spawn(temp) - del(src) ..() for(var/obj/machinery/power/singularity_beacon/singubeacon in machines) if(singubeacon.active) target = singubeacon break - return - /obj/machinery/singularity/attack_hand(mob/user as mob) consume(user) return 1 - /obj/machinery/singularity/blob_act(severity) return - /obj/machinery/singularity/ex_act(severity) + if(current_size == STAGE_SUPER)//IT'S UNSTOPPABLE + return switch(severity) if(1.0) if(prob(25)) - del(src) + investigate_log("has been destroyed by an explosion.", I_SINGULO) + qdel(src) return else energy += 50 if(2.0 to 3.0) energy += round((rand(20,60)/2),1) return - return +/obj/machinery/singularity/bullet_act(obj/item/projectile/P) + return 0 //Will there be an impact? Who knows. Will we see it? No. /obj/machinery/singularity/Bump(atom/A) consume(A) - return - /obj/machinery/singularity/Bumped(atom/A) consume(A) - return - /obj/machinery/singularity/process() eat() dissipate() check_energy() - if(current_size >= 3) + if (current_size >= STAGE_THREE) move() pulse() - if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit + + if (prob(event_chance)) //Chance for it to run a special event TODO: Come up with one or two more that fit. event() + +/obj/machinery/singularity/attack_ai() //To prevent ais from gibbing themselves when they click on one. return - -/obj/machinery/singularity/attack_ai() //to prevent ais from gibbing themselves when they click on one. - return - - /obj/machinery/singularity/proc/admin_investigate_setup() last_warning = world.time var/count = locate(/obj/machinery/containment_field) in orange(30, src) - if(!count) message_admins("A singulo has been created without containment fields active ([x],[y],[z])",1) - investigate_log("was created. [count?"":"No containment fields were active"]","singulo") + + if (!count) + message_admins("A singulo has been created without containment fields active ([x], [y], [z] - JMP).") + + investigate_log("was created. [count ? "" : "No containment fields were active."]", I_SINGULO) /obj/machinery/singularity/proc/dissipate() - if(!dissipate) + if (!dissipate) return + if(dissipate_track >= dissipate_delay) - src.energy -= dissipate_strength + energy -= dissipate_strength dissipate_track = 0 else dissipate_track++ +/obj/machinery/singularity/proc/expand(var/force_size = 0, var/growing = 1) + if(current_size == STAGE_SUPER)//if this is happening, this is an error + message_admins("expand() was called on a super singulo. This should not happen. Contact a coder immediately!") + return + var/temp_allowed_size = allowed_size -/obj/machinery/singularity/proc/expand(var/force_size = 0) - var/temp_allowed_size = src.allowed_size - if(force_size) + if (force_size) temp_allowed_size = force_size - switch(temp_allowed_size) - if(1) - current_size = 1 + + switch (temp_allowed_size) + if (STAGE_ONE) + name = "gravitational singularity" + desc = "A gravitational singularity." + current_size = STAGE_ONE icon = 'icons/obj/singularity.dmi' icon_state = "singularity_s1" pixel_x = 0 @@ -131,8 +133,14 @@ var/global/list/uneatable = list( dissipate_delay = 10 dissipate_track = 0 dissipate_strength = 1 - if(3)//1 to 3 does not check for the turfs if you put the gens right next to a 1x1 then its going to eat them - current_size = 3 + overlays = 0 + if(chained) + overlays = "chain_s1" + visible_message("The singularity has shrunk to a rather pitiful size.") + if (STAGE_TWO) //1 to 3 does not check for the turfs if you put the gens right next to a 1x1 then its going to eat them. + name = "gravitational singularity" + desc = "A gravitational singularity." + current_size = STAGE_TWO icon = 'icons/effects/96x96.dmi' icon_state = "singularity_s3" pixel_x = -32 @@ -142,9 +150,18 @@ var/global/list/uneatable = list( dissipate_delay = 5 dissipate_track = 0 dissipate_strength = 5 - if(5) - if((check_turfs_in(1,2))&&(check_turfs_in(2,2))&&(check_turfs_in(4,2))&&(check_turfs_in(8,2))) - current_size = 5 + overlays = 0 + if(chained) + overlays = "chain_s3" + if(growing) + visible_message("The singularity noticeably grows in size.") + else + visible_message("The singularity has shrunk to a less powerful size.") + if (STAGE_THREE) + if ((check_turfs_in(1, 2)) && (check_turfs_in(2, 2)) && (check_turfs_in(4, 2)) && (check_turfs_in(8, 2))) + name = "gravitational singularity" + desc = "A gravitational singularity." + current_size = STAGE_THREE icon = 'icons/effects/160x160.dmi' icon_state = "singularity_s5" pixel_x = -64 @@ -154,9 +171,18 @@ var/global/list/uneatable = list( dissipate_delay = 4 dissipate_track = 0 dissipate_strength = 20 - if(7) - if((check_turfs_in(1,3))&&(check_turfs_in(2,3))&&(check_turfs_in(4,3))&&(check_turfs_in(8,3))) - current_size = 7 + overlays = 0 + if(chained) + overlays = "chain_s5" + if(growing) + visible_message("The singularity expands to a reasonable size.") + else + visible_message("The singularity has returned to a safe size.") + if(STAGE_FOUR) + if ((check_turfs_in(1, 3)) && (check_turfs_in(2, 3)) && (check_turfs_in(4, 3)) && (check_turfs_in(8, 3))) + name = "gravitational singularity" + desc = "A gravitational singularity." + current_size = STAGE_FOUR icon = 'icons/effects/224x224.dmi' icon_state = "singularity_s7" pixel_x = -96 @@ -166,123 +192,100 @@ var/global/list/uneatable = list( dissipate_delay = 10 dissipate_track = 0 dissipate_strength = 10 - if(9)//this one also lacks a check for gens because it eats everything - current_size = 9 + overlays = 0 + if(chained) + overlays = "chain_s7" + if(growing) + visible_message("The singularity expands to a dangerous size.") + else + visible_message("Miraculously, the singularity reduces in size, and can be contained.") + if(STAGE_FIVE) //This one also lacks a check for gens because it eats everything. + name = "gravitational singularity" + desc = "A gravitational singularity." + current_size = STAGE_FIVE icon = 'icons/effects/288x288.dmi' icon_state = "singularity_s9" pixel_x = -128 pixel_y = -128 grav_pull = 10 consume_range = 4 + dissipate = 0 //It cant go smaller due to e loss. + overlays = 0 + if(chained) + overlays = "chain_s9" + if(growing) + visible_message("The singularity has grown out of control!") + else + visible_message("The singularity miraculously reduces in size and loses its supermatter properties.") + if(STAGE_SUPER)//SUPERSINGULO + name = "super gravitational singularity" + desc = "A gravitational singularity with the properties of supermatter. It has the power to destroy worlds." + current_size = STAGE_SUPER + icon = 'icons/effects/352x352.dmi' + icon_state = "singularity_s11"//uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo? + pixel_x = -160 + pixel_y = -160 + grav_pull = 16 + consume_range = 5 dissipate = 0 //It cant go smaller due to e loss - if(current_size == allowed_size) - investigate_log("grew to size [current_size]","singulo") + event_chance = 25 //Events will fire off more often. + if(chained) + overlays = "chain_s9" + visible_message("You witness the creation of a destructive force that cannot possibly be stopped by human hands.") + + if (current_size == allowed_size) + investigate_log("grew to size [current_size].", I_SINGULO) return 1 - else if(current_size < (--temp_allowed_size)) + else if (current_size < (--temp_allowed_size) && current_size != STAGE_SUPER) expand(temp_allowed_size) else return 0 - /obj/machinery/singularity/proc/check_energy() - if(energy <= 0) - del(src) + if (energy <= 0) + investigate_log("collapsed.", I_SINGULO) + qdel(src) return 0 - switch(energy)//Some of these numbers might need to be changed up later -Mport - if(1 to 199) - allowed_size = 1 - if(200 to 499) - allowed_size = 3 - if(500 to 999) - allowed_size = 5 - if(1000 to 1999) - allowed_size = 7 - if(2000 to INFINITY) - allowed_size = 9 - if(current_size != allowed_size) - expand() + + switch (energy) //Some of these numbers might need to be changed up later -Mport. + if (1 to 199) + allowed_size = STAGE_ONE + if (200 to 499) + allowed_size = STAGE_TWO + if (500 to 999) + allowed_size = STAGE_THREE + if (1000 to 1999) + allowed_size = STAGE_FOUR + if(2000 to 49999) + allowed_size = STAGE_FIVE + if(50000 to INFINITY) + allowed_size = STAGE_SUPER + + if (current_size != allowed_size && current_size != STAGE_SUPER) + expand(null, current_size > allowed_size) return 1 - /obj/machinery/singularity/proc/eat() - set background = 1 - // Let's just make this one loop. - for(var/atom/X in orange(grav_pull,src)) + set background = BACKGROUND_ENABLED + + for(var/atom/X in orange(grav_pull, src)) var/dist = get_dist(X, src) - // Movable atoms only - if(dist > consume_range && istype(X, /atom/movable)) - if(is_type_in_list(X, uneatable)) continue - if(((X) &&(!X:anchored) && (!istype(X,/mob/living/carbon/human)))|| (src.current_size >= 9)) - step_towards(X,src) - else if(istype(X,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = X - if(istype(H.shoes,/obj/item/clothing/shoes/magboots)) - var/obj/item/clothing/shoes/magboots/M = H.shoes - if(M.magpulse) - continue - step_towards(H,src) - // Turf and movable atoms - else if(dist <= consume_range && (isturf(X) || istype(X, /atom/movable))) - consume(X) - return - - -/obj/machinery/singularity/proc/consume(var/atom/A) - var/gain = 0 - if(is_type_in_list(A, uneatable)) - return 0 - if (istype(A,/mob/living))//Mobs get gibbed - gain = 20 - if(istype(A,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = A - if(H.mind) - - if((H.mind.assigned_role == "Station Engineer") || (H.mind.assigned_role == "Chief Engineer") ) - gain = 100 - - if(H.mind.assigned_role == "Clown") - gain = rand(-300, 300) // HONK - - spawn() - A:gib() - sleep(1) - else if(istype(A,/obj/)) - - if (istype(A,/obj/item/weapon/storage/backpack/holding)) - var/dist = max((current_size - 2),1) - explosion(src.loc,(dist),(dist*2),(dist*4)) + var/obj/machinery/singularity/S = src + if(!istype(src)) return + if(dist > consume_range) + X.singularity_pull(S, current_size) + else if(dist <= consume_range) + consume(X) - if(istype(A, /obj/machinery/singularity))//Welp now you did it - var/obj/machinery/singularity/S = A - src.energy += (S.energy/2)//Absorb most of it - del(S) - var/dist = max((current_size - 2),1) - explosion(src.loc,(dist),(dist*2),(dist*4)) - return//Quits here, the obj should be gone, hell we might be + //for (var/turf/T in trange(grav_pull, src)) //TODO: Create a similar trange for orange to prevent snowflake of self check. + // consume(T) - if((teleport_del) && (!istype(A, /obj/machinery)))//Going to see if it does not lag less to tele items over to Z 2 - var/obj/O = A - O.x = 2 - O.y = 2 - O.z = 2 - else - A.ex_act(1.0) - if(A) del(A) - gain = 2 - else if(isturf(A)) - var/turf/T = A - if(T.intact) - for(var/obj/O in T.contents) - if(O.level != 1) - continue - if(O.invisibility == 101) - src.consume(O) - T.ChangeTurf(/turf/space) - gain = 2 - src.energy += gain return +/obj/machinery/singularity/proc/consume(const/atom/A) + src.energy += A.singularity_act(src, current_size) + return /obj/machinery/singularity/proc/move(var/force_move = 0) if(!move_self) @@ -311,7 +314,6 @@ var/global/list/uneatable = list( last_failed_movement = movement_dir return 0 - /obj/machinery/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0) if(!direction) return 0 @@ -328,6 +330,8 @@ var/global/list/uneatable = list( steps = 4 if(9) steps = 5 + if(11) + steps = 6 else steps = step var/list/turfs = list() @@ -364,34 +368,38 @@ var/global/list/uneatable = list( return 0 return 1 +/obj/machinery/singularity/proc/can_move(const/turf/T) + if (!isturf(T)) + return 0 -/obj/machinery/singularity/proc/can_move(var/turf/T) - if(!T) + if ((locate(/obj/machinery/containment_field) in T) || (locate(/obj/machinery/shieldwall) in T)) return 0 - if((locate(/obj/machinery/containment_field) in T)||(locate(/obj/machinery/shieldwall) in T)) - return 0 - else if(locate(/obj/machinery/field_generator) in T) + else if (locate(/obj/machinery/field_generator) in T) var/obj/machinery/field_generator/G = locate(/obj/machinery/field_generator) in T - if(G && G.active) + + if (G && G.active) return 0 - else if(locate(/obj/machinery/shieldwallgen) in T) + else if (locate(/obj/machinery/shieldwallgen) in T) var/obj/machinery/shieldwallgen/S = locate(/obj/machinery/shieldwallgen) in T - if(S && S.active) + + if (S && S.active) return 0 return 1 - /obj/machinery/singularity/proc/event() - var/numb = pick(1,2,3,4,5,6) - switch(numb) - if(1)//EMP + var/numb = pick(1, 2, 3, 4, 5, 6) + + switch (numb) + if (1) //EMP. emp_area() - if(2,3)//tox damage all carbon mobs in area + if (2, 3) //Tox damage all carbon mobs in area. toxmob() - if(4)//Stun mobs who lack optic scanners + if (4) //Stun mobs who lack optic scanners. mezzer() else return 0 + if(current_size == 11) + smwave() return 1 @@ -405,6 +413,8 @@ var/global/list/uneatable = list( radiation = round(((src.energy-150)/50)*5,1) radiationmin = round((radiation/5),1)// for(var/mob/living/M in view(toxrange, src.loc)) + if(M.status_flags & GODMODE) + continue M.apply_effect(rand(radiationmin,radiation), IRRADIATE) toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad"))) M.apply_effect(toxdamage, TOX) @@ -415,28 +425,70 @@ var/global/list/uneatable = list( for(var/mob/living/carbon/M in oviewers(8, src)) if(istype(M, /mob/living/carbon/brain)) //Ignore brains continue - + if(M.status_flags & GODMODE) + continue if(M.stat == CONSCIOUS) if (istype(M,/mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(istype(H.glasses,/obj/item/clothing/glasses/meson)) - H << "\blue You look directly into The [src.name], good thing you had your protective eyewear on!" + if(istype(H.glasses,/obj/item/clothing/glasses/meson) && current_size != 11) + H << "You look directly into The [src.name], good thing you had your protective eyewear on!" return - M << "\red You look directly into The [src.name] and feel weak." + else + H << "You look directly into The [src.name], but your eyewear does absolutely nothing to protect you from it!" + M << "You look directly into The [src.name] and feel [current_size == 11 ? "helpless" : "weak"]." M.apply_effect(3, STUN) for(var/mob/O in viewers(M, null)) - O.show_message(text("\red [] stares blankly at The []!", M, src), 1) - return - + O.show_message(text("[] stares blankly at The []!", M, src), 1) /obj/machinery/singularity/proc/emp_area() - empulse(src, 8, 10) - return + if(current_size != 11) + empulse(src, 8, 10) + else + empulse(src, 12, 16) +/obj/machinery/singularity/proc/smwave() + for(var/mob/living/M in view(10, src.loc)) + if(prob(67)) + M.apply_effect(rand(energy), IRRADIATE) + M << "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat." + M << "Miraculously, it fails to kill you." + else + M << "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat." + M << "You don't even have a moment to react as you are reduced to ashes by the intense radiation." + M.dust() + return /obj/machinery/singularity/proc/pulse() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) - if(get_dist(R, src) <= 15) // Better than using orange() every process + if (get_dist(R, src) <= 15) //Better than using orange() every process. R.receive_pulse(energy) - return + +/obj/machinery/singularity/proc/on_capture() + chained = 1 + overlays = 0 + move_self = 0 + switch (current_size) + if(1) + overlays += image('icons/obj/singularity.dmi',"chain_s1") + if(3) + overlays += image('icons/effects/96x96.dmi',"chain_s3") + if(5) + overlays += image('icons/effects/160x160.dmi',"chain_s5") + if(7) + overlays += image('icons/effects/224x224.dmi',"chain_s7") + if(9) + overlays += image('icons/effects/288x288.dmi',"chain_s9") + +/obj/machinery/singularity/proc/on_release() + chained = 0 + overlays = 0 + move_self = 1 + +/obj/machinery/singularity/singularity_act(S, size) + if(current_size <= size) + var/gain = (energy/2) + var/dist = max((current_size - 2), 1) + explosion(src.loc,(dist),(dist*2),(dist*4)) + spawn(0) + qdel(src) + return gain diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 2a73fd5786..44ee2987c4 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -156,6 +156,8 @@ datum else if(istype(self.data["donor"], /mob/living/carbon/alien)) var/obj/effect/decal/cleanable/blood/B = blood_splatter(T,self,1) if(B) B.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*" + if(volume >= 5 && !istype(T.loc, /area/chapel)) //blood desanctifies non-chapel tiles + T.holy = 0 return /* Must check the transfering of reagents and their data first. They all can point to one disease datum. @@ -289,6 +291,12 @@ datum holder.remove_reagent(src.id, 10 * REAGENTS_METABOLISM) //high metabolism to prevent extended uncult rolls. return + reaction_turf(var/turf/T, var/volume) + src = null + if(volume >= 5) + T.holy = 1 + return + lube name = "Space Lube" id = "lube" diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index 6cdf0c3e91..587b5d9342 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -332,29 +332,7 @@ defer_powernet_rebuild = 1 // Let's just make this one loop. for(var/atom/X in orange(pull_radius,src)) - // Movable atoms only - if(istype(X, /atom/movable)) - if(is_type_in_list(X, uneatable)) continue - if(((X) && (!istype(X,/mob/living/carbon/human)))) - step_towards(X,src) - if(istype(X, /obj)) //unanchored objects pulled twice as fast - var/obj/O = X - if(!O.anchored) - step_towards(X,src) - else - step_towards(X,src) - if(istype(X, /obj/structure/window)) //shatter windows - var/obj/structure/window/W = X - W.ex_act(2.0) - else if(istype(X,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = X - if(istype(H.shoes,/obj/item/clothing/shoes/magboots)) - var/obj/item/clothing/shoes/magboots/M = H.shoes - if(M.magpulse) - step_towards(H,src) //step just once with magboots - continue - step_towards(H,src) //step twice - step_towards(H,src) + X.singularity_pull(src, STAGE_FIVE) if(defer_powernet_rebuild != 2) defer_powernet_rebuild = 0 diff --git a/code/setup.dm b/code/setup.dm index e5c8242477..38836d54d5 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -909,3 +909,11 @@ var/list/be_special_flags = list( #define Sp_HOLDVAR "holdervar" ///////WIZ END///////// + +//singularity defines +#define STAGE_ONE 1 +#define STAGE_TWO 3 +#define STAGE_THREE 5 +#define STAGE_FOUR 7 +#define STAGE_FIVE 9 +#define STAGE_SUPER 11 diff --git a/icons/effects/352x352.dmi b/icons/effects/352x352.dmi new file mode 100644 index 0000000000..de15d61dd9 Binary files /dev/null and b/icons/effects/352x352.dmi differ diff --git a/icons/mob/bats.dmi b/icons/mob/bats.dmi new file mode 100644 index 0000000000..7446693507 Binary files /dev/null and b/icons/mob/bats.dmi differ diff --git a/icons/mob/screen1_construct.dmi b/icons/mob/screen1_construct.dmi new file mode 100644 index 0000000000..67a37ccd73 Binary files /dev/null and b/icons/mob/screen1_construct.dmi differ diff --git a/icons/obj/magic_terror.dmi b/icons/obj/magic_terror.dmi deleted file mode 100644 index 025e164ccd..0000000000 Binary files a/icons/obj/magic_terror.dmi and /dev/null differ diff --git a/icons/obj/narsie.dmi b/icons/obj/narsie.dmi index 940b094176..73df7c31d1 100644 Binary files a/icons/obj/narsie.dmi and b/icons/obj/narsie.dmi differ diff --git a/icons/obj/rift.dmi b/icons/obj/rift.dmi new file mode 100644 index 0000000000..85b7510386 Binary files /dev/null and b/icons/obj/rift.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 859c6e7681..c3fdbcdb33 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/turf/space.dmi b/icons/turf/space.dmi index 9f15fbbe63..30d0d1428a 100644 Binary files a/icons/turf/space.dmi and b/icons/turf/space.dmi differ diff --git a/maps/exodus-2.dmm b/maps/exodus-2.dmm index 3259c44b42..e0ba7543f2 100644 --- a/maps/exodus-2.dmm +++ b/maps/exodus-2.dmm @@ -1756,7 +1756,7 @@ "HN" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/snacks/chips,/turf/unsimulated/beach/sand,/area/beach) "HO" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/turf/unsimulated/beach/sand,/area/beach) "HP" = (/obj/item/weapon/beach_ball,/turf/unsimulated/beach/sand,/area/beach) -"HQ" = (/obj/structure/bed/chair,/turf/unsimulated/beach/sand,/area/beach) +"HQ" = (/obj/structure/bed/chair{dir = 1},/obj/item/clothing/glasses/thermal/plain/monocle,/obj/item/clothing/head/pirate,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/skipjack/station) "HR" = (/mob/living/simple_animal/crab/Coffee,/turf/unsimulated/beach/sand,/area/beach) "HS" = (/obj/item/clothing/head/collectable/paper,/turf/unsimulated/beach/sand,/area/beach) "HT" = (/turf/unsimulated/floor{icon_state = "sandwater"},/area/beach) @@ -2090,7 +2090,7 @@ "Oj" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/turf/simulated/shuttle/plating,/area/shuttle/skipjack/station) "Ok" = (/obj/machinery/atmospherics/pipe/simple/visible,/obj/item/weapon/crowbar,/turf/simulated/shuttle/plating,/area/shuttle/skipjack/station) "Ol" = (/obj/machinery/portable_atmospherics/hydroponics,/turf/simulated/shuttle/plating,/area/shuttle/skipjack/station) -"Om" = (/obj/structure/bed/chair{dir = 1},/obj/item/clothing/glasses/thermal/plain/monocle,/obj/item/clothing/head/pirate,/turf/simulated/shuttle/floor{icon_state ="floor4"},/area/shuttle/skipjack/station) +"Om" = (/obj/structure/bed/chair,/obj/effect/landmark{name = "endgame_exit"},/turf/unsimulated/beach/sand,/area/beach) "On" = (/turf/simulated/shuttle/floor{icon_state = "floor7"},/area/shuttle/skipjack/station) "Oo" = (/obj/machinery/atmospherics/pipe/manifold/visible{dir = 8},/turf/simulated/shuttle/plating,/area/shuttle/skipjack/station) "Op" = (/obj/machinery/body_scanconsole,/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/skipjack/station) @@ -2121,6 +2121,7 @@ "OO" = (/obj/structure/table/rack,/obj/item/weapon/gun/launcher/crossbow,/obj/item/stack/rods{amount = 10},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/skipjack/station) "OP" = (/obj/structure/table/rack,/obj/item/weapon/grenade/empgrenade,/obj/item/weapon/grenade/flashbang,/obj/item/weapon/grenade/spawnergrenade,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/skipjack/station) "OQ" = (/obj/structure/table/rack,/obj/item/clothing/suit/space/vox/stealth,/obj/item/clothing/head/helmet/space/vox/stealth,/obj/item/clothing/shoes/magboots/vox,/obj/item/clothing/gloves/yellow/vox,/obj/item/clothing/glasses/thermal/plain/monocle,/obj/item/clothing/under/vox/vox_robes,/turf/unsimulated/floor{tag = "icon-asteroid"; icon_state = "asteroid"},/area/syndicate_mothership{name = "\improper Raider Base"}) +"OR" = (/obj/effect/landmark{name = "endgame_exit"},/turf/unsimulated/beach/sand,/area/beach) "OS" = (/obj/machinery/door/airlock/command{name = "Thunderdome Administration"; req_access = list(102)},/turf/unsimulated/floor{icon_state = "floor"},/area/tdome) "OT" = (/obj/machinery/door/airlock/command{name = "Thunderdome Administration"; req_access = list(102)},/turf/simulated/floor,/area/tdome) "OU" = (/obj/structure/table/woodentable,/obj/machinery/chemical_dispenser/bar_soft/full,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/wizard_station) @@ -2301,7 +2302,7 @@ mumumumumumumumumuaMaMaMaMaMKPKVKUKRaMaMaMaMaMaMaMaMaMaMaMaMaMKPKVKUKRaMaMaMaMmt mumumumumumumumumuaMaMaMaMaMKYKQKQKZaMaMaMKYaMaMaMaMaMKZaMaMaMKYKQKQKZaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHNODgDgDgDgEoDaCPCPCPCPCPCPCPCPCPDGDSDSLaEqLbLcCNEtDVDVDVEwExDVDVEyCNaMaMaMaMaMaMaMEAEBEBAtNQEaNREbNPAtEBEBBVaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM mumumumumumuaMaMaMaMaMaMaMaMMHLfMLMHaMaMaMLgMOMIMIMIMJLkaMaMaMMHNnLmMHaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHDgECNuDrEDEEEFEGEGEGEHEHEHEIEJLnELEMEHEHEHCNCNCNNvDVDVEwEPEQExERESCNaMaMaMaMaMaMaMETEVEVBVDYDZEaNtNsEAEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM mumumumumumuaMaMaMaMaMaMaMaMLsMpMwLsaMaMKYLsLrMmMnMoLrLsKZaMaMLsMGMFLsaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHDgDgDgEDEXEYEZEZEZEZEHFaFbFcFdFeFfFgFbFaEHCNCNCNCNCNCNNrFiNqFkERESCNaMaMaMaMaMaMaMaMaMaMETATEUEUEUATEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM -mumumumumumuaMaMaMaMaMaMaMaMLsOoOuLsaMaMLgMfMaOhOmOhMaMeLkaMaMLsOfOgLsaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHFlDgEDEXEYEYEZEZEZEZEHFbFmFnFdFeFfFnFoFbEHFpFqFrFsFtCNDVFhFkDVDVEwFuaMaMaMaMaMaMaMaMaMaMaMETEVEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM +mumumumumumuaMaMaMaMaMaMaMaMLsOoOuLsaMaMLgMfMaOhHQOhMaMeLkaMaMLsOfOgLsaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHFlDgEDEXEYEYEZEZEZEZEHFbFmFnFdFeFfFnFoFbEHFpFqFrFsFtCNDVFhFkDVDVEwFuaMaMaMaMaMaMaMaMaMaMaMETEVEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM mumumumumumuaMaMaMaMaMaMaMaMLyOeLpLoLpLpLXOdMaMaMaMaMaOcLyLpLpLoLpNBLXaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHDgEDEXEYEYEYEZEZEZEZEHFvFbFvFdFeFfFvFbFvEHFwDVDVDVDVMqDVDVDVDVDVFyFzaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM mumumumumumuaMaMaMaMaMaMaMaMLsMsMrMuMtMvLsOLMaMaMaMaMaOLLsMyMxMBMzMsLsaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHEDEXEYEYEYEYEYEYEYEYEHFAFbFbFdFeFfFbFbFBEHFCFDFEFFMCCNDVDVDVDVDVFHFIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM mumumuaMaMaMaMaMaMaMaMaMaMaMLsMsMDMDMDMELsOwOGOHMbOwOGOHLsOKMDMDMKMsLsaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHAHAHAHAHAHAHAHAHAHAHAHEHFJFKFKFdFeFfFLFLFMEHFNFOFPFQFRCNFSFTFUFVFWFXCNaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM @@ -2323,13 +2324,13 @@ mumumumuaMaMaMaMaMaMaMaMaMaMmumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmt mumumumuaMaMaMaMaMaMaMaMmumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHFAEHOSEHHbHbHbHbHbEHGBGCGCGCGCGCGCHcGCGCGCGCGCGDGBEHHbHbHbHbHbEHOSEHFBEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYGYGYGYGYGYGYGYGYHhGYGYGYGYGYGU mumumumuaMaMaMaMaMaMaMmumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHFJHiFbEHGzGzGzGzGzEHGxGxGxGxGxGxOTHlOTGxGxGxGxGyGxEHGEGEGEGEGEEHFbHnFMEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYGYGYGYGYGYGYGYGYHdGYGYGYGYGYGU mumuaMaMaMaMaMaMaMaMaMaMmumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHFbEHEHEHEHEHEHEHHoHpHpHpHpHpHqHrHoHpHpHpHpHsHoEHEHEHEHEHEHEHFbEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYHtHhGYGYGYGYGYGYGYGYGYGYGYGYGYGU -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHFbFbFeFeFeFeFeEHHoHoHuHoHuHoHoHvHwHoHuHoHuHxHoEHFeFeFeFeFeFbFbEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGU -mtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHEHEHEHEHFeMNHoHoHoHyHyHyHoHoHoHyHyHyHyHyHoMNFeEHEHEHEHEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYHzHAGYGYGYGYGYGYGYGYGYGYGYGYGU -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHHBHBHBHCHDHEHFHoHGHHHIHJHKHLHMEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYHNHOGYGYGYHtGYHPGYGYGYGYGYGYGU -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHEHEHEHEHEHEHEHEHEHEHEHEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGU +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHFbFbFeFeFeFeFeEHHoHoHuHoHuHoHoHvHwHoHuHoHuHxHoEHFeFeFeFeFeFbFbEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYORORGYGYGYGYGYGYGYGYGYGYGYGYGU +mtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHEHEHEHEHFeMNHoHoHoHyHyHyHoHoHoHyHyHyHyHyHoMNFeEHEHEHEHEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYORHzHAORGYGYGYGYGYGYGYGYGYGYGYGU +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHHBHBHBHCHDHEHFHoHGHHHIHJHKHLHMEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYORHNHOORGYGYHtGYHPGYGYGYGYGYGYGU +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHEHEHEHEHEHEHEHEHEHEHEHEHEHEHEHEHaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYORORGYGYGYGYGYGYGYGYGYGYGYGYGU aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYHhGYGYGYGYGYGYGYGYGYGYGYGYGYHdGYGYGU aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYHtHhGYGYGYGYGYGYGYGYGYGYGYGYHhGYGYGU -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYGYGYHQGYHQGYHQGYHRGYGYGYGYGYGU +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYGYGYGYGYOmGYOmGYOmGYHRGYGYGYGYGYGU aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUGYGYGYHSGYGYGYGYGYGYGYGYGYGYGYGYGYGYGYGU aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMGUHTHTHTHTHTHTHTHTHTHTHTHTHTHTHTHTHTHTHTGU aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMHUHVHVHVHVHVHVHVHVHVHVHVHVHVHVHVHVHVHVHVHU diff --git a/maps/exodus-5.dmm b/maps/exodus-5.dmm index 22732bb0b8..239b3b0674 100644 --- a/maps/exodus-5.dmm +++ b/maps/exodus-5.dmm @@ -815,7 +815,7 @@ "pI" = (/obj/structure/disposalpipe/segment,/turf/unsimulated/mask,/area/mine/unexplored) "pJ" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock"},/obj/machinery/door/airlock/research{name = "Temporary Storage Loading"; req_access = list(65)},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/eva) "pK" = (/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/isolation_c) -"pL" = (/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/isolation_b) +"pL" = (/obj/structure/table,/obj/effect/landmark{name = "bluespacerift"},/turf/simulated/floor{icon_state = "cafeteria"; dir = 2},/area/outpost/research/kitchen) "pM" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock"},/obj/machinery/door/airlock/glass_mining{name = "Expedition Prep"; req_access = list(65)},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable/blue{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor,/area/outpost/research/dock) "pN" = (/obj/item/device/radio/intercom{freerange = 1; frequency = 1459; name = "Station Intercom (General)"; pixel_x = -27},/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/isolation_c) "pO" = (/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/isolation_a) @@ -1600,6 +1600,9 @@ "EN" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor/plating/airless,/area/space) "EO" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/obj/structure/grille,/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/outpost/mining_main/east_hall) "EP" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/floor,/area/outpost/mining_main/east_hall) +"EQ" = (/obj/effect/landmark{name = "bluespacerift"},/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/anomaly_analysis) +"ER" = (/obj/effect/landmark{name = "bluespacerift"},/turf/simulated/floor/plating,/area/outpost/research/chemistry) +"ES" = (/obj/effect/landmark{name = "bluespacerift"},/turf/simulated/floor{icon_state = "vault"; dir = 5},/area/outpost/research/isolation_b) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -1647,11 +1650,11 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababiLiKiKiJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababaJaJaJaJaJababababababababiMeOeOdHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaabababababababaJiNiOiPaJaJaJaJaJaJaGaGaGaGiQiRaGaGaGaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaababababababababaJjbiTiUiViWaKaKaKiSaiiZjfaiiYeOaijaiZaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaababababababababaJjbERiUiViWaKaKaKiSaiiZjfaiiYeOaijaiZaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaabababababaAaAaAaAjpjhiTjrjgjdjdjdmraijojmjnjkjljijjjcaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaababababaAaAaNaOaAaJaJaJaJaKaKaLaLaMaiaiaiaiaIaHaiaiaiaGazazazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahagafaaaaaaaaaaababababababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaababababaAaBaCaDaEaFasaraqapawavauataiakajaiaoanaiamayaUaxamazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabkbmblaeaaaaaaabababababababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaababababaAaWbobpaAbnbAbgbBbAbybxaubzaibubwbvbrbqbtbsbjbhbhfJazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabkbmblaeaaaaaaabababababababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaababababaAaWbobpaAbnbAbgbBbAbybxaubzaibubwbvbrbqbtbsbjpLbhfJazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPaRaQaSaeaaaaabababababababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaabababaAaWaTbiaAaVbgbfbebdbbbcbbbaaGaGaGaGaZaYaiaXbjbhbhdvazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadkdldleubWbVblaeaaaaababababababababababababababababababababababababababababababababababababababababababababababababababababaeaeaeaeaeaeaeaeaeabababaAaWcmcnaAclbYbXcabZcccbcecdcgcfchaGcjcickamamiXamjeazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadQdRdSdTbDbCbEaeaeababababababababababababababababababababababababababababababababababababababababababababababababababalalalaeaeaeaeaeaeaeaebTaGaGaGaGaGaGbUaGaGaGaGbFaGaGbIbHbGbLbKbJaGbPbObNbMbRbSbQbRazalalaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -1663,7 +1666,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaefcfdfeffeUeTeWeVeYeXfaeZfbcrabababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaeAereseyezeresevewepeqeneneneoeoeoeoeoeSeReQePeOeNeMaGfqfpeJeIaieHeFeGeDeEeCaGaGeBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahSfchbfcfEfEdJheeUcrekhdcrfahccrabababababababababababababababababababababababababababababababababababababababababababababababdXaaaaaaaaaagMgPgQgNgOgTgQgRgSgWgXgUgVhaeogYgZgweogxeRgBgAgDgCgEaGgGgFgIgHaiaigJaiaiaieReRgKeBeBeBeBgLeBeBeBeBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaegugvfEgsgtfEcpgqeTgrgpgocrcrcrcrcrcrababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaaaagngbgcgcgcgcgdgegfggghgigjgkeoglgmfVfUfTeIfXfWeReRfYfweReReJeIgafZfKfLfIlzeReRfMeBfOfPeBfNfRfSfQeBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaeiCiBhRfEgtiDffiGeUiFcriIiHcrhOhKbCiEcrabababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaagngQgQgQhWgQhVhUgQibgXhZiahYeogmhXihigijiiidicifieilieimieikieieieirisitiuinioipiqixiyiziAivhAiweBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaeiCiBhRfEgtiDffiGeUiFcriIiHcrhOhKbCiEcrabababababababababababababababababababababababababababababababababababababababababababababababaaaaaaaagngQgQgQhWgQhVhUgQibgXhZiahYeogmhXihigijiiidicifieilieimieikieieieirisitiuinioipiqixiyiziAivEQiweBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaeaeababcrfFhLhPhQhRhThNeThOafbChKcrhOhLhKhMcrababababababababababababababababababababababababababababababababababalalalalalalababababababkDkEaaaaaahrgQgQhihjhfhggRhhhnhohphqhkeohlhmhHeoeohGhGhFhuhEhxhuhJhuhIhwhwhwhwhxhuhvhththseBhChDeBhBhzhAhyeBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaecrcrcrcrcrcrfGeUnWhLeUgqnUhOhOeVeYiIcrhOcpeknVcrababababababababababababababababababababababababababababababababalalalgygygygyalalalababsEgygyaaaaaaaanwereseynwnwnwnwnwpMnwnununueopJeonSnTnRhGsesjhunMnKnLnInJnGnHkmkmkmnFhunEnChtnBlulululurVnznyfQeBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaecrmPeUhRoEcriCoDiBcrgrcroGoHoFcrbClLiFmOcpeleUcrabababababababababababababababababababababababababababababababalalgygygygygygygygyalalabgygyaaaaaaaaaaaaaaaeaekBohogoflnoeodocqOoanZnYqhoqorosrIrfrvhuopokollDkmnGoiojkmkmmghuoCozhtoBoAovoulueBeBeBeBeBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -1674,7 +1677,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababababababababcrkPcrkNekkOhTkMcphKcreUekcrkLkJkJkKcradababababababababababababababababababababababababababababalalgygygyprgygygygygygygygygygyaeaaaaaaaaaaaaaeaeaekBkBkCkFkBkBkGlhkGkBkIeoowpBpCkokpmFkshukVkvkwkYkukzkAlckyknkmhuhththtababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababababababababcrkPcrhTcpbVljeUekgocrkPcrcrhOeUkJkKlkadababababababababababababababababababababababababababababalpSpTgypUpSpQgygygygygygygygygytjaaaaaaaaaaaetjtjtjgygyqdqeqfkBmllglfkBlieogylrlAhGkSkTkTkUlUkWkXkUlVkZlalblXleldlbababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababcrkPcrcrcrcrcrcrcrcrcrkPcrphbCeUbCkKpiadababababababababababababababababababababababababababababalpSgygygypSpQgygygygygygygyqwqCpjsWsWsWsWsWsWpoqwqCgygygygygykBplpnpmkBpkgygygygyhGpApxpykUpwpupvkUptpqpslbpppEpDlbababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLaaaaaaaaaaqLababababababababababababababcrkPkPkPkPkPkPkPkPkPkPkPcrhOeUiFeUiEcradababababababababababababababababababababababababababababalgygygygyqMqNgygygygygygygygyrWqPqPqPqPqPqPqPqPrWgygygygygygykBpHrUkGkBpFrigygygyhGpXkTkTkUpWpOtykUpRpLtllbpNpKsIlbababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLaaaaaaaaaaqLababababababababababababababcrkPkPkPkPkPkPkPkPkPkPkPcrhOeUiFeUiEcradababababababababababababababababababababababababababababalgygygygyqMqNgygygygygygygygyrWqPqPqPqPqPqPqPqPrWgygygygygygykBpHrUkGkBpFrigygygyhGpXkTkTkUpWpOtykUpREStllbpNpKsIlbababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLababababababababababababababababcrcrcrcrcrcrcrcrcrcrcrcrcrcrmjrOoMcrcradababababababababababababababababababababababababababababalgygygygygygygygygygygygygyqwqCrdrerererererereqwqCgygygygygygypBrSpCpdpcpeoVoVoVoToUsyoZkUoWoOoPkUoNoRoSlboQpbpalbabababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLabababababababababababababababababababababababababababadadadcrkJkJeUcradadababababababababababababababababababababababababababababalpSpTgygygygygygygygygygyaaaaaaaaaaaaaaaaalalalalalalalalgygygygygygypBpgpCgygyalhGhGhGhGkUkUkUkUkUpfpfpflblblblblbabababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLabababababababababababababababababababababababababababadadadcroJoIoJcradabababababababababababababababababababababababababababababalpSgygygygygygygygygygygyaaaaaaaaaaaaaaaaalalalababababalalalalalalalgyjHgygyalalababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/sound/effects/cascade.ogg b/sound/effects/cascade.ogg new file mode 100644 index 0000000000..9de7b01b0c Binary files /dev/null and b/sound/effects/cascade.ogg differ diff --git a/sound/effects/supermatter.ogg b/sound/effects/supermatter.ogg new file mode 100644 index 0000000000..83081a5e9b Binary files /dev/null and b/sound/effects/supermatter.ogg differ diff --git a/sound/weapons/heavysmash.ogg b/sound/weapons/heavysmash.ogg new file mode 100644 index 0000000000..609e20fd96 Binary files /dev/null and b/sound/weapons/heavysmash.ogg differ diff --git a/sound/weapons/rapidslice.ogg b/sound/weapons/rapidslice.ogg new file mode 100644 index 0000000000..a428c18efe Binary files /dev/null and b/sound/weapons/rapidslice.ogg differ diff --git a/sound/weapons/spiderlunge.ogg b/sound/weapons/spiderlunge.ogg new file mode 100644 index 0000000000..fc2d91e079 Binary files /dev/null and b/sound/weapons/spiderlunge.ogg differ