You can no longer stack machines on one tile (#19683)

* Ports climbable & blocked turf

Adds the climbable element to replace the copy paste code between machines and structures
Ports the code improvements to blocked turf checks, commenting back in its uses that tattax had added but couldnt get functional (fixes ethereal jaunt & hierophant teleporting)
Ports over LADYADDASSOCLIST code improvements, this has no effect in-game and mostly in the codebase, it's only ever used in two other locations total.
Fixes being able to stack several machines on one tile

* fixes climbing on crates

* Update climbable.dm

* merge conflicts r awesome
This commit is contained in:
John Willard
2023-07-28 18:29:22 -04:00
committed by GitHub
parent 77ddc8414a
commit b5718d1994
53 changed files with 358 additions and 278 deletions

View File

@@ -0,0 +1,13 @@
// Byond direction defines, because I want to put them somewhere.
// #define NORTH 1
// #define SOUTH 2
// #define EAST 4
// #define WEST 8
#define TEXT_NORTH "[NORTH]"
#define TEXT_SOUTH "[SOUTH]"
#define TEXT_EAST "[EAST]"
#define TEXT_WEST "[WEST]"
/// Inverse direction, taking into account UP|DOWN if necessary.
#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) )

View File

@@ -1,15 +1,3 @@
// Byond direction defines, because I want to put them somewhere.
// #define NORTH 1
// #define SOUTH 2
// #define EAST 4
// #define WEST 8
#define TEXT_NORTH "[NORTH]"
#define TEXT_SOUTH "[SOUTH]"
#define TEXT_EAST "[EAST]"
#define TEXT_WEST "[WEST]"
//Human Overlays Indexes/////////
#define MUTATIONS_LAYER 28 //mutations. Tk headglows, cold resistance glow, etc
#define BODY_BEHIND_LAYER 27 //certain mutantrace features (tail when looking south) that must appear behind the body parts

View File

@@ -359,6 +359,8 @@
/// trait associated to being held in a chokehold
#define CHOKEHOLD_TRAIT "chokehold"
#define CRYO_TRAIT "cryo_trait"
/// Trait applied by element
#define ELEMENT_TRAIT(source) "element_trait_[source]"
// unique trait sources, still defines
#define CLONING_POD_TRAIT "cloning-pod"
@@ -439,5 +441,8 @@
///every object that is currently the active storage of some client mob has this trait
#define TRAIT_ACTIVE_STORAGE "active_storage"
/// Climbable trait, given and taken by the climbable element when added or removed. Exists to be easily checked via HAS_TRAIT().
#define TRAIT_CLIMBABLE "trait_climbable"
///Organ traits
#define TRAIT_BALLMER_SCIENTIST "ballmer_scientist"

View File

@@ -32,7 +32,11 @@
///Returns the list if it's actually a valid list, otherwise will initialize it
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V);
///Adds to the item K the value V, if the list is null it will initialize it
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += V;
///This is used to add onto lazy assoc list when the value you're adding is a /list/. This one has extra safety over lazyaddassoc because the value could be null (and thus cant be used to += objects)
#define LAZYADDASSOCLIST(L, K, V) if(!L) { L = list(); } L[K] += list(V);
///Removes the value V from the item K, if the item K is empty will remove it from the list, if the list is empty will set the list to null
#define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; }
/// Passed into BINARY_INSERT to compare keys

View File

@@ -736,7 +736,7 @@
continue
if (!isspaceturf(found_turf))
if (!is_blocked_turf(found_turf))
if (!found_turf.is_blocked_turf())
possible_loc.Add(found_turf)
// Need at least one free location.

View File

@@ -504,15 +504,6 @@ Turf and target are separate in case you want to teleport some distance from a t
return 1
/proc/is_blocked_turf(turf/T, exclude_mobs)
if(T.density)
return 1
for(var/i in T)
var/atom/A = i
if(A.density && (!exclude_mobs || !ismob(A)))
return 1
return 0
/proc/is_anchored_dense_turf(turf/T) //like the older version of the above, fails only if also anchored
if(T.density)
return 1
@@ -526,7 +517,7 @@ Turf and target are separate in case you want to teleport some distance from a t
var/base_dir = get_dir(ref, get_step_towards(ref,trg))
var/turf/temp = get_step_towards(ref,trg)
if(is_blocked_turf(temp))
if(temp.is_blocked_turf())
var/dir_alt1 = turn(base_dir, 90)
var/dir_alt2 = turn(base_dir, -90)
var/turf/turf_last1 = temp
@@ -535,10 +526,10 @@ Turf and target are separate in case you want to teleport some distance from a t
var/breakpoint = 0
while(!free_tile && breakpoint < 10)
if(!is_blocked_turf(turf_last1))
if(!turf_last1.is_blocked_turf())
free_tile = turf_last1
break
if(!is_blocked_turf(turf_last2))
if(!turf_last2.is_blocked_turf())
free_tile = turf_last2
break
turf_last1 = get_step(turf_last1,dir_alt1)

View File

@@ -836,7 +836,7 @@ SUBSYSTEM_DEF(job)
//last hurrah
var/list/avail = list()
for(var/turf/T in A)
if(!is_blocked_turf(T, TRUE))
if(!T.is_blocked_turf(TRUE))
avail += T
if(avail.len)
destination = pick(avail)
@@ -847,7 +847,7 @@ SUBSYSTEM_DEF(job)
var/list/arrivals_turfs = shuffle(get_area_turfs(/area/shuttle/arrival))
if(arrivals_turfs.len)
for(var/turf/T in arrivals_turfs)
if(!is_blocked_turf(T, TRUE))
if(!T.is_blocked_turf(TRUE))
T.JoinPlayerHere(M, FALSE)
return
//last chance, pick ANY spot on arrivals and dump em

View File

@@ -54,7 +54,7 @@ SUBSYSTEM_DEF(minor_mapping)
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
all_turfs += block(locate(1,1,z), locate(world.maxx,world.maxy,z))
for(var/turf/open/floor/plating/T in all_turfs)
if(is_blocked_turf(T))
if(T.is_blocked_turf())
continue
if(locate(/obj/structure/cable) in T)
exposed_wires += T

View File

@@ -196,7 +196,7 @@
message.maptext = complete_text
// View the message
LAZYADDASSOC(owned_by.seen_messages, message_loc, src)
LAZYADDASSOCLIST(owned_by.seen_messages, message_loc, src)
owned_by.images |= message
animate(message, alpha = 255, time = CHAT_MESSAGE_SPAWN_TIME)

