diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 340ce4d32f5..bcaa6e98001 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -181,3 +181,8 @@ #define COLOR_PALE_RED_GRAY "#CC9090" #define COLOR_PALE_PURPLE_GRAY "#BDA2BA" #define COLOR_PURPLE_GRAY "#A2819E" + +//Camera capture modes +#define CAPTURE_MODE_REGULAR 0 //Regular polaroid camera mode +#define CAPTURE_MODE_ALL 1 //Admin camera mode +#define CAPTURE_MODE_PARTIAL 3 //Simular to regular mode, but does not do dummy check diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index cabf7c04b37..bac27c1f5a9 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -760,7 +760,11 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu // Pull the default direction. add = icon(I:icon, I:icon_state) else // 'I' is an appearance object. - add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) + if(istype(A,/obj/machinery/atmospherics) && I in A.underlays) + var/image/Im = I + add = getFlatIcon(new/image(I), Im.dir, curicon, curstate, curblend, 1) + else + add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, always_use_defdir) // Find the new dimensions of the flat icon to fit the added overlay addX1 = min(flatX1, I:pixel_x+1) @@ -773,9 +777,15 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) flatX1=addX1;flatX2=addX2 flatY1=addY1;flatY2=addY2 - + var/iconmode + if(I in A.overlays) + iconmode = ICON_OVERLAY + else if(I in A.underlays) + iconmode = ICON_UNDERLAY + else + iconmode = blendMode2iconMode(curblend) // Blend the overlay into the flattened icon - flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) + flat.Blend(add, iconmode, I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) if(A.color) flat.Blend(A.color, ICON_MULTIPLY) @@ -853,3 +863,53 @@ proc/sort_atoms_by_layer(var/list/atoms) result.Swap(i, gap + i) swapped = 1 return result +/* +generate_image function generates image of specified range and location +arguments tx, ty, tz are target coordinates (requred), range defines render distance to opposite corner (requred) +cap_mode is capturing mode (optional), user is capturing mob (requred only wehen cap_mode = CAPTURE_MODE_REGULAR), +lighting determines lighting capturing (optional), suppress_errors suppreses errors and continues to capture (optional). +*/ +proc/generate_image(var/tx as num, var/ty as num, var/tz as num, var/range as num, var/cap_mode = CAPTURE_MODE_PARTIAL, var/mob/living/user, var/lighting = 1, var/suppress_errors = 1) + var/list/turfstocapture = list() + //Lines below determine what tiles will be rendered + for(var/xoff = 0 to range) + for(var/yoff = 0 to range) + var/turf/T = locate(tx + xoff,ty + yoff,tz) + if(T) + if(cap_mode == CAPTURE_MODE_REGULAR) + if(user.can_capture_turf(T)) + turfstocapture.Add(T) + continue + else + turfstocapture.Add(T) + else + //Capture includes non-existan turfs + if(!suppress_errors) + return + //Lines below determine what objects will be rendered + var/list/atoms = list() + for(var/turf/T in turfstocapture) + atoms.Add(T) + for(var/atom/A in T) + if(istype(A, /atom/movable/lighting_overlay) && lighting) //Special case for lighting + atoms.Add(A) + continue + if(A.invisibility) continue + atoms.Add(A) + //Lines below actually render all colected data + atoms = sort_atoms_by_layer(atoms) + var/icon/cap = icon('icons/effects/96x96.dmi', "") + cap.Scale(range*32, range*32) + cap.Blend("#000", ICON_OVERLAY) + for(var/atom/A in atoms) + if(A) + var/icon/img = getFlatIcon(A) + if(istype(img, /icon)) + if(istype(A, /mob/living) && A:lying) + img.BecomeLying() + var/xoff = (A.x - tx) * 32 + var/yoff = (A.y - ty) * 32 + cap.Blend(img, blendMode2iconMode(A.blend_mode), A.pixel_x + xoff, A.pixel_y + yoff) + + return cap + diff --git a/code/modules/admin/map_capture.dm b/code/modules/admin/map_capture.dm index ced6d257bf4..1930ae8d672 100644 --- a/code/modules/admin/map_capture.dm +++ b/code/modules/admin/map_capture.dm @@ -4,6 +4,7 @@ set desc = "Usage: Capture-Map-Part target_x_cord target_y_cord target_z_cord range (captures part of a map originating from bottom left corner)" if(!check_rights(R_ADMIN|R_DEBUG|R_SERVER)) + usr << "You are not allowed to use this command" return if(isnull(tx) || isnull(ty) || isnull(tz) || isnull(range)) @@ -17,41 +18,7 @@ return if(locate(tx,ty,tz)) - var/list/turfstocapture = list() - var/hasasked = 0 - for(var/xoff = 0 to range) - for(var/yoff = 0 to range) - var/turf/T = locate(tx + xoff,ty + yoff,tz) - if(T) - turfstocapture.Add(T) - else - if(!hasasked) - var/answer = alert("Capture includes non existant turf, Continue capture?","Continue capture?", "No", "Yes") - hasasked = 1 - if(answer == "No") - return - - var/list/atoms = list() - for(var/turf/T in turfstocapture) - atoms.Add(T) - for(var/atom/A in T) - if(A.invisibility) continue - atoms.Add(A) - - atoms = sort_atoms_by_layer(atoms) - var/icon/cap = icon('icons/effects/96x96.dmi', "") - cap.Scale(range*32, range*32) - cap.Blend("#000", ICON_OVERLAY) - for(var/atom/A in atoms) - if(A) - var/icon/img = getFlatIcon(A) - if(istype(img, /icon)) - if(istype(A, /mob/living) && A:lying) - img.BecomeLying() - var/xoff = (A.x - tx) * 32 - var/yoff = (A.y - ty) * 32 - cap.Blend(img, blendMode2iconMode(A.blend_mode), A.pixel_x + xoff, A.pixel_y + yoff) - + var/cap = generate_image(tx ,ty ,tz ,range, CAPTURE_MODE_PARTIAL, null, 1, 1) var/file_name = "map_capture_x[tx]_y[ty]_z[tz]_r[range].png" usr << "Saved capture in cache as [file_name]." usr << browse_rsc(cap, file_name) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 90ed7ccf59e..62f85d8f3b1 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -165,55 +165,6 @@ var/global/photo_count = 0 ..() -/obj/item/device/camera/proc/get_icon(list/turfs, turf/center) - - //Bigger icon base to capture those icons that were shifted to the next tile - //i.e. pretty much all wall-mounted machinery - var/icon/res = icon('icons/effects/96x96.dmi', "") - res.Scale(size*32, size*32) - // Initialize the photograph to black. - res.Blend("#000", ICON_OVERLAY) - - var/atoms[] = list() - for(var/turf/the_turf in turfs) - // Add outselves to the list of stuff to draw - atoms.Add(the_turf); - // As well as anything that isn't invisible. - for(var/atom/A in the_turf) - if(A.invisibility) continue - atoms.Add(A) - - // Sort the atoms into their layers - var/list/sorted = sort_atoms_by_layer(atoms) - var/center_offset = (size-1)/2 * 32 + 1 - for(var/i; i <= sorted.len; i++) - var/atom/A = sorted[i] - if(A) - var/icon/img = getFlatIcon(A)//build_composite_icon(A) - - // If what we got back is actually a picture, draw it. - if(istype(img, /icon)) - // Check if we're looking at a mob that's lying down - if(istype(A, /mob/living) && A:lying) - // If they are, apply that effect to their picture. - img.BecomeLying() - // Calculate where we are relative to the center of the photo - var/xoff = (A.x - center.x) * 32 + center_offset - var/yoff = (A.y - center.y) * 32 + center_offset - if (istype(A,/atom/movable)) - xoff+=A:step_x - yoff+=A:step_y - res.Blend(img, blendMode2iconMode(A.blend_mode), A.pixel_x + xoff, A.pixel_y + yoff) - - // Lastly, render any contained effects on top. - for(var/turf/the_turf in turfs) - // Calculate where we are relative to the center of the photo - var/xoff = (the_turf.x - center.x) * 32 + center_offset - var/yoff = (the_turf.y - center.y) * 32 + center_offset - res.Blend(getFlatIcon(the_turf.loc), blendMode2iconMode(the_turf.blend_mode),xoff,yoff) - return res - - /obj/item/device/camera/proc/get_mobs(turf/the_turf as turf) var/mob_detail for(var/mob/living/carbon/A in the_turf) @@ -248,37 +199,39 @@ var/global/photo_count = 0 icon_state = icon_on on = 1 -/obj/item/device/camera/proc/can_capture_turf(turf/T, mob/user) +//Proc for capturing check +/mob/living/proc/can_capture_turf(turf/T) var/mob/dummy = new(T) //Go go visibility check dummy - var/viewer = user - if(user.client) //To make shooting through security cameras possible - viewer = user.client.eye + var/viewer = src + if(src.client) //To make shooting through security cameras possible + viewer = src.client.eye var/can_see = (dummy in viewers(world.view, viewer)) qdel(dummy) return can_see -/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) +/obj/item/device/camera/proc/captureimage(atom/target, mob/living/user, flag) var/x_c = target.x - (size-1)/2 var/y_c = target.y + (size-1)/2 var/z_c = target.z - var/list/turfs = list() var/mobs = "" for(var/i = 1; i <= size; i++) for(var/j = 1; j <= size; j++) var/turf/T = locate(x_c, y_c, z_c) - if(can_capture_turf(T, user)) - turfs.Add(T) + if(user.can_capture_turf(T)) mobs += get_mobs(T) x_c++ y_c-- x_c = x_c - size - var/obj/item/weapon/photo/p = createpicture(target, user, turfs, mobs, flag) + var/obj/item/weapon/photo/p = createpicture(target, user, mobs, flag) printpicture(user, p) -/obj/item/device/camera/proc/createpicture(atom/target, mob/user, list/turfs, mobs, flag) - var/icon/photoimage = get_icon(turfs, target) +/obj/item/device/camera/proc/createpicture(atom/target, mob/user, mobs, flag) + var/x_c = target.x - (size-1)/2 + var/y_c = target.y - (size-1)/2 + var/z_c = target.z + var/icon/photoimage = generate_image(x_c, y_c, z_c, size, CAPTURE_MODE_REGULAR, user) var/icon/small_img = icon(photoimage) var/icon/tiny_img = icon(photoimage) diff --git a/code/modules/paperwork/silicon_photography.dm b/code/modules/paperwork/silicon_photography.dm index c754909c4ca..dc22014ae8a 100644 --- a/code/modules/paperwork/silicon_photography.dm +++ b/code/modules/paperwork/silicon_photography.dm @@ -69,8 +69,9 @@ aipictures -= selection usr << "Local image deleted" -/obj/item/device/camera/siliconcam/ai_camera/can_capture_turf(turf/T, mob/user) - var/mob/living/silicon/ai = user +//Capture Proc for AI / Robot +/mob/living/silicon/ai/can_capture_turf(turf/T) + var/mob/living/silicon/ai = src return ai.TurfAdjacent(T) /obj/item/device/camera/siliconcam/proc/toggle_camera_mode()