Adds admin tokens

This commit is contained in:
Heroman3003
2022-12-12 05:40:48 +10:00
committed by CHOMPStation2
parent 7566c3306c
commit 70923e0c22
19 changed files with 445 additions and 173 deletions

View File

@@ -46,26 +46,26 @@
#define SMITE_SPONTANEOUSCOMBUSTION "Spontaneous Combustion"
#define SMITE_LIGHTNINGBOLT "Lightning Bolt"
#define ADMIN_QUE(user) "(<a href='?_src_=holder;adminmoreinfo=\ref[user]'>?</a>)"
#define ADMIN_FLW(user) "(<a href='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</a>)"
#define ADMIN_PP(user) "(<a href='?_src_=holder;adminplayeropts=\ref[user]'>PP</a>)"
#define ADMIN_VV(atom) "(<a href='?_src_=vars;Vars=\ref[atom]'>VV</a>)"
#define ADMIN_SM(user) "(<a href='?_src_=holder;subtlemessage=\ref[user]'>SM</a>)"
#define ADMIN_TP(user) "(<a href='?_src_=holder;traitor=\ref[user]'>TP</a>)"
#define ADMIN_BSA(user) "(<a href='?_src_=holder;BlueSpaceArtillery=\ref[user]'>BSA</a>)"
#define ADMIN_KICK(user) "(<a href='?_src_=holder;boot2=\ref[user]'>KICK</a>)"
#define ADMIN_CENTCOM_REPLY(user) "(<a href='?_src_=holder;CentcommReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SYNDICATE_REPLY(user) "(<a href='?_src_=holder;SyndicateReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SC(user) "(<a href='?_src_=holder;adminspawncookie=\ref[user]'>SC</a>)"
#define ADMIN_SMITE(user) "(<a href='?_src_=holder;adminsmite=\ref[user]'>SMITE</a>)"
#define ADMIN_QUE(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminmoreinfo=\ref[user]'>?</a>)"
#define ADMIN_FLW(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayerobservefollow=\ref[user]'>FLW</a>)"
#define ADMIN_PP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayeropts=\ref[user]'>PP</a>)"
#define ADMIN_VV(atom) "(<a href='?_src_=vars;[HrefToken(TRUE)];Vars=\ref[atom]'>VV</a>)"
#define ADMIN_SM(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];subtlemessage=\ref[user]'>SM</a>)"
#define ADMIN_TP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];traitor=\ref[user]'>TP</a>)"
#define ADMIN_BSA(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];BlueSpaceArtillery=\ref[user]'>BSA</a>)"
#define ADMIN_KICK(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];boot2=\ref[user]'>KICK</a>)"
#define ADMIN_CENTCOM_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];CentcommReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SYNDICATE_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];SyndicateReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SC(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminspawncookie=\ref[user]'>SC</a>)"
#define ADMIN_SMITE(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminsmite=\ref[user]'>SMITE</a>)"
#define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]"
#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]"
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)]"
#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]"
#define ADMIN_JMP(src) "(<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)"
#define ADMIN_JMP(src) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)"
#define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]"
#define ADMIN_COORDJMP(src) "[src ? "[COORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]"
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
#define AHELP_RESOLVED 3
#define AHELP_RESOLVED 3

View File

@@ -0,0 +1,25 @@
/// Represents a proc or verb path.
///
/// Despite having no DM-defined static type, proc paths have some variables,
/// listed below. These are not modifiable, but for a given procpath P,
/// `new P(null, "Name", "Desc")` can be used to create a new procpath with the
/// same code but new `name` and `desc` values. The other variables cannot be
/// changed in this way.
///
/// This type exists only to act as an annotation, providing reasonable static
/// typing for procpaths. Previously, types like `/atom/verb` were used, with
/// the `name` and `desc` vars of `/atom` thus being accessible. Proc and verb
/// paths will fail `istype` and `ispath` checks against `/procpath`.
/procpath
// Although these variables are effectively const, if they are marked const
// below, their accesses are optimized away.
/// A text string of the verb's name.
var/name as text
/// The verb's help text or description.
var/desc as text
/// The category or tab the verb will appear in.
var/category as text
/// Only clients/mobs with `see_invisibility` higher can use the verb.
var/invisibility as num
/// Whether or not the verb appears in statpanel and commandbar when you press space
var/hidden as num

View File

@@ -58,3 +58,18 @@
fileaccess_timer = world.time + FTPDELAY
return 0
#undef FTPDELAY
/// Returns the md5 of a file at a given path.
/proc/md5filepath(path)
. = md5(file(path))
/// Save file as an external file then md5 it.
/// Used because md5ing files stored in the rsc sometimes gives incorrect md5 results.
/proc/md5asfile(file)
var/static/notch = 0
// its importaint this code can handle md5filepath sleeping instead of hard blocking, if it's converted to use rust_g.
var/filename = "tmp/md5asfile.[world.realtime].[world.timeofday].[world.time].[world.tick_usage].[notch]"
notch = WRAP(notch+1, 0, 2**15)
fcopy(file, filename)
. = md5filepath(filename)
fdel(filename)

View File

