Initial Commit

This commit is contained in:
skull132
2014-03-11 09:03:52 +02:00
commit a8d9450c7e
3486 changed files with 415920 additions and 0 deletions
+406
View File
@@ -0,0 +1,406 @@
datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null)
if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return
establish_db_connection()
if(!dbcon.IsConnected())
return
var/serverip = "[world.internet_address]:[world.port]"
var/bantype_pass = 0
var/bantype_str
switch(bantype)
if(BANTYPE_PERMA)
bantype_str = "PERMABAN"
duration = -1
bantype_pass = 1
if(BANTYPE_TEMP)
bantype_str = "TEMPBAN"
bantype_pass = 1
if(BANTYPE_JOB_PERMA)
bantype_str = "JOB_PERMABAN"
duration = -1
bantype_pass = 1
if(BANTYPE_JOB_TEMP)
bantype_str = "JOB_TEMPBAN"
bantype_pass = 1
if( !bantype_pass ) return
if( !istext(reason) ) return
if( !isnum(duration) ) return
var/ckey
var/computerid
var/ip
if(ismob(banned_mob))
ckey = banned_mob.ckey
if(banned_mob.client)
computerid = banned_mob.client.computer_id
ip = banned_mob.client.address
else if(banckey)
ckey = ckey(banckey)
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'")
query.Execute()
var/validckey = 0
if(query.NextRow())
validckey = 1
if(!validckey)
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
message_admins("<font color='red'>[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.</font>",1)
return
var/a_ckey
var/a_computerid
var/a_ip
if(src.owner && istype(src.owner, /client))
a_ckey = src.owner:ckey
a_computerid = src.owner:computer_id
a_ip = src.owner:address
var/who
for(var/client/C in clients)
if(!who)
who = "[C]"
else
who += ", [C]"
var/adminwho
for(var/client/C in admins)
if(!adminwho)
adminwho = "[C]"
else
adminwho += ", [C]"
reason = sql_sanitize_text(reason)
var/sql = "INSERT INTO erro_ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
var/DBQuery/query_insert = dbcon.NewQuery(sql)
query_insert.Execute()
usr << "\blue Ban saved to database."
message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1)
datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
if(!check_rights(R_BAN)) return
var/bantype_str
if(bantype)
var/bantype_pass = 0
switch(bantype)
if(BANTYPE_PERMA)
bantype_str = "PERMABAN"
bantype_pass = 1
if(BANTYPE_TEMP)
bantype_str = "TEMPBAN"
bantype_pass = 1
if(BANTYPE_JOB_PERMA)
bantype_str = "JOB_PERMABAN"
bantype_pass = 1
if(BANTYPE_JOB_TEMP)
bantype_str = "JOB_TEMPBAN"
bantype_pass = 1
if(BANTYPE_ANY_FULLBAN)
bantype_str = "ANY"
bantype_pass = 1
if( !bantype_pass ) return
var/bantype_sql
if(bantype_str == "ANY")
bantype_sql = "(bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now() ) )"
else
bantype_sql = "bantype = '[bantype_str]'"
var/sql = "SELECT id FROM erro_ban WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
if(job)
sql += " AND job = '[job]'"
establish_db_connection()
if(!dbcon.IsConnected())
return
var/ban_id
var/ban_number = 0 //failsafe
var/DBQuery/query = dbcon.NewQuery(sql)
query.Execute()
while(query.NextRow())
ban_id = query.item[1]
ban_number++;
if(ban_number == 0)
usr << "\red Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin."
return
if(ban_number > 1)
usr << "\red Database update failed due to multiple bans fitting the search criteria. Note down the ckey, job and current time and contact the database admin."
return
if(istext(ban_id))
ban_id = text2num(ban_id)
if(!isnum(ban_id))
usr << "\red Database update failed due to a ban ID mismatch. Contact the database admin."
return
DB_ban_unban_by_id(ban_id)
datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
if(!check_rights(R_BAN)) return
if(!isnum(banid) || !istext(param))
usr << "Cancelled"
return
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]")
query.Execute()
var/eckey = usr.ckey //Editing admin ckey
var/pckey //(banned) Player ckey
var/duration //Old duration
var/reason //Old reason
if(query.NextRow())
pckey = query.item[1]
duration = query.item[2]
reason = query.item[3]
else
usr << "Invalid ban id. Contact the database admin"
return
reason = sql_sanitize_text(reason)
var/value
switch(param)
if("reason")
if(!value)
value = input("Insert the new reason for [pckey]'s ban", "New Reason", "[reason]", null) as null|text
value = sql_sanitize_text(value)
if(!value)
usr << "Cancelled"
return
var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
update_query.Execute()
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
if("duration")
if(!value)
value = input("Insert the new duration (in minutes) for [pckey]'s ban", "New Duration", "[duration]", null) as null|num
if(!isnum(value) || !value)
usr << "Cancelled"
return
var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
update_query.Execute()
if("unban")
if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes")
DB_ban_unban_by_id(banid)
return
else
usr << "Cancelled"
return
else
usr << "Cancelled"
return
datum/admins/proc/DB_ban_unban_by_id(var/id)
if(!check_rights(R_BAN)) return
var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]"
establish_db_connection()
if(!dbcon.IsConnected())
return
var/ban_number = 0 //failsafe
var/pckey
var/DBQuery/query = dbcon.NewQuery(sql)
query.Execute()
while(query.NextRow())
pckey = query.item[1]
ban_number++;
if(ban_number == 0)
usr << "\red Database update failed due to a ban id not being present in the database."
return
if(ban_number > 1)
usr << "\red Database update failed due to multiple bans having the same ID. Contact the database admin."
return
if(!src.owner || !istype(src.owner, /client))
return
var/unban_ckey = src.owner:ckey
var/unban_computerid = src.owner:computer_id
var/unban_ip = src.owner:address
var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]"
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
var/DBQuery/query_update = dbcon.NewQuery(sql_update)
query_update.Execute()
/client/proc/DB_ban_panel()
set category = "Admin"
set name = "Banning Panel"
set desc = "Edit admin permissions"
if(!holder)
return
holder.DB_ban_panel()
/datum/admins/proc/DB_ban_panel(var/playerckey = null, var/adminckey = null)
if(!usr.client)
return
if(!check_rights(R_BAN)) return
establish_db_connection()
if(!dbcon.IsConnected())
usr << "\red Failed to establish database connection"
return
var/output = "<div align='center'><table width='90%'><tr>"
output += "<td width='35%' align='center'>"
output += "<h1>Banning panel</h1>"
output += "</td>"
output += "<td width='65%' align='center' bgcolor='#f9f9f9'>"
output += "<form method='GET' action='?src=\ref[src]'><b>Add custom ban:</b> (ONLY use this if you can't ban through any other method)"
output += "<input type='hidden' name='src' value='\ref[src]'>"
output += "<table width='100%'><tr>"
output += "<td><b>Ban type:</b><select name='dbbanaddtype'>"
output += "<option value=''>--</option>"
output += "<option value='[BANTYPE_PERMA]'>PERMABAN</option>"
output += "<option value='[BANTYPE_TEMP]'>TEMPBAN</option>"
output += "<option value='[BANTYPE_JOB_PERMA]'>JOB PERMABAN</option>"
output += "<option value='[BANTYPE_JOB_TEMP]'>JOB TEMPBAN</option>"
output += "</select></td>"
output += "<td><b>Ckey:</b> <input type='text' name='dbbanaddckey'></td></tr>"
output += "<tr><td><b>Duration:</b> <input type='text' name='dbbaddduration'></td>"
output += "<td><b>Job:</b><select name='dbbanaddjob'>"
output += "<option value=''>--</option>"
for(var/j in get_all_jobs())
output += "<option value='[j]'>[j]</option>"
for(var/j in nonhuman_positions)
output += "<option value='[j]'>[j]</option>"
for(var/j in list("traitor","changeling","operative","revolutionary","cultist","wizard"))
output += "<option value='[j]'>[j]</option>"
output += "</select></td></tr></table>"
output += "<b>Reason:<br></b><textarea name='dbbanreason' cols='50'></textarea><br>"
output += "<input type='submit' value='Add ban'>"
output += "</form>"
output += "</td>"
output += "</tr>"
output += "</table>"
output += "<form method='GET' action='?src=\ref[src]'><b>Search:</b> "
output += "<input type='hidden' name='src' value='\ref[src]'>"
output += "<b>Ckey:</b> <input type='text' name='dbsearchckey' value='[playerckey]'>"
output += "<b>Admin ckey:</b> <input type='text' name='dbsearchadmin' value='[adminckey]'>"
output += "<input type='submit' value='search'>"
output += "</form>"
output += "Please note that all jobban bans or unbans are in-effect the following round."
if(adminckey || playerckey)
var/blcolor = "#ffeeee" //banned light
var/bdcolor = "#ffdddd" //banned dark
var/ulcolor = "#eeffee" //unbanned light
var/udcolor = "#ddffdd" //unbanned dark
output += "<table width='90%' bgcolor='#e3e3e3' cellpadding='5' cellspacing='0' align='center'>"
output += "<tr>"
output += "<th width='25%'><b>TYPE</b></th>"
output += "<th width='20%'><b>CKEY</b></th>"
output += "<th width='20%'><b>TIME APPLIED</b></th>"
output += "<th width='20%'><b>ADMIN</b></th>"
output += "<th width='15%'><b>OPTIONS</b></th>"
output += "</tr>"
adminckey = ckey(adminckey)
playerckey = ckey(playerckey)
var/adminsearch = ""
var/playersearch = ""
if(adminckey)
adminsearch = "AND a_ckey = '[adminckey]' "
if(playerckey)
playersearch = "AND ckey = '[playerckey]' "
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC")
select_query.Execute()
while(select_query.NextRow())
var/banid = select_query.item[1]
var/bantime = select_query.item[2]
var/bantype = select_query.item[3]
var/reason = select_query.item[4]
var/job = select_query.item[5]
var/duration = select_query.item[6]
var/expiration = select_query.item[7]
var/ckey = select_query.item[8]
var/ackey = select_query.item[9]
var/unbanned = select_query.item[10]
var/unbanckey = select_query.item[11]
var/unbantime = select_query.item[12]
var/edits = select_query.item[13]
var/lcolor = blcolor
var/dcolor = bdcolor
if(unbanned)
lcolor = ulcolor
dcolor = udcolor
var/typedesc =""
switch(bantype)
if("PERMABAN")
typedesc = "<font color='red'><b>PERMABAN</b></font>"
if("TEMPBAN")
typedesc = "<b>TEMPBAN</b><br><font size='2'>([duration] minutes [(unbanned) ? "" : "(<a href=\"byond://?src=\ref[src];dbbanedit=duration;dbbanid=[banid]\">Edit</a>))"]<br>Expires [expiration]</font>"
if("JOB_PERMABAN")
typedesc = "<b>JOBBAN</b><br><font size='2'>([job])"
if("JOB_TEMPBAN")
typedesc = "<b>TEMP JOBBAN</b><br><font size='2'>([job])<br>([duration] minutes<br>Expires [expiration]"
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center'>[typedesc]</td>"
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) ? "" : "<b><a href=\"byond://?src=\ref[src];dbbanedit=unban;dbbanid=[banid]\">Unban</a></b>"]</td>"
output += "</tr>"
output += "<tr bgcolor='[lcolor]'>"
output += "<td align='center' colspan='5'><b>Reason: [(unbanned) ? "" : "(<a href=\"byond://?src=\ref[src];dbbanedit=reason;dbbanid=[banid]\">Edit</a>)"]</b> <cite>\"[reason]\"</cite></td>"
output += "</tr>"
if(edits)
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center' colspan='5'><b>EDITS</b></td>"
output += "</tr>"
output += "<tr bgcolor='[lcolor]'>"
output += "<td align='center' colspan='5'><font size='2'>[edits]</font></td>"
output += "</tr>"
if(unbanned)
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center' colspan='5' bgcolor=''><b>UNBANNED by admin [unbanckey] on [unbantime]</b></td>"
output += "</tr>"
output += "<tr>"
output += "<td colspan='5' bgcolor='white'>&nbsp</td>"
output += "</tr>"
output += "</table></div>"
usr << browse(output,"window=lookupbans;size=900x500")
+81
View File
@@ -0,0 +1,81 @@
//Blocks an attempt to connect before even creating our client datum thing.
world/IsBanned(key,address,computer_id)
if(ckey(key) in admin_datums)
return ..()
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
log_access("Failed Login: [key] - Guests not allowed")
message_admins("\blue Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
//check if the IP address is a known TOR node
if(config && config.ToRban && ToRban_isbanned(address))
log_access("Failed Login: [src] - Banned: ToR")
message_admins("\blue Failed Login: [src] - Banned: ToR")
//ban their computer_id and ckey for posterity
AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0)
return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]")
if(config.ban_legacy_system)
//Ban Checking
. = CheckBan( ckey(key), computer_id, address )
if(.)
log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
return .
return ..() //default pager ban stuff
else
var/ckeytext = ckey(key)
if(!establish_db_connection())
world.log << "Ban database connection failure. Key [ckeytext] not checked"
diary << "Ban database connection failure. Key [ckeytext] not checked"
return
var/failedcid = 1
var/failedip = 1
var/ipquery = ""
var/cidquery = ""
if(address)
failedip = 0
ipquery = " OR ip = '[address]' "
if(computer_id)
failedcid = 0
cidquery = " OR computerid = '[computer_id]' "
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_Ban WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
while(query.NextRow())
var/pckey = query.item[1]
//var/pip = query.item[2]
//var/pcid = query.item[3]
var/ackey = query.item[4]
var/reason = query.item[5]
var/expiration = query.item[6]
var/duration = query.item[7]
var/bantime = query.item[8]
var/bantype = query.item[9]
var/expires = ""
if(text2num(duration) > 0)
expires = " The ban is for [duration] minutes and expires on [expiration] (server time)."
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime], [expires]"
return list("reason"="[bantype]", "desc"="[desc]")
if (failedcid)
message_admins("[key] has logged in with a blank computer id in the ban check.")
if (failedip)
message_admins("[key] has logged in with a blank ip in the ban check.")
return ..() //default pager ban stuff
+229
View File
@@ -0,0 +1,229 @@
var/CMinutes = null
var/savefile/Banlist
/proc/CheckBan(var/ckey, var/id, var/address)
if(!Banlist) // if Banlist cannot be located for some reason
LoadBans() // try to load the bans
if(!Banlist) // uh oh, can't find bans!
return 0 // ABORT ABORT ABORT
. = list()
var/appeal
if(config && config.banappeals)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[config.banappeals]'>[config.banappeals]</a>"
Banlist.cd = "/base"
if( "[ckey][id]" in Banlist.dir )
Banlist.cd = "[ckey][id]"
if (Banlist["temp"])
if (!GetExp(Banlist["minutes"]))
ClearTempbans()
return 0
else
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]"
else
Banlist.cd = "/base/[ckey][id]"
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [Banlist["bannedby"]][appeal]"
.["reason"] = "ckey/id"
return .
else
for (var/A in Banlist.dir)
Banlist.cd = "/base/[A]"
var/matches
if( ckey == Banlist["key"] )
matches += "ckey"
if( id == Banlist["id"] )
if(matches)
matches += "/"
matches += "id"
if( address == Banlist["ip"] )
if(matches)
matches += "/"
matches += "ip"
if(matches)
if(Banlist["temp"])
if (!GetExp(Banlist["minutes"]))
ClearTempbans()
return 0
else
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]"
else
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [Banlist["bannedby"]][appeal]"
.["reason"] = matches
return .
return 0
/proc/UpdateTime() //No idea why i made this a proc.
CMinutes = (world.realtime / 10) / 60
return 1
/hook/startup/proc/loadBans()
return LoadBans()
/proc/LoadBans()
Banlist = new("data/banlist.bdb")
log_admin("Loading Banlist")
if (!length(Banlist.dir)) log_admin("Banlist is empty.")
if (!Banlist.dir.Find("base"))
log_admin("Banlist missing base dir.")
Banlist.dir.Add("base")
Banlist.cd = "/base"
else if (Banlist.dir.Find("base"))
Banlist.cd = "/base"
ClearTempbans()
return 1
/proc/ClearTempbans()
UpdateTime()
Banlist.cd = "/base"
for (var/A in Banlist.dir)
Banlist.cd = "/base/[A]"
if (!Banlist["key"] || !Banlist["id"])
RemoveBan(A)
log_admin("Invalid Ban.")
message_admins("Invalid Ban.")
continue
if (!Banlist["temp"]) continue
if (CMinutes >= Banlist["minutes"]) RemoveBan(A)
return 1
/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes, address)
var/bantimestamp
if (temp)
UpdateTime()
bantimestamp = CMinutes + minutes
Banlist.cd = "/base"
if ( Banlist.dir.Find("[ckey][computerid]") )
usr << text("\red Ban already exists.")
return 0
else
Banlist.dir.Add("[ckey][computerid]")
Banlist.cd = "/base/[ckey][computerid]"
Banlist["key"] << ckey
Banlist["id"] << computerid
Banlist["ip"] << address
Banlist["reason"] << reason
Banlist["bannedby"] << bannedby
Banlist["temp"] << temp
if (temp)
Banlist["minutes"] << bantimestamp
return 1
/proc/RemoveBan(foldername)
var/key
var/id
Banlist.cd = "/base/[foldername]"
Banlist["key"] >> key
Banlist["id"] >> id
Banlist.cd = "/base"
if (!Banlist.dir.Remove(foldername)) return 0
if(!usr)
log_admin("Ban Expired: [key]")
message_admins("Ban Expired: [key]")
else
ban_unban_log_save("[key_name_admin(usr)] unbanned [key]")
log_admin("[key_name_admin(usr)] unbanned [key]")
message_admins("[key_name_admin(usr)] unbanned: [key]")
feedback_inc("ban_unban",1)
usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN)
for (var/A in Banlist.dir)
Banlist.cd = "/base/[A]"
if (key == Banlist["key"] /*|| id == Banlist["id"]*/)
Banlist.cd = "/base"
Banlist.dir.Remove(A)
continue
return 1
/proc/GetExp(minutes as num)
UpdateTime()
var/exp = minutes - CMinutes
if (exp <= 0)
return 0
else
var/timeleftstring
if (exp >= 1440) //1440 = 1 day in minutes
timeleftstring = "[round(exp / 1440, 0.1)] Days"
else if (exp >= 60) //60 = 1 hour in minutes
timeleftstring = "[round(exp / 60, 0.1)] Hours"
else
timeleftstring = "[exp] Minutes"
return timeleftstring
/datum/admins/proc/unbanpanel()
var/count = 0
var/dat
//var/dat = "<HR><B>Unban Player:</B> \blue(U) = Unban , (E) = Edit Ban\green (Total<HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >"
Banlist.cd = "/base"
for (var/A in Banlist.dir)
count++
Banlist.cd = "/base/[A]"
var/ref = "\ref[src]"
var/key = Banlist["key"]
var/id = Banlist["id"]
var/ip = Banlist["ip"]
var/reason = Banlist["reason"]
var/by = Banlist["bannedby"]
var/expiry
if(Banlist["temp"])
expiry = GetExp(Banlist["minutes"])
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 += "</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]"
usr << browse(dat, "window=unbanp;size=875x400")
//////////////////////////////////// DEBUG ////////////////////////////////////
/proc/CreateBans()
UpdateTime()
var/i
var/last
for(i=0, i<1001, i++)
var/a = pick(1,0)
var/b = pick(1,0)
if(b)
Banlist.cd = "/base"
Banlist.dir.Add("trash[i]trashid[i]")
Banlist.cd = "/base/trash[i]trashid[i]"
Banlist["key"] << "trash[i]"
else
Banlist.cd = "/base"
Banlist.dir.Add("[last]trashid[i]")
Banlist.cd = "/base/[last]trashid[i]"
Banlist["key"] << last
Banlist["id"] << "trashid[i]"
Banlist["reason"] << "Trashban[i]."
Banlist["temp"] << a
Banlist["minutes"] << CMinutes + rand(1,2000)
Banlist["bannedby"] << "trashmin"
last = "trash[i]"
Banlist.cd = "/base"
/proc/ClearAllBans()
Banlist.cd = "/base"
for (var/A in Banlist.dir)
RemoveBan(A)
+88
View File
@@ -0,0 +1,88 @@
//By Carnwennan
//fetches an external list and processes it into a list of ip addresses.
//It then stores the processed list into a savefile for later use
#define TORFILE "data/ToR_ban.bdb"
#define TOR_UPDATE_INTERVAL 216000 //~6 hours
/proc/ToRban_isbanned(var/ip_address)
var/savefile/F = new(TORFILE)
if(F)
if( ip_address in F.dir )
return 1
return 0
/proc/ToRban_autoupdate()
var/savefile/F = new(TORFILE)
if(F)
var/last_update
F["last_update"] >> last_update
if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while
ToRban_update()
return
/proc/ToRban_update()
spawn(0)
diary << "Downloading updated ToR data..."
var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
var/list/rawlist = file2list(http["CONTENT"])
if(rawlist.len)
fdel(TORFILE)
var/savefile/F = new(TORFILE)
for( var/line in rawlist )
if(!line) continue
if( copytext(line,1,12) == "ExitAddress" )
var/cleaned = copytext(line,13,length(line)-19)
if(!cleaned) continue
F[cleaned] << 1
F["last_update"] << world.realtime
diary << "ToR data updated!"
if(usr) usr << "ToRban updated."
return 1
diary << "ToR data update aborted: no data."
return 0
/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find"))
set name = "ToRban"
set category = "Server"
if(!holder) return
switch(task)
if("update")
ToRban_update()
if("toggle")
if(config)
if(config.ToRban)
config.ToRban = 0
message_admins("<font color='red'>ToR banning disabled.</font>")
else
config.ToRban = 1
message_admins("<font colot='green'>ToR banning enabled.</font>")
if("show")
var/savefile/F = new(TORFILE)
var/dat
if( length(F.dir) )
for( var/i=1, i<=length(F.dir), i++ )
dat += "<tr><td>#[i]</td><td> [F.dir[i]]</td></tr>"
dat = "<table width='100%'>[dat]</table>"
else
dat = "No addresses in list."
src << browse(dat,"window=ToRban_show")
if("remove")
var/savefile/F = new(TORFILE)
var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir
if(choice)
F.dir.Remove(choice)
src << "<b>Address removed</b>"
if("remove all")
src << "<b>[TORFILE] was [fdel(TORFILE)?"":"not "]removed.</b>"
if("find")
var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text
if(input)
if(ToRban_isbanned(input))
src << "<font color='green'><b>Address is a known ToR address</b></font>"
else
src << "<font color='red'><b>Address is not a known ToR address</b></font>"
return
#undef TORFILE
#undef TOR_UPDATE_INTERVAL
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
//By Carnwennan
//This system was made as an alternative to all the in-game lists and variables used to log stuff in-game.
//lists and variables are great. However, they have several major flaws:
//Firstly, they use memory. TGstation has one of the highest memory usage of all the ss13 branches.
//Secondly, they are usually stored in an object. This means that they aren't centralised. It also means that
//the data is lost when the object is deleted! This is especially annoying for things like the singulo engine!
#define INVESTIGATE_DIR "data/investigate/"
//SYSTEM
/proc/investigate_subject2file(var/subject)
return file("[INVESTIGATE_DIR][subject].html")
/hook/startup/proc/resetInvestigate()
investigate_reset()
return 1
/proc/investigate_reset()
if(fdel(INVESTIGATE_DIR)) return 1
return 0
/atom/proc/investigate_log(var/message, var/subject)
if(!message) return
var/F = investigate_subject2file(subject)
if(!F) return
F << "<small>[time2text(world.timeofday,"hh:mm")] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
//ADMINVERBS
/client/proc/investigate_show( subject in list("hrefs","notes","singulo","telesci") )
set name = "Investigate"
set category = "Admin"
if(!holder) return
switch(subject)
if("singulo", "telesci") //general one-round-only stuff
var/F = investigate_subject2file(subject)
if(!F)
src << "<font color='red'>Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed.</font>"
return
src << browse(F,"window=investigate[subject];size=800x300")
if("hrefs") //persistant logs and stuff
if(config && config.log_hrefs)
if(href_logfile)
src << browse(href_logfile,"window=investigate[subject];size=800x300")
else
src << "<font color='red'>Error: admin_investigate: No href logfile found.</font>"
return
else
src << "<font color='red'>Error: admin_investigate: Href Logging is not on.</font>"
return
+54
View File
@@ -0,0 +1,54 @@
#define MEMOFILE "data/memo.sav" //where the memos are saved
#define ENABLE_MEMOS 1 //using a define because screw making a config variable for it. This is more efficient and purty.
//switch verb so we don't spam up the verb lists with like, 3 verbs for this feature.
/client/proc/admin_memo(task in list("write","show","delete"))
set name = "Memo"
set category = "Server"
if(!ENABLE_MEMOS) return
if(!check_rights(0)) return
switch(task)
if("write") admin_memo_write()
if("show") admin_memo_show()
if("delete") admin_memo_delete()
//write a message
/client/proc/admin_memo_write()
var/savefile/F = new(MEMOFILE)
if(F)
var/memo = input(src,"Type your memo\n(Leaving it blank will delete your current memo):","Write Memo",null) as null|message
switch(memo)
if(null)
return
if("")
F.dir.Remove(ckey)
src << "<b>Memo removed</b>"
return
if( findtext(memo,"<script",1,0) )
return
F[ckey] << "[key] on [time2text(world.realtime,"(DDD) DD MMM hh:mm")]<br>[memo]"
message_admins("[key] set an admin memo:<br>[memo]")
//show all memos
/client/proc/admin_memo_show()
if(ENABLE_MEMOS)
var/savefile/F = new(MEMOFILE)
if(F)
for(var/ckey in F.dir)
src << "<center><span class='motd'><b>Admin Memo</b><i> by [F[ckey]]</i></span></center>"
//delete your own or somebody else's memo
/client/proc/admin_memo_delete()
var/savefile/F = new(MEMOFILE)
if(F)
var/ckey
if(check_rights(R_SERVER,0)) //high ranking admins can delete other admin's memos
ckey = input(src,"Whose memo shall we remove?","Remove Memo",null) as null|anything in F.dir
else
ckey = src.ckey
if(ckey)
F.dir.Remove(ckey)
src << "<b>Removed Memo created by [ckey].</b>"
#undef MEMOFILE
#undef ENABLE_MEMOS
+161
View File
@@ -0,0 +1,161 @@
var/list/admin_ranks = list() //list of all ranks with associated rights
//load our rank - > rights associations
/proc/load_admin_ranks()
admin_ranks.Cut()
var/previous_rights = 0
//load text from file
var/list/Lines = file2list("config/admin_ranks.txt")
//process each line seperately
for(var/line in Lines)
if(!length(line)) continue
if(copytext(line,1,2) == "#") continue
var/list/List = text2list(line,"+")
if(!List.len) continue
var/rank = ckeyEx(List[1])
switch(rank)
if(null,"") continue
if("Removed") continue //Reserved
var/rights = 0
for(var/i=2, i<=List.len, i++)
switch(ckey(List[i]))
if("@","prev") rights |= previous_rights
if("buildmode","build") rights |= R_BUILDMODE
if("admin") rights |= R_ADMIN
if("ban") rights |= R_BAN
if("fun") rights |= R_FUN
if("server") rights |= R_SERVER
if("debug") rights |= R_DEBUG
if("permissions","rights") rights |= R_PERMISSIONS
if("possess") rights |= R_POSSESS
if("stealth") rights |= R_STEALTH
if("rejuv","rejuvinate") rights |= R_REJUVINATE
if("varedit") rights |= R_VAREDIT
if("everything","host","all") rights |= R_HOST
if("sound","sounds") rights |= R_SOUNDS
if("spawn","create") rights |= R_SPAWN
if("mod") rights |= R_MOD
admin_ranks[rank] = rights
previous_rights = rights
#ifdef TESTING
var/msg = "Permission Sets Built:\n"
for(var/rank in admin_ranks)
msg += "\t[rank] - [admin_ranks[rank]]\n"
testing(msg)
#endif
/hook/startup/proc/loadAdmins()
load_admins()
return 1
/proc/load_admins()
//clear the datums references
admin_datums.Cut()
for(var/client/C in admins)
C.remove_admin_verbs()
C.holder = null
admins.Cut()
if(config.admin_legacy_system)
load_admin_ranks()
//load text from file
var/list/Lines = file2list("config/admins.txt")
//process each line seperately
for(var/line in Lines)
if(!length(line)) continue
if(copytext(line,1,2) == "#") continue
//Split the line at every "-"
var/list/List = text2list(line, "-")
if(!List.len) continue
//ckey is before the first "-"
var/ckey = ckey(List[1])
if(!ckey) continue
//rank follows the first "-"
var/rank = ""
if(List.len >= 2)
rank = ckeyEx(List[2])
//load permissions associated with this rank
var/rights = admin_ranks[rank]
//create the admin datum and store it for later use
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
//find the client for a ckey if they are connected and associate them with the new admin datum
D.associate(directory[ckey])
else
//The current admin system uses SQL
establish_db_connection()
if(!dbcon.IsConnected())
world.log << "Failed to connect to database in load_admins(). Reverting to legacy system."
diary << "Failed to connect to database in load_admins(). Reverting to legacy system."
config.admin_legacy_system = 1
load_admins()
return
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin")
query.Execute()
while(query.NextRow())
var/ckey = query.item[1]
var/rank = query.item[2]
if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes.
var/rights = query.item[4]
if(istext(rights)) rights = text2num(rights)
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
//find the client for a ckey if they are connected and associate them with the new admin datum
D.associate(directory[ckey])
if(!admin_datums)
world.log << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system."
diary << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system."
config.admin_legacy_system = 1
load_admins()
return
#ifdef TESTING
var/msg = "Admins Built:\n"
for(var/ckey in admin_datums)
var/rank
var/datum/admins/D = admin_datums[ckey]
if(D) rank = D.rank
msg += "\t[ckey] - [rank]\n"
testing(msg)
#endif
#ifdef TESTING
/client/verb/changerank(newrank in admin_ranks)
if(holder)
holder.rank = newrank
holder.rights = admin_ranks[newrank]
else
holder = new /datum/admins(newrank,admin_ranks[newrank],ckey)
remove_admin_verbs()
holder.associate(src)
/client/verb/changerights(newrights as num)
if(holder)
holder.rights = newrights
else
holder = new /datum/admins("testing",newrights,ckey)
remove_admin_verbs()
holder.associate(src)
#endif
+180
View File
@@ -0,0 +1,180 @@
// Reports are a way to notify admins of wrongdoings that happened
// while no admin was present. They work a bit similar to news, but
// they can only be read by admins and moderators.
// a single admin report
datum/admin_report/var
ID // the ID of the report
body // the content of the report
author // key of the author
date // date on which this was created
done // whether this was handled
offender_key // store the key of the offender
offender_cid // store the cid of the offender
datum/report_topic_handler
Topic(href,href_list)
..()
var/client/C = locate(href_list["client"])
if(href_list["action"] == "show_reports")
C.display_admin_reports()
else if(href_list["action"] == "remove")
C.mark_report_done(text2num(href_list["ID"]))
else if(href_list["action"] == "edit")
C.edit_report(text2num(href_list["ID"]))
var/datum/report_topic_handler/report_topic_handler
world/New()
..()
report_topic_handler = new
// add a new news datums
proc/make_report(body, author, okey, cid)
var/savefile/Reports = new("data/reports.sav")
var/list/reports
var/lastID
Reports["reports"] >> reports
Reports["lastID"] >> lastID
if(!reports) reports = list()
if(!lastID) lastID = 0
var/datum/admin_report/created = new()
created.ID = ++lastID
created.body = body
created.author = author
created.date = world.realtime
created.done = 0
created.offender_key = okey
created.offender_cid = cid
reports.Insert(1, created)
Reports["reports"] << reports
Reports["lastID"] << lastID
// load the reports from disk
proc/load_reports()
var/savefile/Reports = new("data/reports.sav")
var/list/reports
Reports["reports"] >> reports
if(!reports) reports = list()
return reports
// check if there are any unhandled reports
client/proc/unhandled_reports()
if(!src.holder) return 0
var/list/reports = load_reports()
for(var/datum/admin_report/N in reports)
if(N.done)
continue
else return 1
return 0
// checks if the player has an unhandled report against him
client/proc/is_reported()
var/list/reports = load_reports()
for(var/datum/admin_report/N in reports) if(!N.done)
if(N.offender_key == src.key)
return 1
return 0
// display only the reports that haven't been handled
client/proc/display_admin_reports()
set category = "Admin"
set name = "Display Admin Reports"
if(!src.holder) return
var/list/reports = load_reports()
var/output = ""
if(unhandled_reports())
// load the list of unhandled reports
for(var/datum/admin_report/N in reports)
if(N.done)
continue
output += "<b>Reported player:</b> [N.offender_key](CID: [N.offender_cid])<br>"
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>"
if(src.key == N.author)
output += " <a href='?src=\ref[report_topic_handler];client=\ref[src];action=edit;ID=[N.ID]'>Edit</a>"
output += "<br>"
output += "<br>"
else
output += "Whoops, no reports!"
usr << browse(output, "window=news;size=600x400")
client/proc/Report(mob/M as mob in world)
set category = "Admin"
if(!src.holder)
return
var/CID = "Unknown"
if(M.client)
CID = M.client.computer_id
var/body = input(src.mob, "Describe in detail what you're reporting [M] for", "Report") as null|text
if(!body) return
make_report(body, key, M.key, CID)
spawn(1)
display_admin_reports()
client/proc/mark_report_done(ID as num)
if(!src.holder || src.holder.level < 0)
return
var/savefile/Reports = new("data/reports.sav")
var/list/reports
Reports["reports"] >> reports
var/datum/admin_report/found
for(var/datum/admin_report/N in reports)
if(N.ID == ID)
found = N
if(!found) src << "<b>* An error occured, sorry.</b>"
found.done = 1
Reports["reports"] << reports
client/proc/edit_report(ID as num)
if(!src.holder || src.holder.level < 0)
src << "<b>You tried to modify the news, but you're not an admin!"
return
var/savefile/Reports = new("data/reports.sav")
var/list/reports
Reports["reports"] >> reports
var/datum/admin_report/found
for(var/datum/admin_report/N in reports)
if(N.ID == ID)
found = N
if(!found) src << "<b>* An error occured, sorry.</b>"
var/body = input(src.mob, "Enter a body for the news", "Body") as null|message
if(!body) return
found.body = body
Reports["reports"] << reports
+777
View File
@@ -0,0 +1,777 @@
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
var/list/admin_verbs_default = list(
/datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
/client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/
/client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/
/client/proc/hide_verbs, /*hides all our adminverbs*/
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
/client/proc/check_antagonists /*shows all antags*/
// /client/proc/deadchat /*toggles deadchat on/off*/
)
var/list/admin_verbs_admin = list(
/client/proc/player_panel, /*shows an interface for all players, with links to various panels (old style)*/
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
/datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/
/datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/
/datum/admins/proc/announce, /*priority announce something to all clients.*/
/client/proc/colorooc, /*allows us to set a custom colour for everythign we say in ooc*/
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
/client/proc/toggle_view_range, /*changes how far we can see*/
/datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/
/datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
/client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/
/datum/admins/proc/access_news_network, /*allows access of newscasters*/
/client/proc/giveruntimelog, /*allows us to give access to runtime logs to somebody*/
/client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/
/client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/
/client/proc/jumptocoord, /*we ghost and jump to a coordinate*/
/client/proc/Getmob, /*teleports a mob to our location*/
/client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/
// /client/proc/sendmob, /*sends a mob somewhere*/ -Removed due to it needing two sorting procs to work, which were executed every time an admin right-clicked. ~Errorage
/client/proc/Jump,
/client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/
/client/proc/jumptomob, /*allows us to jump to a specific mob*/
/client/proc/jumptoturf, /*allows us to jump to a specific turf*/
/client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/
/client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/
/client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/
/client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/
/client/proc/cmd_admin_create_centcom_report,
/client/proc/check_words, /*displays cult-words*/
/client/proc/check_ai_laws, /*shows AI and borg laws*/
/client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
/client/proc/toggleprayers, /*toggles prayers on/off*/
// /client/proc/toggle_hear_deadcast, /*toggles whether we hear deadchat*/
/client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
/client/proc/secrets,
/datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/
/datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/
/datum/admins/proc/toggledsay, /*toggles dsay on/off for everyone*/
/client/proc/game_panel, /*game panel, allows to change game-mode etc*/
/client/proc/cmd_admin_say, /*admin-only ooc chat*/
/datum/admins/proc/PlayerNotes,
/client/proc/cmd_mod_say,
/datum/admins/proc/show_player_info,
/client/proc/free_slot, /*frees slot for chosen job*/
/client/proc/cmd_admin_change_custom_event,
/client/proc/cmd_admin_rejuvenate,
/client/proc/toggleattacklogs,
/client/proc/toggledebuglogs,
/client/proc/toggleghostwriters,
/datum/admins/proc/show_skills,
/client/proc/check_customitem_activity,
/client/proc/man_up,
/client/proc/global_man_up,
/client/proc/response_team, // Response Teams admin verb
/client/proc/toggle_antagHUD_use,
/client/proc/toggle_antagHUD_restrictions,
/client/proc/allow_character_respawn /* Allows a ghost to respawn */
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
/client/proc/jobbans
)
var/list/admin_verbs_sounds = list(
/client/proc/play_local_sound,
/client/proc/play_sound
)
var/list/admin_verbs_fun = list(
/client/proc/object_talk,
/client/proc/cmd_admin_dress,
/client/proc/cmd_admin_gib_self,
/client/proc/drop_bomb,
/client/proc/cinematic,
/client/proc/one_click_antag,
/datum/admins/proc/toggle_aliens,
/datum/admins/proc/toggle_space_ninja,
/client/proc/send_space_ninja,
/client/proc/cmd_admin_add_freeform_ai_law,
/client/proc/cmd_admin_add_random_ai_law,
/client/proc/make_sound,
/client/proc/toggle_random_events,
/client/proc/set_ooc,
/client/proc/editappear
)
var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, /*allows us to spawn instances*/
/client/proc/respawn_character
)
var/list/admin_verbs_server = list(
/client/proc/Set_Holiday,
/client/proc/ToRban,
/datum/admins/proc/startnow,
/datum/admins/proc/restart,
/datum/admins/proc/delay,
/datum/admins/proc/toggleaban,
/client/proc/toggle_log_hrefs,
/datum/admins/proc/immreboot,
/client/proc/everyone_random,
/datum/admins/proc/toggleAI,
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
/client/proc/cmd_debug_del_all,
/datum/admins/proc/adrev,
/datum/admins/proc/adspawn,
/datum/admins/proc/adjump,
/datum/admins/proc/toggle_aliens,
/datum/admins/proc/toggle_space_ninja,
/client/proc/toggle_random_events,
/client/proc/check_customitem_activity
)
var/list/admin_verbs_debug = list(
/client/proc/cmd_admin_list_open_jobs,
/client/proc/Debug2,
/client/proc/kill_air,
/client/proc/ZASSettings,
/client/proc/cmd_debug_make_powernets,
/client/proc/kill_airgroup,
/client/proc/debug_controller,
/client/proc/cmd_debug_mob_lists,
/client/proc/cmd_admin_delete,
/client/proc/cmd_debug_del_all,
/client/proc/cmd_debug_tog_aliens,
/client/proc/air_report,
/client/proc/reload_admins,
/client/proc/restart_controller,
/client/proc/enable_debug_verbs,
/client/proc/callproc,
/client/proc/toggledebuglogs,
/client/proc/SDQL_query,
/client/proc/SDQL2_query
)
var/list/admin_verbs_possess = list(
/proc/possess,
/proc/release
)
var/list/admin_verbs_permissions = list(
/client/proc/edit_admin_permissions
)
var/list/admin_verbs_rejuv = list(
/client/proc/respawn_character
)
//verbs which can be hidden - needs work
var/list/admin_verbs_hideable = list(
/client/proc/set_ooc,
/client/proc/deadmin_self,
// /client/proc/deadchat,
/client/proc/toggleprayers,
/client/proc/toggle_hear_radio,
/datum/admins/proc/show_traitor_panel,
/datum/admins/proc/toggleenter,
/datum/admins/proc/toggleguests,
/datum/admins/proc/announce,
/client/proc/colorooc,
/client/proc/admin_ghost,
/client/proc/toggle_view_range,
/datum/admins/proc/view_txt_log,
/datum/admins/proc/view_atk_log,
/client/proc/cmd_admin_subtle_message,
/client/proc/cmd_admin_check_contents,
/datum/admins/proc/access_news_network,
/client/proc/admin_call_shuttle,
/client/proc/admin_cancel_shuttle,
/client/proc/cmd_admin_direct_narrate,
/client/proc/cmd_admin_world_narrate,
/client/proc/check_words,
/client/proc/play_local_sound,
/client/proc/play_sound,
/client/proc/object_talk,
/client/proc/cmd_admin_dress,
/client/proc/cmd_admin_gib_self,
/client/proc/drop_bomb,
/client/proc/cinematic,
/datum/admins/proc/toggle_aliens,
/datum/admins/proc/toggle_space_ninja,
/client/proc/send_space_ninja,
/client/proc/cmd_admin_add_freeform_ai_law,
/client/proc/cmd_admin_add_random_ai_law,
/client/proc/cmd_admin_create_centcom_report,
/client/proc/make_sound,
/client/proc/toggle_random_events,
/client/proc/cmd_admin_add_random_ai_law,
/client/proc/Set_Holiday,
/client/proc/ToRban,
/datum/admins/proc/startnow,
/datum/admins/proc/restart,
/datum/admins/proc/delay,
/datum/admins/proc/toggleaban,
/client/proc/toggle_log_hrefs,
/datum/admins/proc/immreboot,
/client/proc/everyone_random,
/datum/admins/proc/toggleAI,
/datum/admins/proc/adrev,
/datum/admins/proc/adspawn,
/datum/admins/proc/adjump,
/client/proc/restart_controller,
/client/proc/cmd_admin_list_open_jobs,
/client/proc/callproc,
/client/proc/Debug2,
/client/proc/reload_admins,
/client/proc/kill_air,
/client/proc/cmd_debug_make_powernets,
/client/proc/kill_airgroup,
/client/proc/debug_controller,
/client/proc/startSinglo,
/client/proc/cmd_debug_mob_lists,
/client/proc/cmd_debug_del_all,
/client/proc/cmd_debug_tog_aliens,
/client/proc/air_report,
/client/proc/enable_debug_verbs,
/proc/possess,
/proc/release
)
var/list/admin_verbs_mod = list(
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game.*/
/client/proc/toggledebuglogs,
/datum/admins/proc/PlayerNotes,
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
/client/proc/cmd_mod_say,
/datum/admins/proc/show_player_info,
/client/proc/player_panel_new,
/client/proc/dsay,
/datum/admins/proc/show_skills,
/client/proc/jobbans,
/client/proc/cmd_admin_subtle_message /*send an message to somebody as a 'voice in their head'*/
)
/client/proc/add_admin_verbs()
if(holder)
verbs += admin_verbs_default
if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself
if(holder.rights & R_ADMIN) verbs += admin_verbs_admin
if(holder.rights & R_BAN) verbs += admin_verbs_ban
if(holder.rights & R_FUN) verbs += admin_verbs_fun
if(holder.rights & R_SERVER) verbs += admin_verbs_server
if(holder.rights & R_DEBUG) verbs += admin_verbs_debug
if(holder.rights & R_POSSESS) verbs += admin_verbs_possess
if(holder.rights & R_PERMISSIONS) verbs += admin_verbs_permissions
if(holder.rights & R_STEALTH) verbs += /client/proc/stealth
if(holder.rights & R_REJUVINATE) verbs += admin_verbs_rejuv
if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds
if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn
if(holder.rights & R_MOD) verbs += admin_verbs_mod
/client/proc/remove_admin_verbs()
verbs.Remove(
admin_verbs_default,
/client/proc/togglebuildmodeself,
admin_verbs_admin,
admin_verbs_ban,
admin_verbs_fun,
admin_verbs_server,
admin_verbs_debug,
admin_verbs_possess,
admin_verbs_permissions,
/client/proc/stealth,
admin_verbs_rejuv,
admin_verbs_sounds,
admin_verbs_spawn,
/*Debug verbs added by "show debug verbs"*/
/client/proc/Cell,
/client/proc/do_not_use_these,
/client/proc/camera_view,
/client/proc/sec_camera_report,
/client/proc/intercom_view,
/client/proc/air_status,
/client/proc/atmosscan,
/client/proc/powerdebug,
/client/proc/count_objects_on_z_level,
/client/proc/count_objects_all,
/client/proc/cmd_assume_direct_control,
/client/proc/jump_to_dead_group,
/client/proc/startSinglo,
/client/proc/ticklag,
/client/proc/cmd_admin_grantfullaccess,
/client/proc/kaboom,
/client/proc/splash,
/client/proc/cmd_admin_areatest
)
/client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs
set name = "Adminverbs - Hide Most"
set category = "Admin"
verbs.Remove(/client/proc/hide_most_verbs, admin_verbs_hideable)
verbs += /client/proc/show_verbs
src << "<span class='interface'>Most of your adminverbs have been hidden.</span>"
feedback_add_details("admin_verb","HMV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/hide_verbs()
set name = "Adminverbs - Hide All"
set category = "Admin"
remove_admin_verbs()
verbs += /client/proc/show_verbs
src << "<span class='interface'>Almost all of your adminverbs have been hidden.</span>"
feedback_add_details("admin_verb","TAVVH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/show_verbs()
set name = "Adminverbs - Show"
set category = "Admin"
verbs -= /client/proc/show_verbs
add_admin_verbs()
src << "<span class='interface'>All of your adminverbs are now visible.</span>"
feedback_add_details("admin_verb","TAVVS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_ghost()
set category = "Admin"
set name = "Aghost"
if(!holder) return
if(istype(mob,/mob/dead/observer))
//re-enter
var/mob/dead/observer/ghost = mob
ghost.can_reenter_corpse = 1 //just in-case.
ghost.reenter_corpse()
feedback_add_details("admin_verb","P") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else if(istype(mob,/mob/new_player))
src << "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.</font>"
else
//ghostize
var/mob/body = mob
body.ghostize(1)
if(body && !body.key)
body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus
feedback_add_details("admin_verb","O") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/invisimin()
set name = "Invisimin"
set category = "Admin"
set desc = "Toggles ghost-like invisibility (Don't abuse this)"
if(holder && mob)
if(mob.invisibility == INVISIBILITY_OBSERVER)
mob.invisibility = initial(mob.invisibility)
mob << "\red <b>Invisimin off. Invisibility reset.</b>"
mob.alpha = max(mob.alpha + 100, 255)
else
mob.invisibility = INVISIBILITY_OBSERVER
mob << "\blue <b>Invisimin on. You are now as invisible as a ghost.</b>"
mob.alpha = max(mob.alpha - 100, 0)
/client/proc/player_panel()
set name = "Player Panel"
set category = "Admin"
if(holder)
holder.player_panel_old()
feedback_add_details("admin_verb","PP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/player_panel_new()
set name = "Player Panel New"
set category = "Admin"
if(holder)
holder.player_panel_new()
feedback_add_details("admin_verb","PPN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/check_antagonists()
set name = "Check Antagonists"
set category = "Admin"
if(holder)
holder.check_antagonists()
log_admin("[key_name(usr)] checked antagonists.") //for tsar~
feedback_add_details("admin_verb","CHA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/jobbans()
set name = "Display Job bans"
set category = "Admin"
if(holder)
if(config.ban_legacy_system)
holder.Jobbans()
else
holder.DB_ban_panel()
feedback_add_details("admin_verb","VJB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/unban_panel()
set name = "Unban Panel"
set category = "Admin"
if(holder)
if(config.ban_legacy_system)
holder.unbanpanel()
else
holder.DB_ban_panel()
feedback_add_details("admin_verb","UBP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/game_panel()
set name = "Game Panel"
set category = "Admin"
if(holder)
holder.Game()
feedback_add_details("admin_verb","GP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/secrets()
set name = "Secrets"
set category = "Admin"
if (holder)
holder.Secrets()
feedback_add_details("admin_verb","S") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/colorooc()
set category = "Fun"
set name = "OOC Text Color"
if(!holder) return
var/new_ooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null
if(new_ooccolor)
prefs.ooccolor = new_ooccolor
prefs.save_preferences()
feedback_add_details("admin_verb","OC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/stealth()
set category = "Admin"
set name = "Stealth Mode"
if(holder)
if(holder.fakekey)
holder.fakekey = null
else
var/new_key = ckeyEx(input("Enter your desired display name.", "Fake Key", key) as text|null)
if(!new_key) return
if(length(new_key) >= 26)
new_key = copytext(new_key, 1, 26)
holder.fakekey = new_key
log_admin("[key_name(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]")
message_admins("[key_name_admin(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]", 1)
feedback_add_details("admin_verb","SM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
#define MAX_WARNS 3
#define AUTOBANTIME 10
/client/proc/warn(warned_ckey)
if(!check_rights(R_ADMIN)) return
if(!warned_ckey || !istext(warned_ckey)) return
if(warned_ckey in admin_datums)
usr << "<font color='red'>Error: warn(): You can't warn admins.</font>"
return
var/datum/preferences/D
var/client/C = directory[warned_ckey]
if(C) D = C.prefs
else D = preferences_datums[warned_ckey]
if(!D)
src << "<font color='red'>Error: warn(): No such ckey found.</font>"
return
if(++D.warns >= MAX_WARNS) //uh ohhhh...you'reee iiiiin trouuuubble O:)
ban_unban_log_save("[ckey] warned [warned_ckey], resulting in a [AUTOBANTIME] minute autoban.")
if(C)
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] resulting in a [AUTOBANTIME] minute ban.")
C << "<font color='red'><BIG><B>You have been autobanned due to a warning by [ckey].</B></BIG><br>This is a temporary ban, it will be removed in [AUTOBANTIME] minutes."
del(C)
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban.")
AddBan(warned_ckey, D.last_id, "Autobanning due to too many formal warnings", ckey, 1, AUTOBANTIME)
feedback_inc("ban_warn",1)
else
if(C)
C << "<font color='red'><BIG><B>You have been formally warned by an administrator.</B></BIG><br>Further warnings will result in an autoban.</font>"
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)]. They have [MAX_WARNS-D.warns] strikes remaining.")
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] (DC). They have [MAX_WARNS-D.warns] strikes remaining.")
feedback_add_details("admin_verb","WARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
#undef MAX_WARNS
#undef AUTOBANTIME
/client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE
set category = "Special Verbs"
set name = "Drop Bomb"
set desc = "Cause an explosion of varying strength at your location."
var/turf/epicenter = mob.loc
var/list/choices = list("Small Bomb", "Medium Bomb", "Big Bomb", "Custom Bomb")
var/choice = input("What size explosion would you like to produce?") in choices
switch(choice)
if(null)
return 0
if("Small Bomb")
explosion(epicenter, 1, 2, 3, 3)
if("Medium Bomb")
explosion(epicenter, 2, 3, 4, 4)
if("Big Bomb")
explosion(epicenter, 3, 5, 7, 5)
if("Custom Bomb")
var/devastation_range = input("Devastation range (in tiles):") as num
var/heavy_impact_range = input("Heavy impact range (in tiles):") as num
var/light_impact_range = input("Light impact range (in tiles):") as num
var/flash_range = input("Flash range (in tiles):") as num
explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range)
message_admins("\blue [ckey] creating an admin explosion at [epicenter.loc].")
feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/give_spell(mob/T as mob in mob_list) // -- Urist
set category = "Fun"
set name = "Give Spell"
set desc = "Gives a spell to a mob."
var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells
if(!S) return
T.spell_list += new S
feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].")
message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1)
/client/proc/give_disease(mob/T as mob in mob_list) // -- Giacom
set category = "Fun"
set name = "Give Disease"
set desc = "Gives a Disease to a mob."
var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in diseases
if(!D) return
T.contract_disease(new D, 1)
feedback_add_details("admin_verb","GD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].")
message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the disease [D].", 1)
/client/proc/make_sound(var/obj/O in world) // -- TLE
set category = "Special Verbs"
set name = "Make Sound"
set desc = "Display a message to everyone who can hear the target"
if(O)
var/message = input("What do you want the message to be?", "Make Sound") as text|null
if(!message)
return
for (var/mob/V in hearers(O))
V.show_message(message, 2)
log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound")
message_admins("\blue [key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound", 1)
feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/togglebuildmodeself()
set name = "Toggle Build Mode Self"
set category = "Special Verbs"
if(src.mob)
togglebuildmode(src.mob)
feedback_add_details("admin_verb","TBMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/object_talk(var/msg as text) // -- TLE
set category = "Special Verbs"
set name = "oSay"
set desc = "Display a message to everyone who can hear the target"
if(mob.control_object)
if(!msg)
return
for (var/mob/V in hearers(mob.control_object))
V.show_message("<b>[mob.control_object.name]</b> says: \"" + msg + "\"", 2)
feedback_add_details("admin_verb","OT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/kill_air() // -- TLE
set category = "Debug"
set name = "Kill Air"
set desc = "Toggle Air Processing"
if(air_processing_killed)
air_processing_killed = 0
usr << "<b>Enabled air processing.</b>"
else
air_processing_killed = 1
usr << "<b>Disabled air processing.</b>"
feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] used 'kill air'.")
message_admins("\blue [key_name_admin(usr)] used 'kill air'.", 1)
/client/proc/deadmin_self()
set name = "De-admin self"
set category = "Admin"
if(holder)
if(alert("Confirm self-deadmin for the round? You can't re-admin yourself without someont promoting you.",,"Yes","No") == "Yes")
log_admin("[src] deadmined themself.")
message_admins("[src] deadmined themself.", 1)
deadmin()
src << "<span class='interface'>You are now a normal player.</span>"
feedback_add_details("admin_verb","DAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_log_hrefs()
set name = "Toggle href logging"
set category = "Server"
if(!holder) return
if(config)
if(config.log_hrefs)
config.log_hrefs = 0
src << "<b>Stopped logging hrefs</b>"
else
config.log_hrefs = 1
src << "<b>Started logging hrefs</b>"
/client/proc/check_ai_laws()
set name = "Check AI Laws"
set category = "Admin"
if(holder)
src.holder.output_ai_laws()
//---- bs12 verbs ----
/client/proc/mod_panel()
set name = "Moderator Panel"
set category = "Admin"
/* if(holder)
holder.mod_panel()*/
// feedback_add_details("admin_verb","MP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/editappear(mob/living/carbon/human/M as mob in world)
set name = "Edit Appearance"
set category = "Fun"
if(!check_rights(R_FUN)) return
if(!istype(M, /mob/living/carbon/human))
usr << "\red You can only do this to humans!"
return
switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Vox and Tajaran can result in unintended consequences.",,"Yes","No"))
if("No")
return
var/new_facial = input("Please select facial hair color.", "Character Generation") as color
if(new_facial)
M.r_facial = hex2num(copytext(new_facial, 2, 4))
M.g_facial = hex2num(copytext(new_facial, 4, 6))
M.b_facial = hex2num(copytext(new_facial, 6, 8))
var/new_hair = input("Please select hair color.", "Character Generation") as color
if(new_facial)
M.r_hair = hex2num(copytext(new_hair, 2, 4))
M.g_hair = hex2num(copytext(new_hair, 4, 6))
M.b_hair = hex2num(copytext(new_hair, 6, 8))
var/new_eyes = input("Please select eye color.", "Character Generation") as color
if(new_eyes)
M.r_eyes = hex2num(copytext(new_eyes, 2, 4))
M.g_eyes = hex2num(copytext(new_eyes, 4, 6))
M.b_eyes = hex2num(copytext(new_eyes, 6, 8))
var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text
if (new_tone)
M.s_tone = max(min(round(text2num(new_tone)), 220), 1)
M.s_tone = -M.s_tone + 35
// hair
var/new_hstyle = input(usr, "Select a hair style", "Grooming") as null|anything in hair_styles_list
if(new_hstyle)
M.h_style = new_hstyle
// facial hair
var/new_fstyle = input(usr, "Select a facial hair style", "Grooming") as null|anything in facial_hair_styles_list
if(new_fstyle)
M.f_style = new_fstyle
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
if (new_gender)
if(new_gender == "Male")
M.gender = MALE
else
M.gender = FEMALE
M.update_hair()
M.update_body()
M.check_dna(M)
/client/proc/playernotes()
set name = "Show Player Info"
set category = "Admin"
if(holder)
holder.PlayerNotes()
return
/client/proc/free_slot()
set name = "Free Job Slot"
set category = "Admin"
if(holder)
var/list/jobs = list()
for (var/datum/job/J in job_master.occupations)
if (J.current_positions >= J.total_positions && J.total_positions != -1)
jobs += J.title
if (!jobs.len)
usr << "There are no fully staffed jobs."
return
var/job = input("Please select job slot to free", "Free job slot") as null|anything in jobs
if (job)
job_master.FreeRole(job)
return
/client/proc/toggleattacklogs()
set name = "Toggle Attack Log Messages"
set category = "Preferences"
prefs.toggles ^= CHAT_ATTACKLOGS
if (prefs.toggles & CHAT_ATTACKLOGS)
usr << "You now will get attack log messages"
else
usr << "You now won't get attack log messages"
/client/proc/toggleghostwriters()
set name = "Toggle ghost writers"
set category = "Server"
if(!holder) return
if(config)
if(config.cult_ghostwriter)
config.cult_ghostwriter = 0
src << "<b>Disallowed ghost writers.</b>"
message_admins("Admin [key_name_admin(usr)] has disabled ghost writers.", 1)
else
config.cult_ghostwriter = 1
src << "<b>Enabled ghost writers.</b>"
message_admins("Admin [key_name_admin(usr)] has enabled ghost writers.", 1)
/client/proc/toggledebuglogs()
set name = "Toggle Debug Log Messages"
set category = "Preferences"
prefs.toggles ^= CHAT_DEBUGLOGS
if (prefs.toggles & CHAT_DEBUGLOGS)
usr << "You now will get debug log messages"
else
usr << "You now won't get debug log messages"
/client/proc/man_up(mob/T as mob in mob_list)
set category = "Fun"
set name = "Man Up"
set desc = "Tells mob to man up and deal with it."
T << "<span class='notice'><b><font size=3>Man up and deal with it.</font></b></span>"
T << "<span class='notice'>Move on.</span>"
log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.")
message_admins("\blue [key_name_admin(usr)] told [key_name(T)] to man up and deal with it.", 1)
/client/proc/global_man_up()
set category = "Fun"
set name = "Man Up Global"
set desc = "Tells everyone to man up and deal with it."
for (var/mob/T as mob in mob_list)
T << "<br><center><span class='notice'><b><font size=4>Man up.<br> Deal with it.</font></b><br>Move on.</span></center><br>"
T << 'sound/voice/ManUp1.ogg'
log_admin("[key_name(usr)] told everyone to man up and deal with it.")
message_admins("\blue [key_name_admin(usr)] told everyone to man up and deal with it.", 1)
+114
View File
@@ -0,0 +1,114 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
var/jobban_runonce // Updates legacy bans with new info
var/jobban_keylist[0] //to store the keys & ranks
/proc/jobban_fullban(mob/M, rank, reason)
if (!M || !M.key) return
jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]"))
jobban_savebanfile()
/proc/jobban_client_fullban(ckey, rank)
if (!ckey || !rank) return
jobban_keylist.Add(text("[ckey] - [rank]"))
jobban_savebanfile()
//returns a reason if M is banned from rank, returns 0 otherwise
/proc/jobban_isbanned(mob/M, rank)
if(M && rank)
/*
if(_jobban_isbanned(M, rank)) return "Reason Unspecified" //for old jobban
*/
if (guest_jobbans(rank))
if(config.guest_jobban && IsGuestKey(M.key))
return "Guest Job-ban"
if(config.usewhitelist && !check_whitelist(M))
return "Whitelisted Job"
for (var/s in jobban_keylist)
if( findtext(s,"[M.ckey] - [rank]") == 1 )
var/startpos = findtext(s, "## ")+3
if(startpos && startpos<length(s))
var/text = copytext(s, startpos, 0)
if(text)
return text
return "Reason Unspecified"
return 0
/*
DEBUG
/mob/verb/list_all_jobbans()
set name = "list all jobbans"
for(var/s in jobban_keylist)
world << s
/mob/verb/reload_jobbans()
set name = "reload jobbans"
jobban_loadbanfile()
*/
/hook/startup/proc/loadJobBans()
jobban_loadbanfile()
return 1
/proc/jobban_loadbanfile()
if(config.ban_legacy_system)
var/savefile/S=new("data/job_full.ban")
S["keys[0]"] >> jobban_keylist
log_admin("Loading jobban_rank")
S["runonce"] >> jobban_runonce
if (!length(jobban_keylist))
jobban_keylist=list()
log_admin("jobban_keylist was empty")
else
if(!establish_db_connection())
world.log << "Database connection failed. Reverting to the legacy ban system."
diary << "Database connection failed. Reverting to the legacy ban system."
config.ban_legacy_system = 1
jobban_loadbanfile()
return
//Job permabans
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
query.Execute()
while(query.NextRow())
var/ckey = query.item[1]
var/job = query.item[2]
jobban_keylist.Add("[ckey] - [job]")
//Job tempbans
var/DBQuery/query1 = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
query1.Execute()
while(query1.NextRow())
var/ckey = query1.item[1]
var/job = query1.item[2]
jobban_keylist.Add("[ckey] - [job]")
/proc/jobban_savebanfile()
var/savefile/S=new("data/job_full.ban")
S["keys[0]"] << jobban_keylist
/proc/jobban_unban(mob/M, rank)
jobban_remove("[M.ckey] - [rank]")
jobban_savebanfile()
/proc/ban_unban_log_save(var/formatted_log)
text2file(formatted_log,"data/ban_unban_log.txt")
/proc/jobban_remove(X)
for (var/i = 1; i <= length(jobban_keylist); i++)
if( findtext(jobban_keylist[i], "[X]") )
jobban_keylist.Remove(jobban_keylist[i])
jobban_savebanfile()
return 1
return 0
+9
View File
@@ -0,0 +1,9 @@
/var/create_mob_html = null
/datum/admins/proc/create_mob(var/mob/user)
if (!create_mob_html)
var/mobjs = null
mobjs = list2text(typesof(/mob), ";")
create_mob_html = file2text('html/create_object.html')
create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"")
user << browse(replacetext(create_mob_html, "/* ref src */", "\ref[src]"), "window=create_mob;size=425x475")
+28
View File
@@ -0,0 +1,28 @@
/var/create_object_html = null
/datum/admins/proc/create_object(var/mob/user)
if (!create_object_html)
var/objectjs = null
objectjs = list2text(typesof(/obj), ";")
create_object_html = file2text('html/create_object.html')
create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"")
user << browse(replacetext(create_object_html, "/* ref src */", "\ref[src]"), "window=create_object;size=425x475")
/datum/admins/proc/quick_create_object(var/mob/user)
var/quick_create_object_html = null
var/pathtext = null
pathtext = input("Select the path of the object you wish to create.", "Path", "/obj") in list("/obj","/obj/structure","/obj/item","/obj/item/weapon","/obj/machinery")
var path = text2path(pathtext)
if (!quick_create_object_html)
var/objectjs = null
objectjs = list2text(typesof(path), ";")
quick_create_object_html = file2text('html/create_object.html')
quick_create_object_html = replacetext(quick_create_object_html, "null /* object types */", "\"[objectjs]\"")
user << browse(replacetext(quick_create_object_html, "/* ref src */", "\ref[src]"), "window=quick_create_object;size=425x475")
+9
View File
@@ -0,0 +1,9 @@
/var/create_turf_html = null
/datum/admins/proc/create_turf(var/mob/user)
if (!create_turf_html)
var/turfjs = null
turfjs = list2text(typesof(/turf), ";")
create_turf_html = file2text('html/create_object.html')
create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"")
user << browse(replacetext(create_turf_html, "/* ref src */", "\ref[src]"), "window=create_turf;size=425x475")
+89
View File
@@ -0,0 +1,89 @@
var/list/admin_datums = list()
/datum/admins
var/rank = "Temporary Admin"
var/client/owner = null
var/rights = 0
var/fakekey = null
var/datum/marked_datum
var/admincaster_screen = 0 //See newscaster.dm under machinery for a full description
var/datum/feed_message/admincaster_feed_message = new /datum/feed_message //These two will act as holders.
var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel
var/admincaster_signature //What you'll sign the newsfeeds as
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
if(!ckey)
error("Admin datum created without a ckey argument. Datum has been deleted")
del(src)
return
admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
rank = initial_rank
rights = initial_rights
admin_datums[ckey] = src
/datum/admins/proc/associate(client/C)
if(istype(C))
owner = C
owner.holder = src
owner.add_admin_verbs() //TODO
admins |= C
/datum/admins/proc/disassociate()
if(owner)
admins -= owner
owner.remove_admin_verbs()
owner.holder = null
owner = null
/*
checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags)
if rights_required == 0, then it simply checks if they are an admin.
if it doesn't return 1 and show_msg=1 it will prints a message explaining why the check has failed
generally it would be used like so:
proc/admin_proc()
if(!check_rights(R_ADMIN)) return
world << "you have enough rights!"
NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call
you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
*/
/proc/check_rights(rights_required, show_msg=1)
if(usr && usr.client)
if(rights_required)
if(usr.client.holder)
if(rights_required & usr.client.holder.rights)
return 1
else
if(show_msg)
usr << "<font color='red'>Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].</font>"
else
if(usr.client.holder)
return 1
else
if(show_msg)
usr << "<font color='red'>Error: You are not an admin.</font>"
return 0
//probably a bit iffy - will hopefully figure out a better solution
/proc/check_if_greater_rights_than(client/other)
if(usr && usr.client)
if(usr.client.holder)
if(!other || !other.holder)
return 1
if(usr.client.holder.rights != other.holder.rights)
if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights )
return 1 //we have all the rights they have and more
usr << "<font color='red'>Error: Cannot proceed. They have more or equal rights to us.</font>"
return 0
/client/proc/deadmin()
admin_datums -= ckey
if(holder)
holder.disassociate()
del(holder)
return 1
+274
View File
@@ -0,0 +1,274 @@
var/savefile/Banlistjob
/proc/_jobban_isbanned(var/client/clientvar, var/rank)
if(!clientvar) return 1
ClearTempbansjob()
var/id = clientvar.computer_id
var/key = clientvar.ckey
if (guest_jobbans(rank))
if(config.guest_jobban && IsGuestKey(key))
return 1
Banlistjob.cd = "/base"
if (Banlistjob.dir.Find("[key][id][rank]"))
return 1
Banlistjob.cd = "/base"
for (var/A in Banlistjob.dir)
Banlistjob.cd = "/base/[A]"
if ((id == Banlistjob["id"] || key == Banlistjob["key"]) && rank == Banlistjob["rank"])
return 1
return 0
/proc/LoadBansjob()
Banlistjob = new("data/job_fullnew.bdb")
log_admin("Loading Banlistjob")
if (!length(Banlistjob.dir)) log_admin("Banlistjob is empty.")
if (!Banlistjob.dir.Find("base"))
log_admin("Banlistjob missing base dir.")
Banlistjob.dir.Add("base")
Banlistjob.cd = "/base"
else if (Banlistjob.dir.Find("base"))
Banlistjob.cd = "/base"
ClearTempbansjob()
return 1
/proc/ClearTempbansjob()
UpdateTime()
Banlistjob.cd = "/base"
for (var/A in Banlistjob.dir)
Banlistjob.cd = "/base/[A]"
//if (!Banlistjob["key"] || !Banlistjob["id"])
// RemoveBanjob(A, "full")
// log_admin("Invalid Ban.")
// message_admins("Invalid Ban.")
// continue
if (!Banlistjob["temp"]) continue
if (CMinutes >= Banlistjob["minutes"]) RemoveBanjob(A)
return 1
/proc/AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, rank)
UpdateTime()
var/bantimestamp
if (temp)
UpdateTime()
bantimestamp = CMinutes + minutes
if(rank == "Heads")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Personnel")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Captain")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
return 1
if(rank == "Security")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Warden")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Detective")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Security Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg")
return 1
if(rank == "Engineering")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Station Engineer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Atmospheric Technician")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg")
return 1
if(rank == "Research")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Scientist")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director")
return 1
if(rank == "Medical")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Medical Doctor")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chemist")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg")
return 1
if(rank == "CE_Station_Engineer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Station Engineer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer")
return 1
if(rank == "CE_Atmospheric_Tech")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Atmospheric Technician")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer")
return 1
if(rank == "CE_Shaft_Miner")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Shaft Miner")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer")
return 1
if(rank == "Chemist_RD_CMO")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chemist")
return 1
if(rank == "Geneticist_RD_CMO")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist")
return 1
if(rank == "MD_CMO")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Medical Doctor")
return 1
if(rank == "Scientist_RD")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Scientist")
return 1
if(rank == "AI_Cyborg")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "AI")
return 1
if(rank == "Detective_HoS")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Detective")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security")
return 1
if(rank == "Virologist_RD_CMO")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director")
AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Virologist")
return 1
Banlistjob.cd = "/base"
if ( Banlistjob.dir.Find("[ckey][computerid][rank]") )
usr << text("\red Banjob already exists.")
return 0
else
Banlistjob.dir.Add("[ckey][computerid][rank]")
Banlistjob.cd = "/base/[ckey][computerid][rank]"
Banlistjob["key"] << ckey
Banlistjob["id"] << computerid
Banlistjob["rank"] << rank
Banlistjob["reason"] << reason
Banlistjob["bannedby"] << bannedby
Banlistjob["temp"] << temp
if (temp)
Banlistjob["minutes"] << bantimestamp
return 1
/proc/RemoveBanjob(foldername)
var/key
var/id
var/rank
Banlistjob.cd = "/base/[foldername]"
Banlistjob["key"] >> key
Banlistjob["id"] >> id
Banlistjob["rank"] >> rank
Banlistjob.cd = "/base"
if (!Banlistjob.dir.Remove(foldername)) return 0
if(!usr)
log_admin("Banjob Expired: [key]")
message_admins("Banjob Expired: [key]")
else
log_admin("[key_name_admin(usr)] unjobbanned [key] from [rank]")
message_admins("[key_name_admin(usr)] unjobbanned:[key] from [rank]")
ban_unban_log_save("[key_name_admin(usr)] unjobbanned [key] from [rank]")
feedback_inc("ban_job_unban",1)
feedback_add_details("ban_job_unban","- [rank]")
for (var/A in Banlistjob.dir)
Banlistjob.cd = "/base/[A]"
if ((key == Banlistjob["key"] || id == Banlistjob["id"]) && (rank == Banlistjob["rank"]))
Banlistjob.cd = "/base"
Banlistjob.dir.Remove(A)
continue
return 1
/proc/GetBanExpjob(minutes as num)
UpdateTime()
var/exp = minutes - CMinutes
if (exp <= 0)
return 0
else
var/timeleftstring
if (exp >= 1440) //1440 = 1 day in minutes
timeleftstring = "[round(exp / 1440, 0.1)] Days"
else if (exp >= 60) //60 = 1 hour in minutes
timeleftstring = "[round(exp / 60, 0.1)] Hours"
else
timeleftstring = "[exp] Minutes"
return timeleftstring
/datum/admins/proc/unjobbanpanel()
var/count = 0
var/dat
//var/dat = "<HR><B>Unban Player:</B> \blue(U) = Unban , (E) = Edit Ban\green (Total<HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >"
Banlistjob.cd = "/base"
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 += "</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]"
usr << browse(dat, "window=unbanp;size=875x400")
/*/datum/admins/proc/permjobban(ckey, computerid, reason, bannedby, temp, minutes, rank)
if(AddBanjob(ckey, computerid, reason, usr.ckey, 0, 0, job))
M << "\red<BIG><B>You have been banned from [job] by [usr.client.ckey].\nReason: [reason].</B></BIG>"
M << "\red This is a permanent ban."
if(config.banappeals)
M << "\red To try to resolve this matter head to [config.banappeals]"
else
M << "\red No ban appeals URL has been set."
log_admin("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis is a permanent ban.")
message_admins("\blue[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis is a permanent ban.")
/datum/admins/proc/timejobban(ckey, computerid, reason, bannedby, temp, minutes, rank)
if(AddBanjob(ckey, computerid, reason, usr.ckey, 1, mins, job))
M << "\red<BIG><B>You have been jobbanned from [job] by [usr.client.ckey].\nReason: [reason].</B></BIG>"
M << "\red This is a temporary ban, it will be removed in [mins] minutes."
if(config.banappeals)
M << "\red To try to resolve this matter head to [config.banappeals]"
else
M << "\red No ban appeals URL has been set."
log_admin("[usr.client.ckey] has jobbanned from [job] [ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
message_admins("\blue[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")*/
//////////////////////////////////// DEBUG ////////////////////////////////////
/proc/CreateBansjob()
UpdateTime()
var/i
var/last
for(i=0, i<1001, i++)
var/a = pick(1,0)
var/b = pick(1,0)
if(b)
Banlistjob.cd = "/base"
Banlistjob.dir.Add("trash[i]trashid[i]")
Banlistjob.cd = "/base/trash[i]trashid[i]"
Banlistjob["key"] << "trash[i]"
else
Banlistjob.cd = "/base"
Banlistjob.dir.Add("[last]trashid[i]")
Banlistjob.cd = "/base/[last]trashid[i]"
Banlistjob["key"] << last
Banlistjob["id"] << "trashid[i]"
Banlistjob["reason"] << "Trashban[i]."
Banlistjob["temp"] << a
Banlistjob["minutes"] << CMinutes + rand(1,2000)
Banlistjob["bannedby"] << "trashmin"
last = "trash[i]"
Banlistjob.cd = "/base"
/proc/ClearAllBansjob()
Banlistjob.cd = "/base"
for (var/A in Banlistjob.dir)
RemoveBanjob(A, "full")
@@ -0,0 +1,149 @@
/client/proc/edit_admin_permissions()
set category = "Admin"
set name = "Permissions Panel"
set desc = "Edit admin permissions"
if(!check_rights(R_PERMISSIONS)) return
usr.client.holder.edit_admin_permissions()
/datum/admins/proc/edit_admin_permissions()
if(!check_rights(R_PERMISSIONS)) return
var/output = {"<!DOCTYPE html>
<html>
<head>
<title>Permissions Panel</title>
<script type='text/javascript' src='search.js'></script>
<link rel='stylesheet' type='text/css' href='panels.css'>
</head>
<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;'>RANK</th><th style='width:100%;'>PERMISSIONS</th>
</tr>
"}
for(var/adm_ckey in admin_datums)
var/datum/admins/D = admin_datums[adm_ckey]
if(!D) continue
var/rank = D.rank ? D.rank : "*none*"
var/rights = rights2text(D.rights," ")
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></font></td>"
output += "</tr>"
output += {"
</table></div>
<div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div>
</body>
</html>"}
usr << browse(output,"window=editrights;size=600x500")
/datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank)
if(config.admin_legacy_system) return
if(!usr.client)
return
if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
usr << "\red You do not have permission to do this!"
return
establish_db_connection()
if(!dbcon.IsConnected())
usr << "\red Failed to establish database connection"
return
if(!adm_ckey || !new_rank)
return
adm_ckey = ckey(adm_ckey)
if(!adm_ckey)
return
if(!istext(adm_ckey) || !istext(new_rank))
return
var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/new_admin = 1
var/admin_id
while(select_query.NextRow())
new_admin = 0
admin_id = text2num(select_query.item[1])
if(new_admin)
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
insert_query.Execute()
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
log_query.Execute()
usr << "\blue New admin added."
else
if(!isnull(admin_id) && isnum(admin_id))
var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]")
insert_query.Execute()
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
log_query.Execute()
usr << "\blue Admin rank changed."
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
if(config.admin_legacy_system) return
if(!usr.client)
return
if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
usr << "\red You do not have permission to do this!"
return
establish_db_connection()
if(!dbcon.IsConnected())
usr << "\red Failed to establish database connection"
return
if(!adm_ckey || !new_permission)
return
adm_ckey = ckey(adm_ckey)
if(!adm_ckey)
return
if(istext(new_permission))
new_permission = text2num(new_permission)
if(!istext(adm_ckey) || !isnum(new_permission))
return
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/admin_id
var/admin_rights
while(select_query.NextRow())
admin_id = text2num(select_query.item[1])
admin_rights = text2num(select_query.item[2])
if(!admin_id)
return
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
insert_query.Execute()
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
log_query.Execute()
usr << "\blue Permission removed."
else //This admin doesn't have this permission, so we are adding it.
var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
insert_query.Execute()
var/DBQuery/log_query = dbcon.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]')")
log_query.Execute()
usr << "\blue Permission added."
+154
View File
@@ -0,0 +1,154 @@
//This stuff was originally intended to be integrated into the ban-system I was working on
//but it's safe to say that'll never be finished. So I've merged it into the current player panel.
//enjoy ~Carn
/*
#define NOTESFILE "data/player_notes.sav" //where the player notes are saved
datum/admins/proc/notes_show(var/ckey)
usr << browse("<head><title>Player Notes</title></head><body>[notes_gethtml(ckey)]</body>","window=player_notes;size=700x400")
datum/admins/proc/notes_gethtml(var/ckey)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return "<font color='red'>Error: Cannot access [NOTESFILE]</font>"
if(ckey)
. = "<b>Notes for <a href='?src=\ref[src];notes=show'>[ckey]</a>:</b> <a href='?src=\ref[src];notes=add;ckey=[ckey]'>\[+\]</a> <a href='?src=\ref[src];notes=remove;ckey=[ckey]'>\[-\]</a><br>"
notesfile.cd = "/[ckey]"
var/index = 1
while( !notesfile.eof )
var/note
notesfile >> note
. += "[note] <a href='?src=\ref[src];notes=remove;ckey=[ckey];from=[index]'>\[-\]</a><br>"
index++
else
. = "<b>All Notes:</b> <a href='?src=\ref[src];notes=add'>\[+\]</a> <a href='?src=\ref[src];notes=remove'>\[-\]</a><br>"
notesfile.cd = "/"
for(var/dir in notesfile.dir)
. += "<a href='?src=\ref[src];notes=show;ckey=[dir]'>[dir]</a><br>"
return
//handles adding notes to the end of a ckey's buffer
//originally had seperate entries such as var/by to record who left the note and when
//but the current bansystem is a heap of dung.
/proc/notes_add(var/ckey, var/note)
if(!ckey)
ckey = ckey(input(usr,"Who would you like to add notes for?","Enter a ckey",null) as text|null)
if(!ckey) return
if(!note)
note = html_encode(input(usr,"Enter your note:","Enter some text",null) as message|null)
if(!note) return
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return
notesfile.cd = "/[ckey]"
notesfile.eof = 1 //move to the end of the buffer
notesfile << "[time2text(world.realtime,"DD-MMM-YYYY")] | [note][(usr && usr.ckey)?" ~[usr.ckey]":""]"
return
//handles removing entries from the buffer, or removing the entire directory if no start_index is given
/proc/notes_remove(var/ckey, var/start_index, var/end_index)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return
if(!ckey)
notesfile.cd = "/"
ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir)
if(!ckey) return
if(start_index)
notesfile.cd = "/[ckey]"
var/list/noteslist = list()
if(!end_index) end_index = start_index
var/index = 0
while( !notesfile.eof )
index++
var/temp
notesfile >> temp
if( (start_index <= index) && (index <= end_index) )
continue
noteslist += temp
notesfile.eof = -2 //Move to the start of the buffer and then erase.
for( var/note in noteslist )
notesfile << note
else
notesfile.cd = "/"
if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes")
notesfile.dir.Remove(ckey)
return
#undef NOTESFILE
*/
//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky.
/proc/notes_add(var/key, var/note, var/mob/usr)
if (!key || !note)
return
//Loading list of notes for this key
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos) infos = list()
//Overly complex timestamp creation
var/modifyer = "th"
switch(time2text(world.timeofday, "DD"))
if("01","21","31")
modifyer = "st"
if("02","22",)
modifyer = "nd"
if("03","23")
modifyer = "rd"
var/day_string = "[time2text(world.timeofday, "DD")][modifyer]"
if(copytext(day_string,1,2) == "0")
day_string = copytext(day_string,2)
var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY")
var/day_loc = findtext(full_date, time2text(world.timeofday, "DD"))
var/datum/player_info/P = new
if (usr)
P.author = usr.key
P.rank = usr.client.holder.rank
else
P.author = "Adminbot"
P.rank = "Friendly Robot"
P.content = note
P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]"
infos += P
info << infos
message_admins("\blue [key_name_admin(usr)] has edited [key]'s notes.")
log_admin("[key_name(usr)] has edited [key]'s notes.")
del info
//Updating list of keys with notes on them
var/savefile/note_list = new("data/player_notes.sav")
var/list/note_keys
note_list >> note_keys
if(!note_keys) note_keys = list()
if(!note_keys.Find(key)) note_keys += key
note_list << note_keys
del note_list
/proc/notes_del(var/key, var/index)
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos || infos.len < index) return
var/datum/player_info/item = infos[index]
infos.Remove(item)
info << infos
message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.")
log_admin("[key_name(usr)] deleted one of [key]'s notes.")
del info
+527
View File
@@ -0,0 +1,527 @@
/datum/admins/proc/player_panel_new()//The new one
if (!usr.client.holder)
return
var/dat = "<html><head><title>Admin Player Panel</title></head>"
//javascript, the part that does most of the work~
dat += {"
<head>
<script type='text/javascript'>
var locked_tabs = new Array();
function updateSearch(){
var filter_text = document.getElementById('filter');
var filter = filter_text.value.toLowerCase();
if(complete_list != null && complete_list != ""){
var mtbl = document.getElementById("maintable_data_archive");
mtbl.innerHTML = complete_list;
}
if(filter.value == ""){
return;
}else{
var maintable_data = document.getElementById('maintable_data');
var ltr = maintable_data.getElementsByTagName("tr");
for ( var i = 0; i < ltr.length; ++i )
{
try{
var tr = ltr\[i\];
if(tr.getAttribute("id").indexOf("data") != 0){
continue;
}
var ltd = tr.getElementsByTagName("td");
var td = ltd\[0\];
var lsearch = td.getElementsByTagName("b");
var search = lsearch\[0\];
//var inner_span = li.getElementsByTagName("span")\[1\] //Should only ever contain one element.
//document.write("<p>"+search.innerText+"<br>"+filter+"<br>"+search.innerText.indexOf(filter))
if ( search.innerText.toLowerCase().indexOf(filter) == -1 )
{
//document.write("a");
//ltr.removeChild(tr);
td.innerHTML = "";
i--;
}
}catch(err) { }
}
}
var count = 0;
var index = -1;
var debug = document.getElementById("debug");
locked_tabs = new Array();
}
function expand(id,job,name,real_name,image,key,ip,antagonist,ref){
clearAll();
var span = document.getElementById(id);
body = "<table><tr><td>";
body += "</td><td align='center'>";
body += "<font size='2'><b>"+job+" "+name+"</b><br><b>Real name "+real_name+"</b><br><b>Played by "+key+" ("+ip+")</b></font>"
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_=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>"
if(antagonist > 0)
body += "<font size='2'><a href='?src=\ref[src];check_antagonist=1'><font color='red'><b>Antagonist</b></font></a></font>";
body += "</td></tr></table>";
span.innerHTML = body
}
function clearAll(){
var spans = document.getElementsByTagName('span');
for(var i = 0; i < spans.length; i++){
var span = spans\[i\];
var id = span.getAttribute("id");
if(!(id.indexOf("item")==0))
continue;
var pass = 1;
for(var j = 0; j < locked_tabs.length; j++){
if(locked_tabs\[j\]==id){
pass = 0;
break;
}
}
if(pass != 1)
continue;
span.innerHTML = "";
}
}
function addToLocked(id,link_id,notice_span_id){
var link = document.getElementById(link_id);
var decision = link.getAttribute("name");
if(decision == "1"){
link.setAttribute("name","2");
}else{
link.setAttribute("name","1");
removeFromLocked(id,link_id,notice_span_id);
return;
}
var pass = 1;
for(var j = 0; j < locked_tabs.length; j++){
if(locked_tabs\[j\]==id){
pass = 0;
break;
}
}
if(!pass)
return;
locked_tabs.push(id);
var notice_span = document.getElementById(notice_span_id);
notice_span.innerHTML = "<font color='red'>Locked</font> ";
//link.setAttribute("onClick","attempt('"+id+"','"+link_id+"','"+notice_span_id+"');");
//document.write("removeFromLocked('"+id+"','"+link_id+"','"+notice_span_id+"')");
//document.write("aa - "+link.getAttribute("onClick"));
}
function attempt(ab){
return ab;
}
function removeFromLocked(id,link_id,notice_span_id){
//document.write("a");
var index = 0;
var pass = 0;
for(var j = 0; j < locked_tabs.length; j++){
if(locked_tabs\[j\]==id){
pass = 1;
index = j;
break;
}
}
if(!pass)
return;
locked_tabs\[index\] = "";
var notice_span = document.getElementById(notice_span_id);
notice_span.innerHTML = "";
//var link = document.getElementById(link_id);
//link.setAttribute("onClick","addToLocked('"+id+"','"+link_id+"','"+notice_span_id+"')");
}
function selectTextField(){
var filter_text = document.getElementById('filter');
filter_text.focus();
filter_text.select();
}
</script>
</head>
"}
//body tag start + onload and onkeypress (onkeyup) javascript event calls
dat += "<body onload='selectTextField(); updateSearch();' onkeyup='updateSearch();'>"
//title + search bar
dat += {"
<table width='560' align='center' cellspacing='0' cellpadding='5' id='maintable'>
<tr id='title_tr'>
<td align='center'>
<font size='5'><b>Player panel</b></font><br>
Hover over a line to see more information - <a href='?src=\ref[src];check_antagonist=1'>Check antagonists</a>
<p>
</td>
</tr>
<tr id='search_tr'>
<td align='center'>
<b>Search:</b> <input type='text' id='filter' value='' style='width:300px;'>
</td>
</tr>
</table>
"}
//player table header
dat += {"
<span id='maintable_data_archive'>
<table width='560' align='center' cellspacing='0' cellpadding='5' id='maintable_data'>"}
var/list/mobs = sortmobs()
var/i = 1
for(var/mob/M in mobs)
if(M.ckey)
var/color = "#e6e6e6"
if(i%2 == 0)
color = "#f2f2f2"
var/is_antagonist = is_special_character(M)
var/M_job = ""
if(isliving(M))
if(iscarbon(M)) //Carbon stuff
if(ishuman(M))
M_job = M.job
else if(isslime(M))
M_job = "slime"
else if(ismonkey(M))
M_job = "Monkey"
else if(isalien(M)) //aliens
if(islarva(M))
M_job = "Alien larva"
else
M_job = "Alien"
else
M_job = "Carbon-based"
else if(issilicon(M)) //silicon
if(isAI(M))
M_job = "AI"
else if(ispAI(M))
M_job = "pAI"
else if(isrobot(M))
M_job = "Cyborg"
else
M_job = "Silicon-based"
else if(isanimal(M)) //simple animals
if(iscorgi(M))
M_job = "Corgi"
else
M_job = "Animal"
else
M_job = "Living"
else if(istype(M,/mob/new_player))
M_job = "New player"
else if(isobserver(M))
M_job = "Ghost"
M_job = replacetext(M_job, "'", "")
M_job = replacetext(M_job, "\"", "")
M_job = replacetext(M_job, "\\", "")
var/M_name = M.name
M_name = replacetext(M_name, "'", "")
M_name = replacetext(M_name, "\"", "")
M_name = replacetext(M_name, "\\", "")
var/M_rname = M.real_name
M_rname = replacetext(M_rname, "'", "")
M_rname = replacetext(M_rname, "\"", "")
M_rname = replacetext(M_rname, "\\", "")
var/M_key = M.key
M_key = replacetext(M_key, "'", "")
M_key = replacetext(M_key, "\"", "")
M_key = replacetext(M_key, "\\", "")
//output for each mob
dat += {"
<tr id='data[i]' name='[i]' onClick="addToLocked('item[i]','data[i]','notice_span[i]')">
<td align='center' bgcolor='[color]'>
<span id='notice_span[i]'></span>
<a id='link[i]'
onmouseover='expand("item[i]","[M_job]","[M_name]","[M_rname]","--unused--","[M_key]","[M.lastKnownIP]",[is_antagonist],"\ref[M]")'
>
<b id='search[i]'>[M_name] - [M_rname] - [M_key] ([M_job])</b>
</a>
<br><span id='item[i]'></span>
</td>
</tr>
"}
i++
//player table ending
dat += {"
</table>
</span>
<script type='text/javascript'>
var maintable = document.getElementById("maintable_data_archive");
var complete_list = maintable.innerHTML;
</script>
</body></html>
"}
usr << browse(dat, "window=players;size=600x480")
//The old one
/datum/admins/proc/player_panel_old()
if (!usr.client.holder)
return
var/dat = "<html><head><title>Player Menu</title></head>"
dat += "<body><table border=1 cellspacing=5><B><tr><th>Name</th><th>Real Name</th><th>Assigned Job</th><th>Key</th><th>Options</th><th>PM</th><th>Traitor?</th></tr></B>"
//add <th>IP:</th> to this if wanting to add back in IP checking
//add <td>(IP: [M.lastKnownIP])</td> if you want to know their ip to the lists below
var/list/mobs = sortmobs()
for(var/mob/M in mobs)
if(!M.ckey) continue
dat += "<tr><td>[M.name]</td>"
if(isAI(M))
dat += "<td>AI</td>"
else if(isrobot(M))
dat += "<td>Cyborg</td>"
else if(ishuman(M))
dat += "<td>[M.real_name]</td>"
else if(istype(M, /mob/living/silicon/pai))
dat += "<td>pAI</td>"
else if(istype(M, /mob/new_player))
dat += "<td>New Player</td>"
else if(isobserver(M))
dat += "<td>Ghost</td>"
else if(ismonkey(M))
dat += "<td>Monkey</td>"
else if(isalien(M))
dat += "<td>Alien</td>"
else
dat += "<td>Unknown</td>"
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.mind && H.mind.assigned_role)
dat += "<td>[H.mind.assigned_role]</td>"
else
dat += "<td>NA</td>"
dat += {"<td>[(M.client ? "[M.client]" : "No client")]</td>
<td align=center><A HREF='?src=\ref[src];adminplayeropts=\ref[M]'>X</A></td>
<td align=center><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>
"}
switch(is_special_character(M))
if(0)
dat += {"<td align=center><A HREF='?src=\ref[src];traitor=\ref[M]'>Traitor?</A></td>"}
if(1)
dat += {"<td align=center><A HREF='?src=\ref[src];traitor=\ref[M]'><font color=red>Traitor?</font></A></td>"}
if(2)
dat += {"<td align=center><A HREF='?src=\ref[src];traitor=\ref[M]'><font color=red><b>Traitor?</b></font></A></td>"}
dat += "</table></body></html>"
usr << browse(dat, "window=players;size=640x480")
/datum/admins/proc/check_antagonists()
if (ticker && ticker.current_state >= GAME_STATE_PLAYING)
var/dat = "<html><head><title>Round Status</title></head><body><h1><B>Round Status</B></h1>"
dat += "Current Game Mode: <B>[ticker.mode.name]</B><BR>"
dat += "Round Duration: <B>[round(world.time / 36000)]:[add_zero(world.time / 600 % 60, 2)]:[world.time / 100 % 6][world.time / 100 % 10]</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>"
else
var/timeleft = emergency_shuttle.timeleft()
switch(emergency_shuttle.location)
if(0)
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>"
if(1)
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];delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
if(ticker.mode.syndicates.len)
dat += "<br><table cellspacing=5><tr><td><B>Syndicates</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.syndicates)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
else
dat += "<tr><td><i>Nuclear Operative not found!</i></td></tr>"
dat += "</table><br><table><tr><td><B>Nuclear Disk(s)</B></td></tr>"
for(var/obj/item/weapon/disk/nuclear/N in world)
dat += "<tr><td>[N.name], "
var/atom/disk_loc = N.loc
while(!istype(disk_loc, /turf))
if(istype(disk_loc, /mob))
var/mob/M = disk_loc
dat += "carried by <a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a> "
if(istype(disk_loc, /obj))
var/obj/O = disk_loc
dat += "in \a [O.name] "
disk_loc = disk_loc.loc
dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])</td></tr>"
dat += "</table>"
if(ticker.mode.head_revolutionaries.len || ticker.mode.revolutionaries.len)
dat += "<br><table cellspacing=5><tr><td><B>Revolutionaries</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.head_revolutionaries)
var/mob/M = N.current
if(!M)
dat += "<tr><td><i>Head Revolutionary not found!</i></td></tr>"
else
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a> <b>(Leader)</b>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
for(var/datum/mind/N in ticker.mode.revolutionaries)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
dat += "</table><table cellspacing=5><tr><td><B>Target(s)</B></td><td></td><td><B>Location</B></td></tr>"
for(var/datum/mind/N in ticker.mode.get_living_heads())
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
var/turf/mob_loc = get_turf_loc(M)
dat += "<td>[mob_loc.loc]</td></tr>"
else
dat += "<tr><td><i>Head not found!</i></td></tr>"
dat += "</table>"
if(ticker.mode.changelings.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Changelings</B></td><td></td><td></td></tr>"
for(var/datum/mind/changeling in ticker.mode.changelings)
var/mob/M = changeling.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
dat += "<td><A HREF='?src=\ref[src];traitor=\ref[M]'>Show Objective</A></td></tr>"
else
dat += "<tr><td><i>Changeling not found!</i></td></tr>"
dat += "</table>"
if(ticker.mode.wizards.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Wizards</B></td><td></td><td></td></tr>"
for(var/datum/mind/wizard in ticker.mode.wizards)
var/mob/M = wizard.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
dat += "<td><A HREF='?src=\ref[src];traitor=\ref[M]'>Show Objective</A></td></tr>"
else
dat += "<tr><td><i>Wizard not found!</i></td></tr>"
dat += "</table>"
if(ticker.mode.raiders.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Raiders</B></td><td></td><td></td></tr>"
for(var/datum/mind/raider in ticker.mode.raiders)
var/mob/M = raider.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
dat += "<td><A HREF='?src=\ref[src];traitor=\ref[M]'>Show Objective</A></td></tr>"
dat += "</table>"
if(ticker.mode.ninjas.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Ninjas</B></td><td></td><td></td></tr>"
for(var/datum/mind/ninja in ticker.mode.ninjas)
var/mob/M = ninja.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
dat += "<td><A HREF='?src=\ref[src];traitor=\ref[M]'>Show Objective</A></td></tr>"
else
dat += "<tr><td><i>Ninja not found!</i></td></tr>"
dat += "</table>"
if(ticker.mode.cult.len)
dat += "<br><table cellspacing=5><tr><td><B>Cultists</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.cult)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
dat += "</table>"
/*if(istype(ticker.mode, /datum/game_mode/anti_revolution) && ticker.mode:heads.len) //comment out anti-revolution
dat += "<br><table cellspacing=5><tr><td><B>Corrupt Heads</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode:heads)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
dat += "</table>"
*/
if(ticker.mode.traitors.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Traitors</B></td><td></td><td></td></tr>"
for(var/datum/mind/traitor in ticker.mode.traitors)
var/mob/M = traitor.current
if(M)
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
dat += "<td><A HREF='?src=\ref[src];traitor=\ref[M]'>Show Objective</A></td></tr>"
else
dat += "<tr><td><i>Traitor not found!</i></td></tr>"
dat += "</table>"
dat += "</body></html>"
usr << browse(dat, "window=roundstatus;size=400x500")
else
alert("The game hasn't started yet!")
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
/proc/getbrokeninhands()
var/icon/IL = new('icons/mob/items_lefthand.dmi')
var/list/Lstates = IL.IconStates()
var/icon/IR = new('icons/mob/items_righthand.dmi')
var/list/Rstates = IR.IconStates()
var/text
for(var/A in typesof(/obj/item))
var/obj/item/O = new A( locate(1,1,1) )
if(!O) continue
var/icon/J = new(O.icon)
var/list/istates = J.IconStates()
if(!Lstates.Find(O.icon_state) && !Lstates.Find(O.item_state))
if(O.icon_state)
text += "[O.type] is missing left hand icon called \"[O.icon_state]\".\n"
if(!Rstates.Find(O.icon_state) && !Rstates.Find(O.item_state))
if(O.icon_state)
text += "[O.type] is missing right hand icon called \"[O.icon_state]\".\n"
if(O.icon_state)
if(!istates.Find(O.icon_state))
text += "[O.type] is missing normal icon called \"[O.icon_state]\" in \"[O.icon]\".\n"
//if(O.item_state)
// if(!istates.Find(O.item_state))
// text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.item_state]\" IN \"[O.icon]\"\n"
//text+="\n"
del(O)
if(text)
var/F = file("broken_icons.txt")
fdel(F)
F << text
world << "Completeled successfully and written to [F]"
+497
View File
@@ -0,0 +1,497 @@
//Structured Datum Query Language. Basically SQL meets BYOND objects.
//Note: For use in BS12, need text_starts_with proc, and to modify the action on select to use BS12's object edit command(s).
/client/proc/SDQL_query(query_text as message)
set category = "Admin"
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
message_admins("\red ERROR: Non-admin [usr.key] attempted to execute a SDQL query!")
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!")
var/list/query_list = SDQL_tokenize(query_text)
if(query_list.len < 2)
if(query_list.len > 0)
usr << "\red SDQL: Too few discrete tokens in query \"[query_text]\". Please check your syntax and try again."
return
if(!(lowertext(query_list[1]) in list("select", "delete", "update")))
usr << "\red SDQL: Unknown query type: \"[query_list[1]]\" in query \"[query_text]\". Please check your syntax and try again."
return
var/list/types = list()
var/i
for(i = 2; i <= query_list.len; i += 2)
types += query_list[i]
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
break
i++
var/list/from = list()
if(i <= query_list.len)
if(lowertext(query_list[i]) in list("from", "in"))
for(i++; i <= query_list.len; i += 2)
from += query_list[i]
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
break
i++
if(from.len < 1)
from += "world"
var/list/set_vars = list()
if(lowertext(query_list[1]) == "update")
if(i <= query_list.len && lowertext(query_list[i]) == "set")
for(i++; i <= query_list.len; i++)
if(i + 2 <= query_list.len && query_list[i + 1] == "=")
set_vars += query_list[i]
set_vars[query_list[i]] = query_list[i + 2]
else
usr << "\red SDQL: Invalid set parameter in query \"[query_text]\". Please check your syntax and try again."
return
i += 3
if(i >= query_list.len || query_list[i] != ",")
break
if(set_vars.len < 1)
usr << "\red SDQL: Invalid or missing set in query \"[query_text]\". Please check your syntax and try again."
return
var/list/where = list()
if(i <= query_list.len && lowertext(query_list[i]) == "where")
where = query_list.Copy(i + 1)
var/list/from_objs = list()
if("world" in from)
from_objs += world
else
for(var/f in from)
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
from_objs += locate(copytext(f, 2, length(f)))
else if(copytext(f, 1, 2) != "/")
from_objs += locate(f)
else
var/f2 = text2path(f)
if(text_starts_with(f, "/mob"))
for(var/mob/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf/space"))
for(var/turf/space/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf/simulated"))
for(var/turf/simulated/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf/unsimulated"))
for(var/turf/unsimulated/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf"))
for(var/turf/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/area"))
for(var/area/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/obj/item"))
for(var/obj/item/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/obj/machinery"))
for(var/obj/machinery/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/obj"))
for(var/obj/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/atom"))
for(var/atom/m in world)
if(istype(m, f2))
from_objs += m
/*
else
for(var/datum/m in world)
if(istype(m, f2))
from_objs += m
*/
var/list/objs = list()
for(var/from_obj in from_objs)
if("*" in types)
objs += from_obj:contents
else
for(var/f in types)
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
objs += locate(copytext(f, 2, length(f))) in from_obj
else if(copytext(f, 1, 2) != "/")
objs += locate(f) in from_obj
else
var/f2 = text2path(f)
if(text_starts_with(f, "/mob"))
for(var/mob/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf/space"))
for(var/turf/space/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf/simulated"))
for(var/turf/simulated/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf/unsimulated"))
for(var/turf/unsimulated/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf"))
for(var/turf/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/area"))
for(var/area/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/obj/item"))
for(var/obj/item/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/obj/machinery"))
for(var/obj/machinery/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/obj"))
for(var/obj/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/atom"))
for(var/atom/m in from_obj)
if(istype(m, f2))
objs += m
else
for(var/datum/m in from_obj)
if(istype(m, f2))
objs += m
for(var/datum/t in objs)
var/currently_false = 0
for(i = 1, i - 1 < where.len, i++)
var/v = where[i++]
var/compare_op = where[i++]
if(!(compare_op in list("==", "=", "<>", "<", ">", "<=", ">=", "!=")))
usr << "\red SDQL: Unknown comparison operator [compare_op] in where clause following [v] in query \"[query_text]\". Please check your syntax and try again."
return
var/j
for(j = i, j <= where.len, j++)
if(lowertext(where[j]) in list("and", "or", ";"))
break
if(!currently_false)
var/value = SDQL_text2value(t, v)
var/result = SDQL_evaluate(t, where.Copy(i, j))
switch(compare_op)
if("=", "==")
currently_false = !(value == result)
if("!=", "<>")
currently_false = !(value != result)
if("<")
currently_false = !(value < result)
if(">")
currently_false = !(value > result)
if("<=")
currently_false = !(value <= result)
if(">=")
currently_false = !(value >= result)
if(j > where.len || lowertext(where[j]) == ";")
break
else if(lowertext(where[j]) == "or")
if(currently_false)
currently_false = 0
else
break
i = j
if(currently_false)
objs -= t
usr << "\blue SQDL Query: [query_text]"
message_admins("[usr] executed SDQL query: \"[query_text]\".")
/*
for(var/t in types)
usr << "Type: [t]"
for(var/t in from)
usr << "From: [t]"
for(var/t in set_vars)
usr << "Set: [t] = [set_vars[t]]"
if(where.len)
var/where_str = ""
for(var/t in where)
where_str += "[t] "
usr << "Where: [where_str]"
usr << "From objects:"
for(var/datum/t in from_objs)
usr << t
usr << "Objects:"
for(var/datum/t in objs)
usr << t
*/
switch(lowertext(query_list[1]))
if("delete")
for(var/datum/t in objs)
del t
if("update")
for(var/datum/t in objs)
objs[t] = list()
for(var/v in set_vars)
if(v in t.vars)
objs[t][v] = SDQL_text2value(t, set_vars[v])
for(var/datum/t in objs)
for(var/v in objs[t])
t.vars[v] = objs[t][v]
if("select")
var/text = ""
for(var/datum/t in objs)
if(istype(t, /atom))
var/atom/a = t
if(a.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
else if(a.loc && a.loc.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
//text += "[t]<br>"
usr << browse(text, "window=sdql_result")
/client/Topic(href,href_list[],hsrc)
if(href_list["SDQL_select"])
debug_variables(locate(href_list["SDQL_select"]))
..()
/proc/SDQL_evaluate(datum/object, list/equation)
if(equation.len == 0)
return null
else if(equation.len == 1)
return SDQL_text2value(object, equation[1])
else if(equation[1] == "!")
return !SDQL_evaluate(object, equation.Copy(2))
else if(equation[1] == "-")
return -SDQL_evaluate(object, equation.Copy(2))
else
usr << "\red SDQL: Sorry, equations not yet supported :("
return null
/proc/SDQL_text2value(datum/object, text)
if(text2num(text) != null)
return text2num(text)
else if(text == "null")
return null
else if(copytext(text, 1, 2) == "'" || copytext(text, 1, 2) == "\"" )
return copytext(text, 2, length(text))
else if(copytext(text, 1, 2) == "/")
return text2path(text)
else
if(findtext(text, "."))
var/split = findtext(text, ".")
var/v = copytext(text, 1, split)
if((v in object.vars) && istype(object.vars[v], /datum))
return SDQL_text2value(object.vars[v], copytext(text, split + 1))
else
return null
else
if(text in object.vars)
return object.vars[text]
else
return null
/proc/text_starts_with(text, start)
if(copytext(text, 1, length(start) + 1) == start)
return 1
else
return 0
/proc/SDQL_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
var/list/single = list("(", ")", ",", "+", "-")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
">" = list("", "="),
"!" = list("", "="))
var/word = ""
var/list/query_list = list()
var/len = length(query_text)
for(var/i = 1, i <= len, i++)
var/char = copytext(query_text, i, i + 1)
if(char in whitespace)
if(word != "")
query_list += word
word = ""
else if(char in single)
if(word != "")
query_list += word
word = ""
query_list += char
else if(char in multi)
if(word != "")
query_list += word
word = ""
var/char2 = copytext(query_text, i + 1, i + 2)
if(char2 in multi[char])
query_list += "[char][char2]"
i++
else
query_list += char
else if(char == "'")
if(word != "")
usr << "\red SDQL: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "'"
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "'")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "'"
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]'"
word = ""
else if(char == "\"")
if(word != "")
usr << "\red SDQL: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "\""
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "\"")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "\""
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]\""
word = ""
else
word += char
if(word != "")
query_list += word
return query_list
+426
View File
@@ -0,0 +1,426 @@
/client/proc/SDQL2_query(query_text as message)
set category = "Admin"
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
message_admins("\red ERROR: Non-admin [usr.key] attempted to execute a SDQL query!")
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!")
if(!query_text || length(query_text) < 1)
return
//world << query_text
var/list/query_list = SDQL2_tokenize(query_text)
if(!query_list || query_list.len < 1)
return
var/list/query_tree = SDQL_parse(query_list)
if(query_tree.len < 1)
return
var/list/from_objs = list()
var/list/select_types = list()
switch(query_tree[1])
if("explain")
SDQL_testout(query_tree["explain"])
return
if("call")
if("on" in query_tree)
select_types = query_tree["on"]
else
return
if("select", "delete", "update")
select_types = query_tree[query_tree[1]]
from_objs = SDQL_from_objs(query_tree["from"])
var/list/objs = list()
for(var/type in select_types)
var/char = copytext(type, 1, 2)
if(char == "/" || char == "*")
for(var/from in from_objs)
objs += SDQL_get_all(type, from)
else if(char == "'" || char == "\"")
objs += locate(copytext(type, 2, length(type)))
if("where" in query_tree)
var/objs_temp = objs
objs = list()
for(var/datum/d in objs_temp)
if(SDQL_expression(d, query_tree["where"]))
objs += d
//usr << "Query: [query_text]"
message_admins("[usr] executed SDQL query: \"[query_text]\".")
switch(query_tree[1])
if("delete")
for(var/datum/d in objs)
del d
if("select")
var/text = ""
for(var/datum/t in objs)
if(istype(t, /atom))
var/atom/a = t
if(a.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
else if(a.loc && a.loc.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
usr << browse(text, "window=SDQL-result")
if("update")
if("set" in query_tree)
var/list/set_list = query_tree["set"]
for(var/datum/d in objs)
var/list/vals = list()
for(var/v in set_list)
if(v in d.vars)
vals += v
vals[v] = SDQL_expression(d, set_list[v])
if(istype(d, /turf))
for(var/v in vals)
if(v == "x" || v == "y" || v == "z")
continue
d.vars[v] = vals[v]
else
for(var/v in vals)
d.vars[v] = vals[v]
/proc/SDQL_parse(list/query_list)
var/datum/SDQL_parser/parser = new(query_list)
var/list/query_tree = parser.parse()
del(parser)
return query_tree
/proc/SDQL_testout(list/query_tree, indent = 0)
var/spaces = ""
for(var/s = 0, s < indent, s++)
spaces += " "
for(var/item in query_tree)
if(istype(item, /list))
world << "[spaces]("
SDQL_testout(item, indent + 1)
world << "[spaces])"
else
world << "[spaces][item]"
if(!isnum(item) && query_tree[item])
if(istype(query_tree[item], /list))
world << "[spaces] ("
SDQL_testout(query_tree[item], indent + 2)
world << "[spaces] )"
else
world << "[spaces] [query_tree[item]]"
/proc/SDQL_from_objs(list/tree)
if("world" in tree)
return list(world)
var/list/out = list()
for(var/type in tree)
var/char = copytext(type, 1, 2)
if(char == "/")
out += SDQL_get_all(type, world)
else if(char == "'" || char == "\"")
out += locate(copytext(type, 2, length(type)))
return out
/proc/SDQL_get_all(type, location)
var/list/out = list()
if(type == "*")
for(var/datum/d in location)
out += d
return out
type = text2path(type)
if(ispath(type, /mob))
for(var/mob/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /turf))
for(var/turf/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /obj))
for(var/obj/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /area))
for(var/area/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /atom))
for(var/atom/d in location)
if(istype(d, type))
out += d
else
for(var/datum/d in location)
if(istype(d, type))
out += d
return out
/proc/SDQL_expression(datum/object, list/expression, start = 1)
var/result = 0
var/val
for(var/i = start, i <= expression.len, i++)
var/op = ""
if(i > start)
op = expression[i]
i++
var/list/ret = SDQL_value(object, expression, i)
val = ret["val"]
i = ret["i"]
if(op != "")
switch(op)
if("+")
result += val
if("-")
result -= val
if("*")
result *= val
if("/")
result /= val
if("&")
result &= val
if("|")
result |= val
if("^")
result ^= val
if("=", "==")
result = (result == val)
if("!=", "<>")
result = (result != val)
if("<")
result = (result < val)
if("<=")
result = (result <= val)
if(">")
result = (result > val)
if(">=")
result = (result >= val)
if("and", "&&")
result = (result && val)
if("or", "||")
result = (result || val)
else
usr << "\red SDQL2: Unknown op [op]"
result = null
else
result = val
return result
/proc/SDQL_value(datum/object, list/expression, start = 1)
var/i = start
var/val = null
if(i > expression.len)
return list("val" = null, "i" = i)
if(istype(expression[i], /list))
val = SDQL_expression(object, expression[i])
else if(expression[i] == "!")
var/list/ret = SDQL_value(object, expression, i + 1)
val = !ret["val"]
i = ret["i"]
else if(expression[i] == "~")
var/list/ret = SDQL_value(object, expression, i + 1)
val = ~ret["val"]
i = ret["i"]
else if(expression[i] == "-")
var/list/ret = SDQL_value(object, expression, i + 1)
val = -ret["val"]
i = ret["i"]
else if(expression[i] == "null")
val = null
else if(isnum(expression[i]))
val = expression[i]
else if(copytext(expression[i], 1, 2) in list("'", "\""))
val = copytext(expression[i], 2, length(expression[i]))
else
val = SDQL_var(object, expression, i)
i = expression.len
return list("val" = val, "i" = i)
/proc/SDQL_var(datum/object, list/expression, start = 1)
if(expression[start] in object.vars)
if(start < expression.len && expression[start + 1] == ".")
return SDQL_var(object.vars[expression[start]], expression[start + 2])
else
return object.vars[expression[start]]
else
return null
/proc/SDQL2_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
var/list/single = list("(", ")", ",", "+", "-", ".")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
">" = list("", "="),
"!" = list("", "="))
var/word = ""
var/list/query_list = list()
var/len = length(query_text)
for(var/i = 1, i <= len, i++)
var/char = copytext(query_text, i, i + 1)
if(char in whitespace)
if(word != "")
query_list += word
word = ""
else if(char in single)
if(word != "")
query_list += word
word = ""
query_list += char
else if(char in multi)
if(word != "")
query_list += word
word = ""
var/char2 = copytext(query_text, i + 1, i + 2)
if(char2 in multi[char])
query_list += "[char][char2]"
i++
else
query_list += char
else if(char == "'")
if(word != "")
usr << "\red SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "'"
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "'")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "'"
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]'"
word = ""
else if(char == "\"")
if(word != "")
usr << "\red SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "\""
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "\"")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "\""
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]\""
word = ""
else
word += char
if(word != "")
query_list += word
return query_list
+531
View File
@@ -0,0 +1,531 @@
//I'm pretty sure that this is a recursive [s]descent[/s] ascent parser.
//Spec
//////////
//
// query : select_query | delete_query | update_query | call_query | explain
// explain : 'EXPLAIN' query
//
// select_query : 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// delete_query : 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// update_query : 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
// call_query : 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
//
// select_list : select_item [',' select_list]
// select_item : '*' | select_function | object_type
// select_function : count_function
// count_function : 'COUNT' '(' '*' ')' | 'COUNT' '(' object_types ')'
//
// from_list : from_item [',' from_list]
// from_item : 'world' | object_type
//
// call_function : <function name> ['(' [arguments] ')']
// arguments : expression [',' arguments]
//
// object_type : <type path> | string
//
// assignments : assignment, [',' assignments]
// assignment : <variable name> '=' expression
// variable : <variable name> | <variable name> '.' variable
//
// bool_expression : expression comparitor expression [bool_operator bool_expression]
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
// value : variable | string | number | 'null'
// unary_operator : '!' | '-' | '~'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
// bool_operator : 'AND' | '&&' | 'OR' | '||'
//
// string : ''' <some text> ''' | '"' <some text > '"'
// number : <some digits>
//
//////////
/datum/SDQL_parser
var/query_type
var/error = 0
var/list/query
var/list/tree
var/list/select_functions = list("count")
var/list/boolean_operators = list("and", "or", "&&", "||")
var/list/unary_operators = list("!", "-", "~")
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^")
var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
/datum/SDQL_parser/New(query_list)
query = query_list
/datum/SDQL_parser/proc/parse_error(error_message)
error = 1
usr << "\red SQDL2 Parsing Error: [error_message]"
return query.len + 1
/datum/SDQL_parser/proc/parse()
tree = list()
query(1, tree)
if(error)
return list()
else
return tree
/datum/SDQL_parser/proc/token(i)
if(i <= query.len)
return query[i]
else
return null
/datum/SDQL_parser/proc/tokens(i, num)
if(i + num <= query.len)
return query.Copy(i, i + num)
else
return null
/datum/SDQL_parser/proc/tokenl(i)
return lowertext(token(i))
/datum/SDQL_parser/proc
//query: select_query | delete_query | update_query
query(i, list/node)
query_type = tokenl(i)
switch(query_type)
if("select")
select_query(i, node)
if("delete")
delete_query(i, node)
if("update")
update_query(i, node)
if("call")
call_query(i, node)
if("explain")
node += "explain"
node["explain"] = list()
query(i + 1, node["explain"])
// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
select_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "select"
node["select"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
delete_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "delete"
node["delete"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
update_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "update"
node["update"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) != "set")
i = parse_error("UPDATE has misplaced SET")
var/list/set_assignments = list()
i = assignments(i + 1, set_assignments)
node += "set"
node["set"] = set_assignments
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
call_query(i, list/node)
var/list/func = list()
i = call_function(i + 1, func)
node += "call"
node["call"] = func
if(tokenl(i) != "on")
return i
var/list/select = list()
i = select_list(i + 1, select)
node += "on"
node["on"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//select_list: select_item [',' select_list]
select_list(i, list/node)
i = select_item(i, node)
if(token(i) == ",")
i = select_list(i + 1, node)
return i
//from_list: from_item [',' from_list]
from_list(i, list/node)
i = from_item(i, node)
if(token(i) == ",")
i = from_list(i + 1, node)
return i
//assignments: assignment, [',' assignments]
assignments(i, list/node)
i = assignment(i, node)
if(token(i) == ",")
i = assignments(i + 1, node)
return i
//select_item: '*' | select_function | object_type
select_item(i, list/node)
if(token(i) == "*")
node += "*"
i++
else if(tokenl(i) in select_functions)
i = select_function(i, node)
else
i = object_type(i, node)
return i
//from_item: 'world' | object_type
from_item(i, list/node)
if(token(i) == "world")
node += "world"
i++
else
i = object_type(i, node)
return i
//bool_expression: expression [bool_operator bool_expression]
bool_expression(i, list/node)
var/list/bool = list()
i = expression(i, bool)
node[++node.len] = bool
if(tokenl(i) in boolean_operators)
i = bool_operator(i, node)
i = bool_expression(i, node)
return i
//assignment: <variable name> '=' expression
assignment(i, list/node)
node += token(i)
if(token(i + 1) == "=")
var/varname = token(i)
node[varname] = list()
i = expression(i + 2, node[varname])
else
parse_error("Assignment expected, but no = found")
return i
//variable: <variable name> | <variable name> '.' variable
variable(i, list/node)
var/list/L = list(token(i))
node[++node.len] = L
if(token(i + 1) == ".")
L += "."
i = variable(i + 2, L)
else
i++
return i
//object_type: <type path> | string
object_type(i, list/node)
if(copytext(token(i), 1, 2) == "/")
node += token(i)
else
i = string(i, node)
return i + 1
//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
comparitor(i, list/node)
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//bool_operator: 'AND' | '&&' | 'OR' | '||'
bool_operator(i, list/node)
if(tokenl(i) in list("and", "or", "&&", "||"))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//string: ''' <some text> ''' | '"' <some text > '"'
string(i, list/node)
if(copytext(token(i), 1, 2) in list("'", "\""))
node += token(i)
else
parse_error("Expected string but found '[token(i)]'")
return i + 1
//call_function: <function name> ['(' [arguments] ')']
call_function(i, list/node)
parse_error("Sorry, function calls aren't available yet")
return i
//select_function: count_function
select_function(i, list/node)
parse_error("Sorry, function calls aren't available yet")
return i
//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
expression(i, list/node)
if(token(i) in unary_operators)
i = unary_expression(i, node)
else if(token(i) == "(")
var/list/expr = list()
i = expression(i + 1, expr)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
else
i++
node[++node.len] = expr
else
i = value(i, node)
if(token(i) in binary_operators)
i = binary_operator(i, node)
i = expression(i, node)
else if(token(i) in comparitors)
i = binary_operator(i, node)
var/list/rhs = list()
i = expression(i, rhs)
node[++node.len] = rhs
return i
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
unary_expression(i, list/node)
if(token(i) in unary_operators)
var/list/unary_exp = list()
unary_exp += token(i)
i++
if(token(i) in unary_operators)
i = unary_expression(i, unary_exp)
else if(token(i) == "(")
var/list/expr = list()
i = expression(i + 1, expr)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
else
i++
unary_exp[++unary_exp.len] = expr
else
i = value(i, unary_exp)
node[++node.len] = unary_exp
else
parse_error("Expected unary operator but found '[token(i)]'")
return i
//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
binary_operator(i, list/node)
if(token(i) in (binary_operators + comparitors))
node += token(i)
else
parse_error("Unknown binary operator [token(i)]")
return i + 1
//value: variable | string | number | 'null'
value(i, list/node)
if(token(i) == "null")
node += "null"
i++
else if(isnum(text2num(token(i))))
node += text2num(token(i))
i++
else if(copytext(token(i), 1, 2) in list("'", "\""))
i = string(i, node)
else
i = variable(i, node)
return i
/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
+115
View File
@@ -0,0 +1,115 @@
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as")
/client/verb/adminhelp(msg as text)
set category = "Admin"
set name = "Adminhelp"
if(say_disabled) //This is here to try to identify lag problems
usr << "\red Speech is currently admin-disabled."
return
//handle muting and automuting
if(prefs.muted & MUTE_ADMINHELP)
src << "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>"
return
if(src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
/**src.verbs -= /client/verb/adminhelp
spawn(1200)
src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps
src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps//Go to hell
**/
//clean the input msg
if(!msg) return
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/original_msg = msg
//explode the input msg into a list
var/list/msglist = text2list(msg, " ")
//generate keywords lookup
var/list/surnames = list()
var/list/forenames = list()
var/list/ckeys = list()
for(var/mob/M in mob_list)
var/list/indexing = list(M.real_name, M.name)
if(M.mind) indexing += M.mind.name
for(var/string in indexing)
var/list/L = text2list(string, " ")
var/surname_found = 0
//surnames
for(var/i=L.len, i>=1, i--)
var/word = ckey(L[i])
if(word)
surnames[word] = M
surname_found = i
break
//forenames
for(var/i=1, i<surname_found, i++)
var/word = ckey(L[i])
if(word)
forenames[word] = M
//ckeys
ckeys[M.ckey] = M
var/ai_found = 0
msg = ""
var/list/mobs_found = list()
for(var/original_word in msglist)
var/word = ckey(original_word)
if(word)
if(!(word in adminhelp_ignored_words))
if(word == "ai")
ai_found = 1
else
var/mob/found = ckeys[word]
if(!found)
found = surnames[word]
if(!found)
found = forenames[word]
if(found)
if(!(found in mobs_found))
mobs_found += found
if(!ai_found && isAI(found))
ai_found = 1
msg += "<b><font color='black'>[original_word] (<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>)</font></b> "
continue
msg += "[original_word] "
if(!mob) return //this doesn't happen
var/ref_mob = "\ref[mob]"
msg = "\blue <b><font color=red>HELP: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>) [ai_found ? " (<A HREF='?_src_=holder;adminchecklaws=[ref_mob]'>CL</A>)" : ""]:</b> [msg]"
//send this msg to all admins
var/admin_number_afk = 0
for(var/client/X in admins)
if((R_ADMIN|R_MOD) & X.holder.rights)
if(X.is_afk())
admin_number_afk++
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
//show it to the person adminhelping too
src << "<font color='blue'>PM to-<b>Admins</b>: [original_msg]</font>"
var/admin_number_present = admins.len - admin_number_afk
log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.")
if(admin_number_present <= 0)
if(!admin_number_afk)
send2adminirc("ADMINHELP from [key_name(src)]: [original_msg] - !!No admins online!!")
else
send2adminirc("ADMINHELP from [key_name(src)]: [original_msg] - !!All admins AFK ([admin_number_afk])!!")
else
send2adminirc("ADMINHELP from [key_name(src)]: [original_msg]")
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+157
View File
@@ -0,0 +1,157 @@
/client/proc/Jump(var/area/A in return_sorted_areas())
set name = "Jump to Area"
set desc = "Area to jump to"
set category = "Admin"
if(!src.holder)
src << "Only administrators may use this command."
return
if(config.allow_admin_jump)
usr.loc = pick(get_area_turfs(A))
log_admin("[key_name(usr)] jumped to [A]")
message_admins("[key_name_admin(usr)] jumped to [A]", 1)
feedback_add_details("admin_verb","JA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else
alert("Admin jumping disabled")
/client/proc/jumptoturf(var/turf/T in world)
set name = "Jump to Turf"
set category = "Admin"
if(!src.holder)
src << "Only administrators may use this command."
return
if(config.allow_admin_jump)
log_admin("[key_name(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]")
message_admins("[key_name_admin(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]", 1)
usr.loc = T
feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else
alert("Admin jumping disabled")
return
/client/proc/jumptomob(var/mob/M in mob_list)
set category = "Admin"
set name = "Jump to Mob"
if(!src.holder)
src << "Only administrators may use this command."
return
if(config.allow_admin_jump)
log_admin("[key_name(usr)] jumped to [key_name(M)]")
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
if(src.mob)
var/mob/A = src.mob
var/turf/T = get_turf(M)
if(T && isturf(T))
feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
A.loc = T
else
A << "This mob is not located in the game world."
else
alert("Admin jumping disabled")
/client/proc/jumptocoord(tx as num, ty as num, tz as num)
set category = "Admin"
set name = "Jump to Coordinate"
if (!holder)
src << "Only administrators may use this command."
return
if (config.allow_admin_jump)
if(src.mob)
var/mob/A = src.mob
A.x = tx
A.y = ty
A.z = tz
feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]")
else
alert("Admin jumping disabled")
/client/proc/jumptokey()
set category = "Admin"
set name = "Jump to Key"
if(!src.holder)
src << "Only administrators may use this command."
return
if(config.allow_admin_jump)
var/list/keys = list()
for(var/mob/M in player_list)
keys += M.client
var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
if(!selection)
src << "No keys found."
return
var/mob/M = selection:mob
log_admin("[key_name(usr)] jumped to [key_name(M)]")
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
usr.loc = M.loc
feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else
alert("Admin jumping disabled")
/client/proc/Getmob(var/mob/M in mob_list)
set category = "Admin"
set name = "Get Mob"
set desc = "Mob to teleport"
if(!src.holder)
src << "Only administrators may use this command."
return
if(config.allow_admin_jump)
log_admin("[key_name(usr)] teleported [key_name(M)]")
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1)
M.loc = get_turf(usr)
feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else
alert("Admin jumping disabled")
/client/proc/Getkey()
set category = "Admin"
set name = "Get Key"
set desc = "Key to teleport"
if(!src.holder)
src << "Only administrators may use this command."
return
if(config.allow_admin_jump)
var/list/keys = list()
for(var/mob/M in player_list)
keys += M.client
var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
if(!selection)
return
var/mob/M = selection:mob
if(!M)
return
log_admin("[key_name(usr)] teleported [key_name(M)]")
message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1)
if(M)
M.loc = get_turf(usr)
feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else
alert("Admin jumping disabled")
/client/proc/sendmob(var/mob/M in sortmobs())
set category = "Admin"
set name = "Send Mob"
if(!src.holder)
src << "Only administrators may use this command."
return
var/area/A = input(usr, "Pick an area.", "Pick an area") in return_sorted_areas()
if(A)
if(config.allow_admin_jump)
M.loc = pick(get_area_turfs(A))
feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1)
else
alert("Admin jumping disabled")
+184
View File
@@ -0,0 +1,184 @@
//allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm
/client/proc/cmd_admin_pm_context(mob/M as mob in mob_list)
set category = null
set name = "Admin PM Mob"
if(!holder)
src << "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>"
return
if( !ismob(M) || !M.client ) return
cmd_admin_pm(M.client,null)
feedback_add_details("admin_verb","APMM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//shows a list of clients we could send PMs to, then forwards our choice to cmd_admin_pm
/client/proc/cmd_admin_pm_panel()
set category = "Admin"
set name = "Admin PM"
if(!holder)
src << "<font color='red'>Error: Admin-PM-Panel: Only administrators may use this command.</font>"
return
var/list/client/targets[0]
for(var/client/T)
if(T.mob)
if(istype(T.mob, /mob/new_player))
targets["(New Player) - [T]"] = T
else if(istype(T.mob, /mob/dead/observer))
targets["[T.mob.name](Ghost) - [T]"] = T
else
targets["[T.mob.real_name](as [T.mob.name]) - [T]"] = T
else
targets["(No Mob) - [T]"] = T
var/list/sorted = sortList(targets)
var/target = input(src,"To whom shall we send a message?","Admin PM",null) in sorted|null
cmd_admin_pm(targets[target],null)
feedback_add_details("admin_verb","APM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM.
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(var/client/C, var/msg)
if(prefs.muted & MUTE_ADMINHELP)
src << "<font color='red'>Error: Private-Message: You are unable to use PM-s (muted).</font>"
return
if(!istype(C,/client))
if(holder) src << "<font color='red'>Error: Private-Message: Client not found.</font>"
else adminhelp(msg) //admin we are replying to left. adminhelp instead
return
/*if(C && C.last_pm_recieved + config.simultaneous_pm_warning_timeout > world.time && holder)
//send a warning to admins, but have a delay popup for mods
if(holder.rights & R_ADMIN)
src << "\red <b>Simultaneous PMs warning:</b> that player has been PM'd in the last [config.simultaneous_pm_warning_timeout / 10] seconds by: [C.ckey_last_pm]"
else
if(alert("That player has been PM'd in the last [config.simultaneous_pm_warning_timeout / 10] seconds by: [C.ckey_last_pm]","Simultaneous PMs warning","Continue","Cancel") == "Cancel")
return*/
//get message text, limit it's length.and clean/escape html
if(!msg)
msg = input(src,"Message:", "Private message to [key_name(C, 0, holder ? 1 : 0)]") as text|null
if(!msg) return
if(!C)
if(holder) src << "<font color='red'>Error: Admin-PM: Client not found.</font>"
else adminhelp(msg) //admin we are replying to has vanished, adminhelp instead
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0))
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/recieve_color = "purple"
var/send_pm_type = " "
var/recieve_pm_type = "Player"
if(holder)
//mod PMs are maroon
//PMs sent from admins and mods display their rank
if(holder)
if( holder.rights & R_ADMIN )
recieve_color = "red"
else
recieve_color = "maroon"
send_pm_type = holder.rank + " "
recieve_pm_type = holder.rank
else if(!C.holder)
src << "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>"
return
var/recieve_message = ""
if(holder && !C.holder)
recieve_message = "<font color='[recieve_color]' size='4'><b>-- Administrator private message --</b></font>\n"
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
spawn(0) //so we don't hold the caller proc up
var/sender = src
var/sendername = key
var/reply = input(C, msg,"[recieve_pm_type] PM from-[sendername]", "") as text|null //show message and await a reply
if(C && reply)
if(sender)
C.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
else
adminhelp(reply) //sender has left, adminhelp instead
return
recieve_message = "<font color='[recieve_color]'>[recieve_pm_type] PM from-<b>[key_name(src, C, C.holder ? 1 : 0)]</b>: [msg]</font>"
C << recieve_message
src << "<font color='blue'>[send_pm_type]PM to-<b>[key_name(C, src, holder ? 1 : 0)]</b>: [msg]</font>"
/*if(holder && !C.holder)
C.last_pm_recieved = world.time
C.ckey_last_pm = ckey*/
//play the recieving admin the adminhelp sound (if they have them enabled)
//non-admins shouldn't be able to disable this
if(C.prefs.toggles & SOUND_ADMINHELP)
C << 'sound/effects/adminhelp.ogg'
/*
if(C.holder)
if(holder) //both are admins
if(holder.rank == "Moderator") //If moderator
C << "<font color='maroon'>Mod PM from-<b>[key_name(src, C, 1)]</b>: [msg]</font>"
src << "<font color='blue'>Mod PM to-<b>[key_name(C, src, 1)]</b>: [msg]</font>"
else
C << "<font color='red'>Admin PM from-<b>[key_name(src, C, 1)]</b>: [msg]</font>"
src << "<font color='blue'>Admin PM to-<b>[key_name(C, src, 1)]</b>: [msg]</font>"
else //recipient is an admin but sender is not
C << "<font color='red'>Reply PM from-<b>[key_name(src, C, 1)]</b>: [msg]</font>"
src << "<font color='blue'>PM to-<b>Admins</b>: [msg]</font>"
//play the recieving admin the adminhelp sound (if they have them enabled)
if(C.prefs.toggles & SOUND_ADMINHELP)
C << 'sound/effects/adminhelp.ogg'
else
if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT
if(holder.rank == "Moderator")
C << "<font color='maroon'>Mod PM from-<b>[key_name(src, C, 0)]</b>: [msg]</font>"
C << "<font color='maroon'><i>Click on the moderators's name to reply.</i></font>"
src << "<font color='blue'>Mod PM to-<b>[key_name(C, src, 1)]</b>: [msg]</font>"
else
C << "<font color='red' size='4'><b>-- Administrator private message --</b></font>"
C << "<font color='red'>Admin PM from-<b>[key_name(src, C, 0)]</b>: [msg]</font>"
C << "<font color='red'><i>Click on the administrator's name to reply.</i></font>"
src << "<font color='blue'>Admin PM to-<b>[key_name(C, src, 1)]</b>: [msg]</font>"
//always play non-admin recipients the adminhelp sound
C << 'sound/effects/adminhelp.ogg'
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
spawn() //so we don't hold the caller proc up
var/sender = src
var/sendername = key
var/reply = input(C, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply
if(C && reply)
if(sender)
C.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
else
adminhelp(reply) //sender has left, adminhelp instead
return
else //neither are admins
src << "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>"
return
*/
log_admin("PM: [key_name(src)]->[key_name(C)]: [msg]")
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in admins)
//check client/X is an admin and isn't the sender or recipient
if(X == C || X == src)
continue
if(X.key!=key && X.key!=C.key && (X.holder.rights & R_ADMIN) || (X.holder.rights & R_MOD) )
X << "<B><font color='blue'>PM: [key_name(src, X, 0)]-&gt;[key_name(C, X, 0)]:</B> \blue [msg]</font>" //inform X
+37
View File
@@ -0,0 +1,37 @@
/client/proc/cmd_admin_say(msg as text)
set category = "Special Verbs"
set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite
set hidden = 1
if(!check_rights(R_ADMIN)) return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
if(!msg) return
log_admin("[key_name(src)] : [msg]")
if(check_rights(R_ADMIN,0))
msg = "<span class='adminsay'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> (<a href='?_src_=holder;adminplayerobservejump=\ref[mob]'>JMP</A>): <span class='message'>[msg]</span></span>"
for(var/client/C in admins)
if(R_ADMIN & C.holder.rights)
C << msg
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_mod_say(msg as text)
set category = "Special Verbs"
set name = "Msay"
set hidden = 1
if(!check_rights(R_ADMIN|R_MOD)) return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
log_admin("MOD: [key_name(src)] : [msg]")
if (!msg)
return
var/color = "mod"
if (check_rights(R_ADMIN,0))
color = "adminmod"
for(var/client/C in admins)
if((R_ADMIN|R_MOD) & C.holder.rights)
C << "<span class='[color]'><span class='prefix'>MOD:</span> <EM>[key_name(src,1)]</EM> (<A HREF='?src=\ref[C.holder];adminplayerobservejump=\ref[mob]'>JMP</A>): <span class='message'>[msg]</span></span>"
+41
View File
@@ -0,0 +1,41 @@
/client/proc/atmosscan()
set category = "Mapping"
set name = "Check Plumbing"
if(!src.holder)
src << "Only administrators may use this command."
return
feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//all plumbing - yes, some things might get stated twice, doesn't matter.
for (var/obj/machinery/atmospherics/plumbing in world)
if (plumbing.nodealert)
usr << "Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])"
//Manifolds
for (var/obj/machinery/atmospherics/pipe/manifold/pipe in world)
if (!pipe.node1 || !pipe.node2 || !pipe.node3)
usr << "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])"
//Pipes
for (var/obj/machinery/atmospherics/pipe/simple/pipe in world)
if (!pipe.node1 || !pipe.node2)
usr << "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])"
/client/proc/powerdebug()
set category = "Mapping"
set name = "Check Power"
if(!src.holder)
src << "Only administrators may use this command."
return
feedback_add_details("admin_verb","CPOW") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
for (var/datum/powernet/PN in powernets)
if (!PN.nodes || !PN.nodes.len)
if(PN.cables && (PN.cables.len > 1))
var/obj/structure/cable/C = PN.cables[1]
usr << "Powernet with no nodes! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [get_area(C.loc)]"
if (!PN.cables || (PN.cables.len < 10))
if(PN.cables && (PN.cables.len > 1))
var/obj/structure/cable/C = PN.cables[1]
usr << "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [get_area(C.loc)]"
@@ -0,0 +1,85 @@
var/checked_for_inactives = 0
var/inactive_keys = "None<br>"
/client/proc/check_customitem_activity()
set category = "Admin"
set name = "Check activity of players with custom items"
var/dat = "<b>Inactive players with custom items</b><br>"
dat += "<br>"
dat += "The list below contains players with custom items that have not logged\
in for the past two months, or have not logged in since this system was implemented.\
This system requires the feedback SQL database to be properly setup and linked.<br>"
dat += "<br>"
dat += "Populating this list is done automatically, but must be manually triggered on a per\
round basis. Populating the list may cause a lag spike, so use it sparingly.<br>"
dat += "<hr>"
if(checked_for_inactives)
dat += inactive_keys
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>"
usr << browse(dat, "window=inactive_customitems;size=600x480")
/proc/populate_inactive_customitems_list(var/client/C)
set background = 1
if(checked_for_inactives)
return
establish_db_connection()
if(!dbcon.IsConnected())
return
//grab all ckeys associated with custom items
var/list/ckeys_with_customitems = list()
var/file = file2text("config/custom_items.txt")
var/lines = text2list(file, "\n")
for(var/line in lines)
// split & clean up
var/list/Entry = text2list(line, ":")
for(var/i = 1 to Entry.len)
Entry[i] = trim(Entry[i])
if(Entry.len < 1)
continue
var/cur_key = Entry[1]
if(!ckeys_with_customitems.Find(cur_key))
ckeys_with_customitems.Add(cur_key)
//run a query to get all ckeys inactive for over 2 months
var/list/inactive_ckeys = list()
if(ckeys_with_customitems.len)
var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey, lastseen FROM erro_player WHERE datediff(Now(), lastseen) > 60")
query_inactive.Execute()
while(query_inactive.NextRow())
var/cur_ckey = query_inactive.item[1]
//if the ckey has a custom item attached, output it
if(ckeys_with_customitems.Find(cur_ckey))
ckeys_with_customitems.Remove(cur_ckey)
inactive_ckeys[cur_ckey] = "last seen on [query_inactive.item[2]]"
//if there are ckeys left over, check whether they have a database entry at all
if(ckeys_with_customitems.len)
for(var/cur_ckey in ckeys_with_customitems)
var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE ckey = '[cur_ckey]'")
query_inactive.Execute()
if(!query_inactive.RowCount())
inactive_ckeys += cur_ckey
if(inactive_ckeys.len)
inactive_keys = ""
for(var/cur_key in inactive_ckeys)
if(inactive_ckeys[cur_key])
inactive_keys += "<b>[cur_key]</b> - [inactive_ckeys[cur_key]]<br>"
else
inactive_keys += "[cur_key] - no database entry<br>"
checked_for_inactives = 1
if(C)
C.check_customitem_activity()
+18
View File
@@ -0,0 +1,18 @@
/client/proc/cinematic(var/cinematic as anything in list("explosion",null))
set name = "cinematic"
set category = "Fun"
set desc = "Shows a cinematic." // Intended for testing but I thought it might be nice for events on the rare occasion Feel free to comment it out if it's not wanted.
set hidden = 1
if(alert("Are you sure you want to run [cinematic]?","Confirmation","Yes","No")=="No") return
if(!ticker) return
switch(cinematic)
if("explosion")
var/parameter = input(src,"station_missed = ?","Enter Parameter",0) as num
var/override
switch(parameter)
if(1)
override = input(src,"mode = ?","Enter Parameter",null) as anything in list("nuclear emergency","no override")
if(0)
override = input(src,"mode = ?","Enter Parameter",null) as anything in list("blob","nuclear emergency","AI malfunction","no override")
ticker.station_explosion_cinematic(parameter,override)
return
+40
View File
@@ -0,0 +1,40 @@
// verb for admins to set custom event
/client/proc/cmd_admin_change_custom_event()
set category = "Fun"
set name = "Change Custom Event"
if(!holder)
src << "Only administrators may use this command."
return
var/input = input(usr, "Enter the description of the custom event. Be descriptive. To cancel the event, make this blank or hit cancel.", "Custom Event", custom_event_msg) as message|null
if(!input || input == "")
custom_event_msg = null
log_admin("[usr.key] has cleared the custom event text.")
message_admins("[key_name_admin(usr)] has cleared the custom event text.")
return
log_admin("[usr.key] has changed the custom event text.")
message_admins("[key_name_admin(usr)] has changed the custom event text.")
custom_event_msg = input
world << "<h1 class='alert'>Custom Event</h1>"
world << "<h2 class='alert'>A custom event is starting. OOC Info:</h2>"
world << "<span class='alert'>[html_encode(custom_event_msg)]</span>"
world << "<br>"
// normal verb for players to view info
/client/verb/cmd_view_custom_event()
set category = "OOC"
set name = "Custom Event Info"
if(!custom_event_msg || custom_event_msg == "")
src << "There currently is no known custom event taking place."
src << "Keep in mind: it is possible that an admin has not properly set this."
return
src << "<h1 class='alert'>Custom Event</h1>"
src << "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>"
src << "<span class='alert'>[html_encode(custom_event_msg)]</span>"
src << "<br>"
+47
View File
@@ -0,0 +1,47 @@
/client/proc/dsay(msg as text)
set category = "Special Verbs"
set name = "Dsay" //Gave this shit a shorter name so you only have to time out "dsay" rather than "dead say" to use it --NeoFite
set hidden = 1
if(!src.holder)
src << "Only administrators may use this command."
return
if(!src.mob)
return
if(prefs.muted & MUTE_DEADCHAT)
src << "\red You cannot send DSAY messages (muted)."
return
if(!(prefs.toggles & CHAT_DEAD))
src << "\red You have deadchat muted."
return
if (src.handle_spam_prevention(msg,MUTE_DEADCHAT))
return
var/stafftype = null
if (src.holder.rights & R_MOD)
stafftype = "MOD"
if (src.holder.rights & R_ADMIN)
stafftype = "ADMIN"
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
log_admin("[key_name(src)] : [msg]")
if (!msg)
return
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[stafftype]([src.holder.fakekey ? pick("BADMIN", "hornigranny", "TLF", "scaredforshadows", "KSI", "Silnazi", "HerpEs", "BJ69", "SpoofedEdd", "Uhangay", "Wario90900", "Regarity", "MissPhareon", "LastFish", "unMportant", "Deurpyn", "Fatbeaver") : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
for (var/mob/M in player_list)
if (istype(M, /mob/new_player))
continue
if(M.client && M.client.holder && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to admins who have deadchat toggled on
M.show_message(rendered, 2)
else if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to regular ghosts who have deadchat toggled on
M.show_message(rendered, 2)
feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
File diff suppressed because it is too large Load Diff
+209
View File
@@ -0,0 +1,209 @@
/client/proc/air_report()
set category = "Debug"
set name = "Show Air Report"
if(!master_controller || !air_master)
alert(usr,"Master_controller or air_master not found.","Air Report")
return
var/active_groups = air_master.active_zones.len
var/inactive_groups = air_master.zones.len - active_groups
var/hotspots = 0
for(var/obj/fire/hotspot in world)
hotspots++
var/active_on_main_station = 0
var/inactive_on_main_station = 0
for(var/zone/zone in air_master.zones)
var/turf/simulated/turf = locate() in zone.contents
if(turf && turf.z == 1)
if(zone.status)
active_on_main_station++
else
inactive_on_main_station++
var/output = {"<B>AIR SYSTEMS REPORT</B><HR>
<B>General Processing Data</B><BR>
Cycle: [air_master.current_cycle]<br>
Groups: [air_master.zones.len]<BR>
---- <I>Active:</I> [active_groups]<BR>
---- <I>Inactive:</I> [inactive_groups]<BR><br>
---- <I>Active on station:</i> [active_on_main_station]<br>
---- <i>Inactive on station:</i> [inactive_on_main_station]<br>
<BR>
<B>Special Processing Data</B><BR>
Hotspot Processing: [hotspots]<BR>
<br>
<B>Geometry Processing Data</B><BR>
Tile Update: [air_master.tiles_to_update.len]<BR>
"}
usr << browse(output,"window=airreport")
/client/proc/air_status(turf/target as turf)
set category = "Debug"
set name = "Display Air Status"
/*(!isturf(target))
return
var/datum/gas_mixture/GM = target.return_air()
var/burning = 0
if(istype(target, /turf/simulated))
var/turf/simulated/T = target
if(T.active_hotspot)
burning = 1
usr << "\blue @[target.x],[target.y] ([GM.group_multiplier]): O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("\red BURNING"):(null)]"
for(var/datum/gas/trace_gas in GM.trace_gases)
usr << "[trace_gas.type]: [trace_gas.moles]"
feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
*/
/client/proc/fix_next_move()
set category = "Debug"
set name = "Unfreeze Everyone"
var/largest_move_time = 0
var/largest_click_time = 0
var/mob/largest_move_mob = null
var/mob/largest_click_mob = null
for(var/mob/M in world)
if(!M.client)
continue
if(M.next_move >= largest_move_time)
largest_move_mob = M
if(M.next_move > world.time)
largest_move_time = M.next_move - world.time
else
largest_move_time = 1
if(M.next_click >= largest_click_time)
largest_click_mob = M
if(M.next_click > world.time)
largest_click_time = M.next_click - world.time
else
largest_click_time = 0
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]")
M.next_move = 1
M.next_click = 0
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1)
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1)
message_admins("world.time = [world.time]", 1)
feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/radio_report()
set category = "Debug"
set name = "Radio report"
var/filters = list(
"1" = "RADIO_TO_AIRALARM",
"2" = "RADIO_FROM_AIRALARM",
"3" = "RADIO_CHAT",
"4" = "RADIO_ATMOSIA",
"5" = "RADIO_NAVBEACONS",
"6" = "RADIO_AIRLOCK",
"7" = "RADIO_SECBOT",
"8" = "RADIO_MULEBOT",
"_default" = "NO_FILTER"
)
var/output = "<b>Radio Report</b><hr>"
for (var/fq in radio_controller.frequencies)
output += "<b>Freq: [fq]</b><br>"
var/list/datum/radio_frequency/fqs = radio_controller.frequencies[fq]
if (!fqs)
output += "&nbsp;&nbsp;<b>ERROR</b><br>"
continue
for (var/filter in fqs.devices)
var/list/f = fqs.devices[filter]
if (!f)
output += "&nbsp;&nbsp;[filters[filter]]: ERROR<br>"
continue
output += "&nbsp;&nbsp;[filters[filter]]: [f.len]<br>"
for (var/device in f)
if (isobj(device))
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])<br>"
else
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device]<br>"
usr << browse(output,"window=radioreport")
feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/reload_admins()
set name = "Reload Admins"
set category = "Debug"
if(!check_rights(R_SERVER)) return
message_admins("[usr] manually reloaded admins")
load_admins()
feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//todo:
/client/proc/jump_to_dead_group()
set name = "Jump to dead group"
set category = "Debug"
/*
if(!holder)
src << "Only administrators may use this command."
return
if(!air_master)
usr << "Cannot find air_system"
return
var/datum/air_group/dead_groups = list()
for(var/datum/air_group/group in air_master.air_groups)
if (!group.group_processing)
dead_groups += group
var/datum/air_group/dest_group = pick(dead_groups)
usr.loc = pick(dest_group.members)
feedback_add_details("admin_verb","JDAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
*/
/client/proc/kill_airgroup()
set name = "Kill Local Airgroup"
set desc = "Use this to allow manual manupliation of atmospherics."
set category = "Debug"
/*
if(!holder)
src << "Only administrators may use this command."
return
if(!air_master)
usr << "Cannot find air_system"
return
var/turf/T = get_turf(usr)
if(istype(T, /turf/simulated))
var/datum/air_group/AG = T:parent
AG.next_check = 30
AG.group_processing = 0
else
usr << "Local airgroup is unsimulated!"
feedback_add_details("admin_verb","KLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
*/
/client/proc/print_jobban_old()
set name = "Print Jobban Log"
set desc = "This spams all the active jobban entries for the current round to standard output."
set category = "Debug"
usr << "<b>Jobbans active in this round.</b>"
for(var/t in jobban_keylist)
usr << "[t]"
/client/proc/print_jobban_old_filter()
set name = "Search Jobban Log"
set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output."
set category = "Debug"
var/filter = input("Contains what?","Filter") as text|null
if(!filter)
return
usr << "<b>Jobbans active in this round.</b>"
for(var/t in jobban_keylist)
if(findtext(t, filter))
usr << "[t]"
+111
View File
@@ -0,0 +1,111 @@
/*
HOW DO I LOG RUNTIMES?
Firstly, start dreamdeamon if it isn't already running. Then select "world>Log Session" (or press the F3 key)
navigate the popup window to the data/logs/runtime/ folder from where your tgstation .dmb is located.
(you may have to make this folder yourself)
OPTIONAL: you can select the little checkbox down the bottom to make dreamdeamon save the log everytime you
start a world. Just remember to repeat these steps with a new name when you update to a new revision!
Save it with the name of the revision your server uses (e.g. r3459.txt).
Game Masters will now be able to grant access any runtime logs you have archived this way!
This will allow us to gather information on bugs across multiple servers and make maintaining the TG
codebase for the entire /TG/station commuity a TONNE easier :3 Thanks for your help!
*/
//This proc allows Game Masters to grant a client access to the .getruntimelog verb
//Permissions expire at the end of each round.
//Runtimes can be used to meta or spot game-crashing exploits so it's advised to only grant coders that
//you trust access. Also, it may be wise to ensure that they are not going to play in the current round.
/client/proc/giveruntimelog()
set name = ".giveruntimelog"
set desc = "Give somebody access to any session logfiles saved to the /log/runtime/ folder."
set category = null
if(!src.holder)
src << "<font color='red'>Only Admins may use this command.</font>"
return
var/client/target = input(src,"Choose somebody to grant access to the server's runtime logs (permissions expire at the end of each round):","Grant Permissions",null) as null|anything in clients
if(!istype(target,/client))
src << "<font color='red'>Error: giveruntimelog(): Client not found.</font>"
return
target.verbs |= /client/proc/getruntimelog
target << "<font color='red'>You have been granted access to runtime logs. Please use them responsibly or risk being banned.</font>"
return
//This proc allows download of runtime logs saved within the data/logs/ folder by dreamdeamon.
//It works similarly to show-server-log.
/client/proc/getruntimelog()
set name = ".getruntimelog"
set desc = "Retrieve any session logfiles saved by dreamdeamon."
set category = null
var/path = browse_files("data/logs/runtime/")
if(!path)
return
if(file_spam_check())
return
message_admins("[key_name_admin(src)] accessed file: [path]")
src << run( file(path) )
src << "Attempting to send file, this may take a fair few minutes if the file is very large."
return
//This proc allows download of past server logs saved within the data/logs/ folder.
//It works similarly to show-server-log.
/client/proc/getserverlog()
set name = ".getserverlog"
set desc = "Fetch logfiles from data/logs"
set category = null
var/path = browse_files("data/logs/")
if(!path)
return
if(file_spam_check())
return
message_admins("[key_name_admin(src)] accessed file: [path]")
src << run( file(path) )
src << "Attempting to send file, this may take a fair few minutes if the file is very large."
return
//Other log stuff put here for the sake of organisation
//Shows today's server log
/datum/admins/proc/view_txt_log()
set category = "Admin"
set name = "Show Server Log"
set desc = "Shows today's server log."
var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")].log"
if( fexists(path) )
src << run( file(path) )
else
src << "<font color='red'>Error: view_txt_log(): File not found/Invalid path([path]).</font>"
return
feedback_add_details("admin_verb","VTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
//Shows today's attack log
/datum/admins/proc/view_atk_log()
set category = "Admin"
set name = "Show Server Attack Log"
set desc = "Shows today's server attack log."
var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")] Attack.log"
if( fexists(path) )
src << run( file(path) )
else
src << "<font color='red'>Error: view_atk_log(): File not found/Invalid path([path]).</font>"
return
usr << run( file(path) )
feedback_add_details("admin_verb","SSAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+413
View File
@@ -0,0 +1,413 @@
//- Are all the floors with or without air, as they should be? (regular or airless)
//- Does the area have an APC?
//- Does the area have an Air Alarm?
//- Does the area have a Request Console?
//- Does the area have lights?
//- Does the area have a light switch?
//- Does the area have enough intercoms?
//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug)
//- Is the area connected to the scrubbers air loop?
//- Is the area connected to the vent air loop? (vent pumps)
//- Is everything wired properly?
//- Does the area have a fire alarm and firedoors?
//- Do all pod doors work properly?
//- Are accesses set properly on doors, pod buttons, etc.
//- Are all items placed properly? (not below vents, scrubbers, tables)
//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room?
//- Check for any misplaced or stacked piece of pipe (air and disposal)
//- Check for any misplaced or stacked piece of wire
//- Identify how hard it is to break into the area and where the weak points are
//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
var/camera_range_display_status = 0
var/intercom_range_display_status = 0
/obj/effect/debugging/camera_range
icon = 'icons/480x480.dmi'
icon_state = "25percent"
New()
src.pixel_x = -224
src.pixel_y = -224
/obj/effect/debugging/marker
icon = 'icons/turf/areas.dmi'
icon_state = "yellow"
/obj/effect/debugging/marker/Move()
return 0
/client/proc/do_not_use_these()
set category = "Mapping"
set name = "-None of these are for ingame use!!"
..()
/client/proc/camera_view()
set category = "Mapping"
set name = "Camera Range Display"
if(camera_range_display_status)
camera_range_display_status = 0
else
camera_range_display_status = 1
for(var/obj/effect/debugging/camera_range/C in world)
del(C)
if(camera_range_display_status)
for(var/obj/machinery/camera/C in cameranet.cameras)
new/obj/effect/debugging/camera_range(C.loc)
feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/sec_camera_report()
set category = "Mapping"
set name = "Camera Report"
if(!master_controller)
alert(usr,"Master_controller not found.","Sec Camera Report")
return 0
var/list/obj/machinery/camera/CL = list()
for(var/obj/machinery/camera/C in cameranet.cameras)
CL += C
var/output = {"<B>CAMERA ANNOMALITIES REPORT</B><HR>
<B>The following annomalities have been detected. The ones in red need immediate attention: Some of those in black may be intentional.</B><BR><ul>"}
for(var/obj/machinery/camera/C1 in CL)
for(var/obj/machinery/camera/C2 in CL)
if(C1 != C2)
if(C1.c_tag == C2.c_tag)
output += "<li><font color='red'>c_tag match for sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) and \[[C2.x], [C2.y], [C2.z]\] ([C2.loc.loc]) - c_tag is [C1.c_tag]</font></li>"
if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
output += "<li><font color='red'>FULLY overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
if(C1.loc == C2.loc)
output += "<li>overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
var/turf/T = get_step(C1,turn(C1.dir,180))
if(!T || !isturf(T) || !T.density )
if(!(locate(/obj/structure/grille,T)))
var/window_check = 0
for(var/obj/structure/window/W in T)
if (W.dir == turn(C1.dir,180) || W.dir in list(5,6,9,10) )
window_check = 1
break
if(!window_check)
output += "<li><font color='red'>Camera not connected to wall at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Network: [C1.network]</color></li>"
output += "</ul>"
usr << browse(output,"window=airreport;size=1000x500")
feedback_add_details("admin_verb","mCRP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/intercom_view()
set category = "Mapping"
set name = "Intercom Range Display"
if(intercom_range_display_status)
intercom_range_display_status = 0
else
intercom_range_display_status = 1
for(var/obj/effect/debugging/marker/M in world)
del(M)
if(intercom_range_display_status)
for(var/obj/item/device/radio/intercom/I in world)
for(var/turf/T in orange(7,I))
var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
if (!(F in view(7,I.loc)))
del(F)
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/list/debug_verbs = list (
/client/proc/do_not_use_these
,/client/proc/camera_view
,/client/proc/sec_camera_report
,/client/proc/intercom_view
,/client/proc/air_status
,/client/proc/Cell
,/client/proc/atmosscan
,/client/proc/powerdebug
,/client/proc/count_objects_on_z_level
,/client/proc/count_objects_all
,/client/proc/cmd_assume_direct_control
,/client/proc/jump_to_dead_group
,/client/proc/startSinglo
,/client/proc/ticklag
,/client/proc/cmd_admin_grantfullaccess
,/client/proc/kaboom
,/client/proc/splash
,/client/proc/cmd_admin_areatest
,/client/proc/cmd_admin_rejuvenate
,/datum/admins/proc/show_traitor_panel
,/client/proc/print_jobban_old
,/client/proc/print_jobban_old_filter
,/client/proc/forceEvent
,/client/proc/break_all_air_groups
,/client/proc/regroup_all_air_groups
,/client/proc/kill_pipe_processing
,/client/proc/kill_air_processing
,/client/proc/disable_communication
,/client/proc/disable_movement
,/client/proc/Zone_Info
,/client/proc/Test_ZAS_Connection
,/client/proc/ZoneTick
,/client/proc/TestZASRebuild
,/client/proc/hide_debug_verbs
,/client/proc/testZAScolors
,/client/proc/testZAScolors_remove
)
/client/proc/enable_debug_verbs()
set category = "Debug"
set name = "Debug verbs"
if(!check_rights(R_DEBUG)) return
verbs += debug_verbs
feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/hide_debug_verbs()
set category = "Debug"
set name = "Hide Debug verbs"
if(!check_rights(R_DEBUG)) return
verbs -= debug_verbs
feedback_add_details("admin_verb","hDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/var/list/testZAScolors_turfs = list()
/client/var/list/testZAScolors_zones = list()
/client/var/usedZAScolors = 0
/client/var/list/image/ZAScolors = list()
/client/proc/recurse_zone(var/zone/Z, var/recurse_level =1)
testZAScolors_zones += Z
if(recurse_level > 10)
return
var/icon/yellow = new('icons/misc/debug_group.dmi', "yellow")
for(var/turf/T in Z.contents)
images += image(yellow, T, "zasdebug", TURF_LAYER)
testZAScolors_turfs += T
for(var/zone/connected in Z.connected_zones)
if(connected in testZAScolors_zones)
continue
recurse_zone(connected,recurse_level+1)
/client/proc/testZAScolors()
set category = "ZAS"
set name = "Check ZAS connections"
if(!check_rights(R_DEBUG)) return
testZAScolors_remove()
var/turf/location = get_turf(usr)
if(!istype(location, /turf/simulated)) // We're in space, let's not cause runtimes.
usr << "\red this debug tool cannot be used from space"
return
var/icon/red = new('icons/misc/debug_group.dmi', "red") //created here so we don't have to make thousands of these.
var/icon/green = new('icons/misc/debug_group.dmi', "green")
var/icon/blue = new('icons/misc/debug_group.dmi', "blue")
if(!usedZAScolors)
usr << "ZAS Test Colors"
usr << "Green = Zone you are standing in"
usr << "Blue = Connected zone to the zone you are standing in"
usr << "Yellow = A zone that is connected but not one adjacent to your connected zone"
usr << "Red = Not connected"
usedZAScolors = 1
testZAScolors_zones += location.zone
for(var/turf/T in location.zone.contents)
images += image(green, T,"zasdebug", TURF_LAYER)
testZAScolors_turfs += T
for(var/zone/Z in location.zone.connected_zones)
testZAScolors_zones += Z
for(var/turf/T in Z.contents)
images += image(blue, T,"zasdebug",TURF_LAYER)
testZAScolors_turfs += T
for(var/zone/connected in Z.connected_zones)
if(connected in testZAScolors_zones)
continue
recurse_zone(connected,1)
for(var/turf/T in range(25,location))
if(!istype(T))
continue
if(T in testZAScolors_turfs)
continue
images += image(red, T, "zasdebug", TURF_LAYER)
testZAScolors_turfs += T
/client/proc/testZAScolors_remove()
set category = "ZAS"
set name = "Remove ZAS connection colors"
testZAScolors_turfs.Cut()
testZAScolors_zones.Cut()
if(images.len)
for(var/image/i in images)
if(i.icon_state == "zasdebug")
images.Remove(i)
/client/proc/count_objects_on_z_level()
set category = "Mapping"
set name = "Count Objects On Level"
var/level = input("Which z-level?","Level?") as text
if(!level) return
var/num_level = text2num(level)
if(!num_level) return
if(!isnum(num_level)) return
var/type_text = input("Which type path?","Path?") as text
if(!type_text) return
var/type_path = text2path(type_text)
if(!type_path) return
var/count = 1
var/list/atom/atom_list = list()
for(var/atom/A in world)
if(istype(A,type_path))
var/atom/B = A
while(!(isturf(B.loc)))
if(B && B.loc)
B = B.loc
else
break
if(B)
if(B.z == num_level)
count++
atom_list += A
/*
var/atom/temp_atom
for(var/i = 0; i <= (atom_list.len/10); i++)
var/line = ""
for(var/j = 1; j <= 10; j++)
if(i*10+j <= atom_list.len)
temp_atom = atom_list[i*10+j]
line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; "
world << line*/
world << "There are [count] objects of type [type_path] on z-level [num_level]"
feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/count_objects_all()
set category = "Mapping"
set name = "Count Objects All"
var/type_text = input("Which type path?","") as text
if(!type_text) return
var/type_path = text2path(type_text)
if(!type_path) return
var/count = 0
for(var/atom/A in world)
if(istype(A,type_path))
count++
/*
var/atom/temp_atom
for(var/i = 0; i <= (atom_list.len/10); i++)
var/line = ""
for(var/j = 1; j <= 10; j++)
if(i*10+j <= atom_list.len)
temp_atom = atom_list[i*10+j]
line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; "
world << line*/
world << "There are [count] objects of type [type_path] in the game world"
feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/global/prevent_airgroup_regroup = 0
/client/proc/break_all_air_groups()
set category = "Mapping"
set name = "Break All Airgroups"
/*prevent_airgroup_regroup = 1
for(var/datum/air_group/AG in air_master.air_groups)
AG.suspend_group_processing()
message_admins("[src.ckey] used 'Break All Airgroups'")*/
/client/proc/regroup_all_air_groups()
set category = "Mapping"
set name = "Regroup All Airgroups Attempt"
usr << "\red Proc disabled."
/*prevent_airgroup_regroup = 0
for(var/datum/air_group/AG in air_master.air_groups)
AG.check_regroup()
message_admins("[src.ckey] used 'Regroup All Airgroups Attempt'")*/
/client/proc/kill_pipe_processing()
set category = "Mapping"
set name = "Kill pipe processing"
usr << "\red Proc disabled."
/*pipe_processing_killed = !pipe_processing_killed
if(pipe_processing_killed)
message_admins("[src.ckey] used 'kill pipe processing', stopping all pipe processing.")
else
message_admins("[src.ckey] used 'kill pipe processing', restoring all pipe processing.")*/
/client/proc/kill_air_processing()
set category = "Mapping"
set name = "Kill air processing"
usr << "\red Proc disabled."
/*air_processing_killed = !air_processing_killed
if(air_processing_killed)
message_admins("[src.ckey] used 'kill air processing', stopping all air processing.")
else
message_admins("[src.ckey] used 'kill air processing', restoring all air processing.")*/
//This proc is intended to detect lag problems relating to communication procs
var/global/say_disabled = 0
/client/proc/disable_communication()
set category = "Mapping"
set name = "Disable all communication verbs"
usr << "\red Proc disabled."
/*say_disabled = !say_disabled
if(say_disabled)
message_admins("[src.ckey] used 'Disable all communication verbs', killing all communication methods.")
else
message_admins("[src.ckey] used 'Disable all communication verbs', restoring all communication methods.")*/
//This proc is intended to detect lag problems relating to movement
var/global/movement_disabled = 0
var/global/movement_disabled_exception //This is the client that calls the proc, so he can continue to run around to gauge any change to lag.
/client/proc/disable_movement()
set category = "Mapping"
set name = "Disable all movement"
usr << "\red Proc disabled."
/*movement_disabled = !movement_disabled
if(movement_disabled)
message_admins("[src.ckey] used 'Disable all movement', killing all movement.")
movement_disabled_exception = usr.ckey
else
message_admins("[src.ckey] used 'Disable all movement', restoring all movement.")*/
+375
View File
@@ -0,0 +1,375 @@
/client/proc/cmd_mass_modify_object_variables(atom/A, var/var_name)
set category = "Debug"
set name = "Mass Edit Variables"
set desc="(target) Edit all instances of a target item's variables"
var/method = 0 //0 means strict type detection while 1 means this type and all subtypes (IE: /obj/item with this set to 1 will set it to ALL itms)
if(!check_rights(R_VAREDIT)) return
if(A && A.type)
if(typesof(A.type))
switch(input("Strict object type detection?") as null|anything in list("Strictly this type","This type and subtypes", "Cancel"))
if("Strictly this type")
method = 0
if("This type and subtypes")
method = 1
if("Cancel")
return
if(null)
return
src.massmodify_variables(A, var_name, method)
feedback_add_details("admin_verb","MEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/massmodify_variables(var/atom/O, var/var_name = "", var/method = 0)
if(!check_rights(R_VAREDIT)) return
var/list/locked = list("vars", "key", "ckey", "client")
for(var/p in forbidden_varedit_object_types)
if( istype(O,p) )
usr << "\red It is forbidden to edit this object's variables."
return
var/list/names = list()
for (var/V in O.vars)
names += V
names = sortList(names)
var/variable = ""
if(!var_name)
variable = input("Which var?","Var") as null|anything in names
else
variable = var_name
if(!variable) return
var/default
var/var_value = O.vars[variable]
var/dir
if(variable == "holder" || (variable in locked))
if(!check_rights(R_DEBUG)) return
if(isnull(var_value))
usr << "Unable to determine variable type."
else if(isnum(var_value))
usr << "Variable appears to be <b>NUM</b>."
default = "num"
dir = 1
else if(istext(var_value))
usr << "Variable appears to be <b>TEXT</b>."
default = "text"
else if(isloc(var_value))
usr << "Variable appears to be <b>REFERENCE</b>."
default = "reference"
else if(isicon(var_value))
usr << "Variable appears to be <b>ICON</b>."
var_value = "\icon[var_value]"
default = "icon"
else if(istype(var_value,/atom) || istype(var_value,/datum))
usr << "Variable appears to be <b>TYPE</b>."
default = "type"
else if(istype(var_value,/list))
usr << "Variable appears to be <b>LIST</b>."
default = "list"
else if(istype(var_value,/client))
usr << "Variable appears to be <b>CLIENT</b>."
default = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
default = "file"
usr << "Variable contains: [var_value]"
if(dir)
switch(var_value)
if(1)
dir = "NORTH"
if(2)
dir = "SOUTH"
if(4)
dir = "EAST"
if(8)
dir = "WEST"
if(5)
dir = "NORTHEAST"
if(6)
dir = "SOUTHEAST"
if(9)
dir = "NORTHWEST"
if(10)
dir = "SOUTHWEST"
else
dir = null
if(dir)
usr << "If a direction, direction is: [dir]"
var/class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
"num","type","icon","file","edit referenced object","restore to default")
if(!class)
return
var/original_name
if (!istype(O, /atom))
original_name = "\ref[O] ([O])"
else
original_name = O:name
switch(class)
if("restore to default")
O.vars[variable] = initial(O.vars[variable])
if(method)
if(istype(O, /mob))
for(var/mob/M in mob_list)
if ( istype(M , O.type) )
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if (M.type == O.type)
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
if("edit referenced object")
return .(O.vars[variable])
if("text")
var/new_value = input("Enter new text:","Text",O.vars[variable]) as text|null
if(new_value == null) return
O.vars[variable] = new_value
if(method)
if(istype(O, /mob))
for(var/mob/M in mob_list)
if ( istype(M , O.type) )
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if (M.type == O.type)
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
if("num")
var/new_value = input("Enter new number:","Num",\
O.vars[variable]) as num|null
if(new_value == null) return
if(variable=="luminosity")
O.SetLuminosity(new_value)
else
O.vars[variable] = new_value
if(method)
if(istype(O, /mob))
for(var/mob/M in mob_list)
if ( istype(M , O.type) )
if(variable=="luminosity")
M.SetLuminosity(new_value)
else
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if ( istype(A , O.type) )
if(variable=="luminosity")
A.SetLuminosity(new_value)
else
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if ( istype(A , O.type) )
if(variable=="luminosity")
A.SetLuminosity(new_value)
else
A.vars[variable] = O.vars[variable]
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if (M.type == O.type)
if(variable=="luminosity")
M.SetLuminosity(new_value)
else
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if (A.type == O.type)
if(variable=="luminosity")
A.SetLuminosity(new_value)
else
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if (A.type == O.type)
if(variable=="luminosity")
A.SetLuminosity(new_value)
else
A.vars[variable] = O.vars[variable]
if("type")
var/new_value
new_value = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf)
if(new_value == null) return
O.vars[variable] = new_value
if(method)
if(istype(O, /mob))
for(var/mob/M in mob_list)
if ( istype(M , O.type) )
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if (M.type == O.type)
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
if("file")
var/new_value = input("Pick file:","File",O.vars[variable]) as null|file
if(new_value == null) return
O.vars[variable] = new_value
if(method)
if(istype(O, /mob))
for(var/mob/M in mob_list)
if ( istype(M , O.type) )
M.vars[variable] = O.vars[variable]
else if(istype(O.type, /obj))
for(var/obj/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else if(istype(O.type, /turf))
for(var/turf/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if (M.type == O.type)
M.vars[variable] = O.vars[variable]
else if(istype(O.type, /obj))
for(var/obj/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
else if(istype(O.type, /turf))
for(var/turf/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
if("icon")
var/new_value = input("Pick icon:","Icon",O.vars[variable]) as null|icon
if(new_value == null) return
O.vars[variable] = new_value
if(method)
if(istype(O, /mob))
for(var/mob/M in mob_list)
if ( istype(M , O.type) )
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if ( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if (M.type == O.type)
M.vars[variable] = O.vars[variable]
else if(istype(O, /obj))
for(var/obj/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
else if(istype(O, /turf))
for(var/turf/A in world)
if (A.type == O.type)
A.vars[variable] = O.vars[variable]
log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]")
message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]", 1)
+501
View File
@@ -0,0 +1,501 @@
var/list/forbidden_varedit_object_types = list(
/datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea.
/obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering
/datum/feedback_variable //Prevents people messing with feedback gathering
)
/*
/client/proc/cmd_modify_object_variables(obj/O as obj|mob|turf|area in world)
set category = "Debug"
set name = "Edit Variables"
set desc="(target) Edit a target item's variables"
src.modify_variables(O)
feedback_add_details("admin_verb","EDITV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
*/
/client/proc/cmd_modify_ticker_variables()
set category = "Debug"
set name = "Edit Ticker Variables"
if (ticker == null)
src << "Game hasn't started yet."
else
src.modify_variables(ticker)
feedback_add_details("admin_verb","ETV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/mod_list_add_ass() //haha
var/class = "text"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
else
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
if(!class)
return
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
class = "marked datum"
var/var_value = null
switch(class)
if("text")
var_value = input("Enter new text:","Text") as null|text
if("num")
var_value = input("Enter new number:","Num") as null|num
if("type")
var_value = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf)
if("reference")
var_value = input("Select reference:","Reference") as null|mob|obj|turf|area in world
if("mob reference")
var_value = input("Select reference:","Reference") as null|mob in world
if("file")
var_value = input("Pick file:","File") as null|file
if("icon")
var_value = input("Pick icon:","Icon") as null|icon
if("marked datum")
var_value = holder.marked_datum
if(!var_value) return
return var_value
/client/proc/mod_list_add(var/list/L)
var/class = "text"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
else
class = input("What kind of variable?","Variable Type") as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
if(!class)
return
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
class = "marked datum"
var/var_value = null
switch(class)
if("text")
var_value = input("Enter new text:","Text") as text
if("num")
var_value = input("Enter new number:","Num") as num
if("type")
var_value = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf)
if("reference")
var_value = input("Select reference:","Reference") as mob|obj|turf|area in world
if("mob reference")
var_value = input("Select reference:","Reference") as mob in world
if("file")
var_value = input("Pick file:","File") as file
if("icon")
var_value = input("Pick icon:","Icon") as icon
if("marked datum")
var_value = holder.marked_datum
if(!var_value) return
switch(alert("Would you like to associate a var with the list entry?",,"Yes","No"))
if("Yes")
L += var_value
L[var_value] = mod_list_add_ass() //haha
if("No")
L += var_value
/client/proc/mod_list(var/list/L)
if(!check_rights(R_VAREDIT)) return
if(!istype(L,/list)) src << "Not a List."
var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine", "poo", "icon", "icon_state")
var/list/names = sortList(L)
var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)"
if(variable == "(ADD VAR)")
mod_list_add(L)
return
if(!variable)
return
var/default
var/dir
if(variable in locked)
if(!check_rights(R_DEBUG)) return
if(isnull(variable))
usr << "Unable to determine variable type."
else if(isnum(variable))
usr << "Variable appears to be <b>NUM</b>."
default = "num"
dir = 1
else if(istext(variable))
usr << "Variable appears to be <b>TEXT</b>."
default = "text"
else if(isloc(variable))
usr << "Variable appears to be <b>REFERENCE</b>."
default = "reference"
else if(isicon(variable))
usr << "Variable appears to be <b>ICON</b>."
variable = "\icon[variable]"
default = "icon"
else if(istype(variable,/atom) || istype(variable,/datum))
usr << "Variable appears to be <b>TYPE</b>."
default = "type"
else if(istype(variable,/list))
usr << "Variable appears to be <b>LIST</b>."
default = "list"
else if(istype(variable,/client))
usr << "Variable appears to be <b>CLIENT</b>."
default = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
default = "file"
usr << "Variable contains: [variable]"
if(dir)
switch(variable)
if(1)
dir = "NORTH"
if(2)
dir = "SOUTH"
if(4)
dir = "EAST"
if(8)
dir = "WEST"
if(5)
dir = "NORTHEAST"
if(6)
dir = "SOUTHEAST"
if(9)
dir = "NORTHWEST"
if(10)
dir = "SOUTHWEST"
else
dir = null
if(dir)
usr << "If a direction, direction is: [dir]"
var/class = "text"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST")
else
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "DELETE FROM LIST")
if(!class)
return
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
class = "marked datum"
switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet.
if("list")
mod_list(variable)
if("restore to default")
L[L.Find(variable)]=initial(variable)
if("edit referenced object")
modify_variables(variable)
if("DELETE FROM LIST")
L -= variable
return
if("text")
L[L.Find(variable)] = input("Enter new text:","Text") as text
if("num")
L[L.Find(variable)] = input("Enter new number:","Num") as num
if("type")
L[L.Find(variable)] = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf)
if("reference")
L[L.Find(variable)] = input("Select reference:","Reference") as mob|obj|turf|area in world
if("mob reference")
L[L.Find(variable)] = input("Select reference:","Reference") as mob in world
if("file")
L[L.Find(variable)] = input("Pick file:","File") as file
if("icon")
L[L.Find(variable)] = input("Pick icon:","Icon") as icon
if("marked datum")
L[L.Find(variable)] = holder.marked_datum
/client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
if(!check_rights(R_VAREDIT)) return
var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "cuffed", "ka", "last_eaten", "icon", "icon_state", "mutantrace")
for(var/p in forbidden_varedit_object_types)
if( istype(O,p) )
usr << "\red It is forbidden to edit this object's variables."
return
var/class
var/variable
var/var_value
if(param_var_name)
if(!param_var_name in O.vars)
src << "A variable with this name ([param_var_name]) doesn't exist in this atom ([O])"
return
if(param_var_name == "holder" || (param_var_name in locked))
if(!check_rights(R_DEBUG)) return
variable = param_var_name
var_value = O.vars[variable]
if(autodetect_class)
if(isnull(var_value))
usr << "Unable to determine variable type."
class = null
autodetect_class = null
else if(isnum(var_value))
usr << "Variable appears to be <b>NUM</b>."
class = "num"
dir = 1
else if(istext(var_value))
usr << "Variable appears to be <b>TEXT</b>."
class = "text"
else if(isloc(var_value))
usr << "Variable appears to be <b>REFERENCE</b>."
class = "reference"
else if(isicon(var_value))
usr << "Variable appears to be <b>ICON</b>."
var_value = "\icon[var_value]"
class = "icon"
else if(istype(var_value,/atom) || istype(var_value,/datum))
usr << "Variable appears to be <b>TYPE</b>."
class = "type"
else if(istype(var_value,/list))
usr << "Variable appears to be <b>LIST</b>."
class = "list"
else if(istype(var_value,/client))
usr << "Variable appears to be <b>CLIENT</b>."
class = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
class = "file"
else
var/list/names = list()
for (var/V in O.vars)
names += V
names = sortList(names)
variable = input("Which var?","Var") as null|anything in names
if(!variable) return
var_value = O.vars[variable]
if(variable == "holder" || (variable in locked))
if(!check_rights(R_DEBUG)) return
if(!autodetect_class)
var/dir
var/default
if(isnull(var_value))
usr << "Unable to determine variable type."
else if(isnum(var_value))
usr << "Variable appears to be <b>NUM</b>."
default = "num"
dir = 1
else if(istext(var_value))
usr << "Variable appears to be <b>TEXT</b>."
default = "text"
else if(isloc(var_value))
usr << "Variable appears to be <b>REFERENCE</b>."
default = "reference"
else if(isicon(var_value))
usr << "Variable appears to be <b>ICON</b>."
var_value = "\icon[var_value]"
default = "icon"
else if(istype(var_value,/atom) || istype(var_value,/datum))
usr << "Variable appears to be <b>TYPE</b>."
default = "type"
else if(istype(var_value,/list))
usr << "Variable appears to be <b>LIST</b>."
default = "list"
else if(istype(var_value,/client))
usr << "Variable appears to be <b>CLIENT</b>."
default = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
default = "file"
usr << "Variable contains: [var_value]"
if(dir)
switch(var_value)
if(1)
dir = "NORTH"
if(2)
dir = "SOUTH"
if(4)
dir = "EAST"
if(8)
dir = "WEST"
if(5)
dir = "NORTHEAST"
if(6)
dir = "SOUTHEAST"
if(9)
dir = "NORTHWEST"
if(10)
dir = "SOUTHWEST"
else
dir = null
if(dir)
usr << "If a direction, direction is: [dir]"
if(src.holder && src.holder.marked_datum)
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])")
else
class = input("What kind of variable?","Variable Type",default) as null|anything in list("text",
"num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
if(!class)
return
var/original_name
if (!istype(O, /atom))
original_name = "\ref[O] ([O])"
else
original_name = O:name
if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])")
class = "marked datum"
switch(class)
if("list")
mod_list(O.vars[variable])
return
if("restore to default")
O.vars[variable] = initial(O.vars[variable])
if("edit referenced object")
return .(O.vars[variable])
if("text")
var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|text
if(var_new==null) return
O.vars[variable] = var_new
if("num")
if(variable=="luminosity")
var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num
if(var_new == null) return
O.SetLuminosity(var_new)
else if(variable=="stat")
var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num
if(var_new == null) return
if((O.vars[variable] == 2) && (var_new < 2))//Bringing the dead back to life
dead_mob_list -= O
living_mob_list += O
if((O.vars[variable] < 2) && (var_new == 2))//Kill he
living_mob_list -= O
dead_mob_list += O
O.vars[variable] = var_new
else
var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num
if(var_new==null) return
O.vars[variable] = var_new
if("type")
var/var_new = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf)
if(var_new==null) return
O.vars[variable] = var_new
if("reference")
var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob|obj|turf|area in world
if(var_new==null) return
O.vars[variable] = var_new
if("mob reference")
var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob in world
if(var_new==null) return
O.vars[variable] = var_new
if("file")
var/var_new = input("Pick file:","File",O.vars[variable]) as null|file
if(var_new==null) return
O.vars[variable] = var_new
if("icon")
var/var_new = input("Pick icon:","Icon",O.vars[variable]) as null|icon
if(var_new==null) return
O.vars[variable] = var_new
if("marked datum")
O.vars[variable] = holder.marked_datum
world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]"
log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]")
message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]", 1)
+525
View File
@@ -0,0 +1,525 @@
client/proc/one_click_antag()
set name = "Create Antagonist"
set desc = "Auto-create an antagonist of your choice"
set category = "Admin"
if(holder)
holder.one_click_antag()
return
/datum/admins/proc/one_click_antag()
var/dat = {"<B>One-click Antagonist</B><br>
<a href='?src=\ref[src];makeAntag=1'>Make Traitors</a><br>
<a href='?src=\ref[src];makeAntag=2'>Make Changlings</a><br>
<a href='?src=\ref[src];makeAntag=3'>Make Revs</a><br>
<a href='?src=\ref[src];makeAntag=4'>Make Cult</a><br>
<a href='?src=\ref[src];makeAntag=5'>Make Malf AI</a><br>
<a href='?src=\ref[src];makeAntag=6'>Make Wizard (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=11'>Make Vox Raiders (Requires Ghosts)</a><br>
"}
/* These dont work just yet
Ninja, aliens and deathsquad I have not looked into yet
Nuke team is getting a null mob returned from makebody() (runtime error: null.mind. Line 272)
<a href='?src=\ref[src];makeAntag=7'>Make Nuke Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=8'>Make Space Ninja (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=9'>Make Aliens (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=10'>Make Deathsquad (Syndicate) (Requires Ghosts)</a><br>
"}
*/
usr << browse(dat, "window=oneclickantag;size=400x400")
return
/datum/admins/proc/makeMalfAImode()
var/list/mob/living/silicon/AIs = list()
var/mob/living/silicon/malfAI = null
var/datum/mind/themind = null
for(var/mob/living/silicon/ai/ai in player_list)
if(ai.client)
AIs += ai
if(AIs.len)
malfAI = pick(AIs)
if(malfAI)
themind = malfAI.mind
themind.make_AI_Malf()
return 1
return 0
/datum/admins/proc/makeTraitors()
var/datum/game_mode/traitor/temp = new
if(config.protect_roles_from_antagonist)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
var/mob/living/carbon/human/H = null
for(var/mob/living/carbon/human/applicant in player_list)
if(applicant.client.prefs.be_special & BE_TRAITOR)
if(!applicant.stat)
if(applicant.mind)
if (!applicant.mind.special_role)
if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate"))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
if(candidates.len)
var/numTratiors = min(candidates.len, 3)
for(var/i = 0, i<numTratiors, i++)
H = pick(candidates)
H.mind.make_Tratior()
candidates.Remove(H)
return 1
return 0
/datum/admins/proc/makeChanglings()
var/datum/game_mode/changeling/temp = new
if(config.protect_roles_from_antagonist)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
var/mob/living/carbon/human/H = null
for(var/mob/living/carbon/human/applicant in player_list)
if(applicant.client.prefs.be_special & BE_CHANGELING)
if(!applicant.stat)
if(applicant.mind)
if (!applicant.mind.special_role)
if(!jobban_isbanned(applicant, "changeling") && !jobban_isbanned(applicant, "Syndicate"))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
if(candidates.len)
var/numChanglings = min(candidates.len, 3)
for(var/i = 0, i<numChanglings, i++)
H = pick(candidates)
H.mind.make_Changling()
candidates.Remove(H)
return 1
return 0
/datum/admins/proc/makeRevs()
var/datum/game_mode/revolution/temp = new
if(config.protect_roles_from_antagonist)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
var/mob/living/carbon/human/H = null
for(var/mob/living/carbon/human/applicant in player_list)
if(applicant.client.prefs.be_special & BE_REV)
if(applicant.stat == CONSCIOUS)
if(applicant.mind)
if(!applicant.mind.special_role)
if(!jobban_isbanned(applicant, "revolutionary") && !jobban_isbanned(applicant, "Syndicate"))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
if(candidates.len)
var/numRevs = min(candidates.len, 3)
for(var/i = 0, i<numRevs, i++)
H = pick(candidates)
H.mind.make_Rev()
candidates.Remove(H)
return 1
return 0
/datum/admins/proc/makeWizard()
var/list/mob/dead/observer/candidates = list()
var/mob/dead/observer/theghost = null
var/time_passed = world.time
for(var/mob/dead/observer/G in player_list)
if(!jobban_isbanned(G, "wizard") && !jobban_isbanned(G, "Syndicate"))
spawn(0)
switch(alert(G, "Do you wish to be considered for the position of Space Wizard Foundation 'diplomat'?","Please answer in 30 seconds!","Yes","No"))
if("Yes")
if((world.time-time_passed)>300)//If more than 30 game seconds passed.
return
candidates += G
if("No")
return
else
return
sleep(300)
if(candidates.len)
shuffle(candidates)
for(var/mob/i in candidates)
if(!i || !i.client) continue //Dont bother removing them from the list since we only grab one wizard
theghost = i
break
if(theghost)
var/mob/living/carbon/human/new_character=makeBody(theghost)
new_character.mind.make_Wizard()
return 1
return 0
/datum/admins/proc/makeCult()
var/datum/game_mode/cult/temp = new
if(config.protect_roles_from_antagonist)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
var/mob/living/carbon/human/H = null
for(var/mob/living/carbon/human/applicant in player_list)
if(applicant.client.prefs.be_special & BE_CULTIST)
if(applicant.stat == CONSCIOUS)
if(applicant.mind)
if(!applicant.mind.special_role)
if(!jobban_isbanned(applicant, "cultist") && !jobban_isbanned(applicant, "Syndicate"))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
if(candidates.len)
var/numCultists = min(candidates.len, 4)
for(var/i = 0, i<numCultists, i++)
H = pick(candidates)
H.mind.make_Cultist()
candidates.Remove(H)
temp.grant_runeword(H)
return 1
return 0
/datum/admins/proc/makeNukeTeam()
var/list/mob/dead/observer/candidates = list()
var/mob/dead/observer/theghost = null
var/time_passed = world.time
for(var/mob/dead/observer/G in player_list)
if(!jobban_isbanned(G, "operative") && !jobban_isbanned(G, "Syndicate"))
spawn(0)
switch(alert(G,"Do you wish to be considered for a nuke team being sent in?","Please answer in 30 seconds!","Yes","No"))
if("Yes")
if((world.time-time_passed)>300)//If more than 30 game seconds passed.
return
candidates += G
if("No")
return
else
return
sleep(300)
if(candidates.len)
var/numagents = 5
var/agentcount = 0
for(var/i = 0, i<numagents,i++)
shuffle(candidates) //More shuffles means more randoms
for(var/mob/j in candidates)
if(!j || !j.client)
candidates.Remove(j)
continue
theghost = candidates
candidates.Remove(theghost)
var/mob/living/carbon/human/new_character=makeBody(theghost)
new_character.mind.make_Nuke()
agentcount++
if(agentcount < 1)
return 0
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
var/obj/effect/landmark/closet_spawn = locate("landmark*Nuclear-Closet")
var/nuke_code = "[rand(10000, 99999)]"
if(nuke_spawn)
var/obj/item/weapon/paper/P = new
P.info = "Sadly, the Syndicate could not get you a nuclear bomb. We have, however, acquired the arming code for the station's onboard nuke. The nuclear authorization code is: <b>[nuke_code]</b>"
P.name = "nuclear bomb code and instructions"
P.loc = nuke_spawn.loc
if(closet_spawn)
new /obj/structure/closet/syndicate/nuclear(closet_spawn.loc)
for (var/obj/effect/landmark/A in /area/syndicate_station/start)//Because that's the only place it can BE -Sieve
if (A.name == "Syndicate-Gear-Closet")
new /obj/structure/closet/syndicate/personal(A.loc)
del(A)
continue
if (A.name == "Syndicate-Bomb")
new /obj/effect/spawner/newbomb/timer/syndicate(A.loc)
del(A)
continue
for(var/datum/mind/synd_mind in ticker.mode.syndicates)
if(synd_mind.current)
if(synd_mind.current.client)
for(var/image/I in synd_mind.current.client.images)
if(I.icon_state == "synd")
del(I)
for(var/datum/mind/synd_mind in ticker.mode.syndicates)
if(synd_mind.current)
if(synd_mind.current.client)
for(var/datum/mind/synd_mind_1 in ticker.mode.syndicates)
if(synd_mind_1.current)
var/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd")
synd_mind.current.client.images += I
for (var/obj/machinery/nuclearbomb/bomb in world)
bomb.r_code = nuke_code // All the nukes are set to this code.
return 1
/datum/admins/proc/makeAliens()
alien_infestation(3)
return 1
/datum/admins/proc/makeSpaceNinja()
space_ninja_arrival()
return 1
/datum/admins/proc/makeDeathsquad()
var/list/mob/dead/observer/candidates = list()
var/mob/dead/observer/theghost = null
var/time_passed = world.time
var/input = "Purify the station."
if(prob(10))
input = "Save Runtime and any other cute things on the station."
var/syndicate_leader_selected = 0 //when the leader is chosen. The last person spawned.
//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos.
for(var/mob/dead/observer/G in player_list)
spawn(0)
switch(alert(G,"Do you wish to be considered for an elite syndicate strike team being sent in?","Please answer in 30 seconds!","Yes","No"))
if("Yes")
if((world.time-time_passed)>300)//If more than 30 game seconds passed.
return
candidates += G
if("No")
return
else
return
sleep(300)
for(var/mob/dead/observer/G in candidates)
if(!G.key)
candidates.Remove(G)
if(candidates.len)
var/numagents = 6
//Spawns commandos and equips them.
for (var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad)
if(numagents<=0)
break
if (L.name == "Syndicate-Commando")
syndicate_leader_selected = numagents == 1?1:0
var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected)
while((!theghost || !theghost.client) && candidates.len)
theghost = pick(candidates)
candidates.Remove(theghost)
if(!theghost)
del(new_syndicate_commando)
break
new_syndicate_commando.key = theghost.key
new_syndicate_commando.internal = new_syndicate_commando.s_store
new_syndicate_commando.internals.icon_state = "internal1"
//So they don't forget their code or mission.
new_syndicate_commando << "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"<B>LEADER</B>"] in the service of the Syndicate. \nYour current mission is: \red<B> [input]</B>"
numagents--
if(numagents >= 6)
return 0
for (var/obj/effect/landmark/L in /area/shuttle/syndicate_elite)
if (L.name == "Syndicate-Commando-Bomb")
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
return 1
/datum/admins/proc/makeBody(var/mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character
if(!G_found || !G_found.key) return
//First we spawn a dude.
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
A.randomize_appearance_for(new_character)
if(new_character.gender == MALE)
new_character.real_name = "[pick(first_names_male)] [pick(last_names)]"
else
new_character.real_name = "[pick(first_names_female)] [pick(last_names)]"
new_character.name = new_character.real_name
new_character.age = rand(17,45)
new_character.dna.ready_dna(new_character)
new_character.key = G_found.key
return new_character
/datum/admins/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0)
var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc)
var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major")
var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/syndicate_commando_name = pick(last_names)
new_syndicate_commando.gender = pick(MALE, FEMALE)
var/datum/preferences/A = new()//Randomize appearance for the commando.
A.randomize_appearance_for(new_syndicate_commando)
new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]"
new_syndicate_commando.name = new_syndicate_commando.real_name
new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45)
new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA.
//Creates mind stuff.
new_syndicate_commando.mind_initialize()
new_syndicate_commando.mind.assigned_role = "MODE"
new_syndicate_commando.mind.special_role = "Syndicate Commando"
//Adds them to current traitor list. Which is really the extra antagonist list.
ticker.mode.traitors += new_syndicate_commando.mind
new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected)
return new_syndicate_commando
/datum/admins/proc/makeVoxRaiders()
var/list/mob/dead/observer/candidates = list()
var/mob/dead/observer/theghost = null
var/time_passed = world.time
var/input = "Disregard shinies, acquire hardware."
var/leader_chosen = 0 //when the leader is chosen. The last person spawned.
//Generates a list of candidates from active ghosts.
for(var/mob/dead/observer/G in player_list)
spawn(0)
switch(alert(G,"Do you wish to be considered for a vox raiding party arriving on the station?","Please answer in 30 seconds!","Yes","No"))
if("Yes")
if((world.time-time_passed)>300)//If more than 30 game seconds passed.
return
candidates += G
if("No")
return
else
return
sleep(300) //Debug.
for(var/mob/dead/observer/G in candidates)
if(!G.key)
candidates.Remove(G)
if(candidates.len)
var/max_raiders = 1
var/raiders = max_raiders
//Spawns vox raiders and equips them.
for (var/obj/effect/landmark/L in world)
if(L.name == "voxstart")
if(raiders<=0)
break
var/mob/living/carbon/human/new_vox = create_vox_raider(L, leader_chosen)
while((!theghost || !theghost.client) && candidates.len)
theghost = pick(candidates)
candidates.Remove(theghost)
if(!theghost)
del(new_vox)
break
new_vox.key = theghost.key
new_vox << "\blue You are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at the Tau Ceti system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, but everyong is raring to start pillaging! Your current goal is: \red<B> [input]</B>"
new_vox << "\red Don't forget to turn on your nitrogen internals!"
raiders--
if(raiders > max_raiders)
return 0
else
return 0
return 1
/datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0)
var/mob/living/carbon/human/new_vox = new(spawn_location.loc)
new_vox.gender = pick(MALE, FEMALE)
new_vox.h_style = "Short Vox Quills"
new_vox.regenerate_icons()
var/sounds = rand(2,10)
var/i = 0
var/newname = ""
while(i<=sounds)
i++
newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah"))
new_vox.real_name = capitalize(newname)
new_vox.name = new_vox.real_name
new_vox.age = rand(12,20)
new_vox.dna.ready_dna(new_vox) // Creates DNA.
new_vox.dna.mutantrace = "vox"
new_vox.set_species("Vox") // Actually makes the vox! How about that.
new_vox.add_language("Vox-pidgin")
new_vox.mind_initialize()
new_vox.mind.assigned_role = "MODE"
new_vox.mind.special_role = "Vox Raider"
new_vox.mutations |= NOCLONE //Stops the station crew from messing around with their DNA.
ticker.mode.traitors += new_vox.mind
new_vox.equip_vox_raider()
return new_vox
+50
View File
@@ -0,0 +1,50 @@
/client/proc/only_one()
if(!ticker)
alert("The game hasn't started yet!")
return
for(var/mob/living/carbon/human/H in player_list)
if(H.stat == 2 || !(H.client)) continue
if(is_special_character(H)) continue
ticker.mode.traitors += H.mind
H.mind.special_role = "traitor"
var/datum/objective/steal/steal_objective = new
steal_objective.owner = H.mind
steal_objective.set_target("nuclear authentication disk")
H.mind.objectives += steal_objective
var/datum/objective/hijack/hijack_objective = new
hijack_objective.owner = H.mind
H.mind.objectives += hijack_objective
H << "<B>You are the traitor.</B>"
var/obj_count = 1
for(var/datum/objective/OBJ in H.mind.objectives)
H << "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]"
obj_count++
for (var/obj/item/I in H)
if (istype(I, /obj/item/weapon/implant))
continue
del(I)
H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_l_ear)
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/weapon/claymore(H), slot_l_hand)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(H.loc), slot_l_store)
var/obj/item/weapon/card/id/W = new(H)
W.name = "[H.real_name]'s ID Card"
W.icon_state = "centcom"
W.access = get_all_accesses()
W.access += get_all_centcom_access()
W.assignment = "Highlander"
W.registered_name = H.real_name
H.equip_to_slot_or_del(W, slot_wear_id)
message_admins("\blue [key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1)
log_admin("[key_name(usr)] used there can be only one.")
+76
View File
@@ -0,0 +1,76 @@
/client/proc/play_sound(S as sound)
set category = "Fun"
set name = "Play Global Sound"
if(!check_rights(R_SOUNDS)) return
var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = 777)
uploaded_sound.priority = 250
log_admin("[key_name(src)] played sound [S]")
message_admins("[key_name_admin(src)] played sound [S]", 1)
for(var/mob/M in player_list)
if(M.client.prefs.toggles & SOUND_MIDI)
M << uploaded_sound
feedback_add_details("admin_verb","PGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/play_local_sound(S as sound)
set category = "Fun"
set name = "Play Local Sound"
if(!check_rights(R_SOUNDS)) return
log_admin("[key_name(src)] played a local sound [S]")
message_admins("[key_name_admin(src)] played a local sound [S]", 1)
playsound(get_turf_loc(src.mob), S, 50, 0, 0)
feedback_add_details("admin_verb","PLS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/*
/client/proc/cuban_pete()
set category = "Fun"
set name = "Cuban Pete Time"
message_admins("[key_name_admin(usr)] has declared Cuban Pete Time!", 1)
for(var/mob/M in world)
if(M.client)
if(M.client.midis)
M << 'cubanpetetime.ogg'
for(var/mob/living/carbon/human/CP in world)
if(CP.real_name=="Cuban Pete" && CP.key!="Rosham")
CP << "Your body can't contain the rhumba beat"
CP.gib()
/client/proc/bananaphone()
set category = "Fun"
set name = "Banana Phone"
message_admins("[key_name_admin(usr)] has activated Banana Phone!", 1)
for(var/mob/M in world)
if(M.client)
if(M.client.midis)
M << 'bananaphone.ogg'
client/proc/space_asshole()
set category = "Fun"
set name = "Space Asshole"
message_admins("[key_name_admin(usr)] has played the Space Asshole Hymn.", 1)
for(var/mob/M in world)
if(M.client)
if(M.client.midis)
M << 'sound/music/space_asshole.ogg'
client/proc/honk_theme()
set category = "Fun"
set name = "Honk"
message_admins("[key_name_admin(usr)] has creeped everyone out with Blackest Honks.", 1)
for(var/mob/M in world)
if(M.client)
if(M.client.midis)
M << 'honk_theme.ogg'*/
+53
View File
@@ -0,0 +1,53 @@
/proc/possess(obj/O as obj in world)
set name = "Possess Obj"
set category = "Object"
if(istype(O,/obj/machinery/singularity))
if(config.forbid_singulo_possession)
usr << "It is forbidden to possess singularities."
return
var/turf/T = get_turf(O)
if(T)
log_admin("[key_name(usr)] has possessed [O] ([O.type]) at ([T.x], [T.y], [T.z])")
message_admins("[key_name(usr)] has possessed [O] ([O.type]) at ([T.x], [T.y], [T.z])", 1)
else
log_admin("[key_name(usr)] has possessed [O] ([O.type]) at an unknown location")
message_admins("[key_name(usr)] has possessed [O] ([O.type]) at an unknown location", 1)
if(!usr.control_object) //If you're not already possessing something...
usr.name_archive = usr.real_name
usr.loc = O
usr.real_name = O.name
usr.name = O.name
usr.client.eye = O
usr.control_object = O
feedback_add_details("admin_verb","PO") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/proc/release(obj/O as obj in world)
set name = "Release Obj"
set category = "Object"
//usr.loc = get_turf(usr)
if(usr.control_object && usr.name_archive) //if you have a name archived and if you are actually relassing an object
usr.real_name = usr.name_archive
usr.name = usr.real_name
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
H.name = H.get_visible_name()
// usr.regenerate_icons() //So the name is updated properly
usr.loc = O.loc // Appear where the object you were controlling is -- TLE
usr.client.eye = usr
usr.control_object = null
feedback_add_details("admin_verb","RO") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/proc/givetestverbs(mob/M as mob in mob_list)
set desc = "Give this guy possess/release verbs"
set category = "Debug"
set name = "Give Possessing Verbs"
M.verbs += /proc/possess
M.verbs += /proc/release
feedback_add_details("admin_verb","GPV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+38
View File
@@ -0,0 +1,38 @@
/mob/verb/pray(msg as text)
set category = "IC"
set name = "Pray"
if(say_disabled) //This is here to try to identify lag problems
usr << "\red Speech is currently admin-disabled."
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
if(!msg) return
if(usr.client)
if(usr.client.prefs.muted & MUTE_PRAY)
usr << "\red You cannot pray (muted)."
return
if(src.client.handle_spam_prevention(msg,MUTE_PRAY))
return
var/image/cross = image('icons/obj/storage.dmi',"bible")
msg = "\blue \icon[cross] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[src]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[src]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>):</b> [msg]"
for(var/client/C in admins)
if(C.prefs.toggles & CHAT_PRAYER)
C << msg
usr << "Your prayers have been received by the gods."
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//log_admin("HELP: [key_name(src)]: [msg]")
/proc/Centcomm_announce(var/text , var/mob/Sender , var/iamessage)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "\blue <b><font color=orange>CENTCOMM[iamessage ? " IA" : ""]:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;CentcommReply=\ref[Sender]'>RPLY</A>):</b> [msg]"
admins << msg
/proc/Syndicate_announce(var/text , var/mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "\blue <b><font color=crimson>SYNDICATE:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;SyndicateReply=\ref[Sender]'>RPLY</A>):</b> [msg]"
admins << msg
+964
View File
@@ -0,0 +1,964 @@
/client/proc/cmd_admin_drop_everything(mob/M as mob in mob_list)
set category = null
set name = "Drop Everything"
if(!holder)
src << "Only administrators may use this command."
return
var/confirm = alert(src, "Make [M] drop everything?", "Message", "Yes", "No")
if(confirm != "Yes")
return
for(var/obj/item/W in M)
M.drop_from_inventory(W)
log_admin("[key_name(usr)] made [key_name(M)] drop everything!")
message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!", 1)
feedback_add_details("admin_verb","DEVR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_prison(mob/M as mob in mob_list)
set category = "Admin"
set name = "Prison"
if(!holder)
src << "Only administrators may use this command."
return
if (ismob(M))
if(istype(M, /mob/living/silicon/ai))
alert("The AI can't be sent to prison you jerk!", null, null, null, null, null)
return
//strip their stuff before they teleport into a cell :downs:
for(var/obj/item/W in M)
M.drop_from_inventory(W)
//teleport person to cell
M.Paralyse(5)
sleep(5) //so they black out before warping
M.loc = pick(prisonwarp)
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/prisoner = M
prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(prisoner), slot_w_uniform)
prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes)
spawn(50)
M << "\red You have been sent to the prison station!"
log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.")
message_admins("\blue [key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1)
feedback_add_details("admin_verb","PRISON") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_subtle_message(mob/M as mob in mob_list)
set category = "Special Verbs"
set name = "Subtle Message"
if(!ismob(M)) return
if (!holder)
src << "Only administrators may use this command."
return
var/msg = input("Message:", text("Subtle PM to [M.key]")) as text
if (!msg)
return
if(usr)
if (usr.client)
if(usr.client.holder)
M << "\bold You hear a voice in your head... \italic [msg]"
log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]")
message_admins("\blue \bold SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]", 1)
feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE
set category = "Special Verbs"
set name = "Global Narrate"
if (!holder)
src << "Only administrators may use this command."
return
var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text
if (!msg)
return
world << "[msg]"
log_admin("GlobalNarrate: [key_name(usr)] : [msg]")
message_admins("\blue \bold GlobalNarrate: [key_name_admin(usr)] : [msg]<BR>", 1)
feedback_add_details("admin_verb","GLN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_direct_narrate(var/mob/M) // Targetted narrate -- TLE
set category = "Special Verbs"
set name = "Direct Narrate"
if(!holder)
src << "Only administrators may use this command."
return
if(!M)
M = input("Direct narrate to who?", "Active Players") as null|anything in get_mob_with_client_list()
if(!M)
return
var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text
if( !msg )
return
M << msg
log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]")
message_admins("\blue \bold DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]<BR>", 1)
feedback_add_details("admin_verb","DIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_godmode(mob/M as mob in mob_list)
set category = "Special Verbs"
set name = "Godmode"
if(!holder)
src << "Only administrators may use this command."
return
M.status_flags ^= GODMODE
usr << "\blue Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]"
log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]")
message_admins("[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]", 1)
feedback_add_details("admin_verb","GOD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
if(automute)
if(!config.automute_on) return
else
if(!usr || !usr.client)
return
if(!usr.client.holder)
usr << "<font color='red'>Error: cmd_admin_mute: You don't have permission to do this.</font>"
return
if(!M.client)
usr << "<font color='red'>Error: cmd_admin_mute: This mob doesn't have a client tied to it.</font>"
if(M.client.holder)
usr << "<font color='red'>Error: cmd_admin_mute: You cannot mute an admin/mod.</font>"
if(!M.client) return
if(M.client.holder) return
var/muteunmute
var/mute_string
switch(mute_type)
if(MUTE_IC) mute_string = "IC (say and emote)"
if(MUTE_OOC) mute_string = "OOC"
if(MUTE_PRAY) mute_string = "pray"
if(MUTE_ADMINHELP) mute_string = "adminhelp, admin PM and ASAY"
if(MUTE_DEADCHAT) mute_string = "deadchat and DSAY"
if(MUTE_ALL) mute_string = "everything"
else return
if(automute)
muteunmute = "auto-muted"
M.client.prefs.muted |= mute_type
log_admin("SPAM AUTOMUTE: [muteunmute] [key_name(M)] from [mute_string]")
message_admins("SPAM AUTOMUTE: [muteunmute] [key_name_admin(M)] from [mute_string].", 1)
M << "You have been [muteunmute] from [mute_string] by the SPAM AUTOMUTE system. Contact an admin."
feedback_add_details("admin_verb","AUTOMUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
if(M.client.prefs.muted & mute_type)
muteunmute = "unmuted"
M.client.prefs.muted &= ~mute_type
else
muteunmute = "muted"
M.client.prefs.muted |= mute_type
log_admin("[key_name(usr)] has [muteunmute] [key_name(M)] from [mute_string]")
message_admins("[key_name_admin(usr)] has [muteunmute] [key_name_admin(M)] from [mute_string].", 1)
M << "You have been [muteunmute] from [mute_string]."
feedback_add_details("admin_verb","MUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_add_random_ai_law()
set category = "Fun"
set name = "Add Random AI Law"
if(!holder)
src << "Only administrators may use this command."
return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
log_admin("[key_name(src)] has added a random AI law.")
message_admins("[key_name_admin(src)] has added a random AI law.", 1)
var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No")
if(show_log == "Yes")
command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert")
world << sound('sound/AI/ionstorm.ogg')
IonStorm(0)
feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//I use this proc for respawn character too. /N
/proc/create_xeno(ckey)
if(!ckey)
var/list/candidates = list()
for(var/mob/M in player_list)
if(M.stat != DEAD) continue //we are not dead!
if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium
if(M.client.is_afk()) continue //we are afk
if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to
candidates += M.ckey
if(candidates.len)
ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates
else
usr << "<font color='red'>Error: create_xeno(): no suitable candidates.</font>"
if(!istext(ckey)) return 0
var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva")
var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin)
var/mob/living/carbon/alien/new_xeno
switch(alien_caste)
if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(spawn_here)
if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here)
if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here)
if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here)
if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here)
else return 0
new_xeno.ckey = ckey
message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1)
return 1
/*
Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly
Ccomp's first proc.
*/
/client/proc/get_ghosts(var/notify = 0,var/what = 2)
// what = 1, return ghosts ass list.
// what = 2, return mob list
var/list/mobs = list()
var/list/ghosts = list()
var/list/sortmob = sortAtom(mob_list) // get the mob list.
/var/any=0
for(var/mob/dead/observer/M in sortmob)
mobs.Add(M) //filter it where it's only ghosts
any = 1 //if no ghosts show up, any will just be 0
if(!any)
if(notify)
src << "There doesn't appear to be any ghosts for you to select."
return
for(var/mob/M in mobs)
var/name = M.name
ghosts[name] = M //get the name of the mob for the popup list
if(what==1)
return ghosts
else
return mobs
/client/proc/allow_character_respawn()
set category = "Special Verbs"
set name = "Allow player to respawn"
set desc = "Let's the player bypass the 30 minute wait to respawn or allow them to re-enter their corpse."
if(!holder)
src << "Only administrators may use this command."
var/list/ghosts= get_ghosts(1,1)
var/target = input("Please, select a ghost!", "COME BACK TO LIFE!", null, null) as null|anything in ghosts
if(!target)
src << "Hrm, appears you didn't select a ghost" // Sanity check, if no ghosts in the list we don't want to edit a null variable and cause a runtime error.
return
var/mob/dead/observer/G = ghosts[target]
if(G.has_enabled_antagHUD && config.antag_hud_restricted)
var/response = alert(src, "Are you sure you wish to allow this individual to play?","Ghost has used AntagHUD","Yes","No")
if(response == "No") return
G.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb.
timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure
there won't be an autopsy.
*/
G.has_enabled_antagHUD = 2
G.can_reenter_corpse = 1
G:show_message(text("\blue <B>You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead.</B>"), 1)
log_admin("[key_name(usr)] allowed [key_name(G)] to bypass the 30 minute respawn limit")
message_admins("Admin [key_name_admin(usr)] allowed [key_name_admin(G)] to bypass the 30 minute respawn limit", 1)
/client/proc/toggle_antagHUD_use()
set category = "Server"
set name = "Toggle antagHUD usage"
set desc = "Toggles antagHUD usage for observers"
if(!holder)
src << "Only administrators may use this command."
var/action=""
if(config.antag_hud_allowed)
for(var/mob/dead/observer/g in get_ghosts())
if(!g.client.holder) //Remove the verb from non-admin ghosts
g.verbs -= /mob/dead/observer/verb/toggle_antagHUD
if(g.antagHUD)
g.antagHUD = 0 // Disable it on those that have it enabled
g.has_enabled_antagHUD = 2 // We'll allow them to respawn
g << "\red <B>The Administrator has disabled AntagHUD </B>"
config.antag_hud_allowed = 0
src << "\red <B>AntagHUD usage has been disabled</B>"
action = "disabled"
else
for(var/mob/dead/observer/g in get_ghosts())
if(!g.client.holder) // Add the verb back for all non-admin ghosts
g.verbs += /mob/dead/observer/verb/toggle_antagHUD
g << "\blue <B>The Administrator has enabled AntagHUD </B>" // Notify all observers they can now use AntagHUD
config.antag_hud_allowed = 1
action = "enabled"
src << "\blue <B>AntagHUD usage has been enabled</B>"
log_admin("[key_name(usr)] has [action] antagHUD usage for observers")
message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1)
/client/proc/toggle_antagHUD_restrictions()
set category = "Server"
set name = "Toggle antagHUD Restrictions"
set desc = "Restricts players that have used antagHUD from being able to join this round."
if(!holder)
src << "Only administrators may use this command."
var/action=""
if(config.antag_hud_restricted)
for(var/mob/dead/observer/g in get_ghosts())
g << "\blue <B>The administrator has lifted restrictions on joining the round if you use AntagHUD</B>"
action = "lifted restrictions"
config.antag_hud_restricted = 0
src << "\blue <B>AntagHUD restrictions have been lifted</B>"
else
for(var/mob/dead/observer/g in get_ghosts())
g << "\red <B>The administrator has placed restrictions on joining the round if you use AntagHUD</B>"
g << "\red <B>Your AntagHUD has been disabled, you may choose to re-enabled it but will be under restrictions </B>"
g.antagHUD = 0
g.has_enabled_antagHUD = 0
action = "placed restrictions"
config.antag_hud_restricted = 1
src << "\red <B>AntagHUD restrictions have been enabled</B>"
log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD")
message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1)
/*
If a guy was gibbed and you want to revive him, this is a good way to do so.
Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one.
Traitors and the like can also be revived with the previous role mostly intact.
/N */
/client/proc/respawn_character()
set category = "Special Verbs"
set name = "Respawn Character"
set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into."
if(!holder)
src << "Only administrators may use this command."
return
var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", ""))
if(!input)
return
var/mob/dead/observer/G_found
for(var/mob/dead/observer/G in player_list)
if(G.ckey == input)
G_found = G
break
if(!G_found)//If a ghost was not found.
usr << "<font color='red'>There is no active key like that in the game or the person is not currently a ghost.</font>"
return
if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
//Check if they were an alien
if(G_found.mind.assigned_role=="Alien")
if(alert("This character appears to have been an alien. Would you like to respawn them as such?",,"Yes","No")=="Yes")
var/turf/T
if(xeno_spawn.len) T = pick(xeno_spawn)
else T = pick(latejoin)
var/mob/living/carbon/alien/new_xeno
switch(G_found.mind.special_role)//If they have a mind, we can determine which caste they were.
if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(T)
if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(T)
if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(T)
if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(T)
else//If we don't know what special role they have, for whatever reason, or they're a larva.
create_xeno(G_found.ckey)
return
//Now to give them their mind back.
G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_xeno.key = G_found.key
new_xeno << "You have been fully respawned. Enjoy the game."
message_admins("\blue [key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.", 1)
return //all done. The ghost is auto-deleted
//check if they were a monkey
else if(findtext(G_found.real_name,"monkey"))
if(alert("This character appears to have been a monkey. Would you like to respawn them as such?",,"Yes","No")=="Yes")
var/mob/living/carbon/monkey/new_monkey = new(pick(latejoin))
G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_monkey.key = G_found.key
new_monkey << "You have been fully respawned. Enjoy the game."
message_admins("\blue [key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.", 1)
return //all done. The ghost is auto-deleted
//Ok, it's not a xeno or a monkey. So, spawn a human.
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character.
if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
/*Try and locate a record for the person being respawned through data_core.
This isn't an exact science but it does the trick more often than not.*/
var/id = md5("[G_found.real_name][G_found.mind.assigned_role]")
for(var/datum/data/record/t in data_core.locked)
if(t.fields["id"]==id)
record_found = t//We shall now reference the record.
break
if(record_found)//If they have a record we can determine a few things.
new_character.real_name = record_found.fields["name"]
new_character.gender = record_found.fields["sex"]
new_character.age = record_found.fields["age"]
new_character.b_type = record_found.fields["b_type"]
else
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
A.randomize_appearance_for(new_character)
new_character.real_name = G_found.real_name
if(!new_character.real_name)
if(new_character.gender == MALE)
new_character.real_name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
else
new_character.real_name = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
new_character.name = new_character.real_name
if(G_found.mind && !G_found.mind.active)
G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_character.mind.special_verbs = list()
else
new_character.mind_initialize()
if(!new_character.mind.assigned_role) new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role.
//DNA
if(record_found)//Pull up their name from database records if they did have a mind.
new_character.dna = new()//Let's first give them a new DNA.
new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity.
// I HATE BYOND. HATE. HATE. - N3X
var/list/newSE= record_found.fields["enzymes"]
var/list/newUI = record_found.fields["identity"]
new_character.dna.SE = newSE.Copy() //This is the default of enzymes so I think it's safe to go with.
new_character.dna.UpdateSE()
new_character.UpdateAppearance(newUI.Copy())//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch.
else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile.
new_character.dna.ready_dna(new_character)
new_character.key = G_found.key
/*
The code below functions with the assumption that the mob is already a traitor if they have a special role.
So all it does is re-equip the mob with powers and/or items. Or not, if they have no special role.
If they don't have a mind, they obviously don't have a special role.
*/
//Two variables to properly announce later on.
var/admin = key_name_admin(src)
var/player_key = G_found.key
//Now for special roles and equipment.
switch(new_character.mind.special_role)
if("traitor")
job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)
ticker.mode.equip_traitor(new_character)
if("Wizard")
new_character.loc = pick(wizardstart)
//ticker.mode.learn_basic_spells(new_character)
ticker.mode.equip_wizard(new_character)
if("Syndicate")
var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn")
if(synd_spawn)
new_character.loc = get_turf(synd_spawn)
call(/datum/game_mode/proc/equip_syndicate)(new_character)
if("Ninja")
new_character.equip_space_ninja()
new_character.internal = new_character.s_store
new_character.internals.icon_state = "internal1"
if(ninjastart.len == 0)
new_character << "<B>\red A proper starting location for you could not be found, please report this bug!</B>"
new_character << "<B>\red Attempting to place at a carpspawn.</B>"
for(var/obj/effect/landmark/L in landmarks_list)
if(L.name == "carpspawn")
ninjastart.Add(L)
if(ninjastart.len == 0 && latejoin.len > 0)
new_character << "<B>\red Still no spawneable locations could be found. Defaulting to latejoin.</B>"
new_character.loc = pick(latejoin)
else if (ninjastart.len == 0)
new_character << "<B>\red Still no spawneable locations could be found. Aborting.</B>"
if("Death Commando")//Leaves them at late-join spawn.
new_character.equip_death_commando()
new_character.internal = new_character.s_store
new_character.internals.icon_state = "internal1"
else//They may also be a cyborg or AI.
switch(new_character.mind.assigned_role)
if("Cyborg")//More rigging to make em' work and check if they're traitor.
new_character = new_character.Robotize()
if(new_character.mind.special_role=="traitor")
call(/datum/game_mode/proc/add_law_zero)(new_character)
if("AI")
new_character = new_character.AIize()
if(new_character.mind.special_role=="traitor")
call(/datum/game_mode/proc/add_law_zero)(new_character)
//Add aliens.
else
job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them.
//Announces the character on all the systems, based on the record.
if(!issilicon(new_character))//If they are not a cyborg/AI.
if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
//Power to the user!
if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
data_core.manifest_inject(new_character)
if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes")
call(/mob/new_player/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role)
message_admins("\blue [admin] has respawned [player_key] as [new_character.real_name].", 1)
new_character << "You have been fully respawned. Enjoy the game."
feedback_add_details("admin_verb","RSPCH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return new_character
/client/proc/cmd_admin_add_freeform_ai_law()
set category = "Fun"
set name = "Add Custom AI law"
if(!holder)
src << "Only administrators may use this command."
return
var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
if(!input)
return
for(var/mob/living/silicon/ai/M in mob_list)
if (M.stat == 2)
usr << "Upload failed. No signal is being detected from the AI."
else if (M.see_in_dark == 0)
usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power."
else
M.add_ion_law(input)
for(var/mob/living/silicon/ai/O in mob_list)
O << "\red " + input + "\red...LAWS UPDATED"
log_admin("Admin [key_name(usr)] has added a new AI law - [input]")
message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]", 1)
var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No")
if(show_log == "Yes")
command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert")
world << sound('sound/AI/ionstorm.ogg')
feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list)
set category = "Special Verbs"
set name = "Rejuvenate"
if(!holder)
src << "Only administrators may use this command."
return
if(!mob)
return
if(!istype(M))
alert("Cannot revive a ghost")
return
if(config.allow_admin_rev)
M.revive()
log_admin("[key_name(usr)] healed / revived [key_name(M)]")
message_admins("\red Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!", 1)
else
alert("Admin revive disabled")
feedback_add_details("admin_verb","REJU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_create_centcom_report()
set category = "Special Verbs"
set name = "Create Command Report"
if(!holder)
src << "Only administrators may use this command."
return
var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null
var/customname = input(usr, "Pick a title for the report.", "Title") as text|null
if(!input)
return
if(!customname)
customname = "NanoTrasen Update"
for (var/obj/machinery/computer/communications/C in machines)
if(! (C.stat & (BROKEN|NOPOWER) ) )
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc )
P.name = "'[command_name()] Update.'"
P.info = input
P.update_icon()
C.messagetitle.Add("[command_name()] Update")
C.messagetext.Add(P.info)
switch(alert("Should this be announced to the general population?",,"Yes","No"))
if("Yes")
command_alert(input, customname);
if("No")
world << "\red New NanoTrasen Update available at all communication consoles."
world << sound('sound/AI/commandreport.ogg')
log_admin("[key_name(src)] has created a command report: [input]")
message_admins("[key_name_admin(src)] has created a command report", 1)
feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in world)
set category = "Admin"
set name = "Delete"
if (!holder)
src << "Only administrators may use this command."
return
if (alert(src, "Are you sure you want to delete:\n[O]\nat ([O.x], [O.y], [O.z])?", "Confirmation", "Yes", "No") == "Yes")
log_admin("[key_name(usr)] deleted [O] at ([O.x],[O.y],[O.z])")
message_admins("[key_name_admin(usr)] deleted [O] at ([O.x],[O.y],[O.z])", 1)
feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
del(O)
/client/proc/cmd_admin_list_open_jobs()
set category = "Admin"
set name = "List free slots"
if (!holder)
src << "Only administrators may use this command."
return
if(job_master)
for(var/datum/job/job in job_master.occupations)
src << "[job.title]: [job.total_positions]"
feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world)
set category = "Special Verbs"
set name = "Explosion"
if(!check_rights(R_DEBUG|R_FUN)) return
var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null
if(devastation == null) return
var/heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null
if(heavy == null) return
var/light = input("Range of light impact. -1 to none", text("Input")) as num|null
if(light == null) return
var/flash = input("Range of flash. -1 to none", text("Input")) as num|null
if(flash == null) return
if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1))
if ((devastation > 20) || (heavy > 20) || (light > 20))
if (alert(src, "Are you sure you want to do this? It will laaag.", "Confirmation", "Yes", "No") == "No")
return
explosion(O, devastation, heavy, light, flash)
log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flash]) at ([O.x],[O.y],[O.z])")
message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flash]) at ([O.x],[O.y],[O.z])", 1)
feedback_add_details("admin_verb","EXPL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
else
return
/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world)
set category = "Special Verbs"
set name = "EM Pulse"
if(!check_rights(R_DEBUG|R_FUN)) return
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null) return
var/light = input("Range of light pulse.", text("Input")) as num|null
if(light == null) return
if (heavy || light)
empulse(O, heavy, light)
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])")
message_admins("[key_name_admin(usr)] created an EM PUlse ([heavy],[light]) at ([O.x],[O.y],[O.z])", 1)
feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
else
return
/client/proc/cmd_admin_gib(mob/M as mob in mob_list)
set category = "Special Verbs"
set name = "Gib"
if(!check_rights(R_ADMIN|R_FUN)) return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
//Due to the delay here its easy for something to have happened to the mob
if(!M) return
log_admin("[key_name(usr)] has gibbed [key_name(M)]")
message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(M)]", 1)
if(istype(M, /mob/dead/observer))
gibs(M.loc, M.viruses)
return
M.gib()
feedback_add_details("admin_verb","GIB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_gib_self()
set name = "Gibself"
set category = "Fun"
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm == "Yes")
if (istype(mob, /mob/dead/observer)) // so they don't spam gibs everywhere
return
else
mob.gib()
log_admin("[key_name(usr)] used gibself.")
message_admins("\blue [key_name_admin(usr)] used gibself.", 1)
feedback_add_details("admin_verb","GIBS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/*
/client/proc/cmd_manual_ban()
set name = "Manual Ban"
set category = "Special Verbs"
if(!authenticated || !holder)
src << "Only administrators may use this command."
return
var/mob/M = null
switch(alert("How would you like to ban someone today?", "Manual Ban", "Key List", "Enter Manually", "Cancel"))
if("Key List")
var/list/keys = list()
for(var/mob/M in world)
keys += M.client
var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in keys
if(!selection)
return
M = selection:mob
if ((M.client && M.client.holder && (M.client.holder.level >= holder.level)))
alert("You cannot perform this action. You must be of a higher administrative rank!")
return
switch(alert("Temporary Ban?",,"Yes","No"))
if("Yes")
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num
if(!mins)
return
if(mins >= 525600) mins = 525599
var/reason = input(usr,"Reason?","reason","Griefer") as text
if(!reason)
return
if(M)
AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins)
M << "\red<BIG><B>You have been banned by [usr.client.ckey].\nReason: [reason].</B></BIG>"
M << "\red This is a temporary ban, it will be removed in [mins] minutes."
M << "\red To try to resolve this matter head to http://ss13.donglabs.com/forum/"
log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
message_admins("\blue[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=[mins]&server=[replacetext(config.server_name, "#", "")]")
del(M.client)
del(M)
else
if("No")
var/reason = input(usr,"Reason?","reason","Griefer") as text
if(!reason)
return
AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0)
M << "\red<BIG><B>You have been banned by [usr.client.ckey].\nReason: [reason].</B></BIG>"
M << "\red This is a permanent ban."
M << "\red To try to resolve this matter head to http://ss13.donglabs.com/forum/"
log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
message_admins("\blue[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=perma&server=[replacetext(config.server_name, "#", "")]")
del(M.client)
del(M)
*/
/client/proc/update_world()
// If I see anyone granting powers to specific keys like the code that was here,
// I will both remove their SVN access and permanently ban them from my servers.
return
/client/proc/cmd_admin_check_contents(mob/living/M as mob in mob_list)
set category = "Special Verbs"
set name = "Check Contents"
var/list/L = M.get_contents()
for(var/t in L)
usr << "[t]"
feedback_add_details("admin_verb","CC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/* This proc is DEFERRED. Does not do anything.
/client/proc/cmd_admin_remove_plasma()
set category = "Debug"
set name = "Stabilize Atmos."
if(!holder)
src << "Only administrators may use this command."
return
feedback_add_details("admin_verb","STATM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
// DEFERRED
spawn(0)
for(var/turf/T in view())
T.poison = 0
T.oldpoison = 0
T.tmppoison = 0
T.oxygen = 755985
T.oldoxy = 755985
T.tmpoxy = 755985
T.co2 = 14.8176
T.oldco2 = 14.8176
T.tmpco2 = 14.8176
T.n2 = 2.844e+006
T.on2 = 2.844e+006
T.tn2 = 2.844e+006
T.tsl_gas = 0
T.osl_gas = 0
T.sl_gas = 0
T.temp = 293.15
T.otemp = 293.15
T.ttemp = 293.15
*/
/client/proc/toggle_view_range()
set category = "Special Verbs"
set name = "Change View Range"
set desc = "switches between 1x and custom views"
if(view == world.view)
view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
else
view = world.view
log_admin("[key_name(usr)] changed their view range to [view].")
//message_admins("\blue [key_name_admin(usr)] changed their view range to [view].", 1) //why? removed by order of XSI
feedback_add_details("admin_verb","CVRA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_call_shuttle()
set category = "Admin"
set name = "Call Shuttle"
if ((!( ticker ) || emergency_shuttle.location))
return
if(!check_rights(R_ADMIN)) return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "confliction")
var/choice = input("The shuttle will just return if you call it. Call anyway?") in list("Confirm", "Cancel")
if(choice == "Confirm")
emergency_shuttle.fake_recall = rand(300,500)
else
return
emergency_shuttle.incall()
captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.")
world << sound('sound/AI/shuttlecalled.ogg')
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.")
message_admins("\blue [key_name_admin(usr)] admin-called the emergency shuttle.", 1)
return
/client/proc/admin_cancel_shuttle()
set category = "Admin"
set name = "Cancel Shuttle"
if(!check_rights(R_ADMIN)) return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return
if(!ticker || emergency_shuttle.location || emergency_shuttle.direction == 0)
return
emergency_shuttle.recall()
feedback_add_details("admin_verb","CCSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-recalled the emergency shuttle.")
message_admins("\blue [key_name_admin(usr)] admin-recalled the emergency shuttle.", 1)
return
/client/proc/admin_deny_shuttle()
set category = "Admin"
set name = "Toggle Deny Shuttle"
if (!ticker)
return
if(!check_rights(R_ADMIN)) return
emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle
log_admin("[key_name(src)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.")
message_admins("[key_name_admin(usr)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.")
/client/proc/cmd_admin_attack_log(mob/M as mob in mob_list)
set category = "Special Verbs"
set name = "Attack Log"
usr << text("\red <b>Attack Log for []</b>", mob)
for(var/t in M.attack_log)
usr << t
feedback_add_details("admin_verb","ATTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/everyone_random()
set category = "Fun"
set name = "Make Everyone Random"
set desc = "Make everyone have a random appearance. You can only use this before rounds!"
if(!check_rights(R_FUN)) return
if (ticker && ticker.mode)
usr << "Nope you can't do this, the game's already started. This only works before rounds!"
return
if(ticker.random_players)
ticker.random_players = 0
message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.", 1)
usr << "Disabled."
return
var/notifyplayers = alert(src, "Do you want to notify the players?", "Options", "Yes", "No", "Cancel")
if(notifyplayers == "Cancel")
return
log_admin("Admin [key_name(src)] has forced the players to have random appearances.")
message_admins("Admin [key_name_admin(usr)] has forced the players to have random appearances.", 1)
if(notifyplayers == "Yes")
world << "\blue <b>Admin [usr.key] has forced the players to have completely random identities!"
usr << "<i>Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet</i>."
ticker.random_players = 1
feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_random_events()
set category = "Server"
set name = "Toggle random events on/off"
set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off"
if(!check_rights(R_SERVER)) return
if(!config.allow_random_events)
config.allow_random_events = 1
usr << "Random events enabled"
message_admins("Admin [key_name_admin(usr)] has enabled random events.", 1)
else
config.allow_random_events = 0
usr << "Random events disabled"
message_admins("Admin [key_name_admin(usr)] has disabled random events.", 1)
feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+176
View File
@@ -0,0 +1,176 @@
//STRIKE TEAMS
var/const/commandos_possible = 6 //if more Commandos are needed in the future
var/global/sent_strike_team = 0
/client/proc/strike_team()
if(!ticker)
usr << "<font color='red'>The game hasn't started yet!</font>"
return
if(world.time < 6000)
usr << "<font color='red'>There are [(6000-world.time)/10] seconds remaining before it may be called.</font>"
return
if(sent_strike_team == 1)
usr << "<font color='red'>CentCom is already sending a team.</font>"
return
if(alert("Do you want to send in the CentCom death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes")
return
alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned commandos have internals cameras which are viewable through a monitor inside the Spec. Ops. Office. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.")
var/input = null
while(!input)
input = copytext(sanitize(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", "")),1,MAX_MESSAGE_LEN)
if(!input)
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
return
if(sent_strike_team)
usr << "Looks like someone beat you to it."
return
sent_strike_team = 1
if (emergency_shuttle.direction == 1 && emergency_shuttle.online == 1)
emergency_shuttle.recall()
var/commando_number = commandos_possible //for selecting a leader
var/leader_selected = 0 //when the leader is chosen. The last person spawned.
//Code for spawning a nuke auth code.
var/nuke_code
var/temp_code
for(var/obj/machinery/nuclearbomb/N in world)
temp_code = text2num(N.r_code)
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
nuke_code = N.r_code
break
//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos.
var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world.
var/list/commandos = list() //actual commando ghosts as picked by the user.
for(var/mob/dead/observer/G in player_list)
if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list.
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
candidates += G.key
for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected.
var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate.
candidates -= candidate //Subtract from candidates.
commandos += candidate//Add their ghost to commandos.
//Spawns commandos and equips them.
for(var/obj/effect/landmark/L in landmarks_list)
if(commando_number<=0) break
if (L.name == "Commando")
leader_selected = commando_number == 1?1:0
var/mob/living/carbon/human/new_commando = create_death_commando(L, leader_selected)
if(commandos.len)
new_commando.key = pick(commandos)
commandos -= new_commando.key
new_commando.internal = new_commando.s_store
new_commando.internals.icon_state = "internal1"
//So they don't forget their code or mission.
if(nuke_code)
new_commando.mind.store_memory("<B>Nuke Code:</B> \red [nuke_code].")
new_commando.mind.store_memory("<B>Mission:</B> \red [input].")
new_commando << "\blue You are a Special Ops. [!leader_selected?"commando":"<B>LEADER</B>"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: \red<B>[input]</B>"
commando_number--
//Spawns the rest of the commando gear.
for (var/obj/effect/landmark/L in landmarks_list)
if (L.name == "Commando_Manual")
//new /obj/item/weapon/gun/energy/pulse_rifle(L.loc)
var/obj/item/weapon/paper/P = new(L.loc)
P.info = "<p><b>Good morning soldier!</b>. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:<br>#1 Work as a team.<br>#2 Accomplish your objective at all costs.<br>#3 Leave no witnesses.<br>You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.<br>If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.</p><p>In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations <b>LEADER</b> is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.</p><p>Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.<br>First and foremost, <b>DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.</b> Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.<br>To make the device functional:<br>#1 Place bomb in designated detonation zone<br> #2 Extend and anchor bomb (attack with hand).<br>#3 Insert Nuclear Auth. Disk into slot.<br>#4 Type numeric code into keypad ([nuke_code]).<br>Note: If you make a mistake press R to reset the device.<br>#5 Press the E button to log onto the device.<br>You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.<br>Note: Toggle off the <b>SAFETY</b>.<br>Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.<br>Note: <b>THE BOMB IS STILL SET AND WILL DETONATE</b><br>Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.</p><p>The nuclear authorization code is: <b>[nuke_code ? nuke_code : "None provided"]</b></p><p><b>Good luck, soldier!</b></p>"
P.name = "Spec. Ops. Manual"
for (var/obj/effect/landmark/L in landmarks_list)
if (L.name == "Commando-Bomb")
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
del(L)
message_admins("\blue [key_name_admin(usr)] has spawned a CentCom strike squad.", 1)
log_admin("[key_name(usr)] used Spawn Death Squad.")
return 1
/client/proc/create_death_commando(obj/spawn_location, leader_selected = 0)
var/mob/living/carbon/human/new_commando = new(spawn_location.loc)
var/commando_leader_rank = pick("Lieutenant", "Captain", "Major")
var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/commando_name = pick(last_names)
new_commando.gender = pick(MALE, FEMALE)
var/datum/preferences/A = new()//Randomize appearance for the commando.
A.randomize_appearance_for(new_commando)
new_commando.real_name = "[!leader_selected ? commando_rank : commando_leader_rank] [commando_name]"
new_commando.age = !leader_selected ? rand(23,35) : rand(35,45)
new_commando.dna.ready_dna(new_commando)//Creates DNA.
//Creates mind stuff.
new_commando.mind_initialize()
new_commando.mind.assigned_role = "MODE"
new_commando.mind.special_role = "Death Commando"
ticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list.
new_commando.equip_death_commando(leader_selected)
return new_commando
/mob/living/carbon/human/proc/equip_death_commando(leader_selected = 0)
var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src)
R.set_frequency(1341)
equip_to_slot_or_del(R, slot_l_ear)
if (leader_selected == 0)
equip_to_slot_or_del(new /obj/item/clothing/under/color/green(src), slot_w_uniform)
else
equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head)
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask)
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses)
equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back)
equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/ammo_magazine/a357(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/storage/box/flashbangs(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack)
if (!leader_selected)
equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack)
else
equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/grenade/flashbang(src), slot_r_store)
equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(src), slot_belt)
equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand)
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)//Here you go Deuryn
L.imp_in = src
L.implanted = 1
var/obj/item/weapon/card/id/W = new(src)
W.name = "[real_name]'s ID Card"
W.icon_state = "centcom"
W.access = get_all_accesses()//They get full station access.
W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)//Let's add their alloted CentCom access.
W.assignment = "Death Commando"
W.registered_name = real_name
equip_to_slot_or_del(W, slot_wear_id)
return 1
@@ -0,0 +1,178 @@
//STRIKE TEAMS
var/const/syndicate_commandos_possible = 6 //if more Commandos are needed in the future
var/global/sent_syndicate_strike_team = 0
/client/proc/syndicate_strike_team()
set category = "Fun"
set name = "Spawn Syndicate Strike Team"
set desc = "Spawns a squad of commandos in the Syndicate Mothership if you want to run an admin event."
if(!src.holder)
src << "Only administrators may use this command."
return
if(!ticker)
alert("The game hasn't started yet!")
return
// if(world.time < 6000)
// alert("Not so fast, buddy. Wait a few minutes until the game gets going. There are [(6000-world.time)/10] seconds remaining.")
// return
if(sent_syndicate_strike_team == 1)
alert("The Syndicate are already sending a team, Mr. Dumbass.")
return
if(alert("Do you want to send in the Syndicate Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No")
return
alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned syndicates have internals cameras which are viewable through a monitor inside the Syndicate Mothership Bridge. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.")
var/input = null
while(!input)
input = copytext(sanitize(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", "")),1,MAX_MESSAGE_LEN)
if(!input)
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
return
if(sent_syndicate_strike_team)
src << "Looks like someone beat you to it."
return
sent_syndicate_strike_team = 1
if (emergency_shuttle.direction == 1 && emergency_shuttle.online == 1)
emergency_shuttle.recall()
var/syndicate_commando_number = syndicate_commandos_possible //for selecting a leader
var/syndicate_leader_selected = 0 //when the leader is chosen. The last person spawned.
//Code for spawning a nuke auth code.
var/nuke_code
var/temp_code
for(var/obj/machinery/nuclearbomb/N in world)
temp_code = text2num(N.r_code)
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
nuke_code = N.r_code
break
//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos.
var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world.
var/list/commandos = list() //actual commando ghosts as picked by the user.
for(var/mob/dead/observer/G in player_list)
if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list.
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
candidates += G.key
for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected.
var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate.
candidates -= candidate //Subtract from candidates.
commandos += candidate//Add their ghost to commandos.
//Spawns commandos and equips them.
for(var/obj/effect/landmark/L in landmarks_list)
if(syndicate_commando_number<=0) break
if (L.name == "Syndicate-Commando")
syndicate_leader_selected = syndicate_commando_number == 1?1:0
var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected)
if(commandos.len)
new_syndicate_commando.key = pick(commandos)
commandos -= new_syndicate_commando.key
new_syndicate_commando.internal = new_syndicate_commando.s_store
new_syndicate_commando.internals.icon_state = "internal1"
//So they don't forget their code or mission.
if(nuke_code)
new_syndicate_commando.mind.store_memory("<B>Nuke Code:</B> \red [nuke_code].")
new_syndicate_commando.mind.store_memory("<B>Mission:</B> \red [input].")
new_syndicate_commando << "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"<B>LEADER</B>"] in the service of the Syndicate. \nYour current mission is: \red<B>[input]</B>"
syndicate_commando_number--
//Spawns the rest of the commando gear.
// for (var/obj/effect/landmark/L)
// if (L.name == "Commando_Manual")
//new /obj/item/weapon/gun/energy/pulse_rifle(L.loc)
// var/obj/item/weapon/paper/P = new(L.loc)
// P.info = "<p><b>Good morning soldier!</b>. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:<br>#1 Work as a team.<br>#2 Accomplish your objective at all costs.<br>#3 Leave no witnesses.<br>You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.<br>If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.</p><p>In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations <b>LEADER</b> is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.</p><p>Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.<br>First and foremost, <b>DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.</b> Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.<br>To make the device functional:<br>#1 Place bomb in designated detonation zone<br> #2 Extend and anchor bomb (attack with hand).<br>#3 Insert Nuclear Auth. Disk into slot.<br>#4 Type numeric code into keypad ([nuke_code]).<br>Note: If you make a mistake press R to reset the device.<br>#5 Press the E button to log onto the device.<br>You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.<br>Note: Toggle off the <b>SAFETY</b>.<br>Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.<br>Note: <b>THE BOMB IS STILL SET AND WILL DETONATE</b><br>Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.</p><p>The nuclear authorization code is: <b>[nuke_code ? nuke_code : "None provided"]</b></p><p><b>Good luck, soldier!</b></p>"
// P.name = "Spec. Ops. Manual"
for (var/obj/effect/landmark/L in landmarks_list)
if (L.name == "Syndicate-Commando-Bomb")
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
del(L)
message_admins("\blue [key_name_admin(usr)] has spawned a Syndicate strike squad.", 1)
log_admin("[key_name(usr)] used Spawn Syndicate Squad.")
feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0)
var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc)
var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major")
var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/syndicate_commando_name = pick(last_names)
new_syndicate_commando.gender = pick(MALE, FEMALE)
var/datum/preferences/A = new()//Randomize appearance for the commando.
A.randomize_appearance_for(new_syndicate_commando)
new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]"
new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45)
new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA.
//Creates mind stuff.
new_syndicate_commando.mind_initialize()
new_syndicate_commando.mind.assigned_role = "MODE"
new_syndicate_commando.mind.special_role = "Syndicate Commando"
ticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list.
new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected)
del(spawn_location)
return new_syndicate_commando
/mob/living/carbon/human/proc/equip_syndicate_commando(syndicate_leader_selected = 0)
var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src)
R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode.
equip_to_slot_or_del(R, slot_l_ear)
equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes)
if (!syndicate_leader_selected)
equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black(src), slot_wear_suit)
else
equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black/red(src), slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
if (!syndicate_leader_selected)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black(src), slot_head)
else
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black/red(src), slot_head)
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(src), slot_wear_mask)
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses)
equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back)
equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/ammo_magazine/c45(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack)
if (!syndicate_leader_selected)
equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack)
else
equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/grenade/empgrenade(src), slot_r_store)
equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/silenced(src), slot_belt)
equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) //Will change to something different at a later time -- Superxpdude
var/obj/item/weapon/card/id/syndicate/W = new(src) //Untrackable by AI
W.name = "[real_name]'s ID Card"
W.icon_state = "id"
W.access = get_all_accesses()//They get full station access because obviously the syndicate has HAAAX, and can make special IDs for their most elite members.
W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage, access_syndicate)//Let's add their forged CentCom access and syndicate access.
W.assignment = "Syndicate Commando"
W.registered_name = real_name
equip_to_slot_or_del(W, slot_wear_id)
return 1
+24
View File
@@ -0,0 +1,24 @@
//Merged Doohl's and the existing ticklag as they both had good elements about them ~Carn
/client/proc/ticklag()
set category = "Debug"
set name = "Set Ticklag"
set desc = "Sets a new tick lag. Recommend you don't mess with this too much! Stable, time-tested ticklag value is 0.9"
if(!check_rights(R_DEBUG)) return
var/newtick = input("Sets a new tick lag. Please don't mess with this too much! The stable, time-tested ticklag value is 0.9","Lag of Tick", world.tick_lag) as num|null
//I've used ticks of 2 before to help with serious singulo lags
if(newtick && newtick <= 2 && newtick > 0)
log_admin("[key_name(src)] has modified world.tick_lag to [newtick]", 0)
message_admins("[key_name(src)] has modified world.tick_lag to [newtick]", 0)
world.tick_lag = newtick
feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
switch(alert("Enable Tick Compensation?","Tick Comp is currently: [config.Tickcomp]","Yes","No"))
if("Yes") config.Tickcomp = 1
else config.Tickcomp = 0
else
src << "\red Error: ticklag(): Invalid world.ticklag value. No changes made."
+22
View File
@@ -0,0 +1,22 @@
/client/proc/triple_ai()
set category = "Fun"
set name = "Create AI Triumvirate"
if(ticker.current_state > GAME_STATE_PREGAME)
usr << "This option is currently only usable during pregame. This may change at a later date."
return
if(job_master && ticker)
var/datum/job/job = job_master.GetJob("AI")
if(!job)
usr << "Unable to locate the AI job"
return
if(ticker.triai)
ticker.triai = 0
usr << "Only one AI will be spawned at round start."
message_admins("\blue [key_name_admin(usr)] has toggled off triple AIs at round start.", 1)
else
ticker.triai = 1
usr << "There will be an AI Triumvirate at round start."
message_admins("\blue [key_name_admin(usr)] has toggled on triple AIs at round start.", 1)
return
+87
View File
@@ -0,0 +1,87 @@
var/global/vox_tick = 1
/mob/living/carbon/human/proc/equip_vox_raider()
var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src)
R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode.
equip_to_slot_or_del(R, slot_l_ear)
equip_to_slot_or_del(new /obj/item/clothing/under/vox/vox_robes(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(src), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES.
equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow/vox(src), slot_gloves) // AS ABOVE.
switch(vox_tick)
if(1) // Vox raider!
equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(src), slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(src), slot_head)
equip_to_slot_or_del(new /obj/item/weapon/melee/telebaton(src), slot_belt)
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
equip_to_slot_or_del(new /obj/item/device/chameleon(src), slot_l_store)
var/obj/item/weapon/crossbow/W = new(src)
W.cell = new /obj/item/weapon/cell/crap(W)
W.cell.charge = 500
equip_to_slot_or_del(W, slot_r_hand)
var/obj/item/stack/rods/A = new(src)
A.amount = 20
equip_to_slot_or_del(A, slot_l_hand)
if(2) // Vox engineer!
equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/pressure(src), slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/pressure(src), slot_head)
equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt)
equip_to_slot_or_del(new /obj/item/clothing/glasses/meson(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
equip_to_slot_or_del(new /obj/item/weapon/storage/box/emps(src), slot_r_hand)
equip_to_slot_or_del(new /obj/item/device/multitool(src), slot_l_hand)
if(3) // Vox saboteur!
equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/stealth(src), slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/stealth(src), slot_head)
equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt)
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
equip_to_slot_or_del(new /obj/item/weapon/card/emag(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/dartgun/vox/raider(src), slot_r_hand)
equip_to_slot_or_del(new /obj/item/device/multitool(src), slot_l_hand)
if(4) // Vox medic!
equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/medic(src), slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/medic(src), slot_head)
equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) // Who needs actual surgical tools?
equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
equip_to_slot_or_del(new /obj/item/weapon/circular_saw(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/dartgun/vox/medical, slot_r_hand)
equip_to_slot_or_del(new /obj/item/clothing/mask/breath/vox(src), slot_wear_mask)
equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(src), slot_back)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_r_store)
var/obj/item/weapon/card/id/syndicate/C = new(src)
C.name = "[real_name]'s Legitimate Human ID Card"
C.icon_state = "id"
C.access = list(access_syndicate)
C.assignment = "Trader"
C.registered_name = real_name
C.registered_user = src
var/obj/item/weapon/storage/wallet/W = new(src)
W.handle_item_insertion(C)
spawn_money(rand(50,150)*10,W)
equip_to_slot_or_del(W, slot_wear_id)
var/obj/item/weapon/implant/cortical/I = new(src)
I.imp_in = src
I.implanted = 1
var/datum/organ/external/affected = src.get_organ("head")
affected.implants += I
I.part = affected
if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) )
var/datum/game_mode/heist/M = ticker.mode
M.cortical_stacks += I
M.raiders[mind] = I
vox_tick++
if (vox_tick > 4) vox_tick = 1
return 1