diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index c72241752dd..96206c5f551 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -3,6 +3,9 @@ #define CLICKCATCHER_PLANE -99 +#define GRAVITY_PULSE_PLANE -96 //Needs to be behind space, otherwise it blocks space, lol +#define GRAVITY_PULSE_RENDER_TARGET "*GRAVPULSE_RENDER_TARGET" + #define PLANE_SPACE -95 #define PLANE_SPACE_PARALLAX -90 diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index 95bee94f6a9..8a59bb69275 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -15,6 +15,7 @@ //Why do plane masters need a backdrop sometimes? Read http://www.byond.com/forum/?post=2141928 //Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong. /obj/screen/plane_master/proc/backdrop(mob/mymob) + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, add_filter), "displace", 1, displacement_map_filter(render_source = GRAVITY_PULSE_RENDER_TARGET, size = 10)), 2 SECONDS)//Why a timer vs just apply on initialize / async? I don't know. It just can't be, neither works correctly. Don't lower below 2 seconds unless you can see effects through walls with no issue. /obj/screen/plane_master/floor name = "floor plane master" @@ -29,6 +30,7 @@ blend_mode = BLEND_OVERLAY /obj/screen/plane_master/game_world/backdrop(mob/mymob) + . = ..() //if you delete it so help me god clear_filters() if(istype(mymob) && mymob.client && mymob.client.prefs && (mymob.client.prefs.toggles & PREFTOGGLE_AMBIENT_OCCLUSION)) add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA")) @@ -94,3 +96,11 @@ color = list(null, null, null, "#0000", "#000f") blend_mode = BLEND_ADD appearance_flags = PLANE_MASTER | NO_CLIENT_COLOR | PIXEL_SCALE + +/obj/screen/plane_master/gravpulse + name = "gravpulse plane" + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + plane = GRAVITY_PULSE_PLANE + blend_mode = BLEND_ADD + render_target = GRAVITY_PULSE_RENDER_TARGET + appearance_flags = PLANE_MASTER | NO_CLIENT_COLOR diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 35806c0c4fb..e04af4e44ff 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -97,12 +97,16 @@ name = "gravitational anomaly" icon_state = "shield2" density = FALSE + appearance_flags = PIXEL_SCALE|LONG_GLIDE var/boing = FALSE var/knockdown = FALSE aSignal = /obj/item/assembly/signaler/anomaly/grav + var/obj/effect/warp_effect/supermatter/warp /obj/effect/anomaly/grav/Initialize(mapload, new_lifespan, _drops_core = TRUE, event_spawned = TRUE) . = ..() + warp = new(src) + vis_contents += warp if(!event_spawned) //So an anomaly in the hallway is assured to have some risk to it, but not make sm / vetus too much pain return for(var/I in 1 to 3) @@ -111,6 +115,11 @@ if(prob(75)) new /obj/item/shard(loc) +/obj/effect/anomaly/grav/Destroy() + vis_contents -= warp + QDEL_NULL(warp) // don't want to leave it hanging + return ..() + /obj/effect/anomaly/grav/anomalyEffect() ..() boing = TRUE @@ -127,6 +136,9 @@ var/mob/living/target = locate() in view(4, src) if(target && !target.stat) O.throw_at(target, 5, 10, dodgeable = FALSE) + //anomaly quickly contracts then slowly expands it's ring + animate(warp, time = 6, transform = matrix().Scale(0.5,0.5)) + animate(time = 14, transform = matrix()) /obj/effect/anomaly/grav/Crossed(atom/movable/AM) . = ..() diff --git a/code/game/objects/effects/temporary_visuals/misc_visuals.dm b/code/game/objects/effects/temporary_visuals/misc_visuals.dm index fcb1a35307b..a1e57947b11 100644 --- a/code/game/objects/effects/temporary_visuals/misc_visuals.dm +++ b/code/game/objects/effects/temporary_visuals/misc_visuals.dm @@ -364,6 +364,19 @@ pixel_y = -32 duration = 42 +/obj/effect/temp_visual/bsg_kaboom/Initialize(mapload) + . = ..() + new /obj/effect/warp_effect/bsg(loc) + +/obj/effect/warp_effect/bsg + +/obj/effect/warp_effect/bsg/Initialize(mapload) + . = ..() + var/matrix/M = matrix() * 0.5 + transform = M + animate(src, transform = M * 8, time = 0.8 SECONDS, alpha = 0) + QDEL_IN(src, 0.8 SECONDS) + /obj/effect/temp_visual/rcd_effect icon = 'icons/effects/effects_rcd.dmi' icon_state = "rcd" diff --git a/code/game/objects/effects/warp_effect.dm b/code/game/objects/effects/warp_effect.dm new file mode 100644 index 00000000000..b7f53897b72 --- /dev/null +++ b/code/game/objects/effects/warp_effect.dm @@ -0,0 +1,13 @@ +/obj/effect/warp_effect + plane = GRAVITY_PULSE_PLANE + appearance_flags = PIXEL_SCALE|LONG_GLIDE + icon = 'icons/effects/seismic_stomp_effect.dmi' + icon_state = "stomp_effect" + pixel_y = -16 + pixel_x = -16 + +/obj/effect/warp_effect/ex_act(severity) + return + +/obj/effect/warp_effect/singularity_act() + return FALSE diff --git a/code/modules/power/engines/singularity/singularity.dm b/code/modules/power/engines/singularity/singularity.dm index 53a645a3169..42e59231282 100644 --- a/code/modules/power/engines/singularity/singularity.dm +++ b/code/modules/power/engines/singularity/singularity.dm @@ -26,6 +26,7 @@ var/last_warning var/consumedSupermatter = FALSE //If the singularity has eaten a supermatter shard and can go to stage six var/warps_projectiles = TRUE + var/obj/effect/warp_effect/supermatter/warp resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF /// Whether or not we've pinged ghosts var/isnt_shutting_down = FALSE @@ -51,6 +52,8 @@ STOP_PROCESSING(SSobj, src) GLOB.poi_list.Remove(src) GLOB.singularities -= src + vis_contents -= warp + QDEL_NULL(warp) // don't want to leave it hanging target = null return ..() @@ -114,7 +117,7 @@ /obj/singularity/bullet_act(obj/item/projectile/P) qdel(P) - return 0 //Will there be an impact? Who knows. Will we see it? No. + return 0 //Will there be an impact? Who knows. Will we see it? No. /obj/singularity/Bump(atom/A) @@ -140,6 +143,7 @@ eat() do_dissipate() check_energy() + update_warp() return @@ -183,6 +187,9 @@ dissipate_delay = 10 dissipate_track = 0 dissipate_strength = 1 + if(warp) + vis_contents -= warp + qdel(warp) if(STAGE_TWO) if((check_turfs_in(1,1))&&(check_turfs_in(2,1))&&(check_turfs_in(4,1))&&(check_turfs_in(8,1))) current_size = STAGE_TWO @@ -195,6 +202,9 @@ dissipate_delay = 5 dissipate_track = 0 dissipate_strength = 5 + if(!warp) + warp = new(src) + vis_contents += warp 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 = STAGE_THREE @@ -207,6 +217,9 @@ dissipate_delay = 4 dissipate_track = 0 dissipate_strength = 20 + if(!warp) //In the event the singularity eats a clown and skips stage 2. + warp = new(src) + vis_contents += warp 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 = STAGE_FOUR @@ -459,6 +472,15 @@ empulse(src, 8, 10) return +/obj/singularity/proc/update_warp() + if(!warp) + return + warp.pixel_x = initial(warp.pixel_x) - pixel_x + warp.pixel_y = initial(warp.pixel_x) - pixel_y + var/scaling = allowed_size / 3 + animate(warp, time = 6, transform = matrix().Scale(0.5 * scaling, 0.5 * scaling)) + animate(time = 14, transform = matrix().Scale(scaling, scaling)) + /obj/singularity/singularity_act() var/gain = (energy/2) var/dist = max((current_size - 2),1) diff --git a/code/modules/power/engines/supermatter/supermatter.dm b/code/modules/power/engines/supermatter/supermatter.dm index f74ca7f61c4..9d9dc2c17f7 100644 --- a/code/modules/power/engines/supermatter/supermatter.dm +++ b/code/modules/power/engines/supermatter/supermatter.dm @@ -78,6 +78,13 @@ #define MAX_SPACE_EXPOSURE_DAMAGE 2 +/// Colours used for effects. +#define SUPERMATTER_COLOUR "#ffd04f" +#define SUPERMATTER_RED "#aa2c16" +#define SUPERMATTER_TESLA_COLOUR "#00ffff" +#define SUPERMATTER_SINGULARITY_RAYS_COLOUR "#750000" +#define SUPERMATTER_SINGULARITY_LIGHT_COLOUR "#400060" + /obj/machinery/atmospherics/supermatter_crystal name = "supermatter crystal" desc = "A strangely translucent and iridescent crystal." @@ -85,8 +92,8 @@ icon_state = "darkmatter" density = TRUE anchored = TRUE + appearance_flags = PIXEL_SCALE|LONG_GLIDE flags_2 = RAD_PROTECT_CONTENTS_2 | RAD_NO_CONTAMINATE_2 | IMMUNE_TO_SHUTTLECRUSH_2 | NO_MALF_EFFECT_2 | CRITICAL_ATOM_2 - light_range = 4 resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF base_icon_state = "darkmatter" @@ -160,9 +167,10 @@ var/bullet_energy = 2 ///How much hallucination should we produce per unit of power? var/hallucination_power = 1 - ///Our internal radio var/obj/item/radio/radio + ///Reference to the warp effect + var/obj/effect/warp_effect/supermatter/warp ///Boolean used for logging if we've been powered var/has_been_powered = FALSE @@ -208,6 +216,9 @@ soundloop = new(list(src), TRUE) /obj/machinery/atmospherics/supermatter_crystal/Destroy() + if(warp) + vis_contents -= warp + QDEL_NULL(warp) investigate_log("has been destroyed.", "supermatter") SSair.atmos_machinery -= src QDEL_NULL(radio) @@ -283,7 +294,7 @@ final_countdown = TRUE var/image/causality_field = image(icon, null, "causality_field") - add_overlay(causality_field, TRUE) + add_overlay(causality_field) var/speaking = "[emergency_alert] The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated." for(var/mob/M in GLOB.player_list) // for all players @@ -301,6 +312,7 @@ radio.autosay("[safe_alert] Failsafe has been disengaged.", name, null, list(z)) cut_overlay(causality_field, TRUE) final_countdown = FALSE + remove_filter(list("outline", "icon")) return else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy sleep(10) @@ -593,6 +605,8 @@ if(prob(15)) supermatter_pull(loc, min(power / 850, 3)) //850, 1700, 2550 + lights() + sm_filters() //Tells the engi team to get their butt in gear if(damage > warning_point) // while the core is still damaged and it's still worth noting its status @@ -819,6 +833,106 @@ else L.show_message("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns.", 2) +/obj/machinery/atmospherics/supermatter_crystal/proc/sm_filters() + var/new_filter = isnull(get_filter("ray")) + + add_filter(name = "ray", priority = 1, params = list( + type = "rays", + size = power ? clamp((damage/100) * power, 50, 125) : 1, + color = (gasmix_power_ratio> 0.8 ? SUPERMATTER_RED : SUPERMATTER_COLOUR), + factor = clamp(damage/600, 1, 10), + density = clamp(damage/10, 12, 100) + )) + + // Filter animation persists even if the filter itself is changed externally. + // Probably prone to breaking. Treat with suspicion. + if(new_filter) + animate(get_filter("ray"), offset = 10, time = 10 SECONDS, loop = -1) + animate(offset = 0, time = 10 SECONDS) + + if(power > POWER_PENALTY_THRESHOLD) + add_filter(name = "ray", priority = 1, params = list( + type = "rays", + size = power ? clamp((damage/100) * power, 50, 175) : 1, //Higher power + color = SUPERMATTER_TESLA_COLOUR, + factor = clamp(damage/300, 1, 20), + density = clamp(damage/5, 12, 200) + )) + if(prob(25)) + new /obj/effect/warp_effect/bsg(get_turf(src)) //Some extra visual effect to the shocking sm which is a bit less interesting. + if(final_countdown) + add_filter(name = "icon", priority = 2, params = list( + type = "layer", + icon = new/icon('icons/obj/tesla_engine/energy_ball.dmi', "energy_ball", frame = rand(1,12)), + flags = FILTER_UNDERLAY + )) + else + remove_filter("icon") + + if(combined_gas > MOLE_PENALTY_THRESHOLD) + add_filter(name = "ray", priority = 1, params=list( + type = "rays", + size = power ? clamp((damage/100) * power, 50, 125) : 1, + color = SUPERMATTER_SINGULARITY_RAYS_COLOUR, + factor = clamp(damage / 300, 1, 30), + density = clamp(damage / 5, 12, 300) //More compressed due to gravity + )) + + add_filter(name = "outline", priority = 2, params = list( + type = "outline", + size = 1, + color = SUPERMATTER_SINGULARITY_LIGHT_COLOUR + )) + if(!warp) + warp = new(src) + vis_contents += warp + animate(warp, time = 6, transform = matrix().Scale(0.5,0.5)) + animate(time = 14, transform = matrix()) + if(final_countdown) + add_filter(name = "icon", priority = 3, params = list( + type = "layer", + icon = new/icon('icons/effects/96x96.dmi', "singularity_s3", frame = rand(1,8)), + flags = FILTER_OVERLAY + )) + else + remove_filter("icon") + else + vis_contents -= warp + remove_filter("outline") + QDEL_NULL(warp) + + + +// Change how bright the rock is +/obj/machinery/atmospherics/supermatter_crystal/proc/lights() + set_light( + l_range = 4 + power / 200, + l_power = 1 + power / 1000, + l_color = gasmix_power_ratio > 0.8 ? SUPERMATTER_RED : SUPERMATTER_COLOUR, + ) + + if(power > POWER_PENALTY_THRESHOLD) + set_light( + l_range = 4 + clamp(damage * power, 50, 500), + l_power = 3, + l_color = SUPERMATTER_TESLA_COLOUR, + ) + if(combined_gas > MOLE_PENALTY_THRESHOLD) + set_light( + l_range = 4 + clamp(damage / 2, 10, 50), + l_power = 3, + l_color = SUPERMATTER_SINGULARITY_LIGHT_COLOUR, + ) + + +/obj/effect/warp_effect/supermatter + plane = GRAVITY_PULSE_PLANE + appearance_flags = PIXEL_SCALE|LONG_GLIDE // no tile bound so you can see it around corners and so + icon = 'icons/effects/light_352.dmi' + icon_state = "light" + pixel_x = -176 + pixel_y = -176 + /obj/machinery/atmospherics/supermatter_crystal/engine is_main_engine = TRUE diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 91b5c373746..255636917e8 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -361,6 +361,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) */ /obj/machinery/gravity_generator/main/proc/shake_everyone() var/turf/our_turf = get_turf(src) + new /obj/effect/warp_effect/gravity_generator(our_turf) var/sound/alert_sound = sound('sound/effects/alert.ogg') for(var/shaken in GLOB.mob_list) var/mob/M = shaken @@ -392,6 +393,16 @@ GLOBAL_LIST_EMPTY(gravity_generators) // Misc +/obj/effect/warp_effect/gravity_generator + +/obj/effect/warp_effect/gravity_generator/Initialize(mapload) + . = ..() + var/matrix/M = matrix() * 0.5 + transform = M + animate(src, transform = M * 40, time = 0.8 SECONDS, alpha = 128) + QDEL_IN(src, 0.8 SECONDS) + + /obj/item/paper/gravity_gen name = "paper - 'Generate your own gravity!'" info = {"

Generating Gravity For Dummies

diff --git a/icons/effects/light_352.dmi b/icons/effects/light_352.dmi new file mode 100644 index 00000000000..f895792da42 Binary files /dev/null and b/icons/effects/light_352.dmi differ diff --git a/paradise.dme b/paradise.dme index 0e8f6ce81d3..58a1487a304 100644 --- a/paradise.dme +++ b/paradise.dme @@ -853,6 +853,7 @@ #include "code\game\objects\effects\snowcloud.dm" #include "code\game\objects\effects\spiders.dm" #include "code\game\objects\effects\step_triggers.dm" +#include "code\game\objects\effects\warp_effect.dm" #include "code\game\objects\effects\decals\cleanable.dm" #include "code\game\objects\effects\decals\contraband.dm" #include "code\game\objects\effects\decals\crayon.dm"