View File

@@ -0,0 +1,130 @@
/datum/element/climbable
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH_ON_HOST_DESTROY // Detach for turfs
argument_hash_start_idx = 2
///Time it takes to climb onto the object
var/climb_time
///Stun duration for when you get onto the object
var/climb_stun
///Assoc list of object being climbed on - climbers. This allows us to check who needs to be shoved off a climbable object when its clicked on.
var/list/current_climbers
/datum/element/climbable/Attach(
datum/target,
climb_time = 2 SECONDS,
climb_stun = 2 SECONDS,
)
. = ..()
if(!isatom(target) || isarea(target))
return ELEMENT_INCOMPATIBLE
src.climb_time = climb_time
src.climb_stun = climb_stun
RegisterSignal(target, COMSIG_ATOM_ATTACK_HAND, PROC_REF(attack_hand))
RegisterSignal(target, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
RegisterSignal(target, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(mousedrop_receive))
RegisterSignal(target, COMSIG_ATOM_BUMPED, PROC_REF(try_speedrun))
ADD_TRAIT(target, TRAIT_CLIMBABLE, ELEMENT_TRAIT(type))
/datum/element/climbable/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_PARENT_EXAMINE, COMSIG_MOUSEDROPPED_ONTO, COMSIG_ATOM_BUMPED))
REMOVE_TRAIT(target, TRAIT_CLIMBABLE, ELEMENT_TRAIT(type))
return ..()
/datum/element/climbable/proc/on_examine(atom/source, mob/user, list/examine_texts)
SIGNAL_HANDLER
examine_texts += span_notice("[source] looks climbable.")
/datum/element/climbable/proc/can_climb(atom/source, mob/user)
var/dir_step = get_dir(user, source.loc)
//To jump over a railing you have to be standing next to it, not far behind it.
if(source.flags_1 & ON_BORDER_1 && user.loc != source.loc && (dir_step & source.dir) == source.dir)
return FALSE
return TRUE
/datum/element/climbable/proc/attack_hand(atom/climbed_thing, mob/user)
SIGNAL_HANDLER
var/list/climbers = LAZYACCESS(current_climbers, climbed_thing)
for(var/i in climbers)
var/mob/living/structure_climber = i
if(structure_climber == user)
return
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(climbed_thing)
structure_climber.Paralyze(40)
structure_climber.visible_message(span_warning("[structure_climber] is knocked off [climbed_thing]."), span_warning("You're knocked off [climbed_thing]!"), span_hear("You hear a cry from [structure_climber], followed by a slam."))
/datum/element/climbable/proc/climb_structure(atom/climbed_thing, mob/living/user, params)
if(!can_climb(climbed_thing, user))
return
climbed_thing.add_fingerprint(user)
user.visible_message(span_warning("[user] starts climbing onto [climbed_thing]."), \
span_notice("You start climbing onto [climbed_thing]..."))
var/adjusted_climb_time = climb_time
var/adjusted_climb_stun = climb_stun
if(HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //climbing takes twice as long without help from the hands.
adjusted_climb_time *= 2
if(isalien(user))
adjusted_climb_time *= 0.25 //aliens are terrifyingly fast
if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am???
adjusted_climb_time *= 0.8
adjusted_climb_stun *= 0.8
LAZYADDASSOCLIST(current_climbers, climbed_thing, user)
if(do_after(user, adjusted_climb_time, climbed_thing))
if(QDELETED(climbed_thing)) //Checking if structure has been destroyed
return
if(do_climb(climbed_thing, user, params))
user.visible_message(span_warning("[user] climbs onto [climbed_thing]."), \
span_notice("You climb onto [climbed_thing]."))
log_combat(user, climbed_thing, "climbed onto")
if(adjusted_climb_stun)
user.Stun(adjusted_climb_stun)
else
to_chat(user, span_warning("You fail to climb onto [climbed_thing]."))
LAZYREMOVEASSOC(current_climbers, climbed_thing, user)
/datum/element/climbable/proc/do_climb(atom/climbed_thing, mob/living/user, params)
if(!can_climb(climbed_thing, user))
return
climbed_thing.set_density(FALSE)
var/dir_step = get_dir(user, climbed_thing.loc)
var/same_loc = climbed_thing.loc == user.loc
// on-border objects can be vaulted over and into the next turf.
// The reverse dir check is for when normal behavior should apply instead (e.g. John Doe hops east of a railing facing west, ending on the same turf as it).
if(climbed_thing.flags_1 & ON_BORDER_1 && (same_loc || !(dir_step & REVERSE_DIR(climbed_thing.dir))))
//it can be vaulted over in two different cardinal directions. we choose one.
if(ISDIAGONALDIR(climbed_thing.dir) && same_loc)
if(params) //we check the icon x and y parameters of the click-drag to determine step_dir.
var/list/modifiers = params2list(params)
var/x_dist = (text2num(LAZYACCESS(modifiers, ICON_X)) - world.icon_size/2) * (climbed_thing.dir & WEST ? -1 : 1)
var/y_dist = (text2num(LAZYACCESS(modifiers, ICON_Y)) - world.icon_size/2) * (climbed_thing.dir & SOUTH ? -1 : 1)
dir_step = (x_dist >= y_dist ? (EAST|WEST) : (NORTH|SOUTH)) & climbed_thing.dir
else //user is being moved by a forced_movement datum. dir_step will be the direction to the forced movement target.
dir_step = get_dir(user, user.force_moving.target)
else
dir_step = get_dir(user, get_step(climbed_thing, climbed_thing.dir))
. = step(user, dir_step)
climbed_thing.set_density(TRUE)
///Handles climbing onto the atom when you click-drag
/datum/element/climbable/proc/mousedrop_receive(atom/climbed_thing, atom/movable/dropped_atom, mob/user, params)
SIGNAL_HANDLER
if(user == dropped_atom && isliving(dropped_atom))
var/mob/living/living_target = dropped_atom
if(isanimal(living_target))
var/mob/living/simple_animal/animal = dropped_atom
if (!animal.dextrous)
return
if(living_target.mobility_flags & MOBILITY_MOVE)
INVOKE_ASYNC(src, PROC_REF(climb_structure), climbed_thing, living_target, params)
return
///Tries to climb onto the target if the forced movement of the mob allows it
/datum/element/climbable/proc/try_speedrun(datum/source, mob/bumpee)
SIGNAL_HANDLER
if(!istype(bumpee))
return
if(bumpee.force_moving?.allow_climbing)
do_climb(source, bumpee)

View File

@@ -84,10 +84,3 @@
. = TryMove(TRUE)
. = . && (vic.loc != tar.loc)
/mob/Bump(atom/A)
. = ..()
if(force_moving && force_moving.allow_climbing && isstructure(A))
var/obj/structure/S = A
if(S.climbable)
S.do_climb(src)

View File

@@ -131,7 +131,6 @@ Class Procs:
/// For storing and overriding ui id
var/tgui_id // ID of TGUI interface
var/climbable = FALSE
var/climb_time = 20
var/climb_stun = 20
var/mob/living/machineclimber
@@ -409,25 +408,37 @@ Class Procs:
deconstruct(TRUE)
/obj/machinery/deconstruct(disassembled = TRUE, force = FALSE)
if(!(flags_1 & NODECONSTRUCT_1))
on_deconstruction()
if(component_parts && component_parts.len)
if(!force)
spawn_frame(disassembled)
for(var/obj/item/I in component_parts)
I.forceMove(loc)
component_parts.Cut()
qdel(src)
if(flags_1 & NODECONSTRUCT_1)
return ..()
on_deconstruction()
if(!LAZYLEN(component_parts))
return ..()
spawn_frame(disassembled)
for(var/obj/item/I in component_parts)
I.forceMove(loc)
component_parts.Cut()
return ..()
/obj/machinery/proc/spawn_frame(disassembled)
var/obj/structure/frame/machine/M = new /obj/structure/frame/machine(loc)
. = M
M.setAnchored(anchored)
var/obj/structure/frame/machine/new_frame = new /obj/structure/frame/machine(loc)
new_frame.state = 2
// If the new frame shouldn't be able to fit here due to the turf being blocked, spawn the frame deconstructed.
if(isturf(loc))
var/turf/machine_turf = loc
// We're spawning a frame before this machine is qdeleted, so we want to ignore it. We've also just spawned a new frame, so ignore that too.
if(machine_turf.is_blocked_turf(TRUE, source_atom = new_frame, ignore_atoms = list(src)))
new_frame.deconstruct(disassembled)
return
new_frame.icon_state = "box_1"
. = new_frame
new_frame.setAnchored(anchored)
if(!disassembled)
M.obj_integrity = M.max_integrity * 0.5 //the frame is already half broken
transfer_fingerprints_to(M)
M.state = 2
M.icon_state = "box_1"
new_frame.obj_integrity = (new_frame.max_integrity * 0.5) //the frame is already half broken
transfer_fingerprints_to(new_frame)
/obj/machinery/obj_break(damage_flag)
if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1))
@@ -475,23 +486,28 @@ Class Procs:
return FAILED_UNFASTEN
return SUCCESSFUL_UNFASTEN
/obj/proc/default_unfasten_wrench(mob/user, obj/item/I, time = 20) //try to unwrench an object in a WONDERFUL DYNAMIC WAY
if(!(flags_1 & NODECONSTRUCT_1) && I.tool_behaviour == TOOL_WRENCH)
var/can_be_unfasten = can_be_unfasten_wrench(user)
if(!can_be_unfasten || can_be_unfasten == FAILED_UNFASTEN)
return can_be_unfasten
if(time)
to_chat(user, span_notice("You begin [anchored ? "un" : ""]securing [src]..."))
I.play_tool_sound(src, 50)
var/prev_anchored = anchored
//as long as we're the same anchored state and we're either on a floor or are anchored, toggle our anchored state
if(I.use_tool(src, user, time, extra_checks = CALLBACK(src, PROC_REF(unfasten_wrench_check), prev_anchored, user)))
to_chat(user, span_notice("You [anchored ? "un" : ""]secure [src]."))
setAnchored(!anchored)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
return SUCCESSFUL_UNFASTEN
return FAILED_UNFASTEN
return CANT_UNFASTEN
/obj/proc/default_unfasten_wrench(mob/user, obj/item/wrench, time = 20) //try to unwrench an object in a WONDERFUL DYNAMIC WAY
if((flags_1 & NODECONSTRUCT_1) || wrench.tool_behaviour != TOOL_WRENCH)
return CANT_UNFASTEN
var/turf/ground = get_turf(src)
if(!anchored && ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
to_chat(user, span_notice("You fail to secure [src]."))
return CANT_UNFASTEN
var/can_be_unfasten = can_be_unfasten_wrench(user)
if(!can_be_unfasten || can_be_unfasten == FAILED_UNFASTEN)
return can_be_unfasten
if(time)
to_chat(user, span_notice("You begin [anchored ? "un" : ""]securing [src]..."))
wrench.play_tool_sound(src, 50)
var/prev_anchored = anchored
//as long as we're the same anchored state and we're either on a floor or are anchored, toggle our anchored state
if(wrench.use_tool(src, user, time, extra_checks = CALLBACK(src, PROC_REF(unfasten_wrench_check), prev_anchored, user)))
to_chat(user, span_notice("You [anchored ? "un" : ""]secure [src]."))
setAnchored(!anchored)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
return SUCCESSFUL_UNFASTEN
return FAILED_UNFASTEN
/obj/proc/unfasten_wrench_check(prev_anchored, mob/user) //for the do_after, this checks if unfastening conditions are still valid
if(anchored != prev_anchored)
@@ -636,67 +652,3 @@ Class Procs:
/obj/machinery/rust_heretic_act()
take_damage(500, BRUTE, MELEE, 1)
/obj/machinery/MouseDrop_T(atom/movable/O, mob/user)
. = ..()
if(!climbable)
return
if(user == O && iscarbon(O))
var/mob/living/carbon/C = O
if(C.mobility_flags & MOBILITY_MOVE)
climb_machine(user)
return
if(!istype(O, /obj/item) || user.get_active_held_item() != O)
return
if(iscyborg(user))
return
if(!user.dropItemToGround(O))
return
if (O.loc != src.loc)
step(O, get_dir(O, src))
/obj/machinery/proc/do_climb(atom/movable/A)
if(climbable)
density = FALSE
. = step(A,get_dir(A,src.loc))
density = TRUE
/obj/machinery/proc/climb_machine(mob/living/user)
src.add_fingerprint(user)
user.visible_message("<span class='warning'>[user] starts climbing onto [src].</span>", \
"<span class='notice'>You start climbing onto [src]...</span>")
var/adjusted_climb_time = climb_time
if(user.restrained()) //climbing takes twice as long when restrained.
adjusted_climb_time *= 2
if(isalien(user))
adjusted_climb_time *= 0.25 //aliens are terrifyingly fast
if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am???
adjusted_climb_time *= 0.8
machineclimber = user
if(do_mob(user, user, adjusted_climb_time))
if(src.loc) //Checking if structure has been destroyed
if(do_climb(user))
user.visible_message("<span class='warning'>[user] climbs onto [src].</span>", \
"<span class='notice'>You climb onto [src].</span>")
log_combat(user, src, "climbed onto")
if(climb_stun)
var/mob/living/carbon/human/H = user
var/wagging = FALSE
if(H && H.dna.species.is_wagging_tail())
wagging = TRUE
user.Stun(climb_stun)
if(wagging)
H.dna.species.start_wagging_tail(H)
. = 1
else
to_chat(user, "<span class='warning'>You fail to climb onto [src].</span>")
machineclimber = null
/obj/machinery/CanAStarPass(ID, dir, caller)
. = ..()
if(climbable)
return TRUE
if(can_be_occupant(caller))
return TRUE

View File

@@ -123,10 +123,13 @@
proj_pass_rate = 20
pass_flags = LETPASSTHROW
bar_material = SAND
climbable = TRUE
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/closed/wall, /turf/closed/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/closed/wall/rust, /turf/closed/wall/r_wall/rust, /obj/structure/barricade/security)
/obj/structure/barricade/sandbags/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/barricade/security
name = "security barrier"
desc = "A deployable barrier. Provides good cover in fire fights."
@@ -187,20 +190,20 @@
new /obj/structure/barricade/security(get_turf(src.loc))
switch(mode)
if(VERTICAL)
var/target_turf = get_step(src, NORTH)
if(!(is_blocked_turf(target_turf)))
var/turf/target_turf = get_step(src, NORTH)
if(!(target_turf.is_blocked_turf()))
new /obj/structure/barricade/security(target_turf)
var/target_turf2 = get_step(src, SOUTH)
if(!(is_blocked_turf(target_turf2)))
var/turf/target_turf2 = get_step(src, SOUTH)
if(!(target_turf2.is_blocked_turf()))
new /obj/structure/barricade/security(target_turf2)
if(HORIZONTAL)
var/target_turf = get_step(src, EAST)
if(!(is_blocked_turf(target_turf)))
var/turf/target_turf = get_step(src, EAST)
if(!(target_turf.is_blocked_turf()))
new /obj/structure/barricade/security(target_turf)
var/target_turf2 = get_step(src, WEST)
if(!(is_blocked_turf(target_turf2)))
var/turf/target_turf2 = get_step(src, WEST)
if(!(target_turf2.is_blocked_turf()))
new /obj/structure/barricade/security(target_turf2)
qdel(src)

