Files
Bubberstation/code/game/objects/effects/anomalies.dm
Cheridan a97355fda9 Some Anomaly Changes (#25228)
Pyroclastic anomalies make player-controlled adult slimes.
Tweaks announcement/spawn of anomalies some. Flux anomalies are super dangerous and are now announced ahead of time, and pyroclastic anomalies are somewhat less devastating so they're given some time before announcing, like gravitational ones.
2017-03-19 10:40:19 -03:00

337 lines
9.0 KiB
Plaintext

//Anomalies, used for events. Note that these DO NOT work by themselves; their procs are called by the event datum.
/obj/effect/anomaly
name = "anomaly"
desc = "A mysterious anomaly, seen commonly only in the region of space that the station orbits..."
icon_state = "bhole3"
density = 0
anchored = 1
light_range = 3
var/movechance = 70
var/obj/item/device/assembly/signaler/anomaly/aSignal = null
var/area/impact_area
var/lifespan = 990
var/death_time
var/countdown_colour
var/obj/effect/countdown/anomaly/countdown
/obj/effect/anomaly/New()
..()
poi_list |= src
START_PROCESSING(SSobj, src)
impact_area = get_area(src)
aSignal = new(src)
aSignal.name = "[name] core"
aSignal.code = rand(1,100)
aSignal.frequency = rand(1200, 1599)
if(IsMultiple(aSignal.frequency, 2))//signaller frequencies are always uneven!
aSignal.frequency++
death_time = world.time + lifespan
countdown = new(src)
if(countdown_colour)
countdown.color = countdown_colour
countdown.start()
/obj/effect/anomaly/process()
anomalyEffect()
if(death_time < world.time)
if(loc)
detonate()
qdel(src)
/obj/effect/anomaly/Destroy()
poi_list.Remove(src)
STOP_PROCESSING(SSobj, src)
qdel(countdown)
return ..()
/obj/effect/anomaly/proc/anomalyEffect()
if(prob(movechance))
step(src,pick(alldirs))
/obj/effect/anomaly/proc/detonate()
return
/obj/effect/anomaly/ex_act(severity, target)
if(severity == 1)
qdel(src)
/obj/effect/anomaly/proc/anomalyNeutralize()
new /obj/effect/particle_effect/smoke/bad(loc)
for(var/atom/movable/O in src)
O.loc = src.loc
qdel(src)
/obj/effect/anomaly/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/device/analyzer))
to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>")
///////////////////////
/obj/effect/anomaly/grav
name = "gravitational anomaly"
icon_state = "shield2"
density = 0
var/boing = 0
/obj/effect/anomaly/grav/New()
..()
aSignal.origin_tech = "magnets=7"
/obj/effect/anomaly/grav/anomalyEffect()
..()
boing = 1
for(var/obj/O in orange(4, src))
if(!O.anchored)
step_towards(O,src)
for(var/mob/living/M in range(0, src))
gravShock(M)
for(var/mob/living/M in orange(4, src))
step_towards(M,src)
for(var/obj/O in range(0,src))
if(!O.anchored)
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
O.throw_at(target, 5, 10)
/obj/effect/anomaly/grav/Crossed(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/Bump(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/Bumped(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/proc/gravShock(mob/A)
if(boing && isliving(A) && !A.stat)
A.Weaken(2)
var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src)))
A.throw_at(target, 5, 1)
boing = 0
/////////////////////
/obj/effect/anomaly/flux
name = "flux wave anomaly"
icon_state = "electricity2"
density = 1
var/canshock = 0
var/shockdamage = 20
var/explosive = 1
/obj/effect/anomaly/flux/New()
..()
aSignal.origin_tech = "powerstorage=7"
/obj/effect/anomaly/flux/anomalyEffect()
..()
canshock = 1
for(var/mob/living/M in range(0, src))
mobShock(M)
/obj/effect/anomaly/flux/Crossed(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Bump(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Bumped(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/proc/mobShock(mob/living/M)
if(canshock && istype(M))
canshock = 0 //Just so you don't instakill yourself if you slam into the anomaly five times in a second.
if(iscarbon(M))
if(ishuman(M))
M.electrocute_act(shockdamage, "[name]", safety=1)
return
M.electrocute_act(shockdamage, "[name]")
return
else
M.adjustFireLoss(shockdamage)
M.visible_message("<span class='danger'>[M] was shocked by \the [name]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>")
/obj/effect/anomaly/flux/detonate()
if(explosive)
explosion(src, 1, 4, 16, 18) //Low devastation, but hits a lot of stuff.
else
new /obj/effect/particle_effect/sparks(loc)
/////////////////////
/obj/effect/anomaly/bluespace
name = "bluespace anomaly"
icon = 'icons/obj/projectiles.dmi'
icon_state = "bluespace"
density = 1
/obj/effect/anomaly/bluespace/New()
..()
aSignal.origin_tech = "bluespace=7"
/obj/effect/anomaly/bluespace/anomalyEffect()
..()
for(var/mob/living/M in range(1,src))
do_teleport(M, locate(M.x, M.y, M.z), 4)
/obj/effect/anomaly/bluespace/Bumped(atom/A)
if(isliving(A))
do_teleport(A, locate(A.x, A.y, A.z), 8)
/obj/effect/anomaly/bluespace/detonate()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
// Calculate new position (searches through beacons in world)
var/obj/item/device/radio/beacon/chosen
var/list/possible = list()
for(var/obj/item/device/radio/beacon/W in teleportbeacons)
possible += W
if(possible.len > 0)
chosen = pick(possible)
if(chosen)
// Calculate previous position for transition
var/turf/FROM = T // the turf of origin we're travelling FROM
var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO
playsound(TO, 'sound/effects/phasein.ogg', 100, 1)
priority_announce("Massive bluespace translocation detected.", "Anomaly Alert")
var/list/flashers = list()
for(var/mob/living/carbon/C in viewers(TO, null))
if(C.flash_act())
flashers += C
var/y_distance = TO.y - FROM.y
var/x_distance = TO.x - FROM.x
for (var/atom/movable/A in urange(12, FROM )) // iterate thru list of mobs in the area
if(istype(A, /obj/item/device/radio/beacon)) continue // don't teleport beacons because that's just insanely stupid
if(A.anchored) continue
var/turf/newloc = locate(A.x + x_distance, A.y + y_distance, TO.z) // calculate the new place
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
A.loc = newloc
spawn()
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
var/mob/M = A
if(M.client)
var/obj/blueeffect = new /obj(src)
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.icon_state = "shieldsparkles"
blueeffect.layer = FLASH_LAYER
blueeffect.plane = FULLSCREEN_PLANE
blueeffect.mouse_opacity = 0
M.client.screen += blueeffect
sleep(20)
M.client.screen -= blueeffect
qdel(blueeffect)
/////////////////////
/obj/effect/anomaly/pyro
name = "pyroclastic anomaly"
icon_state = "mustard"
var/ticks = 0
/obj/effect/anomaly/pyro/New()
..()
aSignal.origin_tech = "plasmatech=7"
/obj/effect/anomaly/pyro/anomalyEffect()
..()
ticks++
if(ticks < 5)
return
else
ticks = 0
var/turf/open/T = get_turf(src)
if(istype(T))
T.atmos_spawn_air("o2=5;plasma=5;TEMP=1000")
/obj/effect/anomaly/pyro/detonate()
INVOKE_ASYNC(src, .proc/makepyroslime)
/obj/effect/anomaly/pyro/proc/makepyroslime()
var/turf/open/T = get_turf(src)
if(istype(T))
T.atmos_spawn_air("o2=500;plasma=500;TEMP=1000") //Make it hot and burny for the new slime
var/new_colour = pick("red", "orange")
var/mob/living/simple_animal/slime/S = new(T, new_colour)
S.rabid = TRUE
S.amount_grown = SLIME_EVOLUTION_THRESHOLD
S.Evolve()
offer_control(S)
/////////////////////
/obj/effect/anomaly/bhole
name = "vortex anomaly"
icon_state = "bhole3"
desc = "That's a nice station you have there. It'd be a shame if something happened to it."
/obj/effect/anomaly/bhole/New()
..()
aSignal.origin_tech = "engineering=7"
/obj/effect/anomaly/bhole/anomalyEffect()
..()
if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen
qdel(src)
return
grav(rand(0,3), rand(2,3), 50, 25)
//Throwing stuff around!
for(var/obj/O in range(2,src))
if(O == src)
return //DON'T DELETE YOURSELF GOD DAMN
if(!O.anchored)
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
O.throw_at(target, 7, 5)
else
O.ex_act(2)
/obj/effect/anomaly/bhole/proc/grav(r, ex_act_force, pull_chance, turf_removal_chance)
for(var/t = -r, t < r, t++)
affect_coord(x+t, y-r, ex_act_force, pull_chance, turf_removal_chance)
affect_coord(x-t, y+r, ex_act_force, pull_chance, turf_removal_chance)
affect_coord(x+r, y+t, ex_act_force, pull_chance, turf_removal_chance)
affect_coord(x-r, y-t, ex_act_force, pull_chance, turf_removal_chance)
/obj/effect/anomaly/bhole/proc/affect_coord(x, y, ex_act_force, pull_chance, turf_removal_chance)
//Get turf at coordinate
var/turf/T = locate(x, y, z)
if(isnull(T))
return
//Pulling and/or ex_act-ing movable atoms in that turf
if(prob(pull_chance))
for(var/obj/O in T.contents)
if(O.anchored)
O.ex_act(ex_act_force)
else
step_towards(O,src)
for(var/mob/living/M in T.contents)
step_towards(M,src)
//Damaging the turf
if( T && prob(turf_removal_chance) )
T.ex_act(ex_act_force)