diff --git a/code/__DEFINES/color/color_priority.dm b/code/__DEFINES/color/color_priority.dm new file mode 100644 index 0000000000..040ff5003a --- /dev/null +++ b/code/__DEFINES/color/color_priority.dm @@ -0,0 +1,6 @@ +//different types of atom colorations +#define ADMIN_COLOUR_PRIORITY 1 //only used by rare effects like greentext coloring mobs and when admins varedit color +#define TEMPORARY_COLOUR_PRIORITY 2 //e.g. purple effect of the revenant on a mob, black effect when mob electrocuted +#define WASHABLE_COLOUR_PRIORITY 3 //color splashed onto an atom (e.g. paint on turf) +#define FIXED_COLOUR_PRIORITY 4 //color inherent to the atom (e.g. blob color) +#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are. diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/color/colors.dm similarity index 100% rename from code/__DEFINES/colors.dm rename to code/__DEFINES/color/colors.dm diff --git a/code/__DEFINES/color/lum.dm b/code/__DEFINES/color/lum.dm new file mode 100644 index 0000000000..942462b573 --- /dev/null +++ b/code/__DEFINES/color/lum.dm @@ -0,0 +1,4 @@ +//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1. +#define LUMA_R 0.213 +#define LUMA_G 0.715 +#define LUMA_B 0.072 diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm index 531629c7cd..2550084207 100644 --- a/code/__DEFINES/layers_planes.dm +++ b/code/__DEFINES/layers_planes.dm @@ -5,9 +5,10 @@ #define CLICKCATCHER_PLANE -99 -#define PLANE_SPACE -95 +#define PLANE_SPACE -98 #define PLANE_SPACE_RENDER_TARGET "PLANE_SPACE" -#define PLANE_SPACE_PARALLAX -90 + +#define PLANE_SPACE_PARALLAX -95 #define PLANE_SPACE_PARALLAX_RENDER_TARGET "PLANE_SPACE_PARALLAX" #define OPENSPACE_LAYER 17 //Openspace layer over all diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 1410a5d99a..0b5c277a3a 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -345,18 +345,6 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S //TODO Move to a pref #define STATION_GOAL_BUDGET 1 -//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1. -#define LUMA_R 0.213 -#define LUMA_G 0.715 -#define LUMA_B 0.072 - -//different types of atom colorations -#define ADMIN_COLOUR_PRIORITY 1 //only used by rare effects like greentext coloring mobs and when admins varedit color -#define TEMPORARY_COLOUR_PRIORITY 2 //e.g. purple effect of the revenant on a mob, black effect when mob electrocuted -#define WASHABLE_COLOUR_PRIORITY 3 //color splashed onto an atom (e.g. paint on turf) -#define FIXED_COLOUR_PRIORITY 4 //color inherent to the atom (e.g. blob color) -#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are. - //Endgame Results #define NUKE_NEAR_MISS 1 #define NUKE_MISS_STATION 2 @@ -568,3 +556,8 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define SHOES_KNOTTED 2 #define WANTED_FILE "wanted_message.json" + +// Notification action types +#define NOTIFY_JUMP "jump" +#define NOTIFY_ATTACK "attack" +#define NOTIFY_ORBIT "orbit" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index cd13510366..cb95aab8c0 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -34,12 +34,6 @@ #define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC|CHAT_BANKCARD) -#define PARALLAX_INSANE -1 //for show offs -#define PARALLAX_HIGH 0 //default. -#define PARALLAX_MED 1 -#define PARALLAX_LOW 2 -#define PARALLAX_DISABLE 3 //this option must be the highest number - #define PIXEL_SCALING_AUTO 0 #define PIXEL_SCALING_1X 1 #define PIXEL_SCALING_1_2X 1.5 @@ -50,10 +44,6 @@ #define SCALING_METHOD_DISTORT "distort" #define SCALING_METHOD_BLUR "blur" -#define PARALLAX_DELAY_DEFAULT world.tick_lag -#define PARALLAX_DELAY_MED 1 -#define PARALLAX_DELAY_LOW 2 - #define SEC_DEPT_NONE "None" #define SEC_DEPT_RANDOM "Random" #define SEC_DEPT_ENGINEERING "Engineering" diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/rendering/atom_hud.dm similarity index 95% rename from code/__DEFINES/atom_hud.dm rename to code/__DEFINES/rendering/atom_hud.dm index 386473a3ae..f62a7f6103 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/rendering/atom_hud.dm @@ -62,9 +62,4 @@ #define ANTAG_HUD_FUGITIVE 25 #define ANTAG_HUD_HERETIC 26 -// Notification action types -#define NOTIFY_JUMP "jump" -#define NOTIFY_ATTACK "attack" -#define NOTIFY_ORBIT "orbit" - #define ADD_HUD_TO_COOLDOWN 20 //cooldown for being shown the images for any particular data hud diff --git a/code/__DEFINES/rendering/parallax.dm b/code/__DEFINES/rendering/parallax.dm new file mode 100644 index 0000000000..8170b4190d --- /dev/null +++ b/code/__DEFINES/rendering/parallax.dm @@ -0,0 +1,13 @@ +#define PARALLAX_DELAY_DEFAULT world.tick_lag +#define PARALLAX_DELAY_MED 1 +#define PARALLAX_DELAY_LOW 2 + +// WARNING - client.prefs uses this, if you change these make sure to update the code in preferences! +#define PARALLAX_DISABLE 0 +#define PARALLAX_LOW 1 +#define PARALLAX_MED 2 +#define PARALLAX_HIGH 3 +#define PARALLAX_INSANE 4 // default + +// keep this false until we can fix it being a seizure hazard/ugly as sin +#define PARALLAX_ROTATION_ANIMATIONS FALSE diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm index a188bf8363..862cc27f04 100644 --- a/code/__DEFINES/shuttles.dm +++ b/code/__DEFINES/shuttles.dm @@ -44,7 +44,6 @@ #define SHUTTLE_TRANSIT_BORDER 10 -#define PARALLAX_LOOP_TIME 25 #define HYPERSPACE_END_TIME 5 #define HYPERSPACE_WARMUP 1 diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices/color_matrix.dm similarity index 59% rename from code/__HELPERS/matrices.dm rename to code/__HELPERS/matrices/color_matrix.dm index 59fbb4ffc0..e4a4a9bb48 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices/color_matrix.dm @@ -1,85 +1,3 @@ -/matrix/proc/TurnTo(old_angle, new_angle) - . = new_angle - old_angle - Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT - -/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE) - if(!segments) - return - var/segment = 360/segments - if(!clockwise) - segment = -segment - var/list/matrices = list() - for(var/i in 1 to segments-1) - var/matrix/M = matrix(transform) - M.Turn(segment*i) - matrices += M - var/matrix/last = matrix(transform) - matrices += last - - speed /= segments - - if(parallel) - animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL) - else - animate(src, transform = matrices[1], time = speed, loops) - - for(var/i in 2 to segments) //2 because 1 is covered above - animate(transform = matrices[i], time = speed) - //doesn't have an object argument because this is "Stacking" with the animate call above - //3 billion% intentional - -//Dumps the matrix data in format a-f -/matrix/proc/tolist() - . = list() - . += a - . += b - . += c - . += d - . += e - . += f - -//Dumps the matrix data in a matrix-grid format -/* - a d 0 - b e 0 - c f 1 -*/ -/matrix/proc/togrid() - . = list() - . += a - . += d - . += 0 - . += b - . += e - . += 0 - . += c - . += f - . += 1 - -//The X pixel offset of this matrix -/matrix/proc/get_x_shift() - . = c - -//The Y pixel offset of this matrix -/matrix/proc/get_y_shift() - . = f - -/matrix/proc/get_x_skew() - . = b - -/matrix/proc/get_y_skew() - . = d - -//Skews a matrix in a particular direction -//Missing arguments are treated as no skew in that direction - -//As Rotation is defined as a scale+skew, these procs will break any existing rotation -//Unless the result is multiplied against the current matrix -/matrix/proc/set_skew(x = 0, y = 0) - b = x - d = y - - ///////////////////// // COLOUR MATRICES // ///////////////////// @@ -114,12 +32,64 @@ list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0 return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0) +/** + * Exxagerates or removes colors + */ +/proc/color_matrix_saturation_percent(percent) + if(percent == 0) + return color_matrix_identity() + percent = clamp(percent, -100, 100) + if(percent > 0) + percent *= 3 + var/x = 1 + percent / 100 + var/inv = 1 - x + var/R = LUMA_R * inv + var/G = LUMA_G * inv + var/B = LUMA_B * inv + + return list(R + x,R,R, G,G + x,G, B,B,B + x) + //Changes distance colors have from rgb(127,127,127) grey //1 is identity. 0 makes everything grey >1 blows out colors and greys /proc/color_matrix_contrast(value) var/add = (1 - value) / 2 return list(value,0,0,0, 0,value,0,0, 0,0,value,0, 0,0,0,1, add,add,add,0) +/** + * Exxagerates or removes brightness + */ +/proc/color_matrix_contrast_percent(percent) + var/static/list/delta_index = list( + 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, + 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, + 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, + 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, + 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, + 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, + 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, + 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, + 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, + 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, + 10.0) + percent = clamp(percent, -100, 100) + if(percent == 0) + return color_matrix_identity() + + var/x = 0 + if (percent < 0) + x = 127 + percent / 100 * 127; + else + x = percent % 1 + if(x == 0) + x = delta_index[percent] + else + x = delta_index[percent] * (1-x) + delta_index[percent+1] * x//use linear interpolation for more granularity. + x = x * 127 + 127 + + var/mult = x / 127 + var/add = 0.5 * (127-x) / 255 + return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add) + //Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys //0 is identity, 120 moves reds to greens, 240 moves reds to blues /proc/color_matrix_rotate_hue(angle) @@ -134,6 +104,26 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro 0,0,0,1, 0,0,0,0) +/** + * Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites + * TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone) + */ +/proc/color_matrix_rotation(angle) + if(angle == 0) + return color_matrix_identity() + angle = clamp(angle, -180, 180) + var/cos = cos(angle) + var/sin = sin(angle) + + var/constA = 0.143 + var/constB = 0.140 + var/constC = -0.283 + return list( + LUMA_R + cos * (1-LUMA_R) + sin * -LUMA_R, LUMA_R + cos * -LUMA_R + sin * constA, LUMA_R + cos * -LUMA_R + sin * -(1-LUMA_R), + LUMA_G + cos * -LUMA_G + sin * -LUMA_G, LUMA_G + cos * (1-LUMA_G) + sin * constB, LUMA_G + cos * -LUMA_G + sin * LUMA_G, + LUMA_B + cos * -LUMA_B + sin * (1-LUMA_B), LUMA_B + cos * -LUMA_B + sin * constC, LUMA_B + cos * (1-LUMA_B) + sin * LUMA_B + ) + //These next three rotate values about one axis only //x is the red axis, y is the green axis, z is the blue axis. /proc/color_matrix_rotate_x(angle) @@ -183,3 +173,9 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro */ /proc/rgb_construct_color_matrix(rr = 1, rg, rb, gr, gg = 1, gb, br, bg, bb = 1, cr, cg, cb) return list(rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb) + +/** + * Assembles a color matrix, defaulting to identity + */ +/proc/rgba_construct_color_matrix(rr = 1, rg, rb, ra, gr, gg = 1, gb, ga, br, bg, bb = 1, ba, ar, ag, ab, aa = 1, cr, cg, cb, ca) + return list(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, cr, cg, cb, ca) diff --git a/code/__HELPERS/matrices/transform_matrix.dm b/code/__HELPERS/matrices/transform_matrix.dm new file mode 100644 index 0000000000..251ef8151f --- /dev/null +++ b/code/__HELPERS/matrices/transform_matrix.dm @@ -0,0 +1,86 @@ +/matrix/proc/TurnTo(old_angle, new_angle) + . = new_angle - old_angle + Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT + +/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE) + if(!segments) + return + var/segment = 360/segments + if(!clockwise) + segment = -segment + var/list/matrices = list() + for(var/i in 1 to segments-1) + var/matrix/M = matrix(transform) + M.Turn(segment*i) + matrices += M + var/matrix/last = matrix(transform) + matrices += last + + speed /= segments + + if(parallel) + animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL) + else + animate(src, transform = matrices[1], time = speed, loops) + + for(var/i in 2 to segments) //2 because 1 is covered above + animate(transform = matrices[i], time = speed) + //doesn't have an object argument because this is "Stacking" with the animate call above + //3 billion% intentional + +//Dumps the matrix data in format a-f +/matrix/proc/tolist() + . = list() + . += a + . += b + . += c + . += d + . += e + . += f + +//Dumps the matrix data in a matrix-grid format +/* + a d 0 + b e 0 + c f 1 +*/ +/matrix/proc/togrid() + . = list() + . += a + . += d + . += 0 + . += b + . += e + . += 0 + . += c + . += f + . += 1 + +//The X pixel offset of this matrix +/matrix/proc/get_x_shift() + . = c + +//The Y pixel offset of this matrix +/matrix/proc/get_y_shift() + . = f + +/matrix/proc/get_x_skew() + . = b + +/matrix/proc/get_y_skew() + . = d + +//Skews a matrix in a particular direction +//Missing arguments are treated as no skew in that direction + +//As Rotation is defined as a scale+skew, these procs will break any existing rotation +//Unless the result is multiplied against the current matrix +/matrix/proc/set_skew(x = 0, y = 0) + b = x + d = y + +/** + * constructs a transform matrix, defaulting to identity + */ +/proc/transform_matrix_construct(a = 1, b, c, d = 1, e, f) + return matrix(a, b, c, d, e, f) diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index 1aaebc5f32..1609c5f208 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -152,7 +152,7 @@ continue to_chat(mob_to_teleport, announcement) SEND_SOUND(mob_to_teleport, meeting_sound) //no preferences here, you must hear the funny sound - mob_to_teleport.overlay_fullscreen("emergency_meeting", /atom/movable/screen/fullscreen/emergency_meeting, 1) + mob_to_teleport.overlay_fullscreen("emergency_meeting", /atom/movable/screen/fullscreen/scaled/emergency_meeting, 1) addtimer(CALLBACK(mob_to_teleport, /mob/.proc/clear_fullscreen, "emergency_meeting"), 3 SECONDS) if (is_station_level(mob_to_teleport.z)) //teleport the mob to the crew meeting diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 1b72cc71b1..773adc061f 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -470,51 +470,6 @@ else setDir(WEST, ismousemovement) -//debug -/atom/movable/screen/proc/scale_to(x1,y1) - if(!y1) - y1 = x1 - var/matrix/M = new - M.Scale(x1,y1) - transform = M - -/atom/movable/screen/click_catcher - icon = 'icons/mob/screen_gen.dmi' - icon_state = "catcher" - plane = CLICKCATCHER_PLANE - mouse_opacity = MOUSE_OPACITY_OPAQUE - screen_loc = "CENTER" - -#define MAX_SAFE_BYOND_ICON_SCALE_TILES (MAX_SAFE_BYOND_ICON_SCALE_PX / world.icon_size) -#define MAX_SAFE_BYOND_ICON_SCALE_PX (33 * 32) //Not using world.icon_size on purpose. - -/atom/movable/screen/click_catcher/proc/UpdateGreed(view_size_x = 15, view_size_y = 15) - var/icon/newicon = icon('icons/mob/screen_gen.dmi', "catcher") - var/ox = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_x) - var/oy = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_y) - var/px = view_size_x * world.icon_size - var/py = view_size_y * world.icon_size - var/sx = min(MAX_SAFE_BYOND_ICON_SCALE_PX, px) - var/sy = min(MAX_SAFE_BYOND_ICON_SCALE_PX, py) - newicon.Scale(sx, sy) - icon = newicon - screen_loc = "CENTER-[(ox-1)*0.5],CENTER-[(oy-1)*0.5]" - var/matrix/M = new - M.Scale(px/sx, py/sy) - transform = M - -/atom/movable/screen/click_catcher/Click(location, control, params) - var/list/modifiers = params2list(params) - if(modifiers["middle"] && iscarbon(usr)) - var/mob/living/carbon/C = usr - C.swap_hand() - else - var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr.client ? usr.client.eye : usr), usr.client) - params += "&catcher=1" - if(T) - T.Click(location, control, params) - . = 1 - /* MouseWheelOn */ /mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm deleted file mode 100644 index 81442b602f..0000000000 --- a/code/_onclick/hud/fullscreen.dm +++ /dev/null @@ -1,192 +0,0 @@ -/mob/proc/overlay_fullscreen(category, type, severity) - var/atom/movable/screen/fullscreen/screen = screens[category] - if (!screen || screen.type != type) - // needs to be recreated - clear_fullscreen(category, FALSE) - screens[category] = screen = new type() - else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view)) - // doesn't need to be updated - return screen - - screen.icon_state = "[initial(screen.icon_state)][severity]" - screen.severity = severity - if (client && screen.should_show_to(src)) - screen.update_for_view(client.view) - client.screen += screen - - return screen - -/mob/proc/clear_fullscreen(category, animated = 10) - var/atom/movable/screen/fullscreen/screen = screens[category] - if(!screen) - return - - screens -= category - - if(animated) - animate(screen, alpha = 0, time = animated) - addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME) - else - if(client) - client.screen -= screen - qdel(screen) - -/mob/proc/clear_fullscreen_after_animate(atom/movable/screen/fullscreen/screen) - if(client) - client.screen -= screen - qdel(screen) - -/mob/proc/clear_fullscreens() - for(var/category in screens) - clear_fullscreen(category) - -/mob/proc/hide_fullscreens() - if(client) - for(var/category in screens) - client.screen -= screens[category] - -/mob/proc/reload_fullscreen() - if(client) - var/atom/movable/screen/fullscreen/screen - for(var/category in screens) - screen = screens[category] - if(screen.should_show_to(src)) - screen.update_for_view(client.view) - client.screen |= screen - else - client.screen -= screen - -/atom/movable/screen/fullscreen - icon = 'icons/mob/screen_full.dmi' - icon_state = "default" - screen_loc = "CENTER-7,CENTER-7" - layer = FULLSCREEN_LAYER - plane = FULLSCREEN_PLANE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - var/view = 7 - var/severity = 0 - var/show_when_dead = FALSE - -/atom/movable/screen/fullscreen/proc/update_for_view(client_view) - if (screen_loc == "CENTER-7,CENTER-7" && view != client_view) - var/list/actualview = getviewsize(client_view) - view = client_view - transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0) - -/atom/movable/screen/fullscreen/proc/should_show_to(mob/mymob) - if(!show_when_dead && mymob.stat == DEAD) - return FALSE - return TRUE - -/atom/movable/screen/fullscreen/Destroy() - severity = 0 - . = ..() - -/atom/movable/screen/fullscreen/emergency_meeting - icon_state = "emergency_meeting" - show_when_dead = TRUE - layer = CURSE_LAYER - plane = SPLASHSCREEN_PLANE - -/atom/movable/screen/fullscreen/brute - icon_state = "brutedamageoverlay" - layer = UI_DAMAGE_LAYER - plane = FULLSCREEN_PLANE - -/atom/movable/screen/fullscreen/oxy - icon_state = "oxydamageoverlay" - layer = UI_DAMAGE_LAYER - plane = FULLSCREEN_PLANE - -/atom/movable/screen/fullscreen/crit - icon_state = "passage" - layer = CRIT_LAYER - plane = FULLSCREEN_PLANE - -/atom/movable/screen/fullscreen/crit/vision - icon_state = "oxydamageoverlay" - layer = BLIND_LAYER - -/atom/movable/screen/fullscreen/blind - icon_state = "blackimageoverlay" - layer = BLIND_LAYER - plane = FULLSCREEN_PLANE - -/atom/movable/screen/fullscreen/curse - icon_state = "curse" - layer = CURSE_LAYER - plane = FULLSCREEN_PLANE - -/atom/movable/screen/fullscreen/impaired - icon_state = "impairedoverlay" - -/atom/movable/screen/fullscreen/blurry - icon = 'icons/mob/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" - icon_state = "blurry" - -/atom/movable/screen/fullscreen/flash - icon = 'icons/mob/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" - icon_state = "flash" - -/atom/movable/screen/fullscreen/flash/static - icon = 'icons/mob/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" - icon_state = "noise" - -/atom/movable/screen/fullscreen/high - icon = 'icons/mob/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" - icon_state = "druggy" - -/atom/movable/screen/fullscreen/color_vision - icon = 'icons/mob/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" - icon_state = "flash" - alpha = 80 - -/atom/movable/screen/fullscreen/color_vision/green - color = "#00ff00" - -/atom/movable/screen/fullscreen/color_vision/red - color = "#ff0000" - -/atom/movable/screen/fullscreen/color_vision/blue - color = "#0000ff" - -/atom/movable/screen/fullscreen/cinematic_backdrop - icon = 'icons/mob/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" - icon_state = "flash" - plane = SPLASHSCREEN_PLANE - layer = SPLASHSCREEN_LAYER - 1 - color = "#000000" - show_when_dead = TRUE - -/atom/movable/screen/fullscreen/lighting_backdrop - icon = 'icons/mob/screen_gen.dmi' - icon_state = "flash" - transform = matrix(200, 0, 0, 0, 200, 0) - plane = LIGHTING_PLANE - blend_mode = BLEND_OVERLAY - show_when_dead = TRUE - -//Provides darkness to the back of the lighting plane -/atom/movable/screen/fullscreen/lighting_backdrop/lit - invisibility = INVISIBILITY_LIGHTING - layer = BACKGROUND_LAYER+21 - color = "#000" - show_when_dead = TRUE - -//Provides whiteness in case you don't see lights so everything is still visible -/atom/movable/screen/fullscreen/lighting_backdrop/unlit - layer = BACKGROUND_LAYER+20 - show_when_dead = TRUE - -/atom/movable/screen/fullscreen/see_through_darkness - icon_state = "nightvision" - plane = LIGHTING_PLANE - layer = LIGHTING_LAYER - blend_mode = BLEND_ADD - show_when_dead = TRUE diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 144a38e728..c5f57d9b78 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -133,7 +133,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( return FALSE screenmob.client.screen = list() - screenmob.client.apply_clickcatcher() + screenmob.client.update_clickcatcher() var/display_hud_version = version if(!display_hud_version) //If 0 or blank, display the next hud version @@ -193,8 +193,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( persistent_inventory_update(screenmob) screenmob.update_action_buttons(1) reorganize_alerts() - screenmob.reload_fullscreen() - update_parallax_pref(screenmob) // ensure observers get an accurate and up-to-date view if (!viewmob) @@ -204,6 +202,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list( else if (viewmob.hud_used) viewmob.hud_used.plane_masters_update() + screenmob.reload_rendering() + return TRUE /datum/hud/proc/plane_masters_update() diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 83b8d7be48..4fa2dd538a 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -174,7 +174,7 @@ /datum/hud/human/New(mob/living/carbon/human/owner) ..() - owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/see_through_darkness) + owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/special/see_through_darkness) var/widescreenlayout = FALSE //CIT CHANGE - adds support for different hud layouts depending on widescreen pref if(owner.client && owner.client.prefs && owner.client.prefs.widescreenpref) //CIT CHANGE - ditto diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm deleted file mode 100755 index a98fec03c4..0000000000 --- a/code/_onclick/hud/parallax.dm +++ /dev/null @@ -1,322 +0,0 @@ - -/datum/hud/proc/create_parallax(mob/viewmob) - var/mob/screenmob = viewmob || mymob - var/client/C = screenmob.client - if (!apply_parallax_pref(viewmob)) //don't want shit computers to crash when specing someone with insane parallax, so use the viewer's pref - return - - if(!length(C.parallax_layers_cached)) - C.parallax_layers_cached = list() - C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_1(null, C.view) - C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_2(null, C.view) - C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/planet(null, C.view) - if(SSparallax.random_layer) - C.parallax_layers_cached += new SSparallax.random_layer - C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_3(null, C.view) - - C.parallax_layers = C.parallax_layers_cached.Copy() - - if (length(C.parallax_layers) > C.parallax_layers_max) - C.parallax_layers.len = C.parallax_layers_max - - C.screen |= (C.parallax_layers) - var/atom/movable/screen/plane_master/PM = screenmob.hud_used.plane_masters["[PLANE_SPACE]"] - if(screenmob != mymob) - C.screen -= locate(/atom/movable/screen/plane_master/parallax_white) in C.screen - C.screen += PM - PM.color = list( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 1, 1, 1, 1, - 0, 0, 0, 0 - ) - - -/datum/hud/proc/remove_parallax(mob/viewmob) - var/mob/screenmob = viewmob || mymob - var/client/C = screenmob.client - C.screen -= (C.parallax_layers_cached) - var/atom/movable/screen/plane_master/PM = screenmob.hud_used.plane_masters["[PLANE_SPACE]"] - if(screenmob != mymob) - C.screen -= locate(/atom/movable/screen/plane_master/parallax_white) in C.screen - C.screen += PM - PM.color = initial(PM.color) - C.parallax_layers = null - -/datum/hud/proc/apply_parallax_pref(mob/viewmob) - var/mob/screenmob = viewmob || mymob - var/client/C = screenmob.client - if(C.prefs) - var/pref = C.prefs.parallax - if (isnull(pref)) - pref = PARALLAX_HIGH - switch(C.prefs.parallax) - if (PARALLAX_INSANE) - C.parallax_throttle = FALSE - C.parallax_layers_max = 5 - return TRUE - - if (PARALLAX_MED) - C.parallax_throttle = PARALLAX_DELAY_MED - C.parallax_layers_max = 3 - return TRUE - - if (PARALLAX_LOW) - C.parallax_throttle = PARALLAX_DELAY_LOW - C.parallax_layers_max = 1 - return TRUE - - if (PARALLAX_DISABLE) - return FALSE - - //This is high parallax. - C.parallax_throttle = PARALLAX_DELAY_DEFAULT - C.parallax_layers_max = 4 - return TRUE - -/datum/hud/proc/update_parallax_pref(mob/viewmob) - remove_parallax(viewmob) - create_parallax(viewmob) - update_parallax() - -// This sets which way the current shuttle is moving (returns true if the shuttle has stopped moving so the caller can append their animation) -/datum/hud/proc/set_parallax_movedir(new_parallax_movedir, skip_windups) - . = FALSE - var/client/C = mymob.client - if(new_parallax_movedir == C.parallax_movedir) - return - var/animatedir = new_parallax_movedir - if(new_parallax_movedir == FALSE) - var/animate_time = 0 - for(var/thing in C.parallax_layers) - var/atom/movable/screen/parallax_layer/L = thing - L.icon_state = initial(L.icon_state) - L.update_o(C.view) - var/T = PARALLAX_LOOP_TIME / L.speed - if (T > animate_time) - animate_time = T - C.dont_animate_parallax = world.time + min(animate_time, PARALLAX_LOOP_TIME) - animatedir = C.parallax_movedir - - var/matrix/newtransform - switch(animatedir) - if(NORTH) - newtransform = matrix(1, 0, 0, 0, 1, 480) - if(SOUTH) - newtransform = matrix(1, 0, 0, 0, 1,-480) - if(EAST) - newtransform = matrix(1, 0, 480, 0, 1, 0) - if(WEST) - newtransform = matrix(1, 0,-480, 0, 1, 0) - - var/shortesttimer - if(!skip_windups) - for(var/thing in C.parallax_layers) - var/atom/movable/screen/parallax_layer/L = thing - - var/T = PARALLAX_LOOP_TIME / L.speed - if (isnull(shortesttimer)) - shortesttimer = T - if (T < shortesttimer) - shortesttimer = T - L.transform = newtransform - animate(L, transform = matrix(), time = T, easing = QUAD_EASING | (new_parallax_movedir ? EASE_IN : EASE_OUT), flags = ANIMATION_END_NOW) - if (new_parallax_movedir) - L.transform = newtransform - animate(transform = matrix(), time = T) //queue up another animate so lag doesn't create a shutter - - C.parallax_movedir = new_parallax_movedir - if (C.parallax_animate_timer) - deltimer(C.parallax_animate_timer) - var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform) - if(skip_windups) - CB.InvokeAsync() - else - C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE) - - -/datum/hud/proc/update_parallax_motionblur(client/C, animatedir, new_parallax_movedir, matrix/newtransform) - if(!C) - return - C.parallax_animate_timer = FALSE - for(var/thing in C.parallax_layers) - var/atom/movable/screen/parallax_layer/L = thing - if (!new_parallax_movedir) - animate(L) - continue - - var/newstate = initial(L.icon_state) - var/T = PARALLAX_LOOP_TIME / L.speed - - if (newstate in icon_states(L.icon)) - L.icon_state = newstate - L.update_o(C.view) - - L.transform = newtransform - - animate(L, transform = matrix(), time = T, loop = -1, flags = ANIMATION_END_NOW) - -/datum/hud/proc/update_parallax() - var/client/C = mymob.client - var/turf/posobj = get_turf(C.eye) - if(!posobj) - return - var/area/areaobj = posobj.loc - - // Update the movement direction of the parallax if necessary (for shuttles) - set_parallax_movedir(areaobj.parallax_movedir, FALSE) - - var/force - if(!C.previous_turf || (C.previous_turf.z != posobj.z)) - C.previous_turf = posobj - force = TRUE - - if (!force && world.time < C.last_parallax_shift+C.parallax_throttle) - return - - //Doing it this way prevents parallax layers from "jumping" when you change Z-Levels. - var/offset_x = posobj.x - C.previous_turf.x - var/offset_y = posobj.y - C.previous_turf.y - - if(!offset_x && !offset_y && !force) - return - - var/last_delay = world.time - C.last_parallax_shift - last_delay = min(last_delay, C.parallax_throttle) - C.previous_turf = posobj - C.last_parallax_shift = world.time - - for(var/thing in C.parallax_layers) - var/atom/movable/screen/parallax_layer/L = thing - L.update_status(mymob) - if (L.view_sized != C.view) - L.update_o(C.view) - - var/change_x - var/change_y - - if(L.absolute) - L.offset_x = -(posobj.x - SSparallax.planet_x_offset) * L.speed - L.offset_y = -(posobj.y - SSparallax.planet_y_offset) * L.speed - else - change_x = offset_x * L.speed - L.offset_x -= change_x - change_y = offset_y * L.speed - L.offset_y -= change_y - - if(L.offset_x > 240) - L.offset_x -= 480 - if(L.offset_x < -240) - L.offset_x += 480 - if(L.offset_y > 240) - L.offset_y -= 480 - if(L.offset_y < -240) - L.offset_y += 480 - - - if(!areaobj.parallax_movedir && C.dont_animate_parallax <= world.time && (offset_x || offset_y) && abs(offset_x) <= max(C.parallax_throttle/world.tick_lag+1,1) && abs(offset_y) <= max(C.parallax_throttle/world.tick_lag+1,1) && (round(abs(change_x)) > 1 || round(abs(change_y)) > 1)) - L.transform = matrix(1, 0, offset_x*L.speed, 0, 1, offset_y*L.speed) - animate(L, transform=matrix(), time = last_delay) - - L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]" - -/atom/movable/proc/update_parallax_contents() - if(length(client_mobs_in_contents)) - for(var/thing in client_mobs_in_contents) - var/mob/M = thing - if(M?.client && M.hud_used && length(M.client.parallax_layers)) - M.hud_used.update_parallax() - -/mob/proc/update_parallax_teleport() //used for arrivals shuttle - if(client?.eye && hud_used && length(client.parallax_layers)) - var/area/areaobj = get_area(client.eye) - hud_used.set_parallax_movedir(areaobj.parallax_movedir, TRUE) - -/atom/movable/screen/parallax_layer - icon = 'icons/effects/parallax.dmi' - var/speed = 1 - var/offset_x = 0 - var/offset_y = 0 - var/view_sized - var/absolute = FALSE - blend_mode = BLEND_ADD - plane = PLANE_SPACE_PARALLAX - screen_loc = "CENTER-7,CENTER-7" - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - - -/atom/movable/screen/parallax_layer/Initialize(mapload, view) - . = ..() - if (!view) - view = world.view - update_o(view) - -/atom/movable/screen/parallax_layer/proc/update_o(view) - if (!view) - view = world.view - - var/list/viewscales = getviewsize(view) - var/countx = CEILING((viewscales[1]/2)/(480/world.icon_size), 1)+1 - var/county = CEILING((viewscales[2]/2)/(480/world.icon_size), 1)+1 - var/list/new_overlays = new - for(var/x in -countx to countx) - for(var/y in -county to county) - if(x == 0 && y == 0) - continue - var/mutable_appearance/texture_overlay = mutable_appearance(icon, icon_state) - texture_overlay.transform = matrix(1, 0, x*480, 0, 1, y*480) - new_overlays += texture_overlay - cut_overlays() - add_overlay(new_overlays) - view_sized = view - -/atom/movable/screen/parallax_layer/proc/update_status(mob/M) - return - -/atom/movable/screen/parallax_layer/layer_1 - icon_state = "layer1" - speed = 0.6 - layer = 1 - -/atom/movable/screen/parallax_layer/layer_2 - icon_state = "layer2" - speed = 1 - layer = 2 - -/atom/movable/screen/parallax_layer/layer_3 - icon_state = "layer3" - speed = 1.4 - layer = 3 - -/atom/movable/screen/parallax_layer/random - blend_mode = BLEND_OVERLAY - speed = 3 - layer = 3 - -/atom/movable/screen/parallax_layer/random/space_gas - icon_state = "space_gas" - -/atom/movable/screen/parallax_layer/random/space_gas/Initialize(mapload, view) - . = ..() - src.add_atom_colour(SSparallax.random_parallax_color, ADMIN_COLOUR_PRIORITY) - -/atom/movable/screen/parallax_layer/random/asteroids - icon_state = "asteroids" - -/atom/movable/screen/parallax_layer/planet - icon_state = "planet" - blend_mode = BLEND_OVERLAY - absolute = TRUE //Status of seperation - speed = 3 - layer = 30 - -/atom/movable/screen/parallax_layer/planet/update_status(mob/M) - var/client/C = M.client - var/turf/posobj = get_turf(C.eye) - if(!posobj) - return - invisibility = is_station_level(posobj.z) ? 0 : INVISIBILITY_ABSTRACT - -/atom/movable/screen/parallax_layer/planet/update_o() - return //Shit won't move diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index bb6a9cd925..d83a81fa45 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -124,8 +124,8 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT /atom/movable/screen/plane_master/lighting/backdrop(mob/mymob) - mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/lighting_backdrop/lit) - mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/lighting_backdrop/unlit) + mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/special/lighting_backdrop/lit) + mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/special/lighting_backdrop/unlit) /*! * This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers. @@ -143,7 +143,6 @@ add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE)) add_filter("object_lighting", 2, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE)) - /** * Handles emissive overlays and emissive blockers. */ @@ -163,9 +162,10 @@ plane = PLANE_SPACE_PARALLAX blend_mode = BLEND_MULTIPLY mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_target = PLANE_SPACE_PARALLAX_RENDER_TARGET /atom/movable/screen/plane_master/parallax_white - name = "parallax whitifier plane master" + name = "parallax backdrop/space turf plane master" plane = PLANE_SPACE /atom/movable/screen/plane_master/camera_static @@ -174,7 +174,6 @@ appearance_flags = PLANE_MASTER blend_mode = BLEND_OVERLAY - //Reserved to chat messages, so they are still displayed above the field of vision masking. /atom/movable/screen/plane_master/chat_messages name = "runechat plane master" diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index d431e6d3cd..78fc32480f 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -11,7 +11,6 @@ // Otherwise jump else if(A.loc) forceMove(get_turf(A)) - update_parallax_contents() /mob/dead/observer/ClickOn(var/atom/A, var/params) if(check_click_intercept(params,A)) diff --git a/code/game/alternate_appearance.dm b/code/_rendering/atom_huds/alternate_appearance.dm similarity index 100% rename from code/game/alternate_appearance.dm rename to code/_rendering/atom_huds/alternate_appearance.dm diff --git a/code/datums/hud.dm b/code/_rendering/atom_huds/atom_hud.dm similarity index 97% rename from code/datums/hud.dm rename to code/_rendering/atom_huds/atom_hud.dm index 1c23d5f2a0..07b403284b 100644 --- a/code/datums/hud.dm +++ b/code/_rendering/atom_huds/atom_hud.dm @@ -124,9 +124,3 @@ GLOBAL_LIST_INIT(huds, list( /mob/dead/new_player/reload_huds() return - -/mob/proc/add_click_catcher() - client.screen += client.void - -/mob/dead/new_player/add_click_catcher() - return diff --git a/code/game/data_huds.dm b/code/_rendering/atom_huds/data_huds.dm similarity index 100% rename from code/game/data_huds.dm rename to code/_rendering/atom_huds/data_huds.dm diff --git a/code/_rendering/clickcatcher/clickcatcher.dm b/code/_rendering/clickcatcher/clickcatcher.dm new file mode 100644 index 0000000000..524f753e98 --- /dev/null +++ b/code/_rendering/clickcatcher/clickcatcher.dm @@ -0,0 +1,74 @@ +/atom/movable/screen/click_catcher + icon = 'icons/screen/clickcatcher.dmi' + icon_state = "catcher" + appearance_flags = TILE_BOUND | NO_CLIENT_COLOR | RESET_TRANSFORM | RESET_COLOR | RESET_ALPHA + plane = CLICKCATCHER_PLANE + plane = CLICKCATCHER_PLANE + mouse_opacity = MOUSE_OPACITY_OPAQUE + screen_loc = "CENTER" + +/* +#define MAX_SAFE_BYOND_ICON_SCALE_TILES (MAX_SAFE_BYOND_ICON_SCALE_PX / world.icon_size) +#define MAX_SAFE_BYOND_ICON_SCALE_PX (33 * 32) //Not using world.icon_size on purpose. + +/atom/movable/screen/click_catcher/proc/UpdateFill(view_size_x = 15, view_size_y = 15) + var/icon/newicon = icon('icons/mob/screen_gen.dmi', "catcher") + var/ox = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_x) + var/oy = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_y) + var/px = view_size_x * world.icon_size + var/py = view_size_y * world.icon_size + var/sx = min(MAX_SAFE_BYOND_ICON_SCALE_PX, px) + var/sy = min(MAX_SAFE_BYOND_ICON_SCALE_PX, py) + newicon.Scale(sx, sy) + icon = newicon + screen_loc = "CENTER-[(ox-1)*0.5],CENTER-[(oy-1)*0.5]" + var/matrix/M = new + M.Scale(px/sx, py/sy) + transform = M + +#undef MAX_SAFE_BYOND_ICON_SCALE_TILES +#undef MAX_SAFE_BYOND_ICON_SCALE_PX +*/ + +/atom/movable/screen/click_catcher/proc/UpdateFill(view_size_x, view_size_y) + screen_loc = "1,1 to [view_size_x],[view_size_y]" + +/atom/movable/screen/click_catcher/Click(location, control, params) + var/list/modifiers = params2list(params) + if(modifiers["middle"] && iscarbon(usr)) + var/mob/living/carbon/C = usr + C.swap_hand() + else + var/turf/T = Parse(modifiers["screen-loc"], get_turf(usr.client?.eye || usr), usr.client) + params += "&catcher=1" + if(T) + T.Click(location, control, params) + return TRUE + +/atom/movable/screen/click_catcher/proc/Parse(scr_loc, turf/origin, client/C) + // screen-loc: Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]") + if(!scr_loc) + return null + var/tX = splittext(scr_loc, ",") + var/tY = splittext(tX[2], ":") + var/tZ = origin.z + tY = tY[1] + tX = splittext(tX[1], ":") + tX = tX[1] + var/list/actual_view = getviewsize(C ? C.view : world.view) + tX = clamp(origin.x + text2num(tX) - round(actual_view[1] / 2) - 1, 1, world.maxx) + tY = clamp(origin.y + text2num(tY) - round(actual_view[2] / 2) - 1, 1, world.maxy) + return locate(tX, tY, tZ) + +/** + * Makes a clickcatcher if necessary, and ensures it's fit to our size. + */ +/client/proc/update_clickcatcher(list/view_override) + if(!click_catcher) + click_catcher = new + screen |= click_catcher + if(view_override) + click_catcher.UpdateFill(view_override[1], view_override[2]) + else + var/list/view_list = getviewsize(view) + click_catcher.UpdateFill(view_list[1], view_list[2]) diff --git a/code/_rendering/fullscreen/fullscreen.dm b/code/_rendering/fullscreen/fullscreen.dm new file mode 100644 index 0000000000..dd8f697891 --- /dev/null +++ b/code/_rendering/fullscreen/fullscreen.dm @@ -0,0 +1,234 @@ +/** + * Adds a fullscreen overlay + * + * @params + * - category - string - must exist. will overwrite any other screen in this category. defaults to type. + * - type - the typepath of the screen + * - severity - severity - different screen objects have differing severities + */ +/mob/proc/overlay_fullscreen(category, type, severity) + ASSERT(type) + if(!category) + category = type + var/atom/movable/screen/fullscreen/screen = fullscreens[category] + if (!screen || screen.type != type) + // needs to be recreated + clear_fullscreen(category, 0) + fullscreens[category] = screen = new type + screen.SetSeverity(severity) + if(client && screen.ShouldShow(src)) + screen.SetView(client.view) + client.screen += screen + return screen + +/** + * Wipes a fullscreen of a certain category + * + * Second argument is for animation delay. + */ +/mob/proc/clear_fullscreen(category, animated = 10) + if(!fullscreens) + return + var/atom/movable/screen/fullscreen/screen = fullscreens[category] + fullscreens -= category + if(!screen) + return + if(animated > 0) + animate(screen, alpha = 0, time = animated) + addtimer(CALLBACK(src, .proc/_remove_fullscreen_direct, screen), animated, TIMER_CLIENT_TIME) + else + if(client) + client.screen -= screen + qdel(screen) + +/mob/proc/_remove_fullscreen_direct(atom/movable/screen/fullscreen/screen) + if(client) + client.screen -= screen + qdel(screen) + +/** + * Wipes all fullscreens + */ +/mob/proc/wipe_fullscreens() + for(var/category in fullscreens) + clear_fullscreen(category) + +/** + * Removes fullscreens from client but not the mob + */ +/mob/proc/hide_fullscreens() + if(client) + for(var/category in fullscreens) + client.screen -= fullscreens[category] + +/** + * Ensures all fullscreens are on client. + */ +/mob/proc/reload_fullscreen() + if(client) + var/atom/movable/screen/fullscreen/screen + for(var/category in fullscreens) + screen = fullscreens[category] + if(screen.ShouldShow(src)) + screen.SetView(client.view) + client.screen |= screen + else + client.screen -= screen + +/atom/movable/screen/fullscreen + icon = 'icons/screen/fullscreen_15x15.dmi' + icon_state = "default" + screen_loc = "CENTER-7,CENTER-7" + layer = FULLSCREEN_LAYER + plane = FULLSCREEN_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + /// current view we're adapted to + var/view_current + /// min severity + var/severity_min = 0 + /// max severity + var/severity_max = INFINITY + /// current severity + var/severity = 0 + /// show this while dead + var/show_when_dead = FALSE + +/atom/movable/screen/fullscreen/proc/SetSeverity(severity) + src.severity = clamp(severity, severity_min, severity_max) + icon_state = "[initial(icon_state)][severity]" + +/atom/movable/screen/fullscreen/proc/SetView(client_view) + view_current = client_view + +/atom/movable/screen/fullscreen/proc/ShouldShow(mob/M) + if(!show_when_dead && M.stat == DEAD) + return FALSE + return TRUE + +/atom/movable/screen/fullscreen/Destroy() + SetSeverity(0) + return ..() + +/atom/movable/screen/fullscreen/scaled + icon = 'icons/screen/fullscreen_15x15.dmi' + screen_loc = "CENTER-7,CENTER-7" + /// size of sprite in tiles + var/size_x = 15 + /// size of sprite in tiles + var/size_y = 15 + +/atom/movable/screen/fullscreen/scaled/SetView(client_view) + if(view_current != client_view) + var/list/actualview = getviewsize(client_view) + view_current = client_view + transform = matrix(actualview[1] / size_x, 0, 0, 0, actualview[2] / size_y, 0) + return ..() + +/atom/movable/screen/fullscreen/scaled/brute + icon_state = "brutedamageoverlay" + layer = UI_DAMAGE_LAYER + plane = FULLSCREEN_PLANE + +/atom/movable/screen/fullscreen/scaled/oxy + icon_state = "oxydamageoverlay" + layer = UI_DAMAGE_LAYER + plane = FULLSCREEN_PLANE + +/atom/movable/screen/fullscreen/scaled/crit + icon_state = "passage" + layer = CRIT_LAYER + plane = FULLSCREEN_PLANE + +/atom/movable/screen/fullscreen/scaled/crit/vision + icon_state = "oxydamageoverlay" + layer = BLIND_LAYER + +/atom/movable/screen/fullscreen/scaled/blind + icon_state = "blackimageoverlay" + layer = BLIND_LAYER + plane = FULLSCREEN_PLANE + +/atom/movable/screen/fullscreen/scaled/curse + icon_state = "curse" + layer = CURSE_LAYER + plane = FULLSCREEN_PLANE + +/atom/movable/screen/fullscreen/scaled/impaired + icon_state = "impairedoverlay" + +/atom/movable/screen/fullscreen/scaled/emergency_meeting + icon_state = "emergency_meeting" + show_when_dead = TRUE + layer = CURSE_LAYER + plane = SPLASHSCREEN_PLANE + +/atom/movable/screen/fullscreen/tiled/blurry + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "cloudy" + +/atom/movable/screen/fullscreen/tiled/flash + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "flash" + +/atom/movable/screen/fullscreen/tiled/flash/static + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "noise" + +/atom/movable/screen/fullscreen/tiled/high + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "druggy" + +/atom/movable/screen/fullscreen/tiled/color_vision + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "flash" + alpha = 80 + +/atom/movable/screen/fullscreen/tiled/color_vision/green + color = "#00ff00" + +/atom/movable/screen/fullscreen/tiled/color_vision/red + color = "#ff0000" + +/atom/movable/screen/fullscreen/tiled/color_vision/blue + color = "#0000ff" + +/atom/movable/screen/fullscreen/tiled/cinematic_backdrop + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "flash" + plane = SPLASHSCREEN_PLANE + layer = SPLASHSCREEN_LAYER - 1 + color = "#000000" + show_when_dead = TRUE + +/atom/movable/screen/fullscreen/special/lighting_backdrop + icon = 'icons/mob/screen_gen.dmi' + icon_state = "flash" + transform = matrix(200, 0, 0, 0, 200, 0) + plane = LIGHTING_PLANE + blend_mode = BLEND_OVERLAY + show_when_dead = TRUE + +//Provides darkness to the back of the lighting plane +/atom/movable/screen/fullscreen/special/lighting_backdrop/lit + invisibility = INVISIBILITY_LIGHTING + layer = BACKGROUND_LAYER+21 + color = "#000" + show_when_dead = TRUE + +//Provides whiteness in case you don't see lights so everything is still visible +/atom/movable/screen/fullscreen/special/lighting_backdrop/unlit + layer = BACKGROUND_LAYER+20 + show_when_dead = TRUE + +/atom/movable/screen/fullscreen/special/see_through_darkness + icon_state = "nightvision" + plane = LIGHTING_PLANE + layer = LIGHTING_LAYER + blend_mode = BLEND_ADD + show_when_dead = TRUE diff --git a/code/_rendering/mob.dm b/code/_rendering/mob.dm new file mode 100644 index 0000000000..49095d0910 --- /dev/null +++ b/code/_rendering/mob.dm @@ -0,0 +1,21 @@ +/** + * initializes screen rendering. call on mob new + */ +/mob/proc/init_rendering() + +/** + * loads screen rendering. call on mob login + */ +/mob/proc/reload_rendering() + if(!client.parallax_holder) + client.CreateParallax() + else + client.parallax_holder.Reset(force = TRUE) + client.update_clickcatcher() + reload_fullscreen() + +/** + * destroys screen rendering. call on mob del + */ +/mob/proc/dispose_rendering() + wipe_fullscreens() diff --git a/code/_rendering/parallax/parallax.dm b/code/_rendering/parallax/parallax.dm new file mode 100644 index 0000000000..dbd27ae762 --- /dev/null +++ b/code/_rendering/parallax/parallax.dm @@ -0,0 +1,28 @@ +/** + * Holds parallax information. + */ +/datum/parallax + /// List of parallax objects - these are cloned to a parallax holder using Clone on each. + var/list/atom/movable/screen/parallax_layer/objects + /// Parallax layers + var/layers = 0 + +/datum/parallax/New(create_objects = TRUE) + if(create_objects) + objects = CreateObjects() + layers = objects.len + +/datum/parallax/Destroy() + QDEL_LIST(objects) + return ..() + +/** + * Gets a new version of the objects inside - used when applying to a holder. + */ +/datum/parallax/proc/GetObjects() + . = list() + for(var/atom/movable/screen/parallax_layer/layer in objects) + . += layer.Clone() + +/datum/parallax/proc/CreateObjects() + . = objects = list() diff --git a/code/_rendering/parallax/parallax_holder.dm b/code/_rendering/parallax/parallax_holder.dm new file mode 100644 index 0000000000..8a9e4b71a9 --- /dev/null +++ b/code/_rendering/parallax/parallax_holder.dm @@ -0,0 +1,311 @@ +/** + * # Parallax holders + * + * Holds all the information about a client's parallax + * + * Not on mob because parallax is area based, not mob based. + * + * How parallax works: + * - Layers - normal layers, scroll with movement to relative position, can scroll + * - Absolute - absolute layers, scroll with movement to absolute position, cannot scroll + * - Vis - vis_contents-like model - things in this are directly applied and get no processing whatsoever. Things like overmap ships can use this. + */ +/datum/parallax_holder + /// Client that owns us + var/client/owner + /// The parallax object we're currently rendering + var/datum/parallax/parallax + /// Eye we were last anchored to - used to detect eye changes + var/atom/cached_eye + /// force this eye as the "real" eye - useful for secondary maps + var/atom/forced_eye + /// last turf loc + var/turf/last + /// last area - for parallax scrolling/loop animations + var/area/last_area + /// Holder object for vis + var/atom/movable/screen/parallax_vis/vis_holder + /// are we not on the main map? if so, put map id here + var/secondary_map + /// all layers + var/list/atom/movable/screen/parallax_layer/layers + /// vis contents + var/list/atom/movable/vis + /// currently scrolling? + var/scrolling = FALSE + /// current scroll speed in DS per scroll + var/scroll_speed + /// current scroll turn - applied after angle. if angle is 0 (picture moving north) and turn is 90, it would be like if you turned your viewport 90 deg clockwise. + var/scroll_turn + /// override planemaster we manipulate for turning and other effects + var/atom/movable/screen/plane_master/parallax/planemaster_override + +/datum/parallax_holder/New(client/C, secondary_map, forced_eye, planemaster_override) + owner = C + if(!owner) + CRASH("No client") + src.secondary_map = secondary_map + src.forced_eye = forced_eye + src.planemaster_override = planemaster_override + Reset() + +/datum/parallax_holder/Destroy() + if(owner) + if(owner.parallax_holder == src) + owner.parallax_holder = null + Remove() + HardResetAnimations() + QDEL_NULL(vis_holder) + QDEL_NULL(parallax) + layers = null + vis = null + last = null + forced_eye = cached_eye = null + owner = null + return ..() + +/datum/parallax_holder/proc/Reset(auto_z_change, force) + if(!(cached_eye = Eye())) + // if no eye, tear down + last = cached_eye = last_area = null + SetParallax(null, null, auto_z_change) + return + // first, check loc + var/turf/T = get_turf(cached_eye) + if(!T) + // if in nullspace, tear down + last = cached_eye = last_area = null + SetParallax(null, null, auto_z_change) + return + // set last loc and eye + last = T + last_area = T.loc + // rebuild parallax + SetParallax(SSparallax.get_parallax_datum(T.z), null, auto_z_change, force) + // hard reset positions to correct positions + for(var/atom/movable/screen/parallax_layer/L in layers) + L.ResetPosition(T.x, T.y) + +// better updates via client_mobs_in_contents can be created again when important recursive contents is ported! +/datum/parallax_holder/proc/Update(full) + if(!full && !cached_eye || (get_turf(cached_eye) == last)) + return + if(!owner) // why are we here + if(!QDELETED(src)) + qdel(src) + return + if(cached_eye != Eye()) + // eye mismatch, reset + Reset() + return + var/turf/T = get_turf(cached_eye) + if(!last || T.z != last.z) + // z mismatch, reset + Reset() + return + // get rel offsets + var/rel_x = T.x - last.x + var/rel_y = T.y - last.y + // set last + last = T + // move + for(var/atom/movable/screen/parallax_layer/L in layers) + L.RelativePosition(T.x, T.y, rel_x, rel_y) + // process scrolling/movedir + if(last_area != T.loc) + last_area = T.loc + UpdateMotion() + +/** + * Gets the eye we should be centered on + */ +/datum/parallax_holder/proc/Eye() + return forced_eye || owner?.eye + +/** + * Gets the base parallax planemaster for things like turning + */ +/datum/parallax_holder/proc/GetPlaneMaster() + return planemaster_override || (owner && (locate(/atom/movable/screen/plane_master/parallax) in owner?.screen)) + +/** + * Syncs us to our parallax objects. Does NOT check if we should have those objects, that's Reset()'s job. + * + * Doesn't move/update positions/screen locs either. + * + * Also ensures movedirs are correct for the eye's pos. + */ +/datum/parallax_holder/proc/Sync(auto_z_change, force) + layers = list() + for(var/atom/movable/screen/parallax_layer/L in parallax.objects) + layers += L + L.map_id = secondary_map + if(!istype(vis_holder)) + vis_holder = new /atom/movable/screen/parallax_vis + var/turf/T = get_turf(cached_eye) + vis_holder.vis_contents = vis = T? SSparallax.get_parallax_vis_contents(T.z) : list() + UpdateMotion(auto_z_change, force) + +/** + * Updates motion if needed + */ +/datum/parallax_holder/proc/UpdateMotion(auto_z_change, force) + var/turf/T = get_turf(cached_eye) + if(!T) + if(scroll_speed || scroll_turn) + HardResetAnimations() + return + var/list/ret = SSparallax.get_parallax_motion(T.z) + if(ret) + Animation(ret[1], ret[2], auto_z_change? 0 : ret[3], auto_z_change? 0 : ret[4], force) + else + var/area/A = T.loc + Animation(A.parallax_move_speed, A.parallax_move_angle, auto_z_change? 0 : null, auto_z_change? 0 : null, force) + +/datum/parallax_holder/proc/Apply(client/C = owner) + if(QDELETED(C)) + return + . = list() + for(var/atom/movable/screen/parallax_layer/L in layers) + if(L.parallax_intensity > owner.prefs.parallax) + continue + if(!L.ShouldSee(C, last)) + continue + L.SetView(C.view, TRUE) + . |= L + C.screen |= . + if(!secondary_map) + var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen + if(PM) + PM.color = list( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 1, 1, 1, 1, + 0, 0, 0, 0 + ) + +/datum/parallax_holder/proc/Remove(client/C = owner) + if(QDELETED(C)) + return + C.screen -= layers + if(!secondary_map) + var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen + if(PM) + PM.color = initial(PM.color) + +/datum/parallax_holder/proc/SetParallaxType(path) + if(!ispath(path, /datum/parallax)) + CRASH("Invalid path") + SetParallax(new path) + +/datum/parallax_holder/proc/SetParallax(datum/parallax/P, delete_old = TRUE, auto_z_change, force) + if(P == parallax) + return + Remove() + if(delete_old && istype(parallax) && !QDELETED(parallax)) + qdel(parallax) + HardResetAnimations() + parallax = P + if(!parallax) + return + Sync(auto_z_change, force) + Apply() + +/** + * Runs a modifier to parallax as an animation. + * + * @params + * speed - ds per loop + * turn - angle clockwise from north to turn the motion to + * windup - ds to spend on windups. 0 for immediate. + * turn_speed - ds to spend on turning. 0 for immediate. + */ +/datum/parallax_holder/proc/Animation(speed = 25, turn = 0, windup = speed, turn_speed = speed, force) + // Parallax doesn't currently use this method of rotating. + + // #if !PARALLAX_ROTATION_ANIMATIONS + // turn_speed = 0 + // #endif + + if(speed == 0) + StopScrolling(turn = turn, time = windup) + return + // if(turn != scroll_turn && GetPlaneMaster()) + // // first handle turn. we turn the planemaster + // var/matrix/turn_transform = matrix() + // turn_transform.Turn(turn) + // scroll_turn = turn + // animate(GetPlaneMaster(), transform = turn_transform, time = turn_speed, easing = QUAD_EASING | EASE_IN, flags = ANIMATION_END_NOW | ANIMATION_LINEAR_TRANSFORM) + if(scroll_speed == speed && !force) + // we're done + return + // speed diff? + scroll_speed = speed + scrolling = TRUE + // always scroll from north; turn handles everything + for(var/atom/movable/screen/parallax_layer/P in layers) + if(P.absolute) + continue + var/matrix/translate_matrix = matrix() + translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480) + var/matrix/target_matrix = matrix() + var/move_speed = speed * P.speed + // do the first segment by shifting down one screen + P.transform = translate_matrix + animate(P, transform = target_matrix, time = move_speed, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_END_NOW) + // queue up another incase lag makes QueueLoop not fire on time, this time by shifting up + animate(transform = translate_matrix, time = 0) + animate(transform = target_matrix, time = move_speed) + P.QueueLoop(move_speed, speed * P.speed, translate_matrix, target_matrix) + +/** + * Smoothly stops the animation, turning to a certain angle as needed. + */ +/datum/parallax_holder/proc/StopScrolling(turn = 0, time = 30) + // reset turn + if(turn != scroll_turn && GetPlaneMaster()) + var/matrix/turn_transform = matrix() + turn_transform.Turn(turn) + scroll_turn = turn + animate(GetPlaneMaster(), transform = turn_transform, time = time, easing = QUAD_EASING | EASE_OUT, flags = ANIMATION_END_NOW | ANIMATION_LINEAR_TRANSFORM) + if(scroll_speed == 0) + // we're done + scrolling = FALSE + scroll_speed = 0 + return + scrolling = FALSE + scroll_speed = 0 + // someone can do the math for "stop after a smooth iteration" later. + for(var/atom/movable/screen/parallax_layer/P in layers) + if(P.absolute) + continue + P.CancelAnimation() + var/matrix/translate_matrix = matrix() + translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480) + P.transform = translate_matrix + animate(P, transform = matrix(), time = time, easing = QUAD_EASING | EASE_OUT) + +/** + * fully resets animation state + */ +/datum/parallax_holder/proc/HardResetAnimations() + // reset vars + scroll_turn = 0 + scroll_speed = 0 + scrolling = FALSE + // reset turn + if(GetPlaneMaster()) + animate(GetPlaneMaster(), transform = matrix(), time = 0, flags = ANIMATION_END_NOW) + // reset objects + for(var/atom/movable/screen/parallax_layer/P in layers) + if(P.absolute) + continue + P.CancelAnimation() + animate(P, transform = matrix(), time = 0, flags = ANIMATION_END_NOW) + +/client/proc/CreateParallax() + if(!parallax_holder) + parallax_holder = new(src) +/atom/movable/screen/parallax_vis + screen_loc = "CENTER,CENTER" diff --git a/code/_rendering/parallax/parallax_object.dm b/code/_rendering/parallax/parallax_object.dm new file mode 100644 index 0000000000..8307fc5f08 --- /dev/null +++ b/code/_rendering/parallax/parallax_object.dm @@ -0,0 +1,137 @@ + +/atom/movable/screen/parallax_layer + icon = 'icons/screen/parallax.dmi' + blend_mode = BLEND_ADD + plane = PLANE_SPACE_PARALLAX + screen_loc = "CENTER-7,CENTER-7" + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + appearance_flags = PIXEL_SCALE | KEEP_TOGETHER + + // notice - all parallax layers are 15x15 tiles. They roll over every 240 pixels. + /// pixel x/y shift per real x/y + var/speed = 1 + /// current cached offset x + var/offset_x = 0 + /// current cached offset y + var/offset_y = 0 + /// normal centered x + var/center_x = 0 + /// normal centered y + var/center_y = 0 + /// absolute - always determine shift x/y as a function of real x/y instead of allowing for relative scroll. + var/absolute = FALSE + /// parallax level required to see this + var/parallax_intensity = PARALLAX_INSANE + /// current view we're adapted to + var/view_current + /// dynamic self tile - tile to our view size. set this to false for static parallax layers. + var/dynamic_self_tile = TRUE + /// map id + var/map_id + /// queued animation timerid + var/queued_animation + +/atom/movable/screen/parallax_layer/proc/ResetPosition(x, y) + // remember that our offsets/directiosn are relative to the player's viewport + // this means we need to scroll reverse to them. + offset_x = -(center_x + speed * x) + offset_y = -(center_y + speed * y) + if(!absolute) + if(offset_x > 240) + offset_x -= 480 + if(offset_x < -240) + offset_x += 480 + if(offset_y > 240) + offset_y -= 480 + if(offset_y < -240) + offset_y += 480 + screen_loc = "[map_id && "[map_id]:"]CENTER-7:[round(offset_x,1)],CENTER-7:[round(offset_y,1)]" + +/atom/movable/screen/parallax_layer/proc/RelativePosition(x, y, rel_x, rel_y) + if(absolute) + return ResetPosition(x, y) + offset_x -= rel_x * speed + offset_y -= rel_y * speed + if(offset_x > 240) + offset_x -= 480 + if(offset_x < -240) + offset_x += 480 + if(offset_y > 240) + offset_y -= 480 + if(offset_y < -240) + offset_y += 480 + screen_loc = "[map_id && "[map_id]:"]CENTER-7:[round(offset_x,1)],CENTER-7:[round(offset_y,1)]" + +/atom/movable/screen/parallax_layer/proc/SetView(client_view = world.view, force_update = FALSE) + if(view_current == client_view && !force_update) + return + view_current = client_view + if(!dynamic_self_tile) + return + var/list/real_view = getviewsize(client_view) + var/count_x = CEILING((real_view[1] / 2) / 15, 1) + 1 + var/count_y = CEILING((real_view[2] / 2) / 15, 1) + 1 + var/list/new_overlays = GetOverlays() + for(var/x in -count_x to count_x) + for(var/y in -count_y to count_y) + if(!x && !y) + continue + var/mutable_appearance/clone = new + // appearance clone + clone.icon = icon + clone.icon_state = icon_state + clone.overlays = GetOverlays() + // do NOT inherit our overlays! parallax layers should never have overlays, + // because if it inherited us it'll result in exponentially increasing overlays + // due to cut_overlays() above over there being a queue operation and not instant! + // clone.overlays = list() + // currently instantly using overlays =. + // clone.blend_mode = blend_mode + // clone.mouse_opacity = mouse_opacity + // clone.plane = plane + // clone.layer = layer + // shift to position + clone.transform = matrix(1, 0, x * 480, 0, 1, y * 480) + new_overlays += clone + overlays = new_overlays + +/atom/movable/screen/parallax_layer/proc/ShouldSee(client/C, atom/location) + return TRUE + +/** + * Return "natural" overlays, as we're goin to do some fuckery to overlays above. + */ +/atom/movable/screen/parallax_layer/proc/GetOverlays() + return list() + +/atom/movable/screen/parallax_layer/proc/Clone() + var/atom/movable/screen/parallax_layer/layer = new type + layer.speed = speed + layer.offset_x = offset_x + layer.offset_y = offset_y + layer.absolute = absolute + layer.parallax_intensity = parallax_intensity + layer.view_current = view_current + layer.appearance = appearance + +/atom/movable/screen/parallax_layer/proc/default_x() + return center_x + +/atom/movable/screen/parallax_layer/proc/default_y() + return center_y + +/atom/movable/screen/parallax_layer/proc/QueueLoop(delay, speed, matrix/translate_matrix, matrix/target_matrix) + if(queued_animation) + CancelAnimation() + queued_animation = addtimer(CALLBACK(src, .proc/_loop, speed, translate_matrix, target_matrix), delay, TIMER_STOPPABLE) + +/atom/movable/screen/parallax_layer/proc/_loop(speed, matrix/translate_matrix = matrix(1, 0, 0, 0, 1, 480), matrix/target_matrix = matrix()) + transform = translate_matrix + animate(src, transform = target_matrix, time = speed, loop = -1) + animate(transform = translate_matrix, time = 0) + queued_animation = null + +/atom/movable/screen/parallax_layer/proc/CancelAnimation() + if(queued_animation) + deltimer(queued_animation) + queued_animation = null diff --git a/code/_rendering/parallax/types/space.dm b/code/_rendering/parallax/types/space.dm new file mode 100644 index 0000000000..38ad62aede --- /dev/null +++ b/code/_rendering/parallax/types/space.dm @@ -0,0 +1,66 @@ +/datum/parallax/space + var/static/planet_offset_x = rand(100, 160) + var/static/planet_offset_y = rand(100, 160) + var/static/random_layer = pickweightAllowZero(list( + /atom/movable/screen/parallax_layer/space/random/asteroids = 35, + /atom/movable/screen/parallax_layer/space/random/space_gas = 35, + null = 30 + )) + var/static/random_gas_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE) + +/datum/parallax/space/CreateObjects() + . = ..() + . += new /atom/movable/screen/parallax_layer/space/layer_1 + . += new /atom/movable/screen/parallax_layer/space/layer_2 + . += new /atom/movable/screen/parallax_layer/space/layer_3 + var/atom/movable/screen/parallax_layer/space/planet/P = new + P.pixel_x = planet_offset_x + P.pixel_y = planet_offset_y + . += P + if(random_layer) + . += new random_layer + if(ispath(random_layer, /atom/movable/screen/parallax_layer/space/random/space_gas)) + var/atom/movable/screen/parallax_layer/space/random/space_gas/SG = locate(random_layer) in objects + SG.add_atom_colour(random_gas_color, ADMIN_COLOUR_PRIORITY) + +/atom/movable/screen/parallax_layer/space/layer_1 + icon_state = "layer1" + speed = 0.6 + layer = 1 + parallax_intensity = PARALLAX_LOW + +/atom/movable/screen/parallax_layer/space/layer_2 + icon_state = "layer2" + speed = 1 + layer = 2 + parallax_intensity = PARALLAX_MED + +/atom/movable/screen/parallax_layer/space/layer_3 + icon_state = "layer3" + speed = 1.4 + layer = 3 + parallax_intensity = PARALLAX_HIGH + +/atom/movable/screen/parallax_layer/space/random + blend_mode = BLEND_OVERLAY + speed = 3 + layer = 3 + parallax_intensity = PARALLAX_INSANE + +/atom/movable/screen/parallax_layer/space/random/space_gas + icon_state = "space_gas" + +/atom/movable/screen/parallax_layer/space/random/asteroids + icon_state = "asteroids" + +/atom/movable/screen/parallax_layer/space/planet + icon_state = "planet" + blend_mode = BLEND_OVERLAY + absolute = TRUE //Status of seperation + speed = 3 + layer = 30 + dynamic_self_tile = FALSE + +/atom/movable/screen/parallax_layer/space/planet/ShouldSee(client/C, atom/location) + var/turf/T = get_turf(location) + return ..() && T && is_station_level(T.z) diff --git a/code/controllers/subsystem/parallax.dm b/code/controllers/subsystem/parallax.dm index 86bd517602..248b33d86d 100644 --- a/code/controllers/subsystem/parallax.dm +++ b/code/controllers/subsystem/parallax.dm @@ -5,21 +5,6 @@ SUBSYSTEM_DEF(parallax) priority = FIRE_PRIORITY_PARALLAX runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT var/list/currentrun - var/planet_x_offset = 128 - var/planet_y_offset = 128 - var/random_layer - var/random_parallax_color - - -//These are cached per client so needs to be done asap so people joining at roundstart do not miss these. -/datum/controller/subsystem/parallax/PreInit() - . = ..() - if(prob(70)) //70% chance to pick a special extra layer - random_layer = pick(/atom/movable/screen/parallax_layer/random/space_gas, /atom/movable/screen/parallax_layer/random/asteroids) - random_parallax_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE)//Special color for random_layer1. Has to be done here so everyone sees the same color. [COLOR_SILVER] - planet_y_offset = rand(100, 160) - planet_x_offset = rand(100, 160) - /datum/controller/subsystem/parallax/fire(resumed = FALSE) if (!resumed) @@ -28,28 +13,82 @@ SUBSYSTEM_DEF(parallax) //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun - while(length(currentrun)) - var/client/processing_client = currentrun[currentrun.len] - currentrun.len-- - if (QDELETED(processing_client) || !processing_client.eye) + if(times_fired % 5) // lazy tick + while(length(currentrun)) + var/client/processing_client = currentrun[currentrun.len] + currentrun.len-- + if (QDELETED(processing_client) || !processing_client.eye) + if (MC_TICK_CHECK) + return + continue + processing_client.parallax_holder?.Update() if (MC_TICK_CHECK) return - continue - - var/atom/movable/movable_eye = processing_client.eye - if(!istype(movable_eye)) - continue - - for (movable_eye; isloc(movable_eye.loc) && !isturf(movable_eye.loc); movable_eye = movable_eye.loc); - - if(movable_eye == processing_client.movingmob) + else // full tick + while(length(currentrun)) + var/client/processing_client = currentrun[currentrun.len] + currentrun.len-- + if (QDELETED(processing_client) || !processing_client.eye) + if (MC_TICK_CHECK) + return + continue + processing_client.parallax_holder?.Update(TRUE) if (MC_TICK_CHECK) return - continue - if(!isnull(processing_client.movingmob)) - LAZYREMOVE(processing_client.movingmob.client_mobs_in_contents, processing_client.mob) - LAZYADD(movable_eye.client_mobs_in_contents, processing_client.mob) - processing_client.movingmob = movable_eye - if (MC_TICK_CHECK) - return + currentrun = null + +/** + * Gets parallax type for zlevel. + */ +/datum/controller/subsystem/parallax/proc/get_parallax_type(z) + return /datum/parallax/space + +/** + * Gets parallax for zlevel. + */ +/datum/controller/subsystem/parallax/proc/get_parallax_datum(z) + var/datum_type = get_parallax_type(z) + return new datum_type + +/** + * Gets parallax added vis contents for zlevel + */ +/datum/controller/subsystem/parallax/proc/get_parallax_vis_contents(z) + return list() + +/** + * Gets parallax motion for a zlevel + * + * Returns null or list(speed, dir deg clockwise from north, windup, turnrate) + * THE RETURNED LIST MUST BE A 4-TUPLE, OR PARALLAX WILL CRASH. + * DO NOT SCREW WITH THIS UNLESS YOU KNOW WHAT YOU ARE DOING. + * + * This will override area motion + */ +/datum/controller/subsystem/parallax/proc/get_parallax_motion(z) + return null + +/** + * updates all parallax for clients on a z + */ +/datum/controller/subsystem/parallax/proc/update_clients_on_z(z) + for(var/client/C in GLOB.clients) + if(C.mob.z == z) + C.parallax_holder?.Update() + +/** + * resets all parallax for clients on a z + */ +/datum/controller/subsystem/parallax/proc/reset_clients_on_z(z) + for(var/client/C in GLOB.clients) + if(C.mob.z == z) + C.parallax_holder?.Reset() + +/** + * updates motion of all clients on z + */ +/datum/controller/subsystem/parallax/proc/update_z_motion(z) + for(var/client/C in GLOB.clients) + if(C.mob.z == z) + C.parallax_holder?.UpdateMotion() diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 6af79d4d14..da295d70e2 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -513,7 +513,9 @@ SUBSYSTEM_DEF(shuttle) if(!midpoint) return FALSE var/area/shuttle/transit/A = new() - A.parallax_movedir = travel_dir + A.parallax_moving = TRUE + A.parallax_move_angle = dir2angle(travel_dir) + A.parallax_move_speed = M.parallax_speed A.contents = proposal.reserved_turfs var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint) new_transit_dock.reserved_area = proposal diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm index 2a8a0ea98a..6052b84364 100644 --- a/code/datums/cinematic.dm +++ b/code/datums/cinematic.dm @@ -101,7 +101,7 @@ if(!C) return watching += C - M.overlay_fullscreen("cinematic",/atom/movable/screen/fullscreen/cinematic_backdrop) + M.overlay_fullscreen("cinematic",/atom/movable/screen/fullscreen/tiled/cinematic_backdrop) C.screen += screen //Sound helper diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index 911ca7ecbe..c336213388 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -370,7 +370,7 @@ user.emote("scream") user.gain_trauma(/datum/brain_trauma/severe/paralysis/spinesnapped) // oopsie indeed! shake_camera(user, 7, 7) - user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash) + user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash) user.clear_fullscreen("flash", 4.5) if(94 to 98) @@ -381,7 +381,7 @@ user.gain_trauma_type(BRAIN_TRAUMA_MILD) user.playsound_local(get_turf(user), 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9) shake_camera(user, 6, 6) - user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash) + user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash) user.clear_fullscreen("flash", 3.5) if(84 to 93) @@ -394,7 +394,7 @@ user.playsound_local(get_turf(user), 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9) user.DefaultCombatKnockdown(40) shake_camera(user, 5, 5) - user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash) + user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash) user.clear_fullscreen("flash", 2.5) if(64 to 83) diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 2e0df8917d..a6562f2710 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -771,7 +771,7 @@ /datum/status_effect/necropolis_curse/proc/apply_curse(set_curse) curse_flags |= set_curse if(curse_flags & CURSE_BLINDING) - owner.overlay_fullscreen("curse", /atom/movable/screen/fullscreen/curse, 1) + owner.overlay_fullscreen("curse", /atom/movable/screen/fullscreen/scaled/curse, 1) /datum/status_effect/necropolis_curse/proc/remove_curse(remove_curse) if(remove_curse & CURSE_BLINDING) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 6ad95c8b56..b922f52315 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -50,7 +50,12 @@ var/has_gravity = FALSE - var/parallax_movedir = 0 + /// Parallax moving? + var/parallax_moving = FALSE + /// Parallax move speed - 0 to disable + var/parallax_move_speed = 0 + /// Parallax move dir - degrees clockwise from north + var/parallax_move_angle = 0 var/list/ambientsounds = GENERIC flags_1 = CAN_BE_DIRTY_1 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 391d3b467d..5da389fbb8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -28,7 +28,6 @@ var/pass_flags = 0 var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before. - var/list/client_mobs_in_contents // This contains all the client mobs within this container var/list/acted_explosions //for explosion dodging var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm @@ -108,8 +107,6 @@ for(var/movable_content in contents) qdel(movable_content) - LAZYCLEARLIST(client_mobs_in_contents) - moveToNullspace() /atom/movable/proc/update_emissive_block() diff --git a/code/game/atoms_movement.dm b/code/game/atoms_movement.dm index 43a22c9df0..9fd007e9ee 100644 --- a/code/game/atoms_movement.dm +++ b/code/game/atoms_movement.dm @@ -176,12 +176,8 @@ if (!inertia_moving) inertia_next_move = world.time + inertia_move_delay newtonian_move(Dir) - if (length(client_mobs_in_contents)) - update_parallax_contents() - return TRUE - // Make sure you know what you're doing if you call this, this is intended to only be called by byond directly. // You probably want CanPass() /atom/movable/Cross(atom/movable/AM) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 4d4ddf2f52..b680377d0a 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -407,7 +407,7 @@ /obj/machinery/camera/get_remote_view_fullscreens(mob/user) if(view_range == short_range) //unfocused - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2) + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 2) /obj/machinery/camera/update_remote_sight(mob/living/user) user.see_invisible = SEE_INVISIBLE_LIVING //can't see ghosts through cameras diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 9d675bc5dd..992807bed7 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -275,7 +275,7 @@ if(final) playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) remote_eye.setLoc(get_turf(final)) - C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static) + C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static) C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console! else playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index f01342a903..af4d098157 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -531,7 +531,7 @@ /obj/structure/closet/get_remote_view_fullscreens(mob/user) if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS))) - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1) /obj/structure/closet/emp_act(severity) . = ..() diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 6a588a61cd..73268009ce 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -139,7 +139,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/get_remote_view_fullscreens(mob/user) if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS))) - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2) + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 2) /* * Morgue */ diff --git a/code/modules/admin/callproc/callproc.dm b/code/modules/admin/callproc/callproc.dm index 21bf732493..a9c0984bbc 100644 --- a/code/modules/admin/callproc/callproc.dm +++ b/code/modules/admin/callproc/callproc.dm @@ -115,9 +115,9 @@ GLOBAL_PROTECT(LastAdminCalledProc) //adv proc call this, ya nerds /world/proc/WrapAdminProcCall(datum/target, procname, list/arguments) if(target == GLOBAL_PROC) - return call("/proc/[procname]")(arglist(arguments)) - else if(target != world) - return call(target, procname)(arglist(arguments)) + return text2path("/proc/[procname]")? call("/proc/[procname]")(arglist(arguments)) : null + else if(target != world && istype(target, /datum)) // isdatum check incase someone manages to call WrapAdminProcCall(global) which would otherwise crash the process entirely + return hascall(target, procname)? call(target, procname)(arglist(arguments)) : null else log_admin("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]") diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm index ca07f9a50b..79fd63adcc 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -3,11 +3,19 @@ /proc/_abs(A) return abs(A) -/proc/_animate(atom/A, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null) - var/mutable_appearance/MA = new() - for(var/v in set_vars) - MA.vars[v] = set_vars[v] - animate(A, appearance = MA, time, loop, easing, flags) +/proc/_animate(atom/A, list/data, time = 10, loop = 1, easing = LINEAR_EASING, flags = null) + if(!istype(A)) + return + animate(A, appearance = data, time = time, loop = loop, easing = easing, flags = flags) + +/proc/_animate_adv(atom/A, list/data, loop = 1, easing = LINEAR_EASING, flags = NONE) + if(!A || !islist(data) || data.len < 1) + return + animate(A, appearance = (data[1] - "time"), time = data[1]["time"], loop = loop, easing = easing, flags = flags) + if(data.len < 2) + return + for(var/i in 2 to data.len) + animate(appearance = (data[i] - "time"), time = data[i]["time"]) /proc/_acrccos(A) return arccos(A) diff --git a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm index 3609037f58..562d6a0c94 100644 --- a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm +++ b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm @@ -69,7 +69,7 @@ do_sparks(5, TRUE, AM) if(isliving(AM)) var/mob/living/L = AM - L.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static) + L.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static) L.clear_fullscreen("flash", 5) var/obj/item/transfer_valve/TTV = locate() in L.GetAllContents() if(TTV) diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm index 2391658613..44c57b77ad 100644 --- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm +++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm @@ -141,7 +141,7 @@ if(isliving(M.current) && M.current.stat != DEAD) var/turf/t_turf = isAI(M.current) ? get_step(get_step(src, NORTH),NORTH) : get_turf(src) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark. do_teleport(M.current, t_turf, channel = TELEPORT_CHANNEL_CULT, forced = TRUE) - M.current.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash) + M.current.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash) M.current.clear_fullscreen("flash", 5) playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE) recalls_remaining-- @@ -311,7 +311,7 @@ var/turf/T = get_turf(M) if(is_servant_of_ratvar(M) && (!T || T.z != z)) M.forceMove(get_step(src, SOUTH)) - M.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash) + M.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash) M.clear_fullscreen("flash", 5) progress_in_seconds += GATEWAY_SUMMON_RATE switch(progress_in_seconds) diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm index fd7e6fb98d..619129f679 100644 --- a/code/modules/antagonists/devil/true_devil/_true_devil.dm +++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm @@ -104,7 +104,7 @@ /mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) return 666 -/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0) +/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0) if(mind && has_bane(BANE_LIGHT)) mind.disrupt_spells(-500) return ..() //flashes don't stop devils UNLESS it's their bane. diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 6c9ce28bc7..c652a7f791 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -439,7 +439,7 @@ return // we don't see the pipe network while inside cryo. /obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user) - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1) /obj/machinery/atmospherics/components/unary/cryo_cell/can_crawl_through() return // can't ventcrawl in or out of cryo. diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 70aab57e0a..41c4480c74 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -4,6 +4,16 @@ //BLACK MAGIC THINGS// ////////////////////// parent_type = /datum + + /////////////// + // Rendering // + /////////////// + + /// Click catcher + var/atom/movable/screen/click_catcher/click_catcher + /// Parallax holder + var/datum/parallax_holder/parallax_holder + //////////////// //ADMIN THINGS// //////////////// @@ -153,20 +163,6 @@ ///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns var/cryo_warned = -5 MINUTES - var/list/parallax_layers - var/list/parallax_layers_cached - var/atom/movable/movingmob - var/turf/previous_turf - ///world.time of when we can state animate()ing parallax again - var/dont_animate_parallax - ///world.time of last parallax update - var/last_parallax_shift - ///ds between parallax updates - var/parallax_throttle = 0 - var/parallax_movedir = 0 - var/parallax_layers_max = 3 - var/parallax_animate_timer - /** * Assoc list with all the active maps - when a screen obj is added to * a map, it's put in here as well. diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index ccca7c93cb..9948802bc9 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -444,8 +444,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( send_resources() - generate_clickcatcher() - apply_clickcatcher() + update_clickcatcher() if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates. to_chat(src, "You have unread updates in the changelog.") @@ -535,9 +534,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( send2adminchat("Server", "[cheesy_message] (No admins online)") QDEL_LIST_ASSOC_VAL(char_render_holders) - if(movingmob != null) - movingmob.client_mobs_in_contents -= mob - UNSETEMPTY(movingmob.client_mobs_in_contents) // seen_messages = null Master.UpdateTickRate() . = ..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening @@ -1014,7 +1010,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( var/list/old_view = getviewsize(view) view = new_size var/list/actualview = getviewsize(view) - apply_clickcatcher(actualview) + update_clickcatcher() + parallax_holder.Reset() mob.reload_fullscreen() if (isliving(mob)) var/mob/living/M = mob @@ -1023,17 +1020,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( addtimer(CALLBACK(src,.verb/fit_viewport,10)) //Delayed to avoid wingets from Login calls. SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_CHANGE_VIEW, src, old_view, actualview) -/client/proc/generate_clickcatcher() - if(!void) - void = new() - screen += void - -/client/proc/apply_clickcatcher(list/actualview) - generate_clickcatcher() - if(!actualview) - actualview = getviewsize(view) - void.UpdateGreed(actualview[1],actualview[2]) - /client/proc/AnnouncePR(announcement) if(prefs && prefs.chat_toggles & CHAT_PULLR) to_chat(src, announcement) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 952a11338a..3272060835 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -164,7 +164,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/clientfps = 0 - var/parallax + var/parallax = PARALLAX_INSANE var/ambientocclusion = TRUE ///Should we automatically fit the viewport? @@ -2816,14 +2816,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) toggles ^= MIDROUND_ANTAG if("parallaxup") - parallax = WRAP(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) - if (parent && parent.mob && parent.mob.hud_used) - parent.mob.hud_used.update_parallax_pref(parent.mob) + parallax = WRAP(parallax + 1, PARALLAX_DISABLE, PARALLAX_INSANE + 1) + parent?.parallax_holder?.Reset() if("parallaxdown") - parallax = WRAP(parallax - 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) - if (parent && parent.mob && parent.mob.hud_used) - parent.mob.hud_used.update_parallax_pref(parent.mob) + parallax = WRAP(parallax - 1, PARALLAX_DISABLE, PARALLAX_INSANE + 1) + parent?.parallax_holder?.Reset() // Citadel edit - Prefs don't work outside of this. :c diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index f683ba0ee3..72b2f5d949 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -5,7 +5,7 @@ // You do not need to raise this if you are adding new values that have sane defaults. // Only raise this value when changing the meaning/format/name/layout of an existing value // where you would want the updater procs below to run -#define SAVEFILE_VERSION_MAX 52 +#define SAVEFILE_VERSION_MAX 53 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -343,6 +343,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car marking_list += list(list(part, old_marking_value, copied_color_list)) features["mam_body_markings"] = marking_list + if(current_version < 53) + parallax = PARALLAX_INSANE + /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) return @@ -469,7 +472,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles)) clientfps = sanitize_integer(clientfps, 0, 1000, 0) - parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null) + parallax = sanitize_integer(parallax, PARALLAX_DISABLE, PARALLAX_INSANE, null) ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport)) widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref)) diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index ce767ae00d..90b6da26fa 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -126,5 +126,5 @@ INITIALIZE_IMMEDIATE(/mob/dead) return ..() /mob/dead/onTransitZ(old_z,new_z) - ..() + . = ..() update_z(new_z) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 2068ed47e8..48244a91be 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -578,8 +578,6 @@ Spl.Fade(TRUE) character.playsound_local(get_turf(character), 'sound/voice/ApproachingTG.ogg', 25) - character.update_parallax_teleport() - job.standard_assign_skills(character.mind) SSticker.minds += character.mind diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 0f30fe20fc..624db8caf5 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -377,8 +377,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return ghostize(0, penalize = TRUE) - - /mob/dead/observer/Move(NewLoc, direct) if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, NewLoc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE) return @@ -388,7 +386,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(NewLoc) forceMove(NewLoc) - update_parallax_contents() else forceMove(get_turf(src)) //Get out of closets and such as a ghost if((direct & NORTH) && y < world.maxy) @@ -487,9 +484,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!L || !L.len) to_chat(usr, "No area available.") return - usr.forceMove(pick(L)) - update_parallax_contents() /mob/dead/observer/proc/view_gas() set category = "Ghost" @@ -568,7 +563,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination. A.forceMove(T) - A.update_parallax_contents() else to_chat(A, "This mob is not located in the game world.") diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index 94ebf42a2a..32f775ed46 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -165,7 +165,7 @@ /** * Actual proc that removes us and puts us back on lobby - * + * * Returns the new mob. */ /mob/dead/observer/proc/transfer_to_lobby() @@ -174,8 +174,7 @@ return client.screen.Cut() client.view_size.resetToDefault() - client.generate_clickcatcher() - client.apply_clickcatcher() + client.update_clickcatcher() client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref)) client.view_size.resetToDefault() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 6acd604ca5..61839ce123 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -646,7 +646,7 @@ become_blind(EYES_COVERED) else if(tinttotal >= TINT_DARKENED) cure_blind(EYES_COVERED) - overlay_fullscreen("tint", /atom/movable/screen/fullscreen/impaired, 2) + overlay_fullscreen("tint", /atom/movable/screen/fullscreen/scaled/impaired, 2) else cure_blind(EYES_COVERED) clear_fullscreen("tint", 0) @@ -722,10 +722,10 @@ visionseverity = 9 if(-INFINITY to -24) visionseverity = 10 - overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/crit/vision, visionseverity) + overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/scaled/crit/vision, visionseverity) else clear_fullscreen("critvision") - overlay_fullscreen("crit", /atom/movable/screen/fullscreen/crit, severity) + overlay_fullscreen("crit", /atom/movable/screen/fullscreen/scaled/crit, severity) else clear_fullscreen("crit") clear_fullscreen("critvision") @@ -749,7 +749,7 @@ severity = 6 if(45 to INFINITY) severity = 7 - overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/oxy, severity) + overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/scaled/oxy, severity) else clear_fullscreen("oxy") @@ -770,7 +770,7 @@ severity = 5 if(85 to INFINITY) severity = 6 - overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity) + overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity) else clear_fullscreen("brute") diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 46ba9a5eb0..a12d6614fa 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -361,7 +361,7 @@ return embeds -/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0) +/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0) . = ..() var/damage = override_protection ? intensity : intensity - get_eye_protection() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index c75654e10b..199a6b44be 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -209,7 +209,7 @@ update_tint() if(G.vision_correction) if(HAS_TRAIT(src, TRAIT_NEARSIGHT)) - overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1) + overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/scaled/impaired, 1) if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha)) update_sight() if(!QDELETED(src)) diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm index 5b5aa9d5c0..f7cb0e0760 100644 --- a/code/modules/mob/living/carbon/status_procs.dm +++ b/code/modules/mob/living/carbon/status_procs.dm @@ -5,7 +5,7 @@ /mob/living/carbon/adjust_drugginess(amount) druggy = max(druggy+amount, 0) if(druggy) - overlay_fullscreen("high", /atom/movable/screen/fullscreen/high) + overlay_fullscreen("high", /atom/movable/screen/fullscreen/tiled/high) throw_alert("high", /atom/movable/screen/alert/high) SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high) sound_environment_override = SOUND_ENVIRONMENT_DRUGGED @@ -18,7 +18,7 @@ /mob/living/carbon/set_drugginess(amount) druggy = max(amount, 0) if(druggy) - overlay_fullscreen("high", /atom/movable/screen/fullscreen/high) + overlay_fullscreen("high", /atom/movable/screen/fullscreen/tiled/high) throw_alert("high", /atom/movable/screen/alert/high) else clear_fullscreen("high") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 28fd4e0451..2070d07e14 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -579,7 +579,7 @@ UNLINT(livingdoll.filters += filter(type="alpha", icon = mob_mask)) livingdoll.filters += filter(type="drop_shadow", size = -1) if(severity > 0) - overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity) + overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity) else clear_fullscreen("brute") diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 7423a164a4..5ce80c5575 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -539,7 +539,7 @@ //called when the mob receives a bright flash -/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0) +/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0) if((override_protection || get_eye_protection() < intensity) && (override_blindness_check || !(HAS_TRAIT(src, TRAIT_BLIND)))) overlay_fullscreen("flash", type) addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index dcaa28b39c..3fad48e584 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -84,7 +84,6 @@ if(ai.client && !ai.multicam_on) ai.client.eye = src update_ai_detect_hud() - update_parallax_contents() //Holopad if(istype(ai.current, /obj/machinery/holopad)) var/obj/machinery/holopad/H = ai.current diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm index c2bc49f9a8..07cb671706 100644 --- a/code/modules/mob/living/silicon/pai/death.dm +++ b/code/modules/mob/living/silicon/pai/death.dm @@ -4,7 +4,7 @@ stat = DEAD update_mobility() update_sight() - clear_fullscreens() + wipe_fullscreens() //New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here. remove_from_alive_mob_list() diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 6c9d508fd8..55d0336671 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -144,6 +144,6 @@ P.on_hit(src, 0, def_zone) return BULLET_ACT_HIT -/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/static) +/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash/static) if(affect_silicon) return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index de6b858f79..be596b0292 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -113,7 +113,7 @@ While using this makes the system rely on OnFire, it still gives options for tim severity = 7 hud_used.healths.icon_state = "elite_health[severity]" if(severity > 0) - overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity) + overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity) else clear_fullscreen("brute") diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 02e88e3741..498ca19a39 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -599,7 +599,7 @@ /mob/living/proc/become_nearsighted(source) if(!HAS_TRAIT(src, TRAIT_NEARSIGHT)) - overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1) + overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/scaled/impaired, 1) ADD_TRAIT(src, TRAIT_NEARSIGHT, source) /mob/living/proc/cure_husk(source) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 7d2daac326..aac55c614b 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -58,10 +58,6 @@ //readd this mob's HUDs (antag, med, etc) reload_huds() - reload_fullscreen() // Reload any fullscreen overlays this mob has. - - add_click_catcher() - sync_mind() //Reload alternate appearances @@ -93,6 +89,9 @@ if(has_field_of_vision && CONFIG_GET(flag/use_field_of_vision)) LoadComponent(/datum/component/field_of_vision, field_of_vision_type) + // load rendering + reload_rendering() + AddElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds) // optimized area sound effects. Enable during events (compile flag when 😳) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index d240f97a23..03c5e76e87 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1,25 +1,3 @@ -/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. - remove_from_mob_list() - remove_from_dead_mob_list() - remove_from_alive_mob_list() - GLOB.all_clockwork_mobs -= src - focus = null - LAssailant = null - movespeed_modification = null - for (var/alert in alerts) - clear_alert(alert, TRUE) - if(observers && observers.len) - for(var/M in observers) - var/mob/dead/observe = M - observe.reset_perspective(null) - qdel(hud_used) - for(var/cc in client_colours) - qdel(cc) - client_colours = null - ghostize() - ..() - return QDEL_HINT_HARDDEL - /mob/Initialize() add_to_mob_list() if(stat == DEAD) @@ -38,8 +16,32 @@ update_config_movespeed() update_movespeed(TRUE) initialize_actionspeed() + init_rendering() hook_vr("mob_new",list(src)) +/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. + remove_from_mob_list() + remove_from_dead_mob_list() + remove_from_alive_mob_list() + GLOB.all_clockwork_mobs -= src + focus = null + LAssailant = null + movespeed_modification = null + for (var/alert in alerts) + clear_alert(alert, TRUE) + if(observers && observers.len) + for(var/M in observers) + var/mob/dead/observe = M + observe.reset_perspective(null) + dispose_rendering() + qdel(hud_used) + for(var/cc in client_colours) + qdel(cc) + client_colours = null + ghostize() + ..() + return QDEL_HINT_HARDDEL + /mob/GenerateTag() tag = "mob_[next_mob_id++]" diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 8e6226069c..527b0c0917 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -16,6 +16,10 @@ attack_hand_unwieldlyness = CLICK_CD_MELEE attack_hand_speed = 0 + // Rendering + /// Fullscreen objects + var/list/fullscreens = list() + /// What receives our keyboard input. src by default. var/datum/focus @@ -143,7 +147,6 @@ var/registered_z var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly - var/list/screens = list() var/list/client_colours = list() var/hud_type = /datum/hud diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index bfd4cfcd29..1da355a419 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -110,6 +110,11 @@ SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay) +/mob/Moved(atom/OldLoc, Dir) + . = ..() + if(client) + client.parallax_holder.Update() + /// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement. /client/proc/Process_Grab() if(mob.pulledby) @@ -398,3 +403,8 @@ /mob/proc/canZMove(direction, turf/target) return FALSE + +/mob/onTransitZ(old_z, new_z) + . = ..() + if(old_z != new_z) + client?.parallax_holder?.Reset() diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 089484ea9f..da1919443a 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -53,7 +53,7 @@ if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness if(stat == CONSCIOUS || stat == SOFT_CRIT) throw_alert("blind", /atom/movable/screen/alert/blind) - overlay_fullscreen("blind", /atom/movable/screen/fullscreen/blind) + overlay_fullscreen("blind", /atom/movable/screen/fullscreen/scaled/blind) // You are blind why should you be able to make out details like color, only shapes near you // add_client_colour(/datum/client_colour/monochrome/blind) else // CONSCIOUS no blind trait, no blindness diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 7fc57ee3a7..85b5cdac51 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -465,7 +465,7 @@ /obj/machinery/disposal/bin/get_remote_view_fullscreens(mob/user) if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS))) - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2) + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 2) //Delivery Chute diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index 7109c87999..4a03844a33 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -302,7 +302,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) user.reset_perspective(parentSphere) user.set_machine(src) var/datum/action/peepholeCancel/PHC = new - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1) PHC.Grant(user) return TRUE diff --git a/code/modules/shuttle/docking.dm b/code/modules/shuttle/docking.dm index 5c96bca07c..103e331039 100644 --- a/code/modules/shuttle/docking.dm +++ b/code/modules/shuttle/docking.dm @@ -162,7 +162,7 @@ for(var/i in 1 to areas_to_move.len) CHECK_TICK var/area/internal_area = areas_to_move[i] - internal_area.afterShuttleMove(new_parallax_dir) //areas + internal_area.afterShuttleMove(new_parallax_dir, parallax_speed) //areas for(var/i in 1 to old_turfs.len) CHECK_TICK diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index cc37fbbcc4..2a15558e64 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -461,11 +461,11 @@ for(var/area/shuttle/escape/E in GLOB.sortedAreas) areas += E hyperspace_sound(HYPERSPACE_END, areas) - if(time_left <= PARALLAX_LOOP_TIME) + if(time_left <= parallax_speed) var/area_parallax = FALSE for(var/place in shuttle_areas) var/area/shuttle/shuttle_area = place - if(shuttle_area.parallax_movedir) + if(shuttle_area.parallax_moving) area_parallax = TRUE break if(area_parallax) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index a215b58b55..029d50585a 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -356,7 +356,7 @@ playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) remote_eye.setLoc(T) to_chat(target, "Jumped to [selected]") - C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static) + C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static) C.clear_fullscreen("flash", 3) else playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, 0) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 8c1b3fa955..ceb9b7adea 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -117,8 +117,6 @@ All ShuttleMove procs go here if(rotation) shuttleRotate(rotation) - update_parallax_contents() - return TRUE /atom/movable/proc/lateShuttleMove(turf/oldT, list/movement_force, move_dir) @@ -153,16 +151,21 @@ All ShuttleMove procs go here //The old turf has now been given back to the area that turf originaly belonged to var/area/old_dest_area = newT.loc - parallax_movedir = old_dest_area.parallax_movedir - + parallax_moving = old_dest_area.parallax_moving + parallax_move_angle = old_dest_area.parallax_move_angle + parallax_move_speed = old_dest_area.parallax_move_speed old_dest_area.contents -= newT contents += newT newT.change_area(old_dest_area, src) return TRUE // Called on areas after everything has been moved -/area/proc/afterShuttleMove(new_parallax_dir) - parallax_movedir = new_parallax_dir +/area/proc/afterShuttleMove(new_parallax_dir, speed) + if(!new_parallax_dir) + parallax_moving = FALSE + return + parallax_move_angle = dir2angle(new_parallax_dir) + parallax_move_speed = speed return TRUE /area/proc/lateShuttleMove() @@ -309,6 +312,7 @@ All ShuttleMove procs go here if(buckled) shake_force *= 0.25 shake_camera(src, shake_force, 1) + client?.parallax_holder?.Reset(auto_z_change = FALSE, force = TRUE) /mob/living/lateShuttleMove(turf/oldT, list/movement_force, move_dir) if(buckled) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 0eb7f6ee20..d3e52410d6 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -367,6 +367,9 @@ var/can_move_docking_ports = FALSE var/list/hidden_turfs = list() + /// parallax speed in seconds per loop + var/parallax_speed = 25 + /obj/docking_port/mobile/register(replace = FALSE) . = ..() if(!id) @@ -709,27 +712,24 @@ create_ripples(destination, tl) var/obj/docking_port/stationary/S0 = get_docked() - if(istype(S0, /obj/docking_port/stationary/transit) && timeLeft(1) <= PARALLAX_LOOP_TIME) + if(istype(S0, /obj/docking_port/stationary/transit) && timeLeft(1) <= parallax_speed) + var/parallax_ongoing = FALSE for(var/place in shuttle_areas) var/area/shuttle/shuttle_area = place - if(shuttle_area.parallax_movedir) - parallax_slowdown() + if(shuttle_area.parallax_moving) + parallax_ongoing = TRUE + if(parallax_ongoing) + parallax_slowdown() /obj/docking_port/mobile/proc/parallax_slowdown() - for(var/place in shuttle_areas) - var/area/shuttle/shuttle_area = place - shuttle_area.parallax_movedir = FALSE - if(assigned_transit?.assigned_area) - assigned_transit.assigned_area.parallax_movedir = FALSE - var/list/L0 = return_ordered_turfs(x, y, z, dir) - for (var/thing in L0) - var/turf/T = thing - if(!T || !istype(T.loc, area_type)) - continue - for (var/thing2 in T) - var/atom/movable/AM = thing2 - if (length(AM.client_mobs_in_contents)) - AM.update_parallax_contents() + for(var/mob/M in GLOB.player_list) + var/area/A = get_area(M) + if(A in shuttle_areas) + M.client?.parallax_holder?.StopScrolling(A.parallax_move_angle, parallax_speed) + for(var/area/shuttle_area in shuttle_areas + assigned_transit?.assigned_area) + shuttle_area.parallax_moving = FALSE + shuttle_area.parallax_move_speed = 0 + shuttle_area.parallax_move_angle = 0 /obj/docking_port/mobile/proc/check_transit_zone() if(assigned_transit) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 9861a1b639..06865a0f39 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -41,7 +41,7 @@ return switch(eye_damaged) if(BLURRY_VISION_ONE, BLURRY_VISION_TWO) - owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/impaired, eye_damaged) + owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/scaled/impaired, eye_damaged) if(BLIND_VISION_THREE) owner.become_blind(EYE_DAMAGE) if(ishuman(owner)) @@ -106,7 +106,7 @@ else if(eye_damaged == BLIND_VISION_THREE) owner.become_blind(EYE_DAMAGE) if(eye_damaged && eye_damaged != BLIND_VISION_THREE) - owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/impaired, eye_damaged) + owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/scaled/impaired, eye_damaged) else owner.clear_fullscreen("eye_damage") diff --git a/icons/screen/clickcatcher.dmi b/icons/screen/clickcatcher.dmi new file mode 100644 index 0000000000..50a3616991 Binary files /dev/null and b/icons/screen/clickcatcher.dmi differ diff --git a/icons/screen/fullscreen_15x15.dmi b/icons/screen/fullscreen_15x15.dmi new file mode 100644 index 0000000000..502e9ad3f9 Binary files /dev/null and b/icons/screen/fullscreen_15x15.dmi differ diff --git a/icons/screen/fullscreen_tiled.dmi b/icons/screen/fullscreen_tiled.dmi new file mode 100644 index 0000000000..11b70842ec Binary files /dev/null and b/icons/screen/fullscreen_tiled.dmi differ diff --git a/icons/screen/parallax.dmi b/icons/screen/parallax.dmi new file mode 100644 index 0000000000..36dd36ee7a Binary files /dev/null and b/icons/screen/parallax.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 50a44347a4..38e9409074 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -28,7 +28,6 @@ #include "code\__DEFINES\admin.dm" #include "code\__DEFINES\antagonists.dm" #include "code\__DEFINES\atmospherics.dm" -#include "code\__DEFINES\atom_hud.dm" #include "code\__DEFINES\blackmarket.dm" #include "code\__DEFINES\botany.dm" #include "code\__DEFINES\callbacks.dm" @@ -37,7 +36,6 @@ #include "code\__DEFINES\citadel_defines.dm" #include "code\__DEFINES\cleaning.dm" #include "code\__DEFINES\clockcult.dm" -#include "code\__DEFINES\colors.dm" #include "code\__DEFINES\combat.dm" #include "code\__DEFINES\configuration.dm" #include "code\__DEFINES\construction.dm" @@ -144,6 +142,9 @@ #include "code\__DEFINES\_flags\shields.dm" #include "code\__DEFINES\admin\keybindings.dm" #include "code\__DEFINES\chemistry\reactions.dm" +#include "code\__DEFINES\color\color_priority.dm" +#include "code\__DEFINES\color\colors.dm" +#include "code\__DEFINES\color\lum.dm" #include "code\__DEFINES\combat\attack_types.dm" #include "code\__DEFINES\combat\block.dm" #include "code\__DEFINES\combat\block_parry.dm" @@ -155,6 +156,8 @@ #include "code\__DEFINES\material\worth.dm" #include "code\__DEFINES\mobs\innate_abilities.dm" #include "code\__DEFINES\mobs\slowdowns.dm" +#include "code\__DEFINES\rendering\atom_hud.dm" +#include "code\__DEFINES\rendering\parallax.dm" #include "code\__DEFINES\research\anomalies.dm" #include "code\__DEFINES\research\stock_parts.dm" #include "code\__DEFINES\skills\defines.dm" @@ -187,7 +190,6 @@ #include "code\__HELPERS\level_traits.dm" #include "code\__HELPERS\lighting.dm" #include "code\__HELPERS\markov.dm" -#include "code\__HELPERS\matrices.dm" #include "code\__HELPERS\mobs.dm" #include "code\__HELPERS\mouse_control.dm" #include "code\__HELPERS\names.dm" @@ -212,6 +214,8 @@ #include "code\__HELPERS\verbs.dm" #include "code\__HELPERS\view.dm" #include "code\__HELPERS\yelling.dm" +#include "code\__HELPERS\matrices\color_matrix.dm" +#include "code\__HELPERS\matrices\transform_matrix.dm" #include "code\__HELPERS\sorts\__main.dm" #include "code\__HELPERS\sorts\InsertSort.dm" #include "code\__HELPERS\sorts\MergeSort.dm" @@ -267,7 +271,6 @@ #include "code\_onclick\hud\credits.dm" #include "code\_onclick\hud\devil.dm" #include "code\_onclick\hud\drones.dm" -#include "code\_onclick\hud\fullscreen.dm" #include "code\_onclick\hud\generic_dextrous.dm" #include "code\_onclick\hud\ghost.dm" #include "code\_onclick\hud\guardian.dm" @@ -277,7 +280,6 @@ #include "code\_onclick\hud\map_popups.dm" #include "code\_onclick\hud\monkey.dm" #include "code\_onclick\hud\movable_screen_objects.dm" -#include "code\_onclick\hud\parallax.dm" #include "code\_onclick\hud\picture_in_picture.dm" #include "code\_onclick\hud\plane_master.dm" #include "code\_onclick\hud\radial.dm" @@ -292,6 +294,16 @@ #include "code\_onclick\hud\screen_objects\stamina.dm" #include "code\_onclick\hud\screen_objects\storage.dm" #include "code\_onclick\hud\screen_objects\vore.dm" +#include "code\_rendering\mob.dm" +#include "code\_rendering\atom_huds\alternate_appearance.dm" +#include "code\_rendering\atom_huds\atom_hud.dm" +#include "code\_rendering\atom_huds\data_huds.dm" +#include "code\_rendering\clickcatcher\clickcatcher.dm" +#include "code\_rendering\fullscreen\fullscreen.dm" +#include "code\_rendering\parallax\parallax.dm" +#include "code\_rendering\parallax\parallax_holder.dm" +#include "code\_rendering\parallax\parallax_object.dm" +#include "code\_rendering\parallax\types\space.dm" #include "code\controllers\admin.dm" #include "code\controllers\configuration_citadel.dm" #include "code\controllers\controller.dm" @@ -442,7 +454,6 @@ #include "code\datums\forced_movement.dm" #include "code\datums\holocall.dm" #include "code\datums\http.dm" -#include "code\datums\hud.dm" #include "code\datums\mind.dm" #include "code\datums\mutable_appearance.dm" #include "code\datums\numbered_display.dm" @@ -783,12 +794,10 @@ #include "code\datums\wounds\loss.dm" #include "code\datums\wounds\pierce.dm" #include "code\datums\wounds\slash.dm" -#include "code\game\alternate_appearance.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm" #include "code\game\atoms_movement.dm" #include "code\game\communications.dm" -#include "code\game\data_huds.dm" #include "code\game\say.dm" #include "code\game\shuttle_engines.dm" #include "code\game\sound.dm"