Merge branch 'master' of https://github.com/tgstation/tgstation into upstream-25-04a

This commit is contained in:
Waterpig
2025-04-08 18:58:45 +02:00
1089 changed files with 42417 additions and 34460 deletions
+5 -1
View File
@@ -211,7 +211,11 @@ GLOBAL_PROTECT(protected_ranks)
/// (Re)Loads the admin list.
/// returns TRUE if database admins had to be loaded from the backup json
/proc/load_admins(no_update)
/proc/load_admins(no_update, initial = FALSE)
if(!initial)
if(!global.config.PreConfigReload())
return
var/dbfail
if(!CONFIG_GET(flag/admin_legacy_system) && !SSdbcore.Connect())
message_admins("Failed to connect to database while loading admins. Loading from backup.")
+2 -4
View File
@@ -22,8 +22,7 @@
human.set_facial_hairstyle(random_facial_hairstyle(human.gender), update = FALSE)
human.set_haircolor("#[random_color()]", update = FALSE)
human.set_facial_haircolor(human.hair_color, update = FALSE)
human.eye_color_left = random_eye_color()
human.eye_color_right = human.eye_color_left
human.set_eye_color(random_eye_color())
human.skin_tone = pick(GLOB.skin_tones)
human.dna.species.randomize_active_underwear_only(human)
// Needs to be called towards the end to update all the UIs just set above
@@ -47,8 +46,7 @@
human.physique = human.gender
human.real_name = human.generate_random_mob_name()
human.name = human.get_visible_name()
human.eye_color_left = random_eye_color()
human.eye_color_right = human.eye_color_left
human.set_eye_color(random_eye_color())
human.skin_tone = pick(GLOB.skin_tones)
// No underwear generation handled here
var/picked_color = random_hair_color()
+8 -5
View File
@@ -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]
@@ -172,18 +175,18 @@ GLOBAL_PROTECT(href_token)
return cached_feedback_link
if (!SSdbcore.IsConnected())
return FALSE
return null
var/datum/db_query/feedback_query = SSdbcore.NewQuery("SELECT feedback FROM [format_table_name("admin")] WHERE ckey = '[owner.ckey]'")
if(!feedback_query.Execute())
log_sql("Error retrieving feedback link for [src]")
qdel(feedback_query)
return FALSE
return null
if(!feedback_query.NextRow())
qdel(feedback_query)
return FALSE // no feedback link exists
return null // no feedback link exists
cached_feedback_link = feedback_query.item[1] || NO_FEEDBACK_LINK
qdel(feedback_query)
+1 -1
View File
@@ -471,7 +471,7 @@ ADMIN_VERB(edit_admin_permissions, R_PERMISSIONS, "Permissions Panel", "Edit adm
admin_holder.rank_flags(),
350,
590,
allowed_edit_list = usr.client.holder.can_edit_rights_flags(),
allowed_edit_flags = usr.client.holder.can_edit_rights_flags(),
)
admin_holder.disassociate()
+38
View File
@@ -0,0 +1,38 @@
/// A smite, used by admins to punish players, or for their own amusement
/datum/smite
/// The name of the smite, shown in the menu
var/name
/// Flags which modify how the smite fires
var/smite_flags = NONE
/// Should this smite write to logs?
var/should_log = TRUE
/// Called once after either choosing the option to smite a player, or when selected in smite build mode.
/// Use this to prompt the user configuration options.
/// Return FALSE if the smite should not be used.
/datum/smite/proc/configure(client/user)
/// Invoked externally to actually perform the smite
/datum/smite/proc/do_effect(client/user, mob/living/target)
if(smite_flags & SMITE_DIVINE)
playsound(target, 'sound/effects/pray.ogg', 50, FALSE, -1)
target.add_overlay(mutable_appearance('icons/mob/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
target.apply_status_effect(/datum/status_effect/spotlight_light/divine)
if(smite_flags & SMITE_STUN)
target.Stun(3 SECONDS, ignore_canstun = TRUE)
if(smite_flags & SMITE_DELAY)
addtimer(CALLBACK(src, PROC_REF(delayed_effect), user, target), 2 SECONDS, TIMER_UNIQUE)
else
effect(user, target)
/// Called after a delay if the smite has the SMITE_DELAY flag
/datum/smite/proc/delayed_effect(client/user, mob/living/target)
if(QDELETED(target))
return
effect(user, target)
/// The effect of the smite, make sure to call this in your own smites
/datum/smite/proc/effect(client/user, mob/living/target)
if (should_log)
user.punish_log(target, name)
@@ -40,3 +40,7 @@
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(objectify), target, transform_path), OBJECTIFY_TIME)
#undef OBJECTIFY_TIME
/datum/smite/objectify/divine
name = "Become Object (Divine)"
smite_flags = SMITE_DIVINE|SMITE_STUN
+4
View File
@@ -51,3 +51,7 @@
shots_this_limb += 1
if (shots_this_limb > shots_per_limb_per_rep)
break
/datum/smite/berforate/divine
name = ":B:erforate (Divine)"
smite_flags = SMITE_DIVINE
+10
View File
@@ -0,0 +1,10 @@
/datum/smite/dust
name = "Dust"
/datum/smite/dust/effect(client/user, mob/living/target)
. = ..()
target.dust(just_ash = FALSE, drop_items = TRUE, force = TRUE)
/datum/smite/dust/divine
name = "Dust (Divine)"
smite_flags = SMITE_DIVINE|SMITE_DELAY|SMITE_STUN
+4
View File
@@ -5,3 +5,7 @@
/datum/smite/gib/effect(client/user, mob/living/target)
. = ..()
target.gib(DROP_ORGANS|DROP_BODYPARTS)
/datum/smite/gib/divine
name = "Gib (Divine)"
smite_flags = SMITE_DIVINE|SMITE_DELAY|SMITE_STUN
+5 -1
View File
@@ -1,6 +1,6 @@
/// Strikes the target with a lightning bolt
/datum/smite/lightning
name = "Lightning bolt"
name = "Lightning Bolt"
/datum/smite/lightning/effect(client/user, mob/living/target)
. = ..()
@@ -16,3 +16,7 @@
if(ishuman(user))
var/mob/living/carbon/human/human_target = user
human_target.electrocution_animation(LIGHTNING_BOLT_ELECTROCUTION_ANIMATION_LENGTH)
/datum/smite/lightning/divine
name = "Lightning Bolt (Divine)"
smite_flags = SMITE_DIVINE
+4
View File
@@ -10,3 +10,7 @@
return
var/mob/living/carbon/human/human_target = target
human_target.petrify(statue_timer = INFINITY, save_brain = FALSE)
/datum/smite/petrify/divine
name = "Petrify (Divine)"
smite_flags = SMITE_DIVINE|SMITE_DELAY|SMITE_STUN
+39
View File
@@ -0,0 +1,39 @@
/datum/smite/retcon
name = "Retcon"
/// how long until the thing attacked by this smite gets deleted
var/timer
/// the time it takes to actually do the fade out animation, the victim will always have some time still fully visible
var/fade_out_timer
/datum/smite/retcon/configure(client/user)
timer = tgui_input_number(user, "How long should it take before the target disappears, in seconds?", "Retcon", 5)
if (isnull(timer))
return FALSE
fade_out_timer = timer*3*0.2
/datum/smite/retcon/effect(client/user, mob/living/target)
. = ..()
target.fade_into_nothing(timer SECONDS,fade_out_timer SECONDS)
if(ishuman(target))
delete_record(target)
delete_bank_account(target)
reopen_job_slot(target)
/datum/smite/retcon/proc/delete_record(mob/living/target)
var/name = target.real_name
GLOB.manifest.remove(name)
/datum/smite/retcon/proc/delete_bank_account(mob/living/target)
var/name = target.real_name
var/account_list = flatten_list(SSeconomy.bank_accounts_by_id)
for(var/datum/bank_account/account in account_list)
if(account.account_holder == name)
qdel(account)
return
/datum/smite/retcon/proc/reopen_job_slot(mob/living/target)
var/datum/job/target_job = target.mind?.assigned_role
if(target_job)
target_job.total_positions += 1
-17
View File
@@ -1,17 +0,0 @@
/// A smite, used by admins to punish players, or for their own amusement
/datum/smite
/// The name of the smite, shown in the menu
var/name
/// Should this smite write to logs?
var/should_log = TRUE
/// Called once after either choosing the option to smite a player, or when selected in smite build mode.
/// Use this to prompt the user configuration options.
/// Return FALSE if the smite should not be used.
/datum/smite/proc/configure(client/user)
/// The effect of the smite, make sure to call this in your own smites
/datum/smite/proc/effect(client/user, mob/living/target)
if (should_log)
user.punish_log(target, name)
@@ -64,6 +64,8 @@
return istype(object, type)
/proc/_ispath(path, type)
if(isnull(type))
return ispath(path)
return ispath(path, type)
/proc/_length(E)
@@ -270,7 +272,7 @@
winset(player, control_id, params)
/proc/_winget(player, control_id, params)
winget(player, control_id, params)
return winget(player, control_id, params)
/proc/_text2path(text)
return text2path(text)
@@ -297,3 +299,6 @@
if(!filter_index || filter_index < 1 || filter_index > length(target.filters))
return
animate(target.filters[filter_index], appearance = set_vars, time, loop, easing, flags)
/proc/_is_type_in_typecache(thing_to_check, typecache)
return is_type_in_typecache(thing_to_check, typecache)
+13 -1
View File
@@ -76,6 +76,18 @@ ADMIN_VERB(gib_self, R_ADMIN, "Gibself", "Give yourself the same treatment you g
if (istype(ourself))
ourself.gib()
ADMIN_VERB(dust_self, R_ADMIN, "Dustself", "Give yourself the same treatment you give others.", ADMIN_CATEGORY_FUN)
var/confirm = tgui_alert(user, "You sure?", "Confirm", list("Yes", "No"))
if(confirm != "Yes")
return
log_admin("[key_name(user)] used dustself.")
message_admins(span_adminnotice("[key_name_admin(user)] used dustself."))
BLACKBOX_LOG_ADMIN_VERB("Dust Self")
var/mob/living/ourself = user.mob
if (istype(ourself))
ourself.dust(just_ash = FALSE, drop_items = FALSE, force = TRUE)
ADMIN_VERB(everyone_random, R_SERVER, "Make Everyone Random", "Make everyone have a random appearance.", ADMIN_CATEGORY_FUN)
if(SSticker.HasRoundStarted())
to_chat(user, "Nope you can't do this, the game's already started. This only works before rounds!", confidential = TRUE)
@@ -164,7 +176,7 @@ ADMIN_VERB_AND_CONTEXT_MENU(admin_smite, R_ADMIN|R_FUN, "Smite", "Smite a player
var/configuration_success = smite.configure(user)
if (configuration_success == FALSE)
return
smite.effect(user, target)
smite.do_effect(user, target)
/// "Turns" people into objects. Really, we just add them to the contents of the item.
/proc/objectify(atom/movable/target, path_or_instance)
+10
View File
@@ -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,
+6 -6
View File
@@ -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)
+2 -2
View File
@@ -395,7 +395,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))
@@ -403,7 +403,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
View 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()
+9 -4
View File
@@ -60,6 +60,8 @@ ADMIN_VERB(play_direct_mob_sound, R_SOUND, "Play Direct Mob Sound", "Play a soun
SEND_SOUND(target, sound)
BLACKBOX_LOG_ADMIN_VERB("Play Direct Mob Sound")
GLOBAL_VAR_INIT(web_sound_cooldown, 0)
///Takes an input from either proc/play_web_sound or the request manager and runs it through yt-dlp and prompts the user before playing it to the server.
/proc/web_sound(mob/user, input, credit)
if(!check_rights(R_SOUND))
@@ -150,12 +152,15 @@ ADMIN_VERB(play_direct_mob_sound, R_SOUND, "Play Direct Mob Sound", "Play a soun
var/mob/M = m
var/client/C = M.client
if(C.prefs.read_preference(/datum/preference/numeric/volume/sound_midi))
// Stops playing lobby music and admin loaded music automatically.
SEND_SOUND(C, sound(null, channel = CHANNEL_LOBBYMUSIC))
SEND_SOUND(C, sound(null, channel = CHANNEL_ADMIN))
if(!stop_web_sounds)
C.tgui_panel?.play_music(web_sound_url, music_extra_data)
else
C.tgui_panel?.stop_music()
S_TIMER_COOLDOWN_START(SStimer, COOLDOWN_INTERNET_SOUND, duration)
CLIENT_COOLDOWN_START(GLOB, web_sound_cooldown, duration)
BLACKBOX_LOG_ADMIN_VERB("Play Internet Sound")
@@ -163,8 +168,8 @@ ADMIN_VERB_CUSTOM_EXIST_CHECK(play_web_sound)
return !!CONFIG_GET(string/invoke_youtubedl)
ADMIN_VERB(play_web_sound, R_SOUND, "Play Internet Sound", "Play a given internet sound to all players.", ADMIN_CATEGORY_FUN)
if(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND))
if(tgui_alert(user, "Someone else is already playing an Internet sound! It has [DisplayTimeText(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND), 1)] remaining. \
if(!CLIENT_COOLDOWN_FINISHED(GLOB, web_sound_cooldown))
if(tgui_alert(user, "Someone else is already playing an Internet sound! It has [DisplayTimeText(CLIENT_COOLDOWN_TIMELEFT(GLOB, web_sound_cooldown), 1)] remaining. \
Would you like to override?", "Musicalis Interruptus", list("No","Yes")) != "Yes")
return
@@ -199,7 +204,7 @@ ADMIN_VERB(stop_sounds, R_NONE, "Stop All Playing Sounds", "Stops all playing so
var/client/player_client = player.client
player_client?.tgui_panel?.stop_music()
S_TIMER_COOLDOWN_RESET(SStimer, COOLDOWN_INTERNET_SOUND)
CLIENT_COOLDOWN_RESET(GLOB, web_sound_cooldown)
BLACKBOX_LOG_ADMIN_VERB("Stop All Playing Sounds")
//world/proc/shelleo
+6 -1
View File
@@ -22,7 +22,12 @@ ADMIN_VERB(toggle_hub, R_SERVER, "Toggle Hub", "Toggles the server's visilibilit
#define HARDEST_RESTART "Hardest Restart (No actions, just reboot)"
#define TGS_RESTART "Server Restart (Kill and restart DD)"
ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.", ADMIN_CATEGORY_SERVER)
var/list/options = list(REGULAR_RESTART, REGULAR_RESTART_DELAYED, HARD_RESTART, HARDEST_RESTART)
var/list/options = list(REGULAR_RESTART, REGULAR_RESTART_DELAYED, HARD_RESTART)
// this option runs a codepath that can leak db connections because it skips subsystem (specifically SSdbcore) shutdown
if(!SSdbcore.IsConnected())
options += HARDEST_RESTART
if(world.TgsAvailable())
options += TGS_RESTART;
@@ -86,21 +86,21 @@
items += debug_variable(key, val, level + 1, sanitize = sanitize)
return "<a href='byond://?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a><ul>[items.Join()]</ul>"
else
return "<a href='byond://?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a>"
return "<a href='byond://?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a>"
if(name in GLOB.bitfields)
var/list/flags = list()
for (var/i in GLOB.bitfields[name])
if (value & GLOB.bitfields[name][i])
flags += i
if(length(flags))
return "[VV_HTML_ENCODE(jointext(flags, ", "))]"
else
return "NONE"
else
// if it's a number, is it a bitflag?
var/list/valid_bitflags = get_valid_bitflags(name)
if(!length(valid_bitflags))
return "<span class='value'>[VV_HTML_ENCODE(value)]</span>"
var/list/flags = list()
for (var/bit_name in valid_bitflags)
if (value & valid_bitflags[bit_name])
flags += bit_name
if(length(flags))
return "[VV_HTML_ENCODE(flags.Join(", "))]"
return "NONE"
/datum/proc/debug_variable_value(name, level, datum/owner, sanitize, display_flags)
if("[src]" != "[type]") // If we have a name var, let's use it.
return "<a href='byond://?_src_=vars;[HrefToken()];Vars=[REF(src)]'>[src] [type] [REF(src)]</a>"
@@ -3,7 +3,7 @@
. = VV_NULL
else if(isnum(var_value))
if(var_name in GLOB.bitfields)
if(length(get_valid_bitflags(var_name)))
. = VV_BITFIELD
else
. = VV_NUM
@@ -65,7 +65,6 @@ GLOBAL_PROTECT(VVpixelmovement)
.["[D]([shorttype])[REF(D)]#[i]"] = D
/client/proc/mod_list_add_ass(atom/O) //hehe
var/list/L = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
var/class = L["class"]
if (!class)