mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
* TGUI Preferences Menu + total rewrite of the preferences backend (#17368) * It compiles * It opens * Sync 1 * Add asset caching * Sync 2 * It opens without dev now * Update a few packages * Sync 3 * Sync 4 keybind fix * start of dehardcoded species * Small fixes * Add more individual preferences * ASS sync * Automatic changelog generation #17368 [ci skip] * AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH * e * Fix some TS stuff * Sort quirks starting from good * Fix skin tone selector * Jamie Fixes * Update moth.dm * Fix latejoin menu + tweaks * Some fixes * Finally fix job selection * e * Ling * MORE * config * Convert pref: ooccolor * Convert pref: asay color * Convert pref: tooltips * Convert pref: ui style * Convert pref: buttons locked * Convert pref: hotkeys * Convert pref: tgui stuff * Convert pref: windowflashing * Convert pref: ghost stuff * Convert pref: map & antag * Convert pref: PDA stuff * Convert pref: credits & glasses 1 * Convert pref: name * Convert pref: appearances 1 * Convert pref: appearances 2 * Convert pref: jobless role * Convert pref: runechat * Convert pref: yogtoggles + tail wagging 1 * Convert pref: client fps * Convert pref: graphic settings * Convert pref: pda uplink & menuoptions * Convert pref: map & flare * Convert pref: Bar choice * Fix setup character button * Convert pref: alt announcer * Fix * Add cycle background button * Convert pref: disable balloon alert * fix * Clean savefile * Fix backpack pref * Fix underwear selection * Fixes some shit * Updates * Fix computer runtime * Fix pref names * Convert pref: donor item & hat * More computer fixes * Convert pref: borg hat * Convert pref: donor pda (broken) * Convert pref: purrbation * Convert pref: afreeze * Convert pref: accent * Various savefile improvements * Convert pref: persistent scars 1 * A few pref fixes * Some more fixes * Various SSoverlays improvements * Add IPC appearances * Add polysmorph appearances * No icons for ipc and polysmorph * Podpeople deserve death * Add plasmaman appearance * h * fix * fix2 * asdf * fsdf * aaaaa * FUCK MOTHS * Preternis color * e * e * Update human.dmi * icon fix * un snowflake * fix underwear icon * remove color from here * donor ree * aa * maybe * Restore a bunch of TGUI files * More TGUI fixes * test * Fix more errors * a * test * e? * a;lso this * maybe * Fix * Revert "maybe" This reverts commit14d044a7e3. * fuck off m8 * e * fak off m8 * e2? * AHHH * AHA * AHHH * fix linter 2 * debug * fix runtime * Update dynamic.json * Revert "debug" This reverts commit18681432bd. * 2 * who sleeps in an async? * Hack * e * Fix a few blocking calls * Oh bother * Stay dead * fuck * Update jobs.dm * move debugging * Update jobs.dm * Test * YEET * Revert "YEET" This reverts commit4082e3b133. * Update jobs.dm * Update jobs.dm * e * Fix sechailer runtime * Fix human hair color * d * Ports part of that job refactor * Convert latejoin to new departments * Fix ghost form * Quirk validation * Hopefully pod color fix * oops * Prayge job fix * test * Better unit test asset loading * Remove print * Add error just in case * Remove brief outfit and bypass centcom deadmin * Remove broadcast login/logout * Remove darkened flash * Remove fov darkness * Remove ghost lighting * Remove some tgui prefs * Typo fix * Small fixes * IPC name fix * IPC and pod colors * Jobless fix * Donor item fix * Oopsie * Quirk bandaid * Misc * Move new prefs to Preferences tab for now * Add skillcape * FUCK THIS SHIT * Remove /tg/ gamer cloak * Restrict some job related preferences to clean up UI * Remove useless client var * e * Small tweaks * Dont allow selecting mood quirks if mood is disabled * AHHH * Filter ckey-locked donor items * stupid jamie * AI core display fix * Move donor stuff back to the top * Remove TODOs * Clean up perks * Linter fixes * e * WORKS * LORE * Fix skillcape list * Backpack why * Fixes * Fix cargo console * Remove these * Add horns, frills and mark * Fix not applying all features * Add some missing mutant bodyparts * Update numberinput * Makes animatednumber cooler * Oops * Add default ghost orbit * Default to normal backpack * Fixes skillcapes not being filtered * Donor fix prayge * yep * Adds fallback latejoin menu * Rework donor stuff a bit * Fix donor tgui logic * Delete unused proc * Update FA * Un-yogify quirks * Better checking of quirks * Update tgfont * Fix quirk icons * Fix backup name * Fix donor stuff * A few runtime fixes * Fix another runtime * Give fallback latejoin verb upon connecting * Update AirAlarm interface * maybe this works * Test * Sentient * Remove AI core display preview icons * Fix resetting plasmaman helmet style * Equip plasman in preview * Fix plasmaman preview icon * fuck keybind fix * Extra keybind sanity --------- Co-authored-by: Yogbot-13 <admin@yogstation.net> Co-authored-by: Jamie D <993128+JamieD1@users.noreply.github.com> Co-authored-by: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com> Co-authored-by: adamsong <adamsong@users.noreply.github.com>
1067 lines
53 KiB
Plaintext
1067 lines
53 KiB
Plaintext
|
||
////////////////////////////////
|
||
/proc/message_admins(msg)
|
||
msg = span_admin("<span class=\"prefix\">ADMIN LOG:</span> <span class=\"message\">[msg]</span>")
|
||
to_chat(GLOB.permissions.admins,
|
||
type = MESSAGE_TYPE_ADMINLOG,
|
||
html = msg,
|
||
confidential = TRUE)
|
||
|
||
/proc/relay_msg_admins(msg)
|
||
msg = span_admin("<span class=\"prefix\">RELAY:</span> <span class=\"message\">[msg]</span>")
|
||
to_chat(GLOB.permissions.admins,
|
||
type = MESSAGE_TYPE_ADMINLOG,
|
||
html = msg,
|
||
confidential = TRUE)
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////Panels
|
||
|
||
/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list)
|
||
set category = "Misc.Unused"
|
||
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, "You seem to be selecting a mob that doesn't exist anymore.", confidential=TRUE)
|
||
return
|
||
|
||
if(M.oobe_client) //yogs start
|
||
if(M.oobe_client.mob)
|
||
.(M.oobe_client.mob) //using . because show_player_panel(M.oobe_client.mob) caused "Runtime in admin.dm,30: undefined proc or verb /client/Show Player Panel()."
|
||
else
|
||
to_chat(usr, span_warning("Cannot open player panel because [key_name(M)] has (a)ghosted, but does not appear to have a mob."), confidential=TRUE)
|
||
return //yogs end
|
||
|
||
var/body = "<html><head><meta charset='UTF-8'><title>Options for [M.key]</title></head>"
|
||
body += "<body>Options panel for <b>[M]</b>"
|
||
if(M.client)
|
||
body += " played by <b>[M.client]</b> "
|
||
body += "\[<A href='?_src_=holder;[HrefToken()];editrights=[(GLOB.permissions.admin_datums[M.client.ckey] || GLOB.permissions.deadmins[M.client.ckey]) ? "rank" : "add"];key=[M.key]'>[M.client.holder ? M.client.holder.rank_name() : "Player"]</A>\]"
|
||
if(CONFIG_GET(flag/use_exp_tracking))
|
||
body += "\[<A href='?_src_=holder;[HrefToken()];getplaytimewindow=[REF(M)]'>" + M.client.get_exp_living() + "</a> | "
|
||
body += " <A href='?_src_=holder;[HrefToken()];toggleexempt=[REF(M.client)]'>Toggle Exempt</a>\]"
|
||
|
||
if(isnewplayer(M))
|
||
body += " <B>Hasn't Entered Game</B> "
|
||
else
|
||
body += " \[<A href='?_src_=holder;[HrefToken()];revive=[REF(M)]'>Heal</A>\] "
|
||
|
||
if(M.client)
|
||
body += "<br>\[<b>First Seen:</b> [M.client.player_join_date]\]\[<b>Byond account registered on:</b> [M.client.account_join_date]\]"
|
||
body += "<br><br><b>CentCom Galactic Ban DB: </b> "
|
||
if(CONFIG_GET(string/centcom_ban_db))
|
||
body += "<a href='?_src_=holder;[HrefToken()];centcomlookup=[M.client.ckey]'>Search</a>"
|
||
else
|
||
body += "<i>Disabled</i>"
|
||
body += "<br><br><b>Show related accounts by:</b> "
|
||
body += "\[ <a href='?_src_=holder;[HrefToken()];showrelatedacc=cid;client=[REF(M.client)]'>CID</a> | "
|
||
body += "<a href='?_src_=holder;[HrefToken()];showrelatedacc=ip;client=[REF(M.client)]'>IP</a> \]"
|
||
if(CONFIG_GET(string/vpn_lookup_api) && CONFIG_GET(string/vpn_lookup_key) && M.lastKnownIP)
|
||
body += " \[<a href='?_src_=holder;[HrefToken()];vpnlookup=[M.lastKnownIP]'>Check for VPN</a>\]"
|
||
var/rep = 0
|
||
rep += SSpersistence.antag_rep[M.ckey]
|
||
body += "<br><br>Antagonist reputation: [rep]"
|
||
body += "<br><a href='?_src_=holder;[HrefToken()];modantagrep=add;mob=[REF(M)]'>\[increase\]</a> "
|
||
body += "<a href='?_src_=holder;[HrefToken()];modantagrep=subtract;mob=[REF(M)]'>\[decrease\]</a> "
|
||
body += "<a href='?_src_=holder;[HrefToken()];modantagrep=set;mob=[REF(M)]'>\[set\]</a> "
|
||
body += "<a href='?_src_=holder;[HrefToken()];modantagrep=zero;mob=[REF(M)]'>\[zero\]</a>"
|
||
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 += "<br>\[<b>Byond version:</b> [full_version]\]<br>"
|
||
|
||
|
||
body += "<br><br>\[ "
|
||
body += "<a href='?_src_=vars;[HrefToken()];Vars=[REF(M)]'>VV</a> - "
|
||
if(M.mind)
|
||
body += "<a href='?_src_=holder;[HrefToken()];traitor=[REF(M)]'>TP</a> - "
|
||
else
|
||
body += "<a href='?_src_=holder;[HrefToken()];initmind=[REF(M)]'>Init Mind</a> - "
|
||
if (iscyborg(M))
|
||
body += "<a href='?_src_=holder;[HrefToken()];borgpanel=[REF(M)]'>BP</a> - "
|
||
body += "<a href='?priv_msg=[M.ckey]'>PM</a> - "
|
||
body += "<a href='?_src_=holder;[HrefToken()];subtlemessage=[REF(M)]'>SM</a> - "
|
||
if (ishuman(M) && M.mind)
|
||
body += "<a href='?_src_=holder;[HrefToken()];HeadsetMessage=[REF(M)]'>HM</a> - "
|
||
body += "<a href='?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(M)]'>FLW</a> - "
|
||
//Default to client logs if available
|
||
var/source = LOGSRC_MOB
|
||
if(M.client)
|
||
source = LOGSRC_CLIENT
|
||
body += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_src=[source]'>LOGS</a>\] <br>"
|
||
|
||
body += "<b>Mob type</b> = [M.type]<br><br>"
|
||
|
||
body += "<A href='?_src_=holder;[HrefToken()];boot2=[REF(M)]'>Kick</A> | "
|
||
if(M.client)
|
||
body += "<A href='?_src_=holder;[HrefToken()];newbankey=[M.key];newbanip=[M.client.address];newbancid=[M.client.computer_id]'>Ban</A> | "
|
||
else
|
||
body += "<A href='?_src_=holder;[HrefToken()];newbankey=[M.key]'>Ban</A> | "
|
||
|
||
body += "<A href='?_src_=holder;[HrefToken()];showmessageckey=[M.ckey]'>Notes | Messages | Watchlist</A> | "
|
||
if(M.client)
|
||
body += "| <A href='?_src_=holder;[HrefToken()];sendtoprison=[REF(M)]'>Prison</A> | "
|
||
body += "\ <A href='?_src_=holder;[HrefToken()];sendbacktolobby=[REF(M)]'>Send back to Lobby</A> | "
|
||
var/muted = M.client.prefs.muted
|
||
body += "<br><b>Mute: </b> "
|
||
body += "\[<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"blue"]'>IC</font></a> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"blue"]'>OOC</font></a> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"blue"]'>PRAY</font></a> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"blue"]'>ADMINHELP</font></a> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_MENTORHELP]'><font color='[(muted & MUTE_MENTORHELP)?"red":"blue"]'>MENTORHELP</font></a> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"blue"]'>DEADCHAT</font></a>\]"
|
||
body += "(<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"blue"]'>toggle all</font></a>)"
|
||
body += "<A href='?_src_=holder;[HrefToken()];afreeze=[REF(M)];'><font color='[M.client.afreeze ? "red":"blue"]'>FREEZE</font></a>" //yogs - adminfreezing
|
||
|
||
body += "<br><br>"
|
||
body += "<A href='?_src_=holder;[HrefToken()];jumpto=[REF(M)]'><b>Jump to</b></A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];getmob=[REF(M)]'>Get</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];sendmob=[REF(M)]'>Send To</A>"
|
||
|
||
body += "<br><br>"
|
||
body += "<A href='?_src_=holder;[HrefToken()];traitor=[REF(M)]'>Traitor panel</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];narrateto=[REF(M)]'>Narrate to</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];subtlemessage=[REF(M)]'>Subtle message</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];languagemenu=[REF(M)]'>Language Menu</A>"
|
||
|
||
body += "<br><br>"
|
||
body += "<A href='?_src_=holder;[HrefToken()];antag_token_give=[M.ckey]'>Give Antag Token</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];antag_token_redeem=[M.ckey]'>Redeem Antag Token</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];searchAntagTokenByKey=[M.ckey]'>See Antag Tokens</A>"
|
||
|
||
if (M.client)
|
||
if(!isnewplayer(M))
|
||
body += "<br><br>"
|
||
body += "<b>Transformation:</b>"
|
||
body += "<br>"
|
||
|
||
//Human
|
||
if(ishuman(M))
|
||
body += "<B>Human</B> | "
|
||
else
|
||
body += "<A href='?_src_=holder;[HrefToken()];humanone=[REF(M)]'>Humanize</A> | "
|
||
|
||
//Monkey
|
||
if(ismonkey(M))
|
||
body += "<B>Monkeyized</B> | "
|
||
else
|
||
body += "<A href='?_src_=holder;[HrefToken()];monkeyone=[REF(M)]'>Monkeyize</A> | "
|
||
|
||
//Corgi
|
||
if(iscorgi(M))
|
||
body += "<B>Corgized</B> | "
|
||
else
|
||
body += "<A href='?_src_=holder;[HrefToken()];corgione=[REF(M)]'>Corgize</A> | "
|
||
|
||
//AI / Cyborg
|
||
if(isAI(M))
|
||
body += "<B>Is an AI | </B> "
|
||
body += "<A href='?_src_=holder;[HrefToken()];checkAIDash=[REF(M)]'>Access AI Dashboard | </A>"
|
||
else if(ishuman(M))
|
||
body += "<A href='?_src_=holder;[HrefToken()];makeai=[REF(M)]'>Make AI</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];makerobot=[REF(M)]'>Make Robot</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];makealien=[REF(M)]'>Make Alien</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];makeslime=[REF(M)]'>Make Slime</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];makeblob=[REF(M)]'>Make Blob</A> | "
|
||
|
||
//Simple Animals
|
||
if(isanimal(M))
|
||
body += "<A href='?_src_=holder;[HrefToken()];makeanimal=[REF(M)]'>Re-Animalize</A> | "
|
||
else
|
||
body += "<A href='?_src_=holder;[HrefToken()];makeanimal=[REF(M)]'>Animalize</A> | "
|
||
|
||
body += "<br><br>"
|
||
body += "<b>Rudimentary transformation:</b><font size=2><br>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.</font><br>"
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=observer;mob=[REF(M)]'>Observer</A> | "
|
||
body += "\[ Alien: <A href='?_src_=holder;[HrefToken()];simplemake=drone;mob=[REF(M)]'>Drone</A>, "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=hunter;mob=[REF(M)]'>Hunter</A>, "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=sentinel;mob=[REF(M)]'>Sentinel</A>, "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=praetorian;mob=[REF(M)]'>Praetorian</A>, "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=queen;mob=[REF(M)]'>Queen</A>, "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=larva;mob=[REF(M)]'>Larva</A> \] "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=human;mob=[REF(M)]'>Human</A> "
|
||
body += "\[ slime: <A href='?_src_=holder;[HrefToken()];simplemake=slime;mob=[REF(M)]'>Baby</A>, "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=adultslime;mob=[REF(M)]'>Adult</A> \] "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=monkey;mob=[REF(M)]'>Monkey</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=robot;mob=[REF(M)]'>Cyborg</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=cat;mob=[REF(M)]'>Cat</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=runtime;mob=[REF(M)]'>Runtime</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=corgi;mob=[REF(M)]'>Corgi</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=ian;mob=[REF(M)]'>Ian</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=crab;mob=[REF(M)]'>Crab</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=coffee;mob=[REF(M)]'>Coffee</A> | "
|
||
body += "\[ Construct: <A href='?_src_=holder;[HrefToken()];simplemake=constructarmored;mob=[REF(M)]'>Juggernaut</A> , "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=constructbuilder;mob=[REF(M)]'>Artificer</A> , "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=constructwraith;mob=[REF(M)]'>Wraith</A> \] "
|
||
body += "<A href='?_src_=holder;[HrefToken()];simplemake=shade;mob=[REF(M)]'>Shade</A>"
|
||
body += "<br>"
|
||
|
||
if (M.client)
|
||
body += "<br><br>"
|
||
body += "<b>Other actions:</b>"
|
||
body += "<br>"
|
||
body += "<A href='?_src_=holder;[HrefToken()];forcespeech=[REF(M)]'>Forcesay</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];tdome1=[REF(M)]'>Thunderdome 1</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];tdome2=[REF(M)]'>Thunderdome 2</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];tdomeadmin=[REF(M)]'>Thunderdome Admin</A> | "
|
||
body += "<A href='?_src_=holder;[HrefToken()];tdomeobserve=[REF(M)]'>Thunderdome Observer</A> | "
|
||
|
||
body += usr.client.YogsPPoptions(M) // YOGS - Player panel stuff, big PP
|
||
body += "<br>"
|
||
body += "</body></html>"
|
||
|
||
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.Round Interaction"
|
||
set name = "Access Newscaster"
|
||
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("<HEAD><meta charset='UTF-8'><TITLE>Admin Newscaster</TITLE></HEAD><H3>Admin Newscaster Unit</H3>")
|
||
|
||
switch(admincaster_screen)
|
||
if(0)
|
||
dat += "Welcome to the admin newscaster.<BR> Here you can add, edit and censor every newspiece on the network."
|
||
dat += "<BR>Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units."
|
||
dat += "<BR>Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!</FONT>"
|
||
if(GLOB.news_network.wanted_issue.active)
|
||
dat+= "<HR><A href='?src=[REF(src)];[HrefToken()];ac_view_wanted=1'>Read Wanted Issue</A>"
|
||
dat+= "<HR><BR><A href='?src=[REF(src)];[HrefToken()];ac_create_channel=1'>Create Feed Channel</A>"
|
||
dat+= "<BR><A href='?src=[REF(src)];[HrefToken()];ac_view=1'>View Feed Channels</A>"
|
||
dat+= "<BR><A href='?src=[REF(src)];[HrefToken()];ac_create_feed_story=1'>Submit new Feed story</A>"
|
||
dat+= "<BR><BR><A href='?src=[REF(usr)];[HrefToken()];mach_close=newscaster_main'>Exit</A>"
|
||
var/wanted_already = 0
|
||
if(GLOB.news_network.wanted_issue.active)
|
||
wanted_already = 1
|
||
dat+="<HR><B>Feed Security functions:</B><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_menu_wanted=1'>[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue</A>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_menu_censor_story=1'>Censor Feed Stories</A>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_menu_censor_channel=1'>Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel).</A>"
|
||
dat+="<BR><HR><A href='?src=[REF(src)];[HrefToken()];ac_set_signature=1'>The newscaster recognises you as:<BR> <FONT COLOR='green'>[src.admin_signature]</FONT></A>"
|
||
if(1)
|
||
dat+= "Station Feed Channels<HR>"
|
||
if( isemptylist(GLOB.news_network.network_channels) )
|
||
dat+="<I>No active channels found...</I>"
|
||
else
|
||
for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
|
||
if(CHANNEL.is_admin_channel)
|
||
dat+="<B><FONT style='BACKGROUND-COLOR: LightGreen'><A href='?src=[REF(src)];ac_show_channel=[REF(CHANNEL)]'>[CHANNEL.channel_name]</A></FONT></B><BR>"
|
||
else
|
||
dat+="<B><A href='?src=[REF(src)];[HrefToken()];ac_show_channel=[REF(CHANNEL)]'>[CHANNEL.channel_name]</A> [(CHANNEL.censored) ? ("<FONT COLOR='red'>***</FONT>") : ""]<BR></B>"
|
||
dat+="<BR><HR><A href='?src=[REF(src)];[HrefToken()];ac_refresh=1'>Refresh</A>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Back</A>"
|
||
if(2)
|
||
dat+="Creating new Feed Channel..."
|
||
dat+="<HR><B><A href='?src=[REF(src)];[HrefToken()];ac_set_channel_name=1'>Channel Name</A>:</B> [src.admincaster_feed_channel.channel_name]<BR>"
|
||
dat+="<B><A href='?src=[REF(src)];[HrefToken()];ac_set_signature=1'>Channel Author</A>:</B> <FONT COLOR='green'>[src.admin_signature]</FONT><BR>"
|
||
dat+="<B><A href='?src=[REF(src)];[HrefToken()];ac_set_channel_lock=1'>Will Accept Public Feeds</A>:</B> [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]<BR><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_submit_new_channel=1'>Submit</A><BR><BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Cancel</A><BR>"
|
||
if(3)
|
||
dat+="Creating new Feed Message..."
|
||
dat+="<HR><B><A href='?src=[REF(src)];[HrefToken()];ac_set_channel_receiving=1'>Receiving Channel</A>:</B> [src.admincaster_feed_channel.channel_name]<BR>" //MARK
|
||
dat+="<B>Message Author:</B> <FONT COLOR='green'>[src.admin_signature]</FONT><BR>"
|
||
dat+="<B><A href='?src=[REF(src)];[HrefToken()];ac_set_new_message=1'>Message Body</A>:</B> [src.admincaster_feed_message.returnBody(-1)] <BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_submit_new_message=1'>Submit</A><BR><BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Cancel</A><BR>"
|
||
if(4)
|
||
dat+="Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].<BR><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Return</A><BR>"
|
||
if(5)
|
||
dat+="Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.<BR><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Return</A><BR>"
|
||
if(6)
|
||
dat+="<B><FONT COLOR='maroon'>ERROR: Could not submit Feed story to Network.</B></FONT><HR><BR>"
|
||
if(src.admincaster_feed_channel.channel_name=="")
|
||
dat+="<FONT COLOR='maroon'>Invalid receiving channel name.</FONT><BR>"
|
||
if(src.admincaster_feed_message.returnBody(-1) == "" || src.admincaster_feed_message.returnBody(-1) == "\[REDACTED\]")
|
||
dat+="<FONT COLOR='maroon'>Invalid message body.</FONT><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[3]'>Return</A><BR>"
|
||
if(7)
|
||
dat+="<B><FONT COLOR='maroon'>ERROR: Could not submit Feed Channel to Network.</B></FONT><HR><BR>"
|
||
if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]")
|
||
dat+="<FONT COLOR='maroon'>Invalid channel name.</FONT><BR>"
|
||
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+="<FONT COLOR='maroon'>Channel name already in use.</FONT><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[2]'>Return</A><BR>"
|
||
if(9)
|
||
dat+="<B>[admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[created by: <FONT COLOR='maroon'>[admincaster_feed_channel.returnAuthor(-1)]</FONT>\]</FONT><HR>"
|
||
if(src.admincaster_feed_channel.censored)
|
||
dat+="<FONT COLOR='red'><B>ATTENTION: </B></FONT>This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.<BR>"
|
||
dat+="No further feed story additions are allowed while the D-Notice is in effect.</FONT><BR><BR>"
|
||
else
|
||
if( isemptylist(src.admincaster_feed_channel.messages) )
|
||
dat+="<I>No feed messages found in channel...</I><BR>"
|
||
else
|
||
var/i = 0
|
||
for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
|
||
i++
|
||
dat+="-[MESSAGE.returnBody(-1)] <BR>"
|
||
if(MESSAGE.img)
|
||
usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
|
||
dat+="<img src='tmp_photo[i].png' width = '180'><BR><BR>"
|
||
dat+="<FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.returnAuthor(-1)]</FONT>\]</FONT><BR>"
|
||
dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]:<br>"
|
||
for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments)
|
||
dat+="[comment.body]<br><font size=1>[comment.author] [comment.time_stamp]</font><br>"
|
||
dat+="<br>"
|
||
dat+="<BR><HR><A href='?src=[REF(src)];[HrefToken()];ac_refresh=1'>Refresh</A>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[1]'>Back</A>"
|
||
if(10)
|
||
dat+="<B>Nanotrasen Feed Censorship Tool</B><BR>"
|
||
dat+="<FONT SIZE=1>NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.<BR>"
|
||
dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.</FONT>"
|
||
dat+="<HR>Select Feed channel to get Stories from:<BR>"
|
||
if(isemptylist(GLOB.news_network.network_channels))
|
||
dat+="<I>No feed channels found active...</I><BR>"
|
||
else
|
||
for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
|
||
dat+="<A href='?src=[REF(src)];[HrefToken()];ac_pick_censor_channel=[REF(CHANNEL)]'>[CHANNEL.channel_name]</A> [(CHANNEL.censored) ? ("<FONT COLOR='red'>***</FONT>") : ""]<BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Cancel</A>"
|
||
if(11)
|
||
dat+="<B>Nanotrasen D-Notice Handler</B><HR>"
|
||
dat+="<FONT SIZE=1>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.</FONT><HR>"
|
||
if(isemptylist(GLOB.news_network.network_channels))
|
||
dat+="<I>No feed channels found active...</I><BR>"
|
||
else
|
||
for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels)
|
||
dat+="<A href='?src=[REF(src)];[HrefToken()];ac_pick_d_notice=[REF(CHANNEL)]'>[CHANNEL.channel_name]</A> [(CHANNEL.censored) ? ("<FONT COLOR='red'>***</FONT>") : ""]<BR>"
|
||
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Back</A>"
|
||
if(12)
|
||
dat+="<B>[src.admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[ created by: <FONT COLOR='maroon'>[src.admincaster_feed_channel.returnAuthor(-1)]</FONT> \]</FONT><BR>"
|
||
dat+="<FONT SIZE=2><A href='?src=[REF(src)];[HrefToken()];ac_censor_channel_author=[REF(src.admincaster_feed_channel)]'>[(src.admincaster_feed_channel.authorCensor) ? ("Undo Author censorship") : ("Censor channel Author")]</A></FONT><HR>"
|
||
|
||
if( isemptylist(src.admincaster_feed_channel.messages) )
|
||
dat+="<I>No feed messages found in channel...</I><BR>"
|
||
else
|
||
for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
|
||
dat+="-[MESSAGE.returnBody(-1)] <BR><FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.returnAuthor(-1)]</FONT>\]</FONT><BR>"
|
||
dat+="<FONT SIZE=2><A href='?src=[REF(src)];[HrefToken()];ac_censor_channel_story_body=[REF(MESSAGE)]'>[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")]</A> - <A href='?src=[REF(src)];[HrefToken()];ac_censor_channel_story_author=[REF(MESSAGE)]'>[(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]</A></FONT><BR>"
|
||
dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: <a href='?src=[REF(src)];[HrefToken()];ac_lock_comment=[REF(MESSAGE)]'>[MESSAGE.locked ? "Unlock" : "Lock"]</a><br>"
|
||
for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments)
|
||
dat+="[comment.body] <a href='?src=[REF(src)];[HrefToken()];ac_del_comment=[REF(comment)];ac_del_comment_msg=[REF(MESSAGE)]'>X</a><br><font size=1>[comment.author] [comment.time_stamp]</font><br>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[10]'>Back</A>"
|
||
if(13)
|
||
dat+="<B>[src.admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[ created by: <FONT COLOR='maroon'>[src.admincaster_feed_channel.returnAuthor(-1)]</FONT> \]</FONT><BR>"
|
||
dat+="Channel messages listed below. If you deem them dangerous to the station, you can <A href='?src=[REF(src)];[HrefToken()];ac_toggle_d_notice=[REF(src.admincaster_feed_channel)]'>Bestow a D-Notice upon the channel</A>.<HR>"
|
||
if(src.admincaster_feed_channel.censored)
|
||
dat+="<FONT COLOR='red'><B>ATTENTION: </B></FONT>This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.<BR>"
|
||
dat+="No further feed story additions are allowed while the D-Notice is in effect.</FONT><BR><BR>"
|
||
else
|
||
if( isemptylist(src.admincaster_feed_channel.messages) )
|
||
dat+="<I>No feed messages found in channel...</I><BR>"
|
||
else
|
||
for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
|
||
dat+="-[MESSAGE.returnBody(-1)] <BR><FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.returnAuthor(-1)]</FONT>\]</FONT><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[11]'>Back</A>"
|
||
if(14)
|
||
dat+="<B>Wanted Issue Handler:</B>"
|
||
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+="<FONT SIZE=2><BR><I>A wanted issue is already in Feed Circulation. You can edit or cancel it below.</FONT></I>"
|
||
dat+="<HR>"
|
||
dat+="<A href='?src=[REF(src)];[HrefToken()];ac_set_wanted_name=1'>Criminal Name</A>: [src.admincaster_wanted_message.criminal] <BR>"
|
||
dat+="<A href='?src=[REF(src)];[HrefToken()];ac_set_wanted_desc=1'>Description</A>: [src.admincaster_wanted_message.body] <BR>"
|
||
if(wanted_already)
|
||
dat+="<B>Wanted Issue created by:</B><FONT COLOR='green'>[GLOB.news_network.wanted_issue.scannedUser]</FONT><BR>"
|
||
else
|
||
dat+="<B>Wanted Issue will be created under prosecutor:</B><FONT COLOR='green'>[src.admin_signature]</FONT><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_submit_wanted=[end_param]'>[(wanted_already) ? ("Edit Issue") : ("Submit")]</A>"
|
||
if(wanted_already)
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_cancel_wanted=1'>Take down Issue</A>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Cancel</A>"
|
||
if(15)
|
||
dat+="<FONT COLOR='green'>Wanted issue for [src.admincaster_wanted_message.criminal] is now in Network Circulation.</FONT><BR><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Return</A><BR>"
|
||
if(16)
|
||
dat+="<B><FONT COLOR='maroon'>ERROR: Wanted Issue rejected by Network.</B></FONT><HR><BR>"
|
||
if(src.admincaster_wanted_message.criminal =="" || src.admincaster_wanted_message.criminal == "\[REDACTED\]")
|
||
dat+="<FONT COLOR='maroon'>Invalid name for person wanted.</FONT><BR>"
|
||
if(src.admincaster_wanted_message.body == "" || src.admincaster_wanted_message.body == "\[REDACTED\]")
|
||
dat+="<FONT COLOR='maroon'>Invalid description.</FONT><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Return</A><BR>"
|
||
if(17)
|
||
dat+="<B>Wanted Issue successfully deleted from Circulation</B><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Return</A><BR>"
|
||
if(18)
|
||
dat+="<B><FONT COLOR ='maroon'>-- STATIONWIDE WANTED ISSUE --</B></FONT><BR><FONT SIZE=2>\[Submitted by: <FONT COLOR='green'>[GLOB.news_network.wanted_issue.scannedUser]</FONT>\]</FONT><HR>"
|
||
dat+="<B>Criminal</B>: [GLOB.news_network.wanted_issue.criminal]<BR>"
|
||
dat+="<B>Description</B>: [GLOB.news_network.wanted_issue.body]<BR>"
|
||
dat+="<B>Photo:</B>: "
|
||
if(GLOB.news_network.wanted_issue.img)
|
||
usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png")
|
||
dat+="<BR><img src='tmp_photow.png' width = '180'>"
|
||
else
|
||
dat+="None"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Back</A><BR>"
|
||
if(19)
|
||
dat+="<FONT COLOR='green'>Wanted issue for [src.admincaster_wanted_message.criminal] successfully edited.</FONT><BR><BR>"
|
||
dat+="<BR><A href='?src=[REF(src)];[HrefToken()];ac_setScreen=[0]'>Return</A><BR>"
|
||
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
|
||
|
||
var/dat = {"
|
||
<HTML><HEAD><meta charset='UTF-8'></HEAD><BODY>
|
||
<center><B>Game Panel</B></center><hr>\n
|
||
<A href='?src=[REF(src)];[HrefToken()];c_mode=1'>Change Game Mode</A><br>
|
||
"}
|
||
if(GLOB.master_mode == "secret")
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];f_secret=1'>(Force Secret Mode)</A><br>"
|
||
|
||
if(SSticker.is_mode("dynamic"))
|
||
if(SSticker.current_state <= GAME_STATE_PREGAME)
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_roundstart=1'>(Force Roundstart Rulesets)</A><br>"
|
||
if (GLOB.dynamic_forced_roundstart_ruleset.len > 0)
|
||
for(var/datum/dynamic_ruleset/roundstart/rule in GLOB.dynamic_forced_roundstart_ruleset)
|
||
dat += {"<A href='?src=[REF(src)];[HrefToken()];f_dynamic_roundstart_remove=\ref[rule]'>-> [rule.name] <-</A><br>"}
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_roundstart_clear=1'>(Clear Rulesets)</A><br>"
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_options=1'>(Dynamic mode options)</A><br>"
|
||
dat += "<hr/>"
|
||
if(SSticker.IsRoundInProgress())
|
||
dat += "<a href='?src=[REF(src)];[HrefToken()];gamemode_panel=1'>(Game Mode Panel)</a><BR>"
|
||
|
||
dat += {"
|
||
<BR>
|
||
<A href='?src=[REF(src)];[HrefToken()];create_object=1'>Create Object</A><br>
|
||
<A href='?src=[REF(src)];[HrefToken()];quick_create_object=1'>Quick Create Object</A><br>
|
||
<A href='?src=[REF(src)];[HrefToken()];create_turf=1'>Create Turf</A><br>
|
||
<A href='?src=[REF(src)];[HrefToken()];create_mob=1'>Create Mob</A><br>
|
||
"}
|
||
|
||
if(marked_datum && istype(marked_datum, /atom))
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];dupe_marked_datum=1'>Duplicate Marked Datum</A><br>"
|
||
|
||
dat += "</BODY></HTML>"
|
||
|
||
usr << browse(dat, "window=admin2;size=210x200")
|
||
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/list/options = list("Regular Restart")
|
||
if(check_rights(R_SERVER, FALSE))
|
||
options += list("Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
|
||
if(world.TgsAvailable())
|
||
options += "Server Restart (Kill and restart DD)";
|
||
|
||
var/rebootconfirm
|
||
if(SSticker.admin_delay_notice)
|
||
if(alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") == "Yes")
|
||
rebootconfirm = TRUE
|
||
else
|
||
rebootconfirm = TRUE
|
||
if(rebootconfirm)
|
||
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")
|
||
SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10 SECONDS, check_rights(R_SERVER, FALSE)) // Force if they have +SERVER
|
||
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 = "Server.Global Messages"
|
||
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 class='adminnotice'><b>[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:</b></span>\n \t [message]")
|
||
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 = "Admin"
|
||
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 class ='adminnotice'><b>Admin Notice:</b>\n \t [new_admin_notice]</span>")
|
||
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("<font color='blue'>[usr.key] has started the game.[msg]</font>")
|
||
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, "<span class='infoplain'><b>The game will start in 180 seconds.</b></span>")
|
||
SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
|
||
message_admins("<font color='blue'>[usr.key] has cancelled immediate game start. Game will start in 180 seconds.</font>")
|
||
log_admin("[usr.key] has cancelled immediate game start.")
|
||
else
|
||
to_chat(usr, "<font color='red'>Error: Start Now: Game has already started.</font>", confidential=TRUE)
|
||
|
||
return 0
|
||
|
||
/datum/admins/proc/toggleenter()
|
||
set category = "Server"
|
||
set desc="People can't enter"
|
||
set name="Toggle Entering"
|
||
GLOB.enter_allowed = !( GLOB.enter_allowed )
|
||
if (!( GLOB.enter_allowed ))
|
||
to_chat(world, "<B>New players may no longer enter the game.</B>")
|
||
message_admins(span_adminnotice("[key_name_admin(usr)] toggled new player game entering, no players may enter."))
|
||
else
|
||
to_chat(world, "<B>New players may now enter the game.</B>")
|
||
message_admins(span_adminnotice("[key_name_admin(usr)] toggled new player game entering, players can now enter the game freely."))
|
||
log_admin("[key_name(usr)] toggled new player game entering.")
|
||
world.update_status()
|
||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Entering", "[GLOB.enter_allowed ? "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, "<B>The AI job is no longer chooseable.</B>")
|
||
else
|
||
to_chat(world, "<B>The AI job is chooseable now.</B>")
|
||
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, "<B>You may now respawn.</B>")
|
||
else
|
||
to_chat(world, "<B>You may no longer respawn :(</B>")
|
||
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"
|
||
set name="Delay Start/End"
|
||
|
||
if(!check_rights(R_ADMIN)) //YOGS - R_SERVER -> R_ADMIN
|
||
return
|
||
|
||
if(SSticker.current_state < GAME_STATE_PLAYING)
|
||
var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null
|
||
if(newtime)
|
||
newtime = newtime*10
|
||
SSticker.SetTimeLeft(newtime)
|
||
if(newtime < 0)
|
||
to_chat(world, "<b>The game start has been delayed.</b>")
|
||
log_admin("[key_name(usr)] delayed the round start.")
|
||
message_admins("[key_name(usr)] delayed the round start.")
|
||
else
|
||
to_chat(world, "<b>The game will start in [DisplayTimeText(newtime)].</b>")
|
||
SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
|
||
message_admins("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
|
||
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!
|
||
else
|
||
if(!SSticker.delay_end)
|
||
SSticker.admin_delay_notice = input(usr, "Enter a reason for delaying the round end", "Round Delay Reason") as null|text
|
||
if(isnull(SSticker.admin_delay_notice))
|
||
return
|
||
else
|
||
SSticker.admin_delay_notice = null
|
||
SSticker.delay_end = !SSticker.delay_end
|
||
var/reason = SSticker.delay_end ? "for reason: [SSticker.admin_delay_notice]" : ""
|
||
var/msg = "[SSticker.delay_end ? "delayed" : "undelayed"] the round end [reason]"
|
||
log_admin("[key_name(usr)] [msg]")
|
||
message_admins("[key_name_admin(usr)] [msg]")
|
||
if(SSticker.ready_for_reboot && !SSticker.delay_end) //we undelayed after standard reboot would occur
|
||
if(tgui_alert(usr,"Restart the round?.","Round restart",list("Yes","No")) == "Yes")
|
||
SSticker.Reboot(delay = 100, force = TRUE)
|
||
|
||
/datum/admins/proc/unprison(mob/M in GLOB.mob_list)
|
||
set category = "Admin.Player Interaction"
|
||
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)
|
||
set category = "Misc.Server Debug"
|
||
set desc = "(atom path) Spawn an atom"
|
||
set name = "Spawn"
|
||
|
||
if(!check_rights(R_SPAWN))
|
||
return
|
||
|
||
var/chosen = pick_closest_path(object)
|
||
if(!chosen)
|
||
return
|
||
var/turf/T = get_turf(usr)
|
||
|
||
if(ispath(chosen, /turf))
|
||
T.ChangeTurf(chosen)
|
||
else
|
||
var/atom/A = new chosen(T)
|
||
A.flags_1 |= ADMIN_SPAWNED_1
|
||
|
||
log_admin("[key_name(usr)] spawned [chosen] at [AREACOORD(usr)]")
|
||
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!
|
||
|
||
/datum/admins/proc/podspawn_atom(object as text)
|
||
set category = "Misc.Server Debug"
|
||
set desc = "(atom path) Spawn an atom via supply drop"
|
||
set name = "Podspawn"
|
||
|
||
if(!check_rights(R_SPAWN))
|
||
return
|
||
|
||
var/chosen = pick_closest_path(object)
|
||
if(!chosen)
|
||
return
|
||
var/turf/T = get_turf(usr)
|
||
|
||
if(ispath(chosen, /turf))
|
||
T.ChangeTurf(chosen)
|
||
else
|
||
var/obj/structure/closet/supplypod/centcompod/pod = new()
|
||
var/atom/A = new chosen(pod)
|
||
A.flags_1 |= ADMIN_SPAWNED_1
|
||
new /obj/effect/DPtarget(T, pod)
|
||
|
||
log_admin("[key_name(usr)] pod-spawned [chosen] at [AREACOORD(usr)]")
|
||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Podspawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||
|
||
/datum/admins/proc/spawn_cargo(object as text)
|
||
set category = "Misc.Server Debug"
|
||
set desc = "(atom path) Spawn a cargo crate"
|
||
set name = "Spawn Cargo"
|
||
|
||
if(!check_rights(R_SPAWN))
|
||
return
|
||
|
||
var/chosen = pick_closest_path(object, make_types_fancy(subtypesof(/datum/supply_pack)))
|
||
if(!chosen)
|
||
return
|
||
var/datum/supply_pack/S = new chosen
|
||
S.admin_spawned = TRUE
|
||
S.generate(get_turf(usr))
|
||
|
||
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/M in GLOB.mob_list)
|
||
set category = "Admin.Player Interaction"
|
||
|
||
set desc = "Edit mobs's memory and role"
|
||
set name = "Show Traitor Panel"
|
||
|
||
if(!check_rights(R_ADMIN))
|
||
return
|
||
|
||
if(!istype(M))
|
||
to_chat(usr, "This can only be used on instances of type /mob", confidential=TRUE)
|
||
return
|
||
if(!M.mind)
|
||
to_chat(usr, "This mob has no mind!", confidential=TRUE)
|
||
return
|
||
|
||
M.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/toggletintedweldhelmets()
|
||
set category = "Misc.Server Debug"
|
||
set desc="Reduces view range when wearing welding helmets"
|
||
set name="Toggle tinted welding helmes"
|
||
GLOB.tinted_weldhelh = !( GLOB.tinted_weldhelh )
|
||
if (GLOB.tinted_weldhelh)
|
||
to_chat(world, "<B>The tinted_weldhelh has been enabled!</B>")
|
||
else
|
||
to_chat(world, "<B>The tinted_weldhelh has been disabled!</B>")
|
||
log_admin("[key_name(usr)] toggled tinted_weldhelh.")
|
||
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, "<B>Guests may no longer enter the game.</B>")
|
||
else
|
||
to_chat(world, "<B>Guests may now enter the game.</B>")
|
||
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() // Yogs -- Overridden in yogstation/code/modules/admin/admin.dm
|
||
var/ai_number = 0
|
||
for(var/i in GLOB.silicon_mobs)
|
||
var/mob/living/silicon/S = i
|
||
ai_number++
|
||
if(isAI(S))
|
||
to_chat(usr, "<b>AI [key_name(S, usr)]'s laws:</b>", confidential=TRUE)
|
||
else if(iscyborg(S))
|
||
var/mob/living/silicon/robot/R = S
|
||
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [key_name(R.connected_ai)])":"(Independent)"]: laws:</b>", confidential=TRUE)
|
||
else if (ispAI(S))
|
||
to_chat(usr, "<b>pAI [key_name(S, usr)]'s laws:</b>", confidential=TRUE)
|
||
else
|
||
to_chat(usr, "<b>SOMETHING SILICON [key_name(S, usr)]'s laws:</b>", confidential=TRUE)
|
||
|
||
if (S.laws == null)
|
||
to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.", confidential=TRUE)
|
||
else
|
||
S.laws.show_laws(usr)
|
||
if(!ai_number)
|
||
to_chat(usr, "<b>No AIs located</b>" , confidential=TRUE)
|
||
|
||
/datum/admins/proc/output_all_devil_info()
|
||
var/devil_number = 0
|
||
for(var/datum/mind/D in SSticker.mode.devils)
|
||
devil_number++
|
||
var/datum/antagonist/devil/devil = D.has_antag_datum(/datum/antagonist/devil)
|
||
to_chat(usr, "Devil #[devil_number]:<br><br>" + devil.printdevilinfo(), confidential=TRUE)
|
||
if(!devil_number)
|
||
to_chat(usr, "<b>No Devils located</b>" , confidential=TRUE)
|
||
|
||
/datum/admins/proc/output_devil_info(mob/living/M)
|
||
if(is_devil(M))
|
||
var/datum/antagonist/devil/devil = M.mind.has_antag_datum(/datum/antagonist/devil)
|
||
to_chat(usr, devil.printdevilinfo(), confidential=TRUE)
|
||
else
|
||
to_chat(usr, "<b>[M] is not a devil.", 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
|
||
|
||
dat += "<table>"
|
||
|
||
for(var/j in SSjob.occupations)
|
||
var/datum/job/job = j
|
||
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 += "<tr><td>[J_title]:</td> <td>[J_opPos]/[job.total_positions < 0 ? " (unlimited)" : J_totPos]"
|
||
|
||
dat += "</td>"
|
||
dat += "<td>"
|
||
if(job.total_positions >= 0)
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];customjobslot=[job.title]'>Custom</A> | "
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];addjobslot=[job.title]'>Add 1</A> | "
|
||
if(job.total_positions > job.current_positions)
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];removejobslot=[job.title]'>Remove</A> | "
|
||
else
|
||
dat += "Remove | "
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];unlimitjobslot=[job.title]'>Unlimit</A></td>"
|
||
else
|
||
dat += "<A href='?src=[REF(src)];[HrefToken()];limitjobslot=[job.title]'>Limit</A></td>"
|
||
|
||
browser.height = min(100 + count * 20, 650)
|
||
browser.set_content(dat.Join())
|
||
browser.open()
|
||
|
||
/datum/admins/proc/dynamic_mode_options(mob/user)
|
||
var/dat = {"
|
||
<center><B><h2>Dynamic Mode Options</h2></B></center><hr>
|
||
<br/>
|
||
<h3>Common options</h3>
|
||
<i>All these options can be changed midround.</i> <br/>
|
||
<br/>
|
||
<b>Force extended:</b> - Option is <a href='?src=[REF(src)];[HrefToken()];f_dynamic_force_extended=1'> <b>[GLOB.dynamic_forced_extended ? "ON" : "OFF"]</a></b>.
|
||
<br/>This will force the round to be extended. No rulesets will be drafted. <br/>
|
||
<br/>
|
||
<b>No stacking:</b> - Option is <a href='?src=[REF(src)];[HrefToken()];f_dynamic_no_stacking=1'> <b>[GLOB.dynamic_no_stacking ? "ON" : "OFF"]</b></a>.
|
||
<br/>Unless the threat goes above [GLOB.dynamic_stacking_limit], only one "round-ender" ruleset will be drafted. <br/>
|
||
<br/>
|
||
<b>Forced threat level:</b> Current value : <a href='?src=[REF(src)];[HrefToken()];f_dynamic_forced_threat=1'><b>[GLOB.dynamic_forced_threat_level]</b></a>.
|
||
<br/>The value threat is set to if it is higher than -1.<br/>
|
||
<br/>
|
||
<br/>
|
||
<b>Stacking threeshold:</b> Current value : <a href='?src=[REF(src)];[HrefToken()];f_dynamic_stacking_limit=1'><b>[GLOB.dynamic_stacking_limit]</b></a>.
|
||
<br/>The threshold at which "round-ender" rulesets will stack. A value higher than 100 ensure this never happens. <br/>
|
||
"}
|
||
|
||
user << browse(dat, "window=dyn_mode_options;size=900x650")
|
||
|
||
/datum/admins/proc/create_or_modify_area()
|
||
set category = "Misc.Server Debug"
|
||
set name = "Create or modify area"
|
||
create_area(usr)
|
||
|
||
/datum/admins/proc/observe_follow(atom/movable/AM)
|
||
if(!isobserver(owner.mob) && !check_rights(R_ADMIN))
|
||
return
|
||
var/can_ghost = TRUE
|
||
if(!isobserver(owner.mob))
|
||
can_ghost = owner.admin_ghost()
|
||
|
||
if(!can_ghost)
|
||
return
|
||
var/mob/dead/observer/A = owner.mob
|
||
var/mob/living/silicon/ai/I = AM //yogs start - adminfollow now follows AI eyes instead of the core
|
||
if(istype(I) && I.eyeobj)
|
||
A.ManualFollow(I.eyeobj)
|
||
else
|
||
A.ManualFollow(AM) //yogs stop - adminfollow now follows AI eyes instead of the core
|
||
|
||
|
||
//
|
||
//
|
||
//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
|
||
/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, confidential=TRUE)
|
||
kicked_client_names.Add("[C.key]")
|
||
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, mob/tomob)
|
||
|
||
//this is the exact two check rights checks required to edit a ckey with vv.
|
||
if (!check_rights(R_VAREDIT,0) || !check_rights(R_SPAWN|R_DEBUG,0))
|
||
return 0
|
||
|
||
if (!frommob.ckey)
|
||
return 0
|
||
|
||
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 = tgui_alert(usr, question, "Place ghost in control of mob?", list("Yes", "No"))
|
||
if (ask != "Yes")
|
||
return 1
|
||
|
||
if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response
|
||
return 1
|
||
|
||
tomob.ghostize(0)
|
||
|
||
message_admins(span_adminnotice("[key_name_admin(usr)] has put [frommob.key] in control of [tomob.name]."))
|
||
log_admin("[key_name(usr)] stuffed [frommob.key] into [tomob.name].")
|
||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Ghost Drag Control")
|
||
|
||
tomob.ckey = frommob.ckey
|
||
qdel(frommob)
|
||
|
||
return 1
|
||
|
||
/datum/admins/proc/adminmoreinfo(mob/M)
|
||
if(!ismob(M))
|
||
to_chat(usr, "This can only be used on instances of type /mob.", confidential=TRUE)
|
||
return
|
||
|
||
var/location_description = ""
|
||
var/special_role_description = ""
|
||
var/health_description = ""
|
||
var/gender_description = ""
|
||
var/turf/T = get_turf(M)
|
||
|
||
//Location
|
||
if(isturf(T))
|
||
if(isarea(T.loc))
|
||
location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area <b>[T.loc]</b>)"
|
||
else
|
||
location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])"
|
||
|
||
//Job + antagonist
|
||
if(M.mind)
|
||
special_role_description = "Role: <b>[M.mind.assigned_role]</b>; Antagonist: <font color='red'><b>[M.mind.special_role]</b></font>"
|
||
else
|
||
special_role_description = "Role: <i>Mind datum missing</i> Antagonist: <i>Mind datum missing</i>"
|
||
|
||
//Health
|
||
if(isliving(M))
|
||
var/mob/living/L = M
|
||
var/status
|
||
switch (M.stat)
|
||
if(CONSCIOUS)
|
||
status = "Alive"
|
||
if(SOFT_CRIT)
|
||
status = "<font color='orange'><b>Dying</b></font>"
|
||
if(UNCONSCIOUS)
|
||
status = "<font color='orange'><b>[L.InCritical() ? "Unconscious and Dying" : "Unconscious"]</b></font>"
|
||
if(DEAD)
|
||
status = "<font color='red'><b>Dead</b></font>"
|
||
health_description = "Status = [status]"
|
||
health_description += "<BR>Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getOrganLoss(ORGAN_SLOT_BRAIN)] - Stamina: [L.getStaminaLoss()]"
|
||
else
|
||
health_description = "This mob type has no health to speak of."
|
||
|
||
//Gender
|
||
switch(M.gender)
|
||
if(MALE,FEMALE)
|
||
gender_description = "[M.gender]"
|
||
else
|
||
gender_description = "<font color='red'><b>[M.gender]</b></font>"
|
||
|
||
to_chat(src.owner, "<b>Info about [M.name]:</b> ", confidential=TRUE)
|
||
to_chat(src.owner, "Mob type = [M.type]; Gender = [gender_description] Damage = [health_description]", confidential=TRUE)
|
||
to_chat(src.owner, "Name = <b>[M.name]</b>; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = <b>[M.key]</b>;", confidential=TRUE)
|
||
to_chat(src.owner, "Location = [location_description];", confidential=TRUE)
|
||
to_chat(src.owner, "[special_role_description]", confidential=TRUE)
|
||
to_chat(src.owner, ADMIN_FULLMONTY_NONAME(M), confidential=TRUE)
|
||
|
||
/client/proc/adminGreet(logout)
|
||
if(SSticker.HasRoundStarted())
|
||
var/string
|
||
if(logout && CONFIG_GET(flag/announce_admin_logout))
|
||
string = pick(
|
||
"Admin logout: [key_name(src)]")
|
||
else if(!logout && CONFIG_GET(flag/announce_admin_login) && (prefs.toggles & ANNOUNCE_LOGIN))
|
||
string = pick(
|
||
"Admin login: [key_name(src)]")
|
||
if(string)
|
||
message_admins("[string]")
|