diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm index b824fad687..14b6a862c2 100644 --- a/code/_onclick/hud/picture_in_picture.dm +++ b/code/_onclick/hud/picture_in_picture.dm @@ -12,7 +12,7 @@ var/obj/screen/component_button/button_expand var/obj/screen/component_button/button_shrink - var/mutable_appearance/standard_background + var/list/background_mas = list() var/const/max_dimensions = 10 /obj/screen/movable/pic_in_pic/Initialize() @@ -36,11 +36,17 @@ set_view_size(width-1, height-1) /obj/screen/movable/pic_in_pic/proc/make_backgrounds() - standard_background = new /mutable_appearance() - standard_background.icon = 'icons/misc/pic_in_pic.dmi' - standard_background.icon_state = "background" - standard_background.layer = DISPOSAL_LAYER - standard_background.plane = PLATING_PLANE + var/mutable_appearance/base = new /mutable_appearance() + base.icon = 'icons/misc/pic_in_pic.dmi' + base.layer = DISPOSAL_LAYER + base.plane = PLATING_PLANE + base.appearance_flags = PIXEL_SCALE + + for(var/direction in cardinal) + var/mutable_appearance/dir = new /mutable_appearance(base) + dir.dir = direction + dir.icon_state = "background_[direction]" + background_mas += dir /obj/screen/movable/pic_in_pic/proc/add_buttons() var/static/mutable_appearance/move_tab @@ -97,11 +103,34 @@ /obj/screen/movable/pic_in_pic/proc/add_background() if((width > 0) && (height > 0)) - var/matrix/M = matrix() - M.Scale(width + 0.5, height + 0.5) - M.Translate((width-1)/2 * world.icon_size, (height-1)/2 * world.icon_size) - standard_background.transform = M - overlays += standard_background + for(var/mutable_appearance/dir in background_mas) + var/matrix/M = matrix() + var/x_scale = 1 + var/y_scale = 1 + + var/x_off = 0 + var/y_off = 0 + + if(dir.dir & (NORTH|SOUTH)) + x_scale = width + x_off = (width-1)/2 * world.icon_size + if(dir.dir & NORTH) + y_off = ((height-1) * world.icon_size) + 3 + else + y_off = -3 + + if(dir.dir & (EAST|WEST)) + y_scale = height + y_off = (height-1)/2 * world.icon_size + if(dir.dir & EAST) + x_off = ((width-1) * world.icon_size) + 3 + else + x_off = -3 + + M.Scale(x_scale, y_scale) + M.Translate(x_off, y_off) + dir.transform = M + overlays += dir /obj/screen/movable/pic_in_pic/proc/set_view_size(width, height, do_refresh = TRUE) width = CLAMP(width, 0, max_dimensions) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 367ed9d153..ab6985bdbd 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -610,7 +610,6 @@ /obj/screen/component_button var/obj/screen/parent - /obj/screen/component_button/Initialize(mapload, obj/screen/new_parent) . = ..() parent = new_parent diff --git a/code/game/atoms.dm b/code/game/atoms.dm index ab703fa650..123daae654 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -37,8 +37,8 @@ // During dynamic mapload (reader.dm) this assigns the var overrides from the .dmm file // Native BYOND maploading sets those vars before invoking New(), by doing this FIRST we come as close to that behavior as we can. - if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() - _preloader.load(src) + if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() + GLOB._preloader.load(src) // Pass our arguments to InitAtom so they can be passed to initialize(), but replace 1st with if-we're-during-mapload. var/do_initialize = SSatoms.initialized diff --git a/code/game/jobs/job/job_vr.dm b/code/game/jobs/job/job_vr.dm index 05874df0d1..3ffd0d05f9 100644 --- a/code/game/jobs/job/job_vr.dm +++ b/code/game/jobs/job/job_vr.dm @@ -25,6 +25,9 @@ return (available_in_playhours(C) == 0) /datum/job/proc/available_in_playhours(client/C) - if(C && config.use_playtime_restriction_for_jobs && isnum(C.play_hours[pto_type]) && dept_time_required > 0) - return max(0, dept_time_required - C.play_hours[pto_type]) + if(C && config.use_playtime_restriction_for_jobs) + if(isnum(C.play_hours[pto_type])) // Has played that department before + return max(0, dept_time_required - C.play_hours[pto_type]) + else // List doesn't have that entry, maybe never played, maybe invalid PTO type (you should fix that...) + return dept_time_required // Could be 0, too, which is fine! They can play that return 0 \ No newline at end of file diff --git a/code/modules/maps/tg/reader.dm b/code/modules/maps/tg/reader.dm index 71adb65bad..b7bf3561f5 100644 --- a/code/modules/maps/tg/reader.dm +++ b/code/modules/maps/tg/reader.dm @@ -2,15 +2,9 @@ //SS13 Optimized Map loader ////////////////////////////////////////////////////////////// -/* //global datum that will preload variables on atoms instanciation GLOBAL_VAR_INIT(use_preloader, FALSE) GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new) -*/ - -//global datum that will preload variables on atoms instanciation -var/global/dmm_suite/preloader/_preloader = new() -var/global/use_preloader = FALSE /dmm_suite // /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g @@ -36,6 +30,12 @@ var/global/use_preloader = FALSE * */ /dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num, no_changeturf as num, orientation as num) + + dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g") + trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g") + trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g") + modelCache = list() + //How I wish for RAII if(!measureOnly) Master.StartLoadingMap() @@ -350,7 +350,7 @@ var/global/use_preloader = FALSE index = members.len if(members[index] != /area/template_noop) var/atom/instance - _preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation + GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation var/atype = members[index] for(var/area/A in world) if(A.type == atype) @@ -361,8 +361,8 @@ var/global/use_preloader = FALSE if(crds) instance.contents.Add(crds) - if(use_preloader && instance) - _preloader.load(instance) + if(GLOB.use_preloader && instance) + GLOB._preloader.load(instance) //then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect @@ -398,7 +398,7 @@ var/global/use_preloader = FALSE //Instance an atom at (x,y,z) and gives it the variables in attributes /dmm_suite/proc/instance_atom(path,list/attributes, turf/crds, no_changeturf, orientation=0) - _preloader.setup(attributes, path) + GLOB._preloader.setup(attributes, path) if(crds) if(!no_changeturf && ispath(path, /turf)) @@ -406,8 +406,8 @@ var/global/use_preloader = FALSE else . = create_atom(path, crds)//first preloader pass - if(use_preloader && .)//second preloader pass, for those atoms that don't ..() in New() - _preloader.load(.) + if(GLOB.use_preloader && .)//second preloader pass, for those atoms that don't ..() in New() + GLOB._preloader.load(.) //custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize if(TICK_CHECK) @@ -530,7 +530,7 @@ var/global/use_preloader = FALSE /dmm_suite/preloader/proc/setup(list/the_attributes, path) if(the_attributes.len) - use_preloader = TRUE + GLOB.use_preloader = TRUE attributes = the_attributes target_path = path @@ -540,7 +540,7 @@ var/global/use_preloader = FALSE if(islist(value)) value = deepCopyList(value) what.vars[attribute] = value - use_preloader = FALSE + GLOB.use_preloader = FALSE /area/template_noop name = "Area Passthrough" diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index 9a973e7fa3..018454608c 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -2,7 +2,7 @@ /obj/screen/movable/pic_in_pic/ai var/mob/living/silicon/ai/ai - var/mutable_appearance/highlighted_background + var/list/highlighted_mas = list() var/highlighted = FALSE var/mob/observer/eye/aiEye/pic_in_pic/aiEye @@ -12,9 +12,12 @@ aiEye.screen = src /obj/screen/movable/pic_in_pic/ai/Destroy() + . = ..() + if(!QDELETED(aiEye)) + QDEL_NULL(aiEye) + else + aiEye = null set_ai(null) - QDEL_NULL(aiEye) - return ..() /obj/screen/movable/pic_in_pic/ai/Click() ..() @@ -23,22 +26,57 @@ /obj/screen/movable/pic_in_pic/ai/make_backgrounds() ..() - highlighted_background = new /mutable_appearance() - highlighted_background.icon = 'icons/misc/pic_in_pic.dmi' - highlighted_background.icon_state = "background_highlight" - highlighted_background.layer = DISPOSAL_LAYER - highlighted_background.plane = PLATING_PLANE + var/mutable_appearance/base = new /mutable_appearance() + base.icon = 'icons/misc/pic_in_pic.dmi' + base.layer = DISPOSAL_LAYER + base.plane = PLATING_PLANE + base.appearance_flags = PIXEL_SCALE + + for(var/direction in cardinal) + var/mutable_appearance/dir = new /mutable_appearance(base) + dir.dir = direction + dir.icon_state = "background_highlight_[direction]" + highlighted_mas += dir /obj/screen/movable/pic_in_pic/ai/add_background() if((width > 0) && (height > 0)) - var/matrix/M = matrix() - M.Scale(width + 0.5, height + 0.5) - M.Translate((width-1)/2 * world.icon_size, (height-1)/2 * world.icon_size) - highlighted_background.transform = M - standard_background.transform = M - overlays += highlighted ? highlighted_background : standard_background + if(!highlighted) + return ..() + + for(var/mutable_appearance/dir in highlighted_mas) + var/matrix/M = matrix() + var/x_scale = 1 + var/y_scale = 1 + + var/x_off = 0 + var/y_off = 0 + + if(dir.dir & (NORTH|SOUTH)) + x_scale = width + x_off = (width-1)/2 * world.icon_size + if(dir.dir & NORTH) + y_off = ((height-1) * world.icon_size) + 3 + else + y_off = -3 + + if(dir.dir & (EAST|WEST)) + y_scale = height + y_off = (height-1)/2 * world.icon_size + if(dir.dir & EAST) + x_off = ((width-1) * world.icon_size) + 3 + else + x_off = -3 + + M.Scale(x_scale, y_scale) + M.Translate(x_off, y_off) + dir.transform = M + overlays += dir /obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE) + if(!aiEye) + qdel(src) + return + aiEye.static_visibility_range = (round(max(width, height) / 2) + 1) if(ai) ai.camera_visibility(aiEye) @@ -46,27 +84,50 @@ /obj/screen/movable/pic_in_pic/ai/set_view_center(atom/target, do_refresh = TRUE) ..() + if(!aiEye) + qdel(src) + return + aiEye.setLoc(get_turf(target)) /obj/screen/movable/pic_in_pic/ai/refresh_view() ..() + if(!aiEye) + qdel(src) + return + aiEye.setLoc(get_turf(center)) /obj/screen/movable/pic_in_pic/ai/proc/highlight() if(highlighted) return + if(!aiEye) + qdel(src) + return highlighted = TRUE - overlays -= standard_background - overlays += highlighted_background + overlays.Cut() + add_background() + add_buttons() /obj/screen/movable/pic_in_pic/ai/proc/unhighlight() if(!highlighted) return + if(!aiEye) + qdel(src) + return highlighted = FALSE - overlays -= highlighted_background - overlays += standard_background + overlays.Cut() + add_background() + add_buttons() /obj/screen/movable/pic_in_pic/ai/proc/set_ai(mob/living/silicon/ai/new_ai) + if(!aiEye && !QDELETED(src)) + if(new_ai) + to_chat(new_ai, "