@@ -502,3 +502,184 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
//Animate it growing
animate(img, alpha = 0, transform = matrix()*grow_to, time = anim_duration, loop = loops)
/// generates a filename for a given asset.
/// like generate_asset_name(), except returns the rsc reference and the rsc file hash as well as the asset name (sans extension)
/// used so that certain asset files dont have to be hashed twice
/proc/generate_and_hash_rsc_file(file, dmi_file_path)
var/rsc_ref = fcopy_rsc(file)
var/hash
//if we have a valid dmi file path we can trust md5'ing the rsc file because we know it doesnt have the bug described in http://www.byond.com/forum/post/2611357
if(dmi_file_path)
hash = md5(rsc_ref)
else //otherwise, we need to do the expensive fcopy() workaround
hash = md5asfile(rsc_ref)
return list(rsc_ref, hash, "asset.[hash]")
///given a text string, returns whether it is a valid dmi icons folder path
/proc/is_valid_dmi_file(icon_path)
if(!istext(icon_path) || !length(icon_path))
return FALSE
var/is_in_icon_folder = findtextEx(icon_path, "icons/")
var/is_dmi_file = findtextEx(icon_path, ".dmi")
if(is_in_icon_folder && is_dmi_file)
return TRUE
return FALSE
/// given an icon object, dmi file path, or atom/image/mutable_appearance, attempts to find and return an associated dmi file path.
/// a weird quirk about dm is that /icon objects represent both compile-time or dynamic icons in the rsc,
/// but stringifying rsc references returns a dmi file path
/// ONLY if that icon represents a completely unchanged dmi file from when the game was compiled.
/// so if the given object is associated with an icon that was in the rsc when the game was compiled, this returns a path. otherwise it returns ""
/proc/get_icon_dmi_path(icon/icon)
/// the dmi file path we attempt to return if the given object argument is associated with a stringifiable icon
/// if successful, this looks like "icons/path/to/dmi_file.dmi"
var/icon_path = ""
if(isatom(icon) || istype(icon, /image) || istype(icon, /mutable_appearance))
var/atom/atom_icon = icon
icon = atom_icon.icon
//atom icons compiled in from 'icons/path/to/dmi_file.dmi' are weird and not really icon objects that you generate with icon().
//if theyre unchanged dmi's then they're stringifiable to "icons/path/to/dmi_file.dmi"
if(isicon(icon) && isfile(icon))
//icons compiled in from 'icons/path/to/dmi_file.dmi' at compile time are weird and arent really /icon objects,
///but they pass both isicon() and isfile() checks. theyre the easiest case since stringifying them gives us the path we want
var/icon_ref = "\ref[icon]"
var/locate_icon_string = "[locate(icon_ref)]"
icon_path = locate_icon_string
else if(isicon(icon) && "[icon]" == "/icon")
// icon objects generated from icon() at runtime are icons, but they ARENT files themselves, they represent icon files.
// if the files they represent are compile time dmi files in the rsc, then
// the rsc reference returned by fcopy_rsc() will be stringifiable to "icons/path/to/dmi_file.dmi"
var/rsc_ref = fcopy_rsc(icon)
var/icon_ref = "\ref[rsc_ref]"
var/icon_path_string = "[locate(icon_ref)]"
icon_path = icon_path_string
else if(istext(icon))
var/rsc_ref = fcopy_rsc(icon)
//if its the text path of an existing dmi file, the rsc reference returned by fcopy_rsc() will be stringifiable to a dmi path
var/rsc_ref_ref = "\ref[rsc_ref]"
var/rsc_ref_string = "[locate(rsc_ref_ref)]"
icon_path = rsc_ref_string
if(is_valid_dmi_file(icon_path))
return icon_path
return FALSE
/**
* generate an asset for the given icon or the icon of the given appearance for [thing], and send it to any clients in target.
* Arguments:
* * thing - either a /icon object, or an object that has an appearance (atom, image, mutable_appearance).
* * target - either a reference to or a list of references to /client's or mobs with clients
* * icon_state - string to force a particular icon_state for the icon to be used
* * dir - dir number to force a particular direction for the icon to be used
* * frame - what frame of the icon_state's animation for the icon being used
* * moving - whether or not to use a moving state for the given icon
* * sourceonly - if TRUE, only generate the asset and send back the asset url, instead of tags that display the icon to players
* * extra_clases - string of extra css classes to use when returning the icon string
*/
/proc/icon2html(atom/thing, client/target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE, extra_classes = null)
if (!thing)
return
//if(SSlag_switch.measures[DISABLE_USR_ICON2HTML] && usr && !HAS_TRAIT(usr, TRAIT_BYPASS_MEASURES))
//return
var/key
var/icon/icon2collapse = thing
if (!target)
return
if (target == world)
target = GLOB.clients
var/list/targets
if (!islist(target))
targets = list(target)
else
targets = target
if(!length(targets))
return
//check if the given object is associated with a dmi file in the icons folder. if it is then we dont need to do a lot of work
//for asset generation to get around byond limitations
var/icon_path = get_icon_dmi_path(thing)
if (!isicon(icon2collapse))
if (isfile(thing)) //special snowflake
//var/name = SANITIZE_FILENAME("[generate_asset_name(thing)].png")
var/name = "[generate_asset_name(thing)].png"
if (!SSassets.cache[name])
register_asset(name, thing)
for (var/thing2 in targets)
send_asset(thing2, name)
if(sourceonly)
return get_asset_url(name)
return "<img class='[extra_classes] icon icon-misc' src='[get_asset_url(name)]'>"
//its either an atom, image, or mutable_appearance, we want its icon var
icon2collapse = thing.icon
if (isnull(icon_state))
icon_state = thing.icon_state
//Despite casting to atom, this code path supports mutable appearances, so let's be nice to them
//if(isnull(icon_state) || (isatom(thing) && thing.flags_1 & HTML_USE_INITAL_ICON_1))
if(isnull(icon_state) || isatom(thing))
icon_state = initial(thing.icon_state)
if (isnull(dir))
dir = initial(thing.dir)
if (isnull(dir))
dir = thing.dir
if (ishuman(thing)) // Shitty workaround for a BYOND issue.
var/icon/temp = icon2collapse
icon2collapse = icon()
icon2collapse.Insert(temp, dir = SOUTH)
dir = SOUTH
else
if (isnull(dir))
dir = SOUTH
if (isnull(icon_state))
icon_state = ""
icon2collapse = icon(icon2collapse, icon_state, dir, frame, moving)
var/list/name_and_ref = generate_and_hash_rsc_file(icon2collapse, icon_path)//pretend that tuples exist
var/rsc_ref = name_and_ref[1] //weird object thats not even readable to the debugger, represents a reference to the icons rsc entry
var/file_hash = name_and_ref[2]
key = "[name_and_ref[3]].png"
if(!SSassets.cache[key])
register_asset(key, rsc_ref, file_hash, icon_path)
for (var/client_target in targets)
send_asset(client_target, key)
if(sourceonly)
return get_asset_url(key)
return "<img class='[extra_classes] icon icon-[icon_state]' src='[get_asset_url(key)]'>"
//Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
/proc/costly_icon2html(thing, target, sourceonly = FALSE)
if (!thing)
return
//if(SSlag_switch.measures[DISABLE_USR_ICON2HTML] && usr && !HAS_TRAIT(usr, TRAIT_BYPASS_MEASURES))
//return
if (isicon(thing))
return icon2html(thing, target)
var/icon/I = getFlatIcon(thing)
return icon2html(I, target, sourceonly = sourceonly)

View File

@@ -444,7 +444,7 @@
if("PERMABAN")
typedesc = "<font color='red'><b>PERMABAN</b></font>"
if("TEMPBAN")
typedesc = "<b>TEMPBAN</b><br><font size='2'>([duration] minutes) [(unbanned || auto) ? "" : "(<a href=\"byond://?src=\ref[src];dbbanedit=duration;dbbanid=[banid]\">Edit</a>)"]<br>Expires [expiration]</font>"
typedesc = "<b>TEMPBAN</b><br><font size='2'>([duration] minutes) [(unbanned || auto) ? "" : "(<a href=\"byond://?src=\ref[src];[HrefToken(TRUE)];dbbanedit=duration;dbbanid=[banid]\">Edit</a>)"]<br>Expires [expiration]</font>"
if("JOB_PERMABAN")
typedesc = "<b>JOBBAN</b><br><font size='2'>([job])</font>"
if("JOB_TEMPBAN")
@@ -455,14 +455,14 @@
output += "<td align='center'><b>[ckey]</b></td>"
output += "<td align='center'>[bantime]</td>"
output += "<td align='center'><b>[ackey]</b></td>"
output += "<td align='center'>[(unbanned || auto) ? "" : "<b><a href=\"byond://?src=\ref[src];dbbanedit=unban;dbbanid=[banid]\">Unban</a></b>"]</td>"
output += "<td align='center'>[(unbanned || auto) ? "" : "<b><a href=\"byond://?src=\ref[src];[HrefToken(TRUE)];dbbanedit=unban;dbbanid=[banid]\">Unban</a></b>"]</td>"
output += "</tr>"
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center' colspan='2' bgcolor=''><b>IP:</b> [ip]</td>"
output += "<td align='center' colspan='3' bgcolor=''><b>CIP:</b> [cid]</td>"
output += "</tr>"
output += "<tr bgcolor='[lcolor]'>"
output += "<td align='center' colspan='5'><b>Reason: [(unbanned || auto) ? "" : "(<a href=\"byond://?src=\ref[src];dbbanedit=reason;dbbanid=[banid]\">Edit</a>)"]</b> <cite>\"[reason]\"</cite></td>"
output += "<td align='center' colspan='5'><b>Reason: [(unbanned || auto) ? "" : "(<a href=\"byond://?src=\ref[src];[HrefToken(TRUE)];dbbanedit=reason;dbbanid=[banid]\">Edit</a>)"]</b> <cite>\"[reason]\"</cite></td>"
output += "</tr>"
if(edits)
output += "<tr bgcolor='[dcolor]'>"

View File

