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..f313094b556 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -129,4 +129,11 @@
#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
\ 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 ea68cec863d..b0a76ac7f7b 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..0ccfdb5bda0 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -127,7 +127,7 @@
if(!checkWirePower())
if(user) user << "\blue The connected wire doesn't have enough current."
return
- for(var/obj/machinery/singularity/singulo in world)
+ for(var/obj/singularity/singulo in world)
if(singulo.z == z)
singulo.target = src
icon_state = "[icontype]1"
@@ -136,7 +136,7 @@
proc/Deactivate(mob/user = null)
- for(var/obj/machinery/singularity/singulo in world)
+ for(var/obj/singularity/singulo in world)
if(singulo.target == src)
singulo.target = null
icon_state = "[icontype]0"
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/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..8d4cdbfc45c 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -1,27 +1,15 @@
//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
density = 1
layer = 6
- light_range = 6
+ 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?
@@ -36,86 +24,95 @@ 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
-/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/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 +122,13 @@ 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
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 +138,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 +149,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 +161,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 +173,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
@@ -194,134 +191,46 @@ 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
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
+ allowed_size = STAGE_FOUR
if(2000 to INFINITY)
- allowed_size = 9
+ allowed_size = STAGE_FIVE
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
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 +242,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 +280,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 +298,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 +314,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
@@ -432,7 +328,7 @@ var/global/list/uneatable = list(
return 1
-/obj/machinery/singularity/proc/toxmob()
+/obj/singularity/proc/toxmob()
var/toxrange = 10
var/toxdamage = 4
var/radiation = 15
@@ -448,7 +344,7 @@ var/global/list/uneatable = list(
return
-/obj/machinery/singularity/proc/mezzer()
+/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 +352,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..bc75e077e27 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()
. = ..()
diff --git a/paradise.dme b/paradise.dme
index b94388425b1..92e739d195b 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"