diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 611ffff2394..41413dd2771 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -1,4 +1,3 @@
-
////////////////////////////////
/proc/message_admins(msg)
msg = "ADMIN LOG: [msg]"
@@ -14,400 +13,8 @@
html = msg,
confidential = TRUE)
-
///////////////////////////////////////////////////////////////////////////////////////////////Panels
-/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list)
- set category = "Admin.Game"
- set name = "Show Player Panel"
- set desc="Edit player (respawn, ban, heal, etc)"
-
- if(!check_rights())
- return
-
- log_admin("[key_name(usr)] checked the individual player panel for [key_name(M)][isobserver(usr)?"":" while in game"].")
-
- if(!M)
- to_chat(usr, span_warning("You seem to be selecting a mob that doesn't exist anymore."), confidential = TRUE)
- return
-
- var/body = "
Options for [M.key]"
- body += "Options panel for [M]"
- if(M.client)
- body += " played by [M.client] "
- body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]"
- if(CONFIG_GET(flag/use_exp_tracking))
- body += "\[" + M.client.get_exp_living(FALSE) + "\]"
-
- if(isnewplayer(M))
- body += " Hasn't Entered Game "
- else
- body += " \[Heal\] "
-
- if(M.client)
- body += "
\[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]"
- body += "
CentCom Galactic Ban DB: "
- if(CONFIG_GET(string/centcom_ban_db))
- body += "Search"
- else
- body += "Disabled"
- body += "
Show related accounts by: "
- body += "\[ CID | "
- body += "IP \]"
- var/full_version = "Unknown"
- if(M.client.byond_version)
- full_version = "[M.client.byond_version].[M.client.byond_build ? M.client.byond_build : "xxx"]"
- body += "
\[Byond version: [full_version]\]
"
-
-
- body += "
\[ "
- body += "VV - "
- if(M.mind)
- body += "TP - "
- body += "SKILLS - "
- else
- body += "Init Mind - "
- if (iscyborg(M))
- body += "BP - "
- body += "PM - "
- body += "SM - "
- if (ishuman(M) && M.mind)
- body += "HM - "
- body += "FLW - "
- //Default to client logs if available
- var/source = LOGSRC_MOB
- if(M.client)
- source = LOGSRC_CLIENT
- body += "LOGS\]
"
-
- body += "Mob type = [M.type]
"
-
- body += "Kick | "
- if(M.client)
- body += "Ban | "
- else
- body += "Ban | "
-
- body += "Notes | Messages | Watchlist | "
- if(M.client)
- body += "| Prison | "
- body += "\ Send back to Lobby | "
- var/muted = M.client.prefs.muted
- body += "
Mute: "
- body += "\[IC | "
- body += "OOC | "
- body += "PRAY | "
- body += "ADMINHELP | "
- body += "DEADCHAT\]"
- // Skyrat Edit Addition - Mute LOOC
- body += "LOOC\]"
- // Skyrat Edit End
- body += "(toggle all)"
-
- body += "
"
- body += "Jump to | "
- body += "Get | "
- body += "Send To"
-
- body += "
"
- body += "Traitor panel | "
- body += "Narrate to | "
- body += "Subtle message | "
- body += "Play sound to | "
- body += "Language Menu"
-
- if (M.client)
- if(!isnewplayer(M))
- body += "
"
- body += "Transformation:"
- body += "
"
-
- //Human
- if(ishuman(M) && !ismonkey(M))
- body += "Human | "
- else
- body += "Humanize | "
-
- //Monkey
- if(ismonkey(M))
- body += "Monkeyized | "
- else
- body += "Monkeyize | "
-
- //Corgi
- if(iscorgi(M))
- body += "Corgized | "
- else
- body += "Corgize | "
-
- //AI / Cyborg
- if(isAI(M))
- body += "Is an AI "
- else if(ishuman(M))
- body += "Make AI | "
- body += "Make Robot | "
- body += "Make Alien | "
- body += "Make Slime | "
- body += "Make Blob | "
-
- //Simple Animals
- if(isanimal(M))
- body += "Re-Animalize | "
- else
- body += "Animalize | "
-
- body += "
"
- body += "Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.
"
- body += "Observer | "
- body += "\[ Alien: Drone, "
- body += "Hunter, "
- body += "Sentinel, "
- body += "Praetorian, "
- body += "Queen, "
- body += "Larva \] "
- body += "Human "
- body += "\[ slime: Baby, "
- body += "Adult \] "
- body += "Monkey | "
- body += "Cyborg | "
- body += "Cat | "
- body += "Runtime | "
- body += "Corgi | "
- body += "Ian | "
- body += "Crab | "
- body += "Coffee | "
- body += "\[ Construct: Juggernaut , "
- body += "Artificer , "
- body += "Wraith \] "
- body += "Shade"
- body += "
"
-
- if (M.client)
- body += "
"
- body += "Other actions:"
- body += "
"
- body += "Forcesay | "
- body += "Thunderdome 1 | "
- body += "Thunderdome 2 | "
- body += "Thunderdome Admin | "
- body += "Thunderdome Observer | "
- body += "Commend Behavior | "
-
- body += "
"
- body += ""
-
- usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-
-/datum/admins/proc/access_news_network() //MARKER
- set category = "Admin.Events"
- set name = "Access Newscaster Network"
- set desc = "Allows you to view, add and edit news feeds."
-
- if (!istype(src, /datum/admins))
- src = usr.client.holder
- if (!istype(src, /datum/admins))
- to_chat(usr, "Error: you are not an admin!", confidential = TRUE)
- return
- var/dat
- dat = text("Admin NewscasterAdmin Newscaster Unit
")
-
- switch(admincaster_screen)
- if(0)
- dat += "Welcome to the admin newscaster.
Here you can add, edit and censor every newspiece on the network."
- dat += "
Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units."
- dat += "
Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!"
- if(GLOB.news_network.wanted_issue.active)
- dat+= "
Read Wanted Issue"
- dat+= "
Create Feed Channel"
- dat+= "
View Feed Channels"
- dat+= "
Submit new Feed story"
- dat+= "
Exit"
- var/wanted_already = 0
- if(GLOB.news_network.wanted_issue.active)
- wanted_already = 1
- dat+="
Feed Security functions:
"
- dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue"
- dat+="
Censor Feed Stories"
- dat+="
Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel)."
- dat+="
The newscaster recognises you as:
[src.admin_signature]"
- if(1)
- dat+= "Station Feed Channels
"
- if( !length(GLOB.news_network.network_channels) )
- dat+="No active channels found..."
- else
- for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
- if(CHANNEL.is_admin_channel)
- dat+="[CHANNEL.channel_name]
"
- else
- dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
"
- dat+="
Refresh"
- dat+="
Back"
- if(2)
- dat+="Creating new Feed Channel..."
- dat+="
Channel Name: [src.admincaster_feed_channel.channel_name]
"
- dat+="Channel Author: [src.admin_signature]
"
- dat+="Will Accept Public Feeds: [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]
"
- dat+="
Submit
Cancel
"
- if(3)
- dat+="Creating new Feed Message..."
- dat+="
Receiving Channel: [src.admincaster_feed_channel.channel_name]
" //MARK
- dat+="Message Author: [src.admin_signature]
"
- dat+="Message Body: [src.admincaster_feed_message.returnBody(-1)]
"
- dat+="
Submit
Cancel
"
- if(4)
- dat+="Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].
"
- dat+="
Return
"
- if(5)
- dat+="Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.
"
- dat+="
Return
"
- if(6)
- dat+="ERROR: Could not submit Feed story to Network.
"
- if(src.admincaster_feed_channel.channel_name=="")
- dat+="Invalid receiving channel name.
"
- if(src.admincaster_feed_message.returnBody(-1) == "" || src.admincaster_feed_message.returnBody(-1) == "\[REDACTED\]")
- dat+="Invalid message body.
"
- dat+="
Return
"
- if(7)
- dat+="ERROR: Could not submit Feed Channel to Network.
"
- if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]")
- dat+="Invalid channel name.
"
- var/check = 0
- for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
- if(FC.channel_name == src.admincaster_feed_channel.channel_name)
- check = 1
- break
- if(check)
- dat+="Channel name already in use.
"
- dat+="
Return
"
- if(9)
- dat+="[admincaster_feed_channel.channel_name]: \[created by: [admincaster_feed_channel.returnAuthor(-1)]\]
"
- if(src.admincaster_feed_channel.censored)
- dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
"
- dat+="No further feed story additions are allowed while the D-Notice is in effect.
"
- else
- if( !length(src.admincaster_feed_channel.messages) )
- dat+="No feed messages found in channel...
"
- else
- var/i = 0
- for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
- i++
- dat+="-[MESSAGE.returnBody(-1)]
"
- if(MESSAGE.img)
- usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
- dat+="
"
- dat+="\[Story by [MESSAGE.returnAuthor(-1)]\]
"
- dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]:
"
- for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments)
- dat+="[comment.body]
[comment.author] [comment.time_stamp]
"
- dat+="
"
- dat+="
Refresh"
- dat+="
Back"
- if(10)
- dat+="Nanotrasen Feed Censorship Tool
"
- dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
"
- dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it."
- dat+="
Select Feed channel to get Stories from:
"
- if(!length(GLOB.news_network.network_channels))
- dat+="No feed channels found active...
"
- else
- for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
- dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
"
- dat+="
Cancel"
- if(11)
- dat+="Nanotrasen D-Notice Handler
"
- dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's"
- dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed"
- dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
"
- if(!length(GLOB.news_network.network_channels))
- dat+="No feed channels found active...
"
- else
- for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
- dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
"
-
- dat+="
Back"
- if(12)
- dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
"
- dat+="[(src.admincaster_feed_channel.authorCensor) ? ("Undo Author censorship") : ("Censor channel Author")]
"
-
- if( !length(src.admincaster_feed_channel.messages) )
- dat+="No feed messages found in channel...
"
- else
- for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
- dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
"
- dat+="[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]
"
- dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
"
- for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments)
- dat+="[comment.body] X
[comment.author] [comment.time_stamp]
"
- dat+="
Back"
- if(13)
- dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
"
- dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
"
- if(src.admincaster_feed_channel.censored)
- dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
"
- dat+="No further feed story additions are allowed while the D-Notice is in effect.
"
- else
- if( !length(src.admincaster_feed_channel.messages) )
- dat+="No feed messages found in channel...
"
- else
- for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
- dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
"
- dat+="
Back"
- if(14)
- dat+="Wanted Issue Handler:"
- var/wanted_already = 0
- var/end_param = 1
- if(GLOB.news_network.wanted_issue.active)
- wanted_already = 1
- end_param = 2
- if(wanted_already)
- dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below."
- dat+="
"
- dat+="Criminal Name: [src.admincaster_wanted_message.criminal]
"
- dat+="Description: [src.admincaster_wanted_message.body]
"
- if(wanted_already)
- dat+="Wanted Issue created by:[GLOB.news_network.wanted_issue.scannedUser]
"
- else
- dat+="Wanted Issue will be created under prosecutor:[src.admin_signature]
"
- dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]"
- if(wanted_already)
- dat+="
Take down Issue"
- dat+="
Cancel"
- if(15)
- dat+="Wanted issue for [src.admincaster_wanted_message.criminal] is now in Network Circulation.
"
- dat+="
Return
"
- if(16)
- dat+="ERROR: Wanted Issue rejected by Network.
"
- if(src.admincaster_wanted_message.criminal =="" || src.admincaster_wanted_message.criminal == "\[REDACTED\]")
- dat+="Invalid name for person wanted.
"
- if(src.admincaster_wanted_message.body == "" || src.admincaster_wanted_message.body == "\[REDACTED\]")
- dat+="Invalid description.
"
- dat+="
Return
"
- if(17)
- dat+="Wanted Issue successfully deleted from Circulation
"
- dat+="
Return
"
- if(18)
- dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [GLOB.news_network.wanted_issue.scannedUser]\]
"
- dat+="Criminal: [GLOB.news_network.wanted_issue.criminal]
"
- dat+="Description: [GLOB.news_network.wanted_issue.body]
"
- dat+="Photo:: "
- if(GLOB.news_network.wanted_issue.img)
- usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png")
- dat+="
"
- else
- dat+="None"
- dat+="
Back
"
- if(19)
- dat+="Wanted issue for [src.admincaster_wanted_message.criminal] successfully edited.
"
- dat+="
Return
"
- else
- dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"
-
- usr << browse(dat, "window=admincaster_main;size=400x600")
- onclose(usr, "admincaster_main")
-
-
/datum/admins/proc/Game()
if(!check_rights(0))
return
@@ -437,227 +44,6 @@
usr << browse(dat, "window=admin2;size=240x280")
return
-/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge
-//i.e. buttons/verbs
-
-
-/datum/admins/proc/restart()
- set category = "Server"
- set name = "Reboot World"
- set desc="Restarts the world immediately"
- if (!usr.client.holder)
- return
-
- var/localhost_addresses = list("127.0.0.1", "::1")
- var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
- if(world.TgsAvailable())
- options += "Server Restart (Kill and restart DD)";
-
- if(SSticker.admin_delay_notice)
- if(tgui_alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", list("Yes", "No")) != "Yes")
- return FALSE
-
- var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
- if(result)
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]."
- switch(result)
- if("Regular Restart")
- if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
- if(tgui_alert(usr, "Are you sure you want to restart the server?","This server is live",list("Restart","Cancel")) != "Restart")
- return FALSE
- SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
- if("Regular Restart (with delay)")
- var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
- if(!delay)
- return FALSE
- if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
- if(tgui_alert(usr,"Are you sure you want to restart the server?","This server is live",list("Restart","Cancel")) != "Restart")
- return FALSE
- SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay * 10)
- if("Hard Restart (No Delay, No Feeback Reason)")
- to_chat(world, "World reboot - [init_by]")
- world.Reboot()
- if("Hardest Restart (No actions, just reboot)")
- to_chat(world, "Hard world reboot - [init_by]")
- world.Reboot(fast_track = TRUE)
- if("Server Restart (Kill and restart DD)")
- to_chat(world, "Server restart - [init_by]")
- world.TgsEndProcess()
-
-/datum/admins/proc/end_round()
- set category = "Server"
- set name = "End Round"
- set desc = "Attempts to produce a round end report and then restart the server organically."
-
- if (!usr.client.holder)
- return
- var/confirm = tgui_alert(usr, "End the round and restart the game world?", "End Round", list("Yes", "Cancel"))
- if(confirm == "Cancel")
- return
- if(confirm == "Yes")
- SSticker.force_ending = 1
- SSblackbox.record_feedback("tally", "admin_verb", 1, "End Round") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-
-/datum/admins/proc/announce()
- set category = "Admin"
- set name = "Announce"
- set desc="Announce your desires to the world"
- if(!check_rights(0))
- return
-
- var/message = input("Global message to send:", "Admin Announce", null, null) as message
- if(message)
- if(!check_rights(R_SERVER,0))
- message = adminscrub(message,500)
- to_chat(world, "[span_adminnotice("[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:")]\n \t [message]", confidential = TRUE)
- log_admin("Announce: [key_name(usr)] : [message]")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/set_admin_notice()
- set category = "Server"
- set name = "Set Admin Notice"
- set desc ="Set an announcement that appears to everyone who joins the server. Only lasts this round"
- if(!check_rights(0))
- return
-
- var/new_admin_notice = input(src,"Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):","Set Notice",GLOB.admin_notice) as message|null
- if(new_admin_notice == null)
- return
- if(new_admin_notice == GLOB.admin_notice)
- return
- if(new_admin_notice == "")
- message_admins("[key_name(usr)] removed the admin notice.")
- log_admin("[key_name(usr)] removed the admin notice:\n[GLOB.admin_notice]")
- else
- message_admins("[key_name(usr)] set the admin notice.")
- log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]")
- to_chat(world, span_adminnotice("Admin Notice:\n \t [new_admin_notice]"), confidential = TRUE)
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Admin Notice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- GLOB.admin_notice = new_admin_notice
- return
-
-/datum/admins/proc/toggleooc()
- set category = "Server"
- set desc="Toggle dis bitch"
- set name="Toggle OOC"
- toggle_ooc()
- log_admin("[key_name(usr)] toggled OOC.")
- message_admins("[key_name_admin(usr)] toggled OOC.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/toggleoocdead()
- set category = "Server"
- set desc="Toggle dis bitch"
- set name="Toggle Dead OOC"
- toggle_dooc()
-
- log_admin("[key_name(usr)] toggled OOC.")
- message_admins("[key_name_admin(usr)] toggled Dead OOC.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/startnow()
- set category = "Server"
- set desc="Start the round RIGHT NOW"
- set name="Start Now"
- if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP)
- if(!SSticker.start_immediately)
- var/localhost_addresses = list("127.0.0.1", "::1")
- if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
- if(tgui_alert(usr, "Are you sure you want to start the round?","Start Now",list("Start Now","Cancel")) != "Start Now")
- return FALSE
- SSticker.start_immediately = TRUE
- log_admin("[usr.key] has started the game.")
- var/msg = ""
- if(SSticker.current_state == GAME_STATE_STARTUP)
- msg = " (The server is still setting up, but the round will be \
- started as soon as possible.)"
- message_admins("[usr.key] has started the game.[msg]")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Now") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- return TRUE
- SSticker.start_immediately = FALSE
- SSticker.SetTimeLeft(1800)
- to_chat(world, "The game will start in 180 seconds.")
- SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
- message_admins("[usr.key] has cancelled immediate game start. Game will start in 180 seconds.")
- log_admin("[usr.key] has cancelled immediate game start.")
- else
- to_chat(usr, "Error: Start Now: Game has already started.")
- return FALSE
-
-/datum/admins/proc/toggleenter()
- set category = "Server"
- set desc="People can't enter"
- set name="Toggle Entering"
- if(!SSlag_switch.initialized)
- return
- SSlag_switch.set_measure(DISABLE_NON_OBSJOBS, !SSlag_switch.measures[DISABLE_NON_OBSJOBS])
- log_admin("[key_name(usr)] toggled new player game entering. Lag Switch at index ([DISABLE_NON_OBSJOBS])")
- message_admins("[key_name_admin(usr)] toggled new player game entering [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "OFF" : "ON"].")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Entering", "[!SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/toggleAI()
- set category = "Server"
- set desc="People can't be AI"
- set name="Toggle AI"
- var/alai = CONFIG_GET(flag/allow_ai)
- CONFIG_SET(flag/allow_ai, !alai)
- if (alai)
- to_chat(world, "The AI job is no longer chooseable.", confidential = TRUE)
- else
- to_chat(world, "The AI job is chooseable now.", confidential = TRUE)
- log_admin("[key_name(usr)] toggled AI allowed.")
- world.update_status()
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle AI", "[!alai ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/toggleaban()
- set category = "Server"
- set desc="Respawn basically"
- set name="Toggle Respawn"
- var/new_nores = !CONFIG_GET(flag/norespawn)
- CONFIG_SET(flag/norespawn, new_nores)
- if (!new_nores)
- to_chat(world, "You may now respawn.", confidential = TRUE)
- else
- to_chat(world, "You may no longer respawn :(", confidential = TRUE)
- message_admins(span_adminnotice("[key_name_admin(usr)] toggled respawn to [!new_nores ? "On" : "Off"]."))
- log_admin("[key_name(usr)] toggled respawn to [!new_nores ? "On" : "Off"].")
- world.update_status()
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Respawn", "[!new_nores ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/delay()
- set category = "Server"
- set desc="Delay the game start"
- set name="Delay Pre-Game"
-
- var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null
- if(SSticker.current_state > GAME_STATE_PREGAME)
- return tgui_alert(usr, "Too late... The game has already started!")
- if(newtime)
- newtime = newtime*10
- SSticker.SetTimeLeft(newtime)
- SSticker.start_immediately = FALSE
- if(newtime < 0)
- to_chat(world, "The game start has been delayed.", confidential = TRUE)
- log_admin("[key_name(usr)] delayed the round start.")
- else
- to_chat(world, "The game will start in [DisplayTimeText(newtime)].", confidential = TRUE)
- SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
- log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/unprison(mob/M in GLOB.mob_list)
- set category = "Admin"
- set name = "Unprison"
- if (is_centcom_level(M.z))
- SSjob.SendToLateJoin(M)
- message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]")
- log_admin("[key_name(usr)] has unprisoned [key_name(M)]")
- else
- tgui_alert(usr,"[M.name] is not prisoned.")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Unprison") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS
/datum/admins/proc/spawn_atom(object as text)
@@ -734,36 +120,6 @@
log_admin("[key_name(usr)] spawned cargo pack [chosen] at [AREACOORD(usr)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Cargo") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/admins/proc/show_traitor_panel(mob/target_mob in GLOB.mob_list)
- set category = "Admin.Game"
- set desc = "Edit mobs's memory and role"
- set name = "Show Traitor Panel"
- var/datum/mind/target_mind = target_mob.mind
- if(!target_mind)
- to_chat(usr, "This mob has no mind!", confidential = TRUE)
- return
- if(!istype(target_mob) && !istype(target_mind))
- to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
- return
- target_mind.traitor_panel()
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/datum/admins/proc/show_skill_panel(target)
- set category = "Admin.Game"
- set desc = "Edit mobs's experience and skill levels"
- set name = "Show Skill Panel"
- var/datum/mind/target_mind
- if(ismob(target))
- var/mob/target_mob = target
- target_mind = target_mob.mind
- else if (istype(target, /datum/mind))
- target_mind = target
- else
- to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
- return
- var/datum/skill_panel/SP = new(usr, target_mind)
- SP.ui_interact(usr)
-
/datum/admins/proc/toggletintedweldhelmets()
set category = "Debug"
set desc="Reduces view range when wearing welding helmets"
@@ -777,20 +133,6 @@
message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Tinted Welding Helmets", "[GLOB.tinted_weldhelh ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/admins/proc/toggleguests()
- set category = "Server"
- set desc="Guests can't enter"
- set name="Toggle guests"
- var/new_guest_ban = !CONFIG_GET(flag/guest_ban)
- CONFIG_SET(flag/guest_ban, new_guest_ban)
- if (new_guest_ban)
- to_chat(world, "Guests may no longer enter the game.", confidential = TRUE)
- else
- to_chat(world, "Guests may now enter the game.", confidential = TRUE)
- log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.")
- message_admins(span_adminnotice("[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed."))
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Guests", "[!new_guest_ban ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
/datum/admins/proc/output_ai_laws()
var/ai_number = 0
for(var/i in GLOB.silicon_mobs)
@@ -813,47 +155,6 @@
if(!ai_number)
to_chat(usr, "No AIs located" , confidential = TRUE)
-
-/datum/admins/proc/manage_free_slots()
- if(!check_rights())
- return
- var/datum/browser/browser = new(usr, "jobmanagement", "Manage Free Slots", 520)
- var/list/dat = list()
- var/count = 0
-
- if(!SSjob.initialized)
- tgui_alert(usr, "You cannot manage jobs before the job subsystem is initialized!")
- return
-
- if(SSlag_switch.measures[DISABLE_NON_OBSJOBS])
- dat += "Lag Switch \"Disable non-observer late joining\" is ON. Only Observers may join!
"
-
- dat += ""
-
- for(var/datum/job/job as anything in SSjob.joinable_occupations)
- count++
- var/J_title = html_encode(job.title)
- var/J_opPos = html_encode(job.total_positions - (job.total_positions - job.current_positions))
- var/J_totPos = html_encode(job.total_positions)
- dat += "| [J_title]: | [J_opPos]/[job.total_positions < 0 ? " (unlimited)" : J_totPos]"
-
- dat += " | "
- dat += ""
- if(job.total_positions >= 0)
- dat += "Custom | "
- dat += "Add 1 | "
- if(job.total_positions > job.current_positions)
- dat += "Remove | "
- else
- dat += "Remove | "
- dat += "Unlimit | "
- else
- dat += "Limit"
-
- browser.height = min(100 + count * 20, 650)
- browser.set_content(dat.Join())
- browser.open()
-
/datum/admins/proc/dynamic_mode_options(mob/user)
var/dat = {"
Dynamic Mode Options
@@ -882,16 +183,6 @@
set name = "Create or modify area"
create_area(usr)
-//
-//
-//ALL DONE
-//*********************************************************************************************************
-//TO-DO:
-//
-//
-
-//RIP ferry snowflakes
-
//Kicks all the clients currently in the lobby. The second parameter (kick_only_afk) determins if an is_afk() check is ran, or if all clients are kicked
//defaults to kicking everyone (afk + non afk clients in the lobby)
//returns a list of ckeys of the kicked clients
@@ -959,31 +250,3 @@
"Admin login: [key_name(src)]")
if(string)
message_admins("[string]")
-
-/datum/admins/proc/show_lag_switch_panel()
- set category = "Admin.Game"
- set name = "Show Lag Switches"
- set desc="Display the controls for drastic lag mitigation measures."
-
- if(!SSlag_switch.initialized)
- to_chat(usr, span_notice("The Lag Switch subsystem has not yet been initialized."))
- return
- if(!check_rights())
- return
-
- var/list/dat = list("Lag SwitchesLag (Reduction) Switches
")
- dat += "Automatic Trigger: [SSlag_switch.auto_switch ? "On" : "Off"]
"
- dat += "Population Threshold: [SSlag_switch.trigger_pop]
"
- dat += "Slowmode Cooldown (toggle On/Off below): [SSlag_switch.slowmode_cooldown/10] seconds
"
- dat += "
SET ALL MEASURES: ON | OFF
"
- dat += "
Disable ghosts zoom and t-ray verbs (except staff): [SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] ? "On" : "Off"]
"
- dat += "Disable late joining: [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "On" : "Off"]
"
- dat += "
============! MAD GHOSTS ZONE !============
"
- dat += "Disable deadmob keyLoop (except staff, informs dchat): [SSlag_switch.measures[DISABLE_DEAD_KEYLOOP] ? "On" : "Off"]
"
- dat += "==========================================
"
- dat += "
Measures below can be bypassed with a special trait
"
- dat += "Slowmode say verb (informs world): [SSlag_switch.measures[SLOWMODE_SAY] ? "On" : "Off"]
"
- dat += "Disable runechat: [SSlag_switch.measures[DISABLE_RUNECHAT] ? "On" : "Off"] - trait applies to speaker
"
- dat += "Disable examine icons: [SSlag_switch.measures[DISABLE_USR_ICON2HTML] ? "On" : "Off"] - trait applies to examiner
"
- dat += ""
- usr << browse(dat.Join(), "window=lag_switch_panel;size=420x420")
diff --git a/code/modules/admin/verbs/admin.dm b/code/modules/admin/verbs/admin.dm
new file mode 100644
index 00000000000..8d5bd52beb3
--- /dev/null
+++ b/code/modules/admin/verbs/admin.dm
@@ -0,0 +1,278 @@
+// Admin Tab - Admin Verbs
+
+/client/proc/show_tip()
+ set category = "Admin"
+ set name = "Show Tip"
+ set desc = "Sends a tip (that you specify) to all players. After all \
+ you're the experienced player here."
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/input = input(usr, "Please specify your tip that you want to send to the players.", "Tip", "") as message|null
+ if(!input)
+ return
+
+ if(!SSticker)
+ return
+
+ SSticker.selected_tip = input
+
+ // If we've already tipped, then send it straight away.
+ if(SSticker.tipped)
+ SSticker.send_tip_of_the_round()
+
+ message_admins("[key_name_admin(usr)] sent a tip of the round.")
+ log_admin("[key_name(usr)] sent \"[input]\" as the Tip of the Round.")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Tip")
+
+/datum/admins/proc/announce()
+ set category = "Admin"
+ set name = "Announce"
+ set desc="Announce your desires to the world"
+ if(!check_rights(0))
+ return
+
+ var/message = input("Global message to send:", "Admin Announce", null, null) as message
+ if(message)
+ if(!check_rights(R_SERVER,0))
+ message = adminscrub(message,500)
+ to_chat(world, "[span_adminnotice("[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:")]\n \t [message]", confidential = TRUE)
+ log_admin("Announce: [key_name(usr)] : [message]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/unprison(mob/M in GLOB.mob_list)
+ set category = "Admin"
+ set name = "Unprison"
+ if (is_centcom_level(M.z))
+ SSjob.SendToLateJoin(M)
+ message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]")
+ log_admin("[key_name(usr)] has unprisoned [key_name(M)]")
+ else
+ tgui_alert(usr,"[M.name] is not prisoned.")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Unprison") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are.
+ set category = "Admin"
+ set name = "Player Playtime"
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!CONFIG_GET(flag/use_exp_tracking))
+ to_chat(usr, span_warning("Tracking is disabled in the server configuration file."), confidential = TRUE)
+ return
+
+ var/list/msg = list()
+ msg += "Playtime ReportPlaytime:
"
+ var/list/clients_list_copy = GLOB.clients.Copy()
+ sortList(clients_list_copy)
+ for(var/client/C in clients_list_copy)
+ msg += "- - [key_name_admin(C)]: " + C.get_exp_living() + "
"
+ msg += "
"
+ src << browse(msg.Join(), "window=Player_playtime_check")
+
+/client/proc/trigger_centcom_recall()
+ if(!check_rights(R_ADMIN))
+ return
+ var/message = pick(GLOB.admiral_messages)
+ message = input("Enter message from the on-call admiral to be put in the recall report.", "Admiral Message", message) as text|null
+
+ if(!message)
+ return
+
+ message_admins("[key_name_admin(usr)] triggered a CentCom recall, with the admiral message of: [message]")
+ log_game("[key_name(usr)] triggered a CentCom recall, with the message of: [message]")
+ SSshuttle.centcom_recall(SSshuttle.emergency.timer, message)
+
+/datum/admins/proc/cmd_show_exp_panel(client/client_to_check)
+ if(!check_rights(R_ADMIN))
+ return
+ if(!client_to_check)
+ to_chat(usr, span_danger("ERROR: Client not found."), confidential = TRUE)
+ return
+ if(!CONFIG_GET(flag/use_exp_tracking))
+ to_chat(usr, span_warning("Tracking is disabled in the server configuration file."), confidential = TRUE)
+ return
+
+ new /datum/job_report_menu(client_to_check, usr)
+
+/datum/admins/proc/toggle_exempt_status(client/C)
+ if(!check_rights(R_ADMIN))
+ return
+ if(!C)
+ to_chat(usr, span_danger("ERROR: Client not found."), confidential = TRUE)
+ return
+
+ if(!C.set_db_player_flags())
+ to_chat(usr, span_danger("ERROR: Unable read player flags from database. Please check logs."), confidential = TRUE)
+ var/dbflags = C.prefs.db_flags
+ var/newstate = FALSE
+ if(dbflags & DB_FLAG_EXEMPT)
+ newstate = FALSE
+ else
+ newstate = TRUE
+
+ if(C.update_flag_db(DB_FLAG_EXEMPT, newstate))
+ to_chat(usr, span_danger("ERROR: Unable to update player flags. Please check logs."), confidential = TRUE)
+ else
+ message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
+ log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
+
+/// Allow admin to add or remove traits of datum
+/datum/admins/proc/modify_traits(datum/D)
+ if(!D)
+ return
+
+ var/add_or_remove = input("Remove/Add?", "Trait Remove/Add") as null|anything in list("Add","Remove")
+ if(!add_or_remove)
+ return
+ var/list/available_traits = list()
+
+ switch(add_or_remove)
+ if("Add")
+ for(var/key in GLOB.traits_by_type)
+ if(istype(D,key))
+ available_traits += GLOB.traits_by_type[key]
+ if("Remove")
+ if(!GLOB.trait_name_map)
+ GLOB.trait_name_map = generate_trait_name_map()
+ for(var/trait in D.status_traits)
+ var/name = GLOB.trait_name_map[trait] || trait
+ available_traits[name] = trait
+
+ var/chosen_trait = input("Select trait to modify", "Trait") as null|anything in sortList(available_traits)
+ if(!chosen_trait)
+ return
+ chosen_trait = available_traits[chosen_trait]
+
+ var/source = "adminabuse"
+ 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.
+ D.AddElement(/datum/element/movetype_handler)
+ ADD_TRAIT(D,chosen_trait,source)
+ if("Remove")
+ var/specific = input("All or specific source ?", "Trait Remove/Add") as null|anything in list("All","Specific")
+ if(!specific)
+ return
+ switch(specific)
+ if("All")
+ source = null
+ if("Specific")
+ source = input("Source to be removed","Trait Remove/Add") as null|anything in sortList(D.status_traits[chosen_trait])
+ if(!source)
+ return
+ REMOVE_TRAIT(D,chosen_trait,source)
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/client/proc/cmd_admin_drop_everything(mob/M in GLOB.mob_list)
+ set category = null
+ set name = "Drop Everything"
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/confirm = tgui_alert(usr, "Make [M] drop everything?", "Message", list("Yes", "No"))
+ if(confirm != "Yes")
+ return
+
+ for(var/obj/item/W in M)
+ if(!M.dropItemToGround(W))
+ qdel(W)
+ M.regenerate_icons()
+
+ log_admin("[key_name(usr)] made [key_name(M)] drop everything!")
+ var/msg = "[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] drop everything!"
+ message_admins(msg)
+ admin_ticket_log(M, msg)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Drop Everything") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/proc/cmd_admin_mute(whom, mute_type, automute = 0)
+ if(!whom)
+ return
+
+ var/muteunmute
+ var/mute_string
+ var/feedback_string
+ switch(mute_type)
+ if(MUTE_IC)
+ mute_string = "IC (say and emote)"
+ feedback_string = "IC"
+ if(MUTE_OOC)
+ mute_string = "OOC"
+ feedback_string = "OOC"
+ if(MUTE_PRAY)
+ mute_string = "pray"
+ feedback_string = "Pray"
+ if(MUTE_ADMINHELP)
+ mute_string = "adminhelp, admin PM and ASAY"
+ feedback_string = "Adminhelp"
+ if(MUTE_DEADCHAT)
+ mute_string = "deadchat and DSAY"
+ feedback_string = "Deadchat"
+ if(MUTE_ALL)
+ mute_string = "everything"
+ feedback_string = "Everything"
+ else
+ return
+
+ var/client/C
+ if(istype(whom, /client))
+ C = whom
+ else if(istext(whom))
+ C = GLOB.directory[whom]
+ else
+ return
+
+ var/datum/preferences/P
+ if(C)
+ P = C.prefs
+ else
+ P = GLOB.preferences_datums[whom]
+ if(!P)
+ return
+
+ if(automute)
+ if(!CONFIG_GET(flag/automute_on))
+ return
+ else
+ if(!check_rights())
+ return
+
+ if(automute)
+ muteunmute = "auto-muted"
+ P.muted |= mute_type
+ log_admin("SPAM AUTOMUTE: [muteunmute] [key_name(whom)] from [mute_string]")
+ message_admins("SPAM AUTOMUTE: [muteunmute] [key_name_admin(whom)] from [mute_string].")
+ if(C)
+ to_chat(C, "You have been [muteunmute] from [mute_string] by the SPAM AUTOMUTE system. Contact an admin.", confidential = TRUE)
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Auto Mute [feedback_string]", "1")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ return
+
+ if(P.muted & mute_type)
+ muteunmute = "unmuted"
+ P.muted &= ~mute_type
+ else
+ muteunmute = "muted"
+ P.muted |= mute_type
+
+ log_admin("[key_name(usr)] has [muteunmute] [key_name(whom)] from [mute_string]")
+ message_admins("[key_name_admin(usr)] has [muteunmute] [key_name_admin(whom)] from [mute_string].")
+ if(C)
+ to_chat(C, "You have been [muteunmute] from [mute_string] by [key_name(usr, include_name = FALSE)].", confidential = TRUE)
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Mute [feedback_string]", "[P.muted & mute_type]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/proc/immerse_player(mob/living/carbon/target, toggle=TRUE, remove=FALSE)
+ var/list/immersion_components = list(/datum/component/manual_breathing, /datum/component/manual_blinking)
+
+ for(var/immersies in immersion_components)
+ var/has_component = target.GetComponent(immersies)
+
+ if(has_component && (toggle || remove))
+ qdel(has_component)
+ else if(toggle || !remove)
+ target.AddComponent(immersies)
+
+/proc/mass_immerse(remove=FALSE)
+ for(var/mob/living/carbon/M in GLOB.mob_list)
+ immerse_player(M, toggle=FALSE, remove=remove)
diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm
new file mode 100644
index 00000000000..c67d81cd161
--- /dev/null
+++ b/code/modules/admin/verbs/adminevents.dm
@@ -0,0 +1,507 @@
+// Admin Tab - Event Verbs
+
+/client/proc/cmd_admin_subtle_message(mob/M in GLOB.mob_list)
+ set category = "Admin.Events"
+ set name = "Subtle Message"
+
+ if(!ismob(M))
+ return
+ if(!check_rights(R_ADMIN))
+ return
+
+ message_admins("[key_name_admin(src)] has started answering [ADMIN_LOOKUPFLW(M)]'s prayer.")
+ var/msg = input("Message:", text("Subtle PM to [M.key]")) as text|null
+
+ if(!msg)
+ message_admins("[key_name_admin(src)] decided not to answer [ADMIN_LOOKUPFLW(M)]'s prayer")
+ return
+ if(usr)
+ if (usr.client)
+ if(usr.client.holder)
+ to_chat(M, "You hear a voice in your head... [msg]", confidential = TRUE)
+
+ log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]")
+ msg = span_adminnotice(" SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]")
+ message_admins(msg)
+ admin_ticket_log(M, msg)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Subtle Message") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list)
+ set category = "Admin.Events"
+ set name = "Headset Message"
+
+ admin_headset_message(M)
+
+/client/proc/admin_headset_message(mob/M in GLOB.mob_list, sender = null)
+ var/mob/living/carbon/human/H = M
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!istype(H))
+ to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human", confidential = TRUE)
+ return
+ if(!istype(H.ears, /obj/item/radio/headset))
+ to_chat(usr, "The person you are trying to contact is not wearing a headset.", confidential = TRUE)
+ return
+
+ if (!sender)
+ sender = input("Who is the message from?", "Sender") as null|anything in list(RADIO_CHANNEL_CENTCOM,RADIO_CHANNEL_SYNDICATE)
+ if(!sender)
+ return
+
+ message_admins("[key_name_admin(src)] has started answering [key_name_admin(H)]'s [sender] request.")
+ var/input = input("Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from [sender]", "") as text|null
+ if(!input)
+ message_admins("[key_name_admin(src)] decided not to answer [key_name_admin(H)]'s [sender] request.")
+ return
+
+ log_directed_talk(mob, H, input, LOG_ADMIN, "reply")
+ message_admins("[key_name_admin(src)] replied to [key_name_admin(H)]'s [sender] message with: \"[input]\"")
+ to_chat(H, span_hear("You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from [sender == "Syndicate" ? "your benefactor" : "Central Command"]. Message as follows[sender == "Syndicate" ? ", agent." : ":"] [input]. Message ends.\""), confidential = TRUE)
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Headset Message") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_world_narrate()
+ set category = "Admin.Events"
+ set name = "Global Narrate"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text|null
+
+ if (!msg)
+ return
+ to_chat(world, "[msg]", confidential = TRUE)
+ log_admin("GlobalNarrate: [key_name(usr)] : [msg]")
+ message_admins(span_adminnotice("[key_name_admin(usr)] Sent a global narrate"))
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Global Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_local_narrate(atom/A)
+ set category = "Admin.Events"
+ set name = "Local Narrate"
+
+ if(!check_rights(R_ADMIN))
+ return
+ if(!A)
+ return
+ var/range = input("Range:", "Narrate to mobs within how many tiles:", 7) as num|null
+ if(!range)
+ return
+ var/msg = input("Message:", text("Enter the text you wish to appear to everyone within view:")) as text|null
+ if (!msg)
+ return
+ for(var/mob/M in view(range,A))
+ to_chat(M, msg, confidential = TRUE)
+
+ log_admin("LocalNarrate: [key_name(usr)] at [AREACOORD(A)]: [msg]")
+ message_admins(span_adminnotice(" LocalNarrate: [key_name_admin(usr)] at [ADMIN_VERBOSEJMP(A)]: [msg]
"))
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Local Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_direct_narrate(mob/M)
+ set category = "Admin.Events"
+ set name = "Direct Narrate"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!M)
+ M = input("Direct narrate to whom?", "Active Players") as null|anything in GLOB.player_list
+
+ if(!M)
+ return
+
+ var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text|null
+
+ if( !msg )
+ return
+
+ to_chat(M, msg, confidential = TRUE)
+ log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]")
+ msg = span_adminnotice(" DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]
")
+ message_admins(msg)
+ admin_ticket_log(M, msg)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Direct Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_add_freeform_ai_law()
+ set category = "Admin.Events"
+ set name = "Add Custom AI law"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
+ if(!input)
+ return
+
+ log_admin("Admin [key_name(usr)] has added a new AI law - [input]")
+ message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]")
+
+ var/show_log = tgui_alert(usr, "Show ion message?", "Message", list("Yes", "No"))
+ var/announce_ion_laws = (show_log == "Yes" ? 100 : 0)
+
+ var/datum/round_event/ion_storm/add_law_only/ion = new()
+ ion.announceChance = announce_ion_laws
+ ion.ionMessage = input
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Add Custom AI Law") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/admin_call_shuttle()
+ set category = "Admin.Events"
+ set name = "Call Shuttle"
+
+ if(EMERGENCY_AT_LEAST_DOCKED)
+ return
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/confirm = tgui_alert(usr, "You sure?", "Confirm", list("Yes", "Yes (No Recall)", "No"))
+ switch(confirm)
+ if(null, "No")
+ return
+ if("Yes (No Recall)")
+ SSshuttle.adminEmergencyNoRecall = TRUE
+ SSshuttle.emergency.mode = SHUTTLE_IDLE
+
+ SSshuttle.emergency.request()
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Call Shuttle") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ log_admin("[key_name(usr)] admin-called the emergency shuttle.")
+ message_admins(span_adminnotice("[key_name_admin(usr)] admin-called the emergency shuttle[confirm == "Yes (No Recall)" ? " (non-recallable)" : ""]."))
+ return
+
+/client/proc/admin_cancel_shuttle()
+ set category = "Admin.Events"
+ set name = "Cancel Shuttle"
+ if(!check_rights(0))
+ return
+ if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+
+ if(SSshuttle.adminEmergencyNoRecall)
+ SSshuttle.adminEmergencyNoRecall = FALSE
+
+ if(EMERGENCY_AT_LEAST_DOCKED)
+ return
+
+ SSshuttle.emergency.cancel()
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Cancel Shuttle") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ log_admin("[key_name(usr)] admin-recalled the emergency shuttle.")
+ message_admins(span_adminnotice("[key_name_admin(usr)] admin-recalled the emergency shuttle."))
+
+ return
+
+/client/proc/admin_disable_shuttle()
+ set category = "Admin.Events"
+ set name = "Disable Shuttle"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSshuttle.emergency.mode == SHUTTLE_DISABLED)
+ to_chat(usr, span_warning("Error, shuttle is already disabled."))
+ return
+
+ if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+
+ message_admins(span_adminnotice("[key_name_admin(usr)] disabled the shuttle."))
+
+ SSshuttle.lastMode = SSshuttle.emergency.mode
+ SSshuttle.lastCallTime = SSshuttle.emergency.timeLeft(1)
+ SSshuttle.adminEmergencyNoRecall = TRUE
+ SSshuttle.emergency.setTimer(0)
+ SSshuttle.emergency.mode = SHUTTLE_DISABLED
+ priority_announce("Warning: Emergency Shuttle uplink failure, shuttle disabled until further notice.", "Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
+
+/client/proc/admin_enable_shuttle()
+ set category = "Admin.Events"
+ set name = "Enable Shuttle"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSshuttle.emergency.mode != SHUTTLE_DISABLED)
+ to_chat(usr, span_warning("Error, shuttle not disabled."))
+ return
+
+ if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+
+ message_admins(span_adminnotice("[key_name_admin(usr)] enabled the emergency shuttle."))
+ SSshuttle.adminEmergencyNoRecall = FALSE
+ SSshuttle.emergencyNoRecall = FALSE
+ if(SSshuttle.lastMode == SHUTTLE_DISABLED) //If everything goes to shit, fix it.
+ SSshuttle.lastMode = SHUTTLE_IDLE
+
+ SSshuttle.emergency.mode = SSshuttle.lastMode
+ if(SSshuttle.lastCallTime < 10 SECONDS && SSshuttle.lastMode != SHUTTLE_IDLE)
+ SSshuttle.lastCallTime = 10 SECONDS //Make sure no insta departures.
+ SSshuttle.emergency.setTimer(SSshuttle.lastCallTime)
+ priority_announce("Warning: Emergency Shuttle uplink reestablished, shuttle enabled.", "Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
+
+/client/proc/toggle_nuke(obj/machinery/nuclearbomb/N in GLOB.nuke_list)
+ set category = "Admin.Events"
+ set name = "Toggle Nuke"
+ set popup_menu = FALSE
+ if(!check_rights(R_DEBUG))
+ return
+
+ if(!N.timing)
+ var/newtime = input(usr, "Set activation timer.", "Activate Nuke", "[N.timer_set]") as num|null
+ if(!newtime)
+ return
+ N.timer_set = newtime
+ N.set_safety()
+ N.set_active()
+
+ log_admin("[key_name(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [AREACOORD(N)].")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(N)].")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[N.timing]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/access_news_network() //MARKER
+ set category = "Admin.Events"
+ set name = "Access Newscaster Network"
+ set desc = "Allows you to view, add and edit news feeds."
+
+ if (!istype(src, /datum/admins))
+ src = usr.client.holder
+ if (!istype(src, /datum/admins))
+ to_chat(usr, "Error: you are not an admin!", confidential = TRUE)
+ return
+ var/dat
+ dat = text("Admin NewscasterAdmin Newscaster Unit
")
+
+ switch(admincaster_screen)
+ if(0)
+ dat += "Welcome to the admin newscaster.
Here you can add, edit and censor every newspiece on the network."
+ dat += "
Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units."
+ dat += "
Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!"
+ if(GLOB.news_network.wanted_issue.active)
+ dat+= "
Read Wanted Issue"
+ dat+= "
Create Feed Channel"
+ dat+= "
View Feed Channels"
+ dat+= "
Submit new Feed story"
+ dat+= "
Exit"
+ var/wanted_already = 0
+ if(GLOB.news_network.wanted_issue.active)
+ wanted_already = 1
+ dat+="
Feed Security functions:
"
+ dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue"
+ dat+="
Censor Feed Stories"
+ dat+="
Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel)."
+ dat+="
The newscaster recognises you as:
[src.admin_signature]"
+ if(1)
+ dat+= "Station Feed Channels
"
+ if( !length(GLOB.news_network.network_channels) )
+ dat+="No active channels found..."
+ else
+ for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
+ if(CHANNEL.is_admin_channel)
+ dat+="[CHANNEL.channel_name]
"
+ else
+ dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
"
+ dat+="
Refresh"
+ dat+="
Back"
+ if(2)
+ dat+="Creating new Feed Channel..."
+ dat+="
Channel Name: [src.admincaster_feed_channel.channel_name]
"
+ dat+="Channel Author: [src.admin_signature]
"
+ dat+="Will Accept Public Feeds: [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]
"
+ dat+="
Submit
Cancel
"
+ if(3)
+ dat+="Creating new Feed Message..."
+ dat+="
Receiving Channel: [src.admincaster_feed_channel.channel_name]
" //MARK
+ dat+="Message Author: [src.admin_signature]
"
+ dat+="Message Body: [src.admincaster_feed_message.returnBody(-1)]
"
+ dat+="
Submit
Cancel
"
+ if(4)
+ dat+="Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].
"
+ dat+="
Return
"
+ if(5)
+ dat+="Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.
"
+ dat+="
Return
"
+ if(6)
+ dat+="ERROR: Could not submit Feed story to Network.
"
+ if(src.admincaster_feed_channel.channel_name=="")
+ dat+="Invalid receiving channel name.
"
+ if(src.admincaster_feed_message.returnBody(-1) == "" || src.admincaster_feed_message.returnBody(-1) == "\[REDACTED\]")
+ dat+="Invalid message body.
"
+ dat+="
Return
"
+ if(7)
+ dat+="ERROR: Could not submit Feed Channel to Network.
"
+ if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]")
+ dat+="Invalid channel name.
"
+ var/check = 0
+ for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
+ if(FC.channel_name == src.admincaster_feed_channel.channel_name)
+ check = 1
+ break
+ if(check)
+ dat+="Channel name already in use.
"
+ dat+="
Return
"
+ if(9)
+ dat+="[admincaster_feed_channel.channel_name]: \[created by: [admincaster_feed_channel.returnAuthor(-1)]\]
"
+ if(src.admincaster_feed_channel.censored)
+ dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
"
+ dat+="No further feed story additions are allowed while the D-Notice is in effect.
"
+ else
+ if( !length(src.admincaster_feed_channel.messages) )
+ dat+="No feed messages found in channel...
"
+ else
+ var/i = 0
+ for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
+ i++
+ dat+="-[MESSAGE.returnBody(-1)]
"
+ if(MESSAGE.img)
+ usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
+ dat+="
"
+ dat+="\[Story by [MESSAGE.returnAuthor(-1)]\]
"
+ dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]:
"
+ for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments)
+ dat+="[comment.body]
[comment.author] [comment.time_stamp]
"
+ dat+="
"
+ dat+="
Refresh"
+ dat+="
Back"
+ if(10)
+ dat+="Nanotrasen Feed Censorship Tool
"
+ dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
"
+ dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it."
+ dat+="
Select Feed channel to get Stories from:
"
+ if(!length(GLOB.news_network.network_channels))
+ dat+="No feed channels found active...
"
+ else
+ for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
+ dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
"
+ dat+="
Cancel"
+ if(11)
+ dat+="Nanotrasen D-Notice Handler
"
+ dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's"
+ dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed"
+ dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
"
+ if(!length(GLOB.news_network.network_channels))
+ dat+="No feed channels found active...
"
+ else
+ for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
+ dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
"
+
+ dat+="
Back"
+ if(12)
+ dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
"
+ dat+="[(src.admincaster_feed_channel.authorCensor) ? ("Undo Author censorship") : ("Censor channel Author")]
"
+
+ if( !length(src.admincaster_feed_channel.messages) )
+ dat+="No feed messages found in channel...
"
+ else
+ for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
+ dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
"
+ dat+="[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]
"
+ dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
"
+ for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments)
+ dat+="[comment.body] X
[comment.author] [comment.time_stamp]
"
+ dat+="
Back"
+ if(13)
+ dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
"
+ dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
"
+ if(src.admincaster_feed_channel.censored)
+ dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
"
+ dat+="No further feed story additions are allowed while the D-Notice is in effect.
"
+ else
+ if( !length(src.admincaster_feed_channel.messages) )
+ dat+="No feed messages found in channel...
"
+ else
+ for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
+ dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
"
+ dat+="
Back"
+ if(14)
+ dat+="Wanted Issue Handler:"
+ var/wanted_already = 0
+ var/end_param = 1
+ if(GLOB.news_network.wanted_issue.active)
+ wanted_already = 1
+ end_param = 2
+ if(wanted_already)
+ dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below."
+ dat+="
"
+ dat+="Criminal Name: [src.admincaster_wanted_message.criminal]
"
+ dat+="Description: [src.admincaster_wanted_message.body]
"
+ if(wanted_already)
+ dat+="Wanted Issue created by:[GLOB.news_network.wanted_issue.scannedUser]
"
+ else
+ dat+="Wanted Issue will be created under prosecutor:[src.admin_signature]
"
+ dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]"
+ if(wanted_already)
+ dat+="
Take down Issue"
+ dat+="
Cancel"
+ if(15)
+ dat+="Wanted issue for [src.admincaster_wanted_message.criminal] is now in Network Circulation.
"
+ dat+="
Return
"
+ if(16)
+ dat+="ERROR: Wanted Issue rejected by Network.
"
+ if(src.admincaster_wanted_message.criminal =="" || src.admincaster_wanted_message.criminal == "\[REDACTED\]")
+ dat+="Invalid name for person wanted.
"
+ if(src.admincaster_wanted_message.body == "" || src.admincaster_wanted_message.body == "\[REDACTED\]")
+ dat+="Invalid description.
"
+ dat+="
Return
"
+ if(17)
+ dat+="Wanted Issue successfully deleted from Circulation
"
+ dat+="
Return
"
+ if(18)
+ dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [GLOB.news_network.wanted_issue.scannedUser]\]
"
+ dat+="Criminal: [GLOB.news_network.wanted_issue.criminal]
"
+ dat+="Description: [GLOB.news_network.wanted_issue.body]
"
+ dat+="Photo:: "
+ if(GLOB.news_network.wanted_issue.img)
+ usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png")
+ dat+="
"
+ else
+ dat+="None"
+ dat+="
Back
"
+ if(19)
+ dat+="Wanted issue for [src.admincaster_wanted_message.criminal] successfully edited.
"
+ dat+="
Return
"
+ else
+ dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"
+
+ usr << browse(dat, "window=admincaster_main;size=400x600")
+ onclose(usr, "admincaster_main")
+
+/client/proc/admin_change_sec_level()
+ set category = "Admin.Events"
+ set name = "Set Security Level"
+ set desc = "Changes the security level. Announcement only, i.e. setting to Delta won't activate nuke"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/level = input("Select security level to change to","Set Security Level") as null|anything in list("green","blue","red","delta")
+ if(level)
+ set_security_level(level)
+
+ log_admin("[key_name(usr)] changed the security level to [level]")
+ message_admins("[key_name_admin(usr)] changed the security level to [level]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Security Level [capitalize(level)]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/run_weather()
+ set category = "Admin.Events"
+ set name = "Run Weather"
+ set desc = "Triggers a weather on the z-level you choose."
+
+ if(!holder)
+ return
+
+ var/weather_type = input("Choose a weather", "Weather") as null|anything in sortList(subtypesof(/datum/weather), /proc/cmp_typepaths_asc)
+ if(!weather_type)
+ return
+
+ var/turf/T = get_turf(mob)
+ var/z_level = input("Z-Level to target?", "Z-Level", T?.z) as num|null
+ if(!isnum(z_level))
+ return
+
+ SSweather.run_weather(weather_type, z_level)
+
+ message_admins("[key_name_admin(usr)] started weather of type [weather_type] on the z-level [z_level].")
+ log_admin("[key_name(usr)] started weather of type [weather_type] on the z-level [z_level].")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Run Weather")
diff --git a/code/modules/admin/verbs/adminfun.dm b/code/modules/admin/verbs/adminfun.dm
new file mode 100644
index 00000000000..4e89794a8b7
--- /dev/null
+++ b/code/modules/admin/verbs/adminfun.dm
@@ -0,0 +1,253 @@
+// Admin Tab - Fun Verbs
+
+/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world)
+ set category = "Admin.Fun"
+ set name = "Explosion"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null
+ if(devastation == null)
+ return
+ var/heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null
+ if(heavy == null)
+ return
+ var/light = input("Range of light impact. -1 to none", text("Input")) as num|null
+ if(light == null)
+ return
+ var/flash = input("Range of flash. -1 to none", text("Input")) as num|null
+ if(flash == null)
+ return
+ var/flames = input("Range of flames. -1 to none", text("Input")) as num|null
+ if(flames == null)
+ return
+
+ if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1) || (flames != -1))
+ if ((devastation > 20) || (heavy > 20) || (light > 20) || (flames > 20))
+ if (tgui_alert(usr, "Are you sure you want to do this? It will laaag.", "Confirmation", list("Yes", "No")) == "No")
+ return
+
+ explosion(O, devastation, heavy, light, flames, flash)
+ log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]")
+ message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Explosion") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world)
+ set category = "Admin.Fun"
+ set name = "EM Pulse"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
+ if(heavy == null)
+ return
+ var/light = input("Range of light pulse.", text("Input")) as num|null
+ if(light == null)
+ return
+
+ if (heavy || light)
+ empulse(O, heavy, light)
+ log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
+ message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_gib(mob/victim in GLOB.mob_list)
+ set category = "Admin.Fun"
+ set name = "Gib"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/confirm = tgui_alert(usr, "Drop a brain?", "Confirm", list("Yes", "No","Cancel"))
+ if(confirm == "Cancel")
+ return
+ //Due to the delay here its easy for something to have happened to the mob
+ if(!victim)
+ return
+
+ log_admin("[key_name(usr)] has gibbed [key_name(victim)]")
+ message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(victim)]")
+
+ if(isobserver(victim))
+ new /obj/effect/gibspawner/generic(get_turf(victim))
+ return
+
+ var/mob/living/living_victim = victim
+ if (istype(living_victim))
+ if(confirm == "Yes")
+ living_victim.gib()
+ else
+ living_victim.gib(TRUE)
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Gib") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_gib_self()
+ set name = "Gibself"
+ set category = "Admin.Fun"
+
+ var/confirm = tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No"))
+ if(confirm == "Yes")
+ log_admin("[key_name(usr)] used gibself.")
+ message_admins(span_adminnotice("[key_name_admin(usr)] used gibself."))
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Gib Self") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+ var/mob/living/ourself = mob
+ if (istype(ourself))
+ ourself.gib(TRUE, TRUE, TRUE)
+
+/client/proc/everyone_random()
+ set category = "Admin.Fun"
+ set name = "Make Everyone Random"
+ set desc = "Make everyone have a random appearance. You can only use this before rounds!"
+
+ if(SSticker.HasRoundStarted())
+ to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!", confidential = TRUE)
+ return
+
+ var/frn = CONFIG_GET(flag/force_random_names)
+ if(frn)
+ CONFIG_SET(flag/force_random_names, FALSE)
+ message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.")
+ to_chat(usr, "Disabled.", confidential = TRUE)
+ return
+
+ var/notifyplayers = tgui_alert(usr, "Do you want to notify the players?", "Options", list("Yes", "No", "Cancel"))
+ if(notifyplayers == "Cancel")
+ return
+
+ log_admin("Admin [key_name(src)] has forced the players to have random appearances.")
+ message_admins("Admin [key_name_admin(usr)] has forced the players to have random appearances.")
+
+ if(notifyplayers == "Yes")
+ to_chat(world, span_adminnotice("Admin [usr.key] has forced the players to have completely random identities!"), confidential = TRUE)
+
+ to_chat(usr, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.", confidential = TRUE)
+
+ CONFIG_SET(flag/force_random_names, TRUE)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Make Everyone Random") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/mass_zombie_infection()
+ set category = "Admin.Fun"
+ set name = "Mass Zombie Infection"
+ set desc = "Infects all humans with a latent organ that will zombify \
+ them on death."
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/confirm = tgui_alert(usr, "Please confirm you want to add latent zombie organs in all humans?", "Confirm Zombies", list("Yes", "No"))
+ if(confirm != "Yes")
+ return
+
+ for(var/i in GLOB.human_list)
+ var/mob/living/carbon/human/H = i
+ new /obj/item/organ/zombie_infection/nodamage(H)
+
+ message_admins("[key_name_admin(usr)] added a latent zombie infection to all humans.")
+ log_admin("[key_name(usr)] added a latent zombie infection to all humans.")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Mass Zombie Infection")
+
+/client/proc/mass_zombie_cure()
+ set category = "Admin.Fun"
+ set name = "Mass Zombie Cure"
+ set desc = "Removes the zombie infection from all humans, returning them to normal."
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/confirm = tgui_alert(usr, "Please confirm you want to cure all zombies?", "Confirm Zombie Cure", list("Yes", "No"))
+ if(confirm != "Yes")
+ return
+
+ for(var/obj/item/organ/zombie_infection/nodamage/I in GLOB.zombie_infection_list)
+ qdel(I)
+
+ message_admins("[key_name_admin(usr)] cured all zombies.")
+ log_admin("[key_name(usr)] cured all zombies.")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Mass Zombie Cure")
+
+/client/proc/polymorph_all()
+ set category = "Admin.Fun"
+ set name = "Polymorph All"
+ set desc = "Applies the effects of the bolt of change to every single mob."
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/confirm = tgui_alert(usr, "Please confirm you want polymorph all mobs?", "Confirm Polymorph", list("Yes", "No"))
+ if(confirm != "Yes")
+ return
+
+ var/list/mobs = shuffle(GLOB.alive_mob_list.Copy()) // might change while iterating
+ var/who_did_it = key_name_admin(usr)
+
+ message_admins("[key_name_admin(usr)] started polymorphed all living mobs.")
+ log_admin("[key_name(usr)] polymorphed all living mobs.")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Polymorph All")
+
+ for(var/mob/living/M in mobs)
+ CHECK_TICK
+
+ if(!M)
+ continue
+
+ M.audible_message(span_hear("...wabbajack...wabbajack..."))
+ playsound(M.loc, 'sound/magic/staff_change.ogg', 50, TRUE, -1)
+
+ wabbajack(M)
+
+ message_admins("Mass polymorph started by [who_did_it] is complete.")
+
+/client/proc/smite(mob/living/target as mob)
+ set category = "Admin.Fun"
+ set name = "Smite"
+ if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
+ return
+
+ var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites
+
+ if(QDELETED(target) || !punishment)
+ return
+
+ var/smite_path = GLOB.smites[punishment]
+ var/datum/smite/smite = new smite_path
+ var/configuration_success = smite.configure(usr)
+ if (configuration_success == FALSE)
+ return
+ smite.effect(src, target)
+
+/proc/breadify(atom/movable/target)
+ var/obj/item/food/bread/plain/bread = new(get_turf(target))
+ target.forceMove(bread)
+
+/**
+ * firing_squad is a proc for the :B:erforate smite to shoot each individual bullet at them, so that we can add actual delays without sleep() nonsense
+ *
+ * Hilariously, if you drag someone away mid smite, the bullets will still chase after them from the original spot, possibly hitting other people. Too funny to fix imo
+ *
+ * Arguments:
+ * * target- guy we're shooting obviously
+ * * source_turf- where the bullet begins, preferably on a turf next to the target
+ * * body_zone- which bodypart we're aiming for, if there is one there
+ * * wound_bonus- the wounding power we're assigning to the bullet, since we don't care about the base one
+ * * damage- the damage we're assigning to the bullet, since we don't care about the base one
+ */
+/proc/firing_squad(mob/living/carbon/target, turf/source_turf, body_zone, wound_bonus, damage)
+ if(!target.get_bodypart(body_zone))
+ return
+ playsound(target, 'sound/weapons/gun/revolver/shot.ogg', 100)
+ var/obj/projectile/bullet/smite/divine_wrath = new(source_turf)
+ divine_wrath.damage = damage
+ divine_wrath.wound_bonus = wound_bonus
+ divine_wrath.original = target
+ divine_wrath.def_zone = body_zone
+ divine_wrath.spread = 0
+ divine_wrath.preparePixelProjectile(target, source_turf)
+ divine_wrath.fire()
+
+/client/proc/punish_log(whom, punishment)
+ var/msg = "[key_name_admin(src)] punished [key_name_admin(whom)] with [punishment]."
+ message_admins(msg)
+ admin_ticket_log(whom, msg)
+ log_admin("[key_name(src)] punished [key_name(whom)] with [punishment].")
diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm
new file mode 100644
index 00000000000..b2856939f29
--- /dev/null
+++ b/code/modules/admin/verbs/admingame.dm
@@ -0,0 +1,485 @@
+// Admin Tab - Game Verbs
+
+/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list)
+ set category = "Admin.Game"
+ set name = "Show Player Panel"
+ set desc="Edit player (respawn, ban, heal, etc)"
+
+ if(!check_rights())
+ return
+
+ log_admin("[key_name(usr)] checked the individual player panel for [key_name(M)][isobserver(usr)?"":" while in game"].")
+
+ if(!M)
+ to_chat(usr, span_warning("You seem to be selecting a mob that doesn't exist anymore."), confidential = TRUE)
+ return
+
+ var/body = "Options for [M.key]"
+ body += "Options panel for [M]"
+ if(M.client)
+ body += " played by [M.client] "
+ body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]"
+ if(CONFIG_GET(flag/use_exp_tracking))
+ body += "\[" + M.client.get_exp_living(FALSE) + "\]"
+
+ if(isnewplayer(M))
+ body += " Hasn't Entered Game "
+ else
+ body += " \[Heal\] "
+
+ if(M.client)
+ body += "
\[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]"
+ body += "
CentCom Galactic Ban DB: "
+ if(CONFIG_GET(string/centcom_ban_db))
+ body += "Search"
+ else
+ body += "Disabled"
+ body += "
Show related accounts by: "
+ body += "\[ CID | "
+ body += "IP \]"
+ var/full_version = "Unknown"
+ if(M.client.byond_version)
+ full_version = "[M.client.byond_version].[M.client.byond_build ? M.client.byond_build : "xxx"]"
+ body += "
\[Byond version: [full_version]\]
"
+
+
+ body += "
\[ "
+ body += "VV - "
+ if(M.mind)
+ body += "TP - "
+ body += "SKILLS - "
+ else
+ body += "Init Mind - "
+ if (iscyborg(M))
+ body += "BP - "
+ body += "PM - "
+ body += "SM - "
+ if (ishuman(M) && M.mind)
+ body += "HM - "
+ body += "FLW - "
+ //Default to client logs if available
+ var/source = LOGSRC_MOB
+ if(M.client)
+ source = LOGSRC_CLIENT
+ body += "LOGS\]
"
+
+ body += "Mob type = [M.type]
"
+
+ body += "Kick | "
+ if(M.client)
+ body += "Ban | "
+ else
+ body += "Ban | "
+
+ body += "Notes | Messages | Watchlist | "
+ if(M.client)
+ body += "| Prison | "
+ body += "\ Send back to Lobby | "
+ var/muted = M.client.prefs.muted
+ body += "
Mute: "
+ body += "\[IC | "
+ body += "OOC | "
+ body += "PRAY | "
+ body += "ADMINHELP | "
+ body += "DEADCHAT\]"
+ body += "(toggle all)"
+
+ body += "
"
+ body += "Jump to | "
+ body += "Get | "
+ body += "Send To"
+
+ body += "
"
+ body += "Traitor panel | "
+ body += "Narrate to | "
+ body += "Subtle message | "
+ body += "Play sound to | "
+ body += "Language Menu"
+
+ if (M.client)
+ if(!isnewplayer(M))
+ body += "
"
+ body += "Transformation:"
+ body += "
"
+
+ //Human
+ if(ishuman(M) && !ismonkey(M))
+ body += "Human | "
+ else
+ body += "Humanize | "
+
+ //Monkey
+ if(ismonkey(M))
+ body += "Monkeyized | "
+ else
+ body += "Monkeyize | "
+
+ //Corgi
+ if(iscorgi(M))
+ body += "Corgized | "
+ else
+ body += "Corgize | "
+
+ //AI / Cyborg
+ if(isAI(M))
+ body += "Is an AI "
+ else if(ishuman(M))
+ body += "Make AI | "
+ body += "Make Robot | "
+ body += "Make Alien | "
+ body += "Make Slime | "
+ body += "Make Blob | "
+
+ //Simple Animals
+ if(isanimal(M))
+ body += "Re-Animalize | "
+ else
+ body += "Animalize | "
+
+ body += "
"
+ body += "Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.
"
+ body += "Observer | "
+ body += "\[ Alien: Drone, "
+ body += "Hunter, "
+ body += "Sentinel, "
+ body += "Praetorian, "
+ body += "Queen, "
+ body += "Larva \] "
+ body += "Human "
+ body += "\[ slime: Baby, "
+ body += "Adult \] "
+ body += "Monkey | "
+ body += "Cyborg | "
+ body += "Cat | "
+ body += "Runtime | "
+ body += "Corgi | "
+ body += "Ian | "
+ body += "Crab | "
+ body += "Coffee | "
+ body += "\[ Construct: Juggernaut , "
+ body += "Artificer , "
+ body += "Wraith \] "
+ body += "Shade"
+ body += "
"
+
+ if (M.client)
+ body += "
"
+ body += "Other actions:"
+ body += "
"
+ body += "Forcesay | "
+ body += "Thunderdome 1 | "
+ body += "Thunderdome 2 | "
+ body += "Thunderdome Admin | "
+ body += "Thunderdome Observer | "
+ body += "Commend Behavior | "
+
+ body += "
"
+ body += ""
+
+ usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list)
+ set category = "Admin.Game"
+ set name = "Godmode"
+ if(!check_rights(R_ADMIN))
+ return
+
+ M.status_flags ^= GODMODE
+ to_chat(usr, span_adminnotice("Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]"), confidential = TRUE)
+
+ log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]")
+ var/msg = "[key_name_admin(usr)] has toggled [ADMIN_LOOKUPFLW(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]"
+ message_admins(msg)
+ admin_ticket_log(M, msg)
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Godmode", "[M.status_flags & GODMODE ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/*
+If a guy was gibbed and you want to revive him, this is a good way to do so.
+Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one.
+Traitors and the like can also be revived with the previous role mostly intact.
+/N */
+/client/proc/respawn_character()
+ set category = "Admin.Game"
+ set name = "Respawn Character"
+ set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into."
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", ""))
+ if(!input)
+ return
+
+ var/mob/dead/observer/G_found
+ for(var/mob/dead/observer/G in GLOB.player_list)
+ if(G.ckey == input)
+ G_found = G
+ break
+
+ if(!G_found)//If a ghost was not found.
+ to_chat(usr, "There is no active key like that in the game or the person is not currently a ghost.", confidential = TRUE)
+ return
+
+ if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
+ //check if they were a monkey
+ if(findtext(G_found.real_name,"monkey"))
+ if(tgui_alert(usr,"This character appears to have been a monkey. Would you like to respawn them as such?",,list("Yes","No"))=="Yes")
+ var/mob/living/carbon/human/species/monkey/new_monkey = new
+ SSjob.SendToLateJoin(new_monkey)
+ G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use
+ new_monkey.key = G_found.key
+ to_chat(new_monkey, "You have been fully respawned. Enjoy the game.", confidential = TRUE)
+ var/msg = span_adminnotice("[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy monkey.")
+ message_admins(msg)
+ admin_ticket_log(new_monkey, msg)
+ return //all done. The ghost is auto-deleted
+
+
+ //Ok, it's not a monkey. So, spawn a human.
+ var/mob/living/carbon/human/new_character = new//The mob being spawned.
+ SSjob.SendToLateJoin(new_character)
+
+ var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character.
+ if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
+ /*Try and locate a record for the person being respawned through GLOB.data_core.
+ This isn't an exact science but it does the trick more often than not.*/
+ var/id = md5("[G_found.real_name][G_found.mind.assigned_role.title]")
+
+ record_found = find_record("id", id, GLOB.data_core.locked)
+
+ if(record_found)//If they have a record we can determine a few things.
+ new_character.real_name = record_found.fields["name"]
+ new_character.gender = record_found.fields["gender"]
+ new_character.age = record_found.fields["age"]
+ new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], null, record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"])
+ else
+ new_character.randomize_human_appearance()
+ new_character.dna.update_dna_identity()
+
+ new_character.name = new_character.real_name
+
+ if(G_found.mind && !G_found.mind.active)
+ G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use
+ else
+ new_character.mind_initialize()
+ if(is_unassigned_job(new_character.mind.assigned_role))
+ new_character.mind.set_assigned_role(SSjob.GetJobType(SSjob.overflow_role))
+
+ new_character.key = G_found.key
+
+ /*
+ The code below functions with the assumption that the mob is already a traitor if they have a special role.
+ So all it does is re-equip the mob with powers and/or items. Or not, if they have no special role.
+ If they don't have a mind, they obviously don't have a special role.
+ */
+
+ //Two variables to properly announce later on.
+ var/admin = key_name_admin(src)
+ var/player_key = G_found.key
+
+ //Now for special roles and equipment.
+ var/datum/antagonist/traitor/traitordatum = new_character.mind.has_antag_datum(/datum/antagonist/traitor)
+ if(traitordatum)
+ SSjob.EquipRank(new_character, new_character.mind.assigned_role, new_character.client)
+ new_character.mind.give_uplink(silent = TRUE, antag_datum = traitordatum)
+
+ switch(new_character.mind.special_role)
+ if(ROLE_WIZARD)
+ new_character.forceMove(pick(GLOB.wizardstart))
+ var/datum/antagonist/wizard/A = new_character.mind.has_antag_datum(/datum/antagonist/wizard,TRUE)
+ A.equip_wizard()
+ if(ROLE_SYNDICATE)
+ new_character.forceMove(pick(GLOB.nukeop_start))
+ var/datum/antagonist/nukeop/N = new_character.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)
+ N.equip_op()
+ if(ROLE_NINJA)
+ var/list/ninja_spawn = list()
+ for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
+ ninja_spawn += L
+ var/datum/antagonist/ninja/ninjadatum = new_character.mind.has_antag_datum(/datum/antagonist/ninja)
+ ninjadatum.equip_space_ninja()
+ if(ninja_spawn.len)
+ new_character.forceMove(pick(ninja_spawn))
+
+ else//They may also be a cyborg or AI.
+ switch(new_character.mind.assigned_role.type)
+ if(/datum/job/cyborg)//More rigging to make em' work and check if they're traitor.
+ new_character = new_character.Robotize(TRUE)
+ if(/datum/job/ai)
+ new_character = new_character.AIize()
+ else
+ if(!traitordatum) // Already equipped there.
+ SSjob.EquipRank(new_character, new_character.mind.assigned_role, new_character.client)//Or we simply equip them.
+
+ //Announces the character on all the systems, based on the record.
+ if(!record_found && (new_character.mind.assigned_role.job_flags & JOB_CREW_MEMBER))
+ //Power to the user!
+ if(tgui_alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,list("No","Yes"))=="Yes")
+ GLOB.data_core.manifest_inject(new_character)
+
+ if(tgui_alert(new_character,"Would you like an active AI to announce this character?",,list("No","Yes"))=="Yes")
+ AnnounceArrival(new_character, new_character.mind.assigned_role.title)
+
+ var/msg = span_adminnotice("[admin] has respawned [player_key] as [new_character.real_name].")
+ message_admins(msg)
+ admin_ticket_log(new_character, msg)
+
+ to_chat(new_character, "You have been fully respawned. Enjoy the game.", confidential = TRUE)
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Respawn Character") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ return new_character
+
+/client/proc/cmd_admin_list_open_jobs()
+ set category = "Admin.Game"
+ set name = "Manage Job Slots"
+
+ if(!check_rights(R_ADMIN))
+ return
+ holder.manage_free_slots()
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Manage Job Slots") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/manage_free_slots()
+ if(!check_rights())
+ return
+ var/datum/browser/browser = new(usr, "jobmanagement", "Manage Free Slots", 520)
+ var/list/dat = list()
+ var/count = 0
+
+ if(!SSjob.initialized)
+ tgui_alert(usr, "You cannot manage jobs before the job subsystem is initialized!")
+ return
+
+ if(SSlag_switch.measures[DISABLE_NON_OBSJOBS])
+ dat += "Lag Switch \"Disable non-observer late joining\" is ON. Only Observers may join!
"
+
+ dat += ""
+
+ for(var/datum/job/job as anything in SSjob.joinable_occupations)
+ count++
+ var/J_title = html_encode(job.title)
+ var/J_opPos = html_encode(job.total_positions - (job.total_positions - job.current_positions))
+ var/J_totPos = html_encode(job.total_positions)
+ dat += "| [J_title]: | [J_opPos]/[job.total_positions < 0 ? " (unlimited)" : J_totPos]"
+
+ dat += " | "
+ dat += ""
+ if(job.total_positions >= 0)
+ dat += "Custom | "
+ dat += "Add 1 | "
+ if(job.total_positions > job.current_positions)
+ dat += "Remove | "
+ else
+ dat += "Remove | "
+ dat += "Unlimit | "
+ else
+ dat += "Limit"
+
+ browser.height = min(100 + count * 20, 650)
+ browser.set_content(dat.Join())
+ browser.open()
+
+/client/proc/toggle_view_range()
+ set category = "Admin.Game"
+ set name = "Change View Range"
+ set desc = "switches between 1x and custom views"
+
+ if(view_size.getView() == view_size.default)
+ view_size.setTo(input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,37) - 7)
+ else
+ view_size.resetToDefault(getScreenSize(prefs.widescreenpref))
+
+ log_admin("[key_name(usr)] changed their view range to [view].")
+ //message_admins("\blue [key_name_admin(usr)] changed their view range to [view].") //why? removed by order of XSI
+
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Change View Range", "[view]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/toggle_combo_hud()
+ set category = "Admin.Game"
+ set name = "Toggle Combo HUD"
+ set desc = "Toggles the Admin Combo HUD (antag, sci, med, eng)"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/adding_hud = !has_antag_hud()
+
+ for(var/hudtype in list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED)) // add data huds
+ var/datum/atom_hud/H = GLOB.huds[hudtype]
+ (adding_hud) ? H.add_hud_to(usr) : H.remove_hud_from(usr)
+ for(var/datum/atom_hud/antag/H in GLOB.huds) // add antag huds
+ (adding_hud) ? H.add_hud_to(usr) : H.remove_hud_from(usr)
+
+ if(prefs.toggles & COMBOHUD_LIGHTING)
+ if(adding_hud)
+ mob.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
+ else
+ mob.lighting_alpha = initial(mob.lighting_alpha)
+
+ mob.update_sight()
+
+ to_chat(usr, "You toggled your admin combo HUD [adding_hud ? "ON" : "OFF"].", confidential = TRUE)
+ message_admins("[key_name_admin(usr)] toggled their admin combo HUD [adding_hud ? "ON" : "OFF"].")
+ log_admin("[key_name(usr)] toggled their admin combo HUD [adding_hud ? "ON" : "OFF"].")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Combo HUD", "[adding_hud ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/has_antag_hud()
+ var/datum/atom_hud/A = GLOB.huds[ANTAG_HUD_TRAITOR]
+ return A.hudusers[mob]
+
+/datum/admins/proc/show_traitor_panel(mob/target_mob in GLOB.mob_list)
+ set category = "Admin.Game"
+ set desc = "Edit mobs's memory and role"
+ set name = "Show Traitor Panel"
+ var/datum/mind/target_mind = target_mob.mind
+ if(!target_mind)
+ to_chat(usr, "This mob has no mind!", confidential = TRUE)
+ return
+ if(!istype(target_mob) && !istype(target_mind))
+ to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
+ return
+ target_mind.traitor_panel()
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/show_skill_panel(target)
+ set category = "Admin.Game"
+ set desc = "Edit mobs's experience and skill levels"
+ set name = "Show Skill Panel"
+ var/datum/mind/target_mind
+ if(ismob(target))
+ var/mob/target_mob = target
+ target_mind = target_mob.mind
+ else if (istype(target, /datum/mind))
+ target_mind = target
+ else
+ to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
+ return
+ var/datum/skill_panel/SP = new(usr, target_mind)
+ SP.ui_interact(usr)
+
+/datum/admins/proc/show_lag_switch_panel()
+ set category = "Admin.Game"
+ set name = "Show Lag Switches"
+ set desc="Display the controls for drastic lag mitigation measures."
+
+ if(!SSlag_switch.initialized)
+ to_chat(usr, span_notice("The Lag Switch subsystem has not yet been initialized."))
+ return
+ if(!check_rights())
+ return
+
+ var/list/dat = list("Lag SwitchesLag (Reduction) Switches
")
+ dat += "Automatic Trigger: [SSlag_switch.auto_switch ? "On" : "Off"]
"
+ dat += "Population Threshold: [SSlag_switch.trigger_pop]
"
+ dat += "Slowmode Cooldown (toggle On/Off below): [SSlag_switch.slowmode_cooldown/10] seconds
"
+ dat += "
SET ALL MEASURES: ON | OFF
"
+ dat += "
Disable ghosts zoom and t-ray verbs (except staff): [SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] ? "On" : "Off"]
"
+ dat += "Disable late joining: [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "On" : "Off"]
"
+ dat += "
============! MAD GHOSTS ZONE !============
"
+ dat += "Disable deadmob keyLoop (except staff, informs dchat): [SSlag_switch.measures[DISABLE_DEAD_KEYLOOP] ? "On" : "Off"]
"
+ dat += "==========================================
"
+ dat += "
Measures below can be bypassed with a special trait
"
+ dat += "Slowmode say verb (informs world): [SSlag_switch.measures[SLOWMODE_SAY] ? "On" : "Off"]
"
+ dat += "Disable runechat: [SSlag_switch.measures[DISABLE_RUNECHAT] ? "On" : "Off"] - trait applies to speaker
"
+ dat += "Disable examine icons: [SSlag_switch.measures[DISABLE_USR_ICON2HTML] ? "On" : "Off"] - trait applies to examiner
"
+ dat += ""
+ usr << browse(dat.Join(), "window=lag_switch_panel;size=420x420")
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 68e77e26637..dfd91618498 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -547,6 +547,60 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return dresscode
+/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list)
+ set category = "Debug"
+ set name = "Rejuvenate"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!mob)
+ return
+ if(!istype(M))
+ tgui_alert(usr,"Cannot revive a ghost")
+ return
+ M.revive(full_heal = TRUE, admin_revive = TRUE)
+
+ log_admin("[key_name(usr)] healed / revived [key_name(M)]")
+ var/msg = span_danger("Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!")
+ message_admins(msg)
+ admin_ticket_log(M, msg)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvenate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_admin_delete(atom/A as obj|mob|turf in world)
+ set category = "Debug"
+ set name = "Delete"
+
+ if(!check_rights(R_SPAWN|R_DEBUG))
+ return
+
+ admin_delete(A)
+
+/client/proc/cmd_admin_check_contents(mob/living/M in GLOB.mob_list)
+ set category = "Debug"
+ set name = "Check Contents"
+
+ var/list/L = M.get_contents()
+ for(var/t in L)
+ to_chat(usr, "[t]", confidential = TRUE)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Check Contents") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/modify_goals()
+ set category = "Debug"
+ set name = "Modify goals"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ holder.modify_goals()
+
+/datum/admins/proc/modify_goals()
+ var/dat = ""
+ for(var/datum/station_goal/S in GLOB.station_goals)
+ dat += "[S.name] - Announce | Remove
"
+ dat += "
Add New Goal"
+ usr << browse(dat, "window=goals;size=400x400")
+
/client/proc/cmd_debug_mob_lists()
set category = "Debug"
set name = "Debug Mob Lists"
diff --git a/code/modules/admin/verbs/server.dm b/code/modules/admin/verbs/server.dm
new file mode 100644
index 00000000000..a99ccd33531
--- /dev/null
+++ b/code/modules/admin/verbs/server.dm
@@ -0,0 +1,232 @@
+// Server Tab - Server Verbs
+
+/client/proc/toggle_random_events()
+ set category = "Server"
+ set name = "Toggle random events on/off"
+ set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off"
+ var/new_are = !CONFIG_GET(flag/allow_random_events)
+ CONFIG_SET(flag/allow_random_events, new_are)
+ if(new_are)
+ to_chat(usr, "Random events enabled", confidential = TRUE)
+ message_admins("Admin [key_name_admin(usr)] has enabled random events.")
+ else
+ to_chat(usr, "Random events disabled", confidential = TRUE)
+ message_admins("Admin [key_name_admin(usr)] has disabled random events.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Random Events", "[new_are ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/toggle_hub()
+ set category = "Server"
+ set name = "Toggle Hub"
+
+ world.update_hub_visibility(!GLOB.hub_visibility)
+
+ log_admin("[key_name(usr)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.")
+ message_admins("[key_name_admin(usr)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.")
+ if (GLOB.hub_visibility && !world.reachable)
+ message_admins("WARNING: The server will not show up on the hub because byond is detecting that a filewall is blocking incoming connections.")
+
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/restart()
+ set category = "Server"
+ set name = "Reboot World"
+ set desc="Restarts the world immediately"
+ if (!usr.client.holder)
+ return
+
+ var/localhost_addresses = list("127.0.0.1", "::1")
+ var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
+ if(world.TgsAvailable())
+ options += "Server Restart (Kill and restart DD)";
+
+ if(SSticker.admin_delay_notice)
+ if(tgui_alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", list("Yes", "No")) != "Yes")
+ return FALSE
+
+ var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
+ if(result)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]."
+ switch(result)
+ if("Regular Restart")
+ if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
+ if(tgui_alert(usr, "Are you sure you want to restart the server?","This server is live",list("Restart","Cancel")) != "Restart")
+ return FALSE
+ SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
+ if("Regular Restart (with delay)")
+ var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
+ if(!delay)
+ return FALSE
+ if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
+ if(tgui_alert(usr,"Are you sure you want to restart the server?","This server is live",list("Restart","Cancel")) != "Restart")
+ return FALSE
+ SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay * 10)
+ if("Hard Restart (No Delay, No Feeback Reason)")
+ to_chat(world, "World reboot - [init_by]")
+ world.Reboot()
+ if("Hardest Restart (No actions, just reboot)")
+ to_chat(world, "Hard world reboot - [init_by]")
+ world.Reboot(fast_track = TRUE)
+ if("Server Restart (Kill and restart DD)")
+ to_chat(world, "Server restart - [init_by]")
+ world.TgsEndProcess()
+
+/datum/admins/proc/end_round()
+ set category = "Server"
+ set name = "End Round"
+ set desc = "Attempts to produce a round end report and then restart the server organically."
+
+ if (!usr.client.holder)
+ return
+ var/confirm = tgui_alert(usr, "End the round and restart the game world?", "End Round", list("Yes", "Cancel"))
+ if(confirm == "Cancel")
+ return
+ if(confirm == "Yes")
+ SSticker.force_ending = 1
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "End Round") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/toggleooc()
+ set category = "Server"
+ set desc="Toggle dis bitch"
+ set name="Toggle OOC"
+ toggle_ooc()
+ log_admin("[key_name(usr)] toggled OOC.")
+ message_admins("[key_name_admin(usr)] toggled OOC.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/toggleoocdead()
+ set category = "Server"
+ set desc="Toggle dis bitch"
+ set name="Toggle Dead OOC"
+ toggle_dooc()
+
+ log_admin("[key_name(usr)] toggled OOC.")
+ message_admins("[key_name_admin(usr)] toggled Dead OOC.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/startnow()
+ set category = "Server"
+ set desc="Start the round RIGHT NOW"
+ set name="Start Now"
+ if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP)
+ if(!SSticker.start_immediately)
+ var/localhost_addresses = list("127.0.0.1", "::1")
+ if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
+ if(tgui_alert(usr, "Are you sure you want to start the round?","Start Now",list("Start Now","Cancel")) != "Start Now")
+ return FALSE
+ SSticker.start_immediately = TRUE
+ log_admin("[usr.key] has started the game.")
+ var/msg = ""
+ if(SSticker.current_state == GAME_STATE_STARTUP)
+ msg = " (The server is still setting up, but the round will be \
+ started as soon as possible.)"
+ message_admins("[usr.key] has started the game.[msg]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Now") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ return TRUE
+ SSticker.start_immediately = FALSE
+ SSticker.SetTimeLeft(1800)
+ to_chat(world, "The game will start in 180 seconds.")
+ SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
+ message_admins("[usr.key] has cancelled immediate game start. Game will start in 180 seconds.")
+ log_admin("[usr.key] has cancelled immediate game start.")
+ else
+ to_chat(usr, "Error: Start Now: Game has already started.")
+ return FALSE
+
+/datum/admins/proc/toggleenter()
+ set category = "Server"
+ set desc="People can't enter"
+ set name="Toggle Entering"
+ if(!SSlag_switch.initialized)
+ return
+ SSlag_switch.set_measure(DISABLE_NON_OBSJOBS, !SSlag_switch.measures[DISABLE_NON_OBSJOBS])
+ log_admin("[key_name(usr)] toggled new player game entering. Lag Switch at index ([DISABLE_NON_OBSJOBS])")
+ message_admins("[key_name_admin(usr)] toggled new player game entering [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "OFF" : "ON"].")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Entering", "[!SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/toggleAI()
+ set category = "Server"
+ set desc="People can't be AI"
+ set name="Toggle AI"
+ var/alai = CONFIG_GET(flag/allow_ai)
+ CONFIG_SET(flag/allow_ai, !alai)
+ if (alai)
+ to_chat(world, "The AI job is no longer chooseable.", confidential = TRUE)
+ else
+ to_chat(world, "The AI job is chooseable now.", confidential = TRUE)
+ log_admin("[key_name(usr)] toggled AI allowed.")
+ world.update_status()
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle AI", "[!alai ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/toggleaban()
+ set category = "Server"
+ set desc="Respawn basically"
+ set name="Toggle Respawn"
+ var/new_nores = !CONFIG_GET(flag/norespawn)
+ CONFIG_SET(flag/norespawn, new_nores)
+ if (!new_nores)
+ to_chat(world, "You may now respawn.", confidential = TRUE)
+ else
+ to_chat(world, "You may no longer respawn :(", confidential = TRUE)
+ message_admins(span_adminnotice("[key_name_admin(usr)] toggled respawn to [!new_nores ? "On" : "Off"]."))
+ log_admin("[key_name(usr)] toggled respawn to [!new_nores ? "On" : "Off"].")
+ world.update_status()
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Respawn", "[!new_nores ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/delay()
+ set category = "Server"
+ set desc="Delay the game start"
+ set name="Delay Pre-Game"
+
+ var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null
+ if(SSticker.current_state > GAME_STATE_PREGAME)
+ return tgui_alert(usr, "Too late... The game has already started!")
+ if(newtime)
+ newtime = newtime*10
+ SSticker.SetTimeLeft(newtime)
+ SSticker.start_immediately = FALSE
+ if(newtime < 0)
+ to_chat(world, "The game start has been delayed.", confidential = TRUE)
+ log_admin("[key_name(usr)] delayed the round start.")
+ else
+ to_chat(world, "The game will start in [DisplayTimeText(newtime)].", confidential = TRUE)
+ SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
+ log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/datum/admins/proc/set_admin_notice()
+ set category = "Server"
+ set name = "Set Admin Notice"
+ set desc ="Set an announcement that appears to everyone who joins the server. Only lasts this round"
+ if(!check_rights(0))
+ return
+
+ var/new_admin_notice = input(src,"Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):","Set Notice",GLOB.admin_notice) as message|null
+ if(new_admin_notice == null)
+ return
+ if(new_admin_notice == GLOB.admin_notice)
+ return
+ if(new_admin_notice == "")
+ message_admins("[key_name(usr)] removed the admin notice.")
+ log_admin("[key_name(usr)] removed the admin notice:\n[GLOB.admin_notice]")
+ else
+ message_admins("[key_name(usr)] set the admin notice.")
+ log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]")
+ to_chat(world, span_adminnotice("Admin Notice:\n \t [new_admin_notice]"), confidential = TRUE)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Admin Notice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ GLOB.admin_notice = new_admin_notice
+ return
+
+/datum/admins/proc/toggleguests()
+ set category = "Server"
+ set desc="Guests can't enter"
+ set name="Toggle guests"
+ var/new_guest_ban = !CONFIG_GET(flag/guest_ban)
+ CONFIG_SET(flag/guest_ban, new_guest_ban)
+ if (new_guest_ban)
+ to_chat(world, "Guests may no longer enter the game.", confidential = TRUE)
+ else
+ to_chat(world, "Guests may now enter the game.", confidential = TRUE)
+ log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.")
+ message_admins(span_adminnotice("[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed."))
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Guests", "[!new_guest_ban ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index f8fd230b247..cdfb757179f 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -554,7 +554,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
qdel(query_client_in_db)
return
/*
- var/client_is_in_db = query_client_in_db.NextRow()
//If we aren't an admin, and the flag is set
if(CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey])
var/living_recs = CONFIG_GET(number/panic_bunker_living)
@@ -579,7 +578,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
qdel(src)
return
*/
- if(!client_is_in_db))
+ var/client_is_in_db = query_client_in_db.NextRow()
+ if(!client_is_in_db)
//SKYRAT EDIT ADDITION BEGIN - PANICBUNKER
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough))
log_access("Failed Login: [key] - [address] - New account attempting to connect during panic bunker")
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 0868527d778..46a109cd0d0 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -326,14 +326,8 @@
else if(SSjob.always_promote_captain_job && (rank == "Captain"))
is_captain = TRUE
-<<<<<<< HEAD
- var/equip = SSjob.EquipRank(character, rank, TRUE, is_captain)
- if(isliving(equip)) //Borgs get borged in the equip, so we need to make sure we handle the new mob.
- character = equip
-=======
SSjob.EquipRank(character, job, character.client)
job.after_latejoin_spawn(character)
->>>>>>> 6c8c797cdcc (Fixes security not getting assigned to departments (#60349))
var/datum/job/job = SSjob.GetJob(rank)
diff --git a/tgstation.dme b/tgstation.dme
index 295da91e98f..adfa8530928 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1630,6 +1630,10 @@
#include "code\modules\admin\smites\smite.dm"
#include "code\modules\admin\smites\supply_pod.dm"
#include "code\modules\admin\smites\supply_pod_quick.dm"
+#include "code\modules\admin\verbs\admin.dm"
+#include "code\modules\admin\verbs\adminevents.dm"
+#include "code\modules\admin\verbs\adminfun.dm"
+#include "code\modules\admin\verbs\admingame.dm"
#include "code\modules\admin\verbs\adminhelp.dm"
#include "code\modules\admin\verbs\adminjump.dm"
#include "code\modules\admin\verbs\adminpm.dm"
@@ -1662,10 +1666,10 @@
#include "code\modules\admin\verbs\playsound.dm"
#include "code\modules\admin\verbs\possess.dm"
#include "code\modules\admin\verbs\pray.dm"
-#include "code\modules\admin\verbs\randomverbs.dm"
#include "code\modules\admin\verbs\reestablish_db_connection.dm"
#include "code\modules\admin\verbs\secrets.dm"
#include "code\modules\admin\verbs\selectequipment.dm"
+#include "code\modules\admin\verbs\server.dm"
#include "code\modules\admin\verbs\shuttlepanel.dm"
#include "code\modules\admin\verbs\spawnobjasmob.dm"
#include "code\modules\admin\verbs\SDQL2\SDQL_2.dm"