You've run into a unfixable bug with AI eye code. \ +In order to create a new multicam, you will have to select a different camera first before trying to add one, or ask an admin to fix you. \ +Whatever you did that made the last camera window disappear-- don't do that again.

") + qdel(src) + return if(ai) ai.multicam_screens -= src ai.all_eyes -= aiEye @@ -88,6 +149,8 @@ icon = 'icons/misc/pic_in_pic.dmi' icon_state = "room_background" flags = NOJAUNT + plane = SPACE_PLANE + layer = AREA_LAYER + 0.1 /turf/unsimulated/ai_visible/Initialize() . = ..() @@ -182,6 +245,10 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) disable_camera_telegraphing() if(screen && screen.ai) screen.ai.all_eyes -= src + if(!QDELETED(screen)) + QDEL_NULL(screen) + else + screen = null return ..() //AI procs diff --git a/code/modules/overmap/spacetravel.dm b/code/modules/overmap/spacetravel.dm index a51cfc3f6d..ac5846202a 100644 --- a/code/modules/overmap/spacetravel.dm +++ b/code/modules/overmap/spacetravel.dm @@ -63,11 +63,16 @@ proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A) if (!M) return + // Don't let AI eyes yeet themselves off the map + if(istype(A, /mob/observer/eye)) + return + if(A.lost_in_space()) if(!QDELETED(A)) qdel(A) return + var/nx = 1 var/ny = 1 var/nz = 1 diff --git a/icons/misc/pic_in_pic.dmi b/icons/misc/pic_in_pic.dmi index 9c550f3c25..cdac129513 100644 Binary files a/icons/misc/pic_in_pic.dmi and b/icons/misc/pic_in_pic.dmi differ