From 5775c4b02cb7ce9cee144a652ece30882a554962 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 7 Nov 2023 18:12:58 -0500 Subject: [PATCH] gods all seeing eye gazes down at me --- code/__DEFINES/colors.dm | 1 + code/__DEFINES/layers.dm | 4 + code/__DEFINES/subsystems.dm | 3 +- .../~monkestation-helpers/triangles.dm | 23 ++++ code/_onclick/hud/rendering/plane_master.dm | 17 +++ code/datums/components/chasm.dm | 1 + code/game/turfs/change_turf.dm | 2 +- code/game/turfs/turf.dm | 3 + code/modules/lighting/lighting_turf.dm | 5 + code/modules/mob/living/living_defines.dm | 2 + code/modules/mob/login.dm | 2 + code/modules/mob/mob.dm | 1 + .../modules/shadowcasting/__shadow_vars.dm | 15 +++ .../shadowcasting/_shadow_controller.dm | 42 +++++++ .../modules/shadowcasting/icons/geometric.dmi | Bin 0 -> 301 bytes .../modules/shadowcasting/shadow_component.dm | 95 +++++++++++++++ .../modules/shadowcasting/shadow_holder.dm | 18 +++ .../code/modules/shadowcasting/shadow_turf.dm | 108 ++++++++++++++++++ tgstation.dme | 6 + 19 files changed, 346 insertions(+), 2 deletions(-) create mode 100644 code/__HELPERS/~monkestation-helpers/triangles.dm create mode 100644 monkestation/code/modules/shadowcasting/__shadow_vars.dm create mode 100644 monkestation/code/modules/shadowcasting/_shadow_controller.dm create mode 100644 monkestation/code/modules/shadowcasting/icons/geometric.dmi create mode 100644 monkestation/code/modules/shadowcasting/shadow_component.dm create mode 100644 monkestation/code/modules/shadowcasting/shadow_holder.dm create mode 100644 monkestation/code/modules/shadowcasting/shadow_turf.dm diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 11828510f341..0d04c6e2ab8c 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -258,6 +258,7 @@ #define DEFAULT_HEX_COLOR_LEN 6 // Color filters +#define CHECK_LIGHT_OCCLUSION(turf) (turf.directional_opacity || turf.opacity) /// Icon filter that creates ambient occlusion #define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA") /// Icon filter that creates gaussian blur diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index c9961e328eba..f2dba7bed155 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -28,6 +28,7 @@ #define FLOOR_PLANE -11 #define WALL_PLANE -10 +#define WALL_RENDER_TARGET "*WALL_PLANE" //monkestation edit #define GAME_PLANE -9 #define GAME_PLANE_FOV_HIDDEN -8 #define GAME_PLANE_UPPER -7 @@ -85,6 +86,9 @@ ///---------------- MISC ----------------------- +/// Shadowcasting +#define SHADOWCASTING_PLANE 18 // monkestation edit + ///Pipecrawling images #define PIPECRAWL_IMAGES_PLANE 20 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 2a7084841746..83abf9726056 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -179,7 +179,8 @@ #define INIT_ORDER_STICKY_BAN -10 #define INIT_ORDER_LIGHTING -20 #define INIT_ORDER_OUTDOOR_EFFECTS -21 //monkestation addition -#define INIT_ORDER_SHUTTLE -22 //monkestation edit -21 > -22 +#define INIT_ORDER_SHADOWCASTING -22 // monkestation addition +#define INIT_ORDER_SHUTTLE -23 //monkestation edit -21 > -23 #define INIT_ORDER_MINOR_MAPPING -40 #define INIT_ORDER_PATH -50 #define INIT_ORDER_EXPLOSIONS -69 diff --git a/code/__HELPERS/~monkestation-helpers/triangles.dm b/code/__HELPERS/~monkestation-helpers/triangles.dm new file mode 100644 index 000000000000..826550c5b786 --- /dev/null +++ b/code/__HELPERS/~monkestation-helpers/triangles.dm @@ -0,0 +1,23 @@ +/// A list that caches base appearances of triangles for later access. +GLOBAL_LIST_EMPTY(triangle_appearances) + +/// Returns a mutable appearance of a triangle of the given points, and caches it for later use +/proc/get_triangle_appearance(x1,y1, x2,y2, x3,y3, icon_size = 32, icon = 'monkestation/code/modules/shadowcasting/icons/geometric.dmi', icon_state = "triangle") + var/key = "[x1]_[y2]_[x2]_[y2]_[x3]_[y3]_[icon_size]_[icon]_[icon_state]" + if(GLOB.triangle_appearances[key]) + return GLOB.triangle_appearances[key] + var/mutable_appearance/triangle_appearance = mutable_appearance(icon, icon_state) + triangle_appearance.transform = transform_triangle(x1,y1, x2,y2, x3,y3, icon_size) + GLOB.triangle_appearances[key] = triangle_appearance + return triangle_appearance + +/// Returns a matrix which when applied to a proper triangle image, creates an arbitrary triangle +/proc/transform_triangle(x1, y1, x2, y2, x3, y3, icon_size = 32) + var/i = 1/icon_size + var/a = (x3*i)-(x2*i) + var/b = -(x2*i)+(x1*i) + var/c = (x3*0.5)+(x1*0.5) + var/d = (y1*i)-(y2*i) + var/e = -(y2*i)+(y3*i) + var/f = (y1*0.5)+(y3*0.5) + return matrix(a,b,c,e,d,f) diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm index f0159e998998..639625ec7833 100644 --- a/code/_onclick/hud/rendering/plane_master.dm +++ b/code/_onclick/hud/rendering/plane_master.dm @@ -368,6 +368,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) name = "Wall" documentation = "Holds all walls. We render this onto the game world. Separate so we can use this + space and floor planes as a guide for where byond blackness is NOT." plane = WALL_PLANE + render_target = WALL_RENDER_TARGET // monkestation edit render_relay_planes = list(RENDER_PLANE_GAME_WORLD, LIGHT_MASK_PLANE) /atom/movable/screen/plane_master/wall/Initialize(mapload, datum/plane_master_group/home, offset) @@ -660,3 +661,19 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR render_relay_planes = list(RENDER_PLANE_MASTER) allows_offsetting = FALSE + +/atom/movable/screen/plane_master/shadowcasting + name = "Shadowcasting" + documentation = "Holds shadowcasting images so you can see fancy shadows where your vision can't reach." + plane = SHADOWCASTING_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + start_hidden = TRUE + +/atom/movable/screen/plane_master/shadowcasting/show_to(mob/mymob) + . = ..() + alpha = 96 + add_filter("wall_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(WALL_RENDER_TARGET, offset), flags = MASK_INVERSE)) + var/blurriness = 3 + add_filter("blur", 2, gauss_blur_filter(size = blurriness)) + diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index dbcacdfeaaf4..b9b4a21ac544 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -8,6 +8,7 @@ /// List of refs to falling objects -> how many levels deep we've fallen var/static/list/falling_atoms = list() var/static/list/forbidden_types = typecacheof(list( + /atom/movable/shadowcasting_holder, /obj/singularity, /obj/energy_ball, /obj/narsie, diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 63c0ac86d6be..da41f5e18b58 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/proc/empty(turf_type=/turf/open/space, baseturf_type, list/ignore_typecache, flags) // Remove all atoms except observers, landmarks, docking ports - var/static/list/ignored_atoms = typecacheof(list(/mob/dead, /obj/effect/landmark, /obj/docking_port)) + var/static/list/ignored_atoms = typecacheof(list(/atom/movable/shadowcasting_holder, /mob/dead, /obj/effect/landmark, /obj/docking_port)) var/list/allowed_contents = typecache_filter_list_reverse(get_all_contents_ignoring(ignore_typecache), ignored_atoms) allowed_contents -= src for(var/i in 1 to allowed_contents.len) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d64e51e5113d..d51eb3e72c1e 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -72,6 +72,9 @@ GLOBAL_LIST_EMPTY(station_turfs) ///Lazylist of movable atoms providing opacity sources. var/list/atom/movable/opacity_sources + ///Image used for shadowcasting + var/image/shadowcasting_image + ///the holodeck can load onto this turf if TRUE var/holodeck_compatible = FALSE diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index f3a137f1caf4..657cea25f2d5 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -129,6 +129,11 @@ if(!new_area.lighting_effects && old_area.lighting_effects && space_lit) overlays += GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] + //This, is also very expensive + for(var/turf/turf in range(world.view, src)) + turf.check_shadowcasting_update() + + /turf/proc/generate_missing_corners() if (!lighting_corner_NE) lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 5b7ee004c039..fd7faa4f31fe 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -3,6 +3,8 @@ hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,NANITE_HUD,DIAG_NANITE_FULL_HUD) pressure_resistance = 10 + shadow_caster = TRUE + hud_type = /datum/hud/living ///Badminnery resize diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index d7300dcbabbc..872990bef8dc 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -124,6 +124,8 @@ SEND_SIGNAL(client, COMSIG_CLIENT_MOB_LOGIN, src) client.init_verbs() + update_shadowcasting() + AddElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_LOGGED_IN, src) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 71e675ee5b97..6c94619f5d51 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -102,6 +102,7 @@ initialize_actionspeed() update_movespeed(TRUE) become_hearing_sensitive() + update_shadowcasting() log_mob_tag("CREATED: [key_name(src)] \[[type]\]") /** diff --git a/monkestation/code/modules/shadowcasting/__shadow_vars.dm b/monkestation/code/modules/shadowcasting/__shadow_vars.dm new file mode 100644 index 000000000000..3b2ecdf601e7 --- /dev/null +++ b/monkestation/code/modules/shadowcasting/__shadow_vars.dm @@ -0,0 +1,15 @@ +/mob + ///Should the mob use the shadowcasting component when a client is logged to it? + var/shadow_caster = FALSE + + +/mob/proc/update_shadowcasting() + if(!shadow_caster || !client) + return + for(var/atom/movable/screen/plane_master/plane_master as anything in hud_used.get_true_plane_masters(SHADOWCASTING_PLANE)) + plane_master.alpha = 96 + for(var/atom/movable/screen/plane_master/plane_master as anything in hud_used.get_true_plane_masters(SHADOWCASTING_PLANE)) + plane_master.add_filter("blur", 2, gauss_blur_filter(size = 3)) + var/datum/component/shadowcasting = GetComponent(/datum/component/shadowcasting) + if(!shadowcasting) + AddComponent(/datum/component/shadowcasting) diff --git a/monkestation/code/modules/shadowcasting/_shadow_controller.dm b/monkestation/code/modules/shadowcasting/_shadow_controller.dm new file mode 100644 index 000000000000..49deebc5db81 --- /dev/null +++ b/monkestation/code/modules/shadowcasting/_shadow_controller.dm @@ -0,0 +1,42 @@ +/** + * This subsystem updates shadowcasting overlays for updates not caused by mob movement. + */ +SUBSYSTEM_DEF(shadowcasting) + name = "Shadowcasting" + wait = 2 + init_order = INIT_ORDER_SHADOWCASTING + flags = SS_TICKER + var/static/list/turf/turf_queue = list() + +/datum/controller/subsystem/shadowcasting/stat_entry(msg) + msg = "T:[length(turf_queue)]|" + return ..() + +/datum/controller/subsystem/shadowcasting/Initialize() + fire(FALSE, TRUE) + initialized = TRUE + + return SS_INIT_SUCCESS + +/datum/controller/subsystem/shadowcasting/fire(resumed, init_tick_checks) + MC_SPLIT_TICK_INIT(3) + if(!init_tick_checks) + MC_SPLIT_TICK + + var/list/queue = turf_queue + var/i = 0 + for (i in 1 to length(queue)) + var/turf/shadow_source = queue[i] + + shadow_source.update_shadowcasting() + + if(init_tick_checks) + CHECK_TICK + else if (MC_TICK_CHECK) + break + if (i) + queue.Cut(1, i+1) + +/datum/controller/subsystem/shadowcasting/Recover() + initialized = SSshadowcasting.initialized + return ..() diff --git a/monkestation/code/modules/shadowcasting/icons/geometric.dmi b/monkestation/code/modules/shadowcasting/icons/geometric.dmi new file mode 100644 index 0000000000000000000000000000000000000000..34784b7b5862d5fe7b9f4987c05f7b584aa08078 GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB_V)Sem}`Jdk263GxeO zaCmkj4ah043W+FjNi9w;$}A|!%+F(BsF)KRR!~&>{Y!Ac$FEPcymhtCojD)8A=Kca z@qi;?&a7)A7|gw9+T?;MMc2Z=4v6?Dh4eesApuIw8o@#W6%<;@dMDc@HQE zusC`xH}P7?;>2|1<|JE|bqB@wJe#chG*0)uREdN^;=wi<4p$8)!LEQ7r71EY85a@{ sw6IDS1uS%IXA~C8IZ=G>`{QQrUF%MV{%98y1e(s^>FVdQ&MBb@0IwQv1^@s6 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/shadowcasting/shadow_component.dm b/monkestation/code/modules/shadowcasting/shadow_component.dm new file mode 100644 index 000000000000..7cd9f3b3297d --- /dev/null +++ b/monkestation/code/modules/shadowcasting/shadow_component.dm @@ -0,0 +1,95 @@ +// lots of ctrl c ctrl v from fov component no fucks given +/datum/component/shadowcasting + /// Whether we are applying the masks now or not + var/applied_shadow = FALSE + /// Atom that shows shadowcasting overlays + var/atom/movable/shadowcasting_holder/visual_shadow + +/datum/component/shadowcasting/Initialize() + . = ..() + if(!ismob(parent)) + return COMPONENT_INCOMPATIBLE + var/mob/mob_parent = parent + var/client/parent_client = mob_parent.client + if(!parent_client) //Love client volatility!! + qdel(src) //no QDEL hint for components, and we dont want this to print a warning regarding bad component application + return + + for(var/atom/movable/screen/plane_master/plane_master as anything in mob_parent.hud_used.get_true_plane_masters(SHADOWCASTING_PLANE)) + plane_master.unhide_plane(mob_parent) + + visual_shadow = new + update_shadow() + +/datum/component/shadowcasting/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(update_shadow)) + RegisterSignal(parent, COMSIG_MOB_RESET_PERSPECTIVE, PROC_REF(update_shadow)) + RegisterSignal(parent, COMSIG_MOB_SIGHT_CHANGE, PROC_REF(update_shadow)) + RegisterSignal(parent, COMSIG_MOB_LOGOUT, PROC_REF(mob_logout)) + +/datum/component/shadowcasting/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list( + COMSIG_MOVABLE_MOVED, + COMSIG_MOB_RESET_PERSPECTIVE, + COMSIG_MOB_SIGHT_CHANGE, + COMSIG_MOB_LOGOUT, + )) + +/datum/component/shadowcasting/Destroy(force, silent) + var/mob/living/mob_parent = parent + for(var/atom/movable/screen/plane_master/plane_master as anything in mob_parent.hud_used.get_true_plane_masters(SHADOWCASTING_PLANE)) + plane_master.hide_plane(mob_parent) + + if(applied_shadow) + remove_shadow() + if(visual_shadow) + QDEL_NULL(visual_shadow) + return ..() + +/datum/component/shadowcasting/proc/update_shadow() + SIGNAL_HANDLER + var/mob/living/parent_mob = parent + var/client/parent_client = parent_mob.client + if(!parent_client) //Love client volatility!! + return + + var/user_turf = get_turf(parent_mob) + var/atom/top_most_atom = get_atom_on_turf(parent_mob) + var/user_extends_eye = parent_client.eye != top_most_atom + var/user_sees_turfs = parent_mob.sight & SEE_TURFS + var/user_blind = parent_mob.sight & BLIND + + var/should_apply_mask = user_turf && !user_extends_eye && !user_sees_turfs && !user_blind + if(should_apply_mask) + add_shadow(user_turf) + else + remove_shadow() + +/datum/component/shadowcasting/proc/add_shadow(turf/mob_turf) + var/mob/parent_mob = parent + var/client/parent_client = parent_mob.client + if(!parent_client) //Love client volatility!! + return + applied_shadow = TRUE + if(!mob_turf.shadowcasting_image) + mob_turf.update_shadowcasting_image() + visual_shadow.reflector.overlays = null + visual_shadow.reflector.overlays += mob_turf.shadowcasting_image + visual_shadow.loc = get_turf(parent_mob) + parent_client.images |= visual_shadow.reflector + +/datum/component/shadowcasting/proc/remove_shadow() + var/mob/parent_mob = parent + var/client/parent_client = parent_mob.client + if(!parent_client) //Love client volatility!! + return + applied_shadow = FALSE + visual_shadow.moveToNullspace() + parent_client.images -= visual_shadow.reflector + +/// When a mob logs out, delete the component +/datum/component/shadowcasting/proc/mob_logout(mob/source) + SIGNAL_HANDLER + qdel(src) diff --git a/monkestation/code/modules/shadowcasting/shadow_holder.dm b/monkestation/code/modules/shadowcasting/shadow_holder.dm new file mode 100644 index 000000000000..c83da070ab65 --- /dev/null +++ b/monkestation/code/modules/shadowcasting/shadow_holder.dm @@ -0,0 +1,18 @@ +/atom/movable/shadowcasting_holder + appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE + plane = SHADOWCASTING_PLANE + animate_movement = NO_STEPS + invisibility = INVISIBILITY_LIGHTING + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + var/image/reflector + +/atom/movable/shadowcasting_holder/Initialize(mapload) + . = ..() + reflector = new() + reflector.override = TRUE + reflector.loc = src + +/atom/movable/shadowcasting_holder/Destroy(force) + . = ..() + reflector = null diff --git a/monkestation/code/modules/shadowcasting/shadow_turf.dm b/monkestation/code/modules/shadowcasting/shadow_turf.dm new file mode 100644 index 000000000000..81287736d703 --- /dev/null +++ b/monkestation/code/modules/shadowcasting/shadow_turf.dm @@ -0,0 +1,108 @@ +/turf/proc/check_shadowcasting_update() + if(!shadowcasting_image) + return + SSshadowcasting.turf_queue += src + +/turf/proc/update_shadowcasting() + update_shadowcasting_image() + var/datum/component/shadowcasting/shadowcasting + for(var/mob/mob in src) + if(!mob.client) + continue + shadowcasting = mob.GetComponent(/datum/component/shadowcasting) + if(shadowcasting) + shadowcasting.update_shadow() + +/turf/proc/update_shadowcasting_image() + if(!shadowcasting_image) + shadowcasting_image = new() + shadowcasting_image.overlays = create_shadowcasting_overlays() + +/turf/proc/create_shadowcasting_overlays(view_range = world.view + 2) + var/static/icon_size = world.icon_size + var/static/half_icon_size = icon_size/2 + + var/list/shadows = list() + + var/list/blocker_turfs_in_view = list() + for(var/turf/in_view in (range(view_range, src)-src)) + if(!CHECK_LIGHT_OCCLUSION(in_view)) + continue + blocker_turfs_in_view += in_view + + var/diff_x + var/diff_y + var/fac + var/dx + var/dy + var/sign_x + var/sign_y + var/width + var/height + var/top + var/bottom + var/left + var/right + var/v_dir + var/h_dir + var/turf/temp_turf + for(var/turf/blocker_turf as anything in blocker_turfs_in_view) + diff_x = blocker_turf.x - src.x + diff_y = blocker_turf.y - src.y + fac = icon_size/(abs(diff_x) + abs(diff_y)) + dx = diff_x * icon_size + dy = diff_y * icon_size + sign_x = SIGN(diff_x) + sign_y = SIGN(diff_y) + + width = 1 + height = 1 + if(!diff_x) + temp_turf = get_step(blocker_turf, EAST) + while(temp_turf && CHECK_LIGHT_OCCLUSION(temp_turf) && abs(temp_turf.x - blocker_turf.x) < view_range) + width++ + temp_turf = get_step(temp_turf, EAST) + temp_turf = get_step(blocker_turf, WEST) + while(temp_turf && CHECK_LIGHT_OCCLUSION(temp_turf) && abs(temp_turf.x - blocker_turf.x) < view_range) + width++ + dx -= icon_size + temp_turf = get_step(temp_turf, WEST) + else if(!diff_y) + temp_turf = get_step(blocker_turf, NORTH) + while(temp_turf && CHECK_LIGHT_OCCLUSION(temp_turf) && abs(temp_turf.y - blocker_turf.y) < view_range) + height++ + temp_turf = get_step(temp_turf, NORTH) + temp_turf = get_step(blocker_turf, SOUTH) + while(temp_turf && CHECK_LIGHT_OCCLUSION(temp_turf) && abs(temp_turf.y - blocker_turf.y) < view_range) + height++ + dy -= icon_size + temp_turf = get_step(temp_turf, SOUTH) + else + v_dir = (dy >= 0 ? NORTH : SOUTH) + h_dir = (dx >= 0 ? EAST : WEST) + + temp_turf = get_step(blocker_turf, h_dir) + while(temp_turf && CHECK_LIGHT_OCCLUSION(temp_turf) && abs(temp_turf.x - blocker_turf.x) < view_range) + width++ + temp_turf = get_step(temp_turf, h_dir) + temp_turf = get_step(blocker_turf, v_dir) + while(temp_turf && CHECK_LIGHT_OCCLUSION(temp_turf) && abs(temp_turf.y - blocker_turf.y) < view_range) + height++ + temp_turf = get_step(temp_turf, v_dir) + + top = dy-(sign_y*half_icon_size)+(sign_y*height*icon_size) + bottom = dy-(sign_y*half_icon_size) + left = dx-(sign_x*half_icon_size) + right = dx-(sign_x*half_icon_size)+(sign_x*width*icon_size) + if(!diff_y) + shadows += get_triangle_appearance(left,top, left,bottom, left*fac,bottom*fac) + shadows += get_triangle_appearance(left*fac, top*fac,left,top, left*fac,bottom*fac) + else if(!diff_x) + shadows += get_triangle_appearance(right,bottom, left,bottom, left*fac,bottom*fac) + shadows += get_triangle_appearance(left*fac,bottom*fac, right,bottom, right*fac,bottom*fac) + else + shadows += get_triangle_appearance(right,top, left,top, left*fac,top*fac) + shadows += get_triangle_appearance(right,top, right,bottom, right*fac,bottom*fac) + shadows += get_triangle_appearance(left*fac,top*fac, right,top, right*fac,bottom*fac) + + return shadows diff --git a/tgstation.dme b/tgstation.dme index d6d7bf5094f2..cd429624aba5 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -505,6 +505,7 @@ #include "code\__HELPERS\sorts\MergeSort.dm" #include "code\__HELPERS\sorts\TimSort.dm" #include "code\__HELPERS\~monkestation-helpers\icon_smoothing.dm" +#include "code\__HELPERS\~monkestation-helpers\triangles.dm" #include "code\_globalvars\_regexes.dm" #include "code\_globalvars\admin.dm" #include "code\_globalvars\bitfields.dm" @@ -6256,6 +6257,11 @@ #include "monkestation\code\modules\security\code\holographic_handcuffs.dm" #include "monkestation\code\modules\security\code\weapons\lawbringer.dm" #include "monkestation\code\modules\security\code\weapons\paco.dm" +#include "monkestation\code\modules\shadowcasting\__shadow_vars.dm" +#include "monkestation\code\modules\shadowcasting\_shadow_controller.dm" +#include "monkestation\code\modules\shadowcasting\shadow_component.dm" +#include "monkestation\code\modules\shadowcasting\shadow_holder.dm" +#include "monkestation\code\modules\shadowcasting\shadow_turf.dm" #include "monkestation\code\modules\skyrat_snipes\languages.dm" #include "monkestation\code\modules\skyrat_snipes\reagents\drink_reagents.dm" #include "monkestation\code\modules\skyrat_snipes\vending_machines\vending_food.dm"