/// Is admin BSA (damage a user) currently on cooldown?
GLOBAL_VAR_INIT(BSACooldown, FALSE)
/// Are we in a no-log event (EORG, highlander, etc)?
GLOBAL_VAR_INIT(nologevent, FALSE)
/// Are explosions currently disabled for EORG?
GLOBAL_VAR_INIT(disable_explosions, FALSE)
////////////////////////////////
/proc/message_admins(msg)
msg = "ADMIN LOG: [msg]"
for(var/client/C in GLOB.admins)
if(R_ADMIN & C.holder.rights)
if(C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_ADMINLOGS))
to_chat(C, msg, MESSAGE_TYPE_ADMINLOG, confidential = TRUE)
/proc/msg_admin_attack(text, loglevel)
if(!GLOB.nologevent)
var/rendered = "ATTACK: [text]"
for(var/client/C in GLOB.admins)
if((C.holder.rights & R_ADMIN) && (C.prefs?.atklog <= loglevel))
to_chat(C, rendered, MESSAGE_TYPE_ATTACKLOG, confidential = TRUE)
/**
* Sends a message to the staff able to see admin tickets
* Arguments:
* msg - The message being send
* important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences,
* send a sound and flash the window. Defaults to FALSE
*/
/proc/message_adminTicket(msg, important = FALSE)
for(var/client/C in GLOB.admins)
if(R_ADMIN & C.holder.rights)
if(important || (C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS)))
to_chat(C, msg, MESSAGE_TYPE_ADMINCHAT, confidential = TRUE)
if(important)
if(C.prefs?.sound & SOUND_ADMINHELP)
SEND_SOUND(C, sound('sound/effects/adminhelp.ogg'))
window_flash(C)
/**
* Sends a message to the staff able to see mentor tickets
* Arguments:
* msg - The message being send
* important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences,
* send a sound and flash the window. Defaults to FALSE
*/
/proc/message_mentorTicket(msg, important = FALSE)
for(var/client/C in GLOB.admins)
if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob))
if(important || (C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS)))
to_chat(C, msg, MESSAGE_TYPE_MENTORPM, confidential = TRUE)
if(important)
if(C.prefs?.sound & SOUND_MENTORHELP)
SEND_SOUND(C, sound('sound/machines/notif1.ogg'))
window_flash(C)
/proc/admin_ban_mobsearch(mob/M, ckey_to_find, mob/admin_to_notify)
if(!M || !M.ckey)
if(ckey_to_find)
for(var/mob/O in GLOB.mob_list)
if(O.ckey && O.ckey == ckey_to_find)
if(admin_to_notify)
to_chat(admin_to_notify, "admin_ban_mobsearch: Player [ckey_to_find] is now in mob [O]. Pulling data from new mob.", MESSAGE_TYPE_ADMINLOG, confidential = TRUE)
return O
if(admin_to_notify)
to_chat(admin_to_notify, "admin_ban_mobsearch: Player [ckey_to_find] does not seem to have any mob, anywhere. This is probably an error.", MESSAGE_TYPE_ADMINLOG, confidential = TRUE)
else if(admin_to_notify)
to_chat(admin_to_notify, "admin_ban_mobsearch: No mob or ckey detected.", MESSAGE_TYPE_ADMINLOG, confidential = TRUE)
return M
///////////////////////////////////////////////////////////////////////////////////////////////Panels
USER_CONTEXT_MENU(show_player_panel, R_ADMIN|R_MOD, "\[Admin\] Show Player Panel", mob/M)
if(!M)
to_chat(client, "You seem to be selecting a mob that doesn't exist anymore.")
return
var/our_key = M.key
if(M.client && M.client.holder)
if(M.client.holder.fakekey && M.client.holder.big_brother)
our_key = M.client.holder.fakekey
var/mob_uid = M.UID()
var/body = "
"
dat += "Change Game Mode
"
if(GLOB.master_mode == "secret")
dat += "(Force Secret Mode)
"
if(GLOB.master_mode == "dynamic" || (GLOB.master_mode == "secret" && GLOB.secret_force_mode == "dynamic"))
dat += "(Force Dynamic Rulesets)
"
dat += "
"
dat += "Create Object
"
dat += "Quick Create Object
"
dat += "Create Turf
"
dat += "Create Mob
"
var/datum/browser/popup = new(usr, "game_panel", "Game Panel
", 210, 280)
popup.set_content(dat.Join(""))
popup.set_window_options("can_close=1;can_minimize=0;can_maximize=0;can_resize=0;titlebar=1;")
popup.open()
onclose(usr, "game_panel")
return
/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge
//i.e. buttons/verbs
USER_VERB(restart_server, R_SERVER, "Restart", "Restarts the world.", VERB_CATEGORY_SERVER)
// Give an extra popup if they are rebooting a live server
var/is_live_server = TRUE
if(client.is_connecting_from_localhost())
is_live_server = FALSE
var/list/options = list("Regular Restart", "Hard Restart")
if(world.TgsAvailable()) // TGS lets you kill the process entirely
options += "Terminate Process (Kill and restart DD)"
var/result = input(client, "Select reboot method", "World Reboot", options[1]) as null|anything in options
if(result && is_live_server)
if(alert(client, "WARNING: THIS IS A LIVE SERVER, NOT A LOCAL TEST SERVER. DO YOU STILL WANT TO RESTART","This server is live","Restart","Cancel") != "Restart")
return FALSE
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 [client.holder.fakekey ? "Admin" : client.key]."
switch(result)
if("Regular Restart")
var/delay = input(client, "What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
if(!delay)
return FALSE
// These are pasted each time so that they dont false send if reboot is cancelled
message_admins("[key_name_admin(client)] has initiated a server restart of type [result]")
log_admin("[key_name(client)] has initiated a server restart of type [result]")
SSticker.delay_end = FALSE // We arent delayed anymore
SSticker.reboot_helper(init_by, "admin reboot - by [client.key] [client.holder.fakekey ? "(stealth)" : ""]", delay * 10)
if("Hard Restart")
message_admins("[key_name_admin(client)] has initiated a server restart of type [result]")
log_admin("[key_name(client)] has initiated a server restart of type [result]")
world.Reboot(fast_track = TRUE)
if("Terminate Process (Kill and restart DD)")
message_admins("[key_name_admin(client)] has initiated a server restart of type [result]")
log_admin("[key_name(client)] has initiated a server restart of type [result]")
world.TgsEndProcess() // Just nuke the entire process if we are royally fucked
USER_VERB(end_round, R_SERVER, "End Round", \
"Instantly ends the round and brings up the scoreboard, in the same way that wizards dying do.", \
VERB_CATEGORY_SERVER)
var/input = sanitize(copytext_char(input(client, "What text should players see announcing the round end? Input nothing to cancel.", "Specify Announcement Text", "Shift Has Ended!"), 1, MAX_MESSAGE_LEN))
if(!input)
return
if(SSticker.force_ending)
return
message_admins("[key_name_admin(client)] has admin ended the round with message: '[input]'")
log_admin("[key_name(client)] has admin ended the round with message: '[input]'")
SSticker.force_ending = TRUE
SSticker.record_biohazard_results()
to_chat(world, "[input]")
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!
SSticker.mode_result = "admin ended"
USER_VERB(announce, R_ADMIN, "Announce", "Announce your desires to the world", VERB_CATEGORY_ADMIN)
var/message = input(client, "Global message to send:", "Admin Announce", null) as message|null
if(message)
if(!check_rights_client(R_SERVER, 0, client))
message = adminscrub(message,500)
message = replacetext(message, "\n", "
") // required since we're putting it in a tag
to_chat(world, chat_box_notice("[client.holder.fakekey ? "Administrator" : client.key] Announces:
[message]
"))
log_admin("Announce: [key_name(client)] : [message]")
for(var/client/clients_to_alert in GLOB.clients)
window_flash(clients_to_alert)
if(clients_to_alert.prefs?.sound & SOUND_ADMINHELP)
SEND_SOUND(clients_to_alert, sound('sound/misc/server_alert.ogg'))
SSblackbox.record_feedback("tally", "admin_verb", 1, "Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_ooc, R_ADMIN, "Toggle OOC", "Globally Toggles OOC", VERB_CATEGORY_SERVER)
toggle_ooc()
log_and_message_admins("toggled OOC.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_looc, R_ADMIN, "Toggle LOOC", "Globally Toggles LOOC", VERB_CATEGORY_SERVER)
GLOB.looc_enabled = !(GLOB.looc_enabled)
if(GLOB.looc_enabled)
to_chat(world, "The LOOC channel has been globally enabled!")
else
to_chat(world, "The LOOC channel has been globally disabled!")
log_and_message_admins("toggled LOOC.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle LOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_dsay, R_ADMIN, "Toggle DSAY", "Globally Toggles DSAY", VERB_CATEGORY_SERVER)
GLOB.dsay_enabled = !(GLOB.dsay_enabled)
if(GLOB.dsay_enabled)
to_chat(world, "Deadchat has been globally enabled!", MESSAGE_TYPE_DEADCHAT)
else
to_chat(world, "Deadchat has been globally disabled!", MESSAGE_TYPE_DEADCHAT)
log_admin("[key_name(client)] toggled deadchat.")
message_admins("[key_name_admin(client)] toggled deadchat.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Deadchat") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_ooc_dead, R_ADMIN, "Toggle Dead OOC", "Toggle Dead OOC.", VERB_CATEGORY_SERVER)
GLOB.dooc_enabled = !(GLOB.dooc_enabled)
log_admin("[key_name(client)] toggled Dead OOC.")
message_admins("[key_name_admin(client)] toggled Dead OOC.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Dead OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_emoji, R_ADMIN, "Toggle OOC Emoji", "Toggle OOC Emoji", VERB_CATEGORY_SERVER)
GLOB.configuration.general.enable_ooc_emoji = !(GLOB.configuration.general.enable_ooc_emoji)
log_admin("[key_name(client)] toggled OOC Emoji.")
message_admins("[key_name_admin(client)] toggled OOC Emoji.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle OOC Emoji")
USER_VERB(start_server_now, R_SERVER, "Start Now", "Start the round RIGHT NOW", VERB_CATEGORY_SERVER)
if(SSticker.current_state < GAME_STATE_STARTUP)
alert(client, "Unable to start the game as it is not set up.")
return
if(!SSticker.ticker_going)
alert(client, "Remove the round-start delay first.")
return
if(GLOB.configuration.general.start_now_confirmation)
if(alert(client, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
return
if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP)
SSticker.force_start = TRUE
log_admin("[client.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("[client.key] has started the game.[msg]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Game") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return 1
else
to_chat(client, "Error: Start Now: Game has already started.")
return
USER_VERB(toggle_enter, R_SERVER, "Toggle Entering", "People can't enter", VERB_CATEGORY_SERVER)
if(!client.is_connecting_from_localhost())
if(tgui_alert(client, "Are you sure about this?", "Confirm", list("Yes", "No")) != "Yes")
return
GLOB.enter_allowed = !GLOB.enter_allowed
if(!GLOB.enter_allowed)
to_chat(world, "New players may no longer enter the game.")
else
to_chat(world, "New players may now enter the game.")
log_admin("[key_name(client)] toggled new player game entering.")
message_admins("[key_name_admin(client)] toggled new player game entering.", 1)
world.update_status()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Entering") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_ai_role, R_EVENT, "Toggle AI", "People can't be AI", VERB_CATEGORY_EVENT)
GLOB.configuration.jobs.allow_ai = !(GLOB.configuration.jobs.allow_ai)
if(!GLOB.configuration.jobs.allow_ai)
to_chat(world, "The AI job is no longer chooseable.")
else
to_chat(world, "The AI job is chooseable now.")
message_admins("[key_name_admin(client)] toggled AI allowed.")
log_admin("[key_name(client)] toggled AI allowed.")
world.update_status()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle AI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_respawn, R_SERVER, "Toggle Respawn", "Toggle the ability for players to respawn.", VERB_CATEGORY_SERVER)
if(!client.is_connecting_from_localhost())
if(tgui_alert(client, "Are you sure about this?", "Confirm", list("Yes", "No")) != "Yes")
return
GLOB.configuration.general.respawn_enabled = !(GLOB.configuration.general.respawn_enabled)
if(GLOB.configuration.general.respawn_enabled)
to_chat(world, "You may now respawn.")
else
to_chat(world, "You may no longer respawn")
message_admins("[key_name_admin(client)] toggled respawn to [GLOB.configuration.general.respawn_enabled ? "On" : "Off"].", 1)
log_admin("[key_name(client)] toggled respawn to [GLOB.configuration.general.respawn_enabled ? "On" : "Off"].")
world.update_status()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Respawn") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(delay_game, R_SERVER, "Delay", "Delay the game start/end", VERB_CATEGORY_SERVER)
if(SSticker.current_state < GAME_STATE_STARTUP)
alert(client, "Slow down a moment, let the ticker start first!")
return
if(!client.is_connecting_from_localhost())
if(tgui_alert(client, "Are you sure about this?", "Confirm", list("Yes", "No")) != "Yes")
return
if(SSblackbox)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(SSticker.current_state > GAME_STATE_PREGAME)
SSticker.delay_end = !SSticker.delay_end
log_admin("[key_name(client)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("[key_name(client)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
if(SSticker.delay_end)
SSticker.real_reboot_time = 0 // Immediately show the "Admin delayed round end" message
return //alert("Round end delayed", null, null, null, null, null)
if(SSticker.ticker_going)
SSticker.ticker_going = FALSE
SSticker.delay_end = TRUE
to_chat(world, "The game start has been delayed.")
log_admin("[key_name(client)] delayed the game.")
else
SSticker.ticker_going = TRUE
SSticker.round_start_time = world.time + SSticker.pregame_timeleft
to_chat(world, "The game will start soon.")
log_admin("[key_name(client)] removed the delay.")
////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS
/**
* A proc that return whether the mob is a "Special Character" aka Antagonist
*
* Arguments:
* * M - the mob you're checking
*/
/proc/is_special_character(mob/M)
if(!SSticker.mode)
return FALSE
if(!istype(M))
return FALSE
if(isrobot(M))
var/mob/living/silicon/robot/R = M
if(R.emagged)
return TRUE
if(M.mind?.special_role)//If they have a mind and special role, they are some type of traitor or antagonist.
return TRUE
return FALSE
/**
* A proc that return an array of capitalized strings containing name of the antag types they are
*
* Arguments:
* * M - the mob you're checking
*/
/proc/get_antag_type_strings_list(mob/M) // return an array of all the antag types they are with name
var/list/antag_list = list()
if(!SSticker.mode || !istype(M) || !M.mind)
return FALSE
if(M.mind.has_antag_datum(/datum/antagonist/rev/head))
antag_list += "Head Rev"
if(M.mind.has_antag_datum(/datum/antagonist/rev, FALSE))
antag_list += "Revolutionary"
if(IS_CULTIST(M))
antag_list += "Cultist"
if(M.mind in SSticker.mode.syndicates)
antag_list += "Nuclear Operative"
if(iswizard(M))
antag_list += "Wizard"
if(IS_CHANGELING(M))
antag_list += "Changeling"
if(M.mind.has_antag_datum(/datum/antagonist/abductor))
antag_list += "Abductor"
if(M.mind.has_antag_datum(/datum/antagonist/vampire))
antag_list += "Vampire"
if(M.mind.has_antag_datum(/datum/antagonist/mindslave/thrall))
antag_list += "Vampire Thrall"
if(M.mind.has_antag_datum(/datum/antagonist/traitor))
antag_list += "Traitor"
if(IS_MINDSLAVE(M))
antag_list += "Mindslave"
if(isrobot(M))
var/mob/living/silicon/robot/R = M
if(R.emagged)
antag_list += "Emagged Borg"
if(!length(antag_list) && M.mind.special_role) // Snowflake check. If none of the above but still special, then other antag. Technically not accurate.
antag_list += "Other Antag(s)"
return antag_list
/**
* A proc that return a string containing all the singled out antags . Empty string if not antag
*
* Usually, you'd return a FALSE, but since this is consumed by javascript you're in
* for a world of hurt if you pass a byond FALSE which get converted into a fucking string anyway and pass for TRUE in check. Fuck.
* It always append "(May be other antag)"
* Arguments:
* * M - the mob you're checking
* *
*/
/proc/get_antag_type_truncated_plaintext_string(mob/M as mob)
var/list/antag_list = get_antag_type_strings_list(M)
if(length(antag_list))
return antag_list.Join(" & ") + " " + "(May be other antag)"
return ""
USER_VERB(spawn_atom, R_SPAWN, "Spawn", \
"Spawn an atom. Append a period to the text in order to exclude subtypes of paths matching the input.", \
VERB_CATEGORY_DEBUG, object as text)
if(!object)
return
var/list/types = typesof(/atom)
var/list/matches = list()
var/include_subtypes = TRUE
if(copytext(object, -1) == ".")
include_subtypes = FALSE
object = copytext(object, 1, -1)
if(include_subtypes)
for(var/path in types)
if(findtext("[path]", object))
matches += path
else
var/needle_length = length(object)
for(var/path in types)
if(copytext("[path]", -needle_length) == object)
matches += path
if(length(matches)==0)
return
var/chosen
if(length(matches)==1)
chosen = matches[1]
else
chosen = tgui_input_list(client, "Select an Atom Type", "Spawn Atom", matches)
if(!chosen)
return
if(ispath(chosen,/turf))
var/turf/T = get_turf(client.mob.loc)
T.ChangeTurf(chosen)
else
var/atom/A = new chosen(client.mob.loc)
A.admin_spawned = TRUE
log_admin("[key_name(client)] spawned [chosen] at ([client.mob.x],[client.mob.y],[client.mob.z])")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB_VISIBILITY(show_traitor_panel, VERB_VISIBILITY_FLAG_MOREDEBUG)
USER_VERB(show_traitor_panel, R_ADMIN|R_MOD, "Show Traitor Panel", "Edit mob's memory and role", VERB_CATEGORY_ADMIN, mob/M in GLOB.mob_list)
if(!istype(M))
to_chat(client, "This can only be used on instances of type /mob")
return
if(!M.mind)
to_chat(client, "This mob has no mind!")
return
M.mind.edit_memory()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
USER_VERB(toggle_guests, R_SERVER, "Toggle Guests", "Guests can't enter", VERB_CATEGORY_SERVER)
if(!client.is_connecting_from_localhost())
if(tgui_alert(client, "Are you sure about this?", "Confirm", list("Yes", "No")) != "Yes")
return
GLOB.configuration.general.guest_ban = !(GLOB.configuration.general.guest_ban)
if(GLOB.configuration.general.guest_ban)
to_chat(world, "Guests may no longer enter the game.")
else
to_chat(world, "Guests may now enter the game.")
log_admin("[key_name(client)] toggled guests game entering [GLOB.configuration?.general.guest_ban ? "dis" : ""]allowed.")
message_admins("[key_name_admin(client)] toggled guests game entering [GLOB.configuration?.general.guest_ban ? "dis" : ""]allowed.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Guests") //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
var/list/messages = list()
for(var/mob/living/silicon/S in GLOB.mob_list)
if(istype(S, /mob/living/silicon/decoy) && !S.client)
continue
ai_number++
if(is_ai(S))
messages += "AI [key_name(S, TRUE)]'s laws:"
else if(isrobot(S))
var/mob/living/silicon/robot/R = S
messages += "CYBORG [key_name(S, TRUE)]'s [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independent)"] laws:"
else if(ispAI(S))
var/mob/living/silicon/pai/P = S
messages += "pAI [key_name(S, TRUE)]'s laws:"
messages += "[P.pai_law0]"
if(P.pai_laws)
messages += "[P.pai_laws]"
continue // Skip showing normal silicon laws for pAIs - they don't have any
else
messages += "SILICON [key_name(S, TRUE)]'s laws:"
if(S.laws == null)
messages += "[key_name(S, TRUE)]'s laws are null. Contact a coder."
else
messages += S.laws.return_laws_text()
if(!ai_number)
messages += "No AI's located." //Just so you know the thing is actually working and not just ignoring you.
to_chat(usr, chat_box_examine(messages.Join("
")))
log_admin("[key_name(usr)] checked the AI laws")
message_admins("[key_name_admin(usr)] checked the AI laws")
USER_CONTEXT_MENU(update_mob_sprite, R_ADMIN, "\[Admin\] Update Mob Sprite", mob/living/carbon/human/H as mob)
if(istype(H))
H.regenerate_icons()
//
//
//ALL DONE
//*********************************************************************************************************
/proc/move_gamma_ship()
if(!SSshuttle.gamma_armory)
log_debug("move_gamma_ship(): There is no Gamma Armory shuttle, but the Gamma Armory shuttle was called. Loading a default Gamma Armory shuttle.")
SSshuttle.load_initial_gamma_armory_shuttle(SSmapping.gamma_armory_shuttle_id)
if(SSshuttle.gamma_armory.mode != (SHUTTLE_IDLE || SHUTTLE_DOCKED))
to_chat(usr, "The Gamma Armory shuttle is currently in transit. Please try again in a few moments.")
return
if(SSshuttle.gamma_armory.loc.z == level_name_to_num(CENTCOMM))
SSshuttle.moveShuttle("gamma_armory", "gamma_home", TRUE, usr)
for(var/obj/machinery/door/poddoor/impassable/gamma/H in GLOB.airlocks)
H.open()
GLOB.major_announcement.Announce("Central Command has deployed the Gamma Armory shuttle.", new_sound = 'sound/AI/gamma_deploy.ogg')
else
SSshuttle.moveShuttle("gamma_armory", "gamma_away", TRUE, usr)
for(var/obj/machinery/door/poddoor/impassable/gamma/H in GLOB.airlocks)
H.close() //DOOR STUCK
GLOB.major_announcement.Announce("Central Command has recalled the Gamma Armory shuttle.", new_sound = 'sound/AI/gamma_recall.ogg')
/proc/formatJumpTo(location, where="")
var/turf/loc
if(isturf(location))
loc = location
else
loc = get_turf(location)
if(where=="")
where=formatLocation(loc)
return "[where]"
/proc/formatLocation(location)
var/turf/loc
if(isturf(location))
loc = location
else
loc = get_turf(location)
var/area/A = get_area(location)
return "[A.name] - [loc.x],[loc.y],[loc.z]"
/proc/formatPlayerPanel(mob/U, text="PP")
return "[ADMIN_PP(U,"[text]")]"
//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
/proc/kick_clients_in_lobby(message, kick_only_afk = 0)
var/list/kicked_client_names = list()
for(var/client/C in GLOB.clients)
if(isnewplayer(C.mob))
if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk
continue
if(message)
to_chat(C, message)
kicked_client_names.Add("[C.ckey]")
qdel(C)
return kicked_client_names
//returns 1 to let the dragdrop code know we are trapping this event
//returns 0 if we don't plan to trap the event
/datum/admins/proc/cmd_ghost_drag(mob/dead/observer/frommob, atom/tothing)
if(!istype(frommob))
return //extra sanity check to make sure only observers are shoved into things
//same as assume-direct-control perm requirements.
if(!check_rights(R_VAREDIT,0)) //no varedit, check if they have r_admin and r_debug
if(!check_rights(R_ADMIN|R_DEBUG,0)) //if they don't have r_admin and r_debug, return
return FALSE //otherwise, if they have no varedit, but do have r_admin and r_debug, execute the rest of the code
if(!frommob.ckey)
return FALSE
if(isitem(tothing))
var/mob/living/toitem = tothing
var/ask = alert("Are you sure you want to allow [frommob.name]([frommob.key]) to possess [toitem.name]?", "Place ghost in control of item?", "Yes", "No")
if(ask != "Yes")
return TRUE
if(!frommob || !toitem) //make sure the mobs don't go away while we waited for a response
return TRUE
var/mob/living/basic/possessed_object/tomob = new(toitem)
message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].")
log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Ghost Drag")
tomob.ckey = frommob.ckey
qdel(frommob)
if(isliving(tothing))
var/mob/living/tomob = tothing
var/question = ""
if(tomob.ckey)
question = "This mob already has a user ([tomob.key]) in control of it! "
question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?"
var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No")
if(ask != "Yes")
return TRUE
if(!frommob || !tomob) //make sure the mobs don't go away while we waited for a response
return TRUE
if(tomob.client) //no need to ghostize if there is no client
tomob.ghostize(GHOST_FLAGS_OBSERVE_ONLY)
message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].")
log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Ghost Drag")
tomob.ckey = frommob.ckey
qdel(frommob)
return TRUE
if(istype(tothing, /obj/structure/ai_core/deactivated))
var/question = "Are you sure you want to place [frommob.name]([frommob.key]) in control of an empty AI core?"
var/ask = alert(question, "Place ghost in control of an empty AI core?", "Yes", "No")
if(ask != "Yes")
return TRUE
if(QDELETED(frommob) || QDELETED(tothing)) //make sure the mobs don't go away while we waited for a response
return TRUE
message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of an empty AI core.")
log_admin("[key_name(usr)] stuffed [frommob.ckey] into an empty AI core.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Ghost Drag")
var/transfer_key = frommob.key // frommob is qdel'd in frommob.AIize()
var/mob/living/silicon/ai/ai_character = frommob.AIize()
ai_character.key = transfer_key // this wont occur in mind transferring if the mind is not active, which causes some weird stuff. This fixes it.
GLOB.empty_playable_ai_cores -= tothing
ai_character.forceMove(get_turf(tothing))
ai_character.view_core()
qdel(tothing)
return TRUE
// Returns a list of the number of admins in various categories
// result[1] is the number of staff that match the rank mask and are active
// result[2] is the number of staff that do not match the rank mask
// result[3] is the number of staff that match the rank mask and are inactive
/proc/staff_countup(rank_mask = R_BAN)
var/list/result = list(0, 0, 0)
for(var/client/X in GLOB.admins)
if(rank_mask && !check_rights_client(rank_mask, FALSE, X))
result[2]++
continue
if(X.holder.fakekey)
result[2]++
continue
if(X.is_afk())
result[3]++
continue
result[1]++
return result
/**
* Allows admins to safely pick from SSticker.minds for objectives
* - caller_mob, mob to ask for results
* - blacklist, optional list of targets that are not available
* - default_target, the target to show in the list as default
*/
/proc/get_admin_objective_targets(mob/caller_mob, list/blacklist, mob/default_target)
if(!islist(blacklist))
blacklist = list(blacklist)
var/list/possible_targets = list()
for(var/datum/mind/possible_target in SSticker.minds)
if(!(possible_target in blacklist) && ishuman(possible_target.current))
possible_targets += possible_target.current // Allows for admins to pick off station roles
if(!length(possible_targets))
to_chat(caller_mob, "No possible target found.")
return
possible_targets = sortAtom(possible_targets)
var/mob/new_target = input(caller_mob, "Select target:", "Objective target", default_target) as null|anything in possible_targets
if(!QDELETED(new_target))
return new_target.mind
#undef PLAYER_NOTES_ENTRIES_PER_PAGE