Files
+37 21b4095dfd [MDB IGNORE] [IDB IGNORE] Upstream Sync - 04/17/2026 (#5453)
Upstream 04/17/2026

fixes https://github.com/Bubberstation/Bubberstation/issues/5549

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com>
Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com>
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com>
Co-authored-by: loganuk <fakeemail123@aol.com>
Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com>
Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com>
Co-authored-by: Isratosh <Isratosh@hotmail.com>
Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com>
Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com>
Co-authored-by: Alexander V. <volas@ya.ru>
Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com>
Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Tim <timothymtorres@gmail.com>
Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com>
Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com>
Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com>
Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com>
Co-authored-by: Josh <josh.adam.powell@gmail.com>
Co-authored-by: Josh Powell <josh.powell@softwire.com>
Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com>
Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com>
Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com>
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
2026-05-16 00:56:00 +02:00

161 lines
5.3 KiB
Plaintext

/obj/effect/appearance_clone
/obj/effect/appearance_clone/New(loc, atom/our_atom) //Intentionally not Initialize(), to make sure the clone assumes the intended appearance in time for the camera getFlatIcon.
if(!istype(our_atom))
return ..()
if(!isopenspaceturf(our_atom))
appearance = our_atom.appearance
dir = our_atom.dir
if(ismovable(our_atom))
var/atom/movable/our_movable = our_atom
step_x = our_movable.step_x
step_y = our_movable.step_y
return ..()
#define PHYSICAL_POSITION(atom) ((atom.y * ICON_SIZE_Y) + (atom.pixel_y))
/obj/item/camera/proc/camera_get_icon(list/turfs, turf/center, datum/turf_reservation/clone_area)
PRIVATE_PROC(TRUE)
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"
var/turf/bottom_left = clone_area.bottom_left_turfs[1]
var/cloned_center_x = round(bottom_left.x + ((clone_area.width - 1) / 2))
var/cloned_center_y = round(bottom_left.y + ((clone_area.height - 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/atom/found_atom as anything in T.contents)
if(HAS_TRAIT(found_atom, TRAIT_INVISIBLE_TO_CAMERA))
if(see_ghosts)
atoms += new /obj/effect/appearance_clone(newT, found_atom)
else if(!found_atom.invisibility || (see_ghosts && isobserver(found_atom)))
atoms += new /obj/effect/appearance_clone(newT, found_atom)
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) || HAS_TRAIT(A, TRAIT_INVISIBLE_TO_CAMERA))))
continue
atoms += A
CHECK_TICK
var/psize_x = clone_area.width * ICON_SIZE_X
var/psize_y = clone_area.height * ICON_SIZE_Y
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) * ICON_SIZE_X + A.pixel_x + xcomp
var/yo = (A.y - center.y) * ICON_SIZE_Y + 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) * ICON_SIZE_X + clone.pixel_x + xcomp + clone.step_x
// Center of the image in Y
var/yo = (clone.y - center.y) * ICON_SIZE_Y + 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