diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index afc03f3391f..eb6f3e38082 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -169,23 +169,6 @@ Turf and target are seperate in case you want to teleport some distance from a t return destination -/////////////////// -//A* helpers procs -/////////////////// - -// Returns true if a link is blocked and neither location has something climbable on -// Used for inventory checks -/proc/LinkBlockedUnclimbable(turf/A, turf/B) - if (!A.LinkBlocked(A, B)) - return 0 - for (var/obj/structure/S in A.contents) - if(S.climbable) - return 0 - for (var/obj/structure/S in B.contents) - if(S.climbable) - return 0 - return 1 - // Returns true if direction is blocked from loc // Checks if doors are open /proc/DirBlocked(turf/loc,var/dir) diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index d66110a6d7f..e8b4b9c0d89 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -3,47 +3,25 @@ A Star pathfinding algorithm Returns a list of tiles forming a path from A to B, taking dense objects as well as walls, and the orientation of windows along the route into account. Use: -your_list = AStar(start location, end location, adjacent turf proc, distance proc) -For the adjacent turf proc i wrote: -/turf/proc/AdjacentTurfs -And for the distance one i wrote: -/turf/proc/Distance -So an example use might be: - -src.path_list = AStar(src.loc, target.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance) - -Then to start on the path, all you need to do it: -Step_to(src, src.path_list[1]) -src.path_list -= src.path_list[1] or equivilent to remove that node from the list. +your_list = AStar(start location, end location, moving atom, distance proc, max nodes, maximum node depth, minimum distance to target, adjacent proc, atom id, turfs to exclude, check only simulated) Optional extras to add on (in order): +Distance proc : the distance used in every A* calculation (length of path and heuristic) MaxNodes: The maximum number of nodes the returned path can be (0 = infinite) Maxnodedepth: The maximum number of nodes to search (default: 30, 0 = infinite) Mintargetdist: Minimum distance to the target before path returns, could be used to get near a target, but not right to it - for an AI mob with a gun, for example. -Minnodedist: Minimum number of nodes to return in the path, could be used to give a path a minimum -length to avoid portals or something i guess?? Not that they're counted right now but w/e. +Adjacent proc : returns the turfs to consider around the actually processed node +Simulated only : whether to consider unsimulated turfs or not (used by some Adjacent proc) +Also added 'exclude' turf to avoid travelling over; defaults to null - Modified to provide ID argument - supplied to 'adjacent' proc, defaults to null - Used for checking if route exists through a door which can be opened +Actual Adjacent procs : - Also added 'exclude' turf to avoid travelling over; defaults to null + /turf/proc/reachableAdjacentTurfs : returns reachable turfs in cardinal directions (uses simulated_only) - Currently, there's four main ways to call AStar + /turf/proc/reachableAdjacentAtmosTurfs : returns turfs in cardinal directions reachable via atmos - 1) adjacent = "/turf/proc/AdjacentTurfsWithAccess" and distance = "/turf/proc/Distance" - Seeks a path moving in all directions (including diagonal) and checking for the correct id to get through doors - - 2) adjacent = "/turf/proc/CardinalTurfsWithAccess" and distance = "/turf/proc/Distance_cardinal" - Seeks a path moving only in cardinal directions and checking if for the correct id to get through doors - Used by most bots, including Beepsky - - 3) adjacent = "/turf/proc/AdjacentTurfs" and distance = "/turf/proc/Distance" - Same as 1), but don't check for ID. Can get only get through open doors - - 4) adjacent = "/turf/proc/AdjacentTurfsSpace" and distance = "/turf/proc/Distance" - Same as 1), but check all turf, including unsimulated */ ////////////////////// @@ -83,26 +61,15 @@ length to avoid portals or something i guess?? Not that they're counted right no /proc/HeapPathWeightCompare(PathNode/a, PathNode/b) return b.f - a.f -//search if there's a PathNode that points to turf T in the Priority Queue -/proc/SeekTurf(var/PriorityQueue/Queue, turf/T) - var/i = 1 - var/PathNode/PN - while(i < Queue.L.len + 1) - PN = Queue.L[i] - if(PN.source == T) - return i - i++ - return 0 - //wrapper that returns an empty list if A* failed to find a path -/proc/get_path_to(start, end, atom, dist, maxnodes, maxnodedepth = 30, mintargetdist, minnodedist, id=null, turf/exclude=null) - var/list/path = AStar(start, end, atom, dist, maxnodes, maxnodedepth, mintargetdist, minnodedist,id, exclude) +/proc/get_path_to(start, end, atom, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) + var/list/path = AStar(start, end, atom, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only) if(!path) path = list() return path //the actual algorithm -/proc/AStar(start, end, atom, dist, maxnodes, maxnodedepth = 30, mintargetdist, minnodedist, id=null, turf/exclude=null) +/proc/AStar(start, end, atom, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list var/list/closed = new() //the closed list var/list/path = null //the returned path, if any @@ -136,22 +103,15 @@ length to avoid portals or something i guess?? Not that they're counted right no if(cur.source == end || closeenough) path = new() path.Add(cur.source) + while(cur.prevNode) cur = cur.prevNode path.Add(cur.source) break - //IMPLEMENTATION TO FINISH - //do we really need this minnodedist ??? - /*if(minnodedist && maxnodedepth) - if(call(cur.source,minnodedist)(end) + cur.nt >= maxnodedepth) - continue - */ - //get adjacents turfs using the adjacent proc, checking for access with id - //var/list/L = call(cur.source,adjacent)(id,closed) - var/list/L = cur.source.reachableAdjacentTurfs(atom, id) + var/list/L = call(cur.source,adjacent)(atom,id, simulated_only) for(var/turf/T in L) if(T == exclude || T in closed) continue @@ -186,33 +146,33 @@ length to avoid portals or something i guess?? Not that they're counted right no return path -/turf/proc/reachableAdjacentTurfs(atom, ID) +//Returns adjacent turfs in cardinal directions that are reachable +//simulated_only controls whether only simulated turfs are considered or not +/turf/proc/reachableAdjacentTurfs(atom, ID, simulated_only) var/list/L = new() var/turf/simulated/T - if(ID) - for(var/dir in cardinal) - T = get_step(src,dir) - if(!istype(T) || T.density) - continue - if(!LinkBlockedWithAccess(T, ID)) - L.Add(T) - else - for(var/dir in cardinal) - if(dir & atmos_adjacent_turfs) - T = get_step(src,dir) - if(!istype(T)) - continue - if(!LinkBlocked(atom, T)) - L.Add(T) + + for(var/dir in cardinal) + T = get_step(src,dir) + if(simulated_only && !istype(T)) + continue + if(!T.density && !LinkBlockedWithAccess(T, ID)) + L.Add(T) return L -/turf/proc/LinkBlocked(atom, turf/T) - if(istype(atom, /atom/movable)) - for(var/obj/O in T) - if(!O.CanPass(atom, T, 1)) - return 1 - return 0 - return 0 +//Returns adjacent turfs in cardinal directions that are reachable via atmos +/turf/proc/reachableAdjacentAtmosTurfs() + var/list/L = new() + var/turf/simulated/T + + for(var/dir in cardinal) + if(dir & atmos_adjacent_turfs) + T = get_step(src,dir) + if(!istype(T)) + continue + if(CanAtmosPass(T)) + L.Add(T) + return L /turf/proc/LinkBlockedWithAccess(turf/T, obj/item/weapon/card/id/ID) var/adir = get_dir(src, T) @@ -237,4 +197,4 @@ length to avoid portals or something i guess?? Not that they're counted right no for(var/obj/machinery/door/D in T) if(!D.CanAStarPass(ID, dir)) return 1 - return 0 + return 0 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index bc21b6d7ebc..ecc67496fae 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -39,9 +39,7 @@ return if(!isturf(user.loc)) return - if(get_dist(user, target) > (user.mind.changeling.sting_range)) - return //sanity check as AStar is still throwing insane stunts - if(!AStar(user.loc, target.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, user.mind.changeling.sting_range)) + if(!AStar(user.loc, target.loc, null, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0)) return //hope this ancient magic still works if(target.mind && target.mind.changeling) sting_feedback(user,target) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 9914ba1c582..3e83033169d 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -347,7 +347,7 @@ if(locs.len == 2) //we found 2 locations and thats all we need break var/turf/T = get_step(M.current,direction) //getting a loc in that direction - if(AStar(M.current.loc, T, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 1)) // if a path exists, so no dense objects in the way its valid salid + if(AStar(M.current.loc, T, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 1, simulated_only = 0)) // if a path exists, so no dense objects in the way its valid salid locs += T if(locs.len) for(var/turf/tospawn in locs) diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index 2d68ffa9121..eb8a61235b9 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -272,9 +272,9 @@ if(path.len == 0) if(!istype(target, /turf/)) var/turf/TL = get_turf(target) - path = get_path_to(loc, TL, src, /turf/proc/Distance_cardinal, 0, 30, id=botcard) + path = get_path_to(loc, TL, src, /turf/proc/Distance_cardinal, 0, 30, id=botcard, simulated_only = 0) else - path = get_path_to(loc, target, src, /turf/proc/Distance_cardinal, 0, 30, id=botcard) + path = get_path_to(loc, target, src, /turf/proc/Distance_cardinal, 0, 30, id=botcard, simulated_only = 0) if(!bot_move(target)) add_to_ignore(target) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index e32ebbc7687..6b4a9e8be94 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -273,7 +273,7 @@ for(var/dir in cardinal) T = get_step(src, dir) if(istype(T) && !T.density) - if(!LinkBlocked(src, T)) + if(!CanAtmosPass(T)) L.Add(T) return L @@ -304,7 +304,7 @@ if(T in closed) //turf already proceeded by A* continue if(istype(T) && !T.density) - if(!LinkBlocked(src, T)) + if(!CanAtmosPass(T)) L.Add(T) return L @@ -318,7 +318,7 @@ continue if(istype(T) && !T.density) if(!ID) - if(!LinkBlocked(src, T)) + if(!CanAtmosPass(T)) L.Add(T) else if(!LinkBlockedWithAccess(src, T, ID)) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 4bea67b9ab3..cd4fb9ed8c8 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -618,7 +618,7 @@ It can still be worn/put on as normal. if(!source || !target) return //Target or source no longer exist if(source.loc != s_loc) return //source has moved if(target.loc != t_loc) return //target has moved - if (LinkBlockedUnclimbable(t_loc, s_loc)) return + if(!in_range(source, target)) return if(item && source.get_active_hand() != item) return //Swapped hands / removed item from the active one if ((source.restrained() || source.stat)) return //Source restrained or unconscious / dead if(target.frozen)