@@ -499,4 +499,4 @@
|
||||
|
||||
output += "</table></div>"
|
||||
|
||||
usr << browse(output,"window=lookupbans;size=900x500")
|
||||
usr << browse(output,"window=lookupbans;size=900x500")
|
||||
|
||||
+232
-232
@@ -1,233 +1,233 @@
|
||||
GLOBAL_VAR(CMinutes)
|
||||
GLOBAL_DATUM(Banlist, /savefile)
|
||||
GLOBAL_PROTECT(Banlist)
|
||||
|
||||
|
||||
/proc/CheckBan(ckey, id, address)
|
||||
if(!GLOB.Banlist) // if Banlist cannot be located for some reason
|
||||
LoadBans() // try to load the bans
|
||||
if(!GLOB.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>"
|
||||
GLOB.Banlist.cd = "/base"
|
||||
if( "[ckey][id]" in GLOB.Banlist.dir )
|
||||
GLOB.Banlist.cd = "[ckey][id]"
|
||||
if (GLOB.Banlist["temp"])
|
||||
if (!GetExp(GLOB.Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: [GetExp(GLOB.Banlist["minutes"])]\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
else
|
||||
GLOB.Banlist.cd = "/base/[ckey][id]"
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
.["reason"] = "ckey/id"
|
||||
return .
|
||||
else
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
var/matches
|
||||
if( ckey == GLOB.Banlist["key"] )
|
||||
matches += "ckey"
|
||||
if( id == GLOB.Banlist["id"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "id"
|
||||
if( address == GLOB.Banlist["ip"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "ip"
|
||||
|
||||
if(matches)
|
||||
if(GLOB.Banlist["temp"])
|
||||
if (!GetExp(GLOB.Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: [GetExp(GLOB.Banlist["minutes"])]\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
.["reason"] = matches
|
||||
return .
|
||||
return 0
|
||||
|
||||
/proc/UpdateTime() //No idea why i made this a proc.
|
||||
GLOB.CMinutes = (world.realtime / 10) / 60
|
||||
return 1
|
||||
|
||||
/proc/LoadBans()
|
||||
|
||||
GLOB.Banlist = new("data/banlist.bdb")
|
||||
log_admin("Loading Banlist")
|
||||
|
||||
if (!length(GLOB.Banlist.dir)) log_admin("Banlist is empty.")
|
||||
|
||||
if (!GLOB.Banlist.dir.Find("base"))
|
||||
log_admin("Banlist missing base dir.")
|
||||
GLOB.Banlist.dir.Add("base")
|
||||
GLOB.Banlist.cd = "/base"
|
||||
else if (GLOB.Banlist.dir.Find("base"))
|
||||
GLOB.Banlist.cd = "/base"
|
||||
|
||||
ClearTempbans()
|
||||
return 1
|
||||
|
||||
/proc/ClearTempbans()
|
||||
UpdateTime()
|
||||
|
||||
GLOB.Banlist.cd = "/base"
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
if (!GLOB.Banlist["key"] || !GLOB.Banlist["id"])
|
||||
RemoveBan(A)
|
||||
log_admin("Invalid Ban.")
|
||||
message_admins("Invalid Ban.")
|
||||
continue
|
||||
|
||||
if (!GLOB.Banlist["temp"]) continue
|
||||
if (GLOB.CMinutes >= GLOB.Banlist["minutes"]) RemoveBan(A)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes, address)
|
||||
|
||||
var/bantimestamp
|
||||
|
||||
if (temp)
|
||||
UpdateTime()
|
||||
bantimestamp = GLOB.CMinutes + minutes
|
||||
|
||||
GLOB.Banlist.cd = "/base"
|
||||
if ( GLOB.Banlist.dir.Find("[ckey][computerid]") )
|
||||
to_chat(usr, text("<span class='danger'>Ban already exists.</span>"))
|
||||
return 0
|
||||
else
|
||||
GLOB.Banlist.dir.Add("[ckey][computerid]")
|
||||
GLOB.Banlist.cd = "/base/[ckey][computerid]"
|
||||
GLOB.Banlist["key"] << ckey
|
||||
GLOB.Banlist["id"] << computerid
|
||||
GLOB.Banlist["ip"] << address
|
||||
GLOB.Banlist["reason"] << reason
|
||||
GLOB.Banlist["bannedby"] << bannedby
|
||||
GLOB.Banlist["temp"] << temp
|
||||
if (temp)
|
||||
GLOB.Banlist["minutes"] << bantimestamp
|
||||
if(!temp)
|
||||
create_message("note", ckey, bannedby, "Permanently banned - [reason]", null, null, 0, 0)
|
||||
else
|
||||
create_message("note", ckey, bannedby, "Banned for [minutes] minutes - [reason]", null, null, 0, 0)
|
||||
return 1
|
||||
|
||||
/proc/RemoveBan(foldername)
|
||||
var/key
|
||||
var/id
|
||||
|
||||
GLOB.Banlist.cd = "/base/[foldername]"
|
||||
GLOB.Banlist["key"] >> key
|
||||
GLOB.Banlist["id"] >> id
|
||||
GLOB.Banlist.cd = "/base"
|
||||
|
||||
if (!GLOB.Banlist.dir.Remove(foldername)) return 0
|
||||
|
||||
if(!usr)
|
||||
log_admin_private("Ban Expired: [key]")
|
||||
message_admins("Ban Expired: [key]")
|
||||
else
|
||||
ban_unban_log_save("[key_name(usr)] unbanned [key]")
|
||||
log_admin_private("[key_name(usr)] unbanned [key]")
|
||||
message_admins("[key_name_admin(usr)] unbanned: [key]")
|
||||
GLOBAL_VAR(CMinutes)
|
||||
GLOBAL_DATUM(Banlist, /savefile)
|
||||
GLOBAL_PROTECT(Banlist)
|
||||
|
||||
|
||||
/proc/CheckBan(ckey, id, address)
|
||||
if(!GLOB.Banlist) // if Banlist cannot be located for some reason
|
||||
LoadBans() // try to load the bans
|
||||
if(!GLOB.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>"
|
||||
GLOB.Banlist.cd = "/base"
|
||||
if( "[ckey][id]" in GLOB.Banlist.dir )
|
||||
GLOB.Banlist.cd = "[ckey][id]"
|
||||
if (GLOB.Banlist["temp"])
|
||||
if (!GetExp(GLOB.Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: [GetExp(GLOB.Banlist["minutes"])]\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
else
|
||||
GLOB.Banlist.cd = "/base/[ckey][id]"
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
.["reason"] = "ckey/id"
|
||||
return .
|
||||
else
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
var/matches
|
||||
if( ckey == GLOB.Banlist["key"] )
|
||||
matches += "ckey"
|
||||
if( id == GLOB.Banlist["id"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "id"
|
||||
if( address == GLOB.Banlist["ip"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "ip"
|
||||
|
||||
if(matches)
|
||||
if(GLOB.Banlist["temp"])
|
||||
if (!GetExp(GLOB.Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: [GetExp(GLOB.Banlist["minutes"])]\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.Banlist["bannedby"]][appeal]"
|
||||
.["reason"] = matches
|
||||
return .
|
||||
return 0
|
||||
|
||||
/proc/UpdateTime() //No idea why i made this a proc.
|
||||
GLOB.CMinutes = (world.realtime / 10) / 60
|
||||
return 1
|
||||
|
||||
/proc/LoadBans()
|
||||
|
||||
GLOB.Banlist = new("data/banlist.bdb")
|
||||
log_admin("Loading Banlist")
|
||||
|
||||
if (!length(GLOB.Banlist.dir)) log_admin("Banlist is empty.")
|
||||
|
||||
if (!GLOB.Banlist.dir.Find("base"))
|
||||
log_admin("Banlist missing base dir.")
|
||||
GLOB.Banlist.dir.Add("base")
|
||||
GLOB.Banlist.cd = "/base"
|
||||
else if (GLOB.Banlist.dir.Find("base"))
|
||||
GLOB.Banlist.cd = "/base"
|
||||
|
||||
ClearTempbans()
|
||||
return 1
|
||||
|
||||
/proc/ClearTempbans()
|
||||
UpdateTime()
|
||||
|
||||
GLOB.Banlist.cd = "/base"
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
if (!GLOB.Banlist["key"] || !GLOB.Banlist["id"])
|
||||
RemoveBan(A)
|
||||
log_admin("Invalid Ban.")
|
||||
message_admins("Invalid Ban.")
|
||||
continue
|
||||
|
||||
if (!GLOB.Banlist["temp"]) continue
|
||||
if (GLOB.CMinutes >= GLOB.Banlist["minutes"]) RemoveBan(A)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes, address)
|
||||
|
||||
var/bantimestamp
|
||||
|
||||
if (temp)
|
||||
UpdateTime()
|
||||
bantimestamp = GLOB.CMinutes + minutes
|
||||
|
||||
GLOB.Banlist.cd = "/base"
|
||||
if ( GLOB.Banlist.dir.Find("[ckey][computerid]") )
|
||||
to_chat(usr, text("<span class='danger'>Ban already exists.</span>"))
|
||||
return 0
|
||||
else
|
||||
GLOB.Banlist.dir.Add("[ckey][computerid]")
|
||||
GLOB.Banlist.cd = "/base/[ckey][computerid]"
|
||||
GLOB.Banlist["key"] << ckey
|
||||
GLOB.Banlist["id"] << computerid
|
||||
GLOB.Banlist["ip"] << address
|
||||
GLOB.Banlist["reason"] << reason
|
||||
GLOB.Banlist["bannedby"] << bannedby
|
||||
GLOB.Banlist["temp"] << temp
|
||||
if (temp)
|
||||
GLOB.Banlist["minutes"] << bantimestamp
|
||||
if(!temp)
|
||||
create_message("note", ckey, bannedby, "Permanently banned - [reason]", null, null, 0, 0)
|
||||
else
|
||||
create_message("note", ckey, bannedby, "Banned for [minutes] minutes - [reason]", null, null, 0, 0)
|
||||
return 1
|
||||
|
||||
/proc/RemoveBan(foldername)
|
||||
var/key
|
||||
var/id
|
||||
|
||||
GLOB.Banlist.cd = "/base/[foldername]"
|
||||
GLOB.Banlist["key"] >> key
|
||||
GLOB.Banlist["id"] >> id
|
||||
GLOB.Banlist.cd = "/base"
|
||||
|
||||
if (!GLOB.Banlist.dir.Remove(foldername)) return 0
|
||||
|
||||
if(!usr)
|
||||
log_admin_private("Ban Expired: [key]")
|
||||
message_admins("Ban Expired: [key]")
|
||||
else
|
||||
ban_unban_log_save("[key_name(usr)] unbanned [key]")
|
||||
log_admin_private("[key_name(usr)] unbanned [key]")
|
||||
message_admins("[key_name_admin(usr)] unbanned: [key]")
|
||||
SSblackbox.inc("ban_unban",1)
|
||||
usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN)
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
if (key == GLOB.Banlist["key"] /*|| id == Banlist["id"]*/)
|
||||
GLOB.Banlist.cd = "/base"
|
||||
GLOB.Banlist.dir.Remove(A)
|
||||
continue
|
||||
|
||||
return 1
|
||||
|
||||
/proc/GetExp(minutes as num)
|
||||
UpdateTime()
|
||||
var/exp = minutes - GLOB.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 >"
|
||||
GLOB.Banlist.cd = "/base"
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
count++
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
var/ref = "\ref[src]"
|
||||
var/key = GLOB.Banlist["key"]
|
||||
var/id = GLOB.Banlist["id"]
|
||||
var/ip = GLOB.Banlist["ip"]
|
||||
var/reason = GLOB.Banlist["reason"]
|
||||
var/by = GLOB.Banlist["bannedby"]
|
||||
var/expiry
|
||||
if(GLOB.Banlist["temp"])
|
||||
expiry = GetExp(GLOB.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)
|
||||
GLOB.Banlist.cd = "/base"
|
||||
GLOB.Banlist.dir.Add("trash[i]trashid[i]")
|
||||
GLOB.Banlist.cd = "/base/trash[i]trashid[i]"
|
||||
GLOB.Banlist["key"] << "trash[i]"
|
||||
else
|
||||
GLOB.Banlist.cd = "/base"
|
||||
GLOB.Banlist.dir.Add("[last]trashid[i]")
|
||||
GLOB.Banlist.cd = "/base/[last]trashid[i]"
|
||||
GLOB.Banlist["key"] << last
|
||||
GLOB.Banlist["id"] << "trashid[i]"
|
||||
GLOB.Banlist["reason"] << "Trashban[i]."
|
||||
GLOB.Banlist["temp"] << a
|
||||
GLOB.Banlist["minutes"] << GLOB.CMinutes + rand(1,2000)
|
||||
GLOB.Banlist["bannedby"] << "trashmin"
|
||||
last = "trash[i]"
|
||||
|
||||
GLOB.Banlist.cd = "/base"
|
||||
|
||||
/proc/ClearAllBans()
|
||||
GLOB.Banlist.cd = "/base"
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
RemoveBan(A)
|
||||
|
||||
usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN)
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
if (key == GLOB.Banlist["key"] /*|| id == Banlist["id"]*/)
|
||||
GLOB.Banlist.cd = "/base"
|
||||
GLOB.Banlist.dir.Remove(A)
|
||||
continue
|
||||
|
||||
return 1
|
||||
|
||||
/proc/GetExp(minutes as num)
|
||||
UpdateTime()
|
||||
var/exp = minutes - GLOB.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 >"
|
||||
GLOB.Banlist.cd = "/base"
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
count++
|
||||
GLOB.Banlist.cd = "/base/[A]"
|
||||
var/ref = "\ref[src]"
|
||||
var/key = GLOB.Banlist["key"]
|
||||
var/id = GLOB.Banlist["id"]
|
||||
var/ip = GLOB.Banlist["ip"]
|
||||
var/reason = GLOB.Banlist["reason"]
|
||||
var/by = GLOB.Banlist["bannedby"]
|
||||
var/expiry
|
||||
if(GLOB.Banlist["temp"])
|
||||
expiry = GetExp(GLOB.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)
|
||||
GLOB.Banlist.cd = "/base"
|
||||
GLOB.Banlist.dir.Add("trash[i]trashid[i]")
|
||||
GLOB.Banlist.cd = "/base/trash[i]trashid[i]"
|
||||
GLOB.Banlist["key"] << "trash[i]"
|
||||
else
|
||||
GLOB.Banlist.cd = "/base"
|
||||
GLOB.Banlist.dir.Add("[last]trashid[i]")
|
||||
GLOB.Banlist.cd = "/base/[last]trashid[i]"
|
||||
GLOB.Banlist["key"] << last
|
||||
GLOB.Banlist["id"] << "trashid[i]"
|
||||
GLOB.Banlist["reason"] << "Trashban[i]."
|
||||
GLOB.Banlist["temp"] << a
|
||||
GLOB.Banlist["minutes"] << GLOB.CMinutes + rand(1,2000)
|
||||
GLOB.Banlist["bannedby"] << "trashmin"
|
||||
last = "trash[i]"
|
||||
|
||||
GLOB.Banlist.cd = "/base"
|
||||
|
||||
/proc/ClearAllBans()
|
||||
GLOB.Banlist.cd = "/base"
|
||||
for (var/A in GLOB.Banlist.dir)
|
||||
RemoveBan(A)
|
||||
|
||||
|
||||
+10
-10
@@ -1,3 +1,4 @@
|
||||
|
||||
////////////////////////////////
|
||||
/proc/message_admins(msg)
|
||||
msg = "<span class=\"admin\"><span class=\"prefix\">ADMIN LOG:</span> <span class=\"message\">[msg]</span></span>"
|
||||
@@ -42,6 +43,7 @@
|
||||
body += "\[ <a href='?_src_=holder;showrelatedacc=cid;client=\ref[M.client]'>CID</a> | "
|
||||
body += "<a href='?_src_=holder;showrelatedacc=ip;client=\ref[M.client]'>IP</a> \]"
|
||||
|
||||
|
||||
body += "<br><br>\[ "
|
||||
body += "<a href='?_src_=vars;Vars=\ref[M]'>VV</a> - "
|
||||
body += "<a href='?_src_=holder;traitor=\ref[M]'>TP</a> - "
|
||||
@@ -239,21 +241,21 @@
|
||||
if(6)
|
||||
dat+="<B><FONT COLOR='maroon'>ERROR: Could not submit Feed story to Network.</B></FONT><HR><BR>"
|
||||
if(src.admincaster_feed_channel.channel_name=="")
|
||||
dat+="<FONT COLOR='maroon'>Invalid receiving channel name.</FONT><BR>"
|
||||
dat+="<FONT COLOR='maroon'>Invalid receiving channel name.</FONT><BR>"
|
||||
if(src.admincaster_feed_message.returnBody(-1) == "" || src.admincaster_feed_message.returnBody(-1) == "\[REDACTED\]")
|
||||
dat+="<FONT COLOR='maroon'>Invalid message body.</FONT><BR>"
|
||||
dat+="<FONT COLOR='maroon'>Invalid message body.</FONT><BR>"
|
||||
dat+="<BR><A href='?src=\ref[src];ac_setScreen=[3]'>Return</A><BR>"
|
||||
if(7)
|
||||
dat+="<B><FONT COLOR='maroon'>ERROR: Could not submit Feed Channel to Network.</B></FONT><HR><BR>"
|
||||
if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]")
|
||||
dat+="<FONT COLOR='maroon'>Invalid channel name.</FONT><BR>"
|
||||
dat+="<FONT COLOR='maroon'>Invalid channel name.</FONT><BR>"
|
||||
var/check = 0
|
||||
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
|
||||
if(FC.channel_name == src.admincaster_feed_channel.channel_name)
|
||||
check = 1
|
||||
break
|
||||
if(check)
|
||||
dat+="<FONT COLOR='maroon'>Channel name already in use.</FONT><BR>"
|
||||
dat+="<FONT COLOR='maroon'>Channel name already in use.</FONT><BR>"
|
||||
dat+="<BR><A href='?src=\ref[src];ac_setScreen=[2]'>Return</A><BR>"
|
||||
if(9)
|
||||
dat+="<B>[admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[created by: <FONT COLOR='maroon'>[admincaster_feed_channel.returnAuthor(-1)]</FONT>\]</FONT><HR>"
|
||||
@@ -354,9 +356,9 @@
|
||||
if(16)
|
||||
dat+="<B><FONT COLOR='maroon'>ERROR: Wanted Issue rejected by Network.</B></FONT><HR><BR>"
|
||||
if(src.admincaster_wanted_message.criminal =="" || src.admincaster_wanted_message.criminal == "\[REDACTED\]")
|
||||
dat+="<FONT COLOR='maroon'>Invalid name for person wanted.</FONT><BR>"
|
||||
dat+="<FONT COLOR='maroon'>Invalid name for person wanted.</FONT><BR>"
|
||||
if(src.admincaster_wanted_message.body == "" || src.admincaster_wanted_message.body == "\[REDACTED\]")
|
||||
dat+="<FONT COLOR='maroon'>Invalid description.</FONT><BR>"
|
||||
dat+="<FONT COLOR='maroon'>Invalid description.</FONT><BR>"
|
||||
dat+="<BR><A href='?src=\ref[src];ac_setScreen=[0]'>Return</A><BR>"
|
||||
if(17)
|
||||
dat+="<B>Wanted Issue successfully deleted from Circulation</B><BR>"
|
||||
@@ -426,14 +428,12 @@
|
||||
var result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
|
||||
if(result)
|
||||
SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
switch(result)
|
||||
if("Regular Restart")
|
||||
SSticker.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
|
||||
if("Hard Restart (No Delay, No Feeback Reason)")
|
||||
world.Reboot()
|
||||
if("Hardest Restart (No actions, just reboot)")
|
||||
|
||||
world.Reboot(fast_track = TRUE)
|
||||
if("Service Restart (Force restart DD)")
|
||||
GLOB.reboot_mode = REBOOT_MODE_HARD
|
||||
@@ -694,7 +694,7 @@
|
||||
to_chat(usr, "<b>AI [key_name(S, usr)]'s laws:</b>")
|
||||
else if(iscyborg(S))
|
||||
var/mob/living/silicon/robot/R = S
|
||||
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independant)"]: laws:</b>")
|
||||
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independent)"]: laws:</b>")
|
||||
else if (ispAI(S))
|
||||
to_chat(usr, "<b>pAI [key_name(S, usr)]'s laws:</b>")
|
||||
else
|
||||
@@ -830,4 +830,4 @@
|
||||
string = pick(
|
||||
"Admin login: [key_name(src)]")
|
||||
if(string)
|
||||
message_admins("[string]")
|
||||
message_admins("[string]")
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/atom/proc/investigate_log(message, subject)
|
||||
if(!message || !subject)
|
||||
return
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
|
||||
|
||||
|
||||
/atom/proc/investigate_log(message, subject)
|
||||
if(!message || !subject)
|
||||
return
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
|
||||
|
||||
|
||||
/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY) )
|
||||
set name = "Investigate"
|
||||
set category = "Admin"
|
||||
if(!holder)
|
||||
return
|
||||
switch(subject)
|
||||
if("notes, memos, watchlist")
|
||||
browse_messages()
|
||||
else
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
if(!fexists(F))
|
||||
to_chat(src, "<span class='danger'>No [subject] logfile was found.</span>")
|
||||
return
|
||||
src << browse(F,"window=investigate[subject];size=800x300")
|
||||
set name = "Investigate"
|
||||
set category = "Admin"
|
||||
if(!holder)
|
||||
return
|
||||
switch(subject)
|
||||
if("notes, memos, watchlist")
|
||||
browse_messages()
|
||||
else
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
if(!fexists(F))
|
||||
to_chat(src, "<span class='danger'>No [subject] logfile was found.</span>")
|
||||
return
|
||||
src << browse(F,"window=investigate[subject];size=800x300")
|
||||
|
||||
+378
-372
@@ -1,382 +1,388 @@
|
||||
GLOBAL_LIST_EMPTY(admin_ranks) //list of all admin_rank datums
|
||||
GLOBAL_PROTECT(admin_ranks)
|
||||
|
||||
/datum/admin_rank
|
||||
var/name = "NoRank"
|
||||
var/rights = 0
|
||||
var/list/adds
|
||||
var/list/subs
|
||||
|
||||
/datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs)
|
||||
name = init_name
|
||||
switch(name)
|
||||
if("Removed",null,"")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
throw EXCEPTION("invalid admin-rank name")
|
||||
return
|
||||
if(init_rights)
|
||||
rights = init_rights
|
||||
if(!init_adds)
|
||||
init_adds = list()
|
||||
if(!init_subs)
|
||||
init_subs = list()
|
||||
adds = init_adds
|
||||
subs = init_subs
|
||||
|
||||
/datum/admin_rank/vv_edit_var(var_name, var_value)
|
||||
return FALSE
|
||||
|
||||
/proc/admin_keyword_to_flag(word, previous_rights=0)
|
||||
var/flag = 0
|
||||
switch(ckey(word))
|
||||
if("buildmode","build")
|
||||
flag = R_BUILDMODE
|
||||
if("admin")
|
||||
flag = R_ADMIN
|
||||
if("ban")
|
||||
flag = R_BAN
|
||||
if("fun")
|
||||
flag = R_FUN
|
||||
if("server")
|
||||
flag = R_SERVER
|
||||
if("debug")
|
||||
flag = R_DEBUG
|
||||
if("permissions","rights")
|
||||
flag = R_PERMISSIONS
|
||||
if("possess")
|
||||
flag = R_POSSESS
|
||||
if("stealth")
|
||||
flag = R_STEALTH
|
||||
if("rejuv","rejuvinate")
|
||||
flag = R_REJUVINATE
|
||||
if("varedit")
|
||||
flag = R_VAREDIT
|
||||
if("everything","host","all")
|
||||
flag = 65535
|
||||
if("sound","sounds")
|
||||
flag = R_SOUNDS
|
||||
if("spawn","create")
|
||||
flag = R_SPAWN
|
||||
if("@","prev")
|
||||
flag = previous_rights
|
||||
return flag
|
||||
|
||||
/proc/admin_keyword_to_path(word) //use this with verb keywords eg +/client/proc/blah
|
||||
return text2path(copytext(word, 2, findtext(word, " ", 2, 0)))
|
||||
|
||||
// Adds/removes rights to this admin_rank
|
||||
/datum/admin_rank/proc/process_keyword(word, previous_rights=0)
|
||||
var/flag = admin_keyword_to_flag(word, previous_rights)
|
||||
if(flag)
|
||||
switch(text2ascii(word,1))
|
||||
if(43)
|
||||
rights |= flag //+
|
||||
if(45)
|
||||
rights &= ~flag //-
|
||||
else
|
||||
//isn't a keyword so maybe it's a verbpath?
|
||||
var/path = admin_keyword_to_path(word)
|
||||
if(path)
|
||||
switch(text2ascii(word,1))
|
||||
if(43)
|
||||
if(!subs.Remove(path))
|
||||
adds += path //+
|
||||
if(45)
|
||||
if(!adds.Remove(path))
|
||||
subs += path //-
|
||||
|
||||
// Checks for (keyword-formatted) rights on this admin
|
||||
/datum/admins/proc/check_keyword(word)
|
||||
var/flag = admin_keyword_to_flag(word)
|
||||
if(flag)
|
||||
return ((rank.rights & flag) == flag) //true only if right has everything in flag
|
||||
else
|
||||
var/path = admin_keyword_to_path(word)
|
||||
for(var/i in owner.verbs) //this needs to be a foreach loop for some reason. in operator and verbs.Find() don't work
|
||||
if(i == path)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//load our rank - > rights associations
|
||||
/proc/load_admin_ranks()
|
||||
GLOB.admin_ranks.Cut()
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
var/previous_rights = 0
|
||||
//load text from file and process each line seperately
|
||||
GLOBAL_LIST_EMPTY(admin_ranks) //list of all admin_rank datums
|
||||
GLOBAL_PROTECT(admin_ranks)
|
||||
|
||||
/datum/admin_rank
|
||||
var/name = "NoRank"
|
||||
var/rights = 0
|
||||
var/list/adds
|
||||
var/list/subs
|
||||
|
||||
/datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs)
|
||||
name = init_name
|
||||
switch(name)
|
||||
if("Removed",null,"")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
throw EXCEPTION("invalid admin-rank name")
|
||||
return
|
||||
if(init_rights)
|
||||
rights = init_rights
|
||||
if(!init_adds)
|
||||
init_adds = list()
|
||||
if(!init_subs)
|
||||
init_subs = list()
|
||||
adds = init_adds
|
||||
subs = init_subs
|
||||
|
||||
/datum/admin_rank/vv_edit_var(var_name, var_value)
|
||||
return FALSE
|
||||
|
||||
#if DM_VERSION > 512
|
||||
#error remove the rejuv keyword from this proc
|
||||
#endif
|
||||
/proc/admin_keyword_to_flag(word, previous_rights=0)
|
||||
var/flag = 0
|
||||
switch(ckey(word))
|
||||
if("buildmode","build")
|
||||
flag = R_BUILDMODE
|
||||
if("admin")
|
||||
flag = R_ADMIN
|
||||
if("ban")
|
||||
flag = R_BAN
|
||||
if("fun")
|
||||
flag = R_FUN
|
||||
if("server")
|
||||
flag = R_SERVER
|
||||
if("debug")
|
||||
flag = R_DEBUG
|
||||
if("permissions","rights")
|
||||
flag = R_PERMISSIONS
|
||||
if("possess")
|
||||
flag = R_POSSESS
|
||||
if("stealth")
|
||||
flag = R_STEALTH
|
||||
if("poll")
|
||||
flag = R_POLL
|
||||
if("varedit")
|
||||
flag = R_VAREDIT
|
||||
if("everything","host","all")
|
||||
flag = 65535
|
||||
if("sound","sounds")
|
||||
flag = R_SOUNDS
|
||||
if("spawn","create")
|
||||
flag = R_SPAWN
|
||||
if("@","prev")
|
||||
flag = previous_rights
|
||||
if("rejuv","rejuvinate")
|
||||
stack_trace("Legacy keyword rejuvinate used defaulting to R_ADMIN")
|
||||
flag = R_ADMIN
|
||||
return flag
|
||||
|
||||
/proc/admin_keyword_to_path(word) //use this with verb keywords eg +/client/proc/blah
|
||||
return text2path(copytext(word, 2, findtext(word, " ", 2, 0)))
|
||||
|
||||
// Adds/removes rights to this admin_rank
|
||||
/datum/admin_rank/proc/process_keyword(word, previous_rights=0)
|
||||
var/flag = admin_keyword_to_flag(word, previous_rights)
|
||||
if(flag)
|
||||
switch(text2ascii(word,1))
|
||||
if(43)
|
||||
rights |= flag //+
|
||||
if(45)
|
||||
rights &= ~flag //-
|
||||
else
|
||||
//isn't a keyword so maybe it's a verbpath?
|
||||
var/path = admin_keyword_to_path(word)
|
||||
if(path)
|
||||
switch(text2ascii(word,1))
|
||||
if(43)
|
||||
if(!subs.Remove(path))
|
||||
adds += path //+
|
||||
if(45)
|
||||
if(!adds.Remove(path))
|
||||
subs += path //-
|
||||
|
||||
// Checks for (keyword-formatted) rights on this admin
|
||||
/datum/admins/proc/check_keyword(word)
|
||||
var/flag = admin_keyword_to_flag(word)
|
||||
if(flag)
|
||||
return ((rank.rights & flag) == flag) //true only if right has everything in flag
|
||||
else
|
||||
var/path = admin_keyword_to_path(word)
|
||||
for(var/i in owner.verbs) //this needs to be a foreach loop for some reason. in operator and verbs.Find() don't work
|
||||
if(i == path)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//load our rank - > rights associations
|
||||
/proc/load_admin_ranks()
|
||||
GLOB.admin_ranks.Cut()
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
var/previous_rights = 0
|
||||
//load text from file and process each line seperately
|
||||
for(var/line in world.file2list("config/admin_ranks.txt"))
|
||||
if(!line)
|
||||
continue
|
||||
if(findtextEx(line,"#",1,2))
|
||||
continue
|
||||
|
||||
var/next = findtext(line, "=")
|
||||
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next)))
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
|
||||
var/prev = findchar(line, "+-", next, 0)
|
||||
while(prev)
|
||||
next = findchar(line, "+-", prev + 1, 0)
|
||||
R.process_keyword(copytext(line, prev, next), previous_rights)
|
||||
prev = next
|
||||
|
||||
previous_rights = R.rights
|
||||
else
|
||||
if(!line)
|
||||
continue
|
||||
if(findtextEx(line,"#",1,2))
|
||||
continue
|
||||
|
||||
var/next = findtext(line, "=")
|
||||
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next)))
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
|
||||
var/prev = findchar(line, "+-", next, 0)
|
||||
while(prev)
|
||||
next = findchar(line, "+-", prev + 1, 0)
|
||||
R.process_keyword(copytext(line, prev, next), previous_rights)
|
||||
prev = next
|
||||
|
||||
previous_rights = R.rights
|
||||
else
|
||||
if(!SSdbcore.Connect())
|
||||
log_world("Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
|
||||
log_world("Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
|
||||
GLOB.world_game_log << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
|
||||
config.admin_legacy_system = 1
|
||||
load_admin_ranks()
|
||||
return
|
||||
|
||||
config.admin_legacy_system = 1
|
||||
load_admin_ranks()
|
||||
return
|
||||
|
||||
var/datum/DBQuery/query_load_admin_ranks = SSdbcore.NewQuery("SELECT rank, flags FROM [format_table_name("admin_ranks")]")
|
||||
if(!query_load_admin_ranks.Execute())
|
||||
return
|
||||
while(query_load_admin_ranks.NextRow())
|
||||
var/rank_name = ckeyEx(query_load_admin_ranks.item[1])
|
||||
var/flags = query_load_admin_ranks.item[2]
|
||||
if(istext(flags))
|
||||
flags = text2num(flags)
|
||||
var/datum/admin_rank/R = new(rank_name, flags)
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Permission Sets Built:\n"
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
msg += "\t[R.name]"
|
||||
var/rights = rights2text(R.rights,"\n\t\t",R.adds,R.subs)
|
||||
if(rights)
|
||||
msg += "\t\t[rights]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
|
||||
/proc/load_admins(target = null)
|
||||
//clear the datums references
|
||||
if(!target)
|
||||
GLOB.admin_datums.Cut()
|
||||
for(var/client/C in GLOB.admins)
|
||||
C.remove_admin_verbs()
|
||||
C.holder = null
|
||||
GLOB.admins.Cut()
|
||||
load_admin_ranks()
|
||||
//Clear profile access
|
||||
for(var/A in world.GetConfig("admin"))
|
||||
world.SetConfig("APP/admin", A, null)
|
||||
|
||||
var/list/rank_names = list()
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
rank_names[R.name] = R
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
//load text from file
|
||||
if(!query_load_admin_ranks.Execute())
|
||||
return
|
||||
while(query_load_admin_ranks.NextRow())
|
||||
var/rank_name = ckeyEx(query_load_admin_ranks.item[1])
|
||||
var/flags = query_load_admin_ranks.item[2]
|
||||
if(istext(flags))
|
||||
flags = text2num(flags)
|
||||
var/datum/admin_rank/R = new(rank_name, flags)
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Permission Sets Built:\n"
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
msg += "\t[R.name]"
|
||||
var/rights = rights2text(R.rights,"\n\t\t",R.adds,R.subs)
|
||||
if(rights)
|
||||
msg += "\t\t[rights]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
|
||||
/proc/load_admins(target = null)
|
||||
//clear the datums references
|
||||
if(!target)
|
||||
GLOB.admin_datums.Cut()
|
||||
for(var/client/C in GLOB.admins)
|
||||
C.remove_admin_verbs()
|
||||
C.holder = null
|
||||
GLOB.admins.Cut()
|
||||
load_admin_ranks()
|
||||
//Clear profile access
|
||||
for(var/A in world.GetConfig("admin"))
|
||||
world.SetConfig("APP/admin", A, null)
|
||||
|
||||
var/list/rank_names = list()
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
rank_names[R.name] = R
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
//load text from file
|
||||
var/list/lines = world.file2list("config/admins.txt")
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in lines)
|
||||
if(!length(line))
|
||||
continue
|
||||
if(findtextEx(line, "#", 1, 2))
|
||||
continue
|
||||
|
||||
var/list/entry = splittext(line, "=")
|
||||
if(entry.len < 2)
|
||||
continue
|
||||
|
||||
var/ckey = ckey(entry[1])
|
||||
var/rank = ckeyEx(entry[2])
|
||||
if(!ckey || !rank || (target && ckey != target))
|
||||
continue
|
||||
|
||||
var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use
|
||||
if(!D)
|
||||
continue //will occur if an invalid rank is provided
|
||||
if(D.rank.rights & R_DEBUG) //grant profile access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
else
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in lines)
|
||||
if(!length(line))
|
||||
continue
|
||||
if(findtextEx(line, "#", 1, 2))
|
||||
continue
|
||||
|
||||
var/list/entry = splittext(line, "=")
|
||||
if(entry.len < 2)
|
||||
continue
|
||||
|
||||
var/ckey = ckey(entry[1])
|
||||
var/rank = ckeyEx(entry[2])
|
||||
if(!ckey || !rank || (target && ckey != target))
|
||||
continue
|
||||
|
||||
var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use
|
||||
if(!D)
|
||||
continue //will occur if an invalid rank is provided
|
||||
if(D.rank.rights & R_DEBUG) //grant profile access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
else
|
||||
if(!SSdbcore.Connect())
|
||||
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
GLOB.world_game_log << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
var/datum/DBQuery/query_load_admins = SSdbcore.NewQuery("SELECT ckey, rank FROM [format_table_name("admin")]")
|
||||
if(!query_load_admins.Execute())
|
||||
return
|
||||
while(query_load_admins.NextRow())
|
||||
var/ckey = ckey(query_load_admins.item[1])
|
||||
var/rank = ckeyEx(query_load_admins.item[2])
|
||||
if(target && ckey != target)
|
||||
continue
|
||||
|
||||
if(rank_names[rank] == null)
|
||||
WARNING("Admin rank ([rank]) does not exist.")
|
||||
continue
|
||||
|
||||
var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use
|
||||
if(!D)
|
||||
continue //will occur if an invalid rank is provided
|
||||
if(D.rank.rights & R_DEBUG) //grant profile access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Admins Built:\n"
|
||||
for(var/ckey in GLOB.admin_datums)
|
||||
var/datum/admins/D = GLOB.admin_datums[ckey]
|
||||
msg += "\t[ckey] - [D.rank.name]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TESTING
|
||||
/client/verb/changerank(newrank in GLOB.admin_ranks)
|
||||
if(holder)
|
||||
holder.rank = newrank
|
||||
else
|
||||
holder = new /datum/admins(newrank, ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
|
||||
/client/verb/changerights(newrights as num)
|
||||
if(holder)
|
||||
holder.rank.rights = newrights
|
||||
else
|
||||
holder = new /datum/admins("testing", newrights, ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
#endif
|
||||
|
||||
/datum/admins/proc/edit_rights_topic(list/href_list)
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
message_admins("[key_name_admin(usr)] attempted to edit the admin permissions without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to edit the admin permissions without sufficient rights.")
|
||||
return
|
||||
|
||||
var/adm_ckey
|
||||
var/task = href_list["editrights"]
|
||||
switch(task)
|
||||
if("add")
|
||||
var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null)
|
||||
if(!new_ckey)
|
||||
return
|
||||
if(new_ckey in GLOB.admin_datums)
|
||||
to_chat(usr, "<font color='red'>Error: Topic 'editrights': [new_ckey] is already an admin</font>")
|
||||
return
|
||||
adm_ckey = new_ckey
|
||||
task = "rank"
|
||||
else
|
||||
adm_ckey = ckey(href_list["ckey"])
|
||||
if(!adm_ckey)
|
||||
to_chat(usr, "<font color='red'>Error: Topic 'editrights': No valid ckey</font>")
|
||||
return
|
||||
|
||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||
|
||||
switch(task)
|
||||
if("remove")
|
||||
if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes")
|
||||
if(!D)
|
||||
return
|
||||
if(!check_if_greater_rights_than_holder(D))
|
||||
message_admins("[key_name_admin(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.")
|
||||
return
|
||||
GLOB.admin_datums -= adm_ckey
|
||||
D.disassociate()
|
||||
|
||||
updateranktodb(adm_ckey, "player")
|
||||
message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list")
|
||||
log_admin("[key_name(usr)] removed [adm_ckey] from the admins list")
|
||||
log_admin_rank_modification(adm_ckey, "Removed")
|
||||
|
||||
if("rank")
|
||||
var/datum/admin_rank/R
|
||||
|
||||
var/list/rank_names = list("*New Rank*")
|
||||
for(R in GLOB.admin_ranks)
|
||||
rank_names[R.name] = R
|
||||
|
||||
var/new_rank = input("Please select a rank", "New rank", null, null) as null|anything in rank_names
|
||||
|
||||
switch(new_rank)
|
||||
if(null)
|
||||
return
|
||||
if("*New Rank*")
|
||||
new_rank = ckeyEx(input("Please input a new rank", "New custom rank", null, null) as null|text)
|
||||
if(!new_rank)
|
||||
return
|
||||
|
||||
if(D)
|
||||
if(!check_if_greater_rights_than_holder(D))
|
||||
message_admins("[key_name_admin(usr)] attempted to change the rank of [adm_ckey] to [new_rank] without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to change the rank of [adm_ckey] to [new_rank] without sufficient rights.")
|
||||
return
|
||||
|
||||
R = rank_names[new_rank]
|
||||
if(!R) //rank with that name doesn't exist yet - make it
|
||||
if(D)
|
||||
R = new(new_rank, D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
||||
else
|
||||
R = new(new_rank) //blank new admin_rank
|
||||
GLOB.admin_ranks += R
|
||||
|
||||
if(D) //they were previously an admin
|
||||
D.disassociate() //existing admin needs to be disassociated
|
||||
D.rank = R //set the admin_rank as our rank
|
||||
else
|
||||
D = new(R,adm_ckey) //new admin
|
||||
|
||||
var/client/C = GLOB.directory[adm_ckey] //find the client with the specified ckey (if they are logged in)
|
||||
D.associate(C) //link up with the client and add verbs
|
||||
|
||||
updateranktodb(adm_ckey, new_rank)
|
||||
message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
||||
log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
||||
log_admin_rank_modification(adm_ckey, new_rank)
|
||||
|
||||
if("permissions")
|
||||
if(!D)
|
||||
return //they're not an admin!
|
||||
|
||||
var/keyword = input("Input permission keyword (one at a time):\ne.g. +BAN or -FUN or +/client/proc/someverb", "Permission toggle", null, null) as null|text
|
||||
if(!keyword)
|
||||
return
|
||||
|
||||
if(!check_keyword(keyword) || !check_if_greater_rights_than_holder(D))
|
||||
message_admins("[key_name_admin(usr)] attempted to give [adm_ckey] the keyword [keyword] without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to give [adm_ckey] the keyword [keyword] without sufficient rights.")
|
||||
return
|
||||
|
||||
D.disassociate()
|
||||
|
||||
if(!findtext(D.rank.name, "([adm_ckey])")) //not a modified subrank, need to duplicate the admin_rank datum to prevent modifying others too
|
||||
D.rank = new("[D.rank.name]([adm_ckey])", D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
||||
//we don't add this clone to the admin_ranks list, as it is unique to that ckey
|
||||
|
||||
D.rank.process_keyword(keyword)
|
||||
|
||||
var/client/C = GLOB.directory[adm_ckey] //find the client with the specified ckey (if they are logged in)
|
||||
D.associate(C) //link up with the client and add verbs
|
||||
|
||||
message_admins("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
||||
log_admin("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
||||
log_admin_permission_modification(adm_ckey, D.rank.rights)
|
||||
|
||||
edit_admin_permissions()
|
||||
|
||||
/datum/admins/proc/updateranktodb(ckey,newrank)
|
||||
if(!query_load_admins.Execute())
|
||||
return
|
||||
while(query_load_admins.NextRow())
|
||||
var/ckey = ckey(query_load_admins.item[1])
|
||||
var/rank = ckeyEx(query_load_admins.item[2])
|
||||
if(target && ckey != target)
|
||||
continue
|
||||
|
||||
if(rank_names[rank] == null)
|
||||
WARNING("Admin rank ([rank]) does not exist.")
|
||||
continue
|
||||
|
||||
var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use
|
||||
if(!D)
|
||||
continue //will occur if an invalid rank is provided
|
||||
if(D.rank.rights & R_DEBUG) //grant profile access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Admins Built:\n"
|
||||
for(var/ckey in GLOB.admin_datums)
|
||||
var/datum/admins/D = GLOB.admin_datums[ckey]
|
||||
msg += "\t[ckey] - [D.rank.name]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TESTING
|
||||
/client/verb/changerank(newrank in GLOB.admin_ranks)
|
||||
if(holder)
|
||||
holder.rank = newrank
|
||||
else
|
||||
holder = new /datum/admins(newrank, ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
|
||||
/client/verb/changerights(newrights as num)
|
||||
if(holder)
|
||||
holder.rank.rights = newrights
|
||||
else
|
||||
holder = new /datum/admins("testing", newrights, ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
#endif
|
||||
|
||||
/datum/admins/proc/edit_rights_topic(list/href_list)
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
message_admins("[key_name_admin(usr)] attempted to edit the admin permissions without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to edit the admin permissions without sufficient rights.")
|
||||
return
|
||||
|
||||
var/adm_ckey
|
||||
var/task = href_list["editrights"]
|
||||
switch(task)
|
||||
if("add")
|
||||
var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null)
|
||||
if(!new_ckey)
|
||||
return
|
||||
if(new_ckey in GLOB.admin_datums)
|
||||
to_chat(usr, "<font color='red'>Error: Topic 'editrights': [new_ckey] is already an admin</font>")
|
||||
return
|
||||
adm_ckey = new_ckey
|
||||
task = "rank"
|
||||
else
|
||||
adm_ckey = ckey(href_list["ckey"])
|
||||
if(!adm_ckey)
|
||||
to_chat(usr, "<font color='red'>Error: Topic 'editrights': No valid ckey</font>")
|
||||
return
|
||||
|
||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||
|
||||
switch(task)
|
||||
if("remove")
|
||||
if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes")
|
||||
if(!D)
|
||||
return
|
||||
if(!check_if_greater_rights_than_holder(D))
|
||||
message_admins("[key_name_admin(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.")
|
||||
return
|
||||
GLOB.admin_datums -= adm_ckey
|
||||
D.disassociate()
|
||||
|
||||
updateranktodb(adm_ckey, "player")
|
||||
message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list")
|
||||
log_admin("[key_name(usr)] removed [adm_ckey] from the admins list")
|
||||
log_admin_rank_modification(adm_ckey, "Removed")
|
||||
|
||||
if("rank")
|
||||
var/datum/admin_rank/R
|
||||
|
||||
var/list/rank_names = list("*New Rank*")
|
||||
for(R in GLOB.admin_ranks)
|
||||
rank_names[R.name] = R
|
||||
|
||||
var/new_rank = input("Please select a rank", "New rank", null, null) as null|anything in rank_names
|
||||
|
||||
switch(new_rank)
|
||||
if(null)
|
||||
return
|
||||
if("*New Rank*")
|
||||
new_rank = ckeyEx(input("Please input a new rank", "New custom rank", null, null) as null|text)
|
||||
if(!new_rank)
|
||||
return
|
||||
|
||||
if(D)
|
||||
if(!check_if_greater_rights_than_holder(D))
|
||||
message_admins("[key_name_admin(usr)] attempted to change the rank of [adm_ckey] to [new_rank] without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to change the rank of [adm_ckey] to [new_rank] without sufficient rights.")
|
||||
return
|
||||
|
||||
R = rank_names[new_rank]
|
||||
if(!R) //rank with that name doesn't exist yet - make it
|
||||
if(D)
|
||||
R = new(new_rank, D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
||||
else
|
||||
R = new(new_rank) //blank new admin_rank
|
||||
GLOB.admin_ranks += R
|
||||
|
||||
if(D) //they were previously an admin
|
||||
D.disassociate() //existing admin needs to be disassociated
|
||||
D.rank = R //set the admin_rank as our rank
|
||||
else
|
||||
D = new(R,adm_ckey) //new admin
|
||||
|
||||
var/client/C = GLOB.directory[adm_ckey] //find the client with the specified ckey (if they are logged in)
|
||||
D.associate(C) //link up with the client and add verbs
|
||||
|
||||
updateranktodb(adm_ckey, new_rank)
|
||||
message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
||||
log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
||||
log_admin_rank_modification(adm_ckey, new_rank)
|
||||
|
||||
if("permissions")
|
||||
if(!D)
|
||||
return //they're not an admin!
|
||||
|
||||
var/keyword = input("Input permission keyword (one at a time):\ne.g. +BAN or -FUN or +/client/proc/someverb", "Permission toggle", null, null) as null|text
|
||||
if(!keyword)
|
||||
return
|
||||
|
||||
if(!check_keyword(keyword) || !check_if_greater_rights_than_holder(D))
|
||||
message_admins("[key_name_admin(usr)] attempted to give [adm_ckey] the keyword [keyword] without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to give [adm_ckey] the keyword [keyword] without sufficient rights.")
|
||||
return
|
||||
|
||||
D.disassociate()
|
||||
|
||||
if(!findtext(D.rank.name, "([adm_ckey])")) //not a modified subrank, need to duplicate the admin_rank datum to prevent modifying others too
|
||||
D.rank = new("[D.rank.name]([adm_ckey])", D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
||||
//we don't add this clone to the admin_ranks list, as it is unique to that ckey
|
||||
|
||||
D.rank.process_keyword(keyword)
|
||||
|
||||
var/client/C = GLOB.directory[adm_ckey] //find the client with the specified ckey (if they are logged in)
|
||||
D.associate(C) //link up with the client and add verbs
|
||||
|
||||
message_admins("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
||||
log_admin("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
||||
log_admin_permission_modification(adm_ckey, D.rank.rights)
|
||||
|
||||
edit_admin_permissions()
|
||||
|
||||
/datum/admins/proc/updateranktodb(ckey,newrank)
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/sql_admin_rank = sanitizeSQL(newrank)
|
||||
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/sql_admin_rank = sanitizeSQL(newrank)
|
||||
|
||||
var/datum/DBQuery/query_admin_rank_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'")
|
||||
query_admin_rank_update.Execute()
|
||||
query_admin_rank_update.Execute()
|
||||
|
||||
@@ -12,13 +12,10 @@ GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
|
||||
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
|
||||
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
|
||||
/client/proc/secrets,
|
||||
/client/proc/restart_controller,
|
||||
/client/proc/reload_admins,
|
||||
/client/proc/reload_mentors,
|
||||
/client/proc/reestablish_db_connection,/*reattempt a connection to the database*/
|
||||
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
|
||||
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
|
||||
// /client/proc/mentor_memo, /*mentor memo system. show/delete/write. +SERVER needed to delete mentor memos of others*/
|
||||
/client/proc/cmd_admin_ticket_panel,
|
||||
/client/proc/stop_sounds
|
||||
)
|
||||
@@ -69,7 +66,8 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
|
||||
/client/proc/open_shuttle_manipulator, /* Opens shuttle manipulator UI */
|
||||
/client/proc/deadchat,
|
||||
/client/proc/toggleprayers,
|
||||
/client/proc/toggleadminhelpsound
|
||||
/client/proc/toggleadminhelpsound,
|
||||
/client/proc/respawn_character
|
||||
)
|
||||
GLOBAL_PROTECT(admin_verbs_ban)
|
||||
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel,/client/proc/DB_ban_panel,/client/proc/stickybanpanel))
|
||||
@@ -154,19 +152,15 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
|
||||
/client/proc/clear_dynamic_transit,
|
||||
/client/proc/toggle_medal_disable,
|
||||
/client/proc/view_runtimes,
|
||||
//citadel code
|
||||
/client/proc/give_humans_genitals,
|
||||
/client/proc/test_mammal_overlays,
|
||||
/client/proc/pump_random_event,
|
||||
/client/proc/cmd_display_init_log
|
||||
)
|
||||
|
||||
GLOBAL_PROTECT(admin_verbs_possess)
|
||||
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess,/proc/release))
|
||||
GLOBAL_PROTECT(admin_verbs_permissions)
|
||||
GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions,/client/proc/create_poll))
|
||||
GLOBAL_PROTECT(admin_verbs_rejuv)
|
||||
GLOBAL_LIST_INIT(admin_verbs_rejuv, list(/client/proc/respawn_character))
|
||||
GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions))
|
||||
GLOBAL_PROTECT(admin_verbs_poll)
|
||||
GLOBAL_LIST_INIT(admin_verbs_poll, list(/client/proc/create_poll))
|
||||
|
||||
//verbs which can be hidden - needs work
|
||||
GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
@@ -261,8 +255,8 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
verbs += GLOB.admin_verbs_permissions
|
||||
if(rights & R_STEALTH)
|
||||
verbs += /client/proc/stealth
|
||||
if(rights & R_REJUVINATE)
|
||||
verbs += GLOB.admin_verbs_rejuv
|
||||
if(rights & R_ADMIN)
|
||||
verbs += GLOB.admin_verbs_poll
|
||||
if(rights & R_SOUNDS)
|
||||
verbs += GLOB.admin_verbs_sounds
|
||||
if(rights & R_SPAWN)
|
||||
@@ -285,7 +279,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
GLOB.admin_verbs_possess,
|
||||
GLOB.admin_verbs_permissions,
|
||||
/client/proc/stealth,
|
||||
GLOB.admin_verbs_rejuv,
|
||||
GLOB.admin_verbs_poll,
|
||||
GLOB.admin_verbs_sounds,
|
||||
GLOB.admin_verbs_spawn,
|
||||
/*Debug verbs added by "show debug verbs"*/
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
//returns a reason if M is banned from rank, returns 0 otherwise
|
||||
/proc/jobban_isbanned(mob/M, rank)
|
||||
if(!M || !istype(M) || !M.ckey)
|
||||
return 0
|
||||
|
||||
//returns a reason if M is banned from rank, returns 0 otherwise
|
||||
/proc/jobban_isbanned(mob/M, rank)
|
||||
if(!M || !istype(M) || !M.ckey)
|
||||
return 0
|
||||
|
||||
if(!M.client) //no cache. fallback to a datum/DBQuery
|
||||
var/datum/DBQuery/query_jobban_check_ban = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(M.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[sanitizeSQL(rank)]'")
|
||||
if(!query_jobban_check_ban.warn_execute())
|
||||
return
|
||||
if(query_jobban_check_ban.NextRow())
|
||||
var/reason = query_jobban_check_ban.item[1]
|
||||
return reason ? reason : 1 //we don't want to return "" if there is no ban reason, as that would evaluate to false
|
||||
else
|
||||
return 0
|
||||
|
||||
if(!M.client.jobbancache)
|
||||
jobban_buildcache(M.client)
|
||||
|
||||
if(rank in M.client.jobbancache)
|
||||
var/reason = M.client.jobbancache[rank]
|
||||
return (reason) ? reason : 1 //see above for why we need to do this
|
||||
return 0
|
||||
|
||||
/proc/jobban_buildcache(client/C)
|
||||
if(C && istype(C))
|
||||
C.jobbancache = list()
|
||||
if(!query_jobban_check_ban.warn_execute())
|
||||
return
|
||||
if(query_jobban_check_ban.NextRow())
|
||||
var/reason = query_jobban_check_ban.item[1]
|
||||
return reason ? reason : 1 //we don't want to return "" if there is no ban reason, as that would evaluate to false
|
||||
else
|
||||
return 0
|
||||
|
||||
if(!M.client.jobbancache)
|
||||
jobban_buildcache(M.client)
|
||||
|
||||
if(rank in M.client.jobbancache)
|
||||
var/reason = M.client.jobbancache[rank]
|
||||
return (reason) ? reason : 1 //see above for why we need to do this
|
||||
return 0
|
||||
|
||||
/proc/jobban_buildcache(client/C)
|
||||
if(C && istype(C))
|
||||
C.jobbancache = list()
|
||||
var/datum/DBQuery/query_jobban_build_cache = SSdbcore.NewQuery("SELECT job, reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
if(!query_jobban_build_cache.warn_execute())
|
||||
return
|
||||
while(query_jobban_build_cache.NextRow())
|
||||
C.jobbancache[query_jobban_build_cache.item[1]] = query_jobban_build_cache.item[2]
|
||||
|
||||
/proc/ban_unban_log_save(var/formatted_log)
|
||||
text2file(formatted_log,"data/ban_unban_log.txt")
|
||||
if(!query_jobban_build_cache.warn_execute())
|
||||
return
|
||||
while(query_jobban_build_cache.NextRow())
|
||||
C.jobbancache[query_jobban_build_cache.item[1]] = query_jobban_build_cache.item[2]
|
||||
|
||||
/proc/ban_unban_log_save(var/formatted_log)
|
||||
text2file(formatted_log,"data/ban_unban_log.txt")
|
||||
|
||||
@@ -1,33 +1,11 @@
|
||||
/client/proc/create_poll()
|
||||
set name = "Create Poll"
|
||||
set category = "Special Verbs"
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
if(!check_rights(R_POLL))
|
||||
return
|
||||
if(!SSdbcore.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
var/returned = create_poll_function()
|
||||
if(returned)
|
||||
var/datum/DBQuery/query_check_option = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE pollid = [returned]")
|
||||
if(!query_check_option.warn_execute())
|
||||
return
|
||||
if(query_check_option.NextRow())
|
||||
var/datum/DBQuery/query_log_get = SSdbcore.NewQuery("SELECT polltype, question, adminonly FROM [format_table_name("poll_question")] WHERE id = [returned]")
|
||||
if(!query_log_get.warn_execute())
|
||||
return
|
||||
if(query_log_get.NextRow())
|
||||
var/polltype = query_log_get.item[1]
|
||||
var/question = query_log_get.item[2]
|
||||
var/adminonly = text2num(query_log_get.item[3])
|
||||
log_admin("[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]")
|
||||
message_admins("[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]<br>Question: [question]")
|
||||
else
|
||||
to_chat(src, "Poll question created without any options, poll will be deleted.")
|
||||
var/datum/DBQuery/query_del_poll = SSdbcore.NewQuery("DELETE FROM [format_table_name("poll_question")] WHERE id = [returned]")
|
||||
if(!query_del_poll.warn_execute())
|
||||
return
|
||||
|
||||
/client/proc/create_poll_function()
|
||||
var/polltype = input("Choose poll type.","Poll Type") in list("Single Option","Text Reply","Rating","Multiple Choice", "Instant Runoff Voting")|null
|
||||
var/choice_amount = 0
|
||||
switch(polltype)
|
||||
@@ -40,7 +18,9 @@
|
||||
if("Multiple Choice")
|
||||
polltype = POLLTYPE_MULTI
|
||||
choice_amount = input("How many choices should be allowed?","Select choice amount") as num|null
|
||||
if(!choice_amount)
|
||||
if(choice_amount == 0)
|
||||
to_chat(src, "Multiple choice poll must have at least one choice allowed.")
|
||||
else if (choice_amount == null)
|
||||
return
|
||||
if ("Instant Runoff Voting")
|
||||
polltype = POLLTYPE_IRV
|
||||
@@ -51,22 +31,15 @@
|
||||
if(!endtime)
|
||||
return
|
||||
endtime = sanitizeSQL(endtime)
|
||||
var/datum/DBQuery/query_validate_time = SSdbcore.NewQuery("SELECT STR_TO_DATE('[endtime]','%Y-%c-%d %T')")
|
||||
var/datum/DBQuery/query_validate_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[endtime]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[endtime]','%Y-%c-%d %T'), 0)")
|
||||
if(!query_validate_time.warn_execute())
|
||||
return
|
||||
if(query_validate_time.NextRow())
|
||||
var/checktime = text2num(query_validate_time.item[1])
|
||||
if(!checktime)
|
||||
to_chat(src, "Datetime entered is improperly formatted or not later than current server time.")
|
||||
return
|
||||
endtime = query_validate_time.item[1]
|
||||
if(!endtime)
|
||||
to_chat(src, "Datetime entered is invalid.")
|
||||
return
|
||||
var/datum/DBQuery/query_time_later = SSdbcore.NewQuery("SELECT TIMESTAMP('[endtime]') < NOW()")
|
||||
if(!query_time_later.warn_execute())
|
||||
return
|
||||
if(query_time_later.NextRow())
|
||||
var/checklate = text2num(query_time_later.item[1])
|
||||
if(checklate)
|
||||
to_chat(src, "Datetime entered is not later than current server time.")
|
||||
return
|
||||
var/adminonly
|
||||
switch(alert("Admin only poll?",,"Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
@@ -88,72 +61,77 @@
|
||||
if(!question)
|
||||
return
|
||||
question = sanitizeSQL(question)
|
||||
var/list/sql_option_list = list()
|
||||
if(polltype != POLLTYPE_TEXT)
|
||||
var/add_option = 1
|
||||
while(add_option)
|
||||
var/option = input("Write your option","Option") as message|null
|
||||
if(!option)
|
||||
return
|
||||
option = sanitizeSQL(option)
|
||||
var/default_percentage_calc
|
||||
if(polltype != POLLTYPE_IRV)
|
||||
switch(alert("Should this option be included by default when poll result percentages are generated?",,"Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
default_percentage_calc = 1
|
||||
if("No")
|
||||
default_percentage_calc = 0
|
||||
else
|
||||
return
|
||||
var/minval = 0
|
||||
var/maxval = 0
|
||||
var/descmin = ""
|
||||
var/descmid = ""
|
||||
var/descmax = ""
|
||||
if(polltype == POLLTYPE_RATING)
|
||||
minval = input("Set minimum rating value.","Minimum rating") as num|null
|
||||
if(minval)
|
||||
minval = sanitizeSQL(minval)
|
||||
else if(minval == null)
|
||||
return
|
||||
maxval = input("Set maximum rating value.","Maximum rating") as num|null
|
||||
if(maxval)
|
||||
maxval = sanitizeSQL(maxval)
|
||||
if(minval >= maxval)
|
||||
to_chat(src, "Maximum rating value can't be less than or equal to minimum rating value")
|
||||
continue
|
||||
else if(maxval == null)
|
||||
return
|
||||
descmin = input("Optional: Set description for minimum rating","Minimum rating description") as message|null
|
||||
if(descmin)
|
||||
descmin = sanitizeSQL(descmin)
|
||||
else if(descmin == null)
|
||||
return
|
||||
descmid = input("Optional: Set description for median rating","Median rating description") as message|null
|
||||
if(descmid)
|
||||
descmid = sanitizeSQL(descmid)
|
||||
else if(descmid == null)
|
||||
return
|
||||
descmax = input("Optional: Set description for maximum rating","Maximum rating description") as message|null
|
||||
if(descmax)
|
||||
descmax = sanitizeSQL(descmax)
|
||||
else if(descmax == null)
|
||||
return
|
||||
sql_option_list += list(list("text" = "'[option]'", "minval" = "'[minval]'", "maxval" = "'[maxval]'", "descmin" = "'[descmin]'", "descmid" = "'[descmid]'", "descmax" = "'[descmax]'", "default_display_in_results" = "'[default_percentage_calc]'"))
|
||||
switch(alert(" ",,"Add option","Finish", "Cancel"))
|
||||
if("Add option")
|
||||
add_option = 1
|
||||
if("Finish")
|
||||
add_option = 0
|
||||
else
|
||||
return 0
|
||||
var/datum/DBQuery/query_polladd_question = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip, dontshow) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', INET_ATON('[address]'), '[dontshow]')")
|
||||
if(!query_polladd_question.warn_execute())
|
||||
return
|
||||
if(polltype == POLLTYPE_TEXT)
|
||||
log_admin("[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]")
|
||||
message_admins("[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]<br>Question: [question]")
|
||||
return
|
||||
var/pollid = 0
|
||||
var/datum/DBQuery/query_get_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE question = '[question]' AND starttime = '[starttime]' AND endtime = '[endtime]' AND createdby_ckey = '[sql_ckey]' AND createdby_ip = INET_ATON('[address]')")
|
||||
if(!query_get_id.warn_execute())
|
||||
return
|
||||
if(query_get_id.NextRow())
|
||||
pollid = query_get_id.item[1]
|
||||
var/add_option = 1
|
||||
while(add_option)
|
||||
var/option = input("Write your option","Option") as message|null
|
||||
if(!option)
|
||||
return pollid
|
||||
option = sanitizeSQL(option)
|
||||
var/percentagecalc = 1
|
||||
if (polltype != POLLTYPE_IRV)
|
||||
switch(alert("Calculate option results as percentage?",,"Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
percentagecalc = 1
|
||||
if("No")
|
||||
percentagecalc = 0
|
||||
else
|
||||
return pollid
|
||||
var/minval = 0
|
||||
var/maxval = 0
|
||||
var/descmin = ""
|
||||
var/descmid = ""
|
||||
var/descmax = ""
|
||||
if(polltype == POLLTYPE_RATING)
|
||||
minval = input("Set minimum rating value.","Minimum rating") as num|null
|
||||
if(!minval)
|
||||
return pollid
|
||||
maxval = input("Set maximum rating value.","Maximum rating") as num|null
|
||||
if(!maxval)
|
||||
return pollid
|
||||
if(minval >= maxval)
|
||||
to_chat(src, "Minimum rating value can't be more than maximum rating value")
|
||||
return pollid
|
||||
descmin = input("Optional: Set description for minimum rating","Minimum rating description") as message|null
|
||||
if(descmin)
|
||||
descmin = sanitizeSQL(descmin)
|
||||
else if(descmin == null)
|
||||
return pollid
|
||||
descmid = input("Optional: Set description for median rating","Median rating description") as message|null
|
||||
if(descmid)
|
||||
descmid = sanitizeSQL(descmid)
|
||||
else if(descmid == null)
|
||||
return pollid
|
||||
descmax = input("Optional: Set description for maximum rating","Maximum rating description") as message|null
|
||||
if(descmax)
|
||||
descmax = sanitizeSQL(descmax)
|
||||
else if(descmax == null)
|
||||
return pollid
|
||||
var/datum/DBQuery/query_polladd_option = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_option")] (pollid, text, percentagecalc, minval, maxval, descmin, descmid, descmax) VALUES ('[pollid]', '[option]', '[percentagecalc]', '[minval]', '[maxval]', '[descmin]', '[descmid]', '[descmax]')")
|
||||
if(!query_polladd_option.warn_execute())
|
||||
return pollid
|
||||
switch(alert(" ",,"Add option","Finish", "Cancel"))
|
||||
if("Add option")
|
||||
add_option = 1
|
||||
if("Finish")
|
||||
add_option = 0
|
||||
else
|
||||
return 0
|
||||
return pollid
|
||||
if(polltype != POLLTYPE_TEXT)
|
||||
var/pollid = 0
|
||||
var/datum/DBQuery/query_get_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
|
||||
if(!query_get_id.warn_execute())
|
||||
return
|
||||
if(query_get_id.NextRow())
|
||||
pollid = query_get_id.item[1]
|
||||
for(var/list/i in sql_option_list)
|
||||
i |= list("pollid" = "'[pollid]'")
|
||||
SSdbcore.MassInsert(format_table_name("poll_option"), sql_option_list, warn = 1)
|
||||
log_admin("[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]")
|
||||
message_admins("[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]<br>Question: [question]")
|
||||
|
||||
@@ -1,137 +1,137 @@
|
||||
/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:375px;'>PERMISSIONS</th>
|
||||
<th style='width:100%;'>VERB-OVERRIDES</th>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
for(var/adm_ckey in GLOB.admin_datums)
|
||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||
if(!D)
|
||||
continue
|
||||
|
||||
var/rights = rights2text(D.rank.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]'>[D.rank.name]</a></td>"
|
||||
output += "<td><a class='small' href='?src=\ref[src];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></td>"
|
||||
output += "<td><a class='small' href='?src=\ref[src];editrights=permissions;ckey=[adm_ckey]'>[rights2text(0," ",D.rank.adds,D.rank.subs)]</a></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=900x650")
|
||||
|
||||
/datum/admins/proc/log_admin_rank_modification(adm_ckey, new_rank)
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if (!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
/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:375px;'>PERMISSIONS</th>
|
||||
<th style='width:100%;'>VERB-OVERRIDES</th>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
for(var/adm_ckey in GLOB.admin_datums)
|
||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||
if(!D)
|
||||
continue
|
||||
|
||||
var/rights = rights2text(D.rank.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]'>[D.rank.name]</a></td>"
|
||||
output += "<td><a class='small' href='?src=\ref[src];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></td>"
|
||||
output += "<td><a class='small' href='?src=\ref[src];editrights=permissions;ckey=[adm_ckey]'>[rights2text(0," ",D.rank.adds,D.rank.subs)]</a></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=900x650")
|
||||
|
||||
/datum/admins/proc/log_admin_rank_modification(adm_ckey, new_rank)
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if (!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
|
||||
if(!adm_ckey || !new_rank)
|
||||
return
|
||||
|
||||
adm_ckey = ckey(adm_ckey)
|
||||
|
||||
if(!adm_ckey)
|
||||
return
|
||||
|
||||
if(!istext(adm_ckey) || !istext(new_rank))
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
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/datum/DBQuery/query_get_admin = SSdbcore.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
|
||||
if(!query_get_admin.warn_execute())
|
||||
return
|
||||
|
||||
var/new_admin = 1
|
||||
var/admin_id
|
||||
while(query_get_admin.NextRow())
|
||||
new_admin = 0
|
||||
admin_id = text2num(query_get_admin.item[1])
|
||||
|
||||
if(new_admin)
|
||||
if(!query_get_admin.warn_execute())
|
||||
return
|
||||
|
||||
var/new_admin = 1
|
||||
var/admin_id
|
||||
while(query_get_admin.NextRow())
|
||||
new_admin = 0
|
||||
admin_id = text2num(query_get_admin.item[1])
|
||||
|
||||
if(new_admin)
|
||||
var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin")]` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
|
||||
if(!query_add_admin.warn_execute())
|
||||
return
|
||||
if(!query_add_admin.warn_execute())
|
||||
return
|
||||
var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
|
||||
if(!query_add_admin_log.warn_execute())
|
||||
return
|
||||
to_chat(usr, "<span class='adminnotice'>New admin added.</span>")
|
||||
else
|
||||
if(!isnull(admin_id) && isnum(admin_id))
|
||||
if(!query_add_admin_log.warn_execute())
|
||||
return
|
||||
to_chat(usr, "<span class='adminnotice'>New admin added.</span>")
|
||||
else
|
||||
if(!isnull(admin_id) && isnum(admin_id))
|
||||
var/datum/DBQuery/query_change_admin = SSdbcore.NewQuery("UPDATE `[format_table_name("admin")]` SET rank = '[new_rank]' WHERE id = [admin_id]")
|
||||
if(!query_change_admin.warn_execute())
|
||||
return
|
||||
if(!query_change_admin.warn_execute())
|
||||
return
|
||||
var/datum/DBQuery/query_change_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
|
||||
if(!query_change_admin_log.warn_execute())
|
||||
return
|
||||
to_chat(usr, "<span class='adminnnotice'>Admin rank changed.</span>")
|
||||
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(adm_ckey, new_permission)
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
if(!usr.client)
|
||||
return
|
||||
if(check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
if(!query_change_admin_log.warn_execute())
|
||||
return
|
||||
to_chat(usr, "<span class='adminnnotice'>Admin rank changed.</span>")
|
||||
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(adm_ckey, new_permission)
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
if(!usr.client)
|
||||
return
|
||||
if(check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
|
||||
if(!adm_ckey || !istext(adm_ckey) || !isnum(new_permission))
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
|
||||
if(!adm_ckey || !istext(adm_ckey) || !isnum(new_permission))
|
||||
return
|
||||
|
||||
var/datum/DBQuery/query_get_perms = SSdbcore.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
|
||||
if(!query_get_perms.warn_execute())
|
||||
return
|
||||
|
||||
var/admin_id
|
||||
while(query_get_perms.NextRow())
|
||||
admin_id = text2num(query_get_perms.item[1])
|
||||
|
||||
if(!admin_id)
|
||||
return
|
||||
|
||||
if(!query_get_perms.warn_execute())
|
||||
return
|
||||
|
||||
var/admin_id
|
||||
while(query_get_perms.NextRow())
|
||||
admin_id = text2num(query_get_perms.item[1])
|
||||
|
||||
if(!admin_id)
|
||||
return
|
||||
|
||||
var/datum/DBQuery/query_change_perms = SSdbcore.NewQuery("UPDATE `[format_table_name("admin")]` SET flags = [new_permission] WHERE id = [admin_id]")
|
||||
if(!query_change_perms.warn_execute())
|
||||
return
|
||||
if(!query_change_perms.warn_execute())
|
||||
return
|
||||
var/datum/DBQuery/query_change_perms_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edit permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
|
||||
query_change_perms_log.warn_execute()
|
||||
query_change_perms_log.warn_execute()
|
||||
|
||||
+629
-629
File diff suppressed because it is too large
Load Diff
@@ -335,7 +335,7 @@
|
||||
return
|
||||
SSblackbox.add_details("admin_secrets_fun_used","Traitor All ([objective])")
|
||||
for(var/mob/living/H in GLOB.player_list)
|
||||
if(!(istype(H, /mob/living/carbon/human)||istype(H, /mob/living/silicon/))) continue
|
||||
if(!(ishuman(H)||istype(H, /mob/living/silicon/))) continue
|
||||
if(H.stat == 2 || !H.client || !H.mind || ispAI(H)) continue
|
||||
if(is_special_character(H)) continue
|
||||
H.mind.add_antag_datum(ANTAG_DATUM_TRAITOR_CUSTOM)
|
||||
@@ -390,7 +390,7 @@
|
||||
SSblackbox.add_details("admin_secrets_fun_used","Chinese Cartoons")
|
||||
message_admins("[key_name_admin(usr)] made everything kawaii.")
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
H << sound('sound/AI/animes.ogg')
|
||||
H << sound('sound/ai/animes.ogg')
|
||||
|
||||
if(H.dna.species.id == "human")
|
||||
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
|
||||
@@ -457,7 +457,7 @@
|
||||
if(W.z == ZLEVEL_STATION && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
|
||||
W.req_access = list()
|
||||
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
|
||||
priority_announce("Centcom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/AI/commandreport.ogg')
|
||||
priority_announce("Centcom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/ai/commandreport.ogg')
|
||||
|
||||
if("guns")
|
||||
if(!check_rights(R_FUN))
|
||||
|
||||
@@ -360,4 +360,4 @@ this proc can take several minutes to execute fully if converting and cause DD t
|
||||
to_chat(world, "Deleting NOTESFILE")
|
||||
fdel(NOTESFILE)
|
||||
to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES")*/
|
||||
#undef NOTESFILE
|
||||
#undef NOTESFILE
|
||||
|
||||
+2249
-2250
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -124,10 +124,10 @@
|
||||
var/list/keys = list()
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
keys += M.client
|
||||
var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
|
||||
var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
|
||||
if(!selection)
|
||||
return
|
||||
var/mob/M = selection:mob
|
||||
var/mob/M = selection.mob
|
||||
|
||||
if(!M)
|
||||
return
|
||||
@@ -156,4 +156,4 @@
|
||||
admin_ticket_log(M, msg)
|
||||
else
|
||||
to_chat(src, "Failed to move mob to a valid location.")
|
||||
SSblackbox.add_details("admin_verb","Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
SSblackbox.add_details("admin_verb","Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
+288
-290
@@ -1,249 +1,249 @@
|
||||
#define IRCREPLYCOUNT 2
|
||||
|
||||
|
||||
//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 in GLOB.mob_list)
|
||||
set category = null
|
||||
set name = "Admin PM Mob"
|
||||
if(!holder)
|
||||
to_chat(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)
|
||||
SSblackbox.add_details("admin_verb","Admin PM Mob") //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)
|
||||
to_chat(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(isnewplayer(T.mob))
|
||||
targets["(New Player) - [T]"] = T
|
||||
else if(isobserver(T.mob))
|
||||
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/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
|
||||
cmd_admin_pm(targets[target],null)
|
||||
SSblackbox.add_details("admin_verb","Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_ahelp_reply(whom)
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
|
||||
return
|
||||
var/client/C
|
||||
if(istext(whom))
|
||||
if(cmptext(copytext(whom,1,2),"@"))
|
||||
whom = findStealthKey(whom)
|
||||
C = GLOB.directory[whom]
|
||||
else if(istype(whom,/client))
|
||||
C = whom
|
||||
if(!C)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
return
|
||||
|
||||
var/datum/admin_help/AH = C.current_ticket
|
||||
|
||||
if(AH)
|
||||
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
|
||||
var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as text|null
|
||||
if (!msg)
|
||||
message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
|
||||
return
|
||||
cmd_admin_pm(whom, msg)
|
||||
|
||||
//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(whom, msg)
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
|
||||
return
|
||||
|
||||
if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo
|
||||
to_chat(src, "<font color='red'>You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.</font>")
|
||||
to_chat(src, "<font color='blue'>Message: [msg]</font>")
|
||||
return
|
||||
|
||||
var/client/recipient
|
||||
var/irc = 0
|
||||
if(istext(whom))
|
||||
if(cmptext(copytext(whom,1,2),"@"))
|
||||
whom = findStealthKey(whom)
|
||||
if(whom == "IRCKEY")
|
||||
irc = 1
|
||||
else
|
||||
recipient = GLOB.directory[whom]
|
||||
else if(istype(whom,/client))
|
||||
recipient = whom
|
||||
|
||||
|
||||
if(irc)
|
||||
if(!ircreplyamount) //to prevent people from spamming irc
|
||||
return
|
||||
if(!msg)
|
||||
msg = input(src,"Message:", "Private message to Administrator") as text|null
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Use the admin IRC channel, nerd.</font>")
|
||||
return
|
||||
|
||||
|
||||
else
|
||||
if(!recipient)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
to_chat(src, msg)
|
||||
else
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
return
|
||||
|
||||
//get message text, limit it's length.and clean/escape html
|
||||
if(!msg)
|
||||
msg = input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]") as text|null
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
|
||||
return
|
||||
|
||||
if(!recipient)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
else
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
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)||irc)//no sending html to the poor bots
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/rawmsg = msg
|
||||
|
||||
if(holder)
|
||||
msg = emoji_parse(msg)
|
||||
|
||||
var/keywordparsedmsg = keywords_lookup(msg)
|
||||
|
||||
if(irc)
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [rawmsg]</font>")
|
||||
var/datum/admin_help/AH = admin_ticket_log(src, "<font color='red'>Reply PM from-<b>[key_name(src, TRUE, TRUE)] to <i>IRC</i>: [keywordparsedmsg]</font>")
|
||||
ircreplyamount--
|
||||
send2irc("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg)
|
||||
else
|
||||
if(recipient.holder)
|
||||
if(holder) //both are admins
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>")
|
||||
|
||||
//omg this is dumb, just fill in both their tickets
|
||||
var/interaction_message = "<font color='purple'>PM from-<b>[key_name(src, recipient, 1)]</b> to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>"
|
||||
admin_ticket_log(src, interaction_message)
|
||||
if(recipient != src) //reeee
|
||||
admin_ticket_log(recipient, interaction_message)
|
||||
|
||||
else //recipient is an admin but sender is not
|
||||
var/replymsg = "<font color='red'>Reply PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>"
|
||||
admin_ticket_log(src, replymsg)
|
||||
to_chat(recipient, replymsg)
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [msg]</font>")
|
||||
|
||||
//play the recieving admin the adminhelp sound (if they have them enabled)
|
||||
if(recipient.prefs.toggles & SOUND_ADMINHELP)
|
||||
recipient << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
else
|
||||
if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT
|
||||
if(!recipient.current_ticket)
|
||||
new /datum/admin_help(msg, recipient, TRUE)
|
||||
|
||||
to_chat(recipient, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 0)]</b>: [msg]</font>")
|
||||
to_chat(recipient, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [msg]</font>")
|
||||
|
||||
admin_ticket_log(recipient, "<font color='blue'>PM From [key_name_admin(src)]: [keywordparsedmsg]</font>")
|
||||
|
||||
//always play non-admin recipients the adminhelp sound
|
||||
recipient << '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(recipient, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply
|
||||
if(recipient && reply)
|
||||
if(sender)
|
||||
recipient.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
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>")
|
||||
return
|
||||
|
||||
if(irc)
|
||||
log_admin_private("PM: [key_name(src)]->IRC: [rawmsg]")
|
||||
#define IRCREPLYCOUNT 2
|
||||
|
||||
|
||||
//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 in GLOB.mob_list)
|
||||
set category = null
|
||||
set name = "Admin PM Mob"
|
||||
if(!holder)
|
||||
to_chat(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)
|
||||
SSblackbox.add_details("admin_verb","Admin PM Mob") //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)
|
||||
to_chat(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(isnewplayer(T.mob))
|
||||
targets["(New Player) - [T]"] = T
|
||||
else if(isobserver(T.mob))
|
||||
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/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
|
||||
cmd_admin_pm(targets[target],null)
|
||||
SSblackbox.add_details("admin_verb","Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_ahelp_reply(whom)
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
|
||||
return
|
||||
var/client/C
|
||||
if(istext(whom))
|
||||
if(cmptext(copytext(whom,1,2),"@"))
|
||||
whom = findStealthKey(whom)
|
||||
C = GLOB.directory[whom]
|
||||
else if(istype(whom,/client))
|
||||
C = whom
|
||||
if(!C)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
return
|
||||
|
||||
var/datum/admin_help/AH = C.current_ticket
|
||||
|
||||
if(AH)
|
||||
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
|
||||
var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as text|null
|
||||
if (!msg)
|
||||
message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
|
||||
return
|
||||
cmd_admin_pm(whom, msg)
|
||||
|
||||
//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(whom, msg)
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
|
||||
return
|
||||
|
||||
if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo
|
||||
to_chat(src, "<font color='red'>You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.</font>")
|
||||
to_chat(src, "<font color='blue'>Message: [msg]</font>")
|
||||
return
|
||||
|
||||
var/client/recipient
|
||||
var/irc = 0
|
||||
if(istext(whom))
|
||||
if(cmptext(copytext(whom,1,2),"@"))
|
||||
whom = findStealthKey(whom)
|
||||
if(whom == "IRCKEY")
|
||||
irc = 1
|
||||
else
|
||||
recipient = GLOB.directory[whom]
|
||||
else if(istype(whom,/client))
|
||||
recipient = whom
|
||||
|
||||
|
||||
if(irc)
|
||||
if(!ircreplyamount) //to prevent people from spamming irc
|
||||
return
|
||||
if(!msg)
|
||||
msg = input(src,"Message:", "Private message to Administrator") as text|null
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Use the admin IRC channel, nerd.</font>")
|
||||
return
|
||||
|
||||
|
||||
else
|
||||
if(!recipient)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
to_chat(src, msg)
|
||||
else
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
return
|
||||
|
||||
//get message text, limit it's length.and clean/escape html
|
||||
if(!msg)
|
||||
msg = input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]") as text|null
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
|
||||
return
|
||||
|
||||
if(!recipient)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
else
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
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)||irc)//no sending html to the poor bots
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/rawmsg = msg
|
||||
|
||||
if(holder)
|
||||
msg = emoji_parse(msg)
|
||||
|
||||
var/keywordparsedmsg = keywords_lookup(msg)
|
||||
|
||||
if(irc)
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [rawmsg]</font>")
|
||||
var/datum/admin_help/AH = admin_ticket_log(src, "<font color='red'>Reply PM from-<b>[key_name(src, TRUE, TRUE)] to <i>IRC</i>: [keywordparsedmsg]</font>")
|
||||
ircreplyamount--
|
||||
send2irc("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg)
|
||||
else
|
||||
if(recipient.holder)
|
||||
if(holder) //both are admins
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>")
|
||||
|
||||
//omg this is dumb, just fill in both their tickets
|
||||
var/interaction_message = "<font color='purple'>PM from-<b>[key_name(src, recipient, 1)]</b> to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>"
|
||||
admin_ticket_log(src, interaction_message)
|
||||
if(recipient != src) //reeee
|
||||
admin_ticket_log(recipient, interaction_message)
|
||||
|
||||
else //recipient is an admin but sender is not
|
||||
var/replymsg = "<font color='red'>Reply PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>"
|
||||
admin_ticket_log(src, replymsg)
|
||||
to_chat(recipient, replymsg)
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [msg]</font>")
|
||||
|
||||
//play the recieving admin the adminhelp sound (if they have them enabled)
|
||||
if(recipient.prefs.toggles & SOUND_ADMINHELP)
|
||||
recipient << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
else
|
||||
if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT
|
||||
if(!recipient.current_ticket)
|
||||
new /datum/admin_help(msg, recipient, TRUE)
|
||||
|
||||
to_chat(recipient, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 0)]</b>: [msg]</font>")
|
||||
to_chat(recipient, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [msg]</font>")
|
||||
|
||||
admin_ticket_log(recipient, "<font color='blue'>PM From [key_name_admin(src)]: [keywordparsedmsg]</font>")
|
||||
|
||||
//always play non-admin recipients the adminhelp sound
|
||||
recipient << '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(recipient, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply
|
||||
if(recipient && reply)
|
||||
if(sender)
|
||||
recipient.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
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>")
|
||||
return
|
||||
|
||||
if(irc)
|
||||
log_admin_private("PM: [key_name(src)]->IRC: [rawmsg]")
|
||||
for(var/client/X in GLOB.admins)
|
||||
to_chat(X, "<font color='blue'><B>PM: [key_name(src, X, 0)]->IRC:</B> [keywordparsedmsg]</font>")
|
||||
else
|
||||
window_flash(recipient, ignorepref = TRUE)
|
||||
log_admin_private("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]")
|
||||
//we don't use message_admins here because the sender/receiver might get it too
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
|
||||
else
|
||||
window_flash(recipient, ignorepref = TRUE)
|
||||
log_admin_private("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]")
|
||||
//we don't use message_admins here because the sender/receiver might get it too
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
|
||||
to_chat(X, "<font color='blue'><B>PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]:</B> [keywordparsedmsg]</font>" )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define IRC_AHELP_USAGE "Usage: ticket <close|resolve|icissue|reject|reopen \[ticket #\]|list>"
|
||||
/proc/IrcPm(target,msg,sender)
|
||||
/proc/IrcPm(target,msg,sender)
|
||||
target = ckey(target)
|
||||
var/client/C = GLOB.directory[target]
|
||||
|
||||
var/datum/admin_help/ticket = C ? C.current_ticket : GLOB.ahelp_tickets.CKey2ActiveTicket(target)
|
||||
var/compliant_msg = trim(lowertext(msg))
|
||||
var/irc_tagged = "[sender](IRC)"
|
||||
var/list/splits = splittext(compliant_msg, " ")
|
||||
if(splits.len && splits[1] == "ticket")
|
||||
if(splits.len < 2)
|
||||
var/client/C = GLOB.directory[target]
|
||||
|
||||
var/datum/admin_help/ticket = C ? C.current_ticket : GLOB.ahelp_tickets.CKey2ActiveTicket(target)
|
||||
var/compliant_msg = trim(lowertext(msg))
|
||||
var/irc_tagged = "[sender](IRC)"
|
||||
var/list/splits = splittext(compliant_msg, " ")
|
||||
if(splits.len && splits[1] == "ticket")
|
||||
if(splits.len < 2)
|
||||
return IRC_AHELP_USAGE
|
||||
switch(splits[2])
|
||||
if("close")
|
||||
if(ticket)
|
||||
ticket.Close(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully closed"
|
||||
if("resolve")
|
||||
if(ticket)
|
||||
ticket.Resolve(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully resolved"
|
||||
if("icissue")
|
||||
if(ticket)
|
||||
ticket.ICIssue(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully marked as IC issue"
|
||||
if("reject")
|
||||
if(ticket)
|
||||
ticket.Reject(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully rejected"
|
||||
switch(splits[2])
|
||||
if("close")
|
||||
if(ticket)
|
||||
ticket.Close(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully closed"
|
||||
if("resolve")
|
||||
if(ticket)
|
||||
ticket.Resolve(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully resolved"
|
||||
if("icissue")
|
||||
if(ticket)
|
||||
ticket.ICIssue(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully marked as IC issue"
|
||||
if("reject")
|
||||
if(ticket)
|
||||
ticket.Reject(irc_tagged)
|
||||
return "Ticket #[ticket.id] successfully rejected"
|
||||
if("reopen")
|
||||
if(ticket)
|
||||
return "Error: [target] already has ticket #[ticket.id] open"
|
||||
@@ -272,54 +272,52 @@
|
||||
. += "Active: "
|
||||
. += "#[AH.id]"
|
||||
return
|
||||
else
|
||||
else
|
||||
return IRC_AHELP_USAGE
|
||||
return "Error: Ticket could not be found"
|
||||
|
||||
var/static/stealthkey
|
||||
var/adminname = config.showircname ? irc_tagged : "Administrator"
|
||||
|
||||
if(!C)
|
||||
return "Error: No client"
|
||||
|
||||
if(!stealthkey)
|
||||
stealthkey = GenIrcStealthKey()
|
||||
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return "Error: No message"
|
||||
|
||||
message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]")
|
||||
log_admin_private("IRC PM: [sender] -> [key_name(C)] : [msg]")
|
||||
msg = emoji_parse(msg)
|
||||
|
||||
to_chat(C, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
|
||||
to_chat(C, "<font color='red'>Admin PM from-<b><a href='?priv_msg=[stealthkey]'>[adminname]</A></b>: [msg]</font>")
|
||||
to_chat(C, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
|
||||
|
||||
admin_ticket_log(C, "<font color='blue'>PM From [irc_tagged]: [msg]</font>")
|
||||
|
||||
window_flash(C, ignorepref = TRUE)
|
||||
//always play non-admin recipients the adminhelp sound
|
||||
C << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
C.ircreplyamount = IRCREPLYCOUNT
|
||||
|
||||
return "Message Successful"
|
||||
|
||||
|
||||
|
||||
/proc/GenIrcStealthKey()
|
||||
var/num = (rand(0,1000))
|
||||
var/i = 0
|
||||
while(i == 0)
|
||||
i = 1
|
||||
for(var/P in GLOB.stealthminID)
|
||||
if(num == GLOB.stealthminID[P])
|
||||
num++
|
||||
i = 0
|
||||
var/stealth = "@[num2text(num)]"
|
||||
GLOB.stealthminID["IRCKEY"] = stealth
|
||||
return stealth
|
||||
|
||||
#undef IRCREPLYCOUNT
|
||||
return "Error: Ticket could not be found"
|
||||
|
||||
var/static/stealthkey
|
||||
var/adminname = config.showircname ? irc_tagged : "Administrator"
|
||||
|
||||
if(!C)
|
||||
return "Error: No client"
|
||||
|
||||
if(!stealthkey)
|
||||
stealthkey = GenIrcStealthKey()
|
||||
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return "Error: No message"
|
||||
|
||||
message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]")
|
||||
log_admin_private("IRC PM: [sender] -> [key_name(C)] : [msg]")
|
||||
msg = emoji_parse(msg)
|
||||
|
||||
to_chat(C, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
|
||||
to_chat(C, "<font color='red'>Admin PM from-<b><a href='?priv_msg=[stealthkey]'>[adminname]</A></b>: [msg]</font>")
|
||||
to_chat(C, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
|
||||
|
||||
admin_ticket_log(C, "<font color='blue'>PM From [irc_tagged]: [msg]</font>")
|
||||
|
||||
window_flash(C, ignorepref = TRUE)
|
||||
//always play non-admin recipients the adminhelp sound
|
||||
C << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
C.ircreplyamount = IRCREPLYCOUNT
|
||||
|
||||
return "Message Successful"
|
||||
|
||||
/proc/GenIrcStealthKey()
|
||||
var/num = (rand(0,1000))
|
||||
var/i = 0
|
||||
while(i == 0)
|
||||
i = 1
|
||||
for(var/P in GLOB.stealthminID)
|
||||
if(num == GLOB.stealthminID[P])
|
||||
num++
|
||||
i = 0
|
||||
var/stealth = "@[num2text(num)]"
|
||||
GLOB.stealthminID["IRCKEY"] = stealth
|
||||
return stealth
|
||||
|
||||
#undef IRCREPLYCOUNT
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/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(0))
|
||||
return
|
||||
|
||||
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
log_adminsay("[key_name(src)] : [msg]")
|
||||
msg = keywords_lookup(msg)
|
||||
if(check_rights(R_ADMIN,0))
|
||||
msg = "<span class='admin'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> (<a href='?_src_=holder;adminplayerobservefollow=\ref[mob]'>FLW</A>): <span class='message'>[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
else
|
||||
msg = "<span class='adminobserver'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]:</EM> <span class='message'>[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
|
||||
/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(0))
|
||||
return
|
||||
|
||||
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
log_adminsay("[key_name(src)] : [msg]")
|
||||
msg = keywords_lookup(msg)
|
||||
if(check_rights(R_ADMIN,0))
|
||||
msg = "<span class='admin'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> (<a href='?_src_=holder;adminplayerobservefollow=\ref[mob]'>FLW</A>): <span class='message'>[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
else
|
||||
msg = "<span class='adminobserver'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]:</EM> <span class='message'>[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
|
||||
SSblackbox.add_details("admin_verb","Asay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
/client/proc/atmosscan()
|
||||
set category = "Mapping"
|
||||
set name = "Check Plumbing"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
/client/proc/atmosscan()
|
||||
set category = "Mapping"
|
||||
set name = "Check Plumbing"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
SSblackbox.add_details("admin_verb","Check Plumbing") //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 GLOB.machines)
|
||||
if (plumbing.nodealert)
|
||||
to_chat(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 GLOB.machines)
|
||||
if (!pipe.NODE1 || !pipe.NODE2 || !pipe.NODE3)
|
||||
to_chat(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 GLOB.machines)
|
||||
if (!pipe.NODE1 || !pipe.NODE2)
|
||||
to_chat(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)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
|
||||
//all plumbing - yes, some things might get stated twice, doesn't matter.
|
||||
for (var/obj/machinery/atmospherics/plumbing in GLOB.machines)
|
||||
if (plumbing.nodealert)
|
||||
to_chat(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 GLOB.machines)
|
||||
if (!pipe.NODE1 || !pipe.NODE2 || !pipe.NODE3)
|
||||
to_chat(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 GLOB.machines)
|
||||
if (!pipe.NODE1 || !pipe.NODE2)
|
||||
to_chat(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)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
SSblackbox.add_details("admin_verb","Check Power") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
for (var/datum/powernet/PN in GLOB.powernets)
|
||||
if (!PN.nodes || !PN.nodes.len)
|
||||
if(PN.cables && (PN.cables.len > 1))
|
||||
var/obj/structure/cable/C = PN.cables[1]
|
||||
to_chat(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]
|
||||
|
||||
for (var/datum/powernet/PN in GLOB.powernets)
|
||||
if (!PN.nodes || !PN.nodes.len)
|
||||
if(PN.cables && (PN.cables.len > 1))
|
||||
var/obj/structure/cable/C = PN.cables[1]
|
||||
to_chat(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]
|
||||
to_chat(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)]")
|
||||
@@ -21,7 +21,6 @@
|
||||
target.gib(1, 1)
|
||||
else
|
||||
target.adjustBruteLoss(min(99,(target.health - 1)))
|
||||
target.Stun(20)
|
||||
target.Weaken(20)
|
||||
target.Knockdown(400)
|
||||
target.stuttering = 20
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/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)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
if(!src.mob)
|
||||
return
|
||||
if(prefs.muted & MUTE_DEADCHAT)
|
||||
to_chat(src, "<span class='danger'>You cannot send DSAY messages (muted).</span>")
|
||||
return
|
||||
|
||||
if (src.handle_spam_prevention(msg,MUTE_DEADCHAT))
|
||||
return
|
||||
|
||||
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
|
||||
log_dsay("[key_name(src)] : [msg]")
|
||||
|
||||
if (!msg)
|
||||
return
|
||||
/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)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
if(!src.mob)
|
||||
return
|
||||
if(prefs.muted & MUTE_DEADCHAT)
|
||||
to_chat(src, "<span class='danger'>You cannot send DSAY messages (muted).</span>")
|
||||
return
|
||||
|
||||
if (src.handle_spam_prevention(msg,MUTE_DEADCHAT))
|
||||
return
|
||||
|
||||
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
|
||||
log_dsay("[key_name(src)] : [msg]")
|
||||
|
||||
if (!msg)
|
||||
return
|
||||
var/static/nicknames = world.file2list("config/admin_nicknames.txt")
|
||||
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>ADMIN([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
|
||||
|
||||
for (var/mob/M in GLOB.player_list)
|
||||
if(isnewplayer(M))
|
||||
continue
|
||||
if (M.stat == DEAD || (M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
SSblackbox.add_details("admin_verb","Dsay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>ADMIN([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
|
||||
|
||||
for (var/mob/M in GLOB.player_list)
|
||||
if(isnewplayer(M))
|
||||
continue
|
||||
if (M.stat == DEAD || (M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
SSblackbox.add_details("admin_verb","Dsay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -109,6 +109,7 @@ GLOBAL_PROTECT(AdminProcCallCount)
|
||||
UNTIL(!GLOB.AdminProcCaller)
|
||||
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
|
||||
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
|
||||
++GLOB.AdminProcCallCount
|
||||
. = world.WrapAdminProcCall(target, procname, arguments)
|
||||
if(--GLOB.AdminProcCallCount == 0)
|
||||
GLOB.AdminProcCaller = null
|
||||
@@ -839,4 +840,4 @@ GLOBAL_PROTECT(AdminProcCallCount)
|
||||
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(src)] pumped a random event.</span>")
|
||||
SSblackbox.add_details("admin_verb","Pump Random Event")
|
||||
log_admin("[key_name(src)] pumped a random event.")
|
||||
log_admin("[key_name(src)] pumped a random event.")
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
//replaces the old Ticklag verb, fps is easier to understand
|
||||
/client/proc/set_server_fps()
|
||||
set category = "Debug"
|
||||
set name = "Set Server FPS"
|
||||
set desc = "Sets game speed in frames-per-second. Can potentially break the game"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [config.fps])","FPS", world.fps) as num|null)
|
||||
|
||||
if(new_fps <= 0)
|
||||
to_chat(src, "<span class='danger'>Error: set_server_fps(): Invalid world.fps value. No changes made.</span>")
|
||||
return
|
||||
if(new_fps > config.fps*1.5)
|
||||
if(alert(src, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [config.fps]","Warning!","Confirm","ABORT-ABORT-ABORT") != "Confirm")
|
||||
return
|
||||
|
||||
var/msg = "[key_name(src)] has modified world.fps to [new_fps]"
|
||||
log_admin(msg, 0)
|
||||
message_admins(msg, 0)
|
||||
//replaces the old Ticklag verb, fps is easier to understand
|
||||
/client/proc/set_server_fps()
|
||||
set category = "Debug"
|
||||
set name = "Set Server FPS"
|
||||
set desc = "Sets game speed in frames-per-second. Can potentially break the game"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [config.fps])","FPS", world.fps) as num|null)
|
||||
|
||||
if(new_fps <= 0)
|
||||
to_chat(src, "<span class='danger'>Error: set_server_fps(): Invalid world.fps value. No changes made.</span>")
|
||||
return
|
||||
if(new_fps > config.fps*1.5)
|
||||
if(alert(src, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [config.fps]","Warning!","Confirm","ABORT-ABORT-ABORT") != "Confirm")
|
||||
return
|
||||
|
||||
var/msg = "[key_name(src)] has modified world.fps to [new_fps]"
|
||||
log_admin(msg, 0)
|
||||
message_admins(msg, 0)
|
||||
SSblackbox.add_details("admin_toggle","Set Server FPS|[new_fps]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
world.fps = new_fps
|
||||
|
||||
world.fps = new_fps
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
//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 << ftp(file(path))
|
||||
to_chat(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"
|
||||
//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 << ftp(file(path))
|
||||
to_chat(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 server log for this round."
|
||||
|
||||
|
||||
if(fexists("[GLOB.world_game_log]"))
|
||||
src << ftp(GLOB.world_game_log)
|
||||
else
|
||||
to_chat(src, "<font color='red'>Server log not found, try using .getserverlog.</font>")
|
||||
return
|
||||
else
|
||||
to_chat(src, "<font color='red'>Server log not found, try using .getserverlog.</font>")
|
||||
return
|
||||
SSblackbox.add_details("admin_verb","Show Server Log") //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"
|
||||
return
|
||||
|
||||
//Shows today's attack log
|
||||
/datum/admins/proc/view_atk_log()
|
||||
set category = "Admin"
|
||||
set name = "Show Server Attack Log"
|
||||
set desc = "Shows server attack log for this round."
|
||||
|
||||
|
||||
if(fexists("[GLOB.world_attack_log]"))
|
||||
src << ftp(GLOB.world_attack_log)
|
||||
else
|
||||
to_chat(src, "<font color='red'>Server attack log not found, try using .getserverlog.</font>")
|
||||
return
|
||||
else
|
||||
to_chat(src, "<font color='red'>Server attack log not found, try using .getserverlog.</font>")
|
||||
return
|
||||
SSblackbox.add_details("admin_verb","Show Server Attack log") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
return
|
||||
|
||||
@@ -176,7 +176,6 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
|
||||
SSblackbox.add_details("admin_verb","Show Roundstart Active Turf Markers")
|
||||
|
||||
|
||||
/client/proc/enable_debug_verbs()
|
||||
set category = "Debug"
|
||||
set name = "Debug verbs - Enable"
|
||||
|
||||
@@ -1,266 +1,266 @@
|
||||
/client/proc/cmd_mass_modify_object_variables(atom/A, 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 items)
|
||||
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
|
||||
if(A && A.type)
|
||||
method = vv_subtype_prompt(A.type)
|
||||
|
||||
src.massmodify_variables(A, var_name, method)
|
||||
/client/proc/cmd_mass_modify_object_variables(atom/A, 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 items)
|
||||
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
|
||||
if(A && A.type)
|
||||
method = vv_subtype_prompt(A.type)
|
||||
|
||||
src.massmodify_variables(A, var_name, method)
|
||||
SSblackbox.add_details("admin_verb","Mass Edit Variables") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/massmodify_variables(datum/O, var_name = "", method = 0)
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
if(!istype(O))
|
||||
return
|
||||
|
||||
var/variable = ""
|
||||
if(!var_name)
|
||||
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
|
||||
else
|
||||
variable = var_name
|
||||
|
||||
if(!variable || !O.can_vv_get(variable))
|
||||
return
|
||||
var/default
|
||||
var/var_value = O.vars[variable]
|
||||
|
||||
if(variable in GLOB.VVckey_edit)
|
||||
to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.")
|
||||
return
|
||||
if(variable in GLOB.VVlocked)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
if(variable in GLOB.VVicon_edit_lock)
|
||||
if(!check_rights(R_FUN|R_DEBUG))
|
||||
return
|
||||
if(variable in GLOB.VVpixelmovement)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT")
|
||||
if (prompt != "Continue")
|
||||
return
|
||||
|
||||
default = vv_get_class(var_value)
|
||||
|
||||
if(isnull(default))
|
||||
to_chat(src, "Unable to determine variable type.")
|
||||
else
|
||||
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
|
||||
|
||||
to_chat(src, "Variable contains: [var_value]")
|
||||
|
||||
if(default == VV_NUM)
|
||||
var/dir_text = ""
|
||||
if(dir < 0 && dir < 16)
|
||||
if(dir & 1)
|
||||
dir_text += "NORTH"
|
||||
if(dir & 2)
|
||||
dir_text += "SOUTH"
|
||||
if(dir & 4)
|
||||
dir_text += "EAST"
|
||||
if(dir & 8)
|
||||
dir_text += "WEST"
|
||||
|
||||
if(dir_text)
|
||||
to_chat(src, "If a direction, direction is: [dir_text]")
|
||||
|
||||
var/value = vv_get_value(default_class = default)
|
||||
var/new_value = value["value"]
|
||||
var/class = value["class"]
|
||||
|
||||
if(!class || !new_value == null && class != VV_NULL)
|
||||
return
|
||||
|
||||
if (class == VV_MESSAGE)
|
||||
class = VV_TEXT
|
||||
|
||||
if (value["type"])
|
||||
class = VV_NEW_TYPE
|
||||
|
||||
var/original_name = "[O]"
|
||||
|
||||
var/rejected = 0
|
||||
var/accepted = 0
|
||||
|
||||
switch(class)
|
||||
if(VV_RESTORE_DEFAULT)
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if (D.vv_edit_var(variable, initial(D.vars[variable])) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
CHECK_TICK
|
||||
|
||||
if(VV_TEXT)
|
||||
var/list/varsvars = vv_parse_text(O, new_value)
|
||||
var/pre_processing = new_value
|
||||
var/unique
|
||||
if (varsvars && varsvars.len)
|
||||
unique = alert(usr, "Process vars unique to each instance, or same for all?", "Variable Association", "Unique", "Same")
|
||||
if(unique == "Unique")
|
||||
unique = TRUE
|
||||
else
|
||||
unique = FALSE
|
||||
for(var/V in varsvars)
|
||||
new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]")
|
||||
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if(unique)
|
||||
new_value = pre_processing
|
||||
for(var/V in varsvars)
|
||||
new_value = replacetext(new_value,"\[[V]]","[D.vars[V]]")
|
||||
|
||||
if (D.vv_edit_var(variable, new_value) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
CHECK_TICK
|
||||
|
||||
if (VV_NEW_TYPE)
|
||||
var/many = alert(src, "Create only one [value["type"]] and assign each or a new one for each thing", "How Many", "One", "Many", "Cancel")
|
||||
if (many == "Cancel")
|
||||
return
|
||||
if (many == "Many")
|
||||
many = TRUE
|
||||
else
|
||||
many = FALSE
|
||||
|
||||
var/type = value["type"]
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if(many && !new_value)
|
||||
new_value = new type()
|
||||
|
||||
if (D.vv_edit_var(variable, new_value) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
new_value = null
|
||||
CHECK_TICK
|
||||
|
||||
else
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if (D.vv_edit_var(variable, new_value) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
var/count = rejected+accepted
|
||||
if (!count)
|
||||
to_chat(src, "No objects found")
|
||||
return
|
||||
if (!accepted)
|
||||
to_chat(src, "Every object rejected your edit")
|
||||
return
|
||||
if (rejected)
|
||||
to_chat(src, "[rejected] out of [count] objects rejected your edit")
|
||||
|
||||
log_world("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])")
|
||||
log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
|
||||
message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
|
||||
|
||||
|
||||
/proc/get_all_of_type(var/T, subtypes = TRUE)
|
||||
var/list/typecache = list()
|
||||
typecache[T] = 1
|
||||
if (subtypes)
|
||||
typecache = typecacheof(typecache)
|
||||
. = list()
|
||||
if (ispath(T, /mob))
|
||||
for(var/mob/thing in GLOB.mob_list)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj/machinery/door))
|
||||
for(var/obj/machinery/door/thing in GLOB.airlocks)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj/machinery))
|
||||
for(var/obj/machinery/thing in GLOB.machines)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj))
|
||||
for(var/obj/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /atom/movable))
|
||||
for(var/atom/movable/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /turf))
|
||||
for(var/turf/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /atom))
|
||||
for(var/atom/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /client))
|
||||
for(var/client/thing in GLOB.clients)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /datum))
|
||||
for(var/datum/thing)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else
|
||||
for(var/datum/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
/client/proc/massmodify_variables(datum/O, var_name = "", method = 0)
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
if(!istype(O))
|
||||
return
|
||||
|
||||
var/variable = ""
|
||||
if(!var_name)
|
||||
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
|
||||
else
|
||||
variable = var_name
|
||||
|
||||
if(!variable || !O.can_vv_get(variable))
|
||||
return
|
||||
var/default
|
||||
var/var_value = O.vars[variable]
|
||||
|
||||
if(variable in GLOB.VVckey_edit)
|
||||
to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.")
|
||||
return
|
||||
if(variable in GLOB.VVlocked)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
if(variable in GLOB.VVicon_edit_lock)
|
||||
if(!check_rights(R_FUN|R_DEBUG))
|
||||
return
|
||||
if(variable in GLOB.VVpixelmovement)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT")
|
||||
if (prompt != "Continue")
|
||||
return
|
||||
|
||||
default = vv_get_class(var_value)
|
||||
|
||||
if(isnull(default))
|
||||
to_chat(src, "Unable to determine variable type.")
|
||||
else
|
||||
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
|
||||
|
||||
to_chat(src, "Variable contains: [var_value]")
|
||||
|
||||
if(default == VV_NUM)
|
||||
var/dir_text = ""
|
||||
if(dir < 0 && dir < 16)
|
||||
if(dir & 1)
|
||||
dir_text += "NORTH"
|
||||
if(dir & 2)
|
||||
dir_text += "SOUTH"
|
||||
if(dir & 4)
|
||||
dir_text += "EAST"
|
||||
if(dir & 8)
|
||||
dir_text += "WEST"
|
||||
|
||||
if(dir_text)
|
||||
to_chat(src, "If a direction, direction is: [dir_text]")
|
||||
|
||||
var/value = vv_get_value(default_class = default)
|
||||
var/new_value = value["value"]
|
||||
var/class = value["class"]
|
||||
|
||||
if(!class || !new_value == null && class != VV_NULL)
|
||||
return
|
||||
|
||||
if (class == VV_MESSAGE)
|
||||
class = VV_TEXT
|
||||
|
||||
if (value["type"])
|
||||
class = VV_NEW_TYPE
|
||||
|
||||
var/original_name = "[O]"
|
||||
|
||||
var/rejected = 0
|
||||
var/accepted = 0
|
||||
|
||||
switch(class)
|
||||
if(VV_RESTORE_DEFAULT)
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if (D.vv_edit_var(variable, initial(D.vars[variable])) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
CHECK_TICK
|
||||
|
||||
if(VV_TEXT)
|
||||
var/list/varsvars = vv_parse_text(O, new_value)
|
||||
var/pre_processing = new_value
|
||||
var/unique
|
||||
if (varsvars && varsvars.len)
|
||||
unique = alert(usr, "Process vars unique to each instance, or same for all?", "Variable Association", "Unique", "Same")
|
||||
if(unique == "Unique")
|
||||
unique = TRUE
|
||||
else
|
||||
unique = FALSE
|
||||
for(var/V in varsvars)
|
||||
new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]")
|
||||
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if(unique)
|
||||
new_value = pre_processing
|
||||
for(var/V in varsvars)
|
||||
new_value = replacetext(new_value,"\[[V]]","[D.vars[V]]")
|
||||
|
||||
if (D.vv_edit_var(variable, new_value) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
CHECK_TICK
|
||||
|
||||
if (VV_NEW_TYPE)
|
||||
var/many = alert(src, "Create only one [value["type"]] and assign each or a new one for each thing", "How Many", "One", "Many", "Cancel")
|
||||
if (many == "Cancel")
|
||||
return
|
||||
if (many == "Many")
|
||||
many = TRUE
|
||||
else
|
||||
many = FALSE
|
||||
|
||||
var/type = value["type"]
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if(many && !new_value)
|
||||
new_value = new type()
|
||||
|
||||
if (D.vv_edit_var(variable, new_value) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
new_value = null
|
||||
CHECK_TICK
|
||||
|
||||
else
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
var/datum/D = thing
|
||||
if (D.vv_edit_var(variable, new_value) != FALSE)
|
||||
accepted++
|
||||
else
|
||||
rejected++
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
var/count = rejected+accepted
|
||||
if (!count)
|
||||
to_chat(src, "No objects found")
|
||||
return
|
||||
if (!accepted)
|
||||
to_chat(src, "Every object rejected your edit")
|
||||
return
|
||||
if (rejected)
|
||||
to_chat(src, "[rejected] out of [count] objects rejected your edit")
|
||||
|
||||
log_world("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])")
|
||||
log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
|
||||
message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
|
||||
|
||||
|
||||
/proc/get_all_of_type(var/T, subtypes = TRUE)
|
||||
var/list/typecache = list()
|
||||
typecache[T] = 1
|
||||
if (subtypes)
|
||||
typecache = typecacheof(typecache)
|
||||
. = list()
|
||||
if (ispath(T, /mob))
|
||||
for(var/mob/thing in GLOB.mob_list)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj/machinery/door))
|
||||
for(var/obj/machinery/door/thing in GLOB.airlocks)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj/machinery))
|
||||
for(var/obj/machinery/thing in GLOB.machines)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj))
|
||||
for(var/obj/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /atom/movable))
|
||||
for(var/atom/movable/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /turf))
|
||||
for(var/turf/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /atom))
|
||||
for(var/atom/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /client))
|
||||
for(var/client/thing in GLOB.clients)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /datum))
|
||||
for(var/datum/thing)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else
|
||||
for(var/datum/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+121
-121
@@ -1,124 +1,124 @@
|
||||
GLOBAL_VAR_INIT(highlander, FALSE)
|
||||
/client/proc/only_one() //Gives everyone kilts, berets, claymores, and pinpointers, with the objective to hijack the emergency shuttle.
|
||||
GLOBAL_VAR_INIT(highlander, FALSE)
|
||||
/client/proc/only_one() //Gives everyone kilts, berets, claymores, and pinpointers, with the objective to hijack the emergency shuttle.
|
||||
if(!SSticker.HasRoundStarted())
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
GLOB.highlander = TRUE
|
||||
|
||||
send_to_playing_players("<span class='boldannounce'><font size=6>THERE CAN BE ONLY ONE</font></span>")
|
||||
|
||||
for(var/obj/item/weapon/disk/nuclear/N in GLOB.poi_list)
|
||||
N.relocate() //Gets it out of bags and such
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(H.stat == DEAD || !(H.client))
|
||||
continue
|
||||
H.make_scottish()
|
||||
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used THERE CAN BE ONLY ONE!</span>")
|
||||
log_admin("[key_name(usr)] used THERE CAN BE ONLY ONE.")
|
||||
addtimer(CALLBACK(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 1), 50)
|
||||
|
||||
/client/proc/only_one_delayed()
|
||||
send_to_playing_players("<span class='userdanger'>Bagpipes begin to blare. You feel Scottish pride coming over you.</span>")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used (delayed) THERE CAN BE ONLY ONE!</span>")
|
||||
log_admin("[key_name(usr)] used delayed THERE CAN BE ONLY ONE.")
|
||||
addtimer(CALLBACK(src, .proc/only_one), 420)
|
||||
|
||||
/mob/living/carbon/human/proc/make_scottish()
|
||||
SSticker.mode.traitors += mind
|
||||
mind.special_role = "highlander"
|
||||
dna.species.species_traits |= NOGUNS //nice try jackass
|
||||
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = mind
|
||||
steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
|
||||
mind.objectives += steal_objective
|
||||
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
|
||||
hijack_objective.owner = mind
|
||||
mind.objectives += hijack_objective
|
||||
|
||||
mind.announce_objectives()
|
||||
|
||||
for(var/obj/item/I in get_equipped_items())
|
||||
qdel(I)
|
||||
for(var/obj/item/I in held_items)
|
||||
qdel(I)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(src), slot_w_uniform)
|
||||
equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(src), slot_ears)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(src), slot_head)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_l_store)
|
||||
for(var/obj/item/weapon/pinpointer/P in src)
|
||||
P.attack_self(src)
|
||||
var/obj/item/weapon/card/id/W = new(src)
|
||||
W.icon_state = "centcom"
|
||||
W.access = get_all_accesses()
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Highlander"
|
||||
W.registered_name = real_name
|
||||
W.flags |= NODROP
|
||||
W.update_label(real_name)
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
var/obj/item/weapon/claymore/highlander/H1 = new(src)
|
||||
if(!GLOB.highlander)
|
||||
H1.admin_spawned = TRUE //To prevent announcing
|
||||
put_in_hands(H1)
|
||||
H1.pickup(src) //For the stun shielding
|
||||
|
||||
var/obj/item/weapon/bloodcrawl/antiwelder = new(src)
|
||||
antiwelder.name = "compulsion of honor"
|
||||
antiwelder.desc = "You are unable to hold anything in this hand until you're the last one left!"
|
||||
antiwelder.icon_state = "bloodhand_right"
|
||||
put_in_hands(antiwelder)
|
||||
|
||||
to_chat(src, "<span class='boldannounce'>Your [H1.name] cries out for blood. Claim the lives of others, and your own will be restored!\n\
|
||||
Activate it in your hand, and it will lead to the nearest target. Attack the nuclear authentication disk with it, and you will store it.</span>")
|
||||
|
||||
/proc/only_me()
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
GLOB.highlander = TRUE
|
||||
|
||||
send_to_playing_players("<span class='boldannounce'><font size=6>THERE CAN BE ONLY ONE</font></span>")
|
||||
|
||||
for(var/obj/item/weapon/disk/nuclear/N in GLOB.poi_list)
|
||||
N.relocate() //Gets it out of bags and such
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(H.stat == DEAD || !(H.client))
|
||||
continue
|
||||
H.make_scottish()
|
||||
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used THERE CAN BE ONLY ONE!</span>")
|
||||
log_admin("[key_name(usr)] used THERE CAN BE ONLY ONE.")
|
||||
addtimer(CALLBACK(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 1), 50)
|
||||
|
||||
/client/proc/only_one_delayed()
|
||||
send_to_playing_players("<span class='userdanger'>Bagpipes begin to blare. You feel Scottish pride coming over you.</span>")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used (delayed) THERE CAN BE ONLY ONE!</span>")
|
||||
log_admin("[key_name(usr)] used delayed THERE CAN BE ONLY ONE.")
|
||||
addtimer(CALLBACK(src, .proc/only_one), 420)
|
||||
|
||||
/mob/living/carbon/human/proc/make_scottish()
|
||||
SSticker.mode.traitors += mind
|
||||
mind.special_role = "highlander"
|
||||
dna.species.species_traits |= NOGUNS //nice try jackass
|
||||
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = mind
|
||||
steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
|
||||
mind.objectives += steal_objective
|
||||
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
|
||||
hijack_objective.owner = mind
|
||||
mind.objectives += hijack_objective
|
||||
|
||||
mind.announce_objectives()
|
||||
|
||||
for(var/obj/item/I in get_equipped_items())
|
||||
qdel(I)
|
||||
for(var/obj/item/I in held_items)
|
||||
qdel(I)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(src), slot_w_uniform)
|
||||
equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(src), slot_ears)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(src), slot_head)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_l_store)
|
||||
for(var/obj/item/weapon/pinpointer/P in src)
|
||||
P.attack_self(src)
|
||||
var/obj/item/weapon/card/id/W = new(src)
|
||||
W.icon_state = "centcom"
|
||||
W.access = get_all_accesses()
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Highlander"
|
||||
W.registered_name = real_name
|
||||
W.flags |= NODROP
|
||||
W.update_label(real_name)
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
var/obj/item/weapon/claymore/highlander/H1 = new(src)
|
||||
if(!GLOB.highlander)
|
||||
H1.admin_spawned = TRUE //To prevent announcing
|
||||
put_in_hands(H1)
|
||||
H1.pickup(src) //For the stun shielding
|
||||
|
||||
var/obj/item/weapon/bloodcrawl/antiwelder = new(src)
|
||||
antiwelder.name = "compulsion of honor"
|
||||
antiwelder.desc = "You are unable to hold anything in this hand until you're the last one left!"
|
||||
antiwelder.icon_state = "bloodhand_right"
|
||||
put_in_hands(antiwelder)
|
||||
|
||||
to_chat(src, "<span class='boldannounce'>Your [H1.name] cries out for blood. Claim the lives of others, and your own will be restored!\n\
|
||||
Activate it in your hand, and it will lead to the nearest target. Attack the nuclear authentication disk with it, and you will store it.</span>")
|
||||
|
||||
/proc/only_me()
|
||||
if(!SSticker.HasRoundStarted())
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(H.stat == 2 || !(H.client)) continue
|
||||
if(is_special_character(H)) continue
|
||||
|
||||
SSticker.mode.traitors += H.mind
|
||||
H.mind.special_role = "[H.real_name] Prime"
|
||||
|
||||
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
|
||||
hijack_objective.owner = H.mind
|
||||
H.mind.objectives += hijack_objective
|
||||
|
||||
to_chat(H, "<B>You are the multiverse summoner. Activate your blade to summon copies of yourself from another universe to fight by your side.</B>")
|
||||
H.mind.announce_objectives()
|
||||
|
||||
var/datum/gang/multiverse/G = new(src, "[H.real_name]")
|
||||
SSticker.mode.gangs += G
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(H.stat == 2 || !(H.client)) continue
|
||||
if(is_special_character(H)) continue
|
||||
|
||||
SSticker.mode.traitors += H.mind
|
||||
H.mind.special_role = "[H.real_name] Prime"
|
||||
|
||||
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
|
||||
hijack_objective.owner = H.mind
|
||||
H.mind.objectives += hijack_objective
|
||||
|
||||
to_chat(H, "<B>You are the multiverse summoner. Activate your blade to summon copies of yourself from another universe to fight by your side.</B>")
|
||||
H.mind.announce_objectives()
|
||||
|
||||
var/datum/gang/multiverse/G = new(src, "[H.real_name]")
|
||||
SSticker.mode.gangs += G
|
||||
G.bosses[H.mind] = 0 //No they don't use influence but this prevents runtimes.
|
||||
G.add_gang_hud(H.mind)
|
||||
H.mind.gang_datum = G
|
||||
|
||||
var/obj/item/slot_item_ID = H.get_item_by_slot(slot_wear_id)
|
||||
qdel(slot_item_ID)
|
||||
var/obj/item/slot_item_hand = H.get_item_for_held_index(2)
|
||||
H.dropItemToGround(slot_item_hand)
|
||||
|
||||
var /obj/item/weapon/multisword/multi = new(H)
|
||||
H.put_in_hands_or_del(multi)
|
||||
|
||||
var/obj/item/weapon/card/id/W = new(H)
|
||||
W.icon_state = "centcom"
|
||||
W.access = get_all_accesses()
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Multiverse Summoner"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label(H.real_name)
|
||||
H.equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used THERE CAN BE ONLY ME!</span>")
|
||||
log_admin("[key_name(usr)] used there can be only me.")
|
||||
G.add_gang_hud(H.mind)
|
||||
H.mind.gang_datum = G
|
||||
|
||||
var/obj/item/slot_item_ID = H.get_item_by_slot(slot_wear_id)
|
||||
qdel(slot_item_ID)
|
||||
var/obj/item/slot_item_hand = H.get_item_for_held_index(2)
|
||||
H.dropItemToGround(slot_item_hand)
|
||||
|
||||
var /obj/item/weapon/multisword/multi = new(H)
|
||||
H.put_in_hands_or_del(multi)
|
||||
|
||||
var/obj/item/weapon/card/id/W = new(H)
|
||||
W.icon_state = "centcom"
|
||||
W.access = get_all_accesses()
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Multiverse Summoner"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label(H.real_name)
|
||||
H.equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used THERE CAN BE ONLY ME!</span>")
|
||||
log_admin("[key_name(usr)] used there can be only me.")
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/client/proc/play_sound(S as sound)
|
||||
set category = "Fun"
|
||||
set name = "Play Global Sound"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
var/freq = 1
|
||||
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
|
||||
freq = pick(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.1, 1.2, 1.4, 1.6, 2.0, 2.5)
|
||||
to_chat(src, "You feel the Honkmother messing with your song...")
|
||||
|
||||
var/sound/admin_sound = new()
|
||||
admin_sound.file = S
|
||||
admin_sound.priority = 250
|
||||
admin_sound.channel = CHANNEL_ADMIN
|
||||
admin_sound.frequency = freq
|
||||
admin_sound.wait = 1
|
||||
admin_sound.repeat = 0
|
||||
admin_sound.status = SOUND_STREAM
|
||||
/client/proc/play_sound(S as sound)
|
||||
set category = "Fun"
|
||||
set name = "Play Global Sound"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
var/freq = 1
|
||||
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
|
||||
freq = pick(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.1, 1.2, 1.4, 1.6, 2.0, 2.5)
|
||||
to_chat(src, "You feel the Honkmother messing with your song...")
|
||||
|
||||
var/sound/admin_sound = new()
|
||||
admin_sound.file = S
|
||||
admin_sound.priority = 250
|
||||
admin_sound.channel = CHANNEL_ADMIN
|
||||
admin_sound.frequency = freq
|
||||
admin_sound.wait = 1
|
||||
admin_sound.repeat = 0
|
||||
admin_sound.status = SOUND_STREAM
|
||||
|
||||
var/res = alert(usr, "Show the title of this song to the players?",, "No", "Yes", "Cancel")
|
||||
switch(res)
|
||||
@@ -27,46 +27,46 @@
|
||||
|
||||
log_admin("[key_name(src)] played sound [S]")
|
||||
message_admins("[key_name_admin(src)] played sound [S]")
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client.prefs.toggles & SOUND_MIDI)
|
||||
M << admin_sound
|
||||
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client.prefs.toggles & SOUND_MIDI)
|
||||
M << admin_sound
|
||||
|
||||
SSblackbox.add_details("admin_verb","Play Global Sound") //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]")
|
||||
playsound(get_turf(src.mob), S, 50, 0, 0)
|
||||
|
||||
|
||||
/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]")
|
||||
playsound(get_turf(src.mob), S, 50, 0, 0)
|
||||
SSblackbox.add_details("admin_verb","Play Local Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/set_round_end_sound(S as sound)
|
||||
set category = "Fun"
|
||||
set name = "Set Round End Sound"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
|
||||
/client/proc/set_round_end_sound(S as sound)
|
||||
set category = "Fun"
|
||||
set name = "Set Round End Sound"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
SSticker.SetRoundEndSound(S)
|
||||
|
||||
log_admin("[key_name(src)] set the round end sound to [S]")
|
||||
message_admins("[key_name_admin(src)] set the round end sound to [S]")
|
||||
|
||||
log_admin("[key_name(src)] set the round end sound to [S]")
|
||||
message_admins("[key_name_admin(src)] set the round end sound to [S]")
|
||||
SSblackbox.add_details("admin_verb","Set Round End Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/stop_sounds()
|
||||
set category = "Debug"
|
||||
set name = "Stop All Playing Sounds"
|
||||
if(!src.holder)
|
||||
return
|
||||
|
||||
log_admin("[key_name(src)] stopped all currently playing sounds.")
|
||||
message_admins("[key_name_admin(src)] stopped all currently playing sounds.")
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client)
|
||||
M << sound(null)
|
||||
|
||||
/client/proc/stop_sounds()
|
||||
set category = "Debug"
|
||||
set name = "Stop All Playing Sounds"
|
||||
if(!src.holder)
|
||||
return
|
||||
|
||||
log_admin("[key_name(src)] stopped all currently playing sounds.")
|
||||
message_admins("[key_name_admin(src)] stopped all currently playing sounds.")
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client)
|
||||
M << sound(null)
|
||||
SSblackbox.add_details("admin_verb","Stop All Playing Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
/proc/possess(obj/O in world)
|
||||
set name = "Possess Obj"
|
||||
set category = "Object"
|
||||
|
||||
if(O.dangerous_possession && config.forbid_singulo_possession)
|
||||
to_chat(usr, "[O] is too powerful for you to possess.")
|
||||
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])")
|
||||
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")
|
||||
|
||||
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
|
||||
/proc/possess(obj/O in world)
|
||||
set name = "Possess Obj"
|
||||
set category = "Object"
|
||||
|
||||
if(O.dangerous_possession && config.forbid_singulo_possession)
|
||||
to_chat(usr, "[O] is too powerful for you to possess.")
|
||||
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])")
|
||||
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")
|
||||
|
||||
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
|
||||
SSblackbox.add_details("admin_verb","Possess Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/release(obj/O 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
|
||||
usr.client.eye = usr
|
||||
usr.control_object = null
|
||||
|
||||
/proc/release(obj/O 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
|
||||
usr.client.eye = usr
|
||||
usr.control_object = null
|
||||
SSblackbox.add_details("admin_verb","Release Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/givetestverbs(mob/M in GLOB.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
|
||||
|
||||
/proc/givetestverbs(mob/M in GLOB.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
|
||||
SSblackbox.add_details("admin_verb","Give Possessing Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -65,4 +65,4 @@
|
||||
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)] [ADMIN_SET_SD_CODE]:</b> [msg]</span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
for(var/obj/machinery/computer/communications/C in GLOB.machines)
|
||||
C.overrideCooldown()
|
||||
C.overrideCooldown()
|
||||
|
||||
@@ -483,7 +483,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
var/announce_command_report = TRUE
|
||||
switch(confirm)
|
||||
if("Yes")
|
||||
priority_announce(input, null, 'sound/AI/commandreport.ogg')
|
||||
priority_announce(input, null, 'sound/ai/commandreport.ogg')
|
||||
announce_command_report = FALSE
|
||||
if("Cancel")
|
||||
return
|
||||
@@ -1055,7 +1055,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
continue
|
||||
|
||||
M.audible_message("<span class='italics'>...wabbajack...wabbajack...</span>")
|
||||
playsound(M.loc, 'sound/magic/Staff_Change.ogg', 50, 1, -1)
|
||||
playsound(M.loc, 'sound/magic/staff_change.ogg', 50, 1, -1)
|
||||
|
||||
wabbajack(M)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user