diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm new file mode 100644 index 00000000000..326a6efac98 --- /dev/null +++ b/code/game/objects/effects/anomalies.dm @@ -0,0 +1,116 @@ +//Anomalies, used for events. Note that these won't work by themselves; their procs are called by the event datum. + +/obj/effect/anomaly + name = "anomaly" + icon = 'icons/effects/effects.dmi' + desc = "A mysterious anomaly seen in the region of space that the station orbits." + icon_state = "bhole3" + unacidable = 1 + density = 0 + anchored = 1 + +/obj/effect/anomaly/proc/anomalyEffect() + if(prob(50)) + step(src,pick(alldirs)) + +/////////////////////// + +/obj/effect/anomaly/grav + name = "gravitational anomaly" + icon_state = "shield2" + density = 1 + +/obj/effect/anomaly/grav/anomalyEffect() + ..() + + for(var/obj/O in orange(4, src)) + if(!O.anchored) + step_towards(O,src) + for(var/mob/living/M in orange(4, src)) + step_towards(M,src) + +/obj/effect/anomaly/grav/Bump(mob/A) + gravShock(A) + return + +/obj/effect/anomaly/grav/Bumped(mob/A) + gravShock(A) + return + +/obj/effect/anomaly/grav/proc/gravShock(var/mob/A) + if(isliving(A) && !A.stat) + A.Weaken(4) + var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src))) + A.throw_at(target, 5, 1) + return + +///////////////////// + +obj/effect/anomaly/flux + name = "flux wave anomaly" + icon_state = "electricity" + +///////////////////// + +obj/effect/anomaly/pyro + name = "pyroclastic anomaly" + icon_state = "mustard" + +obj/effect/anomaly/pyro/anomalyEffect() + ..() + var/turf/simulated/T = get_turf(src) + if(istype(T)) + T.atmos_spawn_air("fire", 3) + +///////////////////// + +/obj/effect/anomaly/bhole //TODO: Make this start out weaker, building power until critical mass + 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/anomalyEffect() + ..() + if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen + del(src) + return + + //DESTROYING STUFF AT THE EPICENTER + for(var/mob/living/M in orange(1,src)) + M.gib() + for(var/obj/O in orange(1,src)) + del(O) + for(var/turf/simulated/ST in orange(1,src)) + ST.ChangeTurf(/turf/space) + + grav(rand(2,4), rand(2,4), rand(10,75), rand(0, 25)) +// grav(rand(2,10), rand(2,4), rand(10,75), rand(0, 25)) + +/obj/effect/anomaly/bhole/proc/grav(var/r, var/ex_act_force, var/pull_chance, var/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) + return + +/obj/effect/anomaly/bhole/proc/affect_coord(var/x, var/y, var/ex_act_force, var/pull_chance, var/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) + + //Destroying the turf + if( T && istype(T,/turf/simulated) && prob(turf_removal_chance) ) + var/turf/simulated/ST = T + ST.ChangeTurf(/turf/space) + return \ No newline at end of file diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index e5921b45734..34ea3c5ad73 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -428,14 +428,16 @@ var/global/floorIsLava = 0
"} - if(check_rights(R_FUN,0)) + if(check_rights(R_FUN,0))//TODO: Make all this hardcoded random event panel stuff its own proc so we can actually remove poor events without making the code stop compiling dat += {" 'Random' Events

