Files
Paradise/code/datums/pathfinding_mover.dm
Contrabang 243ff18304 Maint drones now return to the drone manufacturer when shutdown (#23367)
* luv me some drones

* uhhh WIP

* ..() moment

* Gaxeer review & misc change

* henri review

* tgui

* boom, i think

* oops

* sirryan review

* final stuff

* lmaooo

* Apply suggestions from code review

Co-authored-by: Deniz <66401072+Oyu07@users.noreply.github.com>

---------

Co-authored-by: Deniz <66401072+Oyu07@users.noreply.github.com>
2024-01-30 14:39:46 +00:00

129 lines
3.7 KiB
Plaintext

/**
* A generalized datum for pathfinding, and moving to a target.
*/
/datum/pathfinding_mover
/// Can be a simplemob bot, a drone, or even a pathfinding modsuit module (currently only implemented for drones)
VAR_PRIVATE/atom/movable/owner
/// The target turf we are after
VAR_PRIVATE/turf/target
/// List of turfs through which a mod 'steps' to reach the waypoint
VAR_PRIVATE/list/path = list()
/// max amount of tries before resetting path to null
var/max_tries = 10
/// How many times have we tried to move?
VAR_PRIVATE/tries = 0
/// How many 2-tick delays per move (5 = 1 second)
var/move_speed = 2
/// A counter for move_speed via modulo
VAR_PRIVATE/move_ticks = 0
/// Callback invoked on failure
var/datum/callback/on_set_path_null
/// Callback invoked on success
var/datum/callback/on_success
/// The delay called as part of Move()
VAR_PRIVATE/atom/movable/owner_move_delay = 0
/// Do we consider movement delay? Disable for non-mobs
var/consider_movement_delay = TRUE
/// Requires `consider_movement_delay = TRUE`, saves the last movement delay to prevent diagonal weirdness
VAR_PRIVATE/last_movement_delay
/datum/pathfinding_mover/New(_owner, _target)
target = _target
owner = _owner
if(ismob(owner))
var/mob/M = owner
owner_move_delay = M.movement_delay()
RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(signal_qdel))
/datum/pathfinding_mover/Destroy(force, ...)
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
STOP_PROCESSING(SSfastprocess, src)
return ..()
/datum/pathfinding_mover/proc/generate_path(...)
set_path(get_path_to(arglist(list(owner, target) + args)))
return (length(path) > 0)
/datum/pathfinding_mover/proc/set_target(atom/new_target)
if(!isatom(new_target))
target = null
return
target = get_turf(new_target)
/datum/pathfinding_mover/proc/set_path(list/newpath)
PRIVATE_PROC(TRUE)
if(newpath == null)
on_set_path_null?.Invoke() // This is seperate to prevent invoking the callback if calling from generate_path
path = newpath ? newpath : list()
if(!length(path)) // Because newpath could be an empty list
STOP_PROCESSING(SSfastprocess, src)
tries = 0
/**
* Start moving towards our target, returns false if the path does not lead to the target
*/
/datum/pathfinding_mover/proc/start()
if(!target || !length(path)) // Pathfinding failed or a path/destination was not set.
set_path(null)
return FALSE
var/turf/last_node = get_turf(path[length(path)]) // This is the turf at the end of the path
if(target != last_node) // The path should lead us to our given destination. If this is not true, we must stop.
set_path(null)
return FALSE
START_PROCESSING(SSfastprocess, src)
return TRUE
/**
* Using fast process, see if we should take the next step yet
*/
/datum/pathfinding_mover/process(wait) // 2 on fast process
move_ticks++
if(move_speed && (move_ticks < move_speed))
return
if(consider_movement_delay && (last_movement_delay > (move_ticks * wait)))
return
move_ticks = 0
if(tries >= max_tries)
set_path(null)
return // PROCESS_KILL called with set_path(null)
if(get_turf(owner) == target) // We have arrived, no need to move again.
on_success?.Invoke(src)
return PROCESS_KILL
generalized_step()
/**
* Take our next step in our pathfinding algorithm
*/
/datum/pathfinding_mover/proc/generalized_step() // Step, increase tries if failed
PRIVATE_PROC(TRUE)
if(!length(path))
return
var/targetted_direction = get_dir(owner, path[1])
var/delay = owner_move_delay
if(IS_DIR_DIAGONAL(targetted_direction))
delay *= SQRT_2
if(!owner.Move(path[1], targetted_direction, delay))
tries++
return
tries = 0
if(consider_movement_delay)
last_movement_delay = delay
// Increment the path
path.Cut(1, 2)