@@ -186,7 +186,7 @@ var/savefile/Banlist
if(!expiry) expiry = "Removal Pending"
else expiry = "Permaban"
dat += text("<tr><td><A href='?src=[ref];unbanf=[key][id]'>(U)</A><A href='?src=[ref];unbane=[key][id]'>(E)</A> Key: <B>[key]</B></td><td>ComputerID: <B>[id]</B></td><td>IP: <B>[ip]</B></td><td> [expiry]</td><td>(By: [by])</td><td>(Reason: [reason])</td></tr>")
dat += text("<tr><td><A href='?src=[ref];[HrefToken(TRUE)];unbanf=[key][id]'>(U)</A><A href='?src=[ref];[HrefToken(TRUE)];unbane=[key][id]'>(E)</A> Key: <B>[key]</B></td><td>ComputerID: <B>[id]</B></td><td>IP: <B>[ip]</B></td><td> [expiry]</td><td>(By: [by])</td><td>(Reason: [reason])</td></tr>")
dat += "</table>"
dat = "<HR><B>Bans:</B> <FONT COLOR=blue>(U) = Unban , (E) = Edit Ban</FONT> - <FONT COLOR=green>([count] Bans)</FONT><HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >[dat]"
@@ -227,4 +227,3 @@ var/savefile/Banlist
Banlist.cd = "/base"
for (var/A in Banlist.dir)
RemoveBan(A)

View File

