Merge branch 'master' of https://github.com/tgstation/tgstation into upstream-2025-11-05

This commit is contained in:
Roxy
2025-11-05 19:43:07 -05:00
461 changed files with 41708 additions and 37517 deletions
+4 -1
View File
@@ -159,7 +159,10 @@ ADMIN_VERB(advanced_proc_call, R_DEBUG, "Advanced ProcCall", "Call a proc on any
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
BLACKBOX_LOG_ADMIN_VERB("Advanced ProcCall")
if(get_retval)
get_retval += returnval
if (islist(returnval))
get_retval += list(returnval) // Wrap to stop BYOND from concat-ing the lists
else
get_retval += returnval
. = get_callproc_returnval(returnval, procname)
if(.)
to_chat(usr, ., confidential = TRUE)
+1 -1
View File
@@ -125,7 +125,7 @@ ADMIN_VERB(cmd_admin_check_player_exp, R_ADMIN, "Player Playtime", "View player
return
chosen_trait = available_traits[chosen_trait]
var/source = "adminabuse"
var/source = TRAIT_ADMIN_GRANTED
switch(add_or_remove)
if("Add") //Not doing source choosing here intentionally to make this bit faster to use, you can always vv it.
if(GLOB.movement_type_trait_to_flag[chosen_trait]) //include the required element.
+90
View File
@@ -165,6 +165,96 @@ ADMIN_VERB(polymorph_all, R_ADMIN, "Polymorph All", "Applies the effects of the
message_admins("Mass polymorph started by [who_did_it] is complete.")
/// Allow admin to mass add or remove a trait across all mobs
ADMIN_VERB(mass_modify_traits, R_FUN, "Mass Modify Traits", "Adds or removes a trait from every mob.", ADMIN_CATEGORY_FUN)
var/choice = tgui_alert(user, "Add or Remove Trait?", "Mass Add/Remove Trait", list("Add", "Remove"))
if(isnull(choice))
return
var/is_add = (choice == "Add")
var/lower_choice = LOWER_TEXT(choice)
// Build list of valid traits that can be applied to mobs
var/list/available_traits = list()
for(var/key in GLOB.admin_visible_traits)
if(ispath(/mob, key)) // so we get atom and atom/movable traits too, which doing (istype(key, /mob)) would skip
available_traits += GLOB.admin_visible_traits[key]
if(!length(available_traits))
return
available_traits = sort_list(available_traits, GLOBAL_PROC_REF(cmp_typepaths_asc)) // sort alphabetically
var/mob_trait = tgui_input_list(user, "Select a trait to [lower_choice].", "Mass [choice] Trait", available_traits)
if(isnull(mob_trait))
return
mob_trait = available_traits[mob_trait]
var/target_scope = tgui_alert(user, "[choice] [lower_choice == "add" ? "to" : "from"] all mobs, or only cliented ones?", "Scope", list("All", "Cliented"))
if(!target_scope)
return
var/cliented_only = (target_scope == "Cliented")
// So we get readable trait name to display in the uis
if(!GLOB.admin_trait_name_map)
GLOB.admin_trait_name_map = generate_admin_trait_name_map()
var/trait_name = GLOB.admin_trait_name_map[mob_trait] || mob_trait
// Ask for confirmation first
var/action_word = is_add ? "to" : "from"
var/confirm = tgui_alert(
user,
"Please confirm you want to [lower_choice] [trait_name] [action_word] every [cliented_only ? "cliented" : ""] mob?",
"Confirm Mass [choice] Trait",
list("Yes", "No")
)
if(confirm != "Yes")
return
// Perform operation
var/affected = 0
if(is_add) // Adding trait
var/needs_movetype = GLOB.movement_type_trait_to_flag[mob_trait]
for(var/mob/mob_to_modify as anything in GLOB.alive_mob_list)
if(cliented_only && !mob_to_modify.client)
continue
if(needs_movetype)
mob_to_modify.AddElement(/datum/element/movetype_handler)
ADD_TRAIT(mob_to_modify, mob_trait, TRAIT_ADMIN_GRANTED)
affected++
else // Removing trait
var/source = null
var/remove_mode = tgui_alert(user, "Remove from specific source?", "Mass Remove Trait", list("All", "Admin-Granted Traits", "Specific"))
if(isnull(remove_mode))
return
switch(remove_mode)
if("Admin-Granted Traits") source = TRAIT_ADMIN_GRANTED
if("Specific")
source = LOWER_TEXT(tgui_input_text(user, "Enter source", "Mass Remove Trait", max_length = MAX_NAME_LEN))
if(isnull(source))
return
for(var/mob/mob_to_modify as anything in GLOB.alive_mob_list)
if(cliented_only && !mob_to_modify.client)
continue
REMOVE_TRAIT(mob_to_modify, mob_trait, source)
affected++
if(affected)
var/plural = affected == 1 ? "mob" : "mobs"
var/log_msg = "[key_name_admin(user)] mass [lower_choice][is_add ? "ed" : "d"] [trait_name] [action_word] [affected] [plural]."
message_admins(log_msg)
log_admin(log_msg)
/// Returns only traits that apply to mobs
/proc/get_mob_admin_traits()
var/list/out = list()
for(var/key in GLOB.admin_visible_traits)
if(ispath(key, /mob)) // key is a mob type or subtype
out += GLOB.admin_visible_traits[key]
return out
ADMIN_VERB_AND_CONTEXT_MENU(admin_smite, R_ADMIN|R_FUN, "Smite", "Smite a player with divine power.", ADMIN_CATEGORY_FUN, mob/living/target in world)
var/punishment = tgui_input_list(user, "Choose a punishment", "DIVINE SMITING", GLOB.smites)
+4 -4
View File
@@ -119,17 +119,17 @@ GLOBAL_VAR_INIT(web_sound_cooldown, 0)
music_extra_data["album"] = "Default"
if("Cancel", null)
return
var/stay_anonimous = tgui_alert(user, "Display who played the song?", "Credit Yourself", list("Yes", "No", "Cancel"))
var/credit_yourself = tgui_alert(user, "Display who played the song?", "Credit Yourself", list("Yes", "No", "Cancel"))
var/list/to_chat_message = list()
switch(stay_anonimous)
if("No")
switch(credit_yourself)
if("Yes")
if(include_song_data == "Yes")
to_chat_message += span_notice("[user.ckey] played: [span_linkify(webpage_url)]")
else
to_chat_message += span_notice("[user.ckey] played a sound.")
if("Yes")
if("No")
if(include_song_data == "Yes")
to_chat_message += span_notice("An admin played: [span_linkify(webpage_url)]")
else
+11 -7
View File
@@ -18,6 +18,7 @@ ADMIN_VERB(toggle_hub, R_SERVER, "Toggle Hub", "Toggles the server's visilibilit
#define REGULAR_RESTART "Regular Restart"
#define REGULAR_RESTART_DELAYED "Regular Restart (with delay)"
#define NO_EVENT_RESTART "Restart, Skip TGS Event"
#define HARD_RESTART "Hard Restart (No Delay/Feedback Reason)"
#define HARDEST_RESTART "Hardest Restart (No actions, just reboot)"
#define TGS_RESTART "Server Restart (Kill and restart DD)"
@@ -29,6 +30,7 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
options += HARDEST_RESTART
if(world.TgsAvailable())
options.Insert(3, NO_EVENT_RESTART)
options += TGS_RESTART;
if(SSticker.admin_delay_notice)
@@ -42,18 +44,19 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
BLACKBOX_LOG_ADMIN_VERB("Reboot World")
var/init_by = "Initiated by [user.holder.fakekey ? "Admin" : user.key]."
switch(result)
if(REGULAR_RESTART)
if(!user.is_localhost())
if(alert(user, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", 10)
if(REGULAR_RESTART_DELAYED)
var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
if(REGULAR_RESTART, REGULAR_RESTART_DELAYED, NO_EVENT_RESTART)
var/delay = 1
if(result == REGULAR_RESTART_DELAYED)
delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
if(!delay)
return FALSE
if(!user.is_localhost())
if(alert(user,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
if (result != NO_EVENT_RESTART)
SSticker.TriggerRoundEndTgsEvent()
SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", delay * 10)
if(HARD_RESTART)
to_chat(world, "World reboot - [init_by]")
@@ -67,6 +70,7 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
#undef REGULAR_RESTART
#undef REGULAR_RESTART_DELAYED
#undef NO_EVENT_RESTART
#undef HARD_RESTART
#undef HARDEST_RESTART
#undef TGS_RESTART