mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
Pathfinding Visualization, JPS fixes, Misc Improvement (#90233)
## About The Pull Request [cleans up poor namespacing on light debugging tools](93cc9070d5) [Implements a pathfinding visualization tool](ed91f69ac4) It holds a set of inputs from the client, and uses them to generate and display paths from source/target. Left click sets the source, right click sets the target. Pathmap support too, if no target is set we display the paths from every turf in the map to the source, if one is set we build a path TO it from the source. I had to add COMSIG_MOB_CLICKON to observers to make this work (tho idk why it didn't exist already), I also removed the everpresent colorblind datum from admin datums, only needs to exist if they're using it. [Adds a mutable_appearance helper that dirlocks them, wallening port which I thought might be useful here, and will likely be useful elsewhere in future](87f752e7c3) [Fixes an infinite loop in pathmaps if we tried to pull a cached path to an unreachable target, && not || 4head](10086a655d) [Fixes JPS not dealing with border objects properly. They violate some of the assumptions JPS makes, so we need to backfill them with checks. These basically read as (if the thing that should normally take this path can't reach this turf, can we?)](f56cc4dd43) ## Why It's Good For The Game Maybe deals with #80619? Adds more robust testing tools for pathfinding, should allow people to better understand/debug these systems. I added this with the idea of adding multiz support but I don't have the time for that rn. JPS will work around thindows better, that's nice. https://file.house/IrBiR0bGxoKw1jJJoxgMRQ==.mp4 ## Changelog 🆑 fix: Fixed our pathfinding logic getting deeply confused by border objects admin: Added clientside displayed pathfinding debug tools, give em a go /🆑
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
#define COMSIG_MOB_REAGENT_CHECK "mob_reagent_check"
|
||||
///stops the reagent check call
|
||||
#define COMSIG_MOB_STOP_REAGENT_CHECK (1<<0)
|
||||
///from base of mob/clickon(): (atom/A, params)
|
||||
///from base of mob/clickon(): (atom/A, list/modifiers)
|
||||
#define COMSIG_MOB_CLICKON "mob_clickon"
|
||||
///from base of mob/MiddleClickOn(): (atom/A)
|
||||
#define COMSIG_MOB_MIDDLECLICKON "mob_middleclickon"
|
||||
|
||||
@@ -307,6 +307,11 @@
|
||||
/// Layer for light overlays
|
||||
#define LIGHT_DEBUG_LAYER 6
|
||||
|
||||
/// Layer for pathfinding arrows
|
||||
#define PATH_ARROW_DEBUG_LAYER 7
|
||||
/// Layer for pathfinding overlays
|
||||
#define PATH_DEBUG_LAYER 8
|
||||
|
||||
///Layer for lobby menu collapse button
|
||||
#define LOBBY_BELOW_MENU_LAYER 2
|
||||
///Layer for lobby menu background image and main buttons (Join/Ready, Observe, Character Prefs)
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
* If you really want to optimize things, optimize this, cuz this gets called a lot.
|
||||
* We do early next.density check despite it being already checked in LinkBlockedWithAccess for short-circuit performance
|
||||
*/
|
||||
#define CAN_STEP(cur_turf, next, simulated_only, pass_info, avoid) (next && !next.density && !(simulated_only && SSpathfinder.space_type_cache[next.type]) && !cur_turf.LinkBlockedWithAccess(next, pass_info) && (next != avoid))
|
||||
#define CAN_STEP(cur_turf, next, simulated_only, pass_info, avoid) \
|
||||
(next && !next.density && !(simulated_only && SSpathfinder.space_type_cache[next.type]) && (next != avoid) && !cur_turf.LinkBlockedWithAccess(next, pass_info))
|
||||
|
||||
#define DIAGONAL_DO_NOTHING NONE
|
||||
#define DIAGONAL_REMOVE_ALL 1
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
|
||||
/// A helper macro for JPS, for telling when a node has forced neighbors that need expanding
|
||||
/// Only usable in the context of the jps datum because of the datum vars it relies on
|
||||
/// Checks if we are deviating from our "running" directions
|
||||
#define STEP_NOT_HERE_BUT_THERE(cur_turf, dirA, dirB) ((!CAN_STEP(cur_turf, get_step(cur_turf, dirA), simulated_only, pass_info, avoid) && CAN_STEP(cur_turf, get_step(cur_turf, dirB), simulated_only, pass_info, avoid)))
|
||||
/// Checks if a border object stops our parent from reaching a turf we CAN reach
|
||||
#define TURF_CANT_WE_CAN(parent_turf, dir_parent, cur_turf, dur_cur) ((!CAN_STEP(parent_turf, get_step(parent_turf, dir_parent), simulated_only, pass_info, avoid) && CAN_STEP(cur_turf, get_step(cur_turf, dur_cur), simulated_only, pass_info, avoid)))
|
||||
|
||||
|
||||
/// The JPS Node datum represents a turf that we find interesting enough to add to the open list and possibly search for new tiles from
|
||||
/datum/jps_node
|
||||
@@ -212,16 +216,20 @@
|
||||
|
||||
switch(heading)
|
||||
if(NORTH)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, EAST, NORTHEAST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, EAST, NORTHEAST) \
|
||||
|| TURF_CANT_WE_CAN(get_step(current_turf, EAST), NORTH, current_turf, NORTHEAST) || TURF_CANT_WE_CAN(get_step(current_turf, WEST), NORTH, current_turf, NORTHWEST))
|
||||
interesting = TRUE
|
||||
if(SOUTH)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, SOUTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, EAST, SOUTHEAST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, SOUTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, EAST, SOUTHEAST) \
|
||||
|| TURF_CANT_WE_CAN(get_step(current_turf, EAST), SOUTH, current_turf, SOUTHEAST) || TURF_CANT_WE_CAN(get_step(current_turf, WEST), SOUTH, current_turf, SOUTHWEST))
|
||||
interesting = TRUE
|
||||
if(EAST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHEAST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHEAST) \
|
||||
|| TURF_CANT_WE_CAN(get_step(current_turf, SOUTH), EAST, current_turf, SOUTHEAST) || TURF_CANT_WE_CAN(get_step(current_turf, NORTH), EAST, current_turf, NORTHEAST))
|
||||
interesting = TRUE
|
||||
if(WEST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHWEST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHWEST) \
|
||||
|| TURF_CANT_WE_CAN(get_step(current_turf, SOUTH), WEST, current_turf, SOUTHWEST) || TURF_CANT_WE_CAN(get_step(current_turf, NORTH), WEST, current_turf, NORTHWEST))
|
||||
interesting = TRUE
|
||||
|
||||
if(interesting)
|
||||
@@ -274,22 +282,26 @@
|
||||
|
||||
switch(heading)
|
||||
if(NORTHWEST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, EAST, NORTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHWEST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, EAST, NORTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHWEST) \
|
||||
|| TURF_CANT_WE_CAN(lag_turf, NORTH, current_turf, EAST) || TURF_CANT_WE_CAN(lag_turf, WEST, current_turf, SOUTH))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, WEST) || lateral_scan_spec(current_turf, NORTH))
|
||||
if(NORTHEAST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHEAST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHEAST) \
|
||||
|| TURF_CANT_WE_CAN(lag_turf, NORTH, current_turf, WEST) || TURF_CANT_WE_CAN(lag_turf, EAST, current_turf, SOUTH))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, EAST) || lateral_scan_spec(current_turf, NORTH))
|
||||
if(SOUTHWEST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, EAST, SOUTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHWEST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, EAST, SOUTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHWEST) \
|
||||
|| TURF_CANT_WE_CAN(lag_turf, SOUTH, current_turf, EAST) || TURF_CANT_WE_CAN(lag_turf, WEST, current_turf, NORTH))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, SOUTH) || lateral_scan_spec(current_turf, WEST))
|
||||
if(SOUTHEAST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, SOUTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHEAST))
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, SOUTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHEAST) \
|
||||
|| TURF_CANT_WE_CAN(lag_turf, SOUTH, current_turf, WEST) || TURF_CANT_WE_CAN(lag_turf, EAST, current_turf, NORTH))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, SOUTH) || lateral_scan_spec(current_turf, EAST))
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
var/turf/next_turf = other_end
|
||||
// Cache for sonic speed
|
||||
var/next_closest = src.next_closest
|
||||
while(next_turf != FLOW_PATH_END || next_turf == null)
|
||||
while(next_turf != FLOW_PATH_END && next_turf != null)
|
||||
path += next_turf
|
||||
next_turf = next_closest[next_turf] // We take the first entry cause that's the turf
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, modifiers) & COMSIG_MOB_CANCEL_CLICKON)
|
||||
return
|
||||
|
||||
if(LAZYACCESS(modifiers, SHIFT_CLICK))
|
||||
if(LAZYACCESS(modifiers, MIDDLE_CLICK))
|
||||
ShiftMiddleClickOn(A)
|
||||
|
||||
@@ -49,3 +49,11 @@
|
||||
check_topdown_validity(appearance)
|
||||
|
||||
return appearance
|
||||
|
||||
/// Takes an input mutable appearance, returns a copy of it with the hidden flag flipped to avoid inheriting dir from what it's drawn on
|
||||
/// This inheriting thing is handled by a hidden flag on the /image (MAs are subtypes of /image)
|
||||
/proc/make_mutable_appearance_directional(mutable_appearance/to_process, dir = NORTH)
|
||||
// We use the image() proc in combo with a manually set dir to flip this flag
|
||||
// We can then copy the image's appearance to retain the flag, even on MAs and such
|
||||
var/image/holder = image(to_process, dir = dir)
|
||||
return new /mutable_appearance(holder)
|
||||
|
||||
@@ -33,9 +33,10 @@ GLOBAL_PROTECT(href_token)
|
||||
|
||||
var/datum/filter_editor/filteriffic
|
||||
var/datum/particle_editor/particle_test
|
||||
var/datum/colorblind_tester/color_test = new
|
||||
var/datum/colorblind_tester/color_test
|
||||
var/datum/plane_master_debug/plane_debug
|
||||
var/obj/machinery/computer/libraryconsole/admin_only_do_not_map_in_you_fucker/library_manager
|
||||
var/datum/pathfind_debug/path_debug
|
||||
|
||||
/// Whether or not the user tried to connect, but was blocked by 2FA
|
||||
var/blocked_by_2fa = FALSE
|
||||
@@ -78,7 +79,8 @@ GLOBAL_PROTECT(href_token)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
. = ..()
|
||||
QDEL_NULL(path_debug)
|
||||
return ..()
|
||||
|
||||
/datum/admins/proc/activate()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
@@ -99,6 +101,7 @@ GLOBAL_PROTECT(href_token)
|
||||
GLOB.deadmins[target] = src
|
||||
GLOB.admin_datums -= target
|
||||
QDEL_NULL(plane_debug)
|
||||
QDEL_NULL(path_debug)
|
||||
deadmined = TRUE
|
||||
|
||||
var/client/client = owner || GLOB.directory[target]
|
||||
|
||||
@@ -552,6 +552,8 @@ ADMIN_VERB(init_log, R_DEBUG, "Display Initialize() Log", "Displays a list of th
|
||||
browser.open()
|
||||
|
||||
ADMIN_VERB(debug_color_test, R_DEBUG, "Colorblind Testing", "Change your view to a budget version of colorblindness to test for usability.", ADMIN_CATEGORY_DEBUG)
|
||||
if(!user.holder.color_test)
|
||||
user.holder.color_test = new()
|
||||
user.holder.color_test.ui_interact(user.mob)
|
||||
|
||||
ADMIN_VERB(debug_plane_masters, R_DEBUG, "Edit/Debug Planes", "Edit and visualize plane masters and their connections (relays).", ADMIN_CATEGORY_DEBUG)
|
||||
@@ -654,6 +656,14 @@ ADMIN_VERB(run_empty_query, R_DEBUG, "Run Empty Query", "Runs a specified number
|
||||
|
||||
message_admins("[key_name_admin(user)] ran [val] empty queries.")
|
||||
|
||||
ADMIN_VERB(test_pathfinding, R_DEBUG, "Toggle Pathfind Testing", "Enables/Disables pathfinding testing action buttons", ADMIN_CATEGORY_DEBUG)
|
||||
BLACKBOX_LOG_ADMIN_VERB("Toggle Pathfind Testing")
|
||||
log_admin("[key_name(user)] [user.holder.path_debug ? "disabled" : "enabled"] their pathfinding debug tools")
|
||||
if(!user.holder.path_debug)
|
||||
user.holder.path_debug = new(user.holder)
|
||||
else
|
||||
QDEL_NULL(user.holder.path_debug)
|
||||
|
||||
ADMIN_VERB(clear_turf_reservations, R_DEBUG, "Clear Dynamic Turf Reservations", "Deallocates all reserved space, restoring it to round start conditions.", ADMIN_CATEGORY_DEBUG)
|
||||
var/answer = tgui_alert(
|
||||
user,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
/proc/debug_sources()
|
||||
/proc/debug_light_sources()
|
||||
GLOB.light_debug_enabled = TRUE
|
||||
var/list/sum = list()
|
||||
var/total = 0
|
||||
for(var/datum/light_source/source)
|
||||
if(!source.source_atom)
|
||||
continue
|
||||
source.source_atom.debug()
|
||||
source.source_atom.debug_lights()
|
||||
sum[source.source_atom.type] += 1
|
||||
total += 1
|
||||
|
||||
@@ -29,14 +29,14 @@
|
||||
var/datum/action/spawn_light/let_there_be = new (new_lad.mob.mind || new_lad.mob)
|
||||
let_there_be.Grant(new_lad.mob)
|
||||
|
||||
/proc/undebug_sources()
|
||||
/proc/undebug_light_sources()
|
||||
GLOB.light_debug_enabled = FALSE
|
||||
for(var/datum/weakref/button_ref as anything in GLOB.light_debugged_atoms)
|
||||
var/atom/button = button_ref.resolve()
|
||||
if(!button)
|
||||
GLOB.light_debugged_atoms -= button_ref
|
||||
continue
|
||||
button.undebug()
|
||||
button.undebug_lights()
|
||||
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_LIGHT_DEBUG_DISABLED)
|
||||
SSdcs.UnregisterSignal(SSdcs, COMSIG_GLOB_CLIENT_CONNECT)
|
||||
@@ -44,7 +44,7 @@
|
||||
GLOBAL_LIST_EMPTY(light_debugged_atoms)
|
||||
/// Sets up this light source to be debugged, setting up in world buttons to control and move it
|
||||
/// Also freezes it, so it can't change in future
|
||||
/atom/proc/debug()
|
||||
/atom/proc/debug_lights()
|
||||
if(isturf(src) || HAS_TRAIT(src, TRAIT_LIGHTING_DEBUGGED))
|
||||
return
|
||||
ADD_TRAIT(src, TRAIT_LIGHTING_DEBUGGED, LIGHT_DEBUG_TRAIT)
|
||||
@@ -65,7 +65,7 @@ GLOBAL_LIST_EMPTY(light_debugged_atoms)
|
||||
new /atom/movable/screen/light_button/move(src)
|
||||
|
||||
/// Disables light debugging, so you can let a scene fall to what it visually should be, or just fix admin fuckups
|
||||
/atom/proc/undebug()
|
||||
/atom/proc/undebug_lights()
|
||||
// I don't really want to undebug a light if it's off rn
|
||||
// Loses control if we turn it back on again
|
||||
if(isturf(src) || !HAS_TRAIT(src, TRAIT_LIGHTING_DEBUGGED) || !light)
|
||||
|
||||
@@ -390,7 +390,7 @@ ADMIN_VERB(check_for_obstructed_atmospherics, R_DEBUG, "Check For Obstructed Atm
|
||||
ADMIN_VERB_VISIBILITY(modify_lights, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
|
||||
ADMIN_VERB(modify_lights, R_DEBUG, "Toggle Light Debug", "Toggles light debug mode.", ADMIN_CATEGORY_MAPPING)
|
||||
if(GLOB.light_debug_enabled)
|
||||
undebug_sources()
|
||||
undebug_light_sources()
|
||||
return
|
||||
|
||||
for(var/obj/machinery/light/fix_up as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/light))
|
||||
@@ -398,7 +398,7 @@ ADMIN_VERB(modify_lights, R_DEBUG, "Toggle Light Debug", "Toggles light debug mo
|
||||
if(initial(fix_up.status) == LIGHT_OK)
|
||||
fix_up.fix()
|
||||
CHECK_TICK
|
||||
debug_sources()
|
||||
debug_light_sources()
|
||||
|
||||
ADMIN_VERB_VISIBILITY(visualize_lights, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
|
||||
ADMIN_VERB(visualize_lights, R_DEBUG, "Visualize Lighting Corners", "Visualizes the corners of all lights on the station.", ADMIN_CATEGORY_MAPPING)
|
||||
|
||||
263
code/modules/admin/verbs/path_debugger.dm
Normal file
263
code/modules/admin/verbs/path_debugger.dm
Normal file
@@ -0,0 +1,263 @@
|
||||
GLOBAL_DATUM_INIT(pathfind_dude, /obj/pathfind_guy, new())
|
||||
|
||||
/obj/pathfind_guy
|
||||
|
||||
/// Enables testing/visualization of pathfinding work
|
||||
/datum/pathfind_debug
|
||||
var/datum/admins/owner
|
||||
var/datum/action/innate/path_debug/jps/jps_debug
|
||||
var/datum/action/innate/path_debug/sssp/sssp_debug
|
||||
|
||||
/datum/pathfind_debug/New(datum/admins/owner)
|
||||
src.owner = owner
|
||||
hook_client()
|
||||
|
||||
/datum/pathfind_debug/Destroy(force)
|
||||
QDEL_NULL(jps_debug)
|
||||
QDEL_NULL(sssp_debug)
|
||||
return ..()
|
||||
|
||||
/datum/pathfind_debug/proc/hook_client()
|
||||
if(!owner.owner)
|
||||
return
|
||||
QDEL_NULL(jps_debug)
|
||||
QDEL_NULL(sssp_debug)
|
||||
jps_debug = new
|
||||
jps_debug.Grant(owner.owner.mob)
|
||||
sssp_debug = new()
|
||||
sssp_debug.Grant(owner.owner.mob)
|
||||
RegisterSignal(owner.owner.mob, COMSIG_MOB_LOGOUT, PROC_REF(on_logout))
|
||||
|
||||
/datum/pathfind_debug/proc/on_logout(mob/logging_out)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(logging_out, COMSIG_MOB_LOGOUT)
|
||||
var/mob/new_mob = owner.owner?.mob
|
||||
if(!new_mob)
|
||||
RegisterSignal(logging_out, COMSIG_MOB_LOGIN, PROC_REF(on_login))
|
||||
return
|
||||
hook_client()
|
||||
|
||||
/datum/pathfind_debug/proc/on_login(mob/logging_in)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(logging_in, list(COMSIG_MOB_LOGOUT, COMSIG_MOB_LOGIN))
|
||||
hook_client()
|
||||
|
||||
/datum/action/innate/path_debug
|
||||
var/list/image/display_images = list()
|
||||
|
||||
/datum/action/innate/path_debug/Activate()
|
||||
. = ..()
|
||||
RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(clicked_somethin))
|
||||
active = TRUE
|
||||
|
||||
/datum/action/innate/path_debug/Deactivate()
|
||||
UnregisterSignal(owner, COMSIG_MOB_CLICKON)
|
||||
clear_visuals()
|
||||
active = FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/path_debug/proc/clicked_somethin(datum/source, atom/clicked, list/modifiers)
|
||||
SIGNAL_HANDLER
|
||||
if(LAZYACCESS(modifiers, SHIFT_CLICK))
|
||||
return NONE
|
||||
|
||||
var/turf/clunked = get_turf(clicked)
|
||||
if(!clunked)
|
||||
return NONE
|
||||
|
||||
if(LAZYACCESS(modifiers, RIGHT_CLICK))
|
||||
right_clicked(clunked)
|
||||
else
|
||||
left_clicked(clunked)
|
||||
|
||||
update_visuals()
|
||||
if(path_ready())
|
||||
pathfind()
|
||||
|
||||
/datum/action/innate/path_debug/proc/left_clicked(turf/clicked_on)
|
||||
return
|
||||
|
||||
/datum/action/innate/path_debug/proc/right_clicked(turf/clicked_on)
|
||||
return
|
||||
|
||||
/datum/action/innate/path_debug/proc/update_visuals()
|
||||
clear_visuals()
|
||||
build_visuals()
|
||||
owner.client?.images += display_images
|
||||
|
||||
/datum/action/innate/path_debug/proc/clear_visuals()
|
||||
owner.client?.images -= display_images
|
||||
display_images = list()
|
||||
|
||||
/datum/action/innate/path_debug/proc/build_visuals()
|
||||
return
|
||||
|
||||
/datum/action/innate/path_debug/proc/path_ready()
|
||||
return FALSE
|
||||
|
||||
/datum/action/innate/path_debug/proc/pathfind()
|
||||
INVOKE_ASYNC(src, PROC_REF(run_the_path), GLOB.pathfind_dude)
|
||||
GLOB.pathfind_dude.moveToNullspace()
|
||||
|
||||
/datum/action/innate/path_debug/proc/run_the_path(atom/movable/middle_man)
|
||||
return
|
||||
|
||||
/datum/action/innate/path_debug/proc/render_path(list/turf/draw_list)
|
||||
if(!length(draw_list))
|
||||
return list()
|
||||
|
||||
var/list/image/turf_images = list()
|
||||
// Render everything but the first and last
|
||||
for(var/i in 1 to (length(draw_list) - 1))
|
||||
var/turf/problem_child = draw_list[i]
|
||||
var/turf/next = draw_list[i + 1]
|
||||
turf_images += render_turf(problem_child, get_dir(problem_child, next))
|
||||
|
||||
return turf_images
|
||||
|
||||
/datum/action/innate/path_debug/proc/render_turf(turf/draw, direction)
|
||||
var/image/arrow = image('icons/turf/debug.dmi', draw, "arrow", PATH_ARROW_DEBUG_LAYER, direction)
|
||||
SET_PLANE_EXPLICIT(arrow, BALLOON_CHAT_PLANE, draw)
|
||||
return arrow
|
||||
|
||||
/datum/action/innate/path_debug/jps
|
||||
name = "JPS Test"
|
||||
button_icon = 'icons/turf/debug.dmi'
|
||||
button_icon_state = "jps"
|
||||
|
||||
// Mirror vars for jps calls
|
||||
var/turf/source_turf
|
||||
var/turf/target_turf
|
||||
var/max_distance
|
||||
var/min_distance
|
||||
var/allowed_on_space
|
||||
var/turf/blacklisted_turf
|
||||
var/diagonal_handling
|
||||
/// List of turfs we are showing to our owner currently
|
||||
var/list/turf/display_turfs
|
||||
|
||||
/datum/action/innate/path_debug/jps/Activate()
|
||||
. = ..()
|
||||
max_distance = tgui_input_number(owner, "How far should we be allowed to try and path", "Max Distance", min_value = 1, default = 30)
|
||||
min_distance = tgui_input_number(owner, "How close should we try and get to the target before stopping", "Min Distance", min_value = 0, default = 0)
|
||||
allowed_on_space = tgui_alert(owner, "Are we allowed to path over space?", "Space Pathing", buttons = list("Yes", "No")) == "Yes"
|
||||
var/text_blacklist = tgui_input_text(owner, "Enter any turf path you want to blacklist (You get one)", "Turf Blacklist")
|
||||
if(text_blacklist)
|
||||
blacklisted_turf = pick_closest_path(text_blacklist)
|
||||
else
|
||||
blacklisted_turf = null
|
||||
diagonal_handling = DIAGONAL_DO_NOTHING
|
||||
switch(tgui_input_list(owner, "Pick how you want to handle diagonal moves", "Diagonal Moves", list("Leave Them Be", "Drop All", "Drop Odd Ones")))
|
||||
if("Leave Them Be")
|
||||
diagonal_handling = DIAGONAL_DO_NOTHING
|
||||
if("Drop All")
|
||||
diagonal_handling = DIAGONAL_REMOVE_ALL
|
||||
if("Drop Odd Ones")
|
||||
diagonal_handling = DIAGONAL_REMOVE_CLUNKY
|
||||
|
||||
/datum/action/innate/path_debug/jps/Deactivate()
|
||||
source_turf = null
|
||||
target_turf = null
|
||||
display_turfs = list()
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/path_debug/jps/left_clicked(turf/clicked_on)
|
||||
source_turf = clicked_on
|
||||
display_turfs = list()
|
||||
|
||||
/datum/action/innate/path_debug/jps/right_clicked(turf/clicked_on)
|
||||
target_turf = clicked_on
|
||||
display_turfs = list()
|
||||
|
||||
/datum/action/innate/path_debug/jps/build_visuals()
|
||||
. = ..()
|
||||
if(source_turf)
|
||||
var/image/start = image('icons/turf/debug.dmi', source_turf, "start", PATH_DEBUG_LAYER)
|
||||
SET_PLANE_EXPLICIT(start, BALLOON_CHAT_PLANE, source_turf)
|
||||
display_images += start
|
||||
if(target_turf)
|
||||
var/image/end = image('icons/turf/debug.dmi', target_turf, "end", PATH_DEBUG_LAYER)
|
||||
SET_PLANE_EXPLICIT(end, BALLOON_CHAT_PLANE, target_turf)
|
||||
display_images += end
|
||||
|
||||
display_images += render_path(display_turfs)
|
||||
|
||||
/datum/action/innate/path_debug/jps/path_ready()
|
||||
return (source_turf && target_turf)
|
||||
|
||||
/datum/action/innate/path_debug/jps/run_the_path(atom/movable/middle_man)
|
||||
middle_man.forceMove(source_turf)
|
||||
display_turfs = get_path_to(middle_man, target_turf, max_distance, min_distance, list(), allowed_on_space, blacklisted_turf, skip_first = FALSE, diagonal_handling = diagonal_handling)
|
||||
update_visuals()
|
||||
|
||||
/datum/action/innate/path_debug/sssp
|
||||
name = "Pathmap Test"
|
||||
button_icon = 'icons/turf/debug.dmi'
|
||||
button_icon_state = "sssp"
|
||||
|
||||
// Mirror vars for sssp calls
|
||||
var/turf/source_turf
|
||||
var/max_distance
|
||||
var/allowed_on_space
|
||||
var/turf/blacklisted_turf
|
||||
// Turf to display the path to (optional)
|
||||
var/turf/target_turf
|
||||
/// List of turfs we are showing to our owner currently
|
||||
var/datum/path_map/shown_map
|
||||
|
||||
/datum/action/innate/path_debug/sssp/Activate()
|
||||
. = ..()
|
||||
max_distance = tgui_input_number(owner, "How far should we be allowed to try and path", "Max Distance", min_value = 1, default = 30)
|
||||
allowed_on_space = tgui_alert(owner, "Are we allowed to path over space?", "Space Pathing", buttons = list("Yes", "No")) == "Yes"
|
||||
var/text_blacklist = tgui_input_text(owner, "Enter any turf path you want to blacklist (You get one)", "Turf Blacklist")
|
||||
if(text_blacklist)
|
||||
blacklisted_turf = pick_closest_path(text_blacklist)
|
||||
else
|
||||
blacklisted_turf = null
|
||||
|
||||
/datum/action/innate/path_debug/sssp/Deactivate()
|
||||
source_turf = null
|
||||
target_turf = null
|
||||
shown_map = null
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/path_debug/sssp/left_clicked(turf/clicked_on)
|
||||
source_turf = clicked_on
|
||||
shown_map = null
|
||||
|
||||
/datum/action/innate/path_debug/sssp/right_clicked(turf/clicked_on)
|
||||
if(clicked_on == target_turf)
|
||||
target_turf = null
|
||||
return
|
||||
target_turf = clicked_on
|
||||
|
||||
/datum/action/innate/path_debug/sssp/build_visuals()
|
||||
. = ..()
|
||||
if(source_turf)
|
||||
var/image/start = image('icons/turf/debug.dmi', source_turf, "start", PATH_DEBUG_LAYER)
|
||||
SET_PLANE_EXPLICIT(start, BALLOON_CHAT_PLANE, source_turf)
|
||||
display_images += start
|
||||
|
||||
if(target_turf)
|
||||
var/image/end = image('icons/turf/debug.dmi', target_turf, "end", PATH_DEBUG_LAYER)
|
||||
SET_PLANE_EXPLICIT(end, BALLOON_CHAT_PLANE, target_turf)
|
||||
display_images += end
|
||||
if(shown_map)
|
||||
display_images += render_path(shown_map.get_path_to(target_turf))
|
||||
else
|
||||
if(!shown_map)
|
||||
return
|
||||
var/list/turf/next_closest = shown_map.next_closest
|
||||
var/turf/start = shown_map?.start
|
||||
for(var/turf/next_dude as anything in next_closest)
|
||||
if(next_dude == start)
|
||||
continue
|
||||
display_images += render_turf(next_dude, get_dir(next_dude, next_closest[next_dude]))
|
||||
|
||||
/datum/action/innate/path_debug/sssp/path_ready()
|
||||
return (source_turf && source_turf != shown_map?.start)
|
||||
|
||||
/datum/action/innate/path_debug/sssp/run_the_path(atom/movable/middle_man)
|
||||
middle_man.forceMove(source_turf)
|
||||
shown_map = get_sssp(middle_man, max_distance, list(), allowed_on_space, blacklisted_turf)
|
||||
update_visuals()
|
||||
@@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(lighting_sheets)
|
||||
|
||||
update()
|
||||
if(GLOB.light_debug_enabled)
|
||||
source_atom.debug()
|
||||
source_atom.debug_lights()
|
||||
|
||||
/datum/light_source/Destroy(force)
|
||||
remove_lum()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 611 B After Width: | Height: | Size: 1.3 KiB |
@@ -3068,6 +3068,7 @@
|
||||
#include "code\modules\admin\verbs\mapping.dm"
|
||||
#include "code\modules\admin\verbs\maprotation.dm"
|
||||
#include "code\modules\admin\verbs\panicbunker.dm"
|
||||
#include "code\modules\admin\verbs\path_debugger.dm"
|
||||
#include "code\modules\admin\verbs\plane_debugger.dm"
|
||||
#include "code\modules\admin\verbs\player_ticket_history.dm"
|
||||
#include "code\modules\admin\verbs\playsound.dm"
|
||||
|
||||
Reference in New Issue
Block a user