@@ -43,12 +43,12 @@ var/global/floorIsLava = 0
body += "<body>Options panel for <b>[M]</b>"
if(M.client)
body += " played by <b>[M.client]</b> "
body += "\[<A href='?src=\ref[src];editrights=show'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
body += "\[<A href='?src=\ref[src];[HrefToken(TRUE)];editrights=show'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
if(istype(M, /mob/new_player))
body += " <B>Hasn't Entered Game</B> "
else
body += " \[<A href='?src=\ref[src];revive=\ref[M]'>Heal</A>\] "
body += " \[<A href='?src=\ref[src];[HrefToken(TRUE)];revive=\ref[M]'>Heal</A>\] "
if(M.client)
body += "<br><b>First connection:</b> [M.client.player_age] days ago"
@@ -57,41 +57,41 @@ var/global/floorIsLava = 0
body += {"
<br><br>\[
<a href='?_src_=vars;Vars=\ref[M]'>VV</a> -
<a href='?src=\ref[src];traitor=\ref[M]'>TP</a> -
<a href='?src=\ref[usr];priv_msg=\ref[M]'>PM</a> -
<a href='?src=\ref[src];subtlemessage=\ref[M]'>SM</a> -
<a href='?_src_=vars;[HrefToken(TRUE)];Vars=\ref[M]'>VV</a> -
<a href='?src=\ref[src];[HrefToken(TRUE)];traitor=\ref[M]'>TP</a> -
<a href='?src=\ref[usr];[HrefToken(TRUE)];priv_msg=\ref[M]'>PM</a> -
<a href='?src=\ref[src];[HrefToken(TRUE)];subtlemessage=\ref[M]'>SM</a> -
[admin_jump_link(M, src)]\] <br>
<b>Mob type:</b> [M.type]<br>
<b>Inactivity time:</b> [M.client ? "[M.client.inactivity/600] minutes" : "Logged out"]<br/><br/>
<A href='?src=\ref[src];boot2=\ref[M]'>Kick</A> |
<A href='?_src_=holder;warn=[M.ckey]'>Warn</A> |
<A href='?src=\ref[src];newban=\ref[M]'>Ban</A> |
<A href='?src=\ref[src];jobban2=\ref[M]'>Jobban</A> |
<A href='?src=\ref[src];notes=show;mob=\ref[M]'>Notes</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];boot2=\ref[M]'>Kick</A> |
<A href='?_src_=holder;[HrefToken(TRUE)];warn=[M.ckey]'>Warn</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];newban=\ref[M]'>Ban</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];jobban2=\ref[M]'>Jobban</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];notes=show;mob=\ref[M]'>Notes</A>
"}
if(M.client)
body += "| <A HREF='?src=\ref[src];sendtoprison=\ref[M]'>Prison</A> | "
body += "\ <A HREF='?src=\ref[src];sendbacktolobby=\ref[M]'>Send back to Lobby</A> | "
body += "| <A HREF='?src=\ref[src];[HrefToken(TRUE)];sendtoprison=\ref[M]'>Prison</A> | "
body += "\ <A HREF='?src=\ref[src];[HrefToken(TRUE)];sendbacktolobby=\ref[M]'>Send back to Lobby</A> | "
var/muted = M.client.prefs.muted
body += {"<br><b>Mute: </b>
\[<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"blue"]'>IC</font></a> |
<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"blue"]'>OOC</font></a> |
<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"blue"]'>PRAY</font></a> |
<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"blue"]'>ADMINHELP</font></a> |
<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"blue"]'>DEADCHAT</font></a>\]
(<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"blue"]'>toggle all</font></a>)
\[<A href='?src=\ref[src];[HrefToken(TRUE)];mute=\ref[M];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"blue"]'>IC</font></a> |
<A href='?src=\ref[src];[HrefToken(TRUE)];mute=\ref[M];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"blue"]'>OOC</font></a> |
<A href='?src=\ref[src];[HrefToken(TRUE)];mute=\ref[M];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"blue"]'>PRAY</font></a> |
<A href='?src=\ref[src];[HrefToken(TRUE)];mute=\ref[M];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"blue"]'>ADMINHELP</font></a> |
<A href='?src=\ref[src];[HrefToken(TRUE)];mute=\ref[M];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"blue"]'>DEADCHAT</font></a>\]
(<A href='?src=\ref[src];[HrefToken(TRUE)];mute=\ref[M];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"blue"]'>toggle all</font></a>)
"}
body += {"<br><br>
<A href='?src=\ref[src];jumpto=\ref[M]'><b>Jump to</b></A> |
<A href='?src=\ref[src];getmob=\ref[M]'>Get</A> |
<A href='?src=\ref[src];sendmob=\ref[M]'>Send To</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];jumpto=\ref[M]'><b>Jump to</b></A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];getmob=\ref[M]'>Get</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];sendmob=\ref[M]'>Send To</A>
<br><br>
[check_rights(R_ADMIN|R_MOD|R_EVENT,0) ? "<A href='?src=\ref[src];traitor=\ref[M]'>Traitor panel</A> | " : "" ]
<A href='?src=\ref[src];narrateto=\ref[M]'>Narrate to</A> |
<A href='?src=\ref[src];subtlemessage=\ref[M]'>Subtle message</A>
[check_rights(R_ADMIN|R_MOD|R_EVENT,0) ? "<A href='?src=\ref[src];[HrefToken(TRUE)];traitor=\ref[M]'>Traitor panel</A> | " : "" ]
<A href='?src=\ref[src];[HrefToken(TRUE)];narrateto=\ref[M]'>Narrate to</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];subtlemessage=\ref[M]'>Subtle message</A>
"}
if (M.client)
@@ -104,30 +104,30 @@ var/global/floorIsLava = 0
if(issmall(M))
body += "<B>Monkeyized</B> | "
else
body += "<A href='?src=\ref[src];monkeyone=\ref[M]'>Monkeyize</A> | "
body += "<A href='?src=\ref[src];[HrefToken(TRUE)];monkeyone=\ref[M]'>Monkeyize</A> | "
//Corgi
if(iscorgi(M))
body += "<B>Corgized</B> | "
else
body += "<A href='?src=\ref[src];corgione=\ref[M]'>Corgize</A> | "
body += "<A href='?src=\ref[src];[HrefToken(TRUE)];corgione=\ref[M]'>Corgize</A> | "
//AI / Cyborg
if(isAI(M))
body += "<B>Is an AI</B> "
else if(ishuman(M))
body += {"<A href='?src=\ref[src];makeai=\ref[M]'>Make AI</A> |
<A href='?src=\ref[src];makerobot=\ref[M]'>Make Robot</A> |
<A href='?src=\ref[src];makealien=\ref[M]'>Make Alien</A>
body += {"<A href='?src=\ref[src];[HrefToken(TRUE)];makeai=\ref[M]'>Make AI</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];makerobot=\ref[M]'>Make Robot</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];makealien=\ref[M]'>Make Alien</A>
"}
//Simple Animals
if(isanimal(M))
body += "<A href='?src=\ref[src];makeanimal=\ref[M]'>Re-Animalize</A> | "
body += "<A href='?src=\ref[src];[HrefToken(TRUE)];makeanimal=\ref[M]'>Re-Animalize</A> | "
else
body += "<A href='?src=\ref[src];makeanimal=\ref[M]'>Animalize</A> | "
body += "<A href='?src=\ref[src];[HrefToken(TRUE)];makeanimal=\ref[M]'>Animalize</A> | "
body += "<A href='?src=\ref[src];respawn=\ref[M.client]'>Respawn</A> | "
body += "<A href='?src=\ref[src];[HrefToken(TRUE)];respawn=\ref[M.client]'>Respawn</A> | "
// DNA2 - Admin Hax
if(M.dna && iscarbon(M))
@@ -142,7 +142,7 @@ var/global/floorIsLava = 0
if(bname)
var/bstate=M.dna.GetSEState(block)
var/bcolor="[(bstate)?"#006600":"#ff0000"]"
body += "<A href='?src=\ref[src];togmutate=\ref[M];block=[block]' style='color:[bcolor];'>[bname]</A><sub>[block]</sub>"
body += "<A href='?src=\ref[src];[HrefToken(TRUE)];togmutate=\ref[M];block=[block]' style='color:[bcolor];'>[bname]</A><sub>[block]</sub>"
else
body += "[block]"
body+="</td>"
@@ -150,45 +150,45 @@ var/global/floorIsLava = 0
body += {"<br><br>
<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>
<A href='?src=\ref[src];simplemake=observer;mob=\ref[M]'>Observer</A> |
\[ Xenos: <A href='?src=\ref[src];simplemake=larva;mob=\ref[M]'>Larva</A>
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Drone;mob=\ref[M]'>Drone</A>
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Hunter;mob=\ref[M]'>Hunter</A>
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Sentinel;mob=\ref[M]'>Sentinel</A>
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Queen;mob=\ref[M]'>Queen</A> \] |
\[ Crew: <A href='?src=\ref[src];simplemake=human;mob=\ref[M]'>Human</A>
<A href='?src=\ref[src];simplemake=human;species=Unathi;mob=\ref[M]'>Unathi</A>
<A href='?src=\ref[src];simplemake=human;species=Tajaran;mob=\ref[M]'>Tajaran</A>
<A href='?src=\ref[src];simplemake=human;species=Skrell;mob=\ref[M]'>Skrell</A> \] | \[
<A href='?src=\ref[src];simplemake=nymph;mob=\ref[M]'>Nymph</A>
<A href='?src=\ref[src];simplemake=human;species='Diona';mob=\ref[M]'>Diona</A> \] |
\[ slime: <A href='?src=\ref[src];simplemake=slime;mob=\ref[M]'>Baby</A>,
<A href='?src=\ref[src];simplemake=adultslime;mob=\ref[M]'>Adult</A> \]
<A href='?src=\ref[src];simplemake=monkey;mob=\ref[M]'>Monkey</A> |
<A href='?src=\ref[src];simplemake=robot;mob=\ref[M]'>Cyborg</A> |
<A href='?src=\ref[src];simplemake=cat;mob=\ref[M]'>Cat</A> |
<A href='?src=\ref[src];simplemake=runtime;mob=\ref[M]'>Runtime</A> |
<A href='?src=\ref[src];simplemake=corgi;mob=\ref[M]'>Corgi</A> |
<A href='?src=\ref[src];simplemake=ian;mob=\ref[M]'>Ian</A> |
<A href='?src=\ref[src];simplemake=crab;mob=\ref[M]'>Crab</A> |
<A href='?src=\ref[src];simplemake=coffee;mob=\ref[M]'>Coffee</A> |
\[ Construct: <A href='?src=\ref[src];simplemake=constructarmoured;mob=\ref[M]'>Armoured</A> ,
<A href='?src=\ref[src];simplemake=constructbuilder;mob=\ref[M]'>Builder</A> ,
<A href='?src=\ref[src];simplemake=constructwraith;mob=\ref[M]'>Wraith</A> \]
<A href='?src=\ref[src];simplemake=shade;mob=\ref[M]'>Shade</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=observer;mob=\ref[M]'>Observer</A> |
\[ Xenos: <A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=larva;mob=\ref[M]'>Larva</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Xenomorph Drone;mob=\ref[M]'>Drone</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Xenomorph Hunter;mob=\ref[M]'>Hunter</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Xenomorph Sentinel;mob=\ref[M]'>Sentinel</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Xenomorph Queen;mob=\ref[M]'>Queen</A> \] |
\[ Crew: <A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;mob=\ref[M]'>Human</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Unathi;mob=\ref[M]'>Unathi</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Tajaran;mob=\ref[M]'>Tajaran</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species=Skrell;mob=\ref[M]'>Skrell</A> \] | \[
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=nymph;mob=\ref[M]'>Nymph</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=human;species='Diona';mob=\ref[M]'>Diona</A> \] |
\[ slime: <A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=slime;mob=\ref[M]'>Baby</A>,
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=adultslime;mob=\ref[M]'>Adult</A> \]
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=monkey;mob=\ref[M]'>Monkey</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=robot;mob=\ref[M]'>Cyborg</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=cat;mob=\ref[M]'>Cat</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=runtime;mob=\ref[M]'>Runtime</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=corgi;mob=\ref[M]'>Corgi</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=ian;mob=\ref[M]'>Ian</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=crab;mob=\ref[M]'>Crab</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=coffee;mob=\ref[M]'>Coffee</A> |
\[ Construct: <A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=constructarmoured;mob=\ref[M]'>Armoured</A> ,
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=constructbuilder;mob=\ref[M]'>Builder</A> ,
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=constructwraith;mob=\ref[M]'>Wraith</A> \]
<A href='?src=\ref[src];[HrefToken(TRUE)];simplemake=shade;mob=\ref[M]'>Shade</A>
<br>
"}
body += {"<br><br>
<b>Other actions:</b>
<br>
<A href='?src=\ref[src];forcespeech=\ref[M]'>Forcesay</A>
<A href='?src=\ref[src];[HrefToken(TRUE)];forcespeech=\ref[M]'>Forcesay</A>
"}
if (M.client)
body += {" |
<A href='?src=\ref[src];tdome1=\ref[M]'>Thunderdome 1</A> |
<A href='?src=\ref[src];tdome2=\ref[M]'>Thunderdome 2</A> |
<A href='?src=\ref[src];tdomeadmin=\ref[M]'>Thunderdome Admin</A> |
<A href='?src=\ref[src];tdomeobserve=\ref[M]'>Thunderdome Observer</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];tdome1=\ref[M]'>Thunderdome 1</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];tdome2=\ref[M]'>Thunderdome 2</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];tdomeadmin=\ref[M]'>Thunderdome Admin</A> |
<A href='?src=\ref[src];[HrefToken(TRUE)];tdomeobserve=\ref[M]'>Thunderdome Observer</A> |
"}
// language toggles
body += "<br><br><b>Languages:</b><br>"
@@ -199,9 +199,9 @@ var/global/floorIsLava = 0
if(!f) body += " | "
else f = 0
if(L in M.languages)
body += "<a href='?src=\ref[src];toglang=\ref[M];lang=[html_encode(k)]' style='color:#006600'>[k]</a>"
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];toglang=\ref[M];lang=[html_encode(k)]' style='color:#006600'>[k]</a>"
else
body += "<a href='?src=\ref[src];toglang=\ref[M];lang=[html_encode(k)]' style='color:#ff0000'>[k]</a>"
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];toglang=\ref[M];lang=[html_encode(k)]' style='color:#ff0000'>[k]</a>"
body += {"<br>
</body></html>
@@ -527,7 +527,7 @@ var/global/floorIsLava = 0
var/r = t
if( findtext(r,"##") )
r = copytext( r, 1, findtext(r,"##") )//removes the description
dat += text("<tr><td>[t] (<A href='?src=\ref[src];removejobban=[r]'>unban</A>)</td></tr>")
dat += text("<tr><td>[t] (<A href='?src=\ref[src];[HrefToken(TRUE)];removejobban=[r]'>unban</A>)</td></tr>")
dat += "</table>"
usr << browse(dat, "window=ban;size=400x400")
@@ -536,20 +536,20 @@ var/global/floorIsLava = 0
var/dat = {"
<center><B>Game Panel</B></center><hr>\n
<A href='?src=\ref[src];c_mode=1'>Change Game Mode</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];c_mode=1'>Change Game Mode</A><br>
"}
if(master_mode == "secret")
dat += "<A href='?src=\ref[src];f_secret=1'>(Force Secret Mode)</A><br>"
dat += "<A href='?src=\ref[src];[HrefToken(TRUE)];f_secret=1'>(Force Secret Mode)</A><br>"
dat += {"
<BR>
<A href='?src=\ref[src];create_object=1'>Create Object</A><br>
<A href='?src=\ref[src];quick_create_object=1'>Quick Create Object</A><br>
<A href='?src=\ref[src];create_turf=1'>Create Turf</A><br>
<A href='?src=\ref[src];create_mob=1'>Create Mob</A><br>
<br><A href='?src=\ref[src];vsc=airflow'>Edit Airflow Settings</A><br>
<A href='?src=\ref[src];vsc=phoron'>Edit Phoron Settings</A><br>
<A href='?src=\ref[src];vsc=default'>Choose a default ZAS setting</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];create_object=1'>Create Object</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];quick_create_object=1'>Quick Create Object</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];create_turf=1'>Create Turf</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];create_mob=1'>Create Mob</A><br>
<br><A href='?src=\ref[src];[HrefToken(TRUE)];vsc=airflow'>Edit Airflow Settings</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];vsc=phoron'>Edit Phoron Settings</A><br>
<A href='?src=\ref[src];[HrefToken(TRUE)];vsc=default'>Choose a default ZAS setting</A><br>
"}
usr << browse(dat, "window=admin2;size=210x280")
@@ -563,7 +563,7 @@ var/global/floorIsLava = 0
for(var/datum/admin_secret_category/category in admin_secrets.categories)
if(!category.can_view(usr))
continue
dat += "<A href='?src=\ref[src];admin_secrets_panel=\ref[category]'>[category.name]</A> "
dat += "<A href='?src=\ref[src];[HrefToken(TRUE)];admin_secrets_panel=\ref[category]'>[category.name]</A> "
dat += "<HR>"
// If a category is selected, print its description and then options
@@ -574,7 +574,7 @@ var/global/floorIsLava = 0
for(var/datum/admin_secret_item/item in active_category.items)
if(!item.can_view(usr))
continue
dat += "<A href='?src=\ref[src];admin_secrets=\ref[item]'>[item.name()]</A><BR>"
dat += "<A href='?src=\ref[src];[HrefToken(TRUE)];admin_secrets=\ref[item]'>[item.name()]</A><BR>"
dat += "<BR>"
var/datum/browser/popup = new(usr, "secrets", "Secrets", 500, 500)
@@ -1168,34 +1168,34 @@ var/datum/announcement/minor/admin_min_announcer = new
out += "<hr>"
if(ticker.mode.ert_disabled)
out += "<b>Emergency Response Teams:</b> <a href='?src=\ref[ticker.mode];toggle=ert'>disabled</a>"
out += "<b>Emergency Response Teams:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=ert'>disabled</a>"
else
out += "<b>Emergency Response Teams:</b> <a href='?src=\ref[ticker.mode];toggle=ert'>enabled</a>"
out += "<b>Emergency Response Teams:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=ert'>enabled</a>"
out += "<br/>"
if(ticker.mode.deny_respawn)
out += "<b>Respawning:</b> <a href='?src=\ref[ticker.mode];toggle=respawn'>disallowed</a>"
out += "<b>Respawning:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=respawn'>disallowed</a>"
else
out += "<b>Respawning:</b> <a href='?src=\ref[ticker.mode];toggle=respawn'>allowed</a>"
out += "<b>Respawning:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=respawn'>allowed</a>"
out += "<br/>"
out += "<b>Shuttle delay multiplier:</b> <a href='?src=\ref[ticker.mode];set=shuttle_delay'>[ticker.mode.shuttle_delay]</a><br/>"
out += "<b>Shuttle delay multiplier:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];set=shuttle_delay'>[ticker.mode.shuttle_delay]</a><br/>"
if(ticker.mode.auto_recall_shuttle)
out += "<b>Shuttle auto-recall:</b> <a href='?src=\ref[ticker.mode];toggle=shuttle_recall'>enabled</a>"
out += "<b>Shuttle auto-recall:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=shuttle_recall'>enabled</a>"
else
out += "<b>Shuttle auto-recall:</b> <a href='?src=\ref[ticker.mode];toggle=shuttle_recall'>disabled</a>"
out += "<b>Shuttle auto-recall:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=shuttle_recall'>disabled</a>"
out += "<br/><br/>"
if(ticker.mode.event_delay_mod_moderate)
out += "<b>Moderate event time modifier:</b> <a href='?src=\ref[ticker.mode];set=event_modifier_moderate'>[ticker.mode.event_delay_mod_moderate]</a><br/>"
out += "<b>Moderate event time modifier:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];set=event_modifier_moderate'>[ticker.mode.event_delay_mod_moderate]</a><br/>"
else
out += "<b>Moderate event time modifier:</b> <a href='?src=\ref[ticker.mode];set=event_modifier_moderate'>unset</a><br/>"
out += "<b>Moderate event time modifier:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];set=event_modifier_moderate'>unset</a><br/>"
if(ticker.mode.event_delay_mod_major)
out += "<b>Major event time modifier:</b> <a href='?src=\ref[ticker.mode];set=event_modifier_severe'>[ticker.mode.event_delay_mod_major]</a><br/>"
out += "<b>Major event time modifier:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];set=event_modifier_severe'>[ticker.mode.event_delay_mod_major]</a><br/>"
else
out += "<b>Major event time modifier:</b> <a href='?src=\ref[ticker.mode];set=event_modifier_severe'>unset</a><br/>"
out += "<b>Major event time modifier:</b> <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];set=event_modifier_severe'>unset</a><br/>"
out += "<hr>"
@@ -1212,7 +1212,7 @@ var/datum/announcement/minor/admin_min_announcer = new
out += " (not currently scaling, <a href='?src=\ref[ticker.mode];set=antag_scaling'>set a coefficient</a>)"
out += "<br/>"
else
out += "<b>Autotraitor <a href='?src=\ref[ticker.mode];toggle=autotraitor'>disabled</a></b>.<br/>"
out += "<b>Autotraitor <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];toggle=autotraitor'>disabled</a></b>.<br/>"
out += "<b>All antag ids:</b>"
if(ticker.mode.antag_templates && ticker.mode.antag_templates.len)
@@ -1220,10 +1220,10 @@ var/datum/announcement/minor/admin_min_announcer = new
antag.update_current_antag_max()
out += " <a href='?src=\ref[ticker.mode];debug_antag=[antag.id]'>[antag.id]</a>"
out += " ([antag.get_antag_count()]/[antag.cur_max]) "
out += " <a href='?src=\ref[ticker.mode];remove_antag_type=[antag.id]'>\[-\]</a><br/>"
out += " <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];remove_antag_type=[antag.id]'>\[-\]</a><br/>"
else
out += " None."
out += " <a href='?src=\ref[ticker.mode];add_antag_type=1'>\[+\]</a><br/>"
out += " <a href='?src=\ref[ticker.mode];[HrefToken(TRUE)];add_antag_type=1'>\[+\]</a><br/>"
usr << browse(out, "window=edit_mode[src]")
feedback_add_details("admin_verb","SGM")
@@ -1559,12 +1559,12 @@ var/datum/announcement/minor/admin_min_announcer = new
log_admin("[key_name(src.owner)] replied to a fax message from [key_name(P.sender)]")
for(var/client/C in GLOB.admins)
if((R_ADMIN | R_MOD | R_EVENT) & C.holder.rights)
to_chat(C, "<span class='log_message'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(P.sender)] (<a href='?_src_=holder;AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
to_chat(C, "<span class='log_message'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(P.sender)] (<a href='?_src_=holder;[HrefToken(TRUE)];AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
else
log_admin("[key_name(src.owner)] has sent a fax message to [destination.department]")
for(var/client/C in GLOB.admins)
if((R_ADMIN | R_MOD | R_EVENT) & C.holder.rights)
to_chat(C, "<span class='log_message'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] has sent a fax message to [destination.department] (<a href='?_src_=holder;AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
to_chat(C, "<span class='log_message'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] has sent a fax message to [destination.department] (<a href='?_src_=holder;[HrefToken(TRUE)];AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
var/plaintext_title = P.sender ? "replied to [key_name(P.sender)]'s fax" : "sent a fax message to [destination.department]"
var/fax_text = paper_html_to_plaintext(P.info)

View File

@@ -107,9 +107,9 @@ world/New()
output += "<b>Offense:</b>[N.body]<br>"
output += "<small>Occured at [time2text(N.date,"MM/DD hh:mm:ss")]</small><br>"
output += "<small>authored by <i>[N.author]</i></small><br>"
output += " <a href='?src=\ref[report_topic_handler];client=\ref[src];action=remove;ID=[N.ID]'>Flag as Handled</a>"
output += " <a href='?src=\ref[report_topic_handler];client=\ref[src];[HrefToken(TRUE)];action=remove;ID=[N.ID]'>Flag as Handled</a>"
if(src.key == N.author)
output += " <a href='?src=\ref[report_topic_handler];client=\ref[src];action=edit;ID=[N.ID]'>Edit</a>"
output += " <a href='?src=\ref[report_topic_handler];client=\ref[src];[HrefToken(TRUE)];action=edit;ID=[N.ID]'>Edit</a>"
output += "<br>"
output += "<br>"
else
@@ -149,7 +149,7 @@ world/New()
for(var/datum/admin_report/N in reports)
if(N.ID == ID)
found = N
if(!found)
if(!found)
to_chat(src, "<b>* An error occured, sorry.</b>")
found.done = 1
@@ -171,7 +171,7 @@ world/New()
for(var/datum/admin_report/N in reports)
if(N.ID == ID)
found = N
if(!found)
if(!found)
to_chat(src, "<b>* An error occured, sorry.</b>")
var/body = tgui_input_text(src.mob, "Enter a body for the news", "Body", multiline = TRUE, prevent_enter = TRUE)

View File

@@ -1,3 +1,6 @@
GLOBAL_VAR_INIT(href_token, GenerateToken())
GLOBAL_PROTECT(href_token)
var/list/admin_datums = list()
/datum/admins
@@ -13,6 +16,8 @@ var/list/admin_datums = list()
var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel
var/admincaster_signature //What you'll sign the newsfeeds as
var/href_token
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
if(!ckey)
@@ -20,6 +25,7 @@ var/list/admin_datums = list()
qdel(src)
return
admincaster_signature = "[using_map.company_name] Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
href_token = GenerateToken()
rank = initial_rank
rights = initial_rights
admin_datums[ckey] = src
@@ -126,4 +132,26 @@ NOTE: It checks usr by default. Supply the "user" argument if you wish to check
if(rights_required && !(rights_required & subject.holder.rights))
return 0
return 1
return 0
return 0
/proc/GenerateToken()
. = ""
for(var/I in 1 to 32)
. += "[rand(10)]"
/proc/RawHrefToken(forceGlobal = FALSE)
var/tok = GLOB.href_token
if(!forceGlobal && usr)
var/client/C = usr.client
if(!C)
CRASH("No client for HrefToken()!")
var/datum/admins/holder = C.holder
if(holder)
tok = holder.href_token
return tok
/proc/HrefToken(forceGlobal = FALSE)
return "admin_token=[RawHrefToken(forceGlobal)]"
/proc/HrefTokenFormField(forceGlobal = FALSE)
return "<input type='hidden' name='admin_token' value='[RawHrefToken(forceGlobal)]'>"

View File

@@ -211,7 +211,7 @@ var/savefile/Banlistjob
for (var/A in Banlistjob.dir)
count++
Banlistjob.cd = "/base/[A]"
dat += text("<tr><td><A href='?src=\ref[src];unjobbanf=[Banlistjob["key"]][Banlistjob["id"]][Banlistjob["rank"]]'>(U)</A> Key: <B>[Banlistjob["key"]] </B>Rank: <B>[Banlistjob["rank"]]</B></td><td> ([Banlistjob["temp"] ? "[GetBanExpjob(Banlistjob["minutes"]) ? GetBanExpjob(Banlistjob["minutes"]) : "Removal pending" ]" : "Permaban"])</td><td>(By: [Banlistjob["bannedby"]])</td><td>(Reason: [Banlistjob["reason"]])</td></tr>")
dat += text("<tr><td><A href='?src=\ref[src];[HrefToken(TRUE)];unjobbanf=[Banlistjob["key"]][Banlistjob["id"]][Banlistjob["rank"]]'>(U)</A> Key: <B>[Banlistjob["key"]] </B>Rank: <B>[Banlistjob["rank"]]</B></td><td> ([Banlistjob["temp"] ? "[GetBanExpjob(Banlistjob["minutes"]) ? GetBanExpjob(Banlistjob["minutes"]) : "Removal pending" ]" : "Permaban"])</td><td>(By: [Banlistjob["bannedby"]])</td><td>(Reason: [Banlistjob["reason"]])</td></tr>")
dat += "</table>"
dat = "<HR><B>Bans:</B> <FONT COLOR=blue>(U) = Unban , </FONT> - <FONT COLOR=green>([count] Bans)</FONT><HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >[dat]"

View File

@@ -18,7 +18,7 @@
<body onload='selectTextField();updateSearch();'>
<div id='main'><table id='searchable' cellspacing='0'>
<tr class='title'>
<th style='width:125px;text-align:right;'>CKEY <a class='small' href='?src=\ref[src];editrights=add'>\[+\]</a></th>
<th style='width:125px;text-align:right;'>CKEY <a class='small' href='?src=\ref[src];[HrefToken(TRUE)];editrights=add'>\[+\]</a></th>
<th style='width:125px;'>RANK</th><th style='width:100%;'>PERMISSIONS</th>
</tr>
"}
@@ -31,9 +31,9 @@
if(!rights) rights = "*none*"
output += "<tr>"
output += "<td style='text-align:right;'>[adm_ckey] <a class='small' href='?src=\ref[src];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>"
output += "<td><a href='?src=\ref[src];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>"
output += "<td><a class='small' href='?src=\ref[src];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></td>"
output += "<td style='text-align:right;'>[adm_ckey] <a class='small' href='?src=\ref[src];[HrefToken(TRUE)];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>"
output += "<td><a href='?src=\ref[src];[HrefToken(TRUE)];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>"
output += "<td><a class='small' href='?src=\ref[src];[HrefToken(TRUE)];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></td>"
output += "</tr>"
output += {"
@@ -153,5 +153,9 @@
qdel(insert_query) //CHOMPEdit TGSQL
var/DBQuery/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") //CHOMPEdit TGSQL
log_query.Execute()
<<<<<<< HEAD
qdel(log_query) //CHOMPEdit TGSQL
to_chat(usr, "<span class='filter_adminlog'><font color='blue'>Permission added.</font></span>")
to_chat(usr, "<span class='filter_adminlog'><font color='blue'>Permission added.</font></span>")
=======
to_chat(usr, "<span class='filter_adminlog'><font color='blue'>Permission added.</font></span>")
>>>>>>> 3537c20742... Merge pull request #14188 from ItsSelis/selis-admin-tokens

View File

@@ -75,13 +75,13 @@
body += "</td><td align='center'>";
body += "<a href='?src=\ref[src];adminplayeropts="+ref+"'>PP</a> - "
body += "<a href='?src=\ref[src];notes=show;mob="+ref+"'>N</a> - "
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];adminplayeropts="+ref+"'>PP</a> - "
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];notes=show;mob="+ref+"'>N</a> - "
body += "<a href='?_src_=vars;Vars="+ref+"'>VV</a> - "
body += "<a href='?src=\ref[src];traitor="+ref+"'>TP</a> - "
body += "<a href='?src=\ref[usr];priv_msg=\ref"+ref+"'>PM</a> - "
body += "<a href='?src=\ref[src];subtlemessage="+ref+"'>SM</a> - "
body += "<a href='?src=\ref[src];adminplayerobservejump="+ref+"'>JMP</a><br>"
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];traitor="+ref+"'>TP</a> - "
body += "<a href='?src=\ref[usr];[HrefToken(TRUE)];priv_msg=\ref"+ref+"'>PM</a> - "
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];subtlemessage="+ref+"'>SM</a> - "
body += "<a href='?src=\ref[src];[HrefToken(TRUE)];adminplayerobservejump="+ref+"'>JMP</a><br>"
if(antagonist > 0)
body += "<font size='2'><a href='?src=\ref[src];check_antagonist=1'><font color='red'><b>Antagonist</b></font></a></font>";
@@ -389,21 +389,21 @@
dat += "Round Duration: <B>[roundduration2text()]</B><BR>"
dat += "<B>Emergency shuttle</B><BR>"
if (!emergency_shuttle.online())
dat += "<a href='?src=\ref[src];call_shuttle=1'>Call Shuttle</a><br>"
dat += "<a href='?src=\ref[src];[HrefToken(TRUE)];call_shuttle=1'>Call Shuttle</a><br>"
else
if (emergency_shuttle.wait_for_launch)
var/timeleft = emergency_shuttle.estimate_launch_time()
dat += "ETL: <a href='?src=\ref[src];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "ETL: <a href='?src=\ref[src];[HrefToken(TRUE)];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
else if (emergency_shuttle.shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
dat += "ETA: <a href='?src=\ref[src];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "<a href='?src=\ref[src];call_shuttle=2'>Send Back</a><br>"
dat += "ETA: <a href='?src=\ref[src];[HrefToken(TRUE)];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "<a href='?src=\ref[src];[HrefToken(TRUE)];call_shuttle=2'>Send Back</a><br>"
if (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP)
dat += "Launching now..."
dat += "<a href='?src=\ref[src];delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
dat += "<a href='?src=\ref[src];[HrefToken(TRUE)];delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
dat += "<hr>"
for(var/antag_type in all_antag_types)
var/datum/antagonist/A = all_antag_types[antag_type]

View File

@@ -1,3 +1,19 @@
/datum/admins/proc/CheckAdminHref(href, href_list)
var/auth = href_list["admin_token"]
. = auth && (auth == href_token || auth == GLOB.href_token)
if(.)
return
var/msg = !auth ? "no" : "a bad"
message_admins("[key_name_admin(usr)] clicked an href with [msg] authorization key!")
var/debug_admin_hrefs = TRUE // Remove once everything is converted over
if(debug_admin_hrefs)
message_admins("Debug mode enabled, call not blocked. Please ask your coders to review this round's logs.")
log_world("UAH: [href]")
return TRUE
log_admin("[key_name(usr)] clicked an href with [msg] authorization key! [href]")
/datum/admins/Topic(href, href_list)
..()
@@ -6,6 +22,9 @@
message_admins("[usr.key] has attempted to override the admin panel!")
return
if(!CheckAdminHref(href, href_list))
return
if(ticker.mode && ticker.mode.check_antagonists_topic(href, href_list))
check_antagonists()
return

View File

@@ -81,9 +81,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(!l2b)
return
var/list/dat = list("<html><head><title>[title]</title></head>")
dat += "<A HREF='?_src_=holder;ahelp_tickets=[state]'>Refresh</A><br><br>"
dat += "<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp_tickets=[state]'>Refresh</A><br><br>"
for(var/datum/admin_help/AH as anything in l2b)
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A HREF='?_src_=holder;ahelp=\ref[AH];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A HREF='?_src_=holder;ahelp=\ref[AH];[HrefToken(TRUE)];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
usr << browse(dat.Join(), "window=ahelp_list[state];size=600x480")
@@ -250,11 +250,11 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help/proc/ClosureLinks(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=reject'>REJT</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=icissue'>IC</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=close'>CLOSE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=resolve'>RSLVE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=handleissue'>HANDLE</A>)"
. = " (<A HREF='?_src_=holder;ahelp=[ref_src];[HrefToken(TRUE)];ahelp_action=reject'>REJT</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];[HrefToken(TRUE)];ahelp_action=icissue'>IC</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];[HrefToken(TRUE)];ahelp_action=close'>CLOSE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];[HrefToken(TRUE)];ahelp_action=resolve'>RSLVE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];[HrefToken(TRUE)];ahelp_action=handleissue'>HANDLE</A>)"
//private
/datum/admin_help/proc/LinkedReplyName(ref_src)
@@ -266,7 +266,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help/proc/TicketHref(msg, ref_src, action = "ticket")
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=[action]'>[msg]</A>"
return "<A HREF='?_src_=holder;ahelp=[ref_src];[HrefToken(TRUE)];ahelp_action=[action]'>[msg]</A>"
//message from the initiator without a target, all admins will see this
//won't bug irc

View File

@@ -19,7 +19,7 @@ var/inactive_keys = "None<br>"
dat += "<hr>"
dat += "This system was implemented on March 1 2013, and the database a few days before that. Root server access is required to add or disable access to specific custom items.<br>"
else
dat += "<a href='?src=\ref[src];_src_=holder;populate_inactive_customitems=1'>Populate list (requires an active database connection)</a><br>"
dat += "<a href='?src=\ref[src];_src_=holder;[HrefToken(TRUE)];populate_inactive_customitems=1'>Populate list (requires an active database connection)</a><br>"
usr << browse(dat, "window=inactive_customitems;size=600x480")

View File

@@ -8,9 +8,9 @@
name = DA[name] //name is really the index until this line
else
value = DA[name]
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[VV_HK_LIST_EDIT]=1;target=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;[VV_HK_LIST_CHANGE]=1;target=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;[VV_HK_LIST_REMOVE]=1;target=\ref[DA];index=[index]'>-</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken(TRUE)];[VV_HK_LIST_EDIT]=1;target=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken(TRUE)];[VV_HK_LIST_CHANGE]=1;target=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken(TRUE)];[VV_HK_LIST_REMOVE]=1;target=\ref[DA];index=[index]'>-</a>) "
else
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;datummass=\ref[DA];varnamemass=[name]'>M</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken(TRUE)];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken(TRUE)];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken(TRUE)];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
else
header = "<li>"

View File

@@ -35,14 +35,14 @@
/mob/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;mob_player_panel=\ref[src]'>Show player panel</option>
<option value='?_src_=vars;[HrefToken(TRUE)];mob_player_panel=\ref[src]'>Show player panel</option>
<option>---</option>
<option value='?_src_=vars;give_modifier=\ref[src]'>Give Modifier</option>
<option value='?_src_=vars;give_spell=\ref[src]'>Give Spell</option>
<option value='?_src_=vars;give_disease2=\ref[src]'>Give Disease</option>
<option value='?_src_=vars;give_disease=\ref[src]'>Give TG-style Disease</option>
<option value='?_src_=vars;godmode=\ref[src]'>Toggle Godmode</option>
<option value='?_src_=vars;build_mode=\ref[src]'>Toggle Build Mode</option>
<option value='?_src_=vars;[HrefToken(TRUE)];give_modifier=\ref[src]'>Give Modifier</option>
<option value='?_src_=vars;[HrefToken(TRUE)];give_spell=\ref[src]'>Give Spell</option>
<option value='?_src_=vars;[HrefToken(TRUE)];give_disease2=\ref[src]'>Give Disease</option>
<option value='?_src_=vars;[HrefToken(TRUE)];give_disease=\ref[src]'>Give TG-style Disease</option>
<option value='?_src_=vars;[HrefToken(TRUE)];godmode=\ref[src]'>Toggle Godmode</option>
<option value='?_src_=vars;[HrefToken(TRUE)];build_mode=\ref[src]'>Toggle Build Mode</option>
<option value='?_src_=vars;ninja=\ref[src]'>Make Space Ninja</option>
<option value='?_src_=vars;make_skeleton=\ref[src]'>Make 2spooky</option>
@@ -51,26 +51,26 @@
<option value='?_src_=vars;drop_everything=\ref[src]'>Drop Everything</option>
<option value='?_src_=vars;regenerateicons=\ref[src]'>Regenerate Icons</option>
<option value='?_src_=vars;addlanguage=\ref[src]'>Add Language</option>
<option value='?_src_=vars;remlanguage=\ref[src]'>Remove Language</option>
<option value='?_src_=vars;addorgan=\ref[src]'>Add Organ</option>
<option value='?_src_=vars;remorgan=\ref[src]'>Remove Organ</option>
<option value='?_src_=vars;[HrefToken(TRUE)];addlanguage=\ref[src]'>Add Language</option>
<option value='?_src_=vars;[HrefToken(TRUE)];remlanguage=\ref[src]'>Remove Language</option>
<option value='?_src_=vars;[HrefToken(TRUE)];addorgan=\ref[src]'>Add Organ</option>
<option value='?_src_=vars;[HrefToken(TRUE)];remorgan=\ref[src]'>Remove Organ</option>
<option value='?_src_=vars;fix_nano=\ref[src]'>Fix NanoUI</option>
<option value='?_src_=vars;addverb=\ref[src]'>Add Verb</option>
<option value='?_src_=vars;remverb=\ref[src]'>Remove Verb</option>
<option value='?_src_=vars;[HrefToken(TRUE)];addverb=\ref[src]'>Add Verb</option>
<option value='?_src_=vars;[HrefToken(TRUE)];remverb=\ref[src]'>Remove Verb</option>
<option>---</option>
<option value='?_src_=vars;gib=\ref[src]'>Gib</option>
<option value='?_src_=vars;[HrefToken(TRUE)];gib=\ref[src]'>Gib</option>
"}
/mob/living/carbon/human/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;setspecies=\ref[src]'>Set Species</option>
<option value='?_src_=vars;makeai=\ref[src]'>Make AI</option>
<option value='?_src_=vars;makerobot=\ref[src]'>Make cyborg</option>
<option value='?_src_=vars;makemonkey=\ref[src]'>Make monkey</option>
<option value='?_src_=vars;makealien=\ref[src]'>Make alien</option>
<option value='?_src_=vars;[HrefToken(TRUE)];setspecies=\ref[src]'>Set Species</option>
<option value='?_src_=vars;[HrefToken(TRUE)];makeai=\ref[src]'>Make AI</option>
<option value='?_src_=vars;[HrefToken(TRUE)];makerobot=\ref[src]'>Make cyborg</option>
<option value='?_src_=vars;[HrefToken(TRUE)];makemonkey=\ref[src]'>Make monkey</option>
<option value='?_src_=vars;[HrefToken(TRUE)];makealien=\ref[src]'>Make alien</option>
"}
/obj/get_view_variables_options()
@@ -188,4 +188,4 @@
/proc/forbidden_varedit_object_types()
return list(
/datum/admins //Admins editing their own admin-power object? Yup, sounds like a good idea.
)
)

View File

@@ -53,9 +53,9 @@ GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
if(!l2b)
return
var/list/dat = list("<html><head><title>[title]</title></head>")
dat += "<A HREF='?_src_=mentorholder;mhelp_tickets=[state]'>Refresh</A><br><br>"
dat += "<A HREF='?_src_=mentorholder;[HrefToken(TRUE)];mhelp_tickets=[state]'>Refresh</A><br><br>"
for(var/datum/mentor_help/MH as anything in l2b)
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[MH.id]</span>: <A HREF='?_src_=mentorholder;mhelp=\ref[MH];mhelp_action=ticket'>[MH.initiator_ckey]: [MH.name]</A></span><br>"
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[MH.id]</span>: <A HREF='?_src_=mentorholder;mhelp=\ref[MH];[HrefToken(TRUE)];mhelp_action=ticket'>[MH.initiator_ckey]: [MH.name]</A></span><br>"
usr << browse(dat.Join(), "window=mhelp_list[state];size=600x480")
@@ -173,24 +173,24 @@ GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
/datum/mentor_help/proc/ClosureLinks(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = " (<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=resolve'>RSLVE</A>)"
. = " (<A HREF='?_src_=mentorholder;mhelp=[ref_src];[HrefToken(TRUE)];mhelp_action=resolve'>RSLVE</A>)"
//private
/datum/mentor_help/proc/LinkedReplyName(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=reply'>[initiator_ckey]</A>"
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];[HrefToken(TRUE)];mhelp_action=reply'>[initiator_ckey]</A>"
//private
/datum/mentor_help/proc/TicketHref(msg, ref_src, action = "ticket")
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=[action]'>[msg]</A>"
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];[HrefToken(TRUE)];mhelp_action=[action]'>[msg]</A>"
//message from the initiator without a target, all people with mentor powers will see this
/datum/mentor_help/proc/MessageNoRecipient(msg)
var/ref_src = "\ref[src]"
var/chat_msg = "<span class='notice'>(<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=escalate'>ESCALATE</A>) Ticket [TicketHref("#[id]", ref_src)]<b>: [LinkedReplyName(ref_src)]:</b> [msg]</span>"
var/chat_msg = "<span class='notice'>(<A HREF='?_src_=mentorholder;mhelp=[ref_src];[HrefToken(TRUE)];mhelp_action=escalate'>ESCALATE</A>) Ticket [TicketHref("#[id]", ref_src)]<b>: [LinkedReplyName(ref_src)]:</b> [msg]</span>"
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
for (var/client/C in GLOB.mentors)
if (C.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))

View File

@@ -82,6 +82,7 @@
#include "code\__defines\plants.dm"
#include "code\__defines\preferences.dm"
#include "code\__defines\process_scheduler.dm"
#include "code\__defines\procpath.dm"
#include "code\__defines\qdel.dm"
#include "code\__defines\research.dm"
#include "code\__defines\roguemining_vr.dm"