View File

@@ -14,7 +14,6 @@
idle_power_usage = 2
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = OPEN_DOOR_LAYER
climbable = TRUE
/obj/machinery/ministile/hop
name = "HOP line turnstile"
@@ -23,6 +22,7 @@
/obj/machinery/ministile/Initialize(mapload)
. = ..()
icon_state = "ministile"
AddElement(/datum/element/climbable)
/obj/machinery/ministile/CanAtmosPass(turf/T)
return TRUE

View File

@@ -14,7 +14,6 @@
idle_power_usage = 2
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = OPEN_DOOR_LAYER
climbable = FALSE
/obj/machinery/turnstile/brig
name = "Brig turnstile"

View File

@@ -529,13 +529,13 @@
if(T.density)
if(wall_turret_direction)
var/turf/closer = get_step(T,wall_turret_direction)
if(istype(closer) && !is_blocked_turf(closer) && T.Adjacent(closer))
if(istype(closer) && !closer.is_blocked_turf() && T.Adjacent(closer))
T = closer
else
var/target_dir = get_dir(T,target)
for(var/d in list(0,-45,45))
var/turf/closer = get_step(T,turn(target_dir,d))
if(istype(closer) && !is_blocked_turf(closer) && T.Adjacent(closer))
if(istype(closer) && !closer.is_blocked_turf() && T.Adjacent(closer))
T = closer
break