- Trigger a gravity-failure event.
+ Trigger a gravity-failure event
Spawn a wave of meteors (aka lagocolyptic shower)
- Spawn a gravitational anomaly (aka lagitational anomolag)
+ Spawn a black hole
+ Spawn a gravitational anomaly
Spawn wormholes
+ Spawn a pyroclastic anomaly
Spawn blob
Trigger an Alien infestation
Spawn an Alien silently
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index ce1d1fe1308..dfed8fb4544 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1458,7 +1458,7 @@ if(!check_rights(R_FUN,0)) removed_paths += dirty_path continue - else if(ispath(path, /obj/effect/bhole)) + else if(ispath(path, /obj/effect/anomaly/bhole)) if(!check_rights(R_FUN,0)) removed_paths += dirty_path continue @@ -1673,63 +1673,31 @@ message_admins("\red [key_name_admin(usr)] changed the bomb cap to [MAX_EX_DEVESTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]", 1) log_admin("[key_name_admin(usr)] changed the bomb cap to [MAX_EX_DEVESTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") -/* if("shockwave") - ok = 1 - world << "\red ALERT: STATION STRESS CRITICAL" - sleep(60) - world << "\red ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!" - sleep(80) - world << "\red ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!" - sleep(40) - for(var/mob/M in world) - shake_camera(M, 400, 1) - for(var/obj/structure/window/W in world) - spawn(0) - sleep(rand(10,400)) - W.ex_act(rand(2,1)) - for(var/obj/structure/grille/G in world) - spawn(0) - sleep(rand(20,400)) - G.ex_act(rand(2,1)) - for(var/obj/machinery/door/D in world) - spawn(0) - sleep(rand(20,400)) - D.ex_act(rand(2,1)) - for(var/turf/station/floor/Floor in world) - spawn(0) - sleep(rand(30,400)) - Floor.ex_act(rand(2,1)) - for(var/obj/structure/cable/Cable in world) - spawn(0) - sleep(rand(30,400)) - Cable.ex_act(rand(2,1)) - for(var/obj/structure/closet/Closet in world) - spawn(0) - sleep(rand(30,400)) - Closet.ex_act(rand(2,1)) - for(var/obj/machinery/Machinery in world) - spawn(0) - sleep(rand(30,400)) - Machinery.ex_act(rand(1,3)) - for(var/turf/station/wall/Wall in world) - spawn(0) - sleep(rand(30,400)) - Wall.ex_act(rand(2,1)) */ if("wave") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","MW") + message_admins("[key_name_admin(usr)] has spawned meteors") E = new /datum/round_event/meteor_wave() - if("gravanomalies") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","GA") - E = new /datum/round_event/gravitational_anomaly() - + message_admins("[key_name_admin(usr)] has spawned a gravitational anomaly") + E = new /datum/round_event/anomaly_grav() + if("pyroanomalies") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","PYRO") + message_admins("[key_name_admin(usr)] has spawned a pyroclastic anomaly") + E = new /datum/round_event/anomaly_pyro() + if("blackhole") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BH") + message_admins("[key_name_admin(usr)] has spawned a vortex anomaly") + E = new /datum/round_event/anomaly_vortex() if("timeanomalies") //dear god this code was awful :P Still needs further optimisation feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","STA") + message_admins("[key_name_admin(usr)] has made wormholes") E = new /datum/round_event/wormholes() - if("goblob") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","BL") @@ -1911,7 +1879,7 @@ feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","FLUX") message_admins("[key_name_admin(usr)] has triggered an energetic flux") - E = new /datum/round_event/energetic_flux() + E = new /datum/round_event/anomaly_flux() if(E) E.processing = 0 if(E.announceWhen>0) diff --git a/code/modules/events/energetic_flux.dm b/code/modules/events/anomaly_flux.dm similarity index 52% rename from code/modules/events/energetic_flux.dm rename to code/modules/events/anomaly_flux.dm index fed6a5359ba..143546e1930 100644 --- a/code/modules/events/energetic_flux.dm +++ b/code/modules/events/anomaly_flux.dm @@ -1,16 +1,19 @@ -/datum/round_event_control/energetic_flux +/datum/round_event_control/anomaly_flux name = "Energetic Flux" - typepath = /datum/round_event/energetic_flux + typepath = /datum/round_event/anomaly_flux max_occurrences = 2 weight = 15 -/datum/round_event/energetic_flux - startWhen = 30 +/datum/round_event/anomaly_flux + startWhen = 5 + announceWhen = 20 + endWhen = 60 var/area/impact_area + var/obj/effect/anomaly/flux/newflux -/datum/round_event/energetic_flux/setup() +/datum/round_event/anomaly_flux/setup() var/list/safe_areas = list( /area/turret_protected/ai, /area/turret_protected/ai_upload, @@ -36,11 +39,21 @@ impact_area = locate(pick((the_station_areas - safe_areas) + danger_areas)) //need to locate() as it's just a list of paths. -/datum/round_event/energetic_flux/announce() - command_alert("Warning! Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name]. Vacate [impact_area.name].", "Anomaly Alert") +/datum/round_event/anomaly_flux/announce() + command_alert("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert") - -/datum/round_event/energetic_flux/start() +/datum/round_event/anomaly_flux/start() var/turf/T = pick(get_area_turfs(impact_area)) if(T) - explosion(T, -1, 2, 4, 5) \ No newline at end of file + newflux = new /obj/effect/anomaly/flux(T.loc) + +/datum/round_event/anomaly_flux/tick() + if(!newflux) + kill() + return + newflux.anomalyEffect() + +/datum/round_event/anomaly_flux/end() + if(newflux)//If it hasn't been neutralized, it's time to blow up. + explosion(newflux, -1, 2, 4, 5) + del(newflux) \ No newline at end of file diff --git a/code/modules/events/anomaly_grav.dm b/code/modules/events/anomaly_grav.dm new file mode 100644 index 00000000000..fb8576d16bd --- /dev/null +++ b/code/modules/events/anomaly_grav.dm @@ -0,0 +1,58 @@ +/datum/round_event_control/anomaly_grav + name = "Gravitational Anomaly" + typepath = /datum/round_event/anomaly_grav + max_occurrences = 2 + weight = 15 + +/datum/round_event/anomaly_grav + startWhen = 5 + announceWhen = 20 + endWhen = 100 + + var/area/impact_area + var/obj/effect/anomaly/grav/newgrav + + +/datum/round_event/anomaly_grav/setup()//TODO: Make this location stuff into a helper proc to be used in other events. + var/list/safe_areas = list( + /area/turret_protected/ai, + /area/turret_protected/ai_upload, + /area/engine, + /area/solar, + /area/holodeck, + /area/shuttle/arrival, + /area/shuttle/escape/station, + /area/shuttle/escape_pod1/station, + /area/shuttle/escape_pod2/station, + /area/shuttle/escape_pod3/station, + /area/shuttle/escape_pod5/station, + /area/shuttle/mining/station, + /area/shuttle/transport1/station, + /area/shuttle/specops/station) + + //These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up. + var/list/danger_areas = list( + /area/engine/break_room, + /area/engine/chiefs_office) + + + impact_area = locate(pick((the_station_areas - safe_areas) + danger_areas)) //need to locate() as it's just a list of paths. + + +/datum/round_event/anomaly_grav/announce() + command_alert("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") + +/datum/round_event/anomaly_grav/start() + var/turf/T = pick(get_area_turfs(impact_area)) + if(T) + newgrav = new /obj/effect/anomaly/grav(T.loc) + +/datum/round_event/anomaly_grav/tick() + if(!newgrav) + kill() + return + newgrav.anomalyEffect() + +/datum/round_event/anomaly_grav/end() + if(newgrav)//It's possible it could have been neutralized before this point. + del(newgrav) \ No newline at end of file diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm new file mode 100644 index 00000000000..4ed2d531316 --- /dev/null +++ b/code/modules/events/anomaly_pyro.dm @@ -0,0 +1,59 @@ +/datum/round_event_control/anomaly_pyro + name = "Pyroclastic Anomaly" + typepath = /datum/round_event/anomaly_pyro + max_occurrences = 2 + weight = 15 + +/datum/round_event/anomaly_pyro + startWhen = 5 + announceWhen = 10 + endWhen = 50 + + var/area/impact_area + var/obj/effect/anomaly/pyro/newpyro + + +/datum/round_event/anomaly_pyro/setup()//TODO: Make this location stuff into a helper proc to be used in other events. + var/list/safe_areas = list( + /area/turret_protected/ai, + /area/turret_protected/ai_upload, + /area/engine, + /area/solar, + /area/holodeck, + /area/shuttle/arrival, + /area/shuttle/escape/station, + /area/shuttle/escape_pod1/station, + /area/shuttle/escape_pod2/station, + /area/shuttle/escape_pod3/station, + /area/shuttle/escape_pod5/station, + /area/shuttle/mining/station, + /area/shuttle/transport1/station, + /area/shuttle/specops/station) + + //These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up. + var/list/danger_areas = list( + /area/engine/break_room, + /area/engine/chiefs_office) + + + impact_area = locate(pick((the_station_areas - safe_areas) + danger_areas)) //need to locate() as it's just a list of paths. + + +/datum/round_event/anomaly_pyro/announce() + command_alert("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") + +/datum/round_event/anomaly_pyro/start() + var/turf/T = pick(get_area_turfs(impact_area)) + if(T) + newpyro = new /obj/effect/anomaly/pyro(T.loc) + +/datum/round_event/anomaly_pyro/tick() + if(!newpyro) + kill() + return + if(IsMultiple(activeFor, 5)) + newpyro.anomalyEffect() + +/datum/round_event/anomaly_pyro/end() + if(newpyro)//It's possible it could have been neutralized before this point. + del(newpyro) \ No newline at end of file diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm new file mode 100644 index 00000000000..cf52e21f0cd --- /dev/null +++ b/code/modules/events/anomaly_vortex.dm @@ -0,0 +1,33 @@ +/datum/round_event_control/anomaly_vortex + name = "Vortex Anomaly" + typepath = /datum/round_event/anomaly_vortex + max_occurrences = 5 + weight = 2 + +/datum/round_event/anomaly_vortex + startWhen = 10 + var/obj/effect/anomaly/bhole/vortex + + +/datum/round_event/anomaly_vortex/announce() + command_alert("Localized high-intensity gravitational anomaly detected on long range scanners.", "Anomaly Alert") + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player)) + M << sound('sound/AI/granomalies.ogg') + +/datum/round_event/anomaly_vortex/setup() + endWhen = rand(20, 30) + +/datum/round_event/anomaly_vortex/start() + var/turf/T = pick(blobstart) + vortex = new /obj/effect/anomaly/bhole(T.loc) + +/datum/round_event/anomaly_vortex/tick() + if(!vortex) + kill() + return + vortex.anomalyEffect() + +/datum/round_event/anomaly_vortex/end() + if(vortex) + del(vortex) \ No newline at end of file diff --git a/code/modules/events/gravitational_anomaly.dm b/code/modules/events/gravitational_anomaly.dm deleted file mode 100644 index a39c26561b2..00000000000 --- a/code/modules/events/gravitational_anomaly.dm +++ /dev/null @@ -1,114 +0,0 @@ -/datum/round_event_control/gravitational_anomaly - name = "Gravitational Anomaly" - typepath = /datum/round_event/gravitational_anomaly - max_occurrences = 5 - weight = 2 - -/datum/round_event/gravitational_anomaly - startWhen = 10 - - var/obj/effect/bhole/blackhole - -/datum/round_event/gravitational_anomaly/announce() - command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/granomalies.ogg') - -/datum/round_event/gravitational_anomaly/setup() - endWhen = rand(50, 200) - -/datum/round_event/gravitational_anomaly/start() - var/turf/T = pick(blobstart) - blackhole = new /obj/effect/bhole( T.loc, 30 ) - -/datum/round_event/gravitational_anomaly/end() - del(blackhole) - - -/obj/effect/bhole - name = "black hole" - icon = 'icons/obj/objects.dmi' - desc = "FUCK FUCK FUCK AAAHHH" - icon_state = "bhole3" - opacity = 1 - unacidable = 1 - density = 0 - anchored = 1 - -/obj/effect/bhole/New() - spawn(4) - controller() - -/obj/effect/bhole/proc/controller() - while(src) - - if(!isturf(loc)) - del(src) - return - - //DESTROYING STUFF AT THE EPICENTER - for(var/mob/living/M in orange(1,src)) - del(M) - for(var/obj/O in orange(1,src)) - del(O) - for(var/turf/simulated/ST in orange(1,src)) - ST.ChangeTurf(/turf/space) - - sleep(6) - grav(10, 4, 10, 0 ) - sleep(6) - grav( 8, 4, 10, 0 ) - sleep(6) - grav( 9, 4, 10, 0 ) - sleep(6) - grav( 7, 3, 40, 1 ) - sleep(6) - grav( 5, 3, 40, 1 ) - sleep(6) - grav( 6, 3, 40, 1 ) - sleep(6) - grav( 4, 2, 50, 6 ) - sleep(6) - grav( 3, 2, 50, 6 ) - sleep(6) - grav( 2, 2, 75,25 ) - sleep(6) - - //MOVEMENT - if( prob(50) ) - src.anchored = 0 - step(src,pick(alldirs)) - src.anchored = 1 - -/obj/effect/bhole/proc/grav(var/r, var/ex_act_force, var/pull_chance, var/turf_removal_chance) - if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen - del(src) - return - 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) - return - -/obj/effect/bhole/proc/affect_coord(var/x, var/y, var/ex_act_force, var/pull_chance, var/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) - - //Destroying the turf - if( T && istype(T,/turf/simulated) && prob(turf_removal_chance) ) - var/turf/simulated/ST = T - ST.ChangeTurf(/turf/space) - return \ No newline at end of file diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index e397ed768ae..29953fe3a16 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index c3636815d04..2b3286ea819 100644 Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ diff --git a/tgstation.dme b/tgstation.dme index a131fad77a8..1db918ed388 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -396,6 +396,7 @@ #include "code\game\objects\structures.dm" #include "code\game\objects\weapons.dm" #include "code\game\objects\effects\aliens.dm" +#include "code\game\objects\effects\anomalies.dm" #include "code\game\objects\effects\bump_teleporter.dm" #include "code\game\objects\effects\effect_system.dm" #include "code\game\objects\effects\forcefields.dm" @@ -738,6 +739,10 @@ #include "code\modules\detectivework\footprints_and_rag.dm" #include "code\modules\detectivework\scanner.dm" #include "code\modules\events\alien_infestation.dm" +#include "code\modules\events\anomaly_flux.dm" +#include "code\modules\events\anomaly_grav.dm" +#include "code\modules\events\anomaly_pyro.dm" +#include "code\modules\events\anomaly_vortex.dm" #include "code\modules\events\blob.dm" #include "code\modules\events\bluespaceanomaly.dm" #include "code\modules\events\brand_intelligence.dm" @@ -746,10 +751,8 @@ #include "code\modules\events\disease_outbreak.dm" #include "code\modules\events\dust.dm" #include "code\modules\events\electrical_storm.dm" -#include "code\modules\events\energetic_flux.dm" #include "code\modules\events\event.dm" #include "code\modules\events\event_manager.dm" -#include "code\modules\events\gravitational_anomaly.dm" #include "code\modules\events\immovable_rod.dm" #include "code\modules\events\ion_storm.dm" #include "code\modules\events\mass_hallucination.dm"