Files
Bubberstation/code/modules/photography/camera/camera_image_capturing.dm
Ghom 8a6dbb1a45 Gives detectives an ID that looks like an assistant ID when flipped. Also makes their camera silent. (#85912)
## About The Pull Request
This PR adds an ID subtype which the detective outfit uses. It that can
be flipped to go plainclothes as an assistant. Access retained. Spare
clothes not included.

I've also made the detective camera silent (a sound cue is still played
to the user, others won't hear it) and with the flash disabled.

## Why It's Good For The Game
I want to make it a little easier for detectives to go plainclothes.
Between clothings and inventory management, it's already quite tricky as
a gimmick and without doubt a double-edged sword that can lead to
goofy-ass situations where officers actually confuse you for an
assistant. As for the camera, it's just a stealth buff.

## Changelog

🆑
add: Gave the detective an ID that can flipped to look like an assistant
ID.
balance: The detective camera is now silent and doesn't flash.
/🆑
2024-09-15 11:48:09 -07:00

153 lines
5.1 KiB
Plaintext

/obj/effect/appearance_clone
/obj/effect/appearance_clone/New(loc, atom/A) //Intentionally not Initialize(), to make sure the clone assumes the intended appearance in time for the camera getFlatIcon.
if(istype(A))
appearance = A.appearance
dir = A.dir
if(ismovable(A))
var/atom/movable/AM = A
step_x = AM.step_x
step_y = AM.step_y
. = ..()
#define PHYSICAL_POSITION(atom) ((atom.y * world.icon_size) + (atom.pixel_y))
/obj/item/camera/proc/camera_get_icon(list/turfs, turf/center, psize_x = 96, psize_y = 96, datum/turf_reservation/clone_area, size_x, size_y, total_x, total_y)
var/list/atoms = list()
var/list/lighting = list()
var/skip_normal = FALSE
var/wipe_atoms = FALSE
var/mutable_appearance/backdrop = mutable_appearance('icons/hud/screen_gen.dmi', "flash")
backdrop.blend_mode = BLEND_OVERLAY
backdrop.color = "#292319"
if(istype(clone_area) && total_x == clone_area.width && total_y == clone_area.height && size_x >= 0 && size_y > 0)
var/turf/bottom_left = clone_area.bottom_left_turfs[1]
var/cloned_center_x = round(bottom_left.x + ((total_x - 1) / 2))
var/cloned_center_y = round(bottom_left.y + ((total_y - 1) / 2))
for(var/t in turfs)
var/turf/T = t
var/offset_x = T.x - center.x
var/offset_y = T.y - center.y
var/turf/newT = locate(cloned_center_x + offset_x, cloned_center_y + offset_y, bottom_left.z)
if(!(newT in clone_area.reserved_turfs)) //sanity check so we don't overwrite other areas somehow
continue
atoms += new /obj/effect/appearance_clone(newT, T)
if(T.loc.icon_state)
atoms += new /obj/effect/appearance_clone(newT, T.loc)
if(T.lighting_object)
var/obj/effect/appearance_clone/lighting_overlay = new(newT)
lighting_overlay.appearance = T.lighting_object.current_underlay
lighting_overlay.underlays += backdrop
lighting_overlay.blend_mode = BLEND_MULTIPLY
lighting += lighting_overlay
for(var/i in T.contents)
var/atom/A = i
if(!A.invisibility || (see_ghosts && isobserver(A)))
atoms += new /obj/effect/appearance_clone(newT, A)
skip_normal = TRUE
wipe_atoms = TRUE
center = locate(cloned_center_x, cloned_center_y, bottom_left.z)
if(!skip_normal)
for(var/i in turfs)
var/turf/T = i
atoms += T
if(T.lighting_object)
var/obj/effect/appearance_clone/lighting_overlay = new(T)
lighting_overlay.appearance = T.lighting_object.current_underlay
lighting_overlay.underlays += backdrop
lighting_overlay.blend_mode = BLEND_MULTIPLY
lighting += lighting_overlay
for(var/atom/movable/A in T)
if(A.invisibility)
if(!(see_ghosts && isobserver(A)))
continue
atoms += A
CHECK_TICK
var/icon/res = icon('icons/blanks/96x96.dmi', "nothing")
res.Scale(psize_x, psize_y)
atoms += lighting
var/list/sorted = list()
var/j
for(var/i in 1 to atoms.len)
var/atom/c = atoms[i]
for(j = sorted.len, j > 0, --j)
var/atom/c2 = sorted[j]
if(c2.plane > c.plane)
continue
if(c2.plane < c.plane)
break
var/c_position = PHYSICAL_POSITION(c)
var/c2_position = PHYSICAL_POSITION(c2)
// If you are above me, I layer above you
if(c2_position - 32 >= c_position)
break
// If I am above you you will always layer above me
if(c2_position <= c_position - 32)
continue
if(c2.layer < c.layer)
break
sorted.Insert(j+1, c)
CHECK_TICK
var/xcomp = FLOOR(psize_x / 2, 1) - 15
var/ycomp = FLOOR(psize_y / 2, 1) - 15
if(!skip_normal) //these are not clones
for(var/atom/A in sorted)
var/xo = (A.x - center.x) * world.icon_size + A.pixel_x + xcomp
var/yo = (A.y - center.y) * world.icon_size + A.pixel_y + ycomp
if(ismovable(A))
var/atom/movable/AM = A
xo += AM.step_x
yo += AM.step_y
var/icon/img = getFlatIcon(A, no_anim = TRUE)
res.Blend(img, blendMode2iconMode(A.blend_mode), xo, yo)
CHECK_TICK
else
for(var/X in sorted) //these are clones
var/obj/effect/appearance_clone/clone = X
var/icon/img = getFlatIcon(clone, no_anim = TRUE)
if(!img)
CHECK_TICK
continue
// Center of the image in X
var/xo = (clone.x - center.x) * world.icon_size + clone.pixel_x + xcomp + clone.step_x
// Center of the image in Y
var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp + clone.step_y
if(clone.transform) // getFlatIcon doesn't give a snot about transforms.
var/datum/decompose_matrix/decompose = clone.transform.decompose()
// Scale in X, Y
if(decompose.scale_x != 1 || decompose.scale_y != 1)
var/base_w = img.Width()
var/base_h = img.Height()
// scale_x can be negative
img.Scale(base_w * abs(decompose.scale_x), base_h * decompose.scale_y)
if(decompose.scale_x < 0)
img.Flip(EAST)
xo -= base_w * (decompose.scale_x - SIGN(decompose.scale_x)) / 2 * SIGN(decompose.scale_x)
yo -= base_h * (decompose.scale_y - 1) / 2
// Rotation
if(decompose.rotation != 0)
img.Turn(decompose.rotation)
// Shift
xo += decompose.shift_x
yo += decompose.shift_y
res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo)
CHECK_TICK
if(wipe_atoms)
QDEL_LIST(atoms)
else
QDEL_LIST(lighting)
return res
#undef PHYSICAL_POSITION