View File

@@ -47,7 +47,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark)
. = ..()
GLOB.start_landmarks_list += src
if(jobspawn_override)
LAZYADDASSOC(GLOB.jobspawn_overrides, name, src)
LAZYADDASSOCLIST(GLOB.jobspawn_overrides, name, src)
if(name != "start")
tag = "start*[name]"

View File

@@ -476,8 +476,8 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
if(DISPOSALS_CATEGORY) //Making disposals pipes
if(!can_make_pipe)
return ..()
A = get_turf(A)
if(is_blocked_turf(A))
var/turf/attempting_turf = get_turf(A)
if(attempting_turf.is_blocked_turf())
to_chat(user, span_warning("[src]'s error light flickers; there's something in the way!"))
return
to_chat(user, span_notice("You start building a disposals pipe..."))
@@ -501,8 +501,8 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
if(TRANSIT_CATEGORY) //Making transit tubes
if(!can_make_pipe)
return ..()
A = get_turf(A)
if(is_blocked_turf(A))
var/turf/attempting_turf = get_turf(A)
if(attempting_turf.is_blocked_turf())
to_chat(user, span_warning("[src]'s error light flickers; there's something in the way!"))
return
to_chat(user, span_notice("You start building a transit tube..."))
@@ -530,8 +530,8 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
if(PLUMBING_CATEGORY) //Making pancakes
if(!can_make_pipe)
return ..()
A = get_turf(A)
if(is_blocked_turf(A))
var/turf/attempting_turf = get_turf(A)
if(attempting_turf.is_blocked_turf())
to_chat(user, span_warning("[src]'s error light flickers; there's something in the way!"))
return
to_chat(user, span_notice("You start building a fluid duct..."))

View File

@@ -97,7 +97,7 @@
P.icon_state = "[P.icon_base]_[dir]"
P.tape_dir = dir
cur = get_step_towards(cur,end)
//is_blocked_turf(turf/T)
//T.is_blocked_turf()
to_chat(usr, span_notice("You finish placing the [src].")) //Git Test
/obj/item/barrier_taperoll/afterattack(atom/A, mob/user, proximity)

View File

