diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 600c98f3ef6..de3d9544d22 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -191,4 +191,8 @@ obj/machinery/atmospherics/proc/check_connect_types_construction(obj/machinery/a ..() /obj/machinery/atmospherics/proc/can_crawl_through() - return 1 \ No newline at end of file + return 1 + +/obj/machinery/atmospherics/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + Destroy() \ No newline at end of file diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index df4737591a9..19b3f99029a 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -129,4 +129,12 @@ #define LIGHT_COLOR_WHITE "#FFFFFF" -#define RESIZE_DEFAULT_SIZE 1 \ No newline at end of file +#define RESIZE_DEFAULT_SIZE 1 + +//singularity defines +#define STAGE_ONE 1 +#define STAGE_TWO 3 +#define STAGE_THREE 5 +#define STAGE_FOUR 7 +#define STAGE_FIVE 9 +#define STAGE_SIX 11 //From supermatter shard \ No newline at end of file diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index bb5f8b10b4c..671bf0540b8 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -8,7 +8,7 @@ return // seems legit. // Things you might plausibly want to follow - if((ismob(A) && A != src) || istype(A,/obj/machinery/bot) || istype(A,/obj/machinery/singularity)) + if((ismob(A) && A != src) || istype(A,/obj/machinery/bot) || istype(A,/obj/singularity)) ManualFollow(A) // Otherwise jump @@ -19,7 +19,7 @@ if(client.buildmode) build_click(src, client.buildmode, params, A) return - if(world.time <= next_move) + if(world.time <= next_move) return var/list/modifiers = params2list(params) diff --git a/code/controllers/garbage.dm b/code/controllers/garbage.dm index f488ea92aa0..7a33bd6725b 100644 --- a/code/controllers/garbage.dm +++ b/code/controllers/garbage.dm @@ -10,10 +10,10 @@ var/datum/garbage_collector/garbageCollector set name = "(GC) Hard Del List" set desc = "List types that are hard del()'d by the GC." set category = "Debug" - + if(!check_rights(R_DEBUG)) return - + if(!gc_hard_del_types || !gc_hard_del_types.len) usr << "No hard del()'d types found." @@ -45,7 +45,6 @@ var/datum/garbage_collector/garbageCollector var/remainingCollectionPerTick = GC_COLLECTIONS_PER_TICK var/remainingForceDelPerTick = GC_FORCE_DEL_PER_TICK var/collectionTimeScope = world.timeofday - GC_COLLECTION_TIMEOUT - if(narsie_cometh) return //don't even fucking bother, its over. while(queue.len && --remainingCollectionPerTick >= 0) var/refID = queue[1] var/destroyedAtTime = queue[refID] diff --git a/code/datums/spells/construct_spells.dm b/code/datums/spells/construct_spells.dm index ab010295b5d..c81bb108d54 100644 --- a/code/datums/spells/construct_spells.dm +++ b/code/datums/spells/construct_spells.dm @@ -99,3 +99,19 @@ invocation_type = "none" proj_lifespan = 10 max_targets = 6 + +/obj/effect/proc_holder/spell/wizard/targeted/smoke/disable + name = "Paralysing Smoke" + desc = "This spell spawns a cloud of paralysing smoke." + + school = "conjuration" + charge_max = 200 + clothes_req = 0 + invocation = "none" + invocation_type = "none" + range = -1 + include_user = 1 + cooldown_min = 20 //25 deciseconds reduction per rank + + smoke_spread = 3 + smoke_amt = 10 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 71c8f732d48..6681a1b3c6e 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -452,3 +452,12 @@ its easier to just keep the beam vertical. return 1 else return 0 + +/atom/proc/singularity_act() + return + +/atom/proc/singularity_pull() + return + +/atom/proc/narsie_act() + return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a9b2677aa89..2c63514ce5d 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -257,11 +257,6 @@ return src.master.attack_hand(a, b, c) return -///////////////////////////// -// SINGULOTH PULL REFACTOR -///////////////////////////// -/atom/movable/proc/canSingulothPull(var/obj/machinery/singularity/singulo) - return 1 /atom/movable/proc/water_act(var/volume, var/temperature, var/source) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins) return 1 diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 504962771af..a8ebc32995d 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -136,7 +136,7 @@ var/list/sacrificed = list() cultist_count += 1 if(cultist_count >= 9) cult_log("THE CULT HAS SUMMONED NAR'SIE. GGNORE") - new /obj/machinery/singularity/narsie/large(src.loc) + new /obj/singularity/narsie/large(src.loc) if(ticker.mode.name == "cult") ticker.mode:eldergod = 0 return diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 12760904359..7b3066160e7 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -186,7 +186,7 @@ rcd light flash thingy on matter drain set name = "Overload Machine" set category = "Malfunction" if (istype(M, /obj/machinery)) - if(istype(M, /obj/machinery/singularity) || istype(M,/obj/machinery/field_generator) || istype(M, /obj/machinery/singularity/narsie)) + if(istype(M,/obj/machinery/field_generator)) src << "This machine can not be overloaded due to a firewall." return for(var/datum/AI_Module/small/overload_machine/overload in current_modules) @@ -214,7 +214,7 @@ rcd light flash thingy on matter drain set name = "Override Machine" set category = "Malfunction" if (istype(M, /obj/machinery)) - if(istype(M, /obj/machinery/singularity) || istype(M,/obj/machinery/field_generator) || istype(M, /obj/machinery/singularity/narsie)) + if(istype(M,/obj/machinery/field_generator)) src << "This machine can not be overloaded due to a firewall." return for(var/datum/AI_Module/small/override_machine/override in current_modules) diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index d4c1841a507..80b7aa10e81 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -132,7 +132,7 @@ /obj/effect/rend/New() spawn(50) - new /obj/machinery/singularity/narsie/wizard(get_turf(src)) + new /obj/singularity/narsie/wizard(get_turf(src)) del(src) return return diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 58b0077d31b..0a1f21dd430 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -219,3 +219,20 @@ else U << "\red Creation failed!: \black The soul stone is empty! Go kill someone!" return + +/proc/makeNewConstruct(var/mob/living/simple_animal/construct/ctype, var/mob/target, var/mob/stoner = null, cultoverride = 0) + var/mob/living/simple_animal/construct/newstruct = new ctype(get_turf(target)) + newstruct.faction |= "\ref[stoner]" + newstruct.key = target.key + if(stoner && iscultist(stoner) || cultoverride) + if(ticker.mode.name == "cult") + ticker.mode:add_cultist(newstruct.mind) + else + ticker.mode.cult+=newstruct.mind + ticker.mode.update_cult_icons_added(newstruct.mind) + if(stoner && iswizard(stoner)) + newstruct << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." + else if(stoner && iscultist(stoner)) + newstruct << "You are still bound to serve the cult, follow their orders and help them complete their goals at all costs." + else newstruct << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." + newstruct.cancel_camera() \ No newline at end of file diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index a94177cee68..cf6f6717765 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -293,3 +293,6 @@ Made a proc so this is not repeated 14 (or more) times.*/ return 0 else return 1 + +/proc/iswizard(mob/living/M as mob) + return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.wizards) \ No newline at end of file diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index 916ae1a23af..292e3eacbe0 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -105,9 +105,10 @@ -#define SCREWED 32 - -/obj/machinery/singularity_beacon //not the best place for it but it's a hack job anyway -- Urist +//////////////////////////////////////// +//Singularity beacon +//////////////////////////////////////// +/obj/machinery/power/singularity_beacon name = "ominous beacon" desc = "This looks suspicious..." icon = 'icons/obj/singularity.dmi' @@ -115,108 +116,86 @@ anchored = 0 density = 1 - layer = MOB_LAYER - 0.1 //so people can't hide it and it's REALLY OBVIOUS + layer = MOB_LAYER - 0.2 //so people can't hide it and it's REALLY OBVIOUS stat = 0 - var/active = 0 //It doesn't use up power, so use_power wouldn't really suit it + var/active = 0 var/icontype = "beacon" - var/obj/structure/cable/attached = null - proc/Activate(mob/user = null) - if(!checkWirePower()) - if(user) user << "\blue The connected wire doesn't have enough current." - return - for(var/obj/machinery/singularity/singulo in world) - if(singulo.z == z) - singulo.target = src - icon_state = "[icontype]1" - active = 1 - if(user) user << "\blue You activate the beacon." +/obj/machinery/power/singularity_beacon/proc/Activate(mob/user = null) + if(surplus() < 1500) + if(user) user << "The connected wire doesn't have enough current." + return + for(var/obj/singularity/singulo in world) + if(singulo.z == z) + singulo.target = src + icon_state = "[icontype]1" + active = 1 + machines |= src + if(user) + user << "You activate the beacon." - proc/Deactivate(mob/user = null) - for(var/obj/machinery/singularity/singulo in world) - if(singulo.target == src) - singulo.target = null - icon_state = "[icontype]0" - active = 0 - if(user) user << "\blue You deactivate the beacon." +/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user = null) + for(var/obj/singularity/singulo in world) + if(singulo.target == src) + singulo.target = null + icon_state = "[icontype]0" + active = 0 + if(user) + user << "You deactivate the beacon." - attack_ai(mob/user as mob) +/obj/machinery/power/singularity_beacon/attack_ai(mob/user as mob) + return + + +/obj/machinery/power/singularity_beacon/attack_hand(var/mob/user as mob) + if(anchored) + return active ? Deactivate(user) : Activate(user) + else + user << "You need to screw the beacon to the floor first!" return - attack_hand(var/mob/user as mob) - if(stat & SCREWED) - return active ? Deactivate(user) : Activate(user) - else - user << "\red You need to screw the beacon to the floor first!" +/obj/machinery/power/singularity_beacon/attackby(obj/item/weapon/W as obj, mob/user as mob, params) + if(istype(W,/obj/item/weapon/screwdriver)) + if(active) + user << "You need to deactivate the beacon first!" return - - attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(istype(W,/obj/item/weapon/screwdriver)) - if(active) - user << "\red You need to deactivate the beacon first!" - return - - if(stat & SCREWED) - stat &= ~SCREWED - anchored = 0 - user << "\blue You unscrew the beacon from the floor." - attached = null - return - else - var/turf/T = loc - if(isturf(T) && !T.intact) - attached = locate() in T - if(!attached) - user << "This device must be placed over an exposed cable." - return - stat |= SCREWED - anchored = 1 - user << "\blue You screw the beacon to the floor and attach the cable." - return - ..() - return - - - Destroy() - if(active) Deactivate() - ..() - - /* - * Added for a simple way to check power. Verifies that the beacon - * is connected to a wire, the wire is part of a powernet (that part's - * sort of redundant, since all wires either join or create one when placed) - * and that the powernet has at least 1500 power units available for use. - * Doesn't use them, though, just makes sure they're there. - * - QualityVan, Aug 11 2012 - */ - proc/checkWirePower() - if(!attached) - return 0 - var/datum/powernet/PN = attached.get_powernet() - if(!PN) - return 0 - if(PN.avail < 1500) - return 0 - return 1 - - process() - if(!active) + if(anchored) + anchored = 0 + user << "You unscrew the beacon from the floor." + disconnect_from_network() return else - if(!checkWirePower()) - Deactivate() - return + if(!connect_to_network()) + user << "This device must be placed over an exposed cable." + return + anchored = 1 + user << "You screw the beacon to the floor and attach the cable." + return + ..() + return -/obj/machinery/singularity_beacon/syndicate +/obj/machinery/power/singularity_beacon/Destroy() + if(active) + Deactivate() + ..() + +//stealth direct power usage +/obj/machinery/power/singularity_beacon/process() + if(!active) + return PROCESS_KILL + else + if(surplus() > 1500) + add_load(1500) + else + Deactivate() + +/obj/machinery/power/singularity_beacon/syndicate icontype = "beaconsynd" - icon_state = "beaconsynd0" - -#undef SCREWED - + icon_state = "beaconsynd0" \ No newline at end of file diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index a040e460b2c..e20010d0c2a 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -4,6 +4,12 @@ unacidable = 1 var/i_attached//Added for possible image attachments to objects. For hallucinations and the like. +/obj/effect/overlay/singularity_act() + return + +/obj/effect/overlay/singularity_pull() + return + /obj/effect/overlay/beam//Not actually a projectile, just an effect. name="beam" icon='icons/effects/beam.dmi' diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index e91c10432e3..728c4528da5 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -698,3 +698,9 @@ for(var/obj/item/A in world) if(A.type == type && !A.blood_overlay) A.blood_overlay = image(I) + +/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) + else ..() \ No newline at end of file diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index d7967f6ccd2..69adcfb3ae9 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -170,7 +170,7 @@ if(current && current.can_use()) var/list/seen = current.can_see() var/list/names = list() - for(var/obj/machinery/singularity/S in seen) // god help you if you see more than one + for(var/obj/singularity/S in seen) // god help you if you see more than one if(S.name in names) names[S.name]++ dat += "[S.name] ([names[S.name]])" diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm index 628a6ee8bba..146be0a57ed 100644 --- a/code/game/objects/items/devices/radio/beacon.dm +++ b/code/game/objects/items/devices/radio/beacon.dm @@ -13,7 +13,7 @@ emagged = 1 syndicate = 1 user << "\blue The This beacon now only be locked on to by emagged teleporters!" - + /obj/item/device/radio/beacon/hear_talk() return @@ -52,7 +52,7 @@ /obj/item/device/radio/beacon/syndicate/attack_self(mob/user as mob) if(user) user << "\blue Locked In" - new /obj/machinery/singularity_beacon/syndicate( user.loc ) + new /obj/machinery/power/singularity_beacon/syndicate( user.loc ) playsound(src, 'sound/effects/pop.ogg', 100, 1, 1) del(src) return diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm index e2b85f1069a..e0608af5e06 100644 --- a/code/game/objects/items/weapons/chrono_eraser.dm +++ b/code/game/objects/items/weapons/chrono_eraser.dm @@ -246,6 +246,9 @@ /obj/effect/chrono_field/Move() return +/obj/effect/chrono_field/singularity_act() + return + /obj/effect/chrono_field/ex_act() return diff --git a/code/game/objects/items/weapons/grenades.dm b/code/game/objects/items/weapons/grenades.dm index 43acc8df89b..dae50bb302a 100644 --- a/code/game/objects/items/weapons/grenades.dm +++ b/code/game/objects/items/weapons/grenades.dm @@ -349,7 +349,7 @@ /obj/item/weapon/grenade/clusterbuster/apocalypse name = "Apocalypse Bomb" desc = "No matter what, do not EVER use this." - payload = /obj/machinery/singularity + payload = /obj/singularity /obj/item/weapon/grenade/clusterbuster/ultima name = "Earth Shattering Kaboom" @@ -456,6 +456,6 @@ var/atom/A = new payload(loc) if(istype(A,/obj/item/weapon/grenade)) A:prime() - if(istype(A,/obj/machinery/singularity)) // I can't emphasize enough how much you should never use this grenade + if(istype(A,/obj/singularity)) // I can't emphasize enough how much you should never use this grenade A:energy = 200 del src diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index c81ff7d8dbc..b06ea04e671 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -41,7 +41,7 @@ investigate_log("has become a singularity. Caused by [user.key]","singulo") user << "\red The Bluespace interfaces of the two devices catastrophically malfunction!" del(W) - var/obj/machinery/singularity/singulo = new /obj/machinery/singularity (get_turf(src)) + var/obj/singularity/singulo = new /obj/singularity (get_turf(src)) singulo.energy = 300 //should make it a bit bigger~ message_admins("[key_name_admin(user)] detonated a bag of holding") log_game("[key_name(user)] detonated a bag of holding") @@ -61,6 +61,11 @@ crit_fail = 1 icon_state = "brokenpack" + singularity_act(current_size) + var/dist = max((current_size - 2),1) + explosion(src.loc,(dist),(dist*2),(dist*4)) + return + /obj/item/weapon/storage/backpack/santabag name = "Santa's Gift Bag" @@ -300,7 +305,7 @@ desc = "A duffelbag designed to hold bananas and bike horns." icon_state = "duffel-clown" item_state = "duffel-clown" - + //ERT backpacks. /obj/item/weapon/storage/backpack/ert name = "emergency response team backpack" @@ -330,7 +335,7 @@ name = "emergency response team medical backpack" desc = "A spacious backpack with lots of pockets, worn by medical members of a Nanotrasen Emergency Response Team." icon_state = "ert_medical" - + //Janitorial /obj/item/weapon/storage/backpack/ert/janitor name = "emergency response team janitor backpack" diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 31ff44b64f1..d3dbd5d9045 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -245,3 +245,16 @@ a { user << browse(dat, "window=mtcomputer") user.set_machine(src) onclose(user, "mtcomputer") + +/obj/singularity_act() + ex_act(1.0) + if(src && isnull(gc_destroyed)) + qdel(src) + return 2 + +/obj/singularity_pull(S, current_size) + if(anchored) + if(current_size >= STAGE_FIVE) + anchored = 0 + step_towards(src,S) + else step_towards(src,S) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 3ed779f7189..e14c9024d77 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -81,4 +81,7 @@ icon_state = "lattice[dir_sum]" return - \ No newline at end of file + +/obj/structure/lattice/singularity_pull(S, current_size) + if(current_size >= STAGE_FOUR) + Destroy() \ No newline at end of file diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index d217daad32a..0ef6f109b4e 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -95,6 +95,10 @@ var/global/wcColored /obj/structure/window/meteorhit() destroy() +/obj/structure/window/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + destroy() + /obj/structure/window/CheckExit(var/atom/movable/O, var/turf/target) if(istype(O) && O.checkpass(PASSGLASS)) return 1 diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index eb9478c2613..5a2fcbe719c 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -615,4 +615,22 @@ var/list/wood_icons = list("wood","wood-broken") P.x = src.x P.y = src.y P.z = src.z - P.loc = src \ No newline at end of file + P.loc = src + +/turf/simulated/floor/singularity_pull(S, current_size) + if(current_size == STAGE_THREE) + if(prob(30)) + make_plating() + else if(current_size == STAGE_FOUR) + if(prob(50)) + make_plating() + else if(current_size >= STAGE_FIVE) + if(prob(70)) + make_plating() + else + if(prob(50)) + ReplaceWithLattice() + +/turf/simulated/floor/narsie_act() + if(prob(20)) + ChangeTurf(/turf/simulated/floor/engine/cult) \ No newline at end of file diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index 21ae02b8758..08d1458f726 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -96,6 +96,8 @@ name = "engraved floor" icon_state = "cult" +/turf/simulated/floor/engine/cult/narsie_act() + return /turf/simulated/floor/engine/n20/New() ..() @@ -108,6 +110,14 @@ assume_air(adding) +/turf/simulated/floor/engine/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(30)) + make_plating() + else + if(prob(30)) + ReplaceWithLattice() + /turf/simulated/floor/engine/vacuum name = "vacuum floor" icon_state = "engine" diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 482979bc0e2..c0d85564de8 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -478,3 +478,16 @@ else return attack_hand(user) return + +/turf/simulated/wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(50)) + dismantle_wall() + return + if(current_size == STAGE_FOUR) + if(prob(30)) + dismantle_wall() + +/turf/simulated/wall/narsie_act() + if(prob(20)) + ChangeTurf(/turf/simulated/wall/cult) \ No newline at end of file diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm index ca934731723..77edc3c2828 100644 --- a/code/game/turfs/simulated/walls_misc.dm +++ b/code/game/turfs/simulated/walls_misc.dm @@ -4,6 +4,9 @@ icon_state = "cult" walltype = "cult" +/turf/simulated/wall/cult/narsie_act() + return + /turf/simulated/wall/rust name = "rusted wall" desc = "A rusted metal wall." diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index bf79c84e7c0..93a7f289eb4 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -332,4 +332,9 @@ //Finally, CHECKING FOR FALSE WALLS if it isn't damaged else if(!d_state) return attack_hand(user) - return \ No newline at end of file + return + +/turf/simulated/wall/r_wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(30)) + dismantle_wall() \ No newline at end of file diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 9d021fa6da2..87ab3a48ae0 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -341,3 +341,6 @@ proc/setup_map_transitions() //listamania S.transition = directions[Z_NORTH] S.Assign_Destination() + +/turf/space/singularity_act() + return \ No newline at end of file diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index a8fdfaeebd9..e861ac1786a 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -406,4 +406,14 @@ if(!src || !T) return 0 return abs(src.x - T.x) + abs(src.y - T.y) -//////////////////////////////////////////////////// \ No newline at end of file +//////////////////////////////////////////////////// + +/turf/singularity_act() + if(intact) + for(var/obj/O in contents) //this is for deleting things like wires contained in the turf + if(O.level != 1) + continue + if(O.invisibility == 101) + O.singularity_act() + ChangeTurf(/turf/space) + return(2) \ No newline at end of file diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index c9872de0a1b..bf381efbd9e 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1109,7 +1109,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that spawn(30) for(var/obj/machinery/the_singularitygen/G in world) if(G.anchored) - var/obj/machinery/singularity/S = new /obj/machinery/singularity(get_turf(G), 50) + var/obj/singularity/S = new /obj/singularity(get_turf(G), 50) spawn(0) del(G) S.energy = 1750 diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm index e2e004f215c..bb1a6b56480 100644 --- a/code/modules/admin/verbs/possess.dm +++ b/code/modules/admin/verbs/possess.dm @@ -2,7 +2,7 @@ set name = "Possess Obj" set category = null - if(istype(O,/obj/machinery/singularity)) + if(istype(O,/obj/singularity)) if(config.forbid_singulo_possession) usr << "It is forbidden to possess singularities." return diff --git a/code/modules/awaymissions/mission_code/academy.dm b/code/modules/awaymissions/mission_code/academy.dm index 16af3141647..9ae1cdb223e 100644 --- a/code/modules/awaymissions/mission_code/academy.dm +++ b/code/modules/awaymissions/mission_code/academy.dm @@ -23,15 +23,15 @@ //Academy Items -/obj/machinery/singularity/academy +/obj/singularity/academy dissipate = 0 move_self = 0 grav_pull = 1 -/obj/machinery/singularity/academy/admin_investigate_setup() +/obj/singularity/academy/admin_investigate_setup() return -/obj/machinery/singularity/academy/process() +/obj/singularity/academy/process() eat() if(prob(1)) mezzer() diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm index dee5ae20af6..af73c27667d 100644 --- a/code/modules/awaymissions/mission_code/stationCollision.dm +++ b/code/modules/awaymissions/mission_code/stationCollision.dm @@ -21,7 +21,7 @@ //Gateroom gets its own APC specifically for the gate /area/awaymission report_alerts = 0 - + /area/awaymission/gateroom //Library, medbay, storage room @@ -162,21 +162,22 @@ var/sc_safecode5 = "[rand(0,9)]" /* * Modified Nar-Sie */ -/obj/machinery/singularity/narsie/sc_Narsie +/obj/singularity/narsie/sc_Narsie desc = "Your body becomes weak and your feel your mind slipping away as you try to comprehend what you know can't be possible." move_self = 0 //Contianed narsie does not move! grav_pull = 0 //Contained narsie does not pull stuff in! + var/uneatable = list(/turf/space, /obj/effect/overlay, /atom/movable/lighting_overlay, /mob/living/simple_animal/construct) //Override this to prevent no adminlog runtimes and admin warnings about a singularity without containment -/obj/machinery/singularity/narsie/sc_Narsie/admin_investigate_setup() +/obj/singularity/narsie/sc_Narsie/admin_investigate_setup() return -/obj/machinery/singularity/narsie/sc_Narsie/process() +/obj/singularity/narsie/sc_Narsie/process() eat() if(prob(25)) mezzer() -/obj/machinery/singularity/narsie/sc_Narsie/consume(var/atom/A) +/obj/singularity/narsie/sc_Narsie/consume(var/atom/A) if(is_type_in_list(A, uneatable)) return 0 if (istype(A,/mob/living)) @@ -197,5 +198,5 @@ var/sc_safecode5 = "[rand(0,9)]" T.ChangeTurf(/turf/space) return -/obj/machinery/singularity/narsie/sc_Narsie/ex_act() +/obj/singularity/narsie/sc_Narsie/ex_act() return \ No newline at end of file diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index efc19265e43..eb81621c628 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -54,4 +54,10 @@ ) #else color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .) - #endif \ No newline at end of file + #endif + +/atom/movable/lighting_overlay/singularity_act() + return + +/atom/movable/lighting_overlay/singularity_pull() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b4424b3fc66..7adb3db6607 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1501,18 +1501,6 @@ W.add_fingerprint(src) - -/mob/living/carbon/human/canSingulothPull(var/obj/machinery/singularity/singulo) - if(!..()) - return 0 - - if(istype(shoes,/obj/item/clothing/shoes/magboots)) - var/obj/item/clothing/shoes/magboots/M = shoes - if(M.magpulse) - return 0 - return 1 - - //Putting a couple of procs here that I don't know where else to dump. //Mostly going to be used for Vox and Vox Armalis, but other human mobs might like them (for adminbuse). @@ -1695,6 +1683,29 @@ return threatcount +/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 == "Clown") + gain = rand(-300, 300) + investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! + 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) && unEquip(hand)) + step_towards(hand, src) + src << "\The [S] pulls \the [hand] from your grip!" + apply_effect(current_size * 3, IRRADIATE) + if(mob_negates_gravity()) + return + ..() + /mob/living/carbon/human/canBeHandcuffed() return 1 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d6c4a282aea..5ed6b60eceb 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -841,6 +841,21 @@ return "You can't fit into that vent." +/mob/living/singularity_act() + var/gain = 20 + investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! + gib() + return(gain) + +/mob/living/singularity_pull(S) + step_towards(src,S) + +/mob/living/narsie_act() + if(client) + makeNewConstruct(/mob/living/simple_animal/construct/harvester, src, null, 1) + spawn_dust() + gib() + return /atom/movable/proc/do_attack_animation(atom/A) var/pixel_x_diff = 0 @@ -897,4 +912,7 @@ return initial(pixel_x) /mob/living/proc/get_standard_pixel_y_offset(lying = 0) - return initial(pixel_y) \ No newline at end of file + return initial(pixel_y) + +/mob/living/proc/spawn_dust() + new /obj/effect/decal/cleanable/ash(loc) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index a3a3a73df05..9b579c4dadb 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -127,6 +127,8 @@ M.show_message("\red [user] gently taps [src] with [O]. ") +/mob/living/simple_animal/construct/narsie_act() + return /////////////////Juggernaut/////////////// @@ -301,6 +303,29 @@ +/////////////////////////////Harvester///////////////////////// + +/mob/living/simple_animal/construct/harvester + name = "Harvester" + real_name = "Harvester" + desc = "A harbinger of Nar-Sie's enlightenment. It'll be all over soon." + icon = 'icons/mob/mob.dmi' + icon_state = "harvester" + icon_living = "harvester" + maxHealth = 60 + health = 60 + melee_damage_lower = 1 + melee_damage_upper = 5 + attacktext = "prods" + speed = 0 + environment_smash = 1 + see_in_dark = 7 + attack_sound = 'sound/weapons/tap.ogg' + construct_spells = list(/obj/effect/proc_holder/spell/wizard/targeted/smoke/disable) + +/mob/living/simple_animal/construct/harvester/Process_Spacemove(var/check_drift = 0) + return 1 + ////////////////Powers////////////////// diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 12e8d071136..0792f04bf8e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -704,7 +704,7 @@ var/list/slot_equipment_priority = list( \ namecounts[name] = 1 creatures[name] = O - if(istype(O, /obj/machinery/singularity)) + if(istype(O, /obj/singularity)) var/name = "Singularity" if (names.Find(name)) namecounts[name]++ diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 5dfa7fe46db..d6d1e3de046 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -492,3 +492,10 @@ var/list/intents = list("help","disarm","grab","harm") lname = name lname = "[lname] " M << "[lname][follow][message]" + +/proc/notify_ghosts(var/message, var/ghost_sound = null) //Easy notification of ghosts. + for(var/mob/dead/observer/O in player_list) + if(O.client) + O << "[message]" + if(ghost_sound) + O << sound(ghost_sound) \ No newline at end of file diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 4efe44ee90d..a9e7049c9d1 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -199,6 +199,10 @@ qdel(src) return +/obj/structure/cable/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + Destroy() + // the cable coil object, used for laying cable #define MAXCOIL 30 diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 851bbe20eb2..01150e5c416 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -346,7 +346,7 @@ field_generator power level display //I want to avoid using global variables. spawn(1) var/temp = 1 //stops spam - for(var/obj/machinery/singularity/O in machines) + for(var/obj/singularity/O in machines) if(O.last_warning && temp) if((world.time - O.last_warning) > 50) //to stop message-spam temp = 0 diff --git a/code/modules/power/singularity/generator.dm b/code/modules/power/singularity/generator.dm index 1a88f444d24..ef3fb514b52 100644 --- a/code/modules/power/singularity/generator.dm +++ b/code/modules/power/singularity/generator.dm @@ -26,7 +26,7 @@ message_admins("[admin_message] at [x],[y],[z]",1) investigate_log("[admin_message] at [x],[y],[z]","singulo") - new /obj/machinery/singularity/(T, 50) + new /obj/singularity/(T, 50) if(src) del(src) /obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user, params) diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm new file mode 100644 index 00000000000..9498a78d1c9 --- /dev/null +++ b/code/modules/power/singularity/narsie.dm @@ -0,0 +1,159 @@ +/obj/singularity/narsie //Moving narsie to a child object of the singularity so it can be made to function differently. --NEO + name = "Nar-sie's Avatar" + 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? + grav_pull = 5 //How many tiles out do we pull? + consume_range = 6 //How many tiles out do we eat + +/obj/singularity/narsie/large + name = "Nar-Sie" + icon = 'icons/obj/narsie.dmi' + // Pixel stuff centers Narsie. + pixel_x = -236 + pixel_y = -256 + current_size = 12 + move_self = 1 //Do we move on our own? + grav_pull = 10 + consume_range = 12 //How many tiles out do we eat + +/obj/singularity/narsie/large/New() + ..() + world << "NAR-SIE HAS RISEN" + world << pick(sound('sound/hallucinations/im_here1.ogg'), sound('sound/hallucinations/im_here2.ogg')) + + var/area/A = get_area(src) + if(A) + notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.") + + narsie_spawn_animation() + + sleep(70) + if(emergency_shuttle && emergency_shuttle.can_call()) + emergency_shuttle.call_evac() + emergency_shuttle.launch_time = 0 // Cannot recall + + +/obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob) + if(!(src in view())) + user << "Your soul is too far away." + return + makeNewConstruct(/mob/living/simple_animal/construct/harvester, user, null, 1) + new /obj/effect/effect/sleep_smoke(user.loc) + + +/obj/singularity/narsie/process() + eat() + if(!target || prob(5)) + pickcultist() + move() + if(prob(25)) + mezzer() + + +/obj/singularity/narsie/Bump(atom/A)//you dare stand before a god?! + godsmack(A) + return + +/obj/singularity/narsie/Bumped(atom/A) + godsmack(A) + return + +/obj/singularity/narsie/proc/godsmack(var/atom/A) + if(istype(A,/obj/)) + var/obj/O = A + O.ex_act(1.0) + if(O) qdel(O) + + else if(isturf(A)) + var/turf/T = A + T.ChangeTurf(/turf/simulated/floor/engine/cult) + + +/obj/singularity/narsie/mezzer() + for(var/mob/living/carbon/M in oviewers(8, src)) + if(M.stat == CONSCIOUS) + 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/singularity/narsie/consume(var/atom/A) + A.narsie_act() + + +/obj/singularity/narsie/ex_act() //No throwing bombs at it either. --NEO + return + + +/obj/singularity/narsie/proc/pickcultist() //Narsie rewards his cultists with being devoured first, then picks a ghost to follow. --NEO + var/list/cultists = list() + var/list/noncultists = list() + for(var/mob/living/carbon/food in living_mob_list) //we don't care about constructs or cult-Ians or whatever. cult-monkeys are fair game i guess + var/turf/pos = get_turf(food) + if(pos.z != src.z) + continue + + if(iscultist(food)) + cultists += food + else + noncultists += food + + if(cultists.len) //cultists get higher priority + acquire(pick(cultists)) + return + + if(noncultists.len) + acquire(pick(noncultists)) + return + + //no living humans, follow a ghost instead. + for(var/mob/dead/observer/ghost in player_list) + if(!ghost.client) + continue + var/turf/pos = get_turf(ghost) + if(pos.z != src.z) + continue + cultists += ghost + if(cultists.len) + acquire(pick(cultists)) + return + + +/obj/singularity/narsie/proc/acquire(var/mob/food) + target << "NAR-SIE HAS LOST INTEREST IN YOU" + target = food + if(ishuman(target)) + target << "NAR-SIE HUNGERS FOR YOUR SOUL" + else + target << "NAR-SIE HAS CHOSEN YOU TO LEAD HIM TO HIS NEXT MEAL" + +//Wizard narsie +/obj/singularity/narsie/wizard + grav_pull = 0 + +/obj/singularity/narsie/wizard/eat() + set background = BACKGROUND_ENABLED +// if(defer_powernet_rebuild != 2) +// defer_powernet_rebuild = 1 + for(var/atom/X in orange(consume_range,src)) + if(isturf(X) || istype(X, /atom/movable)) + consume(X) +// if(defer_powernet_rebuild != 2) +// defer_powernet_rebuild = 0 + return + + +/obj/singularity/narsie/proc/narsie_spawn_animation() + icon = 'icons/obj/narsie_spawn_anim.dmi' + dir = SOUTH + move_self = 0 + flick("narsie_spawn_anim",src) + sleep(11) + move_self = 1 + icon = initial(icon) diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm index 88c87486c3f..540aee0b692 100644 --- a/code/modules/power/singularity/particle_accelerator/particle.dm +++ b/code/modules/power/singularity/particle_accelerator/particle.dm @@ -41,7 +41,7 @@ if (A) if(ismob(A)) toxmob(A) - if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/machinery/singularity/))) + if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/))) A:energy += energy /* else if( istype(A,/obj/effect/rust_particle_catcher) ) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index f320bb64f6c..4c07ffdbb43 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -1,19 +1,8 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 -// Added spess ghoasts/cameras to this so they don't add to the lag. - N3X -var/global/narsie_cometh = 0 -var/global/list/uneatable = list( - /turf/space, - /obj/effect/overlay, - /atom/movable/lighting_overlay, - /mob/dead, - /mob/camera, - /mob/new_player - ) - -/obj/machinery/singularity/ - name = "Gravitational Singularity" - desc = "A Gravitational Singularity." +/obj/singularity + name = "gravitational singularity" + desc = "A gravitational singularity." icon = 'icons/obj/singularity.dmi' icon_state = "singularity_s1" anchored = 1 @@ -21,7 +10,6 @@ var/global/list/uneatable = list( layer = 6 light_range = 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? @@ -36,86 +24,96 @@ var/global/list/uneatable = list( 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/last_warning + var/consumedSupermatter = 0 //If the singularity has eaten a supermatter shard and can go to stage six -/obj/machinery/singularity/New(loc, var/starting_energy = 50, var/temp = 0) +/obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0) //CARN: admin-alert for chuckle-fuckery. admin_investigate_setup() src.energy = starting_energy - if(temp) - spawn(temp) - del(src) ..() - for(var/obj/machinery/singularity_beacon/singubeacon in machines) + processing_objects.Add(src) + for(var/obj/machinery/power/singularity_beacon/singubeacon in world) if(singubeacon.active) target = singubeacon break return +/obj/singularity/Destroy() + processing_objects.Remove(src) + ..() -/obj/machinery/singularity/attack_hand(mob/user as mob) +/obj/singularity/Move(atom/newloc, direct) + if(current_size >= STAGE_FIVE || check_turfs_in(direct)) + last_failed_movement = 0//Reset this because we moved + return ..() + else + last_failed_movement = direct + return 0 + + +/obj/singularity/attack_hand(mob/user as mob) consume(user) return 1 - -/obj/machinery/singularity/blob_act(severity) +/obj/singularity/blob_act(severity) return - -/obj/machinery/singularity/ex_act(severity) +/obj/singularity/ex_act(severity) switch(severity) if(1.0) - if(prob(25)) - investigate_log("has been destroyed by an explosion.","singulo") - del(src) + if(current_size <= STAGE_TWO) + investigate_log("has been destroyed by a heavy explosion.","singulo") + qdel(src) return else - energy += 50 - if(2.0 to 3.0) - energy += round((rand(20,60)/2),1) - return + energy -= round(((energy+1)/2),1) + if(2.0) + energy -= round(((energy+1)/3),1) + if(3.0) + energy -= round(((energy+1)/4),1) return -/obj/machinery/singularity/bullet_act(obj/item/projectile/P) + +/obj/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) +/obj/singularity/Bump(atom/A) consume(A) return -/obj/machinery/singularity/Bumped(atom/A) +/obj/singularity/Bumped(atom/A) consume(A) return -/obj/machinery/singularity/process() - eat() - dissipate() - check_energy() - - if(current_size >= 3) +/obj/singularity/process() + if(current_size >= STAGE_TWO) move() pulse() if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit event() + eat() + dissipate() + check_energy() + return -/obj/machinery/singularity/attack_ai() //to prevent ais from gibbing themselves when they click on one. +/obj/singularity/attack_ai() //to prevent ais from gibbing themselves when they click on one. return -/obj/machinery/singularity/proc/admin_investigate_setup() +/obj/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") -/obj/machinery/singularity/proc/dissipate() +/obj/singularity/proc/dissipate() if(!dissipate) return if(dissipate_track >= dissipate_delay) @@ -125,13 +123,15 @@ var/global/list/uneatable = list( dissipate_track++ -/obj/machinery/singularity/proc/expand(var/force_size = 0) +/obj/singularity/proc/expand(var/force_size = 0) var/temp_allowed_size = src.allowed_size if(force_size) temp_allowed_size = force_size + if(temp_allowed_size >= STAGE_SIX && !consumedSupermatter) + temp_allowed_size = STAGE_FIVE switch(temp_allowed_size) - if(1) - current_size = 1 + if(STAGE_ONE) + current_size = STAGE_ONE icon = 'icons/obj/singularity.dmi' icon_state = "singularity_s1" pixel_x = 0 @@ -141,8 +141,8 @@ 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 + 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 + current_size = STAGE_TWO icon = 'icons/effects/96x96.dmi' icon_state = "singularity_s3" pixel_x = -32 @@ -152,9 +152,9 @@ var/global/list/uneatable = list( dissipate_delay = 5 dissipate_track = 0 dissipate_strength = 5 - if(5) + if(STAGE_THREE) if((check_turfs_in(1,2))&&(check_turfs_in(2,2))&&(check_turfs_in(4,2))&&(check_turfs_in(8,2))) - current_size = 5 + current_size = STAGE_THREE icon = 'icons/effects/160x160.dmi' icon_state = "singularity_s5" pixel_x = -64 @@ -164,9 +164,9 @@ var/global/list/uneatable = list( dissipate_delay = 4 dissipate_track = 0 dissipate_strength = 20 - if(7) + if(STAGE_FOUR) if((check_turfs_in(1,3))&&(check_turfs_in(2,3))&&(check_turfs_in(4,3))&&(check_turfs_in(8,3))) - current_size = 7 + current_size = STAGE_FOUR icon = 'icons/effects/224x224.dmi' icon_state = "singularity_s7" pixel_x = -96 @@ -176,8 +176,8 @@ 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 + if(STAGE_FIVE)//this one also lacks a check for gens because it eats everything + current_size = STAGE_FIVE icon = 'icons/effects/288x288.dmi' icon_state = "singularity_s9" pixel_x = -128 @@ -185,6 +185,15 @@ var/global/list/uneatable = list( grav_pull = 10 consume_range = 4 dissipate = 0 //It cant go smaller due to e loss + if(STAGE_SIX) //This only happens if a stage 5 singulo consumes a supermatter shard. + current_size = STAGE_SIX + icon = 'icons/effects/352x352.dmi' + icon_state = "singularity_s11" + pixel_x = -160 + pixel_y = -160 + grav_pull = 15 + consume_range = 5 + dissipate = 0 if(current_size == allowed_size) investigate_log("grew to size [current_size]","singulo") return 1 @@ -194,134 +203,55 @@ var/global/list/uneatable = list( return 0 -/obj/machinery/singularity/proc/check_energy() +/obj/singularity/proc/check_energy() if(energy <= 0) investigate_log("collapsed.","singulo") - del(src) + qdel(src) return 0 + if(energy > 2999 && !consumedSupermatter) + energy = 2000 switch(energy)//Some of these numbers might need to be changed up later -Mport if(1 to 199) - allowed_size = 1 + allowed_size = STAGE_ONE if(200 to 499) - allowed_size = 3 + allowed_size = STAGE_TWO if(500 to 999) - allowed_size = 5 + allowed_size = STAGE_THREE if(1000 to 1999) - allowed_size = 7 - if(2000 to INFINITY) - allowed_size = 9 + allowed_size = STAGE_FOUR + if(2000 to 2999) + allowed_size = STAGE_FIVE + if(3000 to INFINITY) + allowed_size = STAGE_SIX if(current_size != allowed_size) expand() return 1 -/obj/machinery/singularity/proc/eat() - //set background = 1 - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 1 - // Let's just make this one loop. +/obj/singularity/proc/eat() + set background = BACKGROUND_ENABLED for(var/atom/X in orange(grav_pull,src)) - // N3X: Move this up here since get_dist is slow. - if(is_type_in_list(X, uneatable)) continue - if(!X.simulated) continue - var/dist = get_dist(X, src) - - // Movable atoms only - if(dist > consume_range && istype(X, /atom/movable)) - if(canPull(X)) - step_towards(X,src) - /* - 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))) + var/obj/singularity/S = src + if(dist > consume_range) + X.singularity_pull(S, current_size) + else if(dist <= consume_range) consume(X) - - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 0 return -// Singulo optimization: -// Jump out whenever we've made a decision. -/obj/machinery/singularity/proc/canPull(var/atom/movable/A) - // If we're big enough, stop checking for this and that and JUST EAT. - if(current_size >= 9) - return 1 - else - if(A && !A:anchored) - if(A.canSingulothPull(src)) - return 1 - return 0 - -/obj/machinery/singularity/proc/consume(var/atom/A) - var/gain = 0 - if(is_type_in_list(A, uneatable)) - return 0 - if(!A.simulated) - return 0 - if (istype(A,/mob/living))//Mobs get gibbed - var/mob/living/M = A - gain = 20 - if(istype(M,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(H.mind) - switch(H.mind.assigned_role) - if("Station Engineer","Chief Engineer") - gain = 100 - if("Clown") - gain = rand(-300, 300) // HONK - M.gib() - // Why - 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)) - return - 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 - - if((teleport_del) && (!istype(A, /obj/machinery)))//Going to see if it does not lag less to tele items over to Z 2 - qdel(A) - else - A.ex_act(1.0) - if(A) - qdel(A) - gain = 2 - else if(isturf(A)) - var/turf/T = A - if(istype(T,/turf/simulated/wall)) - var/turf/simulated/wall/W = T - W.del_suppress_resmoothing=1 // Reduce lag from wallsmoothing. - 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 +/obj/singularity/proc/consume(var/atom/A) + var/gain = A.singularity_act(current_size) src.energy += gain + if(istype(A, /obj/machinery/power/supermatter) && !consumedSupermatter) + desc = "[initial(desc)] It glows fiercely with inner fire." + name = "supermatter-charged [initial(name)]" + consumedSupermatter = 1 + light_range = 10 return -/obj/machinery/singularity/proc/move(var/force_move = 0) +/obj/singularity/proc/move(var/force_move = 0) if(!move_self) return 0 @@ -333,37 +263,24 @@ var/global/list/uneatable = list( if(target && prob(60)) movement_dir = get_dir(src,target) //moves to a singulo beacon, if there is one - if(current_size >= 9)//The superlarge one does not care about things in its way - spawn(0) - step(src, movement_dir) - spawn(1) - step(src, movement_dir) - return 1 - else if(check_turfs_in(movement_dir)) - last_failed_movement = 0//Reset this because we moved - spawn(0) - step(src, movement_dir) - return 1 - else - last_failed_movement = movement_dir - return 0 + step(src, movement_dir) -/obj/machinery/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0) +/obj/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0) if(!direction) return 0 var/steps = 0 if(!step) switch(current_size) - if(1) + if(STAGE_ONE) steps = 1 - if(3) + if(STAGE_TWO) steps = 3//Yes this is right - if(5) + if(STAGE_THREE) steps = 3 - if(7) + if(STAGE_FOUR) steps = 4 - if(9) + if(STAGE_FIVE) steps = 5 else steps = step @@ -384,12 +301,12 @@ var/global/list/uneatable = list( dir2 = 1 dir3 = 2 var/turf/T2 = T - for(var/j = 1 to steps) + for(var/j = 1 to steps-1) T2 = get_step(T2,dir2) if(!isturf(T2)) return 0 turfs.Add(T2) - for(var/k = 1 to steps) + for(var/k = 1 to steps-1) T = get_step(T,dir3) if(!isturf(T)) return 0 @@ -402,7 +319,7 @@ var/global/list/uneatable = list( return 1 -/obj/machinery/singularity/proc/can_move(var/turf/T) +/obj/singularity/proc/can_move(var/turf/T) if(!T) return 0 if((locate(/obj/machinery/containment_field) in T)||(locate(/obj/machinery/shieldwall) in T)) @@ -418,7 +335,7 @@ var/global/list/uneatable = list( return 1 -/obj/machinery/singularity/proc/event() +/obj/singularity/proc/event() var/numb = pick(1,2,3,4,5,6) switch(numb) if(1)//EMP @@ -427,12 +344,16 @@ var/global/list/uneatable = list( toxmob() if(4)//Stun mobs who lack optic scanners mezzer() + if(5,6) //Sets all nearby mobs on fire + if(current_size < STAGE_SIX) + return 0 + combust_mobs() else return 0 return 1 -/obj/machinery/singularity/proc/toxmob() +/obj/singularity/proc/toxmob() var/toxrange = 10 var/toxdamage = 4 var/radiation = 15 @@ -448,7 +369,15 @@ var/global/list/uneatable = list( return -/obj/machinery/singularity/proc/mezzer() +/obj/singularity/proc/combust_mobs() + for(var/mob/living/carbon/C in orange(20, src)) + C.visible_message("[C]'s skin bursts into flame!", \ + "You feel an inner fire as your skin is suddenly covered in fire!") + C.adjust_fire_stacks(5) + C.IgniteMob() + return + +/obj/singularity/proc/mezzer() for(var/mob/living/carbon/M in oviewers(8, src)) if(istype(M, /mob/living/carbon/brain)) //Ignore brains continue @@ -456,202 +385,33 @@ var/global/list/uneatable = list( 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!" - return - M << "\red You look directly into The [src.name] and feel weak." + if(istype(H.glasses, /obj/item/clothing/glasses/meson)) + var/obj/item/clothing/glasses/meson/MS = H.glasses + if(MS.vision_flags == SEE_TURFS) + H << "You look directly into the [src.name], good thing you had your protective eyewear on!" + return + 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) + M.visible_message("[M] stares blankly at the [src.name]!", \ + "You look directly into the [src.name] and feel weak.") return -/obj/machinery/singularity/proc/emp_area() +/obj/singularity/proc/emp_area() empulse(src, 8, 10) return -/obj/machinery/singularity/proc/pulse() +/obj/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 R.receive_pulse(energy) return - - -/obj/machinery/singularity/narsie //Moving narsie to a child object of the singularity so it can be made to function differently. --NEO - gender = NEUTER - name = "Nar-sie's Avatar" - 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? - 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/large - name = "Nar-Sie" - icon = 'icons/obj/narsie.dmi' - // Pixel stuff centers Narsie. - pixel_x = -236 - pixel_y = -256 - current_size = 12 - grav_pull = 10 - consume_range = 12 - - -/obj/machinery/singularity/narsie/large/New() - ..() - world << "NAR-SIE HAS RISEN" - spawn_animation() - if(emergency_shuttle && emergency_shuttle.can_call()) - emergency_shuttle.call_evac() - emergency_shuttle.launch_time = 0 // Cannot recall - narsie_cometh = 1 - - -/obj/machinery/singularity/narsie/proc/spawn_animation() - icon = 'icons/obj/narsie_spawn_anim.dmi' - src.dir = SOUTH - move_self = 0 - flick("narsie_spawn_anim", src) - sleep(11) //0.5 longer than the animation. - move_self = 1 - icon = initial(icon) - - -/obj/machinery/singularity/narsie/process() - eat() - if(!target || prob(5)) - pickcultist() - move() - if(prob(25)) - mezzer() - - -/obj/machinery/singularity/narsie/Bump(atom/A)//you dare stand before a god?! - godsmack(A) - return - -/obj/machinery/singularity/narsie/Bumped(atom/A) - godsmack(A) - return - -/obj/machinery/singularity/narsie/proc/godsmack(var/atom/A) - if(istype(A,/obj/)) - var/obj/O = A - O.ex_act(1.0) - if(O) qdel(O) - - else if(isturf(A)) - var/turf/T = A - T.ChangeTurf(/turf/simulated/floor/engine/cult) - - -/obj/machinery/singularity/narsie/mezzer() - for(var/mob/living/carbon/M in oviewers(8, src)) - if(M.stat == CONSCIOUS) - if(!iscultist(M)) - M << "\red You feel your sanity crumble away in an instant as you gaze upon [src.name]..." - M.apply_effect(3, STUN) - - -/obj/machinery/singularity/narsie/consume(var/atom/A) - if(is_type_in_list(A, uneatable)) - return 0 - if(!A.simulated) - 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 - qdel(O) - else if(isturf(A)) - var/turf/T = A - if(istype(T,/turf/simulated/wall)) - var/turf/simulated/wall/W = T - W.del_suppress_resmoothing=1 // Reduce lag from wallsmoothing. - 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/ex_act() //No throwing bombs at it either. --NEO - return - -/obj/machinery/singularity/narsie/proc/pickcultist() //Narsie rewards it's cultists with being devoured first, then picks a ghost to follow. --NEO - var/list/cultists = list() - for(var/datum/mind/cult_nh_mind in ticker.mode.cult) - 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 - //If there was living cultists, it picks one to follow. - for(var/mob/living/carbon/human/food in living_mob_list) - if(food.stat) - continue - var/turf/pos = get_turf(food) - if(pos.z != src.z) - continue - cultists += food - if(cultists.len) - acquire(pick(cultists)) - return - //no living cultists, pick a living human instead. - for(var/mob/dead/observer/ghost in player_list) - if(!ghost.client) - continue - var/turf/pos = get_turf(ghost) - if(pos.z != src.z) - continue - cultists += ghost - if(cultists.len) - acquire(pick(cultists)) - 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" - target = food - if(ishuman(target)) - target << "\red NAR-SIE HUNGERS FOR YOUR SOUL" - else - target << "\red NAR-SIE HAS CHOSEN YOU TO LEAD THEM TO THEIR NEXT MEAL" - -//Wizard narsie - -/obj/machinery/singularity/narsie/wizard - grav_pull = 0 - -/obj/machinery/singularity/narsie/wizard/eat() - //set background = 1 - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 1 - for(var/atom/X in orange(consume_range,src)) - if(isturf(X) || istype(X, /atom/movable)) - consume(X) - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 0 - return +/obj/singularity/singularity_act() + var/gain = (energy/2) + var/dist = max((current_size - 2),1) + explosion(src.loc,(dist),(dist*2),(dist*4)) + qdel(src) + return(gain) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index b378282ca27..556e172050b 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -72,6 +72,9 @@ icon_state = "emitter" damage = 30 +/obj/item/projectile/beam/emitter/singularity_pull() + return //don't want the emitters to miss + /obj/item/projectile/lasertag name = "laser tag beam" icon_state = "omnilaser" diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 4bb71244045..1aef00f1965 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -478,6 +478,11 @@ else return ..(mover, target, height, air_group) + + singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + Destroy() + // virtual disposal object // travels through pipes in lieu of actual items // contents will be items flushed by the disposal @@ -682,6 +687,10 @@ expel(H, T, 0) ..() + singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + Destroy() + // returns the direction of the next pipe object, given the entrance dir // by default, returns the bitmask of remaining directions proc/nextdir(var/fromdir) diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index f0a80a866ee..92264de763a 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -86,6 +86,7 @@ var/obj/item/device/radio/radio var/debug = 0 + var/uneatable = list(/turf/space, /obj/effect/overlay, /atom/movable/lighting_overlay, /mob/dead, /mob/camera, /mob/new_player) /obj/machinery/power/supermatter/New() . = ..() @@ -244,6 +245,17 @@ damage += Proj.damage * config_bullet_energy return 0 +/obj/machinery/power/supermatter/singularity_act() + var/gain = 100 + investigate_log("Supermatter shard consumed by singularity.","singulo") + message_admins("Singularity has consumed a supermatter shard and can now become stage six.") + visible_message("[src] is consumed by the singularity!") + for(var/mob/M in mob_list) + M << 'sound/effects/supermatter.ogg' //everyone goan know bout this + M << "A horrible screeching fills your ears, and a wave of dread washes over you..." + qdel(src) + return(gain) + /obj/machinery/power/supermatter/attack_robot(mob/user as mob) if(Adjacent(user)) return attack_hand(user) diff --git a/icons/effects/352x352.dmi b/icons/effects/352x352.dmi new file mode 100644 index 00000000000..86b40959d56 Binary files /dev/null and b/icons/effects/352x352.dmi differ diff --git a/paradise.dme b/paradise.dme index 2d679fe3a4f..d73f4d8fc86 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1512,6 +1512,7 @@ #include "code\modules\power\singularity\field_generator.dm" #include "code\modules\power\singularity\generator.dm" #include "code\modules\power\singularity\investigate.dm" +#include "code\modules\power\singularity\narsie.dm" #include "code\modules\power\singularity\singularity.dm" #include "code\modules\power\singularity\particle_accelerator\particle.dm" #include "code\modules\power\singularity\particle_accelerator\particle_accelerator.dm" diff --git a/sound/effects/supermatter.ogg b/sound/effects/supermatter.ogg new file mode 100644 index 00000000000..83081a5e9bf Binary files /dev/null and b/sound/effects/supermatter.ogg differ