Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into auxtools-atmos
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
/turf/open
|
||||
plane = FLOOR_PLANE
|
||||
/// Does dirt buildup happen on us?
|
||||
var/dirt_buildup_allowed = FALSE
|
||||
/// Dirt level.
|
||||
var/dirtyness = 0
|
||||
/// Dirt level to spawn dirt. Null to use config.
|
||||
var/dirt_spawn_threshold
|
||||
/// Slowdown applied to mobs on us.
|
||||
var/slowdown = 0 //negative for faster, positive for slower
|
||||
|
||||
var/postdig_icon_change = FALSE
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
canSmoothWith = list(/turf/open/floor/fakepit, /turf/open/chasm)
|
||||
density = TRUE //This will prevent hostile mobs from pathing into chasms, while the canpass override will still let it function like an open turf
|
||||
bullet_bounce_sound = null //abandon all hope ye who enter
|
||||
dirt_buildup_allowed = FALSE
|
||||
|
||||
/turf/open/chasm/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
//Making the station dirty, one tile at a time. Called by master controller's setup_objects
|
||||
|
||||
/turf/open/floor/proc/MakeDirty()
|
||||
if(CONFIG_GET(flag/persistent_debris_only))
|
||||
return
|
||||
|
||||
if(prob(66)) //fastest possible exit 2/3 of the time
|
||||
return
|
||||
|
||||
@@ -38,7 +41,7 @@
|
||||
return
|
||||
|
||||
//Construction zones. Blood, sweat, and oil. Oh, and dirt.
|
||||
var/static/list/engine_dirt_areas = typecacheof(list(/area/engine,
|
||||
var/static/list/engine_dirt_areas = typecacheof(list(/area/engine,
|
||||
/area/crew_quarters/heads/chief,
|
||||
/area/ruin/space/derelict/assembly_line,
|
||||
/area/science/robotics,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
name = "floor"
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
baseturfs = /turf/open/floor/plating
|
||||
dirt_buildup_allowed = TRUE
|
||||
|
||||
footstep = FOOTSTEP_FLOOR
|
||||
barefootstep = FOOTSTEP_HARD_BAREFOOT
|
||||
@@ -137,6 +138,9 @@
|
||||
burnt = 1
|
||||
|
||||
/turf/open/floor/proc/make_plating()
|
||||
for(var/obj/effect/decal/cleanable/C in src)
|
||||
if(C.wiped_by_floor_change)
|
||||
qdel(C)
|
||||
return ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
|
||||
/turf/open/floor/ChangeTurf(path, new_baseturf, flags)
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
if(M.client && (is_servant_of_ratvar(M) || isobserver(M) || M.stat == DEAD))
|
||||
viewing += M.client
|
||||
flick_overlay(I, viewing, 8)
|
||||
L.adjustToxLoss(-3, TRUE, TRUE)
|
||||
L.adjustToxLoss(-3, TRUE, TRUE, toxins_type = TOX_OMNI)
|
||||
|
||||
/turf/open/floor/clockwork/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
|
||||
return
|
||||
@@ -278,4 +278,4 @@
|
||||
heavyfootstep = FOOTSTEP_RUST
|
||||
|
||||
/turf/open/floor/plating/rust/rust_heretic_act()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -61,6 +61,9 @@
|
||||
to_chat(user, "<span class='notice'>You begin reinforcing the floor...</span>")
|
||||
if(do_after(user, 30, target = src))
|
||||
if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine))
|
||||
for(var/obj/effect/decal/cleanable/decal in src)
|
||||
if(decal.wiped_by_floor_change)
|
||||
qdel(decal)
|
||||
PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
|
||||
R.use(2)
|
||||
@@ -78,6 +81,9 @@
|
||||
to_chat(user, "<span class='notice'>You begin adding glass to the floor...</span>")
|
||||
if(do_after(user, 5, target = src))
|
||||
if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass))
|
||||
for(var/obj/effect/decal/cleanable/decal in src)
|
||||
if(decal.wiped_by_floor_change)
|
||||
qdel(decal)
|
||||
PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
|
||||
G.use(2)
|
||||
@@ -95,6 +101,9 @@
|
||||
to_chat(user, "<span class='notice'>You begin adding reinforced glass to the floor...</span>")
|
||||
if(do_after(user, 10, target = src))
|
||||
if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced))
|
||||
for(var/obj/effect/decal/cleanable/decal in src)
|
||||
if(decal.wiped_by_floor_change)
|
||||
qdel(decal)
|
||||
PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
|
||||
RG.use(2)
|
||||
@@ -110,6 +119,9 @@
|
||||
var/obj/item/stack/tile/W = C
|
||||
if(!W.use(1))
|
||||
return
|
||||
for(var/obj/effect/decal/cleanable/decal in src)
|
||||
if(decal.wiped_by_floor_change)
|
||||
qdel(decal)
|
||||
if(istype(W, /obj/item/stack/tile/material))
|
||||
var/turf/newturf = PlaceOnTop(/turf/open/floor/material, flags = CHANGETURF_INHERIT_AIR)
|
||||
newturf.set_custom_materials(W.custom_materials)
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
return TRUE
|
||||
if(floor_tile)
|
||||
new floor_tile(src, 2)
|
||||
for(var/obj/effect/decal/cleanable/C in src)
|
||||
if(C.wiped_by_floor_change)
|
||||
qdel(C)
|
||||
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
gender = PLURAL //"That's some lava."
|
||||
baseturfs = /turf/open/lava //lava all the way down
|
||||
slowdown = 2
|
||||
dirt_buildup_allowed = FALSE
|
||||
|
||||
light_range = 2
|
||||
light_power = 0.75
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
planetary_atmos = TRUE
|
||||
bullet_bounce_sound = null //forever falling
|
||||
tiled_dirt = FALSE
|
||||
dirt_buildup_allowed = FALSE
|
||||
|
||||
/turf/open/indestructible/reebe_void/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
icon_state = "0"
|
||||
name = "\proper space"
|
||||
intact = 0
|
||||
dirt_buildup_allowed = FALSE
|
||||
|
||||
initial_temperature = TCMB
|
||||
thermal_conductivity = 0
|
||||
@@ -24,7 +25,13 @@
|
||||
//This is used to optimize the map loader
|
||||
return
|
||||
|
||||
/**
|
||||
* Space Initialize
|
||||
*
|
||||
* Doesn't call parent, see [/atom/proc/Initialize]
|
||||
*/
|
||||
/turf/open/space/Initialize()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
icon_state = SPACE_ICON_STATE
|
||||
if(!space_gas)
|
||||
space_gas = new
|
||||
@@ -37,6 +44,15 @@
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
flags_1 |= INITIALIZED_1
|
||||
|
||||
// if (length(smoothing_groups))
|
||||
// sortTim(smoothing_groups) //In case it's not properly ordered, let's avoid duplicate entries with the same values.
|
||||
// SET_BITFLAG_LIST(smoothing_groups)
|
||||
// if (length(canSmoothWith))
|
||||
// sortTim(canSmoothWith)
|
||||
// if(canSmoothWith[length(canSmoothWith)] > MAX_S_TURF) //If the last element is higher than the maximum turf-only value, then it must scan turf contents for smoothing targets.
|
||||
// smoothing_flags |= SMOOTH_OBJ
|
||||
// SET_BITFLAG_LIST(canSmoothWith)
|
||||
|
||||
var/area/A = loc
|
||||
if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
|
||||
add_overlay(/obj/effect/fullbright)
|
||||
@@ -47,6 +63,13 @@
|
||||
if (opacity)
|
||||
has_opaque_atom = TRUE
|
||||
|
||||
var/turf/T = SSmapping.get_turf_above(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, DOWN)
|
||||
T = SSmapping.get_turf_below(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, UP)
|
||||
|
||||
ComponentInitialize()
|
||||
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
@@ -72,6 +95,10 @@
|
||||
/turf/open/space/Assimilate_Air()
|
||||
return
|
||||
|
||||
//IT SHOULD RETURN NULL YOU MONKEY, WHY IN TARNATION WHAT THE FUCKING FUCK
|
||||
/turf/open/space/remove_air(amount)
|
||||
return null
|
||||
|
||||
/turf/open/space/proc/update_starlight()
|
||||
if(CONFIG_GET(flag/starlight))
|
||||
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
|
||||
@@ -88,9 +115,8 @@
|
||||
/turf/open/space/proc/CanBuildHere()
|
||||
return TRUE
|
||||
|
||||
/turf/open/space/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
|
||||
if(lube & FLYING_DOESNT_HELP)
|
||||
return ..()
|
||||
/turf/open/space/handle_slip()
|
||||
return // no lube bullshit, this is space
|
||||
|
||||
/turf/open/space/attackby(obj/item/C, mob/user, params)
|
||||
..()
|
||||
@@ -105,15 +131,16 @@
|
||||
return
|
||||
if(L)
|
||||
if(R.use(1))
|
||||
qdel(L)
|
||||
to_chat(user, "<span class='notice'>You construct a catwalk.</span>")
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
new/obj/structure/lattice/catwalk(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two rods to build a catwalk!</span>")
|
||||
return
|
||||
if(R.use(1))
|
||||
to_chat(user, "<span class='notice'>You construct a lattice.</span>")
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
ReplaceWithLattice()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one rod to build a lattice.</span>")
|
||||
@@ -124,7 +151,7 @@
|
||||
var/obj/item/stack/tile/plasteel/S = C
|
||||
if(S.use(1))
|
||||
qdel(L)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
to_chat(user, "<span class='notice'>You build a floor.</span>")
|
||||
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
|
||||
+47
-37
@@ -1,8 +1,11 @@
|
||||
GLOBAL_LIST_EMPTY(station_turfs)
|
||||
|
||||
/// Any floor or wall. What makes up the station and the rest of the map.
|
||||
/turf
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
level = 1
|
||||
vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_ID //when this be added to vis_contents of something it inherit something.plane and be associatet with something on clicking,
|
||||
//important for visualisation of turf in openspace and interraction with openspace that show you turf.
|
||||
flags_1 = CAN_BE_DIRTY_1
|
||||
vis_flags = VIS_INHERIT_ID|VIS_INHERIT_PLANE // Important for interaction with and visualization of openspace.
|
||||
luminosity = 1
|
||||
|
||||
var/intact = 1
|
||||
|
||||
@@ -19,8 +22,6 @@
|
||||
|
||||
var/blocks_air = FALSE
|
||||
|
||||
flags_1 = CAN_BE_DIRTY_1
|
||||
|
||||
var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes
|
||||
|
||||
var/explosion_level = 0 //for preventing explosion dodging
|
||||
@@ -41,7 +42,13 @@
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
/**
|
||||
* Turf Initialize
|
||||
*
|
||||
* Doesn't call parent, see [/atom/proc/Initialize]
|
||||
*/
|
||||
/turf/Initialize(mapload)
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
flags_1 |= INITIALIZED_1
|
||||
@@ -49,7 +56,7 @@
|
||||
// by default, vis_contents is inherited from the turf that was here before
|
||||
vis_contents.Cut()
|
||||
|
||||
if(color)
|
||||
if(color) // is this being used? This is here because parent isn't being called
|
||||
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
assemble_baseturfs()
|
||||
@@ -57,6 +64,7 @@
|
||||
levelupdate()
|
||||
if(smooth)
|
||||
queue_smooth(src)
|
||||
|
||||
visibilityChanged()
|
||||
|
||||
for(var/atom/movable/AM in src)
|
||||
@@ -75,11 +83,10 @@
|
||||
var/turf/T = SSmapping.get_turf_above(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, DOWN)
|
||||
SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, DOWN)
|
||||
T = SSmapping.get_turf_below(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, UP)
|
||||
SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP)
|
||||
|
||||
|
||||
if (opacity)
|
||||
has_opaque_atom = TRUE
|
||||
@@ -123,8 +130,6 @@
|
||||
var/turf/B = new world.turf(src)
|
||||
for(var/A in B.contents)
|
||||
qdel(A)
|
||||
for(var/I in B.vars)
|
||||
B.vars[I] = null
|
||||
return
|
||||
visibilityChanged()
|
||||
QDEL_LIST(blueprint_data)
|
||||
@@ -132,12 +137,14 @@
|
||||
requires_activation = FALSE
|
||||
..()
|
||||
|
||||
/turf/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
/turf/on_attack_hand(mob/user)
|
||||
user.Move_Pulled(src)
|
||||
|
||||
/turf/proc/multiz_turf_del(turf/T, dir)
|
||||
// SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_DEL, T, dir)
|
||||
|
||||
/turf/proc/multiz_turf_new(turf/T, dir)
|
||||
SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_NEW, T, dir)
|
||||
|
||||
//zPassIn doesn't necessarily pass an atom!
|
||||
//direction is direction of travel of air
|
||||
@@ -168,13 +175,14 @@
|
||||
prev_turf.visible_message("<span class='danger'>[mov_name] falls through [prev_turf]!</span>")
|
||||
if(flags & FALL_INTERCEPTED)
|
||||
return
|
||||
if(zFall(A, ++levels))
|
||||
if(zFall(A, levels + 1))
|
||||
return FALSE
|
||||
A.visible_message("<span class='danger'>[A] crashes into [src]!</span>")
|
||||
A.onZImpact(src, levels)
|
||||
return TRUE
|
||||
|
||||
/turf/proc/can_zFall(atom/movable/A, levels = 1, turf/target)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return zPassOut(A, DOWN, target) && target.zPassIn(A, DOWN, src)
|
||||
|
||||
/turf/proc/zFall(atom/movable/A, levels = 1, force = FALSE)
|
||||
@@ -227,49 +235,54 @@
|
||||
stack_trace("Non movable passed to turf CanPass : [mover]")
|
||||
return FALSE
|
||||
|
||||
//There's a lot of QDELETED() calls here if someone can figure out how to optimize this but not runtime when something gets deleted by a Bump/CanPass/Cross call, lemme know or go ahead and fix this mess - kevinz000
|
||||
/turf/Enter(atom/movable/mover, atom/oldloc)
|
||||
// Do not call ..()
|
||||
// Byond's default turf/Enter() doesn't have the behaviour we want with Bump()
|
||||
// By default byond will call Bump() on the first dense object in contents
|
||||
// Here's hoping it doesn't stay like this for years before we finish conversion to step_
|
||||
var/atom/firstbump
|
||||
if(!CanPass(mover, src))
|
||||
firstbump = src
|
||||
else
|
||||
var/canPassSelf = CanPass(mover, src)
|
||||
if(canPassSelf || (mover.movement_type & UNSTOPPABLE))
|
||||
for(var/i in contents)
|
||||
if(QDELETED(mover))
|
||||
return FALSE //We were deleted, do not attempt to proceed with movement.
|
||||
if(i == mover || i == mover.loc) // Multi tile objects and moving out of other objects
|
||||
continue
|
||||
if(QDELETED(mover))
|
||||
break
|
||||
var/atom/movable/thing = i
|
||||
if(!thing.Cross(mover))
|
||||
if(CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE))
|
||||
if(QDELETED(mover)) //Mover deleted from Cross/CanPass, do not proceed.
|
||||
return FALSE
|
||||
if((mover.movement_type & UNSTOPPABLE))
|
||||
mover.Bump(thing)
|
||||
continue
|
||||
else
|
||||
if(!firstbump || ((thing.layer > firstbump.layer || thing.flags_1 & ON_BORDER_1) && !(firstbump.flags_1 & ON_BORDER_1)))
|
||||
firstbump = thing
|
||||
if(QDELETED(mover)) //Mover deleted from Cross/CanPass/Bump, do not proceed.
|
||||
return FALSE
|
||||
if(!canPassSelf) //Even if mover is unstoppable they need to bump us.
|
||||
firstbump = src
|
||||
if(firstbump)
|
||||
if(!QDELETED(mover))
|
||||
mover.Bump(firstbump)
|
||||
return CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE)
|
||||
mover.Bump(firstbump)
|
||||
return (mover.movement_type & UNSTOPPABLE)
|
||||
return TRUE
|
||||
|
||||
/turf/Exit(atom/movable/mover, atom/newloc)
|
||||
. = ..()
|
||||
if(!.)
|
||||
if(!. || QDELETED(mover))
|
||||
return FALSE
|
||||
for(var/i in contents)
|
||||
if(QDELETED(mover))
|
||||
break
|
||||
if(i == mover)
|
||||
continue
|
||||
var/atom/movable/thing = i
|
||||
if(!thing.Uncross(mover, newloc))
|
||||
if(thing.flags_1 & ON_BORDER_1)
|
||||
mover.Bump(thing)
|
||||
if(!CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE))
|
||||
if(!(mover.movement_type & UNSTOPPABLE))
|
||||
return FALSE
|
||||
if(QDELETED(mover))
|
||||
return FALSE //We were deleted.
|
||||
|
||||
/turf/Entered(atom/movable/AM)
|
||||
..()
|
||||
@@ -281,6 +294,7 @@
|
||||
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
|
||||
reconsider_lights()
|
||||
|
||||
|
||||
/turf/open/Entered(atom/movable/AM)
|
||||
..()
|
||||
//melting
|
||||
@@ -288,7 +302,6 @@
|
||||
var/obj/O = AM
|
||||
if(O.obj_flags & FROZEN)
|
||||
O.make_unfrozen()
|
||||
|
||||
if(!AM.zfalling)
|
||||
zFall(AM)
|
||||
|
||||
@@ -346,14 +359,13 @@
|
||||
|
||||
/turf/proc/levelupdate()
|
||||
for(var/obj/O in src)
|
||||
if(O.level == 1 && (O.flags_1 & INITIALIZED_1))
|
||||
O.hide(src.intact)
|
||||
if(O.flags_1 & INITIALIZED_1)
|
||||
// SEND_SIGNAL(O, COMSIG_OBJ_HIDE, intact)
|
||||
O.hide(intact)
|
||||
|
||||
// override for space turfs, since they should never hide anything
|
||||
/turf/open/space/levelupdate()
|
||||
for(var/obj/O in src)
|
||||
if(O.level == 1 && (O.flags_1 & INITIALIZED_1))
|
||||
O.hide(0)
|
||||
return
|
||||
|
||||
// Removes all signs of lattice on the pos of the turf -Donkieyo
|
||||
/turf/proc/RemoveLattice()
|
||||
@@ -378,13 +390,13 @@
|
||||
if(.)
|
||||
return
|
||||
if(length(src_object.contents()))
|
||||
to_chat(user, "<span class='notice'>You start dumping out the contents...</span>")
|
||||
if(!do_after(user,20,target=src_object.parent))
|
||||
to_chat(usr, "<span class='notice'>You start dumping out the contents...</span>")
|
||||
if(!do_after(usr,20,target=src_object.parent))
|
||||
return FALSE
|
||||
|
||||
var/list/things = src_object.contents()
|
||||
var/datum/progressbar/progress = new(user, things.len, src)
|
||||
while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress)))
|
||||
while (do_after(usr, 1 SECONDS, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress)))
|
||||
stoplag(1)
|
||||
qdel(progress)
|
||||
|
||||
@@ -504,10 +516,8 @@
|
||||
I.loc = src
|
||||
I.setDir(AM.dir)
|
||||
I.alpha = 128
|
||||
|
||||
LAZYADD(blueprint_data, I)
|
||||
|
||||
|
||||
/turf/proc/add_blueprints_preround(atom/movable/AM)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
add_blueprints(AM)
|
||||
@@ -541,7 +551,7 @@
|
||||
if(!forced)
|
||||
return
|
||||
if(has_gravity(src))
|
||||
playsound(src, "bodyfall", 50, 1)
|
||||
playsound(src, "bodyfall", 50, TRUE)
|
||||
faller.drop_all_held_items()
|
||||
|
||||
/turf/proc/photograph(limit=20)
|
||||
|
||||
Reference in New Issue
Block a user