@@ -31,7 +31,7 @@
to_chat(user, span_notice("You use [src] to deactivate [H]."))
qdel(H)
else
if(!is_blocked_turf(T, TRUE)) //can't put hard light on a tile that has dense stuff
if(!T.is_blocked_turf(TRUE)) //can't put hard light on a tile that has dense stuff
if(holocreator_busy)
to_chat(user, span_notice("[src] is busy creating a hard light barrier."))
return
@@ -45,7 +45,7 @@
holocreator_busy = FALSE
if(signs.len >= max_signs)
return
if(is_blocked_turf(T, TRUE)) //don't try to sneak dense stuff on our tile during the wait.
if(T.is_blocked_turf(TRUE)) //don't try to sneak dense stuff on our tile during the wait.
return
H = new holosign_type(get_turf(target), src)
to_chat(user, span_notice("You create \a [H] with [src]."))

View File

@@ -3,13 +3,10 @@
pressure_resistance = 8
max_integrity = 300
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
var/climb_time = 20
var/climb_stun = 20
var/climbable = FALSE
var/mob/living/structureclimber
var/broken = 0 //similar to machinery's stat BROKEN
layer = BELOW_OBJ_LAYER
var/broken = 0 //similar to machinery's stat BROKEN
/obj/structure/Initialize(mapload)
if (!armor)
@@ -32,75 +29,10 @@
if(istype(mover) && (mover.pass_flags & PASSSTRUCTURE))
return TRUE
/obj/structure/attack_hand(mob/user)
. = ..()
if(.)
return
if(structureclimber && structureclimber != user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
structureclimber.Paralyze(40)
structureclimber.visible_message(span_warning("[structureclimber] has been knocked off [src]."), span_warning("You're knocked off [src]!"), span_warning("You see [structureclimber] get knocked off [src]."))
/obj/structure/ui_act(action, params)
add_fingerprint(usr)
return ..()
/obj/structure/MouseDrop_T(atom/movable/O, mob/user)
. = ..()
if(!climbable)
return
if(user == O && iscarbon(O))
var/mob/living/carbon/C = O
if(C.mobility_flags & MOBILITY_MOVE)
climb_structure(user)
return
if(!istype(O, /obj/item) || user.get_active_held_item() != O)
return
if(iscyborg(user))
return
if(!user.dropItemToGround(O))
return
if (O.loc != src.loc)
step(O, get_dir(O, src))
/obj/structure/proc/do_climb(atom/movable/A)
if(climbable)
density = FALSE
. = step(A,get_dir(A,src.loc))
density = TRUE
/obj/structure/proc/climb_structure(mob/living/user)
src.add_fingerprint(user)
user.visible_message(span_warning("[user] starts climbing onto [src]."), \
span_notice("You start climbing onto [src]..."))
var/adjusted_climb_time = climb_time
if(HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //climbing takes twice as long without help from the hands.
adjusted_climb_time *= 2
if(isalien(user))
adjusted_climb_time *= 0.25 //aliens are terrifyingly fast
if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am???
adjusted_climb_time *= 0.8
structureclimber = user
if(do_mob(user, user, adjusted_climb_time))
if(src.loc) //Checking if structure has been destroyed
if(do_climb(user))
user.visible_message(span_warning("[user] climbs onto [src]."), \
span_notice("You climb onto [src]."))
log_combat(user, src, "climbed onto")
if(climb_stun)
var/mob/living/carbon/human/H = user
var/wagging = FALSE
if(H && H.dna.species.is_wagging_tail())
wagging = TRUE
user.Stun(climb_stun)
if(wagging)
H.dna.species.start_wagging_tail(H)
. = 1
else
to_chat(user, span_warning("You fail to climb onto [src]."))
structureclimber = null
/obj/structure/examine(mob/user)
. = ..()
if(!(resistance_flags & INDESTRUCTIBLE))

View File

@@ -209,7 +209,6 @@ GLOBAL_LIST_EMPTY(lockers)
opened = TRUE
if(!dense_when_open)
density = FALSE
climb_time *= 0.5 //it's faster to climb onto an open thing
dump_contents()
animate_door(FALSE)
update_appearance(UPDATE_ICON)
@@ -262,7 +261,6 @@ GLOBAL_LIST_EMPTY(lockers)
return FALSE
take_contents()
playsound(loc, close_sound, 15, 1, -3)
climb_time = initial(climb_time)
opened = FALSE
density = TRUE
animate_door(TRUE)

View File

@@ -7,13 +7,11 @@
can_weld_shut = FALSE
open_flags = HORIZONTAL_HOLD | HORIZONTAL_LID | ALLOW_OBJECTS | ALLOW_DENSE
dense_when_open = TRUE
climbable = TRUE
climb_time = 10 //real fast, because let's be honest stepping into or onto a crate is easy
climb_stun = 0 //climbing onto crates isn't hard, guys
delivery_icon = "deliverycrate"
door_anim_time = 0 // no animation
var/obj/item/paper/fluff/jobs/cargo/manifest/manifest
breakout_time = 20 SECONDS
var/crate_climb_time = 20
var/obj/item/paper/fluff/jobs/cargo/manifest/manifest
///The resident (owner) of this crate/coffin.
var/mob/living/resident
///The time it takes to pry this open with a crowbar.
@@ -21,6 +19,7 @@
/obj/structure/closet/crate/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable, climb_time = crate_climb_time, climb_stun = 0) //add element in closed state before parent init opens it(if it does)
if(icon_state == "[initial(icon_state)]open")
opened = TRUE
update_appearance(UPDATE_ICON)
@@ -53,6 +52,8 @@
/obj/structure/closet/crate/open(mob/living/user)
. = ..()
RemoveElement(/datum/element/climbable, climb_time = crate_climb_time, climb_stun = 0)
AddElement(/datum/element/climbable, climb_time = crate_climb_time * 0.5, climb_stun = 0)
if(. && manifest)
to_chat(user, span_notice("The manifest is torn off [src]."))
playsound(src, 'sound/items/poster_ripped.ogg', 75, 1)
@@ -60,6 +61,11 @@
manifest = null
update_appearance(UPDATE_ICON)
/obj/structure/closet/crate/close(mob/living/user)
. = ..()
RemoveElement(/datum/element/climbable, climb_time = crate_climb_time * 0.5, climb_stun = 0)
AddElement(/datum/element/climbable, climb_time = crate_climb_time, climb_stun = 0)
/obj/structure/closet/crate/proc/tear_manifest(mob/user)
to_chat(user, span_notice("You tear the manifest off of [src]."))
playsound(src, 'sound/items/poster_ripped.ogg', 75, 1)

View File

@@ -3,7 +3,6 @@
#define CUT_TIME 100
#define CLIMB_TIME 150
#define NO_HOLE 0 //section is intact
#define MEDIUM_HOLE 1 //medium hole in the section - can climb through
@@ -79,11 +78,11 @@
if(MEDIUM_HOLE)
visible_message(span_notice("\The [user] cuts into \the [src] some more."))
to_chat(user, span_info("You could probably fit yourself through that hole now. Although climbing through would be much faster if you made it even bigger."))
climbable = TRUE
AddElement(/datum/element/climbable)
if(LARGE_HOLE)
visible_message(span_notice("\The [user] completely cuts through \the [src]."))
to_chat(user, span_info("The hole in \the [src] is now big enough to walk through."))
climbable = FALSE
RemoveElement(/datum/element/climbable)
update_cut_status()
@@ -152,7 +151,6 @@
return TRUE
#undef CUT_TIME
#undef CLIMB_TIME
#undef NO_HOLE
#undef MEDIUM_HOLE

View File

@@ -5,21 +5,24 @@
icon_state = "railing"
density = TRUE
anchored = TRUE
climbable = TRUE
pixel_y = -16
climb_time = 10 // not that hard to jump a rail
climb_stun = 0 // if you dont fall
///Boolean on whether the railing should be cimable.
var/climbable = TRUE
///Initial direction of the railing.
var/ini_dir
/obj/structure/railing/corner //aesthetic corner sharp edges hurt oof ouch
icon_state = "railing_corner"
density = FALSE
climbable = FALSE
/obj/structure/railing/Initialize(mapload)
. = ..()
ini_dir = dir
if(climbable)
AddElement(/datum/element/climbable)
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS ,null,CALLBACK(src, PROC_REF(can_be_rotated)),CALLBACK(src, PROC_REF(after_rotation)))
/obj/structure/railing/attackby(obj/item/I, mob/living/user, params)

