Movement cross/uncross implementation. (#26762)

* refactor: Movement cross/uncross implementation.

* wrong var name

* fix unit tests dropping PDAs into nowhere

* Add documentation.

* remove unused constants

* say which procs are off limits

* fix simpleanimal z change runtime

* helps not to leave merge conflicts

* kill me

* fix typecast

* fix projectile/table collision

* treadmills don't cause MC to crash anymore

* connect_loc is appropriate here

* fix windoors and teleporters

* fix bonfires and clarify docs

* fix proximity sensors

Tested with sensors in crates, sensors in modsuits
Tested new proximity component with firing projectiles at singularity
Tested new proximity component with portable flashes
Tested new proximity component with facehuggers

* lint

* fix: polarized access helper false positives

* Revert "fix: polarized access helper false positives"

This reverts commit 9814f98cf6.

* hopefully the right change for mindflayer steam

* Changes following cameras

* fix glass table collision

* appears to fix doorspam

* fix ore bags not picking up ore

* fix signatures of /Exited

* remove debug log

* remove duplicate signal registrar

* fix emptying bags into locations

* I don't trust these nested Move calls

* use connect_loc for upgraded resonator fields

* use moveToNullspace

* fix spiderweb crossing

* fix pass checking for windows from a tile off

* fix bluespace closet/transparency issues

* fix mechs not interacting with doors and probably other things

* fix debug

* fix telepete

* add some docs

* stop trying to shoehorn prox monitor into cards

* I should make sure things build

* kill override signal warning

* undef signal

* not many prox monitors survive going off like this

* small fixes to storage

* make moving wormholes respect signals

* use correct signals for pulse demon

* fix pulse heart too

* fix smoke signals

* may have fucked singulo projectile swerve

* fix singulo projectile arcing

* remove duplicate define

* just look at it

* hopefully last cleanups of incorrect signal usage

* fix squeaking

* may god have mercy on my soul

* Apply suggestions from code review

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: warriorstar-orion <orion@snowfrost.garden>

* lewc review

* Apply suggestions from code review

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Signed-off-by: warriorstar-orion <orion@snowfrost.garden>

* burza review

* fix bad args for grenade assemblies

* Update code/__DEFINES/is_helpers.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: warriorstar-orion <orion@snowfrost.garden>

---------

Signed-off-by: warriorstar-orion <orion@snowfrost.garden>
Co-authored-by: DGamerL <daan.lyklema@gmail.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
warriorstar-orion
2024-12-21 08:07:44 +00:00
committed by GitHub
co-authored by Luc Burzah DGamerL
parent 3a3bdc8ff1
commit 79bad427c8
175 changed files with 2491 additions and 1322 deletions
+4 -4
View File
@@ -468,6 +468,7 @@
*In the BURST/BURSTING state, the alien egg can be removed by being attacked by a alien or any other weapon
**/
var/status = GROWING
var/datum/proximity_monitor/proximity_monitor
/obj/structure/alien/egg/grown
status = GROWN
@@ -485,7 +486,7 @@
else if(status != GROWN)
addtimer(CALLBACK(src, PROC_REF(grow)), rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME))
if(status == GROWN)
AddComponent(/datum/component/proximity_monitor)
proximity_monitor = new(src)
/obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user)
return attack_hand(user)
@@ -516,7 +517,7 @@
/obj/structure/alien/egg/proc/grow()
icon_state = "egg"
status = GROWN
AddComponent(/datum/component/proximity_monitor)
proximity_monitor = new(src)
///Need to carry the kill from Burst() to Hatch(), this section handles the alien opening the egg
/obj/structure/alien/egg/proc/burst(kill)
@@ -524,8 +525,7 @@
icon_state = "egg_hatched"
flick("egg_opening", src)
status = BURSTING
DeleteComponent(/datum/component/proximity_monitor)
QDEL_NULL(proximity_monitor)
addtimer(CALLBACK(src, PROC_REF(hatch)), 1.5 SECONDS)
///We now check HOW the hugger is hatching, kill carried from Burst() and obj_break()
+1 -1
View File
@@ -29,7 +29,7 @@
return
return ..()
/obj/structure/coatrack/CanPass(atom/movable/mover, turf/target)
/obj/structure/coatrack/CanPass(atom/movable/mover, border_dir)
var/can_hang = FALSE
for(var/T in allowed)
if(istype(mover,T))
@@ -167,7 +167,7 @@
QDEL_NULL(door_obj)
return ..()
/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
/obj/structure/closet/CanPass(atom/movable/mover, border_dir)
if(wall_mounted)
return TRUE
return (!density)
@@ -516,14 +516,23 @@
storage_capacity = 60
var/materials = list(MAT_METAL = 5000, MAT_PLASMA = 2500, MAT_TITANIUM = 500, MAT_BLUESPACE = 500)
/obj/structure/closet/bluespace/CheckExit(atom/movable/AM)
UpdateTransparency(AM, loc)
return TRUE
/obj/structure/closet/bluespace/Initialize(mapload)
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(UpdateTransparency),
COMSIG_ATOM_EXITED = PROC_REF(UpdateTransparency),
)
/obj/structure/closet/bluespace/proc/UpdateTransparency(atom/movable/AM, atom/location)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/structure/closet/bluespace/proc/UpdateTransparency()
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED + COMSIG_ATOM_EXITED
transparent = FALSE
for(var/atom/A in location)
if(A.density && A != src && A != AM)
if(!get_turf(loc))
return
for(var/atom/A in loc)
if(A.density && A != src)
transparent = TRUE
alpha = 180
update_icon()
@@ -531,10 +540,6 @@
alpha = 255
update_icon()
/obj/structure/closet/bluespace/Crossed(atom/movable/AM, oldloc)
if(AM.density)
UpdateTransparency(location = loc)
/obj/structure/closet/bluespace/Move(NewLoc, direct) // Allows for "phasing" throug objects but doesn't allow you to stuff your EOC homebois in one of these and push them through walls.
var/turf/T = get_turf(NewLoc)
if(T.density)
@@ -542,8 +547,10 @@
for(var/atom/A in T.contents)
if(A.density && isairlock(A))
return
UpdateTransparency(src, NewLoc)
forceMove(NewLoc)
. = ..()
UpdateTransparency()
/obj/structure/closet/bluespace/close()
. = ..()
+1 -1
View File
@@ -58,7 +58,7 @@
icon_state = "straight_cut3"
hole_size = LARGE_HOLE
/obj/structure/fence/CanPass(atom/movable/mover, turf/target)
/obj/structure/fence/CanPass(atom/movable/mover, border_dir)
if(istype(mover) && mover.checkpass(PASSFENCE))
return TRUE
if(isprojectile(mover))
+1 -1
View File
@@ -406,7 +406,7 @@
refundMetal(metalUsed)
qdel(src)
/obj/structure/girder/CanPass(atom/movable/mover, turf/target)
/obj/structure/girder/CanPass(atom/movable/mover, border_dir)
if(istype(mover) && mover.checkpass(PASSGIRDER))
return TRUE
if(istype(mover) && mover.checkpass(PASSGRILLE))
+1 -1
View File
@@ -90,7 +90,7 @@
if(!shock(user, 70))
take_damage(20, BRUTE, MELEE, 1)
/obj/structure/grille/CanPass(atom/movable/mover, turf/target)
/obj/structure/grille/CanPass(atom/movable/mover, border_dir)
. = !density
if(istype(mover) && mover.checkpass(PASSGRILLE))
return TRUE
+1 -1
View File
@@ -57,7 +57,7 @@
max_integrity = 20
var/allow_walk = TRUE //can we pass through it on walk intent
/obj/structure/holosign/barrier/CanPass(atom/movable/mover, turf/target)
/obj/structure/holosign/barrier/CanPass(atom/movable/mover, border_dir)
if(!density)
return TRUE
if(mover.pass_flags & (PASSGLASS|PASSTABLE|PASSGRILLE))
+2 -2
View File
@@ -42,7 +42,7 @@
. = ..()
T.recalculate_atmos_connectivity()
/obj/structure/inflatable/CanPass(atom/movable/mover, turf/target)
/obj/structure/inflatable/CanPass(atom/movable/mover, border_dir)
return
/obj/structure/inflatable/CanAtmosPass(direction)
@@ -116,7 +116,7 @@
/obj/structure/inflatable/door/attack_hand(mob/user as mob)
return try_to_operate(user)
/obj/structure/inflatable/door/CanPass(atom/movable/mover, turf/target)
/obj/structure/inflatable/door/CanPass(atom/movable/mover, border_dir)
if(istype(mover, /obj/effect/beam))
return !opacity
return !density
@@ -59,7 +59,7 @@
if(user.can_advanced_admin_interact())
operate()
/obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target)
/obj/structure/mineral_door/CanPass(atom/movable/mover, border_dir)
if(istype(mover, /obj/effect/beam))
return !opacity
return !density
+1 -1
View File
@@ -294,7 +294,7 @@
connected = null
return ..()
/obj/structure/m_tray/CanPass(atom/movable/mover, turf/target)
/obj/structure/m_tray/CanPass(atom/movable/mover, border_dir)
if(istype(mover))
if(mover.checkpass(PASSTABLE))
return TRUE
+11 -3
View File
@@ -25,6 +25,13 @@
var/spawn_mob_options = list(/mob/living/simple_animal/crab) // The nest picks one mob type of this list and spawns them
var/spawn_trigger_distance = 7 // The triggered nest will look this many tiles around itself to find other triggerable nests
/obj/structure/nest/Initialize(mapload)
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_atom_entered),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/structure/nest/examine(mob/user)
. = ..()
if(!spawn_is_triggered)
@@ -35,12 +42,13 @@
return
..()
/obj/structure/nest/Crossed(atom/movable/AM)
/obj/structure/nest/proc/on_atom_entered(datum/source, atom/movable/entered)
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED
if(spawn_is_triggered)
return
if(!isliving(AM))
if(!isliving(entered))
return
var/mob/living/L = AM
var/mob/living/L = entered
if(!L.mind)
return
+33 -26
View File
@@ -12,6 +12,14 @@
var/currently_climbed = FALSE
var/mover_dir = null
/obj/structure/railing/Initialize(mapload)
. = ..()
if(density && flags & ON_BORDER) // blocks normal movement from and to the direction it's facing.
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = PROC_REF(on_atom_exit),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/structure/railing/get_climb_text()
return "<span class='notice'>You can <b>Click-Drag</b> yourself to [src] to climb over it after a short delay.</span>"
@@ -87,8 +95,8 @@
/obj/structure/railing/corner/CanPathfindPass(to_dir, datum/can_pass_info/pass_info)
return TRUE
/obj/structure/railing/corner/CheckExit()
return TRUE
/obj/structure/railing/corner/on_atom_exit(datum/source, atom/movable/leaving, direction)
return
/obj/structure/railing/cap/CanPass()
return TRUE
@@ -96,10 +104,10 @@
/obj/structure/railing/cap/CanPathfindPass(to_dir, datum/can_pass_info/pass_info)
return TRUE
/obj/structure/railing/cap/CheckExit()
return TRUE
/obj/structure/railing/cap/on_atom_exit(datum/source, atom/movable/leaving, direction)
return
/obj/structure/railing/CanPass(atom/movable/mover, turf/target)
/obj/structure/railing/CanPass(atom/movable/mover, border_dir)
if(istype(mover) && mover.checkpass(PASSFENCE))
return TRUE
if(isprojectile(mover))
@@ -110,11 +118,10 @@
return TRUE
if(mover.throwing)
return TRUE
mover_dir = get_dir(loc, target)
//Due to how the other check is done, it would always return density for ordinal directions no matter what
if(ordinal_direction_check(mover_dir))
if(ordinal_direction_check(border_dir))
return FALSE
if(mover_dir != dir)
if(border_dir != dir)
return density
return FALSE
@@ -126,27 +133,27 @@
return TRUE
/obj/structure/railing/CheckExit(atom/movable/O, target)
var/mob/living/M = O
if(istype(O) && O.checkpass(PASSFENCE))
return TRUE
if(isprojectile(O))
return TRUE
/obj/structure/railing/proc/on_atom_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER // COMSIG_ATOM_EXIT
var/mob/living/M = leaving
if(istype(leaving) && leaving.checkpass(PASSFENCE))
return
if(isprojectile(leaving))
return
if(istype(M))
if(HAS_TRAIT(M, TRAIT_FLYING) || M.floating || (IS_HORIZONTAL(M) && HAS_TRAIT(M, TRAIT_CONTORTED_BODY)))
return TRUE
if(O.throwing)
return TRUE
if(O.move_force >= MOVE_FORCE_EXTREMELY_STRONG)
return TRUE
return
if(leaving.throwing)
return
if(leaving.move_force >= MOVE_FORCE_EXTREMELY_STRONG)
return
if(currently_climbed)
return TRUE
mover_dir = get_dir(O.loc, target)
if(mover_dir == dir)
return FALSE
if(ordinal_direction_check(mover_dir))
return FALSE
return TRUE
return
if(direction == dir)
return COMPONENT_ATOM_BLOCK_EXIT
if(ordinal_direction_check(direction))
return COMPONENT_ATOM_BLOCK_EXIT
// Checks if the direction the mob is trying to move towards would be blocked by a corner railing
/obj/structure/railing/proc/ordinal_direction_check(check_dir)
+33 -24
View File
@@ -47,6 +47,11 @@
/obj/structure/table/Initialize(mapload)
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = PROC_REF(on_atom_exit),
)
AddElement(/datum/element/connect_loc, loc_connections)
if(flipped)
update_icon()
@@ -126,9 +131,10 @@
/obj/structure/table/proc/item_placed(item)
return
/obj/structure/table/CanPass(atom/movable/mover, turf/target)
/obj/structure/table/CanPass(atom/movable/mover, border_dir)
if(istype(mover,/obj/item/projectile))
return (check_cover(mover,target))
return check_cover(mover, border_dir)
var/mob/living/living_mover = mover
if(istype(living_mover) && (HAS_TRAIT(living_mover, TRAIT_FLYING) || (IS_HORIZONTAL(living_mover) && HAS_TRAIT(living_mover, TRAIT_CONTORTED_BODY))))
return TRUE
@@ -141,7 +147,7 @@
if(!T.flipped)
return TRUE
if(flipped)
if(get_dir(loc, target) == dir)
if(border_dir == dir)
return !density
else
return TRUE
@@ -158,30 +164,28 @@
*
* Arguments:
* * P - The projectile trying to cross.
* * from - Where the projectile is located.
* * proj_dir - The incoming direction of the projectile.
*/
/obj/structure/table/proc/check_cover(obj/item/projectile/P, turf/from)
/obj/structure/table/proc/check_cover(obj/item/projectile/P, proj_dir)
. = TRUE
if(!flipped)
return
if(get_dist(P.starting, loc) <= 1) // Tables won't help you if people are THIS close
return
var/proj_dir = get_dir(from, loc)
var/block_dir = get_dir(get_step(loc, dir), loc)
if(proj_dir != block_dir) // Back/side shots may pass
if(proj_dir != dir) // Back/side shots may pass
return
if(prob(40))
return FALSE // Blocked
/obj/structure/table/CheckExit(atom/movable/O, turf/target)
if(istype(O) && O.checkpass(PASSTABLE))
return 1
/obj/structure/table/proc/on_atom_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER // COMSIG_ATOM_EXIT
if(istype(leaving) && leaving.checkpass(PASSTABLE))
return
if(flipped)
if(get_dir(loc, target) == dir)
return !density
else
return 1
return 1
if(direction == dir && density)
return COMPONENT_ATOM_BLOCK_EXIT
/obj/structure/table/MouseDrop_T(obj/O, mob/user)
if(..())
@@ -461,27 +465,32 @@
. = ..()
debris += new frame
debris += new shardtype
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/structure/table/glass/Destroy()
for(var/i in debris)
qdel(i)
. = ..()
/obj/structure/table/glass/Crossed(atom/movable/AM, oldloc)
. = ..()
/obj/structure/table/glass/proc/on_entered(datum/source, atom/movable/entered)
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED
if(flags & NODECONSTRUCT)
return
if(!isliving(AM))
if(!isliving(entered))
return
var/mob/living/L = AM
var/mob/living/L = entered
if(L.incorporeal_move || HAS_TRAIT(L, TRAIT_FLYING) || L.floating)
return
// Don't break if they're just flying past
if(AM.throwing)
addtimer(CALLBACK(src, PROC_REF(throw_check), AM), 5)
if(entered.throwing)
addtimer(CALLBACK(src, PROC_REF(throw_check), entered), 5)
else
check_break(AM)
check_break(entered)
/obj/structure/table/glass/proc/throw_check(mob/living/M)
if(M.loc == get_turf(src))
@@ -905,7 +914,7 @@
. = ..()
. += "<span class='notice'>It's held together by a couple of <b>bolts</b>.</span>"
/obj/structure/rack/CanPass(atom/movable/mover, turf/target)
/obj/structure/rack/CanPass(atom/movable/mover, border_dir)
if(!density) //Because broken racks -Agouri |TODO: SPRITE!|
return 1
if(istype(mover))
@@ -33,7 +33,7 @@
P.empty_pod()
return ..()
/obj/structure/transit_tube/CanPass(atom/movable/mover, turf/target)
/obj/structure/transit_tube/CanPass(atom/movable/mover, border_dir)
if(istype(mover) && mover.checkpass(PASSGLASS))
return TRUE
return !density
+10 -3
View File
@@ -307,6 +307,13 @@
pixel_y = -5
layer = FLY_LAYER
/obj/machinery/shower/Initialize(mapload)
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_atom_entered),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/machinery/shower/Destroy()
QDEL_NULL(soundloop)
var/obj/effect/mist/mist = locate() in loc
@@ -401,10 +408,10 @@
if(mist && (!on || current_temperature == SHOWER_FREEZING))
qdel(mist)
/obj/machinery/shower/Crossed(atom/movable/AM)
..()
/obj/machinery/shower/proc/on_atom_entered(datum/source, atom/movable/entered)
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED
if(on)
wash(AM)
wash(entered)
/obj/machinery/shower/proc/convertHeat()
switch(current_temperature)
@@ -55,6 +55,12 @@
if(set_dir)
dir = set_dir
ini_dir = dir
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = PROC_REF(on_atom_exit),
)
AddElement(/datum/element/connect_loc, loc_connections)
recalculate_atmos_connectivity()
/obj/structure/windoor_assembly/Destroy()
@@ -72,10 +78,10 @@
/obj/structure/windoor_assembly/update_icon_state()
icon_state = "[facing]_[secure ? "secure_" : ""]windoor_assembly[state]"
/obj/structure/windoor_assembly/CanPass(atom/movable/mover, turf/target)
/obj/structure/windoor_assembly/CanPass(atom/movable/mover, border_dir)
if(istype(mover) && mover.checkpass(PASSGLASS))
return 1
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
if(border_dir == dir) //Make sure looking at appropriate border
return !density
if(istype(mover, /obj/structure/window))
var/obj/structure/window/W = mover
@@ -95,13 +101,13 @@
else
return TRUE
/obj/structure/windoor_assembly/CheckExit(atom/movable/mover, turf/target)
if(istype(mover) && mover.checkpass(PASSGLASS))
return 1
if(get_dir(loc, target) == dir)
return !density
else
return 1
/obj/structure/windoor_assembly/proc/on_atom_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER // COMSIG_ATOM_EXIT
if(istype(leaving) && leaving.checkpass(PASSGLASS))
return
if(direction == dir && density)
return COMPONENT_ATOM_BLOCK_EXIT
/obj/structure/windoor_assembly/attackby__legacy__attackchain(obj/item/W, mob/user, params)
//I really should have spread this out across more states but thin little windoors are hard to sprite.
+22 -10
View File
@@ -79,6 +79,12 @@
real_explosion_block = explosion_block
explosion_block = EXPLOSION_BLOCK_PROC
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = PROC_REF(on_atom_exit),
)
AddElement(/datum/element/connect_loc, loc_connections)
recalculate_atmos_connectivity()
/obj/structure/window/proc/toggle_polarization()
@@ -109,12 +115,12 @@
else
..(FULLTILE_WINDOW_DIR)
/obj/structure/window/CanPass(atom/movable/mover, turf/target)
/obj/structure/window/CanPass(atom/movable/mover, border_dir)
if(istype(mover) && mover.checkpass(PASSGLASS))
return 1
if(dir == FULLTILE_WINDOW_DIR)
return 0 //full tile window, you can't move into it!
if(get_dir(loc, target) & dir)
if(border_dir & dir)
return !density
if(istype(mover, /obj/structure/window))
var/obj/structure/window/W = mover
@@ -128,14 +134,20 @@
return FALSE
return 1
/obj/structure/window/CheckExit(atom/movable/O, target)
if(istype(O) && O.checkpass(PASSGLASS))
return TRUE
/obj/structure/window/proc/on_atom_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER // COMSIG_ATOM_EXIT
if(istype(leaving) && leaving.checkpass(PASSGLASS))
return
if(leaving == src)
return
if(dir == FULLTILE_WINDOW_DIR)
return TRUE
if(get_dir(O.loc, target) & dir)
return FALSE
return TRUE
return
if(direction & dir)
leaving.Bump(src)
return COMPONENT_ATOM_BLOCK_EXIT
return
/obj/structure/window/CanPathfindPass(to_dir, datum/can_pass_info/pass_info)
if(!density)
@@ -339,7 +351,7 @@
if(!fulltile)
if(get_dir(user, src) & dir)
for(var/obj/O in loc)
if(!O.CanPass(user, user.loc, 1))
if(!O.CanPass(user, get_dir(src, user)))
return 0
return 1