View File

@@ -20,7 +20,6 @@
density = TRUE
anchored = TRUE
layer = TABLE_LAYER
climbable = TRUE
pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.")
var/frame = /obj/structure/table_frame
var/framestack = /obj/item/stack/rods
@@ -36,6 +35,7 @@
/obj/structure/table/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
AddComponent(/datum/component/surgery_bed, \
success_chance = 0.8, \
)

View File

@@ -7,7 +7,6 @@
density = TRUE
layer = LOW_ITEM_LAYER
anchored = TRUE
climbable = 1
var/tube_construction = /obj/structure/c_transit_tube
var/list/tube_dirs //list of directions this tube section can connect to.
var/exit_delay = 1
@@ -15,6 +14,10 @@
var/const/time_to_unwrench = 2 SECONDS
max_integrity = 75
/obj/structure/transit_tube/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/transit_tube/CanAllowThrough(atom/movable/mover, turf/target)
. = ..()
if(istype(mover) && (mover.pass_flags & PASSGLASS))

View File

@@ -380,6 +380,57 @@ GLOBAL_LIST_EMPTY(station_turfs)
return TRUE
/**
* Check whether the specified turf is blocked by something dense inside it with respect to a specific atom.
*
* Returns truthy value TURF_BLOCKED_TURF_DENSE if the turf is blocked because the turf itself is dense.
* Returns truthy value TURF_BLOCKED_CONTENT_DENSE if one of the turf's contents is dense and would block
* a source atom's movement.
* Returns falsey value TURF_NOT_BLOCKED if the turf is not blocked.
*
* Arguments:
* * exclude_mobs - If TRUE, ignores dense mobs on the turf.
* * source_atom - If this is not null, will check whether any contents on the turf can block this atom specifically. Also ignores itself on the turf.
* * ignore_atoms - Check will ignore any atoms in this list. Useful to prevent an atom from blocking itself on the turf.
* * type_list - are we checking for types of atoms to ignore and not physical atoms
*/
/turf/proc/is_blocked_turf(exclude_mobs = FALSE, source_atom = null, list/ignore_atoms, type_list = FALSE)
if(density)
return TRUE
for(var/atom/movable/movable_content as anything in contents)
// We don't want to block ourselves
if((movable_content == source_atom))
continue
// dont consider ignored atoms or their types
if(length(ignore_atoms))
if(!type_list && (movable_content in ignore_atoms))
continue
else if(type_list && is_type_in_list(movable_content, ignore_atoms))
continue
// If the thing is dense AND we're including mobs or the thing isn't a mob AND if there's a source atom and
// it cannot pass through the thing on the turf, we consider the turf blocked.
if(movable_content.density && (!exclude_mobs || !ismob(movable_content)))
if(source_atom && movable_content.CanPass(source_atom, get_dir(src, source_atom)))
continue
return TRUE
return FALSE
/**
* Checks whether the specified turf is blocked by something dense inside it, but ignores anything with the climbable trait
*
* Works similar to is_blocked_turf(), but ignores climbables and has less options. Primarily added for jaunting checks
*/
/turf/proc/is_blocked_turf_ignore_climbable()
if(density)
return TRUE
for(var/atom/movable/atom_content as anything in contents)
if(atom_content.density && !(atom_content.flags_1 & ON_BORDER_1) && !HAS_TRAIT(atom_content, TRAIT_CLIMBABLE))
return TRUE
return FALSE
//////////////////////////////
//Distance procs
//////////////////////////////

View File

@@ -97,7 +97,6 @@
icon_state = "bloodaltar"
density = TRUE
anchored = FALSE
climbable = TRUE
pass_flags = LETPASSTHROW
can_buckle = FALSE
var/sacrifices = 0
@@ -116,6 +115,10 @@
They normally sacrifice hearts or blood in exchange for these ranks, forcing them to move out of their lair.\n\
It can only be used twice per night and it needs to be interacted it to be claimed, making bloodsuckers come back twice a night."
/obj/structure/bloodsucker/bloodaltar/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/bloodsucker/bloodaltar/bolt()
. = ..()
anchored = TRUE

View File

@@ -55,7 +55,7 @@
if(locate(/obj/structure/falsewall) in contents)
to_chat(user, span_warning("There is a false wall in the way, preventing you from fabricating a clockwork wall on [src]."))
return
if(is_blocked_turf(src, TRUE))
if(is_blocked_turf(TRUE))
to_chat(user, span_warning("Something is in the way, preventing you from fabricating a clockwork wall on [src]."))
return TRUE
var/operation_time = 100

View File

@@ -113,7 +113,7 @@
var/turf/T = get_turf(src)
var/list/open_turfs = list()
for(var/turf/open/OT in orange(1, T))
if(!is_blocked_turf(OT, TRUE))
if(!OT.is_blocked_turf(TRUE))
open_turfs |= OT
if(open_turfs.len)
for(var/mob/living/L in T)

View File

@@ -3,7 +3,6 @@
name = "massive gear"
icon_state = "wall_gear"
unanchored_icon = "wall_gear"
climbable = TRUE
max_integrity = 100
construction_value = 3
desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
@@ -12,6 +11,10 @@
/obj/item/clockwork/alloy_shards/medium = 4, \
/obj/item/clockwork/alloy_shards/small = 2) //slightly more debris than the default, totals 26 alloy
/obj/structure/destructible/clockwork/wall_gear/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/destructible/clockwork/wall_gear/displaced
anchored = FALSE

View File

@@ -525,7 +525,7 @@
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
return
var/turf/dest = get_turf(actual_selected_rune)
if(is_blocked_turf(dest, TRUE))
if(dest.is_blocked_turf(TRUE))
to_chat(user, span_warning("The target rune is blocked. You cannot teleport there."))
return
uses--

View File

@@ -162,7 +162,7 @@
chant(i)
var/list/destinations = list()
for(var/turf/T in orange(1, owner))
if(!is_blocked_turf(T, TRUE))
if(!T.is_blocked_turf(TRUE))
destinations += T
if(!LAZYLEN(destinations))
to_chat(owner, span_warning("You need more space to summon your cult!"))

View File

@@ -426,7 +426,7 @@ structure_check() searches for nearby cultist structures required for the invoca
return
var/turf/target = get_turf(actual_selected_rune)
if(is_blocked_turf(target, TRUE))
if(target.is_blocked_turf(TRUE))
to_chat(user, span_warning("The target rune is blocked. Attempting to teleport to it would be massively unwise."))
fail_invoke()
return

View File

@@ -191,7 +191,7 @@
for (var/turf/possible_drop in contract.dropoff.contents)
if (!isspaceturf(possible_drop) && !isclosedturf(possible_drop))
if (!is_blocked_turf(possible_drop))
if (!possible_drop.is_blocked_turf())
possible_drop_loc.Add(possible_drop)
if (possible_drop_loc.len > 0)

View File

@@ -180,7 +180,7 @@
WARNING("[src] couldnt find a Quartermaster/Storage (aka cargobay) area on the station, and as such it has set the supplypod landingzone to the area it resides in.")
landingzone = get_area(src)
for(var/turf/open/floor/T in landingzone.get_contained_turfs())//uses default landing zone
if(is_blocked_turf(T))
if(T.is_blocked_turf())
continue
LAZYADD(empty_turfs, T)
CHECK_TICK
@@ -197,7 +197,7 @@
if(SO.pack.get_cost() * (0.72*MAX_EMAG_ROCKETS) <= points_to_check) // bulk discount :^)
landingzone = GLOB.areas_by_type[pick(GLOB.the_station_areas)] //override default landing zone
for(var/turf/open/floor/T in landingzone.get_contained_turfs())
if(is_blocked_turf(T))
if(T.is_blocked_turf())
continue
LAZYADD(empty_turfs, T)
CHECK_TICK

View File

@@ -108,7 +108,7 @@
for(var/place in shuttle_areas)
var/area/shuttle/shuttle_area = place
for(var/turf/open/floor/T in shuttle_area)
if(is_blocked_turf(T))
if(T.is_blocked_turf())
continue
empty_shuttle_turfs += T
if(!empty_shuttle_turfs.len)

View File

@@ -263,7 +263,7 @@ datum/action/innate/aux_base/install_turret/Activate()
var/turf/turret_turf = get_turf(remote_eye)
if(is_blocked_turf(turret_turf))
if(turret_turf.is_blocked_turf())
to_chat(owner, span_warning("Location is obstructed by something. Please clear the location and try again."))
return

View File

@@ -1560,7 +1560,8 @@ GLOBAL_LIST_EMPTY(aide_list)
if(get_dist(user, beacon) <= 2) //beacon too close abort
to_chat(user, span_warning("You are too close to the beacon to teleport to it!"))
return
if(is_blocked_turf(get_turf(beacon), TRUE))
var/turf/beacon_turf = get_turf(beacon)
if(beacon_turf.is_blocked_turf(TRUE))
to_chat(user, span_warning("The beacon is blocked by something, preventing teleportation!"))
return
if(!isturf(user.loc))
@@ -1577,7 +1578,7 @@ GLOBAL_LIST_EMPTY(aide_list)
if(do_after(user, 4 SECONDS, user) && user && beacon)
var/turf/T = get_turf(beacon)
var/turf/source = get_turf(user)
if(is_blocked_turf(T, TRUE))
if(T.is_blocked_turf(TRUE))
teleporting = FALSE
to_chat(user, span_warning("The beacon is blocked by something, preventing teleportation!"))
user.update_mob_action_buttons()
@@ -1598,7 +1599,7 @@ GLOBAL_LIST_EMPTY(aide_list)
if(beacon)
beacon.icon_state = "hierophant_tele_off"
return
if(is_blocked_turf(T, TRUE))
if(T.is_blocked_turf(TRUE))
teleporting = FALSE
to_chat(user, span_warning("The beacon is blocked by something, preventing teleportation!"))
user.update_mob_action_buttons()
@@ -1633,7 +1634,7 @@ GLOBAL_LIST_EMPTY(aide_list)
/obj/item/hierophant_club/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user)
var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster
if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to, TRUE))
if(!turf_to_teleport_to || turf_to_teleport_to.is_blocked_turf_ignore_climbable())
return
animate(M, alpha = 0, time = 0.2 SECONDS, easing = EASE_OUT) //fade out
sleep(0.1 SECONDS)

View File

@@ -6,7 +6,6 @@
density = TRUE
anchored = TRUE
layer = TABLE_LAYER
climbable = TRUE
pass_flags = LETPASSTHROW
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
@@ -22,6 +21,7 @@
/obj/structure/world_anvil/Initialize(mapload)
. = ..()
internal = new /obj/item/gps/internal/world_anvil(src)
AddElement(/datum/element/climbable)
/obj/structure/world_anvil/Destroy()
QDEL_NULL(internal)

View File

@@ -1028,7 +1028,7 @@
if(T)
T.add_vomit_floor(src, vomit_type, purge_ratio) //toxic barf looks different || call purge when doing detoxicfication to pump more chems out of the stomach.
T = get_step(T, dir)
if (is_blocked_turf(T))
if (T.is_blocked_turf())
break
return TRUE

View File

@@ -208,7 +208,7 @@ Difficulty: Medium
if(get_dist(src, O) >= MINER_DASH_RANGE && turf_dist_to_target <= self_dist_to_target && !islava(O) && !ischasm(O))
var/valid = TRUE
for(var/turf/T in getline(own_turf, O))
if(is_blocked_turf(T, TRUE))
if(T.is_blocked_turf(TRUE))
valid = FALSE
continue
if(valid)

View File

@@ -541,7 +541,7 @@ Difficulty: Very Hard
var/turf/T = Stuff
if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors)
var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR)
if(prob(florachance) && NewFlora.len && !is_blocked_turf(O, TRUE))
if(prob(florachance) && NewFlora.len && !O.is_blocked_turf(TRUE))
var/atom/Picked = pick(NewFlora)
new Picked(O)
continue

View File

@@ -48,7 +48,7 @@
var/mob/living/L = parent
if(!L.can_interact_with(clicked_turf))
return
if(is_blocked_turf(clicked_turf))
if(clicked_turf.is_blocked_turf())
return
if(istype(clicked_turf, /turf/open/indestructible/sound/pool))
return

View File

@@ -124,7 +124,7 @@
if(get_dist(A,B) != required_distance)
return FALSE
for(var/turf/T in getline(get_turf(A),get_turf(B)))
if(is_blocked_turf(T,TRUE))
if(T.is_blocked_turf(TRUE))
return FALSE
return TRUE

View File

@@ -6,7 +6,6 @@
density = TRUE
anchored = TRUE
layer = TABLE_LAYER
climbable = TRUE
pass_flags = LETPASSTHROW
can_buckle = TRUE
buckle_lying = 90 //we turn to you!
@@ -16,6 +15,7 @@
/obj/structure/altar_of_gods/Initialize(mapload)
. = ..()
reflect_sect_in_icons()
AddElement(/datum/element/climbable)
AddComponent(/datum/component/religious_tool, ALL, FALSE, CALLBACK(src, PROC_REF(reflect_sect_in_icons)))
/obj/structure/altar_of_gods/attack_hand(mob/living/user)

View File

@@ -367,7 +367,7 @@ GLOBAL_LIST_EMPTY(bluespace_slime_crystals)
/obj/structure/slime_crystal/cerulean/process()
for(var/turf/T in range(2,src))
if(is_blocked_turf(T) || isspaceturf(T) || T == get_turf(src) || prob(50))
if(T.is_blocked_turf() || isspaceturf(T) || T == get_turf(src) || prob(50))
continue
var/obj/structure/cerulean_slime_crystal/CSC = locate() in range(1,T)
if(CSC)

View File

@@ -91,7 +91,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
for(var/place in shuttle_areas)
var/area/shuttle/shuttle_area = place
for(var/turf/open/floor/T in shuttle_area)
if(is_blocked_turf(T))
if(T.is_blocked_turf())
continue
empty_turfs += T
@@ -227,7 +227,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
for(var/place as anything in shuttle_areas)
var/area/shuttle/shuttle_area = place
for(var/turf/open/floor/shuttle_floor in shuttle_area)
if(is_blocked_turf(shuttle_floor))
if(shuttle_floor.is_blocked_turf())
continue
empty_turfs += shuttle_floor

View File

@@ -112,8 +112,8 @@
// Pick an exit turf to deposit the jaunter
var/turf/found_exit
for(var/turf/possible_exit as anything in exit_point_list)
// if(possible_exit.is_blocked_turf_ignore_climbable())
// continue
if(possible_exit.is_blocked_turf_ignore_climbable())
continue
found_exit = possible_exit
break
@@ -190,8 +190,8 @@
SIGNAL_HANDLER
var/turf/location = get_turf(source)
// if(location.is_blocked_turf_ignore_climbable())
// return
if(location.is_blocked_turf_ignore_climbable())
return
exit_point_list.Insert(1, location)
if(length(exit_point_list) >= 5)
exit_point_list.Cut(5)

View File

@@ -36,8 +36,8 @@
return FALSE
if(selected.density && (destination_flags & TELEPORT_SPELL_SKIP_DENSE))
return FALSE
// if(selected.is_blocked_turf(exclude_mobs = TRUE) && (destination_flags & TELEPORT_SPELL_SKIP_BLOCKED))
// return FALSE
if(selected.is_blocked_turf(exclude_mobs = TRUE) && (destination_flags & TELEPORT_SPELL_SKIP_BLOCKED))
return FALSE
return TRUE

View File

@@ -47,6 +47,7 @@
#include "code\__DEFINES\contracts.dm"
#include "code\__DEFINES\cooldowns.dm"
#include "code\__DEFINES\cult.dm"
#include "code\__DEFINES\directional.dm"
#include "code\__DEFINES\diseases.dm"
#include "code\__DEFINES\DNA.dm"
#include "code\__DEFINES\dye_keys.dm"
@@ -644,6 +645,7 @@
#include "code\datums\diseases\advance\symptoms\youth.dm"
#include "code\datums\elements\_element.dm"
#include "code\datums\elements\cleaning.dm"
#include "code\datums\elements\climbable.dm"
#include "code\datums\elements\connect_loc.dm"
#include "code\datums\elements\content_barfer.dm"
#include "code\datums\elements\earhealing.dm"

View File

@@ -31,9 +31,11 @@
playsound(src, 'sound/items/jaws_pry.ogg', 100)
/obj/machinery/door/airlock/proc/dir_to_cardinal(dir)
if((dir & NORTH) && (!is_blocked_turf(get_step(src, NORTH), TRUE)))
var/turf/north_turf = get_step(src, NORTH)
if((dir & NORTH) && (!north_turf.is_blocked_turf(TRUE)))
return NORTH
if((dir & SOUTH) && (!is_blocked_turf(get_step(src, SOUTH), TRUE)))
var/turf/south_turf = get_step(src, SOUTH)
if((dir & SOUTH) && (!south_turf.is_blocked_turf(TRUE)))
return SOUTH
if(dir & EAST)
return EAST
@@ -43,4 +45,4 @@
/obj/machinery/door/airlock/Moved()
if(brace)
brace.remove()
return ..()
return ..()