mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 20:47:10 +01:00
Merge conflict solved(?)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -25,13 +25,13 @@ world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
|
||||
if (C && ckey == C.ckey && computer_id == C.computer_id && address == C.address)
|
||||
return //don't recheck connected clients.
|
||||
|
||||
if((ckey in admin_datums) || (ckey in GLOB.deadmins))
|
||||
var/datum/admins/A = admin_datums[ckey]
|
||||
if((ckey in GLOB.admin_datums) || (ckey in GLOB.deadmins))
|
||||
var/datum/admins/A = GLOB.admin_datums[ckey]
|
||||
if(A && (A.rights & R_ADMIN))
|
||||
admin = 1
|
||||
|
||||
//Guest Checking
|
||||
if(!guests_allowed && IsGuestKey(key))
|
||||
if(!GLOB.guests_allowed && IsGuestKey(key))
|
||||
log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed")
|
||||
// message_admins("<span class='notice'>Failed Login: [key] - Guests not allowed</span>")
|
||||
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
|
||||
@@ -82,7 +82,7 @@ world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
|
||||
if(computer_id)
|
||||
cidquery = " OR computerid = '[computer_id]' "
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
|
||||
query.Execute()
|
||||
|
||||
|
||||
+232
-232
@@ -1,232 +1,232 @@
|
||||
var/CMinutes = null
|
||||
var/savefile/Banlist
|
||||
|
||||
|
||||
/proc/CheckBan(var/ckey, var/id, var/address)
|
||||
if(!Banlist) // if Banlist cannot be located for some reason
|
||||
LoadBans() // try to load the bans
|
||||
if(!Banlist) // uh oh, can't find bans!
|
||||
return 0 // ABORT ABORT ABORT
|
||||
|
||||
. = list()
|
||||
var/appeal
|
||||
if(config && config.banappeals)
|
||||
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[config.banappeals]'>[config.banappeals]</a>"
|
||||
Banlist.cd = "/base"
|
||||
if( "[ckey][id]" in Banlist.dir )
|
||||
Banlist.cd = "[ckey][id]"
|
||||
if(Banlist["temp"])
|
||||
if(!GetExp(Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]"
|
||||
else
|
||||
Banlist.cd = "/base/[ckey][id]"
|
||||
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [Banlist["bannedby"]][appeal]"
|
||||
.["reason"] = "ckey/id"
|
||||
return .
|
||||
else
|
||||
for(var/A in Banlist.dir)
|
||||
Banlist.cd = "/base/[A]"
|
||||
var/matches
|
||||
if( ckey == Banlist["key"] )
|
||||
matches += "ckey"
|
||||
if( id == Banlist["id"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "id"
|
||||
if( address == Banlist["ip"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "ip"
|
||||
|
||||
if(matches)
|
||||
if(Banlist["temp"])
|
||||
if(!GetExp(Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]"
|
||||
else
|
||||
.["desc"] = "\nReason: [Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [Banlist["bannedby"]][appeal]"
|
||||
.["reason"] = matches
|
||||
return .
|
||||
return 0
|
||||
|
||||
/proc/UpdateTime() //No idea why i made this a proc.
|
||||
CMinutes = (world.realtime / 10) / 60
|
||||
return 1
|
||||
|
||||
/hook/startup/proc/loadBans()
|
||||
return LoadBans()
|
||||
|
||||
/proc/LoadBans()
|
||||
|
||||
Banlist = new("data/banlist.bdb")
|
||||
log_admin("Loading Banlist")
|
||||
|
||||
if(!length(Banlist.dir)) log_admin("Banlist is empty.")
|
||||
|
||||
if(!Banlist.dir.Find("base"))
|
||||
log_admin("Banlist missing base dir.")
|
||||
Banlist.dir.Add("base")
|
||||
Banlist.cd = "/base"
|
||||
else if(Banlist.dir.Find("base"))
|
||||
Banlist.cd = "/base"
|
||||
|
||||
ClearTempbans()
|
||||
return 1
|
||||
|
||||
/proc/ClearTempbans()
|
||||
UpdateTime()
|
||||
|
||||
Banlist.cd = "/base"
|
||||
for(var/A in Banlist.dir)
|
||||
Banlist.cd = "/base/[A]"
|
||||
if(!Banlist["key"] || !Banlist["id"])
|
||||
RemoveBan(A)
|
||||
log_admin("Invalid Ban.")
|
||||
message_admins("Invalid Ban.")
|
||||
continue
|
||||
|
||||
if(!Banlist["temp"]) continue
|
||||
if(CMinutes >= Banlist["minutes"]) RemoveBan(A)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes, address)
|
||||
|
||||
var/bantimestamp
|
||||
|
||||
if(temp)
|
||||
UpdateTime()
|
||||
bantimestamp = CMinutes + minutes
|
||||
|
||||
Banlist.cd = "/base"
|
||||
if( Banlist.dir.Find("[ckey][computerid]") )
|
||||
to_chat(usr, "<span class='danger'>Ban already exists.</span>")
|
||||
return 0
|
||||
else
|
||||
Banlist.dir.Add("[ckey][computerid]")
|
||||
Banlist.cd = "/base/[ckey][computerid]"
|
||||
Banlist["key"] << ckey
|
||||
Banlist["id"] << computerid
|
||||
Banlist["ip"] << address
|
||||
Banlist["reason"] << reason
|
||||
Banlist["bannedby"] << bannedby
|
||||
Banlist["temp"] << temp
|
||||
if(temp)
|
||||
Banlist["minutes"] << bantimestamp
|
||||
if(!temp)
|
||||
add_note(ckey, "Permanently banned - [reason]", null, bannedby, 0)
|
||||
else
|
||||
add_note(ckey, "Banned for [minutes] minutes - [reason]", null, bannedby, 0)
|
||||
return 1
|
||||
|
||||
/proc/RemoveBan(foldername)
|
||||
var/key
|
||||
var/id
|
||||
|
||||
Banlist.cd = "/base/[foldername]"
|
||||
Banlist["key"] >> key
|
||||
Banlist["id"] >> id
|
||||
Banlist.cd = "/base"
|
||||
|
||||
if(!Banlist.dir.Remove(foldername)) return 0
|
||||
|
||||
if(!usr)
|
||||
log_admin("Ban Expired: [key]")
|
||||
message_admins("Ban Expired: [key]")
|
||||
else
|
||||
ban_unban_log_save("[key_name_admin(usr)] unbanned [key]")
|
||||
log_admin("[key_name_admin(usr)] unbanned [key]")
|
||||
message_admins("[key_name_admin(usr)] unbanned: [key]")
|
||||
feedback_inc("ban_unban",1)
|
||||
usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN)
|
||||
for(var/A in Banlist.dir)
|
||||
Banlist.cd = "/base/[A]"
|
||||
if(key == Banlist["key"] /*|| id == Banlist["id"]*/)
|
||||
Banlist.cd = "/base"
|
||||
Banlist.dir.Remove(A)
|
||||
continue
|
||||
|
||||
return 1
|
||||
|
||||
/proc/GetExp(minutes as num)
|
||||
UpdateTime()
|
||||
var/exp = minutes - CMinutes
|
||||
if(exp <= 0)
|
||||
return 0
|
||||
else
|
||||
var/timeleftstring
|
||||
if(exp >= 1440) //1440 = 1 day in minutes
|
||||
timeleftstring = "[round(exp / 1440, 0.1)] Days"
|
||||
else if(exp >= 60) //60 = 1 hour in minutes
|
||||
timeleftstring = "[round(exp / 60, 0.1)] Hours"
|
||||
else
|
||||
timeleftstring = "[exp] Minutes"
|
||||
return timeleftstring
|
||||
|
||||
/datum/admins/proc/unbanpanel()
|
||||
var/count = 0
|
||||
var/dat
|
||||
Banlist.cd = "/base"
|
||||
for(var/A in Banlist.dir)
|
||||
count++
|
||||
Banlist.cd = "/base/[A]"
|
||||
var/ref = UID()
|
||||
var/key = Banlist["key"]
|
||||
var/id = Banlist["id"]
|
||||
var/ip = Banlist["ip"]
|
||||
var/reason = Banlist["reason"]
|
||||
var/by = Banlist["bannedby"]
|
||||
var/expiry
|
||||
if(Banlist["temp"])
|
||||
expiry = GetExp(Banlist["minutes"])
|
||||
if(!expiry) expiry = "Removal Pending"
|
||||
else expiry = "Permaban"
|
||||
|
||||
dat += text("<tr><td><A href='?src=[ref];unbanf=[key][id]'>(U)</A><A href='?src=[ref];unbane=[key][id]'>(E)</A> Key: <B>[key]</B></td><td>ComputerID: <B>[id]</B></td><td>IP: <B>[ip]</B></td><td> [expiry]</td><td>(By: [by])</td><td>(Reason: [reason])</td></tr>")
|
||||
|
||||
dat += "</table>"
|
||||
dat = "<HR><B>Bans:</B> <FONT COLOR=blue>(U) = Unban , (E) = Edit Ban</FONT> - <FONT COLOR=green>([count] Bans)</FONT><HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >[dat]"
|
||||
usr << browse(dat, "window=unbanp;size=875x400")
|
||||
|
||||
//////////////////////////////////// DEBUG ////////////////////////////////////
|
||||
|
||||
/proc/CreateBans()
|
||||
|
||||
UpdateTime()
|
||||
|
||||
var/i
|
||||
var/last
|
||||
|
||||
for(i=0, i<1001, i++)
|
||||
var/a = pick(1,0)
|
||||
var/b = pick(1,0)
|
||||
if(b)
|
||||
Banlist.cd = "/base"
|
||||
Banlist.dir.Add("trash[i]trashid[i]")
|
||||
Banlist.cd = "/base/trash[i]trashid[i]"
|
||||
Banlist["key"] << "trash[i]"
|
||||
else
|
||||
Banlist.cd = "/base"
|
||||
Banlist.dir.Add("[last]trashid[i]")
|
||||
Banlist.cd = "/base/[last]trashid[i]"
|
||||
Banlist["key"] << last
|
||||
Banlist["id"] << "trashid[i]"
|
||||
Banlist["reason"] << "Trashban[i]."
|
||||
Banlist["temp"] << a
|
||||
Banlist["minutes"] << CMinutes + rand(1,2000)
|
||||
Banlist["bannedby"] << "trashmin"
|
||||
last = "trash[i]"
|
||||
|
||||
Banlist.cd = "/base"
|
||||
|
||||
/proc/ClearAllBans()
|
||||
Banlist.cd = "/base"
|
||||
for(var/A in Banlist.dir)
|
||||
RemoveBan(A)
|
||||
|
||||
GLOBAL_VAR(CMinutes)
|
||||
GLOBAL_DATUM(banlist_savefile, /savefile)
|
||||
GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
|
||||
|
||||
/proc/CheckBan(var/ckey, var/id, var/address)
|
||||
if(!GLOB.banlist_savefile) // if banlist_savefile cannot be located for some reason
|
||||
LoadBans() // try to load the bans
|
||||
if(!GLOB.banlist_savefile) // 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_savefile.cd = "/base"
|
||||
if( "[ckey][id]" in GLOB.banlist_savefile.dir )
|
||||
GLOB.banlist_savefile.cd = "[ckey][id]"
|
||||
if(GLOB.banlist_savefile["temp"])
|
||||
if(!GetExp(GLOB.banlist_savefile["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: [GetExp(GLOB.banlist_savefile["minutes"])]\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]"
|
||||
else
|
||||
GLOB.banlist_savefile.cd = "/base/[ckey][id]"
|
||||
.["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]"
|
||||
.["reason"] = "ckey/id"
|
||||
return .
|
||||
else
|
||||
for(var/A in GLOB.banlist_savefile.dir)
|
||||
GLOB.banlist_savefile.cd = "/base/[A]"
|
||||
var/matches
|
||||
if( ckey == GLOB.banlist_savefile["key"] )
|
||||
matches += "ckey"
|
||||
if( id == GLOB.banlist_savefile["id"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "id"
|
||||
if( address == GLOB.banlist_savefile["ip"] )
|
||||
if(matches)
|
||||
matches += "/"
|
||||
matches += "ip"
|
||||
|
||||
if(matches)
|
||||
if(GLOB.banlist_savefile["temp"])
|
||||
if(!GetExp(GLOB.banlist_savefile["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: [GetExp(GLOB.banlist_savefile["minutes"])]\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]"
|
||||
else
|
||||
.["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.banlist_savefile["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
|
||||
|
||||
/hook/startup/proc/loadBans()
|
||||
return LoadBans()
|
||||
|
||||
/proc/LoadBans()
|
||||
|
||||
GLOB.banlist_savefile = new("data/banlist.bdb")
|
||||
log_admin("Loading Banlist")
|
||||
|
||||
if(!length(GLOB.banlist_savefile.dir)) log_admin("Banlist is empty.")
|
||||
|
||||
if(!GLOB.banlist_savefile.dir.Find("base"))
|
||||
log_admin("Banlist missing base dir.")
|
||||
GLOB.banlist_savefile.dir.Add("base")
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
else if(GLOB.banlist_savefile.dir.Find("base"))
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
|
||||
ClearTempbans()
|
||||
return 1
|
||||
|
||||
/proc/ClearTempbans()
|
||||
UpdateTime()
|
||||
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
for(var/A in GLOB.banlist_savefile.dir)
|
||||
GLOB.banlist_savefile.cd = "/base/[A]"
|
||||
if(!GLOB.banlist_savefile["key"] || !GLOB.banlist_savefile["id"])
|
||||
RemoveBan(A)
|
||||
log_admin("Invalid Ban.")
|
||||
message_admins("Invalid Ban.")
|
||||
continue
|
||||
|
||||
if(!GLOB.banlist_savefile["temp"]) continue
|
||||
if(GLOB.CMinutes >= GLOB.banlist_savefile["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_savefile.cd = "/base"
|
||||
if( GLOB.banlist_savefile.dir.Find("[ckey][computerid]") )
|
||||
to_chat(usr, "<span class='danger'>Ban already exists.</span>")
|
||||
return 0
|
||||
else
|
||||
GLOB.banlist_savefile.dir.Add("[ckey][computerid]")
|
||||
GLOB.banlist_savefile.cd = "/base/[ckey][computerid]"
|
||||
GLOB.banlist_savefile["key"] << ckey
|
||||
GLOB.banlist_savefile["id"] << computerid
|
||||
GLOB.banlist_savefile["ip"] << address
|
||||
GLOB.banlist_savefile["reason"] << reason
|
||||
GLOB.banlist_savefile["bannedby"] << bannedby
|
||||
GLOB.banlist_savefile["temp"] << temp
|
||||
if(temp)
|
||||
GLOB.banlist_savefile["minutes"] << bantimestamp
|
||||
if(!temp)
|
||||
add_note(ckey, "Permanently banned - [reason]", null, bannedby, 0)
|
||||
else
|
||||
add_note(ckey, "Banned for [minutes] minutes - [reason]", null, bannedby, 0)
|
||||
return 1
|
||||
|
||||
/proc/RemoveBan(foldername)
|
||||
var/key
|
||||
var/id
|
||||
|
||||
GLOB.banlist_savefile.cd = "/base/[foldername]"
|
||||
GLOB.banlist_savefile["key"] >> key
|
||||
GLOB.banlist_savefile["id"] >> id
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
|
||||
if(!GLOB.banlist_savefile.dir.Remove(foldername)) return 0
|
||||
|
||||
if(!usr)
|
||||
log_admin("Ban Expired: [key]")
|
||||
message_admins("Ban Expired: [key]")
|
||||
else
|
||||
ban_unban_log_save("[key_name_admin(usr)] unbanned [key]")
|
||||
log_admin("[key_name_admin(usr)] unbanned [key]")
|
||||
message_admins("[key_name_admin(usr)] unbanned: [key]")
|
||||
feedback_inc("ban_unban",1)
|
||||
usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN)
|
||||
for(var/A in GLOB.banlist_savefile.dir)
|
||||
GLOB.banlist_savefile.cd = "/base/[A]"
|
||||
if(key == GLOB.banlist_savefile["key"] /*|| id == GLOB.banlist_savefile["id"]*/)
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
GLOB.banlist_savefile.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
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
for(var/A in GLOB.banlist_savefile.dir)
|
||||
count++
|
||||
GLOB.banlist_savefile.cd = "/base/[A]"
|
||||
var/ref = UID()
|
||||
var/key = GLOB.banlist_savefile["key"]
|
||||
var/id = GLOB.banlist_savefile["id"]
|
||||
var/ip = GLOB.banlist_savefile["ip"]
|
||||
var/reason = GLOB.banlist_savefile["reason"]
|
||||
var/by = GLOB.banlist_savefile["bannedby"]
|
||||
var/expiry
|
||||
if(GLOB.banlist_savefile["temp"])
|
||||
expiry = GetExp(GLOB.banlist_savefile["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_savefile.cd = "/base"
|
||||
GLOB.banlist_savefile.dir.Add("trash[i]trashid[i]")
|
||||
GLOB.banlist_savefile.cd = "/base/trash[i]trashid[i]"
|
||||
GLOB.banlist_savefile["key"] << "trash[i]"
|
||||
else
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
GLOB.banlist_savefile.dir.Add("[last]trashid[i]")
|
||||
GLOB.banlist_savefile.cd = "/base/[last]trashid[i]"
|
||||
GLOB.banlist_savefile["key"] << last
|
||||
GLOB.banlist_savefile["id"] << "trashid[i]"
|
||||
GLOB.banlist_savefile["reason"] << "Trashban[i]."
|
||||
GLOB.banlist_savefile["temp"] << a
|
||||
GLOB.banlist_savefile["minutes"] << GLOB.CMinutes + rand(1,2000)
|
||||
GLOB.banlist_savefile["bannedby"] << "trashmin"
|
||||
last = "trash[i]"
|
||||
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
|
||||
/proc/ClearAllBans()
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
for(var/A in GLOB.banlist_savefile.dir)
|
||||
RemoveBan(A)
|
||||
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
//By Carnwennan
|
||||
//fetches an external list and processes it into a list of ip addresses.
|
||||
//It then stores the processed list into a savefile for later use
|
||||
#define TORFILE "data/ToR_ban.bdb"
|
||||
#define TOR_UPDATE_INTERVAL 216000 //~6 hours
|
||||
|
||||
/proc/ToRban_isbanned(var/ip_address)
|
||||
var/savefile/F = new(TORFILE)
|
||||
if(F)
|
||||
if( ip_address in F.dir )
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/ToRban_autoupdate()
|
||||
var/savefile/F = new(TORFILE)
|
||||
if(F)
|
||||
var/last_update
|
||||
F["last_update"] >> last_update
|
||||
if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while
|
||||
ToRban_update()
|
||||
return
|
||||
|
||||
/proc/ToRban_update()
|
||||
spawn(0)
|
||||
log_world("Downloading updated ToR data...")
|
||||
var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
|
||||
|
||||
var/list/rawlist = file2list(http["CONTENT"])
|
||||
if(rawlist.len)
|
||||
fdel(TORFILE)
|
||||
var/savefile/F = new(TORFILE)
|
||||
for( var/line in rawlist )
|
||||
if(!line) continue
|
||||
if( copytext(line,1,12) == "ExitAddress" )
|
||||
var/cleaned = copytext(line,13,length(line)-19)
|
||||
if(!cleaned) continue
|
||||
F[cleaned] << 1
|
||||
to_chat(F["last_update"], world.realtime)
|
||||
log_world("ToR data updated!")
|
||||
if(usr)
|
||||
to_chat(usr, "ToRban updated.")
|
||||
return 1
|
||||
log_world("ToR data update aborted: no data.")
|
||||
return 0
|
||||
|
||||
/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find"))
|
||||
set name = "ToRban"
|
||||
set category = "Server"
|
||||
if(!holder) return
|
||||
switch(task)
|
||||
if("update")
|
||||
ToRban_update()
|
||||
if("toggle")
|
||||
if(config)
|
||||
if(config.ToRban)
|
||||
config.ToRban = 0
|
||||
message_admins("<font color='red'>ToR banning disabled.</font>")
|
||||
else
|
||||
config.ToRban = 1
|
||||
message_admins("<font colot='green'>ToR banning enabled.</font>")
|
||||
if("show")
|
||||
var/savefile/F = new(TORFILE)
|
||||
var/dat
|
||||
if( length(F.dir) )
|
||||
for( var/i=1, i<=length(F.dir), i++ )
|
||||
dat += "<tr><td>#[i]</td><td> [F.dir[i]]</td></tr>"
|
||||
dat = "<table width='100%'>[dat]</table>"
|
||||
else
|
||||
dat = "No addresses in list."
|
||||
src << browse(dat,"window=ToRban_show")
|
||||
if("remove")
|
||||
var/savefile/F = new(TORFILE)
|
||||
var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir
|
||||
if(choice)
|
||||
F.dir.Remove(choice)
|
||||
to_chat(src, "<b>Address removed</b>")
|
||||
if("remove all")
|
||||
to_chat(src, "<b>[TORFILE] was [fdel(TORFILE)?"":"not "]removed.</b>")
|
||||
if("find")
|
||||
var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text
|
||||
if(input)
|
||||
if(ToRban_isbanned(input))
|
||||
to_chat(src, "<font color='green'><b>Address is a known ToR address</b></font>")
|
||||
else
|
||||
to_chat(src, "<font color='red'><b>Address is not a known ToR address</b></font>")
|
||||
return
|
||||
|
||||
#undef TORFILE
|
||||
#undef TOR_UPDATE_INTERVAL
|
||||
//By Carnwennan
|
||||
//fetches an external list and processes it into a list of ip addresses.
|
||||
//It then stores the processed list into a savefile for later use
|
||||
#define TORFILE "data/ToR_ban.bdb"
|
||||
#define TOR_UPDATE_INTERVAL 216000 //~6 hours
|
||||
|
||||
/proc/ToRban_isbanned(var/ip_address)
|
||||
var/savefile/F = new(TORFILE)
|
||||
if(F)
|
||||
if( ip_address in F.dir )
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/ToRban_autoupdate()
|
||||
var/savefile/F = new(TORFILE)
|
||||
if(F)
|
||||
var/last_update
|
||||
F["last_update"] >> last_update
|
||||
if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while
|
||||
ToRban_update()
|
||||
return
|
||||
|
||||
/proc/ToRban_update()
|
||||
spawn(0)
|
||||
log_world("Downloading updated ToR data...")
|
||||
var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
|
||||
|
||||
var/list/rawlist = file2list(http["CONTENT"])
|
||||
if(rawlist.len)
|
||||
fdel(TORFILE)
|
||||
var/savefile/F = new(TORFILE)
|
||||
for( var/line in rawlist )
|
||||
if(!line) continue
|
||||
if( copytext(line,1,12) == "ExitAddress" )
|
||||
var/cleaned = copytext(line,13,length(line)-19)
|
||||
if(!cleaned) continue
|
||||
F[cleaned] << 1
|
||||
to_chat(F["last_update"], world.realtime)
|
||||
log_world("ToR data updated!")
|
||||
if(usr)
|
||||
to_chat(usr, "ToRban updated.")
|
||||
return 1
|
||||
log_world("ToR data update aborted: no data.")
|
||||
return 0
|
||||
|
||||
/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find"))
|
||||
set name = "ToRban"
|
||||
set category = "Server"
|
||||
if(!holder) return
|
||||
switch(task)
|
||||
if("update")
|
||||
ToRban_update()
|
||||
if("toggle")
|
||||
if(config)
|
||||
if(config.ToRban)
|
||||
config.ToRban = 0
|
||||
message_admins("<font color='red'>ToR banning disabled.</font>")
|
||||
else
|
||||
config.ToRban = 1
|
||||
message_admins("<font colot='green'>ToR banning enabled.</font>")
|
||||
if("show")
|
||||
var/savefile/F = new(TORFILE)
|
||||
var/dat
|
||||
if( length(F.dir) )
|
||||
for( var/i=1, i<=length(F.dir), i++ )
|
||||
dat += "<tr><td>#[i]</td><td> [F.dir[i]]</td></tr>"
|
||||
dat = "<table width='100%'>[dat]</table>"
|
||||
else
|
||||
dat = "No addresses in list."
|
||||
src << browse(dat,"window=ToRban_show")
|
||||
if("remove")
|
||||
var/savefile/F = new(TORFILE)
|
||||
var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir
|
||||
if(choice)
|
||||
F.dir.Remove(choice)
|
||||
to_chat(src, "<b>Address removed</b>")
|
||||
if("remove all")
|
||||
to_chat(src, "<b>[TORFILE] was [fdel(TORFILE)?"":"not "]removed.</b>")
|
||||
if("find")
|
||||
var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text
|
||||
if(input)
|
||||
if(ToRban_isbanned(input))
|
||||
to_chat(src, "<font color='green'><b>Address is a known ToR address</b></font>")
|
||||
else
|
||||
to_chat(src, "<font color='red'><b>Address is not a known ToR address</b></font>")
|
||||
return
|
||||
|
||||
#undef TORFILE
|
||||
#undef TOR_UPDATE_INTERVAL
|
||||
|
||||
+1094
-1092
File diff suppressed because it is too large
Load Diff
@@ -23,18 +23,18 @@
|
||||
if(!message) return
|
||||
var/F = investigate_subject2file(subject)
|
||||
if(!F) return
|
||||
investigate_log_subjects |= subject
|
||||
GLOB.investigate_log_subjects |= subject
|
||||
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
|
||||
|
||||
/proc/log_investigate(message, subject)
|
||||
if(!message) return
|
||||
var/F = investigate_subject2file(subject)
|
||||
if(!F) return
|
||||
investigate_log_subjects |= subject
|
||||
GLOB.investigate_log_subjects |= subject
|
||||
F << "<small>[time_stamp()] || [message]<br>"
|
||||
|
||||
//ADMINVERBS
|
||||
/client/proc/investigate_show( subject in investigate_log_subjects )
|
||||
/client/proc/investigate_show( subject in GLOB.investigate_log_subjects )
|
||||
set name = "Investigate"
|
||||
set category = "Admin"
|
||||
if(!holder) return
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set category = "Server"
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
var/memotask = input(usr,"Choose task.","Memo") in list("Show","Write","Edit","Remove")
|
||||
@@ -16,13 +16,13 @@
|
||||
return
|
||||
if(!task)
|
||||
return
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(src.ckey)
|
||||
switch(task)
|
||||
if("Write")
|
||||
var/DBQuery/query_memocheck = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE ckey = '[sql_ckey]'")
|
||||
var/DBQuery/query_memocheck = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_memocheck.Execute())
|
||||
var/err = query_memocheck.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
|
||||
@@ -35,7 +35,7 @@
|
||||
return
|
||||
memotext = sanitizeSQL(memotext)
|
||||
var/timestamp = SQLtime()
|
||||
var/DBQuery/query_memoadd = dbcon.NewQuery("INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES ('[sql_ckey]', '[memotext]', '[timestamp]')")
|
||||
var/DBQuery/query_memoadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES ('[sql_ckey]', '[memotext]', '[timestamp]')")
|
||||
if(!query_memoadd.Execute())
|
||||
var/err = query_memoadd.ErrorMsg()
|
||||
log_game("SQL ERROR adding new memo. Error : \[[err]\]\n")
|
||||
@@ -43,7 +43,7 @@
|
||||
log_admin("[key_name(src)] has set a memo: [memotext]")
|
||||
message_admins("[key_name_admin(src)] has set a memo:<br>[memotext]")
|
||||
if("Edit")
|
||||
var/DBQuery/query_memolist = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
|
||||
var/DBQuery/query_memolist = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
|
||||
if(!query_memolist.Execute())
|
||||
var/err = query_memolist.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
|
||||
@@ -59,7 +59,7 @@
|
||||
if(!target_ckey)
|
||||
return
|
||||
var/target_sql_ckey = sanitizeSQL(target_ckey)
|
||||
var/DBQuery/query_memofind = dbcon.NewQuery("SELECT memotext FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_memofind = GLOB.dbcon.NewQuery("SELECT memotext FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_memofind.Execute())
|
||||
var/err = query_memofind.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining memotext from memo table. Error : \[[err]\]\n")
|
||||
@@ -72,7 +72,7 @@
|
||||
new_memo = sanitizeSQL(new_memo)
|
||||
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from<br>[old_memo]<br>to<br>[new_memo]<hr>"
|
||||
edit_text = sanitizeSQL(edit_text)
|
||||
var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!update_query.Execute())
|
||||
var/err = update_query.ErrorMsg()
|
||||
log_game("SQL ERROR editing memo. Error : \[[err]\]\n")
|
||||
@@ -84,7 +84,7 @@
|
||||
log_admin("[key_name(src)] has edited [target_sql_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"")
|
||||
message_admins("[key_name_admin(src)] has edited [target_sql_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"")
|
||||
if("Show")
|
||||
var/DBQuery/query_memoshow = dbcon.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]")
|
||||
var/DBQuery/query_memoshow = GLOB.dbcon.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]")
|
||||
if(!query_memoshow.Execute())
|
||||
var/err = query_memoshow.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey, memotext, timestamp, last_editor from memo table. Error : \[[err]\]\n")
|
||||
@@ -104,7 +104,7 @@
|
||||
else if(!silent)
|
||||
to_chat(src, "No memos found in database.")
|
||||
if("Remove")
|
||||
var/DBQuery/query_memodellist = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
|
||||
var/DBQuery/query_memodellist = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
|
||||
if(!query_memodellist.Execute())
|
||||
var/err = query_memodellist.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
|
||||
@@ -120,7 +120,7 @@
|
||||
if(!target_ckey)
|
||||
return
|
||||
var/target_sql_ckey = sanitizeSQL(target_ckey)
|
||||
var/DBQuery/query_memodel = dbcon.NewQuery("DELETE FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_memodel = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_memodel.Execute())
|
||||
var/err = query_memodel.ErrorMsg()
|
||||
log_game("SQL ERROR removing memo. Error : \[[err]\]\n")
|
||||
|
||||
+172
-160
@@ -1,160 +1,172 @@
|
||||
var/list/admin_ranks = list() //list of all ranks with associated rights
|
||||
|
||||
//load our rank - > rights associations
|
||||
/proc/load_admin_ranks()
|
||||
admin_ranks.Cut()
|
||||
|
||||
var/previous_rights = 0
|
||||
|
||||
//load text from file
|
||||
var/list/Lines = file2list("config/admin_ranks.txt")
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in Lines)
|
||||
if(!length(line)) continue
|
||||
if(copytext(line,1,2) == "#") continue
|
||||
|
||||
var/list/List = splittext(line,"+")
|
||||
if(!List.len) continue
|
||||
|
||||
var/rank = ckeyEx(List[1])
|
||||
switch(rank)
|
||||
if(null,"") continue
|
||||
if("Removed") continue //Reserved
|
||||
|
||||
var/rights = 0
|
||||
for(var/i=2, i<=List.len, i++)
|
||||
switch(ckey(List[i]))
|
||||
if("@","prev") rights |= previous_rights
|
||||
if("buildmode","build") rights |= R_BUILDMODE
|
||||
if("admin") rights |= R_ADMIN
|
||||
if("ban") rights |= R_BAN
|
||||
if("event") rights |= R_EVENT
|
||||
if("server") rights |= R_SERVER
|
||||
if("debug") rights |= R_DEBUG
|
||||
if("permissions","rights") rights |= R_PERMISSIONS
|
||||
if("possess") rights |= R_POSSESS
|
||||
if("stealth") rights |= R_STEALTH
|
||||
if("rejuv","rejuvinate") rights |= R_REJUVINATE
|
||||
if("varedit") rights |= R_VAREDIT
|
||||
if("everything","host","all") rights |= R_HOST
|
||||
if("sound","sounds") rights |= R_SOUNDS
|
||||
if("spawn","create") rights |= R_SPAWN
|
||||
if("mod") rights |= R_MOD
|
||||
if("mentor") rights |= R_MENTOR
|
||||
if("proccall") rights |= R_PROCCALL
|
||||
|
||||
admin_ranks[rank] = rights
|
||||
previous_rights = rights
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Permission Sets Built:\n"
|
||||
for(var/rank in admin_ranks)
|
||||
msg += "\t[rank] - [admin_ranks[rank]]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
/hook/startup/proc/loadAdmins()
|
||||
load_admins()
|
||||
return 1
|
||||
|
||||
/proc/load_admins()
|
||||
//clear the datums references
|
||||
admin_datums.Cut()
|
||||
for(var/client/C in GLOB.admins)
|
||||
C.remove_admin_verbs()
|
||||
C.holder = null
|
||||
GLOB.admins.Cut()
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
load_admin_ranks()
|
||||
|
||||
//load text from file
|
||||
var/list/Lines = file2list("config/admins.txt")
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in Lines)
|
||||
if(!length(line)) continue
|
||||
if(copytext(line,1,2) == "#") continue
|
||||
|
||||
//Split the line at every "-"
|
||||
var/list/List = splittext(line, "-")
|
||||
if(!List.len) continue
|
||||
|
||||
//ckey is before the first "-"
|
||||
var/ckey = ckey(List[1])
|
||||
if(!ckey) continue
|
||||
|
||||
//rank follows the first "-"
|
||||
var/rank = ""
|
||||
if(List.len >= 2)
|
||||
rank = ckeyEx(List[2])
|
||||
|
||||
//load permissions associated with this rank
|
||||
var/rights = admin_ranks[rank]
|
||||
|
||||
//create the admin datum and store it for later use
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
|
||||
else
|
||||
//The current admin system uses SQL
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]")
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
var/rank = query.item[2]
|
||||
if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes.
|
||||
|
||||
var/rights = query.item[4]
|
||||
if(istext(rights)) rights = text2num(rights)
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
if(!admin_datums)
|
||||
log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Admins Built:\n"
|
||||
for(var/ckey in admin_datums)
|
||||
var/rank
|
||||
var/datum/admins/D = admin_datums[ckey]
|
||||
if(D) rank = D.rank
|
||||
msg += "\t[ckey] - [rank]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TESTING
|
||||
/client/verb/changerank(newrank in admin_ranks)
|
||||
if(holder)
|
||||
holder.rank = newrank
|
||||
holder.rights = admin_ranks[newrank]
|
||||
else
|
||||
holder = new /datum/admins(newrank,admin_ranks[newrank],ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
|
||||
/client/verb/changerights(newrights as num)
|
||||
if(holder)
|
||||
holder.rights = newrights
|
||||
else
|
||||
holder = new /datum/admins("testing",newrights,ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
|
||||
#endif
|
||||
GLOBAL_LIST_EMPTY(admin_ranks) //list of all ranks with associated rights
|
||||
GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
|
||||
|
||||
//load our rank - > rights associations
|
||||
/proc/load_admin_ranks()
|
||||
GLOB.admin_ranks.Cut()
|
||||
|
||||
var/previous_rights = 0
|
||||
|
||||
//load text from file
|
||||
var/list/Lines = file2list("config/admin_ranks.txt")
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in Lines)
|
||||
if(!length(line)) continue
|
||||
if(copytext(line,1,2) == "#") continue
|
||||
|
||||
var/list/List = splittext(line,"+")
|
||||
if(!List.len) continue
|
||||
|
||||
var/rank = ckeyEx(List[1])
|
||||
switch(rank)
|
||||
if(null,"") continue
|
||||
if("Removed") continue //Reserved
|
||||
|
||||
var/rights = 0
|
||||
for(var/i=2, i<=List.len, i++)
|
||||
switch(ckey(List[i]))
|
||||
if("@","prev") rights |= previous_rights
|
||||
if("buildmode","build") rights |= R_BUILDMODE
|
||||
if("admin") rights |= R_ADMIN
|
||||
if("ban") rights |= R_BAN
|
||||
if("event") rights |= R_EVENT
|
||||
if("server") rights |= R_SERVER
|
||||
if("debug") rights |= R_DEBUG
|
||||
if("permissions","rights") rights |= R_PERMISSIONS
|
||||
if("possess") rights |= R_POSSESS
|
||||
if("stealth") rights |= R_STEALTH
|
||||
if("rejuv","rejuvinate") rights |= R_REJUVINATE
|
||||
if("varedit") rights |= R_VAREDIT
|
||||
if("everything","host","all") rights |= R_HOST
|
||||
if("sound","sounds") rights |= R_SOUNDS
|
||||
if("spawn","create") rights |= R_SPAWN
|
||||
if("mod") rights |= R_MOD
|
||||
if("mentor") rights |= R_MENTOR
|
||||
if("proccall") rights |= R_PROCCALL
|
||||
if("viewruntimes") rights |= R_VIEWRUNTIMES
|
||||
|
||||
GLOB.admin_ranks[rank] = rights
|
||||
previous_rights = rights
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Permission Sets Built:\n"
|
||||
for(var/rank in GLOB.admin_ranks)
|
||||
msg += "\t[rank] - [GLOB.admin_ranks[rank]]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
/hook/startup/proc/loadAdmins()
|
||||
load_admins()
|
||||
return 1
|
||||
|
||||
/proc/load_admins()
|
||||
//clear the datums references
|
||||
GLOB.admin_datums.Cut()
|
||||
for(var/client/C in GLOB.admins)
|
||||
C.remove_admin_verbs()
|
||||
C.holder = null
|
||||
GLOB.admins.Cut()
|
||||
|
||||
// Remove all profiler access
|
||||
for(var/A in world.GetConfig("admin"))
|
||||
world.SetConfig("APP/admin", A, null)
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
load_admin_ranks()
|
||||
|
||||
//load text from file
|
||||
var/list/Lines = file2list("config/admins.txt")
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in Lines)
|
||||
if(!length(line)) continue
|
||||
if(copytext(line,1,2) == "#") continue
|
||||
|
||||
//Split the line at every "-"
|
||||
var/list/List = splittext(line, "-")
|
||||
if(!List.len) continue
|
||||
|
||||
//ckey is before the first "-"
|
||||
var/ckey = ckey(List[1])
|
||||
if(!ckey) continue
|
||||
|
||||
//rank follows the first "-"
|
||||
var/rank = ""
|
||||
if(List.len >= 2)
|
||||
rank = ckeyEx(List[2])
|
||||
|
||||
//load permissions associated with this rank
|
||||
var/rights = GLOB.admin_ranks[rank]
|
||||
|
||||
//create the admin datum and store it for later use
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
|
||||
else
|
||||
//The current admin system uses SQL
|
||||
|
||||
establish_db_connection()
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]")
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
var/rank = query.item[2]
|
||||
if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes.
|
||||
|
||||
var/rights = query.item[4]
|
||||
if(istext(rights)) rights = text2num(rights)
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
if(!GLOB.admin_datums)
|
||||
log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
#ifdef TESTING
|
||||
var/msg = "Admins Built:\n"
|
||||
for(var/ckey in GLOB.admin_datums)
|
||||
var/rank
|
||||
var/datum/admins/D = GLOB.admin_datums[ckey]
|
||||
if(D) rank = D.rank
|
||||
msg += "\t[ckey] - [rank]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TESTING
|
||||
/client/verb/changerank(newrank in GLOB.admin_ranks)
|
||||
if(holder)
|
||||
holder.rank = newrank
|
||||
holder.rights = GLOB.admin_ranks[newrank]
|
||||
else
|
||||
holder = new /datum/admins(newrank,GLOB.admin_ranks[newrank],ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
|
||||
/client/verb/changerights(newrights as num)
|
||||
if(holder)
|
||||
holder.rights = newrights
|
||||
else
|
||||
holder = new /datum/admins("testing",newrights,ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
|
||||
#endif
|
||||
|
||||
+1027
-1032
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,22 @@
|
||||
//ban people from using custom names and appearances. that'll show 'em.
|
||||
|
||||
var/appearanceban_runonce //Updates legacy bans with new info
|
||||
var/appearance_keylist[0] //to store the keys
|
||||
GLOBAL_VAR(appearanceban_runonce) //Updates legacy bans with new info
|
||||
GLOBAL_LIST_EMPTY(appearance_keylist) //to store the keys
|
||||
|
||||
/proc/appearance_fullban(mob/M, reason)
|
||||
if(!M || !M.key) return
|
||||
appearance_keylist.Add(text("[M.ckey] ## [reason]"))
|
||||
GLOB.appearance_keylist.Add(text("[M.ckey] ## [reason]"))
|
||||
appearance_savebanfile()
|
||||
|
||||
/proc/appearance_client_fullban(ckey)
|
||||
if(!ckey) return
|
||||
appearance_keylist.Add(text("[ckey]"))
|
||||
GLOB.appearance_keylist.Add(text("[ckey]"))
|
||||
appearance_savebanfile()
|
||||
|
||||
//returns a reason if M is banned, returns 0 otherwise
|
||||
/proc/appearance_isbanned(mob/M)
|
||||
if(M)
|
||||
for(var/s in appearance_keylist)
|
||||
for(var/s in GLOB.appearance_keylist)
|
||||
if(findtext(s, "[M.ckey]") == 1)
|
||||
var/startpos = findtext(s, "## ") + 3
|
||||
if(startpos && startpos < length(s))
|
||||
@@ -43,12 +43,12 @@ DEBUG
|
||||
/proc/appearance_loadbanfile()
|
||||
if(config.ban_legacy_system)
|
||||
var/savefile/S=new("data/appearance_full.ban")
|
||||
S["keys[0]"] >> appearance_keylist
|
||||
S["keys[0]"] >> GLOB.appearance_keylist
|
||||
log_admin("Loading appearance_rank")
|
||||
S["runonce"] >> appearanceban_runonce
|
||||
S["runonce"] >> GLOB.appearanceban_runonce
|
||||
|
||||
if(!length(appearance_keylist))
|
||||
appearance_keylist=list()
|
||||
if(!length(GLOB.appearance_keylist))
|
||||
GLOB.appearance_keylist=list()
|
||||
log_admin("appearance_keylist was empty")
|
||||
else
|
||||
if(!establish_db_connection())
|
||||
@@ -58,17 +58,17 @@ DEBUG
|
||||
return
|
||||
|
||||
//appearance bans
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
|
||||
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
|
||||
query.Execute()
|
||||
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
|
||||
appearance_keylist.Add("[ckey]")
|
||||
GLOB.appearance_keylist.Add("[ckey]")
|
||||
|
||||
/proc/appearance_savebanfile()
|
||||
var/savefile/S=new("data/appearance_full.ban")
|
||||
to_chat(S["keys[0]"], appearance_keylist)
|
||||
to_chat(S["keys[0]"], GLOB.appearance_keylist)
|
||||
|
||||
/proc/appearance_unban(mob/M)
|
||||
appearance_remove("[M.ckey]")
|
||||
@@ -76,18 +76,18 @@ DEBUG
|
||||
|
||||
|
||||
/proc/appearance_updatelegacybans()
|
||||
if(!appearanceban_runonce)
|
||||
if(!GLOB.appearanceban_runonce)
|
||||
log_admin("Updating appearancefile!")
|
||||
// Updates bans.. Or fixes them. Either way.
|
||||
for(var/T in appearance_keylist)
|
||||
for(var/T in GLOB.appearance_keylist)
|
||||
if(!T) continue
|
||||
appearanceban_runonce++ //don't run this update again
|
||||
GLOB.appearanceban_runonce++ //don't run this update again
|
||||
|
||||
|
||||
/proc/appearance_remove(X)
|
||||
for(var/i = 1; i <= length(appearance_keylist); i++)
|
||||
if( findtext(appearance_keylist[i], "[X]") )
|
||||
appearance_keylist.Remove(appearance_keylist[i])
|
||||
for(var/i = 1; i <= length(GLOB.appearance_keylist); i++)
|
||||
if( findtext(GLOB.appearance_keylist[i], "[X]") )
|
||||
GLOB.appearance_keylist.Remove(GLOB.appearance_keylist[i])
|
||||
appearance_savebanfile()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
+179
-179
@@ -1,179 +1,179 @@
|
||||
var/jobban_runonce // Updates legacy bans with new info
|
||||
var/jobban_keylist[0] // Linear list of jobban strings, kept around for the legacy system
|
||||
var/jobban_assoclist[0] // Associative list, for efficiency
|
||||
|
||||
// Matches string-based jobbans into ckey, rank, and reason groups
|
||||
var/regex/jobban_regex = regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## (.+))?")
|
||||
|
||||
/proc/jobban_assoc_insert(ckey, rank, reason)
|
||||
if(!ckey || !rank)
|
||||
return
|
||||
if(!jobban_assoclist[ckey])
|
||||
jobban_assoclist[ckey] = list()
|
||||
jobban_assoclist[ckey][rank] = reason || "Reason Unspecified"
|
||||
|
||||
/proc/jobban_fullban(mob/M, rank, reason)
|
||||
if(!M || !M.key)
|
||||
return
|
||||
jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]"))
|
||||
jobban_assoc_insert(M.ckey, rank, reason)
|
||||
if(config.ban_legacy_system)
|
||||
jobban_savebanfile()
|
||||
|
||||
/proc/jobban_client_fullban(ckey, rank)
|
||||
if(!ckey || !rank)
|
||||
return
|
||||
jobban_keylist.Add(text("[ckey] - [rank]"))
|
||||
jobban_assoc_insert(ckey, rank)
|
||||
if(config.ban_legacy_system)
|
||||
jobban_savebanfile()
|
||||
|
||||
//returns a reason if M is banned from rank, returns 0 otherwise
|
||||
/proc/jobban_isbanned(mob/M, rank)
|
||||
if(!M || !rank)
|
||||
return 0
|
||||
|
||||
if(config.guest_jobban && guest_jobbans(rank))
|
||||
if(IsGuestKey(M.key))
|
||||
return "Guest Job-ban"
|
||||
|
||||
if(jobban_assoclist[M.ckey])
|
||||
return jobban_assoclist[M.ckey][rank]
|
||||
else
|
||||
return 0
|
||||
|
||||
/*
|
||||
DEBUG
|
||||
/mob/verb/list_all_jobbans()
|
||||
set name = "list all jobbans"
|
||||
|
||||
for(var/s in jobban_keylist)
|
||||
to_chat(world, s)
|
||||
|
||||
/mob/verb/reload_jobbans()
|
||||
set name = "reload jobbans"
|
||||
|
||||
jobban_loadbanfile()
|
||||
*/
|
||||
|
||||
/hook/startup/proc/loadJobBans()
|
||||
jobban_loadbanfile()
|
||||
return 1
|
||||
|
||||
/proc/jobban_loadbanfile()
|
||||
if(config.ban_legacy_system)
|
||||
var/savefile/S=new("data/job_full.ban")
|
||||
S["keys[0]"] >> jobban_keylist
|
||||
log_admin("Loading jobban_rank")
|
||||
S["runonce"] >> jobban_runonce
|
||||
|
||||
if(!length(jobban_keylist))
|
||||
jobban_keylist=list()
|
||||
log_admin("jobban_keylist was empty")
|
||||
|
||||
for(var/s in jobban_keylist)
|
||||
if(jobban_regex.Find(s))
|
||||
jobban_assoc_insert(jobban_regex.group[1], jobban_regex.group[2], jobban_regex.group[3])
|
||||
else
|
||||
log_runtime(EXCEPTION("Skipping malformed job ban: [s]"))
|
||||
else
|
||||
if(!establish_db_connection())
|
||||
log_world("Database connection failed. Reverting to the legacy ban system.")
|
||||
config.ban_legacy_system = 1
|
||||
jobban_loadbanfile()
|
||||
return
|
||||
|
||||
//Job permabans
|
||||
var/DBQuery/permabans = dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
|
||||
permabans.Execute()
|
||||
// Job tempbans
|
||||
var/DBQuery/tempbans = dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
|
||||
tempbans.Execute()
|
||||
|
||||
while(TRUE)
|
||||
var/ckey
|
||||
var/job
|
||||
if(permabans.NextRow())
|
||||
ckey = permabans.item[1]
|
||||
job = permabans.item[2]
|
||||
else if(tempbans.NextRow())
|
||||
ckey = tempbans.item[1]
|
||||
job = tempbans.item[2]
|
||||
else
|
||||
break
|
||||
|
||||
jobban_keylist.Add("[ckey] - [job]")
|
||||
jobban_assoc_insert(ckey, job)
|
||||
|
||||
/proc/jobban_savebanfile()
|
||||
var/savefile/S=new("data/job_full.ban")
|
||||
S["keys[0]"] << jobban_keylist
|
||||
|
||||
/proc/jobban_unban(mob/M, rank)
|
||||
jobban_remove("[M.ckey] - [rank]")
|
||||
|
||||
/proc/jobban_unban_client(ckey, rank)
|
||||
jobban_remove("[ckey] - [rank]")
|
||||
|
||||
/proc/ban_unban_log_save(var/formatted_log)
|
||||
text2file(formatted_log,"data/ban_unban_log.txt")
|
||||
|
||||
|
||||
/proc/jobban_remove(X)
|
||||
for(var/i = 1; i <= length(jobban_keylist); i++)
|
||||
if( findtext(jobban_keylist[i], "[X]") )
|
||||
// This need to be here, instead of jobban_unban, due to direct calls to jobban_remove
|
||||
if(jobban_regex.Find(X))
|
||||
var/ckey = jobban_regex.group[1]
|
||||
var/rank = jobban_regex.group[2]
|
||||
if(jobban_assoclist[ckey] && jobban_assoclist[ckey][rank])
|
||||
jobban_assoclist[ckey] -= rank
|
||||
else
|
||||
log_runtime(EXCEPTION("Attempted to remove non-existent job ban: [X]"))
|
||||
else
|
||||
log_runtime(EXCEPTION("Failed to remove malformed job ban from associative list: [X]"))
|
||||
jobban_keylist.Remove(jobban_keylist[i])
|
||||
if(config.ban_legacy_system)
|
||||
jobban_savebanfile()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/verb/displayjobbans()
|
||||
set category = "OOC"
|
||||
set name = "Display Current Jobbans"
|
||||
set desc = "Displays all of your current jobbans."
|
||||
|
||||
if(!client || !ckey)
|
||||
return
|
||||
if(config.ban_legacy_system)
|
||||
//using the legacy .txt ban system
|
||||
to_chat(src, "The server is using the legacy ban system. Ask an administrator for help!")
|
||||
|
||||
else
|
||||
//using the SQL ban system
|
||||
var/is_actually_banned = FALSE
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey like '[ckey]' AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned) ORDER BY bantime DESC LIMIT 100")
|
||||
select_query.Execute()
|
||||
|
||||
while(select_query.NextRow())
|
||||
|
||||
var/bantime = select_query.item[1]
|
||||
var/bantype = select_query.item[2]
|
||||
var/reason = select_query.item[3]
|
||||
var/job = select_query.item[4]
|
||||
var/duration = select_query.item[5]
|
||||
var/expiration = select_query.item[6]
|
||||
var/ackey = select_query.item[7]
|
||||
|
||||
if(bantype == "JOB_PERMABAN")
|
||||
to_chat(src, "<span class='warning'>[bantype]: [job] - REASON: [reason], by [ackey]; [bantime]</span>")
|
||||
else if(bantype == "JOB_TEMPBAN")
|
||||
to_chat(src, "<span class='warning'>[bantype]: [job] - REASON: [reason], by [ackey]; [bantime]; [duration]; expires [expiration]</span>")
|
||||
|
||||
is_actually_banned = TRUE
|
||||
|
||||
if(is_actually_banned)
|
||||
if(config.banappeals)
|
||||
to_chat(src, "<span class='warning'>You can appeal the bans at: [config.banappeals]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You have no active jobbans!</span>")
|
||||
GLOBAL_VAR(jobban_runonce) // Updates legacy bans with new info
|
||||
GLOBAL_LIST_INIT(jobban_keylist, new()) // Linear list of jobban strings, kept around for the legacy system
|
||||
GLOBAL_LIST_INIT(jobban_assoclist, new()) // Associative list, for efficiency
|
||||
|
||||
// Matches string-based jobbans into ckey, rank, and reason groups
|
||||
GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## (.+))?"))
|
||||
|
||||
/proc/jobban_assoc_insert(ckey, rank, reason)
|
||||
if(!ckey || !rank)
|
||||
return
|
||||
if(!GLOB.jobban_assoclist[ckey])
|
||||
GLOB.jobban_assoclist[ckey] = list()
|
||||
GLOB.jobban_assoclist[ckey][rank] = reason || "Reason Unspecified"
|
||||
|
||||
/proc/jobban_fullban(mob/M, rank, reason)
|
||||
if(!M || !M.key)
|
||||
return
|
||||
GLOB.jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]"))
|
||||
jobban_assoc_insert(M.ckey, rank, reason)
|
||||
if(config.ban_legacy_system)
|
||||
jobban_savebanfile()
|
||||
|
||||
/proc/jobban_client_fullban(ckey, rank)
|
||||
if(!ckey || !rank)
|
||||
return
|
||||
GLOB.jobban_keylist.Add(text("[ckey] - [rank]"))
|
||||
jobban_assoc_insert(ckey, rank)
|
||||
if(config.ban_legacy_system)
|
||||
jobban_savebanfile()
|
||||
|
||||
//returns a reason if M is banned from rank, returns 0 otherwise
|
||||
/proc/jobban_isbanned(mob/M, rank)
|
||||
if(!M || !rank)
|
||||
return 0
|
||||
|
||||
if(config.guest_jobban && guest_jobbans(rank))
|
||||
if(IsGuestKey(M.key))
|
||||
return "Guest Job-ban"
|
||||
|
||||
if(GLOB.jobban_assoclist[M.ckey])
|
||||
return GLOB.jobban_assoclist[M.ckey][rank]
|
||||
else
|
||||
return 0
|
||||
|
||||
/*
|
||||
DEBUG
|
||||
/mob/verb/list_all_jobbans()
|
||||
set name = "list all jobbans"
|
||||
|
||||
for(var/s in jobban_keylist)
|
||||
to_chat(world, s)
|
||||
|
||||
/mob/verb/reload_jobbans()
|
||||
set name = "reload jobbans"
|
||||
|
||||
jobban_loadbanfile()
|
||||
*/
|
||||
|
||||
/hook/startup/proc/loadJobBans()
|
||||
jobban_loadbanfile()
|
||||
return 1
|
||||
|
||||
/proc/jobban_loadbanfile()
|
||||
if(config.ban_legacy_system)
|
||||
var/savefile/S=new("data/job_full.ban")
|
||||
S["keys[0]"] >> GLOB.jobban_keylist
|
||||
log_admin("Loading jobban_rank")
|
||||
S["runonce"] >> GLOB.jobban_runonce
|
||||
|
||||
if(!length(GLOB.jobban_keylist))
|
||||
GLOB.jobban_keylist=list()
|
||||
log_admin("jobban_keylist was empty")
|
||||
|
||||
for(var/s in GLOB.jobban_keylist)
|
||||
if(GLOB.jobban_regex.Find(s))
|
||||
jobban_assoc_insert(GLOB.jobban_regex.group[1], GLOB.jobban_regex.group[2], GLOB.jobban_regex.group[3])
|
||||
else
|
||||
log_runtime(EXCEPTION("Skipping malformed job ban: [s]"))
|
||||
else
|
||||
if(!establish_db_connection())
|
||||
log_world("Database connection failed. Reverting to the legacy ban system.")
|
||||
config.ban_legacy_system = 1
|
||||
jobban_loadbanfile()
|
||||
return
|
||||
|
||||
//Job permabans
|
||||
var/DBQuery/permabans = GLOB.dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
|
||||
permabans.Execute()
|
||||
// Job tempbans
|
||||
var/DBQuery/tempbans = GLOB.dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
|
||||
tempbans.Execute()
|
||||
|
||||
while(TRUE)
|
||||
var/ckey
|
||||
var/job
|
||||
if(permabans.NextRow())
|
||||
ckey = permabans.item[1]
|
||||
job = permabans.item[2]
|
||||
else if(tempbans.NextRow())
|
||||
ckey = tempbans.item[1]
|
||||
job = tempbans.item[2]
|
||||
else
|
||||
break
|
||||
|
||||
GLOB.jobban_keylist.Add("[ckey] - [job]")
|
||||
jobban_assoc_insert(ckey, job)
|
||||
|
||||
/proc/jobban_savebanfile()
|
||||
var/savefile/S=new("data/job_full.ban")
|
||||
S["keys[0]"] << GLOB.jobban_keylist
|
||||
|
||||
/proc/jobban_unban(mob/M, rank)
|
||||
jobban_remove("[M.ckey] - [rank]")
|
||||
|
||||
/proc/jobban_unban_client(ckey, rank)
|
||||
jobban_remove("[ckey] - [rank]")
|
||||
|
||||
/proc/ban_unban_log_save(var/formatted_log)
|
||||
text2file(formatted_log,"data/ban_unban_log.txt")
|
||||
|
||||
|
||||
/proc/jobban_remove(X)
|
||||
for(var/i = 1; i <= length(GLOB.jobban_keylist); i++)
|
||||
if( findtext(GLOB.jobban_keylist[i], "[X]") )
|
||||
// This need to be here, instead of jobban_unban, due to direct calls to jobban_remove
|
||||
if(GLOB.jobban_regex.Find(X))
|
||||
var/ckey = GLOB.jobban_regex.group[1]
|
||||
var/rank = GLOB.jobban_regex.group[2]
|
||||
if(GLOB.jobban_assoclist[ckey] && GLOB.jobban_assoclist[ckey][rank])
|
||||
GLOB.jobban_assoclist[ckey] -= rank
|
||||
else
|
||||
log_runtime(EXCEPTION("Attempted to remove non-existent job ban: [X]"))
|
||||
else
|
||||
log_runtime(EXCEPTION("Failed to remove malformed job ban from associative list: [X]"))
|
||||
GLOB.jobban_keylist.Remove(GLOB.jobban_keylist[i])
|
||||
if(config.ban_legacy_system)
|
||||
jobban_savebanfile()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/verb/displayjobbans()
|
||||
set category = "OOC"
|
||||
set name = "Display Current Jobbans"
|
||||
set desc = "Displays all of your current jobbans."
|
||||
|
||||
if(!client || !ckey)
|
||||
return
|
||||
if(config.ban_legacy_system)
|
||||
//using the legacy .txt ban system
|
||||
to_chat(src, "The server is using the legacy ban system. Ask an administrator for help!")
|
||||
|
||||
else
|
||||
//using the SQL ban system
|
||||
var/is_actually_banned = FALSE
|
||||
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey like '[ckey]' AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned) ORDER BY bantime DESC LIMIT 100")
|
||||
select_query.Execute()
|
||||
|
||||
while(select_query.NextRow())
|
||||
|
||||
var/bantime = select_query.item[1]
|
||||
var/bantype = select_query.item[2]
|
||||
var/reason = select_query.item[3]
|
||||
var/job = select_query.item[4]
|
||||
var/duration = select_query.item[5]
|
||||
var/expiration = select_query.item[6]
|
||||
var/ackey = select_query.item[7]
|
||||
|
||||
if(bantype == "JOB_PERMABAN")
|
||||
to_chat(src, "<span class='warning'>[bantype]: [job] - REASON: [reason], by [ackey]; [bantime]</span>")
|
||||
else if(bantype == "JOB_TEMPBAN")
|
||||
to_chat(src, "<span class='warning'>[bantype]: [job] - REASON: [reason], by [ackey]; [bantime]; [duration]; expires [expiration]</span>")
|
||||
|
||||
is_actually_banned = TRUE
|
||||
|
||||
if(is_actually_banned)
|
||||
if(config.banappeals)
|
||||
to_chat(src, "<span class='warning'>You can appeal the bans at: [config.banappeals]</span>")
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You have no active jobbans!</span>")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/var/create_mob_html = null
|
||||
/datum/admins/proc/create_mob(var/mob/user)
|
||||
if(!create_mob_html)
|
||||
var/mobjs = null
|
||||
mobjs = jointext(typesof(/mob), ";")
|
||||
create_mob_html = file2text('html/create_object.html')
|
||||
create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"")
|
||||
|
||||
user << browse(replacetext(create_mob_html, "/* ref src */", UID()), "window=create_mob;size=425x475")
|
||||
GLOBAL_VAR(create_mob_html)
|
||||
/datum/admins/proc/create_mob(var/mob/user)
|
||||
if(!GLOB.create_mob_html)
|
||||
var/mobjs = null
|
||||
mobjs = jointext(typesof(/mob), ";")
|
||||
GLOB.create_mob_html = file2text('html/create_object.html')
|
||||
GLOB.create_mob_html = replacetext(GLOB.create_mob_html, "null /* object types */", "\"[mobjs]\"")
|
||||
|
||||
user << browse(replacetext(GLOB.create_mob_html, "/* ref src */", UID()), "window=create_mob;size=425x475")
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
var/create_object_html = null
|
||||
var/list/create_object_forms = list(/obj, /obj/structure, /obj/machinery, /obj/effect, /obj/item, /obj/mecha, /obj/item/clothing, /obj/item/stack, /obj/item/reagent_containers, /obj/item/gun)
|
||||
|
||||
/datum/admins/proc/create_object(var/mob/user)
|
||||
if(!create_object_html)
|
||||
var/objectjs = null
|
||||
objectjs = jointext(typesof(/obj), ";")
|
||||
create_object_html = file2text('html/create_object.html')
|
||||
create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"")
|
||||
|
||||
user << browse(replacetext(create_object_html, "/* ref src */", UID()), "window=create_object;size=425x475")
|
||||
|
||||
/datum/admins/proc/quick_create_object(var/mob/user)
|
||||
var/path = input("Select the path of the object you wish to create.", "Path", /obj) in create_object_forms
|
||||
var/html_form = create_object_forms[path]
|
||||
|
||||
if(!html_form)
|
||||
var/objectjs = jointext(typesof(path), ";")
|
||||
html_form = file2text('html/create_object.html')
|
||||
html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"")
|
||||
create_object_forms[path] = html_form
|
||||
|
||||
user << browse(replacetext(html_form, "/* ref src */", UID()), "window=qco[path];size=425x475")
|
||||
GLOBAL_VAR(create_object_html)
|
||||
GLOBAL_LIST_INIT(create_object_forms, list(/obj, /obj/structure, /obj/machinery, /obj/effect, /obj/item, /obj/mecha, /obj/item/clothing, /obj/item/stack, /obj/item/reagent_containers, /obj/item/gun))
|
||||
|
||||
/datum/admins/proc/create_object(var/mob/user)
|
||||
if(!GLOB.create_object_html)
|
||||
var/objectjs = null
|
||||
objectjs = jointext(typesof(/obj), ";")
|
||||
GLOB.create_object_html = file2text('html/create_object.html')
|
||||
GLOB.create_object_html = replacetext(GLOB.create_object_html, "null /* object types */", "\"[objectjs]\"")
|
||||
|
||||
user << browse(replacetext(GLOB.create_object_html, "/* ref src */", UID()), "window=create_object;size=425x475")
|
||||
|
||||
/datum/admins/proc/quick_create_object(var/mob/user)
|
||||
var/path = input("Select the path of the object you wish to create.", "Path", /obj) in GLOB.create_object_forms
|
||||
var/html_form = GLOB.create_object_forms[path]
|
||||
|
||||
if(!html_form)
|
||||
var/objectjs = jointext(typesof(path), ";")
|
||||
html_form = file2text('html/create_object.html')
|
||||
html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"")
|
||||
GLOB.create_object_forms[path] = html_form
|
||||
|
||||
user << browse(replacetext(html_form, "/* ref src */", UID()), "window=qco[path];size=425x475")
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/client/proc/create_poll()
|
||||
set name = "Create Server Poll"
|
||||
set category = "Server"
|
||||
if(!check_rights(R_SERVER))
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
create_poll_window()
|
||||
|
||||
/client/proc/create_poll_window(var/errormessage = "")
|
||||
if(!check_rights(R_SERVER))
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
var/output={"<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -75,7 +75,7 @@ function onload() {
|
||||
<form name='createpoll' action='byond://' method='post' style='padding-left:30px;padding-right:30px;padding-top:10px'>
|
||||
<input type='hidden' name='createpollnumoptions' id='createpollnumoptions' value='0'>
|
||||
<table><tr><td style='width:50%' style="vertical-align:top"><div id='polloptions'><div id='polloptionsinner'>
|
||||
|
||||
|
||||
</div>
|
||||
<input type='button' onclick='add_option()' value="Add Option"></input>
|
||||
<input type='button' onclick='del_option()' value="Delete Option"></input>
|
||||
@@ -99,7 +99,7 @@ function onload() {
|
||||
src << browse(output, "window=createplayerpoll;size=950x500")
|
||||
|
||||
/client/proc/create_poll_function(href_list)
|
||||
if(!check_rights(R_SERVER))
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
var/polltype = href_list["createpoll"]
|
||||
if(polltype != POLLTYPE_OPTION && polltype != POLLTYPE_TEXT && polltype != POLLTYPE_RATING && polltype != POLLTYPE_MULTI)
|
||||
@@ -122,15 +122,15 @@ function onload() {
|
||||
create_poll_window("<font color='red'>Question cannot be blank.</font>")
|
||||
return
|
||||
question = sanitizeSQL(question)
|
||||
|
||||
|
||||
var/starttime
|
||||
var/endtime
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT Now() AS starttime, ADDDATE(Now(), INTERVAL [poll_len] DAY) AS endtime")
|
||||
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT Now() AS starttime, ADDDATE(Now(), INTERVAL [poll_len] DAY) AS endtime")
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
starttime = query.item[1]
|
||||
endtime = query.item[2]
|
||||
|
||||
|
||||
var/pollquery = "INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', '[address]')"
|
||||
var/idquery = "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 = '[address]'"
|
||||
var/list/option_queries = list()
|
||||
@@ -175,15 +175,15 @@ function onload() {
|
||||
if(descmax)
|
||||
descmax = sanitizeSQL(descmax)
|
||||
option_queries += "INSERT INTO [format_table_name("poll_option")] (pollid, text, percentagecalc, minval, maxval, descmin, descmid, descmax) VALUES ('{POLLID}', '[option]', '[percentagecalc]', '[minval]', '[maxval]', '[descmin]', '[descmid]', '[descmax]')"
|
||||
|
||||
query = dbcon.NewQuery(pollquery)
|
||||
|
||||
query = GLOB.dbcon.NewQuery(pollquery)
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
create_poll_window("<font color='red'>An SQL error has occured while creating your poll</font>")
|
||||
log_game("SQL ERROR adding new poll question to table. Error : \[[err]\]\n")
|
||||
return
|
||||
var/pollid = 0
|
||||
query = dbcon.NewQuery(idquery)
|
||||
query = GLOB.dbcon.NewQuery(idquery)
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
create_poll_window("<font color='red'>An SQL error has occured while creating your poll</font>")
|
||||
@@ -192,11 +192,11 @@ function onload() {
|
||||
if(query.NextRow())
|
||||
pollid = text2num(query.item[1])
|
||||
for(var/querytext in option_queries)
|
||||
query = dbcon.NewQuery(replacetext(idquery, "{POLLID}", pollid))
|
||||
query = GLOB.dbcon.NewQuery(replacetext(idquery, "{POLLID}", pollid))
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
create_poll_window("<font color='red'>An SQL error has occured while creating your poll</font>")
|
||||
log_game("SQL ERROR obtaining id from poll_question table. Error : \[[err]\]\n")
|
||||
return
|
||||
create_poll_window("<font color='#008800'>Your poll has been successfully created</font>")
|
||||
return pollid
|
||||
return pollid
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/var/create_turf_html = null
|
||||
/datum/admins/proc/create_turf(var/mob/user)
|
||||
if(!create_turf_html)
|
||||
var/turfjs = null
|
||||
turfjs = jointext(typesof(/turf), ";")
|
||||
create_turf_html = file2text('html/create_object.html')
|
||||
create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"")
|
||||
|
||||
user << browse(replacetext(create_turf_html, "/* ref src */", UID()), "window=create_turf;size=425x475")
|
||||
GLOBAL_VAR(create_turf_html)
|
||||
/datum/admins/proc/create_turf(var/mob/user)
|
||||
if(!GLOB.create_turf_html)
|
||||
var/turfjs = null
|
||||
turfjs = jointext(typesof(/turf), ";")
|
||||
GLOB.create_turf_html = file2text('html/create_object.html')
|
||||
GLOB.create_turf_html = replacetext(GLOB.create_turf_html, "null /* object types */", "\"[turfjs]\"")
|
||||
|
||||
user << browse(replacetext(GLOB.create_turf_html, "/* ref src */", UID()), "window=create_turf;size=425x475")
|
||||
|
||||
+109
-108
@@ -1,108 +1,109 @@
|
||||
var/list/admin_datums = list()
|
||||
|
||||
/datum/admins
|
||||
var/rank = "Temporary Admin"
|
||||
var/client/owner = null
|
||||
var/rights = 0
|
||||
var/fakekey = null
|
||||
var/big_brother = 0
|
||||
|
||||
var/datum/marked_datum
|
||||
|
||||
var/admincaster_screen = 0 //See newscaster.dm under machinery for a full description
|
||||
var/datum/feed_message/admincaster_feed_message = new /datum/feed_message //These two will act as holders.
|
||||
var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel
|
||||
var/admincaster_signature //What you'll sign the newsfeeds as
|
||||
|
||||
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
|
||||
if(!ckey)
|
||||
error("Admin datum created without a ckey argument. Datum has been deleted")
|
||||
qdel(src)
|
||||
return
|
||||
admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
|
||||
rank = initial_rank
|
||||
rights = initial_rights
|
||||
admin_datums[ckey] = src
|
||||
|
||||
/datum/admins/Destroy()
|
||||
..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
/datum/admins/proc/associate(client/C)
|
||||
if(istype(C))
|
||||
owner = C
|
||||
owner.holder = src
|
||||
owner.on_holder_add()
|
||||
owner.add_admin_verbs() //TODO
|
||||
owner.verbs -= /client/proc/readmin
|
||||
GLOB.admins |= C
|
||||
|
||||
/datum/admins/proc/disassociate()
|
||||
if(owner)
|
||||
GLOB.admins -= owner
|
||||
owner.remove_admin_verbs()
|
||||
owner.holder = null
|
||||
owner = null
|
||||
|
||||
/*
|
||||
checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags)
|
||||
if rights_required == 0, then it simply checks if they are an admin.
|
||||
if it doesn't return 1 and show_msg=1 it will prints a message explaining why the check has failed
|
||||
generally it would be used like so:
|
||||
|
||||
proc/admin_proc()
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
to_chat(world, "you have enough rights!")
|
||||
|
||||
NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call
|
||||
you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
|
||||
*/
|
||||
/proc/check_rights(rights_required, show_msg=1, var/mob/user = usr)
|
||||
if(user && user.client)
|
||||
if(rights_required)
|
||||
if(user.client.holder)
|
||||
if(rights_required & user.client.holder.rights)
|
||||
return 1
|
||||
else
|
||||
if(show_msg)
|
||||
to_chat(user, "<font color='red'>Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].</font>")
|
||||
else
|
||||
if(user.client.holder)
|
||||
return 1
|
||||
else
|
||||
if(show_msg)
|
||||
to_chat(user, "<font color='red'>Error: You are not an admin.</font>")
|
||||
return 0
|
||||
|
||||
//probably a bit iffy - will hopefully figure out a better solution
|
||||
/proc/check_if_greater_rights_than(client/other)
|
||||
if(usr && usr.client)
|
||||
if(usr.client.holder)
|
||||
if(!other || !other.holder)
|
||||
return 1
|
||||
if(usr.client.holder.rights != other.holder.rights)
|
||||
if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights )
|
||||
return 1 //we have all the rights they have and more
|
||||
to_chat(usr, "<font color='red'>Error: Cannot proceed. They have more or equal rights to us.</font>")
|
||||
return 0
|
||||
|
||||
/client/proc/deadmin()
|
||||
admin_datums -= ckey
|
||||
if(holder)
|
||||
holder.disassociate()
|
||||
qdel(holder)
|
||||
return 1
|
||||
|
||||
//This proc checks whether subject has at least ONE of the rights specified in rights_required.
|
||||
/proc/check_rights_for(client/subject, rights_required)
|
||||
if(subject && subject.holder)
|
||||
if(rights_required && !(rights_required & subject.holder.rights))
|
||||
return 0
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/admins/vv_edit_var(var_name, var_value)
|
||||
return FALSE // no admin abuse
|
||||
|
||||
/datum/admins/can_vv_delete()
|
||||
return FALSE // don't break shit either
|
||||
GLOBAL_LIST_EMPTY(admin_datums)
|
||||
GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people making their own admin ranks, for obvious reasons
|
||||
|
||||
/datum/admins
|
||||
var/rank = "Temporary Admin"
|
||||
var/client/owner = null
|
||||
var/rights = 0
|
||||
var/fakekey = null
|
||||
var/big_brother = 0
|
||||
|
||||
var/datum/marked_datum
|
||||
|
||||
var/admincaster_screen = 0 //See newscaster.dm under machinery for a full description
|
||||
var/datum/feed_message/admincaster_feed_message = new /datum/feed_message //These two will act as holders.
|
||||
var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel
|
||||
var/admincaster_signature //What you'll sign the newsfeeds as
|
||||
|
||||
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
|
||||
if(!ckey)
|
||||
error("Admin datum created without a ckey argument. Datum has been deleted")
|
||||
qdel(src)
|
||||
return
|
||||
admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
|
||||
rank = initial_rank
|
||||
rights = initial_rights
|
||||
GLOB.admin_datums[ckey] = src
|
||||
|
||||
/datum/admins/Destroy()
|
||||
..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
/datum/admins/proc/associate(client/C)
|
||||
if(istype(C))
|
||||
owner = C
|
||||
owner.holder = src
|
||||
owner.on_holder_add()
|
||||
owner.add_admin_verbs() //TODO
|
||||
owner.verbs -= /client/proc/readmin
|
||||
GLOB.admins |= C
|
||||
|
||||
/datum/admins/proc/disassociate()
|
||||
if(owner)
|
||||
GLOB.admins -= owner
|
||||
owner.remove_admin_verbs()
|
||||
owner.holder = null
|
||||
owner = null
|
||||
|
||||
/*
|
||||
checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags)
|
||||
if rights_required == 0, then it simply checks if they are an admin.
|
||||
if it doesn't return 1 and show_msg=1 it will prints a message explaining why the check has failed
|
||||
generally it would be used like so:
|
||||
|
||||
proc/admin_proc()
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
to_chat(world, "you have enough rights!")
|
||||
|
||||
NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call
|
||||
you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
|
||||
*/
|
||||
/proc/check_rights(rights_required, show_msg=1, var/mob/user = usr)
|
||||
if(user && user.client)
|
||||
if(rights_required)
|
||||
if(user.client.holder)
|
||||
if(rights_required & user.client.holder.rights)
|
||||
return 1
|
||||
else
|
||||
if(show_msg)
|
||||
to_chat(user, "<font color='red'>Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].</font>")
|
||||
else
|
||||
if(user.client.holder)
|
||||
return 1
|
||||
else
|
||||
if(show_msg)
|
||||
to_chat(user, "<font color='red'>Error: You are not an admin.</font>")
|
||||
return 0
|
||||
|
||||
//probably a bit iffy - will hopefully figure out a better solution
|
||||
/proc/check_if_greater_rights_than(client/other)
|
||||
if(usr && usr.client)
|
||||
if(usr.client.holder)
|
||||
if(!other || !other.holder)
|
||||
return 1
|
||||
if(usr.client.holder.rights != other.holder.rights)
|
||||
if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights )
|
||||
return 1 //we have all the rights they have and more
|
||||
to_chat(usr, "<font color='red'>Error: Cannot proceed. They have more or equal rights to us.</font>")
|
||||
return 0
|
||||
|
||||
/client/proc/deadmin()
|
||||
GLOB.admin_datums -= ckey
|
||||
if(holder)
|
||||
holder.disassociate()
|
||||
qdel(holder)
|
||||
return 1
|
||||
|
||||
//This proc checks whether subject has at least ONE of the rights specified in rights_required.
|
||||
/proc/check_rights_for(client/subject, rights_required)
|
||||
if(subject && subject.holder)
|
||||
if(rights_required && !(rights_required & subject.holder.rights))
|
||||
return 0
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/admins/vv_edit_var(var_name, var_value)
|
||||
return FALSE // no admin abuse
|
||||
|
||||
/datum/admins/can_vv_delete()
|
||||
return FALSE // don't break shit either
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
cachedintel.cache = TRUE
|
||||
return cachedintel
|
||||
|
||||
if(dbcon.IsConnected())
|
||||
if(GLOB.dbcon.IsConnected())
|
||||
var/rating_bad = config.ipintel_rating_bad
|
||||
var/DBQuery/query_get_ip_intel = dbcon.NewQuery({"
|
||||
var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery({"
|
||||
SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW())
|
||||
FROM [format_table_name("ipintel")]
|
||||
WHERE
|
||||
@@ -67,8 +67,8 @@
|
||||
res.intel = ip_intel_query(ip)
|
||||
if(updatecache && res.intel >= 0)
|
||||
SSipintel.cache[ip] = res
|
||||
if(dbcon.IsConnected())
|
||||
var/DBQuery/query_add_ip_intel = dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()")
|
||||
if(GLOB.dbcon.IsConnected())
|
||||
var/DBQuery/query_add_ip_intel = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()")
|
||||
query_add_ip_intel.Execute()
|
||||
qdel(query_add_ip_intel)
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
return FALSE
|
||||
if(!config.ipintel_whitelist)
|
||||
return FALSE
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
return FALSE
|
||||
if(!ipintel_badip_check(t_ip))
|
||||
return FALSE
|
||||
@@ -160,7 +160,7 @@
|
||||
rating_bad = sanitizeSQL(rating_bad)
|
||||
valid_hours = sanitizeSQL(valid_hours)
|
||||
var/check_sql = {"SELECT * FROM [format_table_name("ipintel")] WHERE ip = INET_ATON('[target_ip]') AND intel >= [rating_bad] AND (date + INTERVAL [valid_hours] HOUR) > NOW()"}
|
||||
var/DBQuery/query_get_ip_intel = dbcon.NewQuery(check_sql)
|
||||
var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery(check_sql)
|
||||
if(!query_get_ip_intel.Execute())
|
||||
log_debug("ipintel_badip_check reports failed query execution")
|
||||
qdel(query_get_ip_intel)
|
||||
@@ -175,7 +175,7 @@
|
||||
if(!config.ipintel_whitelist)
|
||||
return FALSE
|
||||
var/target_sql_ckey = ckey(target_ckey)
|
||||
var/DBQuery/query_whitelist_check = dbcon.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_whitelist_check = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_whitelist_check.Execute())
|
||||
var/err = query_whitelist_check.ErrorMsg()
|
||||
log_debug("SQL ERROR on proc/vpn_whitelist_check for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
|
||||
@@ -190,7 +190,7 @@
|
||||
if(!reason_string)
|
||||
return FALSE
|
||||
reason_string = sanitizeSQL(reason_string)
|
||||
var/DBQuery/query_whitelist_add = dbcon.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES ('[target_sql_ckey]','[reason_string]')")
|
||||
var/DBQuery/query_whitelist_add = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES ('[target_sql_ckey]','[reason_string]')")
|
||||
if(!query_whitelist_add.Execute())
|
||||
var/err = query_whitelist_add.ErrorMsg()
|
||||
log_debug("SQL ERROR on proc/vpn_whitelist_add for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
/proc/vpn_whitelist_remove(target_ckey)
|
||||
var/target_sql_ckey = ckey(target_ckey)
|
||||
var/DBQuery/query_whitelist_remove = dbcon.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_whitelist_remove = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_whitelist_remove.Execute())
|
||||
var/err = query_whitelist_remove.ErrorMsg()
|
||||
log_debug("SQL ERROR on proc/vpn_whitelist_remove for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
|
||||
@@ -225,4 +225,4 @@
|
||||
if(vpn_whitelist_add(target_ckey))
|
||||
to_chat(usr, "[target_ckey] was added to the VPN whitelist.")
|
||||
else
|
||||
to_chat(usr, "VPN whitelist unchanged.")
|
||||
to_chat(usr, "VPN whitelist unchanged.")
|
||||
|
||||
@@ -1,167 +1,170 @@
|
||||
/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=[UID()];editrights=add'>\[+\]</a></th>
|
||||
<th style='width:125px;'>RANK</th><th style='width:100%;'>PERMISSIONS</th>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
for(var/adm_ckey in admin_datums)
|
||||
var/datum/admins/D = admin_datums[adm_ckey]
|
||||
if(!D) continue
|
||||
var/rank = D.rank ? D.rank : "*none*"
|
||||
var/rights = rights2text(D.rights," ")
|
||||
if(!rights) rights = "*none*"
|
||||
output += {"<tr>
|
||||
<td style='text-align:right;'>[adm_ckey] <a class='small' href='?src=[UID()];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>
|
||||
<td><a href='?src=[UID()];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>
|
||||
<td><a class='small' href='?src=[UID()];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></font></td>
|
||||
</tr>"}
|
||||
|
||||
/*output += "<tr>"
|
||||
output += "<td style='text-align:right;'>[adm_ckey] <a class='small' href='?src=[UID()];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>"
|
||||
output += "<td><a href='?src=[UID()];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>"
|
||||
output += "<td><a class='small' href='?src=[UID()];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></font></td>"
|
||||
output += "</tr>"*/
|
||||
|
||||
output += {"
|
||||
</table></div>
|
||||
<div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div>
|
||||
</body>
|
||||
</html>"}
|
||||
|
||||
usr << browse(output,"window=editrights;size=600x500")
|
||||
|
||||
/datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank)
|
||||
if(config.admin_legacy_system) return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
|
||||
if(!dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='warning'>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/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
|
||||
var/new_admin = 1
|
||||
var/admin_id
|
||||
while(select_query.NextRow())
|
||||
new_admin = 0
|
||||
admin_id = text2num(select_query.item[1])
|
||||
|
||||
if(new_admin)
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[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]');")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>New admin added.</span>")
|
||||
else
|
||||
if(!isnull(admin_id) && isnum(admin_id))
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[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]');")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>Admin rank changed.</span>")
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
|
||||
return
|
||||
|
||||
if(!adm_ckey || !new_permission)
|
||||
return
|
||||
|
||||
adm_ckey = ckey(adm_ckey)
|
||||
|
||||
if(!adm_ckey)
|
||||
return
|
||||
|
||||
if(istext(new_permission))
|
||||
new_permission = text2num(new_permission)
|
||||
|
||||
if(!istext(adm_ckey) || !isnum(new_permission))
|
||||
return
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
|
||||
var/admin_id
|
||||
var/admin_rights
|
||||
while(select_query.NextRow())
|
||||
admin_id = text2num(select_query.item[1])
|
||||
admin_rights = text2num(select_query.item[2])
|
||||
|
||||
if(!admin_id)
|
||||
return
|
||||
|
||||
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>Permission removed.</span>")
|
||||
else //This admin doesn't have this permission, so we are adding it.
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>Permission added.</span>")
|
||||
|
||||
/datum/admins/proc/updateranktodb(ckey,newrank)
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
return
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/sql_admin_rank = sanitizeSQL(newrank)
|
||||
|
||||
var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'")
|
||||
query_update.Execute()
|
||||
/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=[UID()];editrights=add'>\[+\]</a></th>
|
||||
<th style='width:125px;'>RANK</th><th style='width:100%;'>PERMISSIONS</th>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
for(var/adm_ckey in GLOB.admin_datums)
|
||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||
if(!D) continue
|
||||
var/rank = D.rank ? D.rank : "*none*"
|
||||
var/rights = rights2text(D.rights," ")
|
||||
if(!rights) rights = "*none*"
|
||||
output += {"<tr>
|
||||
<td style='text-align:right;'>[adm_ckey] <a class='small' href='?src=[UID()];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>
|
||||
<td><a href='?src=[UID()];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>
|
||||
<td><a class='small' href='?src=[UID()];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></font></td>
|
||||
</tr>"}
|
||||
|
||||
/*output += "<tr>"
|
||||
output += "<td style='text-align:right;'>[adm_ckey] <a class='small' href='?src=[UID()];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>"
|
||||
output += "<td><a href='?src=[UID()];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>"
|
||||
output += "<td><a class='small' href='?src=[UID()];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></font></td>"
|
||||
output += "</tr>"*/
|
||||
|
||||
output += {"
|
||||
</table></div>
|
||||
<div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div>
|
||||
</body>
|
||||
</html>"}
|
||||
|
||||
usr << browse(output,"window=editrights;size=600x500")
|
||||
|
||||
/datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank)
|
||||
if(config.admin_legacy_system) return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='warning'>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/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
|
||||
var/new_admin = 1
|
||||
var/admin_id
|
||||
while(select_query.NextRow())
|
||||
new_admin = 0
|
||||
admin_id = text2num(select_query.item[1])
|
||||
|
||||
flag_account_for_forum_sync(adm_ckey)
|
||||
if(new_admin)
|
||||
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>New admin added.</span>")
|
||||
else
|
||||
if(!isnull(admin_id) && isnum(admin_id))
|
||||
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>Admin rank changed.</span>")
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
|
||||
return
|
||||
|
||||
if(!adm_ckey || !new_permission)
|
||||
return
|
||||
|
||||
adm_ckey = ckey(adm_ckey)
|
||||
|
||||
if(!adm_ckey)
|
||||
return
|
||||
|
||||
if(istext(new_permission))
|
||||
new_permission = text2num(new_permission)
|
||||
|
||||
if(!istext(adm_ckey) || !isnum(new_permission))
|
||||
return
|
||||
|
||||
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
|
||||
var/admin_id
|
||||
var/admin_rights
|
||||
while(select_query.NextRow())
|
||||
admin_id = text2num(select_query.item[1])
|
||||
admin_rights = text2num(select_query.item[2])
|
||||
|
||||
if(!admin_id)
|
||||
return
|
||||
|
||||
flag_account_for_forum_sync(adm_ckey)
|
||||
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
|
||||
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>Permission removed.</span>")
|
||||
else //This admin doesn't have this permission, so we are adding it.
|
||||
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
|
||||
log_query.Execute()
|
||||
to_chat(usr, "<span class='notice'>Permission added.</span>")
|
||||
|
||||
/datum/admins/proc/updateranktodb(ckey,newrank)
|
||||
establish_db_connection()
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
return
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/sql_admin_rank = sanitizeSQL(newrank)
|
||||
|
||||
var/DBQuery/query_update = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'")
|
||||
query_update.Execute()
|
||||
flag_account_for_forum_sync(sql_ckey)
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
/datum/admins/proc/player_panel_new()//The new one
|
||||
if(!usr.client.holder)
|
||||
return
|
||||
// This stops the panel from being invoked by mentors who press F7.
|
||||
if(!check_rights(R_ADMIN))
|
||||
message_admins("[key_name_admin(usr)] attempted to invoke player panel without admin rights. If this is a mentor, its a chance they accidentally hit F7. If this is NOT a mentor, there is a high chance an exploit is being used")
|
||||
return
|
||||
var/dat = "<html><head><title>Admin Player Panel</title></head>"
|
||||
|
||||
//javascript, the part that does most of the work~
|
||||
@@ -392,11 +396,12 @@
|
||||
var/logout_status
|
||||
logout_status = M.client ? "" : " <i>(logged out)</i>"
|
||||
var/dname = M.real_name
|
||||
var/area/A = get_area(M)
|
||||
if(!dname)
|
||||
dname = M
|
||||
|
||||
return {"<tr><td><a href='?src=[UID()];adminplayeropts=[M.UID()]'>[dname]</a><b>[caption]</b>[logout_status][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>
|
||||
<td><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A></td>[close ? "</tr>" : ""]"}
|
||||
return {"<tr><td><a href='?src=[UID()];adminplayeropts=[M.UID()]'>[dname]</a><b>[caption]</b>[logout_status][istype(A, /area/security/permabrig) ? "<b><font color=red> (PERMA) </b></font>" : ""][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>
|
||||
<td><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A> [ADMIN_FLW(M, "FLW")] </td>[close ? "</tr>" : ""]"}
|
||||
|
||||
/datum/admins/proc/check_antagonists()
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
@@ -465,7 +470,7 @@
|
||||
if(GAMEMODE_IS_BLOB)
|
||||
var/datum/game_mode/blob/mode = SSticker.mode
|
||||
dat += "<br><table cellspacing=5><tr><td><B>Blob</B></td><td></td><td></td></tr>"
|
||||
dat += "<tr><td><i>Progress: [blobs.len]/[mode.blobwincount]</i></td></tr>"
|
||||
dat += "<tr><td><i>Progress: [GLOB.blobs.len]/[mode.blobwincount]</i></td></tr>"
|
||||
|
||||
for(var/datum/mind/blob in mode.infected_crew)
|
||||
var/mob/M = blob.current
|
||||
@@ -475,7 +480,7 @@
|
||||
else
|
||||
dat += "<tr><td><i>Blob not found!</i></td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
|
||||
if(SSticker.mode.blob_overminds.len)
|
||||
dat += check_role_table("Blob Overminds", SSticker.mode.blob_overminds)
|
||||
|
||||
@@ -492,7 +497,7 @@
|
||||
dat += check_role_table("Ninjas", ticker.mode.ninjas)*/
|
||||
|
||||
if(SSticker.mode.cult.len)
|
||||
dat += check_role_table("Cultists", SSticker.mode.cult, 0)
|
||||
dat += check_role_table("Cultists", SSticker.mode.cult)
|
||||
dat += "<br> use <a href='?src=[UID()];cult_mindspeak=[UID()]'>Cult Mindspeak</a>"
|
||||
if(GAMEMODE_IS_CULT)
|
||||
var/datum/game_mode/cult/cult_round = SSticker.mode
|
||||
@@ -541,9 +546,9 @@
|
||||
if(SSticker.mode.eventmiscs.len)
|
||||
dat += check_role_table("Event Roles", SSticker.mode.eventmiscs)
|
||||
|
||||
if(ts_spiderlist.len)
|
||||
if(GLOB.ts_spiderlist.len)
|
||||
var/list/spider_minds = list()
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/S in ts_spiderlist)
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/S in GLOB.ts_spiderlist)
|
||||
if(S.ckey)
|
||||
spider_minds += S.mind
|
||||
if(spider_minds.len)
|
||||
@@ -551,10 +556,10 @@
|
||||
|
||||
var/count_eggs = 0
|
||||
var/count_spiderlings = 0
|
||||
for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in ts_egg_list)
|
||||
for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in GLOB.ts_egg_list)
|
||||
if(is_station_level(E.z))
|
||||
count_eggs += E.spiderling_number
|
||||
for(var/obj/structure/spider/spiderling/terror_spiderling/L in ts_spiderling_list)
|
||||
for(var/obj/structure/spider/spiderling/terror_spiderling/L in GLOB.ts_spiderling_list)
|
||||
if(!L.stillborn && is_station_level(L.z))
|
||||
count_spiderlings += 1
|
||||
dat += "<table cellspacing=5><TR><TD>Growing TS on-station: [count_eggs] egg[count_eggs != 1 ? "s" : ""], [count_spiderlings] spiderling[count_spiderlings != 1 ? "s" : ""]. </TD></TR></TABLE>"
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
<B>Bombs</b><br>
|
||||
[check_rights(R_SERVER, 0) ? " <A href='?src=[UID()];secretsfun=togglebombcap'>Toggle bomb cap</A><br>" : "<br>"]
|
||||
<B>Lists</b><br>
|
||||
<A href='?src=[UID()];secretsadmin=list_signalers'>Show last [length(lastsignalers)] signalers</A>
|
||||
<A href='?src=[UID()];secretsadmin=list_lawchanges'>Show last [length(lawchanges)] law changes</A><BR>
|
||||
<A href='?src=[UID()];secretsadmin=list_signalers'>Show last [length(GLOB.lastsignalers)] signalers</A>
|
||||
<A href='?src=[UID()];secretsadmin=list_lawchanges'>Show last [length(GLOB.lawchanges)] law changes</A><BR>
|
||||
<A href='?src=[UID()];secretsadmin=DNA'>List DNA (Blood)</A>
|
||||
<A href='?src=[UID()];secretsadmin=fingerprints'>List Fingerprints</A><BR>
|
||||
<B>Power</b><br>
|
||||
@@ -49,7 +49,7 @@
|
||||
<B>Security Level Elevated</B><BR>
|
||||
<BR>
|
||||
<A href='?src=[UID()];secretscoder=maint_access_engiebrig'>Change all maintenance doors to engie/brig access only</A><BR>
|
||||
<A href='?src=[UID()];secretscoder=maint_access_brig'>Change all maintenance doors to brig access only</A><BR>
|
||||
<A href='?src=[UID()];secretscoder=maint_ACCESS_BRIG'>Change all maintenance doors to brig access only</A><BR>
|
||||
<A href='?src=[UID()];secretscoder=infinite_sec'>Remove cap on security officers</A>
|
||||
<BR>
|
||||
<B>Coder Secrets</B><BR>
|
||||
@@ -105,7 +105,7 @@
|
||||
<A href='?src=[UID()];secretsfun=monkey'>Turn all humans into monkeys</A><BR>
|
||||
<A href='?src=[UID()];secretsfun=fakeguns'>Make all items look like guns</A><BR>
|
||||
<A href='?src=[UID()];secretsfun=prisonwarp'>Warp all Players to Prison</A><BR>
|
||||
<A href='?src=[UID()];secretsfun=retardify'>Make all players retarded</A><BR>
|
||||
<A href='?src=[UID()];secretsfun=stupify'>Make all players stupid</A><BR>
|
||||
<b>Misc</b><br>
|
||||
<A href='?src=[UID()];secretsfun=sec_classic1'>Remove firesuits, grilles, and pods</A>
|
||||
<A href='?src=[UID()];secretsfun=tripleAI'>Triple AI mode (needs to be used in the lobby)</A><BR>
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server, checkrights = 1)
|
||||
if(checkrights && !check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
|
||||
if(!target_ckey)
|
||||
var/new_ckey = ckey(clean_input("Who would you like to add a note for?","Enter a ckey",null))
|
||||
if(!new_ckey)
|
||||
return
|
||||
new_ckey = ckey(new_ckey)
|
||||
var/DBQuery/query_find_ckey = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
|
||||
if(!query_find_ckey.Execute())
|
||||
var/err = query_find_ckey.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
|
||||
return
|
||||
if(!query_find_ckey.NextRow())
|
||||
to_chat(usr, "<span class='redtext'>[new_ckey] has not been seen before, you can only add notes to known players.</span>")
|
||||
return
|
||||
else
|
||||
target_ckey = new_ckey
|
||||
var/target_sql_ckey = ckey(target_ckey)
|
||||
target_ckey = ckey(new_ckey)
|
||||
else
|
||||
target_ckey = ckey(target_ckey)
|
||||
|
||||
var/DBQuery/query_find_ckey = GLOB.dbcon.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'")
|
||||
if(!query_find_ckey.Execute())
|
||||
var/err = query_find_ckey.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
|
||||
return
|
||||
if(!query_find_ckey.NextRow())
|
||||
to_chat(usr, "<span class='redtext'>[target_ckey] has not been seen before, you can only add notes to known players.</span>")
|
||||
return
|
||||
|
||||
var/exp_data = query_find_ckey.item[2]
|
||||
var/crew_number = 0
|
||||
if(exp_data)
|
||||
var/list/play_records = params2list(exp_data)
|
||||
crew_number = play_records[EXP_TYPE_CREW]
|
||||
|
||||
if(!notetext)
|
||||
notetext = input(usr,"Write your note","Add Note") as message|null
|
||||
if(!notetext)
|
||||
@@ -38,7 +46,7 @@
|
||||
if(config && config.server_name)
|
||||
server = config.server_name
|
||||
server = sanitizeSQL(server)
|
||||
var/DBQuery/query_noteadd = dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server) VALUES ('[target_sql_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]')")
|
||||
var/DBQuery/query_noteadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) VALUES ('[target_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]', '[crew_number]')")
|
||||
if(!query_noteadd.Execute())
|
||||
var/err = query_noteadd.ErrorMsg()
|
||||
log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n")
|
||||
@@ -54,13 +62,13 @@
|
||||
var/ckey
|
||||
var/notetext
|
||||
var/adminckey
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
if(!note_id)
|
||||
return
|
||||
note_id = text2num(note_id)
|
||||
var/DBQuery/query_find_note_del = dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
|
||||
var/DBQuery/query_find_note_del = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
|
||||
if(!query_find_note_del.Execute())
|
||||
var/err = query_find_note_del.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey, notetext, adminckey from player table. Error : \[[err]\]\n")
|
||||
@@ -69,7 +77,7 @@
|
||||
ckey = query_find_note_del.item[1]
|
||||
notetext = query_find_note_del.item[2]
|
||||
adminckey = query_find_note_del.item[3]
|
||||
var/DBQuery/query_del_note = dbcon.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id = [note_id]")
|
||||
var/DBQuery/query_del_note = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id = [note_id]")
|
||||
if(!query_del_note.Execute())
|
||||
var/err = query_del_note.ErrorMsg()
|
||||
log_game("SQL ERROR removing note from table. Error : \[[err]\]\n")
|
||||
@@ -81,7 +89,7 @@
|
||||
/proc/edit_note(note_id)
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
if(!dbcon.IsConnected())
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
if(!note_id)
|
||||
@@ -89,7 +97,7 @@
|
||||
note_id = text2num(note_id)
|
||||
var/target_ckey
|
||||
var/sql_ckey = usr.ckey
|
||||
var/DBQuery/query_find_note_edit = dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
|
||||
var/DBQuery/query_find_note_edit = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
|
||||
if(!query_find_note_edit.Execute())
|
||||
var/err = query_find_note_edit.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining notetext from notes table. Error : \[[err]\]\n")
|
||||
@@ -104,7 +112,7 @@
|
||||
new_note = sanitizeSQL(new_note)
|
||||
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"<hr>"
|
||||
edit_text = sanitizeSQL(edit_text)
|
||||
var/DBQuery/query_update_note = dbcon.NewQuery("UPDATE [format_table_name("notes")] SET notetext = '[new_note]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [note_id]")
|
||||
var/DBQuery/query_update_note = GLOB.dbcon.NewQuery("UPDATE [format_table_name("notes")] SET notetext = '[new_note]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [note_id]")
|
||||
if(!query_update_note.Execute())
|
||||
var/err = query_update_note.ErrorMsg()
|
||||
log_game("SQL ERROR editing note. Error : \[[err]\]\n")
|
||||
@@ -131,10 +139,10 @@
|
||||
output = navbar
|
||||
if(target_ckey)
|
||||
var/target_sql_ckey = ckey(target_ckey)
|
||||
var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
|
||||
var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
|
||||
if(!query_get_notes.Execute())
|
||||
var/err = query_get_notes.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server from notes table. Error : \[[err]\]\n")
|
||||
log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server, crew_playtime from notes table. Error : \[[err]\]\n")
|
||||
return
|
||||
output += "<h2><center>Notes of [target_ckey]</center></h2>"
|
||||
if(!linkless)
|
||||
@@ -147,7 +155,13 @@
|
||||
var/adminckey = query_get_notes.item[4]
|
||||
var/last_editor = query_get_notes.item[5]
|
||||
var/server = query_get_notes.item[6]
|
||||
output += "<b>[timestamp] | [server] | [adminckey]</b>"
|
||||
var/mins = text2num(query_get_notes.item[7])
|
||||
output += "<b>[timestamp] | [server] | [adminckey]"
|
||||
if(mins)
|
||||
var/playstring = get_exp_format(mins)
|
||||
output += " | [playstring] as Crew"
|
||||
output += "</b>"
|
||||
|
||||
if(!linkless)
|
||||
output += " <a href='?_src_=holder;removenote=[id]'>\[Remove Note\]</a> <a href='?_src_=holder;editnote=[id]'>\[Edit Note\]</a>"
|
||||
if(last_editor)
|
||||
@@ -167,7 +181,7 @@
|
||||
search = "^\[^\[:alpha:\]\]"
|
||||
else
|
||||
search = "^[index]"
|
||||
var/DBQuery/query_list_notes = dbcon.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
|
||||
var/DBQuery/query_list_notes = GLOB.dbcon.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
|
||||
if(!query_list_notes.Execute())
|
||||
var/err = query_list_notes.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n")
|
||||
@@ -182,10 +196,10 @@
|
||||
|
||||
/proc/show_player_info_irc(var/key as text)
|
||||
var/target_sql_ckey = ckey(key)
|
||||
var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
|
||||
var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
|
||||
if(!query_get_notes.Execute())
|
||||
var/err = query_get_notes.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining timestamp, notetext, adminckey, server from notes table. Error : \[[err]\]\n")
|
||||
log_game("SQL ERROR obtaining timestamp, notetext, adminckey, server, crew_playtime from notes table. Error : \[[err]\]\n")
|
||||
return
|
||||
var/output = " Info on [key]%0D%0A"
|
||||
while(query_get_notes.NextRow())
|
||||
|
||||
+3500
-3480
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,36 @@
|
||||
/proc/getbrokeninhands()
|
||||
set name = "Broken Sprite List"
|
||||
set category = "Debug"
|
||||
|
||||
var/text
|
||||
for(var/A in typesof(/obj/item))
|
||||
var/obj/item/O = new A( locate(1,1,1) )
|
||||
if(!O) continue
|
||||
var/icon/IL = new(O.lefthand_file)
|
||||
var/list/Lstates = IL.IconStates()
|
||||
var/icon/IR = new(O.righthand_file)
|
||||
var/list/Rstates = IR.IconStates()
|
||||
var/icon/J = new(O.icon)
|
||||
var/list/istates = J.IconStates()
|
||||
if(!Lstates.Find(O.icon_state) && !Lstates.Find(O.item_state))
|
||||
if(O.icon_state)
|
||||
text += "[O.type] is missing left hand icon called \"[O.icon_state]\".\n"
|
||||
if(!Rstates.Find(O.icon_state) && !Rstates.Find(O.item_state))
|
||||
if(O.icon_state)
|
||||
text += "[O.type] is missing right hand icon called \"[O.icon_state]\".\n"
|
||||
|
||||
|
||||
if(O.icon_state)
|
||||
if(!istates.Find(O.icon_state))
|
||||
text += "[O.type] is missing normal icon called \"[O.icon_state]\" in \"[O.icon]\".\n"
|
||||
//if(O.item_state)
|
||||
// if(!istates.Find(O.item_state))
|
||||
// text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.item_state]\" IN \"[O.icon]\"\n"
|
||||
//text+="\n"
|
||||
qdel(O)
|
||||
if(text)
|
||||
var/F = file("broken_hand_icons.txt")
|
||||
fdel(F)
|
||||
to_chat(F, text)
|
||||
to_chat(world, "Completed and written to [F]")
|
||||
|
||||
/proc/getbrokeninhands()
|
||||
set name = "Broken Sprite List"
|
||||
set category = "Debug"
|
||||
|
||||
var/text
|
||||
for(var/A in typesof(/obj/item))
|
||||
var/obj/item/O = new A( locate(1,1,1) )
|
||||
if(!O) continue
|
||||
var/icon/IL = new(O.lefthand_file)
|
||||
var/list/Lstates = IL.IconStates()
|
||||
var/icon/IR = new(O.righthand_file)
|
||||
var/list/Rstates = IR.IconStates()
|
||||
var/icon/J = new(O.icon)
|
||||
var/list/istates = J.IconStates()
|
||||
if(!Lstates.Find(O.icon_state) && !Lstates.Find(O.item_state))
|
||||
if(O.icon_state)
|
||||
text += "[O.type] is missing left hand icon called \"[O.icon_state]\".\n"
|
||||
if(!Rstates.Find(O.icon_state) && !Rstates.Find(O.item_state))
|
||||
if(O.icon_state)
|
||||
text += "[O.type] is missing right hand icon called \"[O.icon_state]\".\n"
|
||||
|
||||
|
||||
if(O.icon_state)
|
||||
if(!istates.Find(O.icon_state))
|
||||
text += "[O.type] is missing normal icon called \"[O.icon_state]\" in \"[O.icon]\".\n"
|
||||
//if(O.item_state)
|
||||
// if(!istates.Find(O.item_state))
|
||||
// text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.item_state]\" IN \"[O.icon]\"\n"
|
||||
//text+="\n"
|
||||
qdel(O)
|
||||
if(text)
|
||||
var/F = file("broken_hand_icons.txt")
|
||||
fdel(F)
|
||||
to_chat(F, text)
|
||||
to_chat(world, "Completed and written to [F]")
|
||||
|
||||
|
||||
@@ -1,187 +1,187 @@
|
||||
|
||||
|
||||
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
|
||||
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as")
|
||||
|
||||
/client/verb/adminhelp()
|
||||
set category = "Admin"
|
||||
set name = "Adminhelp"
|
||||
|
||||
//handle muting and automuting
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>")
|
||||
return
|
||||
|
||||
adminhelped = 1 //Determines if they get the message to reply by clicking the name.
|
||||
|
||||
var/msg
|
||||
var/list/type = list("Mentorhelp","Adminhelp")
|
||||
var/selected_type = input("Pick a category.", "Admin Help", null, null) as null|anything in type
|
||||
if(selected_type)
|
||||
msg = clean_input("Please enter your message.", "Admin Help", null)
|
||||
|
||||
//clean the input msg
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(handle_spam_prevention(msg, MUTE_ADMINHELP, OOC_COOLDOWN))
|
||||
return
|
||||
|
||||
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
var/original_msg = msg
|
||||
|
||||
//explode the input msg into a list
|
||||
var/list/msglist = splittext(msg, " ")
|
||||
|
||||
//generate keywords lookup
|
||||
var/list/surnames = list()
|
||||
var/list/forenames = list()
|
||||
var/list/ckeys = list()
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
var/list/indexing = list(M.real_name, M.name)
|
||||
if(M.mind) indexing += M.mind.name
|
||||
|
||||
for(var/string in indexing)
|
||||
var/list/L = splittext(string, " ")
|
||||
var/surname_found = 0
|
||||
//surnames
|
||||
for(var/i=L.len, i>=1, i--)
|
||||
var/word = ckey(L[i])
|
||||
if(word)
|
||||
surnames[word] = M
|
||||
surname_found = i
|
||||
break
|
||||
//forenames
|
||||
for(var/i=1, i<surname_found, i++)
|
||||
var/word = ckey(L[i])
|
||||
if(word)
|
||||
forenames[word] = M
|
||||
//ckeys
|
||||
ckeys[M.ckey] = M
|
||||
|
||||
var/ai_found = 0
|
||||
msg = ""
|
||||
var/list/mobs_found = list()
|
||||
for(var/original_word in msglist)
|
||||
var/word = ckey(original_word)
|
||||
if(word)
|
||||
if(!(word in adminhelp_ignored_words))
|
||||
if(word == "ai")
|
||||
ai_found = 1
|
||||
else
|
||||
var/mob/found = ckeys[word]
|
||||
if(!found)
|
||||
found = surnames[word]
|
||||
if(!found)
|
||||
found = forenames[word]
|
||||
if(found)
|
||||
if(!(found in mobs_found))
|
||||
mobs_found += found
|
||||
if(!ai_found && isAI(found))
|
||||
ai_found = 1
|
||||
msg += "<b><font color='black'>[original_word] </font></b> "
|
||||
continue
|
||||
msg += "[original_word] "
|
||||
|
||||
if(!mob) return //this doesn't happen
|
||||
|
||||
//send this msg to all admins
|
||||
var/admin_number_afk = 0
|
||||
var/list/mentorholders = list()
|
||||
var/list/modholders = list()
|
||||
var/list/adminholders = list()
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_ADMIN, 0, X.mob))
|
||||
if(X.is_afk())
|
||||
admin_number_afk++
|
||||
adminholders += X
|
||||
continue
|
||||
if(check_rights(R_MOD, 0, X.mob))
|
||||
modholders += X
|
||||
continue
|
||||
if(check_rights(R_MENTOR, 0, X.mob))
|
||||
mentorholders += X
|
||||
continue
|
||||
var/ticketNum // Holder for the ticket number
|
||||
var/prunedmsg ="[src]: [msg]" // Message without links
|
||||
var/datum/ticket/T
|
||||
var/isMhelp = selected_type == "Mentorhelp"
|
||||
var/span
|
||||
if(isMhelp)
|
||||
span = "<span class='mentorhelp'>"
|
||||
if(SSmentor_tickets.checkForOpenTicket(src)) // If user already has an open ticket
|
||||
T = SSmentor_tickets.checkForOpenTicket(src)
|
||||
else
|
||||
ticketNum = SSmentor_tickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
|
||||
else //Ahelp
|
||||
span = "<span class='adminhelp'>"
|
||||
if(SStickets.checkForOpenTicket(src)) // If user already has an open ticket
|
||||
T = SStickets.checkForOpenTicket(src) // Make T equal to the ticket they have open
|
||||
else
|
||||
ticketNum = SStickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
|
||||
|
||||
if(T)
|
||||
ticketNum = T.ticketNum // ticketNum is the number of their ticket.
|
||||
T.addResponse(src, msg)
|
||||
|
||||
msg = "[span][selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] ([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_TP(mob,"TP")]) ([ADMIN_SM(mob,"SM")]) ([admin_jump_link(mob)]) (<A HREF='?_src_=holder;[isMhelp ? "openmentorticket" : "openadminticket"]=[ticketNum]'>TICKET</A>) [ai_found ? "(<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""] (<A HREF='?_src_=holder;take_question=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>TAKE</A>) (<A HREF='?_src_=holder;resolve=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>RESOLVE</A>) [isMhelp ? "" : "<A HREF='?_src_=holder;autorespond=[ticketNum]'>(AUTO)</A>"] :</span> [span][msg]</span>"
|
||||
if(isMhelp)
|
||||
//Open a new adminticket and inform the user.
|
||||
SSmentor_tickets.newTicket(src, prunedmsg, msg)
|
||||
for(var/client/X in mentorholders + modholders + adminholders)
|
||||
if(X.prefs.sound & SOUND_MENTORHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
to_chat(X, msg)
|
||||
else //Ahelp
|
||||
//Open a new adminticket and inform the user.
|
||||
SStickets.newTicket(src, prunedmsg, msg)
|
||||
for(var/client/X in modholders + adminholders)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
window_flash(X)
|
||||
to_chat(X, msg)
|
||||
|
||||
|
||||
|
||||
//show it to the person adminhelping too
|
||||
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [original_msg]</span>")
|
||||
|
||||
var/admin_number_present = adminholders.len - admin_number_afk
|
||||
log_admin("[selected_type]: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.")
|
||||
if(admin_number_present <= 0)
|
||||
if(!admin_number_afk)
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!No admins online!!")
|
||||
else
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!All admins AFK ([admin_number_afk])!!")
|
||||
else
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg]")
|
||||
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
|
||||
var/admin_number_total = 0 //Total number of admins
|
||||
var/admin_number_afk = 0 //Holds the number of admins who are afk
|
||||
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
|
||||
var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
|
||||
for(var/client/X in GLOB.admins)
|
||||
admin_number_total++;
|
||||
var/invalid = 0
|
||||
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
|
||||
admin_number_ignored++
|
||||
invalid = 1
|
||||
if(X.is_afk())
|
||||
admin_number_afk++
|
||||
invalid = 1
|
||||
if(X.holder.fakekey)
|
||||
admin_number_ignored++
|
||||
invalid = 1
|
||||
if(invalid)
|
||||
admin_number_decrease++
|
||||
var/admin_number_present = admin_number_total - admin_number_decrease //Number of admins who are neither afk nor invalid
|
||||
if(admin_number_present <= 0)
|
||||
if(!admin_number_afk && !admin_number_ignored)
|
||||
send2irc(source, "[msg] - No admins online")
|
||||
else
|
||||
send2irc(source, "[msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])")
|
||||
return admin_number_present
|
||||
|
||||
|
||||
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
|
||||
GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","monkey","alien","as"))
|
||||
|
||||
/client/verb/adminhelp()
|
||||
set category = "Admin"
|
||||
set name = "Adminhelp"
|
||||
|
||||
//handle muting and automuting
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>")
|
||||
return
|
||||
|
||||
adminhelped = 1 //Determines if they get the message to reply by clicking the name.
|
||||
|
||||
var/msg
|
||||
var/list/type = list("Mentorhelp","Adminhelp")
|
||||
var/selected_type = input("Pick a category.", "Admin Help", null, null) as null|anything in type
|
||||
if(selected_type)
|
||||
msg = clean_input("Please enter your message.", "Admin Help", null)
|
||||
|
||||
//clean the input msg
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(handle_spam_prevention(msg, MUTE_ADMINHELP, OOC_COOLDOWN))
|
||||
return
|
||||
|
||||
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
var/original_msg = msg
|
||||
|
||||
//explode the input msg into a list
|
||||
var/list/msglist = splittext(msg, " ")
|
||||
|
||||
//generate keywords lookup
|
||||
var/list/surnames = list()
|
||||
var/list/forenames = list()
|
||||
var/list/ckeys = list()
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
var/list/indexing = list(M.real_name, M.name)
|
||||
if(M.mind) indexing += M.mind.name
|
||||
|
||||
for(var/string in indexing)
|
||||
var/list/L = splittext(string, " ")
|
||||
var/surname_found = 0
|
||||
//surnames
|
||||
for(var/i=L.len, i>=1, i--)
|
||||
var/word = ckey(L[i])
|
||||
if(word)
|
||||
surnames[word] = M
|
||||
surname_found = i
|
||||
break
|
||||
//forenames
|
||||
for(var/i=1, i<surname_found, i++)
|
||||
var/word = ckey(L[i])
|
||||
if(word)
|
||||
forenames[word] = M
|
||||
//ckeys
|
||||
ckeys[M.ckey] = M
|
||||
|
||||
var/ai_found = 0
|
||||
msg = ""
|
||||
var/list/mobs_found = list()
|
||||
for(var/original_word in msglist)
|
||||
var/word = ckey(original_word)
|
||||
if(word)
|
||||
if(!(word in GLOB.adminhelp_ignored_words))
|
||||
if(word == "ai")
|
||||
ai_found = 1
|
||||
else
|
||||
var/mob/found = ckeys[word]
|
||||
if(!found)
|
||||
found = surnames[word]
|
||||
if(!found)
|
||||
found = forenames[word]
|
||||
if(found)
|
||||
if(!(found in mobs_found))
|
||||
mobs_found += found
|
||||
if(!ai_found && isAI(found))
|
||||
ai_found = 1
|
||||
msg += "<b><font color='black'>[original_word] </font></b> "
|
||||
continue
|
||||
msg += "[original_word] "
|
||||
|
||||
if(!mob) return //this doesn't happen
|
||||
|
||||
//send this msg to all admins
|
||||
var/admin_number_afk = 0
|
||||
var/list/mentorholders = list()
|
||||
var/list/modholders = list()
|
||||
var/list/adminholders = list()
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_ADMIN, 0, X.mob))
|
||||
if(X.is_afk())
|
||||
admin_number_afk++
|
||||
adminholders += X
|
||||
continue
|
||||
if(check_rights(R_MOD, 0, X.mob))
|
||||
modholders += X
|
||||
continue
|
||||
if(check_rights(R_MENTOR, 0, X.mob))
|
||||
mentorholders += X
|
||||
continue
|
||||
var/ticketNum // Holder for the ticket number
|
||||
var/prunedmsg ="[src]: [msg]" // Message without links
|
||||
var/datum/ticket/T
|
||||
var/isMhelp = selected_type == "Mentorhelp"
|
||||
var/span
|
||||
if(isMhelp)
|
||||
span = "<span class='mentorhelp'>"
|
||||
if(SSmentor_tickets.checkForOpenTicket(src)) // If user already has an open ticket
|
||||
T = SSmentor_tickets.checkForOpenTicket(src)
|
||||
else
|
||||
ticketNum = SSmentor_tickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
|
||||
else //Ahelp
|
||||
span = "<span class='adminhelp'>"
|
||||
if(SStickets.checkForOpenTicket(src)) // If user already has an open ticket
|
||||
T = SStickets.checkForOpenTicket(src) // Make T equal to the ticket they have open
|
||||
else
|
||||
ticketNum = SStickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
|
||||
|
||||
if(T)
|
||||
ticketNum = T.ticketNum // ticketNum is the number of their ticket.
|
||||
T.addResponse(src, msg)
|
||||
|
||||
msg = "[span][selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] ([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_TP(mob,"TP")]) ([ADMIN_SM(mob,"SM")]) ([admin_jump_link(mob)]) (<A HREF='?_src_=holder;[isMhelp ? "openmentorticket" : "openadminticket"]=[ticketNum]'>TICKET</A>) [ai_found ? "(<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""] (<A HREF='?_src_=holder;take_question=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>TAKE</A>) (<A HREF='?_src_=holder;resolve=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>RESOLVE</A>) [isMhelp ? "" : "<A HREF='?_src_=holder;autorespond=[ticketNum]'>(AUTO)</A>"] :</span> [span][msg]</span>"
|
||||
if(isMhelp)
|
||||
//Open a new adminticket and inform the user.
|
||||
SSmentor_tickets.newTicket(src, prunedmsg, msg)
|
||||
for(var/client/X in mentorholders + modholders + adminholders)
|
||||
if(X.prefs.sound & SOUND_MENTORHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
to_chat(X, msg)
|
||||
else //Ahelp
|
||||
//Open a new adminticket and inform the user.
|
||||
SStickets.newTicket(src, prunedmsg, msg)
|
||||
for(var/client/X in modholders + adminholders)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
window_flash(X)
|
||||
to_chat(X, msg)
|
||||
|
||||
|
||||
|
||||
//show it to the person adminhelping too
|
||||
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [original_msg]</span>")
|
||||
|
||||
var/admin_number_present = adminholders.len - admin_number_afk
|
||||
log_admin("[selected_type]: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.")
|
||||
if(admin_number_present <= 0)
|
||||
if(!admin_number_afk)
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!No admins online!!")
|
||||
else
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!All admins AFK ([admin_number_afk])!!")
|
||||
else
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg]")
|
||||
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
|
||||
var/admin_number_total = 0 //Total number of admins
|
||||
var/admin_number_afk = 0 //Holds the number of admins who are afk
|
||||
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
|
||||
var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
|
||||
for(var/client/X in GLOB.admins)
|
||||
admin_number_total++;
|
||||
var/invalid = 0
|
||||
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
|
||||
admin_number_ignored++
|
||||
invalid = 1
|
||||
if(X.is_afk())
|
||||
admin_number_afk++
|
||||
invalid = 1
|
||||
if(X.holder.fakekey)
|
||||
admin_number_ignored++
|
||||
invalid = 1
|
||||
if(invalid)
|
||||
admin_number_decrease++
|
||||
var/admin_number_present = admin_number_total - admin_number_decrease //Number of admins who are neither afk nor invalid
|
||||
if(admin_number_present <= 0)
|
||||
if(!admin_number_afk && !admin_number_ignored)
|
||||
send2irc(source, "[msg] - No admins online")
|
||||
else
|
||||
send2irc(source, "[msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])")
|
||||
return admin_number_present
|
||||
|
||||
@@ -1,161 +1,161 @@
|
||||
/client/proc/Jump(area/A in return_sorted_areas())
|
||||
set name = "Jump to Area"
|
||||
set desc = "Area to jump to"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(!A)
|
||||
return
|
||||
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in A)
|
||||
if(T.density)
|
||||
continue
|
||||
if(locate(/obj/structure/grille, T)) // Quick check to not spawn in windows
|
||||
continue
|
||||
turfs.Add(T)
|
||||
|
||||
var/turf/T = pick_n_take(turfs)
|
||||
if(!T)
|
||||
to_chat(src, "Nowhere to jump to!")
|
||||
return
|
||||
|
||||
admin_forcemove(usr, T)
|
||||
log_admin("[key_name(usr)] jumped to [A]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [A]")
|
||||
feedback_add_details("admin_verb","JA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/jumptoturf(var/turf/T in world)
|
||||
set name = "Jump to Turf"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]", 1)
|
||||
admin_forcemove(usr, T)
|
||||
feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/jumptomob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Jump to Mob"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
|
||||
if(src.mob)
|
||||
var/mob/A = src.mob
|
||||
var/turf/T = get_turf(M)
|
||||
if(T && isturf(T))
|
||||
feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
admin_forcemove(A, M.loc)
|
||||
else
|
||||
to_chat(A, "This mob is not located in the game world.")
|
||||
|
||||
/client/proc/jumptocoord(tx as num, ty as num, tz as num)
|
||||
set category = "Admin"
|
||||
set name = "Jump to Coordinate"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/turf/T = locate(tx, ty, tz)
|
||||
if(T)
|
||||
admin_forcemove(usr, T)
|
||||
if(isobserver(usr))
|
||||
var/mob/dead/observer/O = usr
|
||||
O.ManualFollow(T)
|
||||
feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]")
|
||||
|
||||
/client/proc/jumptokey()
|
||||
set category = "Admin"
|
||||
set name = "Jump to Key"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
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)
|
||||
if(!selection)
|
||||
to_chat(src, "No keys found.")
|
||||
return
|
||||
var/mob/M = selection:mob
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
|
||||
|
||||
admin_forcemove(usr, M.loc)
|
||||
|
||||
feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getmob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Get Mob"
|
||||
set desc = "Mob to teleport"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1)
|
||||
admin_forcemove(M, get_turf(usr))
|
||||
feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getkey()
|
||||
set category = "Admin"
|
||||
set name = "Get Key"
|
||||
set desc = "Key to teleport"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
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)
|
||||
if(!selection)
|
||||
return
|
||||
var/mob/M = selection:mob
|
||||
|
||||
if(!M)
|
||||
return
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1)
|
||||
if(M)
|
||||
admin_forcemove(M, get_turf(usr))
|
||||
admin_forcemove(usr, M.loc)
|
||||
feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/sendmob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Send Mob"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/area/A = input(usr, "Pick an area.", "Pick an area") in return_sorted_areas()
|
||||
if(A)
|
||||
admin_forcemove(M, pick(get_area_turfs(A)))
|
||||
feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1)
|
||||
|
||||
/proc/admin_forcemove(mob/mover, atom/newloc)
|
||||
mover.forceMove(newloc)
|
||||
mover.on_forcemove(newloc)
|
||||
|
||||
/mob/proc/on_forcemove(atom/newloc)
|
||||
return
|
||||
/client/proc/Jump(area/A in return_sorted_areas())
|
||||
set name = "Jump to Area"
|
||||
set desc = "Area to jump to"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(!A)
|
||||
return
|
||||
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in A)
|
||||
if(T.density)
|
||||
continue
|
||||
if(locate(/obj/structure/grille, T)) // Quick check to not spawn in windows
|
||||
continue
|
||||
turfs.Add(T)
|
||||
|
||||
var/turf/T = pick_n_take(turfs)
|
||||
if(!T)
|
||||
to_chat(src, "Nowhere to jump to!")
|
||||
return
|
||||
|
||||
admin_forcemove(usr, T)
|
||||
log_admin("[key_name(usr)] jumped to [A]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [A]")
|
||||
feedback_add_details("admin_verb","JA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/jumptoturf(var/turf/T in world)
|
||||
set name = "Jump to Turf"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]", 1)
|
||||
admin_forcemove(usr, T)
|
||||
feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/jumptomob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Jump to Mob"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
|
||||
if(src.mob)
|
||||
var/mob/A = src.mob
|
||||
var/turf/T = get_turf(M)
|
||||
if(T && isturf(T))
|
||||
feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
admin_forcemove(A, M.loc)
|
||||
else
|
||||
to_chat(A, "This mob is not located in the game world.")
|
||||
|
||||
/client/proc/jumptocoord(tx as num, ty as num, tz as num)
|
||||
set category = "Admin"
|
||||
set name = "Jump to Coordinate"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/turf/T = locate(tx, ty, tz)
|
||||
if(T)
|
||||
admin_forcemove(usr, T)
|
||||
if(isobserver(usr))
|
||||
var/mob/dead/observer/O = usr
|
||||
O.ManualFollow(T)
|
||||
feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]")
|
||||
|
||||
/client/proc/jumptokey()
|
||||
set category = "Admin"
|
||||
set name = "Jump to Key"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
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)
|
||||
if(!selection)
|
||||
to_chat(src, "No keys found.")
|
||||
return
|
||||
var/mob/M = selection:mob
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
|
||||
|
||||
admin_forcemove(usr, M.loc)
|
||||
|
||||
feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getmob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Get Mob"
|
||||
set desc = "Mob to teleport"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1)
|
||||
admin_forcemove(M, get_turf(usr))
|
||||
feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getkey()
|
||||
set category = "Admin"
|
||||
set name = "Get Key"
|
||||
set desc = "Key to teleport"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
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)
|
||||
if(!selection)
|
||||
return
|
||||
var/mob/M = selection:mob
|
||||
|
||||
if(!M)
|
||||
return
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1)
|
||||
if(M)
|
||||
admin_forcemove(M, get_turf(usr))
|
||||
admin_forcemove(usr, M.loc)
|
||||
feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/sendmob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Send Mob"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/area/A = input(usr, "Pick an area.", "Pick an area") in return_sorted_areas()
|
||||
if(A)
|
||||
admin_forcemove(M, pick(get_area_turfs(A)))
|
||||
feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1)
|
||||
|
||||
/proc/admin_forcemove(mob/mover, atom/newloc)
|
||||
mover.forceMove(newloc)
|
||||
mover.on_forcemove(newloc)
|
||||
|
||||
/mob/proc/on_forcemove(atom/newloc)
|
||||
return
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
/datum/pm_tracker
|
||||
var/current_title = ""
|
||||
var/open = FALSE
|
||||
var/list/pms = list()
|
||||
var/list/datum/pm_convo/pms = list()
|
||||
var/show_archived = FALSE
|
||||
var/window_id = "pms_window"
|
||||
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
/client/proc/cmd_admin_say(msg as text)
|
||||
set category = "Admin"
|
||||
set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite
|
||||
set hidden = 1
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
|
||||
log_adminsay(msg, src)
|
||||
|
||||
if(check_rights(R_ADMIN,0))
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(R_ADMIN & C.holder.rights)
|
||||
msg = "<span class='emoji_enabled'>[msg]</span>"
|
||||
to_chat(C, "<span class='admin_channel'>ADMIN: <span class='name'>[key_name(usr, 1)]</span> ([admin_jump_link(mob)]): <span class='message'>[msg]</span></span>")
|
||||
|
||||
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/get_admin_say()
|
||||
var/msg = input(src, null, "asay \"text\"") as text|null
|
||||
cmd_admin_say(msg)
|
||||
|
||||
/client/proc/cmd_mentor_say(msg as text)
|
||||
set category = "Admin"
|
||||
set name = "Msay"
|
||||
set hidden = 1
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD|R_MENTOR))
|
||||
return
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
log_mentorsay(msg, src)
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob))
|
||||
var/display_name = key
|
||||
if(holder.fakekey)
|
||||
if(C.holder && C.holder.rights & R_ADMIN)
|
||||
display_name = "[holder.fakekey]/([key])"
|
||||
else
|
||||
display_name = holder.fakekey
|
||||
msg = "<span class='emoji_enabled'>[msg]</span>"
|
||||
to_chat(C, "<span class='[check_rights(R_ADMIN, 0) ? "mentor_channel_admin" : "mentor_channel"]'>MENTOR: <span class='name'>[display_name]</span> ([admin_jump_link(mob)]): <span class='message'>[msg]</span></span>")
|
||||
|
||||
feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/toggle_mentor_chat()
|
||||
set category = "Server"
|
||||
set name = "Toggle Mentor Chat"
|
||||
set desc = "Toggle whether mentors have access to the msay command"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/enabling
|
||||
var/msay = /client/proc/cmd_mentor_say
|
||||
|
||||
if(msay in admin_verbs_mentor)
|
||||
enabling = FALSE
|
||||
admin_verbs_mentor -= msay
|
||||
else
|
||||
enabling = TRUE
|
||||
admin_verbs_mentor += msay
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_ADMIN|R_MOD, 0, C.mob))
|
||||
continue
|
||||
if(!check_rights(R_MENTOR, 0, C.mob))
|
||||
continue
|
||||
if(enabling)
|
||||
C.verbs += msay
|
||||
to_chat(C, "<b>Mentor chat has been enabled.</b> Use 'msay' to speak in it.")
|
||||
else
|
||||
C.verbs -= msay
|
||||
to_chat(C, "<b>Mentor chat has been disabled.</b>")
|
||||
|
||||
admin_log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
|
||||
feedback_add_details("admin_verb", "TMC")
|
||||
/client/proc/cmd_admin_say(msg as text)
|
||||
set category = "Admin"
|
||||
set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite
|
||||
set hidden = 1
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
|
||||
log_adminsay(msg, src)
|
||||
|
||||
if(check_rights(R_ADMIN,0))
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(R_ADMIN & C.holder.rights)
|
||||
msg = "<span class='emoji_enabled'>[msg]</span>"
|
||||
to_chat(C, "<span class='admin_channel'>ADMIN: <span class='name'>[key_name(usr, 1)]</span> ([admin_jump_link(mob)]): <span class='message'>[msg]</span></span>")
|
||||
|
||||
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/get_admin_say()
|
||||
var/msg = input(src, null, "asay \"text\"") as text|null
|
||||
cmd_admin_say(msg)
|
||||
|
||||
/client/proc/cmd_mentor_say(msg as text)
|
||||
set category = "Admin"
|
||||
set name = "Msay"
|
||||
set hidden = 1
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD|R_MENTOR))
|
||||
return
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
log_mentorsay(msg, src)
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob))
|
||||
var/display_name = key
|
||||
if(holder.fakekey)
|
||||
if(C.holder && C.holder.rights & R_ADMIN)
|
||||
display_name = "[holder.fakekey]/([key])"
|
||||
else
|
||||
display_name = holder.fakekey
|
||||
msg = "<span class='emoji_enabled'>[msg]</span>"
|
||||
to_chat(C, "<span class='[check_rights(R_ADMIN, 0) ? "mentor_channel_admin" : "mentor_channel"]'>MENTOR: <span class='name'>[display_name]</span> ([admin_jump_link(mob)]): <span class='message'>[msg]</span></span>")
|
||||
|
||||
feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/toggle_mentor_chat()
|
||||
set category = "Server"
|
||||
set name = "Toggle Mentor Chat"
|
||||
set desc = "Toggle whether mentors have access to the msay command"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/enabling
|
||||
var/msay = /client/proc/cmd_mentor_say
|
||||
|
||||
if(msay in GLOB.admin_verbs_mentor)
|
||||
enabling = FALSE
|
||||
GLOB.admin_verbs_mentor -= msay
|
||||
else
|
||||
enabling = TRUE
|
||||
GLOB.admin_verbs_mentor += msay
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_ADMIN|R_MOD, 0, C.mob))
|
||||
continue
|
||||
if(!check_rights(R_MENTOR, 0, C.mob))
|
||||
continue
|
||||
if(enabling)
|
||||
C.verbs += msay
|
||||
to_chat(C, "<b>Mentor chat has been enabled.</b> Use 'msay' to speak in it.")
|
||||
else
|
||||
C.verbs -= msay
|
||||
to_chat(C, "<b>Mentor chat has been disabled.</b>")
|
||||
|
||||
admin_log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
|
||||
feedback_add_details("admin_verb", "TMC")
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<br>Additionally make an attempt to introduce new players to the server
|
||||
<HR>"}
|
||||
|
||||
if(dbcon.IsConnected())
|
||||
if(GLOB.dbcon.IsConnected())
|
||||
for(var/client/C in GLOB.clients)
|
||||
dat += "<p>[C.ckey] (Player Age: <font color = 'red'>[C.player_age]</font>) - <b>[C.computer_id]</b> / <b>[C.address]</b><br>"
|
||||
if(C.related_accounts_cid.len)
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
/client/proc/atmosscan()
|
||||
set category = "Mapping"
|
||||
set name = "Check Piping"
|
||||
set background = 1
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
if(alert("WARNING: This command should not be run on a live server. Do you want to continue?", "Check Piping", "No", "Yes") == "No")
|
||||
return
|
||||
|
||||
to_chat(usr, "Checking for disconnected pipes...")
|
||||
//all plumbing - yes, some things might get stated twice, doesn't matter.
|
||||
for(var/obj/machinery/atmospherics/plumbing in world)
|
||||
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 world)
|
||||
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 world)
|
||||
if(!pipe.node1 || !pipe.node2)
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
|
||||
|
||||
to_chat(usr, "Checking for overlapping pipes...")
|
||||
for(var/turf/T in world)
|
||||
for(var/dir in cardinal)
|
||||
var/list/check = list(0, 0, 0)
|
||||
var/done = 0
|
||||
for(var/obj/machinery/atmospherics/pipe in T)
|
||||
if(dir & pipe.initialize_directions)
|
||||
for(var/ct in pipe.connect_types)
|
||||
check[ct]++
|
||||
if(check[ct] > 1)
|
||||
to_chat(usr, "Overlapping pipe ([pipe.name]) located at [T.x],[T.y],[T.z] ([get_area(T)])")
|
||||
done = 1
|
||||
break
|
||||
if(done)
|
||||
break
|
||||
to_chat(usr, "Done")
|
||||
|
||||
/client/proc/powerdebug()
|
||||
set category = "Mapping"
|
||||
set name = "Check Power"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
feedback_add_details("admin_verb","CPOW") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
for(var/datum/powernet/PN in SSmachines.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)]")
|
||||
/client/proc/atmosscan()
|
||||
set category = "Mapping"
|
||||
set name = "Check Piping"
|
||||
set background = 1
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
if(alert("WARNING: This command should not be run on a live server. Do you want to continue?", "Check Piping", "No", "Yes") == "No")
|
||||
return
|
||||
|
||||
to_chat(usr, "Checking for disconnected pipes...")
|
||||
//all plumbing - yes, some things might get stated twice, doesn't matter.
|
||||
for(var/obj/machinery/atmospherics/plumbing in world)
|
||||
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 world)
|
||||
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 world)
|
||||
if(!pipe.node1 || !pipe.node2)
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
|
||||
|
||||
to_chat(usr, "Checking for overlapping pipes...")
|
||||
for(var/turf/T in world)
|
||||
for(var/dir in GLOB.cardinal)
|
||||
var/list/check = list(0, 0, 0)
|
||||
var/done = 0
|
||||
for(var/obj/machinery/atmospherics/pipe in T)
|
||||
if(dir & pipe.initialize_directions)
|
||||
for(var/ct in pipe.connect_types)
|
||||
check[ct]++
|
||||
if(check[ct] > 1)
|
||||
to_chat(usr, "Overlapping pipe ([pipe.name]) located at [T.x],[T.y],[T.z] ([get_area(T)])")
|
||||
done = 1
|
||||
break
|
||||
if(done)
|
||||
break
|
||||
to_chat(usr, "Done")
|
||||
|
||||
/client/proc/powerdebug()
|
||||
set category = "Mapping"
|
||||
set name = "Check Power"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
feedback_add_details("admin_verb","CPOW") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
for(var/datum/powernet/PN in SSmachines.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)]")
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
override = input(src, "mode = ?","Enter Parameter", null) as anything in list("nuclear emergency", "fake", "no override")
|
||||
if(0)
|
||||
override = input(src, "mode = ?","Enter Parameter", null) as anything in list("blob", "nuclear emergency", "AI malfunction", "no override")
|
||||
SSticker.station_explosion_cinematic(parameter, override)
|
||||
SSticker.station_explosion_cinematic(parameter, override)
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
|
||||
var/input = input(usr, "Enter the description of the custom event. Be descriptive. To cancel the event, make this blank or hit cancel.", "Custom Event", custom_event_msg) as message|null
|
||||
var/input = input(usr, "Enter the description of the custom event. Be descriptive. To cancel the event, make this blank or hit cancel.", "Custom Event", GLOB.custom_event_msg) as message|null
|
||||
if(!input || input == "")
|
||||
custom_event_msg = null
|
||||
GLOB.custom_event_msg = null
|
||||
log_admin("[key_name(usr)] has cleared the custom event text.")
|
||||
message_admins("[key_name_admin(usr)] has cleared the custom event text.")
|
||||
return
|
||||
@@ -17,11 +17,11 @@
|
||||
log_admin("[key_name(usr)] has changed the custom event text.")
|
||||
message_admins("[key_name_admin(usr)] has changed the custom event text.")
|
||||
|
||||
custom_event_msg = input
|
||||
GLOB.custom_event_msg = input
|
||||
|
||||
to_chat(world, "<h1 class='alert'>Custom Event</h1>")
|
||||
to_chat(world, "<h2 class='alert'>A custom event is starting. OOC Info:</h2>")
|
||||
to_chat(world, "<span class='alert'>[html_encode(custom_event_msg)]</span>")
|
||||
to_chat(world, "<span class='alert'>[html_encode(GLOB.custom_event_msg)]</span>")
|
||||
to_chat(world, "<br>")
|
||||
|
||||
// normal verb for players to view info
|
||||
@@ -29,12 +29,12 @@
|
||||
set category = "OOC"
|
||||
set name = "Custom Event Info"
|
||||
|
||||
if(!custom_event_msg || custom_event_msg == "")
|
||||
if(!GLOB.custom_event_msg || GLOB.custom_event_msg == "")
|
||||
to_chat(src, "There currently is no known custom event taking place.")
|
||||
to_chat(src, "Keep in mind: it is possible that an admin has not properly set this.")
|
||||
return
|
||||
|
||||
to_chat(src, "<h1 class='alert'>Custom Event</h1>")
|
||||
to_chat(src, "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>")
|
||||
to_chat(src, "<span class='alert'>[html_encode(custom_event_msg)]</span>")
|
||||
to_chat(src, "<span class='alert'>[html_encode(GLOB.custom_event_msg)]</span>")
|
||||
to_chat(src, "<br>")
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
/client/proc/dsay(msg as text)
|
||||
set category = "Admin"
|
||||
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(!check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
|
||||
if(!src.mob)
|
||||
return
|
||||
|
||||
if(prefs.muted & MUTE_DEADCHAT)
|
||||
to_chat(src, "<span class='warning'>You cannot send DSAY messages (muted).</span>")
|
||||
return
|
||||
|
||||
if(!(prefs.toggles & CHAT_DEAD))
|
||||
to_chat(src, "<span class='warning'>You have deadchat muted.</span>")
|
||||
return
|
||||
|
||||
if(handle_spam_prevention(msg,MUTE_DEADCHAT))
|
||||
return
|
||||
|
||||
var/stafftype = null
|
||||
|
||||
if(check_rights(R_MENTOR, 0))
|
||||
stafftype = "MENTOR"
|
||||
|
||||
if(check_rights(R_MOD, 0))
|
||||
stafftype = "MOD"
|
||||
|
||||
if(check_rights(R_ADMIN, 0))
|
||||
stafftype = "ADMIN"
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
log_admin("[key_name(src)] : [msg]")
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/prefix = "[stafftype] ([src.key])"
|
||||
if(holder.fakekey)
|
||||
prefix = "Administrator"
|
||||
say_dead_direct("<span class='name'>[prefix]</span> says, <span class='message'>\"[msg]\"</span>")
|
||||
|
||||
feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/get_dead_say()
|
||||
var/msg = input(src, null, "dsay \"text\"") as text
|
||||
dsay(msg)
|
||||
/client/proc/dsay(msg as text)
|
||||
set category = "Admin"
|
||||
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(!check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
|
||||
if(!src.mob)
|
||||
return
|
||||
|
||||
if(prefs.muted & MUTE_DEADCHAT)
|
||||
to_chat(src, "<span class='warning'>You cannot send DSAY messages (muted).</span>")
|
||||
return
|
||||
|
||||
if(!(prefs.toggles & CHAT_DEAD))
|
||||
to_chat(src, "<span class='warning'>You have deadchat muted.</span>")
|
||||
return
|
||||
|
||||
if(handle_spam_prevention(msg,MUTE_DEADCHAT))
|
||||
return
|
||||
|
||||
var/stafftype = null
|
||||
|
||||
if(check_rights(R_MENTOR, 0))
|
||||
stafftype = "MENTOR"
|
||||
|
||||
if(check_rights(R_MOD, 0))
|
||||
stafftype = "MOD"
|
||||
|
||||
if(check_rights(R_ADMIN, 0))
|
||||
stafftype = "ADMIN"
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
log_admin("[key_name(src)] : [msg]")
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/prefix = "[stafftype] ([src.key])"
|
||||
if(holder.fakekey)
|
||||
prefix = "Administrator"
|
||||
say_dead_direct("<span class='name'>[prefix]</span> says, <span class='message'>\"[msg]\"</span>")
|
||||
|
||||
feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/get_dead_say()
|
||||
var/msg = input(src, null, "dsay \"text\"") as text
|
||||
dsay(msg)
|
||||
|
||||
+894
-892
File diff suppressed because it is too large
Load Diff
@@ -1,178 +1,178 @@
|
||||
/client/proc/air_status(turf/target as turf)
|
||||
set category = "Debug"
|
||||
set name = "Display Air Status"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
if(!isturf(target))
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/GM = target.return_air()
|
||||
var/burning = 0
|
||||
if(istype(target, /turf/simulated))
|
||||
var/turf/simulated/T = target
|
||||
if(T.active_hotspot)
|
||||
burning = 1
|
||||
|
||||
to_chat(usr, "<span class='notice'>@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("<span class='warning'>BURNING</span>"):(null)]</span>")
|
||||
for(var/datum/gas/trace_gas in GM.trace_gases)
|
||||
to_chat(usr, "[trace_gas.type]: [trace_gas.moles]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has checked the air status of [T]")
|
||||
log_admin("[key_name(usr)] has checked the air status of [T]")
|
||||
|
||||
feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/fix_next_move()
|
||||
set category = "Debug"
|
||||
set name = "Unfreeze Everyone"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(usr)] has unfrozen everyone")
|
||||
log_admin("[key_name(usr)] has unfrozen everyone")
|
||||
|
||||
var/largest_move_time = 0
|
||||
var/largest_click_time = 0
|
||||
var/mob/largest_move_mob = null
|
||||
var/mob/largest_click_mob = null
|
||||
for(var/mob/M in world)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(M.next_move >= largest_move_time)
|
||||
largest_move_mob = M
|
||||
if(M.next_move > world.time)
|
||||
largest_move_time = M.next_move - world.time
|
||||
else
|
||||
largest_move_time = 1
|
||||
if(M.next_click >= largest_click_time)
|
||||
largest_click_mob = M
|
||||
if(M.next_click > world.time)
|
||||
largest_click_time = M.next_click - world.time
|
||||
else
|
||||
largest_click_time = 0
|
||||
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]")
|
||||
M.next_move = 1
|
||||
M.next_click = 0
|
||||
|
||||
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1)
|
||||
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1)
|
||||
message_admins("world.time = [world.time]", 1)
|
||||
|
||||
feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/radio_report()
|
||||
set category = "Debug"
|
||||
set name = "Radio report"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/filters = list(
|
||||
"1" = "RADIO_TO_AIRALARM",
|
||||
"2" = "RADIO_FROM_AIRALARM",
|
||||
"3" = "RADIO_CHAT",
|
||||
"4" = "RADIO_ATMOSIA",
|
||||
"5" = "RADIO_NAVBEACONS",
|
||||
"6" = "RADIO_AIRLOCK",
|
||||
"7" = "RADIO_SECBOT",
|
||||
"8" = "RADIO_MULEBOT",
|
||||
"_default" = "NO_FILTER"
|
||||
)
|
||||
var/output = "<b>Radio Report</b><hr>"
|
||||
for(var/fq in SSradio.frequencies)
|
||||
output += "<b>Freq: [fq]</b><br>"
|
||||
var/list/datum/radio_frequency/fqs = SSradio.frequencies[fq]
|
||||
if(!fqs)
|
||||
output += " <b>ERROR</b><br>"
|
||||
continue
|
||||
for(var/filter in fqs.devices)
|
||||
var/list/f = fqs.devices[filter]
|
||||
if(!f)
|
||||
output += " [filters[filter]]: ERROR<br>"
|
||||
continue
|
||||
output += " [filters[filter]]: [f.len]<br>"
|
||||
for(var/device in f)
|
||||
if(isobj(device))
|
||||
output += " [device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])<br>"
|
||||
else
|
||||
output += " [device]<br>"
|
||||
|
||||
usr << browse(output,"window=radioreport")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has generated a radio report")
|
||||
log_admin("[key_name(usr)] has generated a radio report")
|
||||
|
||||
feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/reload_admins()
|
||||
set name = "Reload Admins"
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(usr)] has manually reloaded admins")
|
||||
log_admin("[key_name(usr)] has manually reloaded admins")
|
||||
|
||||
load_admins()
|
||||
feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/client/proc/print_jobban_old()
|
||||
set name = "Print Jobban Log"
|
||||
set desc = "This spams all the active jobban entries for the current round to standard output."
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
to_chat(usr, "<b>Jobbans active in this round.</b>")
|
||||
for(var/t in jobban_keylist)
|
||||
to_chat(usr, "[t]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has printed the jobban log")
|
||||
log_admin("[key_name(usr)] has printed the jobban log")
|
||||
|
||||
/client/proc/print_jobban_old_filter()
|
||||
set name = "Search Jobban Log"
|
||||
set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output."
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/filter = clean_input("Contains what?","Filter")
|
||||
if(!filter)
|
||||
return
|
||||
|
||||
to_chat(usr, "<b>Jobbans active in this round.</b>")
|
||||
for(var/t in jobban_keylist)
|
||||
if(findtext(t, filter))
|
||||
to_chat(usr, "[t]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has searched the jobban log for [filter]")
|
||||
log_admin("[key_name(usr)] has searched the jobban log for [filter]")
|
||||
|
||||
/client/proc/vv_by_ref()
|
||||
set name = "VV by Ref"
|
||||
set desc = "Give this a ref string, and you will see its corresponding VV panel if it exists"
|
||||
set category = "Debug"
|
||||
|
||||
// It's gated by "Debug Verbs", so might as well gate it to the debug permission
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/refstring = clean_input("Which reference?","Ref")
|
||||
if(!refstring)
|
||||
return
|
||||
|
||||
var/datum/D = locate(refstring)
|
||||
if(!D)
|
||||
to_chat(usr, "<span class='warning'>That ref string does not correspond to any datum.</span>")
|
||||
return
|
||||
|
||||
debug_variables(D)
|
||||
/client/proc/air_status(turf/target as turf)
|
||||
set category = "Debug"
|
||||
set name = "Display Air Status"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
if(!isturf(target))
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/GM = target.return_air()
|
||||
var/burning = 0
|
||||
if(istype(target, /turf/simulated))
|
||||
var/turf/simulated/T = target
|
||||
if(T.active_hotspot)
|
||||
burning = 1
|
||||
|
||||
to_chat(usr, "<span class='notice'>@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("<span class='warning'>BURNING</span>"):(null)]</span>")
|
||||
for(var/datum/gas/trace_gas in GM.trace_gases)
|
||||
to_chat(usr, "[trace_gas.type]: [trace_gas.moles]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has checked the air status of [target]")
|
||||
log_admin("[key_name(usr)] has checked the air status of [target]")
|
||||
|
||||
feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/fix_next_move()
|
||||
set category = "Debug"
|
||||
set name = "Unfreeze Everyone"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(usr)] has unfrozen everyone")
|
||||
log_admin("[key_name(usr)] has unfrozen everyone")
|
||||
|
||||
var/largest_move_time = 0
|
||||
var/largest_click_time = 0
|
||||
var/mob/largest_move_mob = null
|
||||
var/mob/largest_click_mob = null
|
||||
for(var/mob/M in world)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(M.next_move >= largest_move_time)
|
||||
largest_move_mob = M
|
||||
if(M.next_move > world.time)
|
||||
largest_move_time = M.next_move - world.time
|
||||
else
|
||||
largest_move_time = 1
|
||||
if(M.next_click >= largest_click_time)
|
||||
largest_click_mob = M
|
||||
if(M.next_click > world.time)
|
||||
largest_click_time = M.next_click - world.time
|
||||
else
|
||||
largest_click_time = 0
|
||||
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]")
|
||||
M.next_move = 1
|
||||
M.next_click = 0
|
||||
|
||||
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1)
|
||||
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1)
|
||||
message_admins("world.time = [world.time]", 1)
|
||||
|
||||
feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/radio_report()
|
||||
set category = "Debug"
|
||||
set name = "Radio report"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/filters = list(
|
||||
"1" = "RADIO_TO_AIRALARM",
|
||||
"2" = "RADIO_FROM_AIRALARM",
|
||||
"3" = "RADIO_CHAT",
|
||||
"4" = "RADIO_ATMOSIA",
|
||||
"5" = "RADIO_NAVBEACONS",
|
||||
"6" = "RADIO_AIRLOCK",
|
||||
"7" = "RADIO_SECBOT",
|
||||
"8" = "RADIO_MULEBOT",
|
||||
"_default" = "NO_FILTER"
|
||||
)
|
||||
var/output = "<b>Radio Report</b><hr>"
|
||||
for(var/fq in SSradio.frequencies)
|
||||
output += "<b>Freq: [fq]</b><br>"
|
||||
var/datum/radio_frequency/fqs = SSradio.frequencies[fq]
|
||||
if(!fqs)
|
||||
output += " <b>ERROR</b><br>"
|
||||
continue
|
||||
for(var/filter in fqs.devices)
|
||||
var/list/f = fqs.devices[filter]
|
||||
if(!f)
|
||||
output += " [filters[filter]]: ERROR<br>"
|
||||
continue
|
||||
output += " [filters[filter]]: [f.len]<br>"
|
||||
for(var/device in f)
|
||||
if(isobj(device))
|
||||
output += " [device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])<br>"
|
||||
else
|
||||
output += " [device]<br>"
|
||||
|
||||
usr << browse(output,"window=radioreport")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has generated a radio report")
|
||||
log_admin("[key_name(usr)] has generated a radio report")
|
||||
|
||||
feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/reload_admins()
|
||||
set name = "Reload Admins"
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(usr)] has manually reloaded admins")
|
||||
log_admin("[key_name(usr)] has manually reloaded admins")
|
||||
|
||||
load_admins()
|
||||
feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/client/proc/print_jobban_old()
|
||||
set name = "Print Jobban Log"
|
||||
set desc = "This spams all the active jobban entries for the current round to standard output."
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
to_chat(usr, "<b>Jobbans active in this round.</b>")
|
||||
for(var/t in GLOB.jobban_keylist)
|
||||
to_chat(usr, "[t]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has printed the jobban log")
|
||||
log_admin("[key_name(usr)] has printed the jobban log")
|
||||
|
||||
/client/proc/print_jobban_old_filter()
|
||||
set name = "Search Jobban Log"
|
||||
set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output."
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/filter = clean_input("Contains what?","Filter")
|
||||
if(!filter)
|
||||
return
|
||||
|
||||
to_chat(usr, "<b>Jobbans active in this round.</b>")
|
||||
for(var/t in GLOB.jobban_keylist)
|
||||
if(findtext(t, filter))
|
||||
to_chat(usr, "[t]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has searched the jobban log for [filter]")
|
||||
log_admin("[key_name(usr)] has searched the jobban log for [filter]")
|
||||
|
||||
/client/proc/vv_by_ref()
|
||||
set name = "VV by Ref"
|
||||
set desc = "Give this a ref string, and you will see its corresponding VV panel if it exists"
|
||||
set category = "Debug"
|
||||
|
||||
// It's gated by "Debug Verbs", so might as well gate it to the debug permission
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/refstring = clean_input("Which reference?","Ref")
|
||||
if(!refstring)
|
||||
return
|
||||
|
||||
var/datum/D = locate(refstring)
|
||||
if(!D)
|
||||
to_chat(usr, "<span class='warning'>That ref string does not correspond to any datum.</span>")
|
||||
return
|
||||
|
||||
debug_variables(D)
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
if(alert("Do you want to inform the world about the result?",,"Yes", "No") == "Yes")
|
||||
to_chat(world, "<h2 style=\"color:#A50400\">Gods rolled [dice], result is [result]</h2>")
|
||||
|
||||
message_admins("[key_name_admin(src)] rolled dice [dice], result is [result]", 1)
|
||||
message_admins("[key_name_admin(src)] rolled dice [dice], result is [result]", 1)
|
||||
|
||||
@@ -5,121 +5,99 @@
|
||||
//////Allows admin's to right click on any mob/mech and freeze them in place.///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
var/global/list/frozen_mob_list = list()
|
||||
/client/proc/freeze(var/mob/living/M as mob in GLOB.mob_list)
|
||||
|
||||
GLOBAL_LIST_EMPTY(frozen_atom_list) // A list of admin-frozen atoms.
|
||||
|
||||
/client/proc/freeze(atom/movable/M)
|
||||
set name = "Freeze"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(!istype(M))
|
||||
return
|
||||
M.admin_Freeze(src)
|
||||
|
||||
if(M in frozen_mob_list)
|
||||
M.admin_unFreeze(src)
|
||||
else
|
||||
M.admin_Freeze(src)
|
||||
/// Created here as a base proc. Override as needed for any type of object or mob you want able to be frozen.
|
||||
/atom/movable/proc/admin_Freeze(client/admin)
|
||||
to_chat(admin, "<span class='warning'>Freeze is not able to be called on this type of object.</span")
|
||||
return
|
||||
|
||||
///mob freeze procs
|
||||
|
||||
/mob/living/var/frozen = null //used for preventing attacks on admin-frozen mobs
|
||||
/mob/living/var/admin_prev_sleeping = 0 //used for keeping track of previous sleeping value with admin freeze
|
||||
/mob/living
|
||||
/// Used for preventing attacks on admin-frozen mobs.
|
||||
var/frozen = null
|
||||
/// Used for keeping track of previous sleeping value with admin freeze.
|
||||
var/admin_prev_sleeping = 0
|
||||
|
||||
/mob/living/proc/admin_Freeze(client/admin, skip_overlays = FALSE)
|
||||
if(istype(admin))
|
||||
to_chat(src, "<b><font color= red>You have been frozen by [admin]</b></font>")
|
||||
message_admins("<span class='notice'>[key_name_admin(admin)]</span> froze [key_name_admin(src)]")
|
||||
log_admin("[key_name(admin)] froze [key_name(src)]")
|
||||
/mob/living/admin_Freeze(client/admin, skip_overlays = FALSE, mech = null)
|
||||
if(!istype(admin))
|
||||
return
|
||||
|
||||
var/obj/effect/overlay/adminoverlay/AO = new
|
||||
if(skip_overlays)
|
||||
overlays += AO
|
||||
if(!(src in GLOB.frozen_atom_list))
|
||||
GLOB.frozen_atom_list += src
|
||||
|
||||
anchored = TRUE
|
||||
canmove = FALSE
|
||||
admin_prev_sleeping = sleeping
|
||||
AdjustSleeping(20000)
|
||||
frozen = AO
|
||||
if(!(src in frozen_mob_list))
|
||||
frozen_mob_list += src
|
||||
var/obj/effect/overlay/adminoverlay/AO = new
|
||||
if(skip_overlays)
|
||||
overlays += AO
|
||||
|
||||
/mob/living/proc/admin_unFreeze(client/admin, skip_overlays = FALSE)
|
||||
if(istype(admin))
|
||||
to_chat(src, "<b><font color= red>You have been unfrozen by [admin]</b></font>")
|
||||
message_admins("<span class='notice'>[key_name_admin(admin)] unfroze [key_name_admin(src)]</span>")
|
||||
log_admin("[key_name(admin)] unfroze [key_name(src)]")
|
||||
anchored = TRUE
|
||||
canmove = FALSE
|
||||
admin_prev_sleeping = sleeping
|
||||
AdjustSleeping(20000)
|
||||
frozen = AO
|
||||
|
||||
if(skip_overlays)
|
||||
overlays -= frozen
|
||||
else
|
||||
GLOB.frozen_atom_list -= src
|
||||
|
||||
anchored = FALSE
|
||||
canmove = TRUE
|
||||
frozen = null
|
||||
SetSleeping(admin_prev_sleeping)
|
||||
admin_prev_sleeping = null
|
||||
if(src in frozen_mob_list)
|
||||
frozen_mob_list -= src
|
||||
if(skip_overlays)
|
||||
overlays -= frozen
|
||||
|
||||
anchored = FALSE
|
||||
canmove = TRUE
|
||||
frozen = null
|
||||
SetSleeping(admin_prev_sleeping)
|
||||
admin_prev_sleeping = null
|
||||
|
||||
to_chat(src, "<b><font color= red>You have been [frozen ? "frozen" : "unfrozen"] by [admin]</b></font>")
|
||||
message_admins("<span class='notice'>[key_name_admin(admin)] [frozen ? "froze" : "unfroze"] [key_name_admin(src)] [mech ? "in a [mech]" : ""]</span>")
|
||||
log_admin("[key_name(admin)] [frozen ? "froze" : "unfroze"] [key_name(src)] [mech ? "in a [mech]" : ""]")
|
||||
update_icons()
|
||||
|
||||
return frozen
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/admin_Freeze(admin)
|
||||
..(admin)
|
||||
adjustHealth(1000) //arbitrary large value
|
||||
|
||||
/mob/living/simple_animal/slime/admin_unFreeze(admin)
|
||||
..(admin)
|
||||
revive()
|
||||
|
||||
if(..()) // The result of the parent call here will be the value of the mob's `frozen` variable after they get (un)frozen.
|
||||
adjustHealth(1000) //arbitrary large value
|
||||
else
|
||||
revive()
|
||||
|
||||
/mob/living/simple_animal/var/admin_prev_health = null
|
||||
|
||||
/mob/living/simple_animal/admin_Freeze(admin)
|
||||
..(admin)
|
||||
admin_prev_health = health
|
||||
health = 0
|
||||
|
||||
/mob/living/simple_animal/admin_unFreeze(admin)
|
||||
..(admin)
|
||||
revive()
|
||||
overlays.Cut()
|
||||
if(..()) // The result of the parent call here will be the value of the mob's `frozen` variable after they get (un)frozen.
|
||||
admin_prev_health = health
|
||||
health = 0
|
||||
else
|
||||
revive()
|
||||
overlays.Cut()
|
||||
|
||||
//////////////////////////Freeze Mech
|
||||
|
||||
/client/proc/freezemecha(var/obj/mecha/O as obj in GLOB.mechas_list)
|
||||
set name = "Freeze Mech"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/obj/mecha/M = O
|
||||
if(!istype(M,/obj/mecha))
|
||||
to_chat(src, "<span class='danger'>This can only be used on mechs!</span>")
|
||||
return
|
||||
/obj/mecha/admin_Freeze(client/admin)
|
||||
var/obj/effect/overlay/adminoverlay/freeze_overlay = new
|
||||
if(!frozen)
|
||||
GLOB.frozen_atom_list += src
|
||||
frozen = TRUE
|
||||
overlays += freeze_overlay
|
||||
else
|
||||
if(usr)
|
||||
if(usr.client)
|
||||
if(usr.client.holder)
|
||||
var/adminomaly = new/obj/effect/overlay/adminoverlay
|
||||
if(M.can_move == 1)
|
||||
M.can_move = 0
|
||||
M.overlays += adminomaly
|
||||
if(M.occupant)
|
||||
to_chat(M.occupant, "<b><font color= red>You have been frozen by <a href='?priv_msg=[usr.client.UID()]'>[key]</a></b></font>")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] froze [key_name(M.occupant)] in a [M.name]</span>")
|
||||
log_admin("[key_name(usr)] froze [key_name(M.occupant)] in a [M.name]")
|
||||
else
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] froze an empty [M.name]</span>")
|
||||
log_admin("[key_name(usr)] froze an empty [M.name]")
|
||||
else if(M.can_move == 0)
|
||||
M.can_move = 1
|
||||
M.overlays -= adminomaly
|
||||
if(M.occupant)
|
||||
to_chat(M.occupant, "<b><font color= red>You have been unfrozen by <a href='?priv_msg=[usr.client.UID()]'>[key]</a></b></font>")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] unfroze [key_name(M.occupant)] in a [M.name]</span>")
|
||||
log_admin("[key_name(usr)] unfroze [key_name(M.occupant)] in a [M.name]")
|
||||
else
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] unfroze an empty [M.name]</span>")
|
||||
log_admin("[key_name(usr)] unfroze an empty [M.name]")
|
||||
GLOB.frozen_atom_list -= src
|
||||
frozen = FALSE
|
||||
overlays -= freeze_overlay
|
||||
|
||||
if(occupant)
|
||||
occupant.admin_Freeze(admin, mech = name) // We also want to freeze the driver of the mech.
|
||||
else
|
||||
message_admins("<span class='notice'>[key_name_admin(admin)] [frozen ? "froze" : "unfroze"] an empty [name]</span>")
|
||||
log_admin("[key_name(admin)] [frozen ? "froze" : "unfroze"] an empty [name]")
|
||||
|
||||
@@ -38,4 +38,4 @@
|
||||
else
|
||||
return
|
||||
to_chat(src, "Attempting to send [path], this may take a fair few minutes if the file is very large.")
|
||||
return
|
||||
return
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
if(!themission)
|
||||
alert("No mission specified. Aborting.")
|
||||
return
|
||||
var/admin_outfits = subtypesof(/datum/outfit/admin)
|
||||
var/admin_outfits = subtypesof(/datum/outfit/admin) + list(/datum/outfit/naked)
|
||||
var/outfit_list = list()
|
||||
for(var/type in admin_outfits)
|
||||
var/datum/outfit/admin/O = type
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//HONKsquad
|
||||
|
||||
var/const/honksquad_possible = 6 //if more Commandos are needed in the future
|
||||
var/global/sent_honksquad = 0
|
||||
#define HONKSQUAD_POSSIBLE 6 //if more Commandos are needed in the future
|
||||
GLOBAL_VAR_INIT(sent_honksquad, 0)
|
||||
|
||||
/client/proc/honksquad()
|
||||
if(!SSticker)
|
||||
@@ -10,7 +10,7 @@ var/global/sent_honksquad = 0
|
||||
if(world.time < 6000)
|
||||
to_chat(usr, "<font color='red'>There are [(6000-world.time)/10] seconds remaining before it may be called.</font>")
|
||||
return
|
||||
if(sent_honksquad == 1)
|
||||
if(GLOB.sent_honksquad == 1)
|
||||
to_chat(usr, "<font color='red'>Clown Planet has already dispatched a HONKsquad.</font>")
|
||||
return
|
||||
if(alert("Do you want to send in the HONKsquad? Once enabled, this is irreversible.",,"Yes","No")!="Yes")
|
||||
@@ -24,14 +24,14 @@ var/global/sent_honksquad = 0
|
||||
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
|
||||
return
|
||||
|
||||
if(sent_honksquad)
|
||||
if(GLOB.sent_honksquad)
|
||||
to_chat(usr, "Looks like someone beat you to it. HONK.")
|
||||
return
|
||||
|
||||
sent_honksquad = 1
|
||||
GLOB.sent_honksquad = 1
|
||||
|
||||
|
||||
var/honksquad_number = honksquad_possible //for selecting a leader
|
||||
var/honksquad_number = HONKSQUAD_POSSIBLE //for selecting a leader
|
||||
var/honk_leader_selected = 0 //when the leader is chosen. The last person spawned.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ var/global/sent_honksquad = 0
|
||||
if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list.
|
||||
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
|
||||
candidates += G.key
|
||||
for(var/i=honksquad_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected.
|
||||
for(var/i=HONKSQUAD_POSSIBLE,(i>0&&candidates.len),i--)//Decrease with every commando selected.
|
||||
var/candidate = input("Pick characters to spawn as the HONKsquad. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate.
|
||||
candidates -= candidate //Subtract from candidates.
|
||||
commandos += candidate//Add their ghost to commandos.
|
||||
@@ -132,7 +132,7 @@ var/global/sent_honksquad = 0
|
||||
var/obj/item/card/id/W = new(src)
|
||||
W.name = "[real_name]'s ID Card"
|
||||
W.icon_state = "centcom_old"
|
||||
W.access = list(access_clown)//They get full station access.
|
||||
W.access = list(ACCESS_CLOWN)//They get full station access.
|
||||
W.assignment = "HONKsquad"
|
||||
W.registered_name = real_name
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Syndicate Infiltration Team (SIT)
|
||||
// A little like Syndicate Strike Team (SST) but geared towards stealthy team missions rather than murderbone.
|
||||
|
||||
var/global/sent_syndicate_infiltration_team = 0
|
||||
GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
|
||||
|
||||
/client/proc/syndicate_infiltration_team()
|
||||
set category = "Event"
|
||||
@@ -35,7 +35,7 @@ var/global/sent_syndicate_infiltration_team = 0
|
||||
var/tctext = input(src, "How much TC do you want to give each team member? Suggested: 20-30. They cannot trade TC.") as num
|
||||
var/tcamount = text2num(tctext)
|
||||
tcamount = between(0, tcamount, 1000)
|
||||
if(sent_syndicate_infiltration_team == 1)
|
||||
if(GLOB.sent_syndicate_infiltration_team == 1)
|
||||
if(alert("A Syndicate Infiltration Team has already been sent. Sure you want to send another?",,"Yes","No")=="No")
|
||||
return
|
||||
|
||||
@@ -61,7 +61,7 @@ var/global/sent_syndicate_infiltration_team = 0
|
||||
to_chat(src, "Nobody volunteered.")
|
||||
return 0
|
||||
|
||||
sent_syndicate_infiltration_team = 1
|
||||
GLOB.sent_syndicate_infiltration_team = 1
|
||||
|
||||
var/list/sit_spawns = list()
|
||||
var/list/sit_spawns_leader = list()
|
||||
@@ -90,7 +90,7 @@ var/global/sent_syndicate_infiltration_team = 0
|
||||
to_chat(new_syndicate_infiltrator, "<span class='danger'>You are a [!syndicate_leader_selected?"Infiltrator":"<B>Lead Infiltrator</B>"] in the service of the Syndicate. \nYour current mission is: <B>[input]</B></span>")
|
||||
to_chat(new_syndicate_infiltrator, "<span class='notice'>You are equipped with an uplink implant to help you achieve your objectives. ((activate it via button in top left of screen))</span>")
|
||||
new_syndicate_infiltrator.faction += "syndicate"
|
||||
data_core.manifest_inject(new_syndicate_infiltrator)
|
||||
GLOB.data_core.manifest_inject(new_syndicate_infiltrator)
|
||||
if(syndicate_leader_selected)
|
||||
var/obj/effect/landmark/warpto = pick(sit_spawns_leader)
|
||||
new_syndicate_infiltrator.loc = warpto.loc
|
||||
@@ -104,7 +104,7 @@ var/global/sent_syndicate_infiltration_team = 0
|
||||
new_syndicate_infiltrator.mind.store_memory("<B>Mission:</B> [input] ")
|
||||
new_syndicate_infiltrator.mind.store_memory("<B>Team Leader:</B> [team_leader] ")
|
||||
new_syndicate_infiltrator.mind.store_memory("<B>Starting Equipment:</B> <BR>- Syndicate Headset ((.h for your radio))<BR>- Chameleon Jumpsuit ((right click to Change Color))<BR> - Agent ID card ((disguise as another job))<BR> - Uplink Implant ((top left of screen)) <BR> - Dust Implant ((destroys your body on death)) <BR> - Combat Gloves ((insulated, disguised as black gloves)) <BR> - Anything bought with your uplink implant")
|
||||
var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS]
|
||||
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
|
||||
opshud.join_hud(new_syndicate_infiltrator.mind.current)
|
||||
set_antag_hud(new_syndicate_infiltrator.mind.current, "hudoperative")
|
||||
new_syndicate_infiltrator.regenerate_icons()
|
||||
@@ -177,10 +177,10 @@ var/global/sent_syndicate_infiltration_team = 0
|
||||
W.icon_state = "commander"
|
||||
else
|
||||
W.icon_state = "id"
|
||||
W.access = list(access_maint_tunnels,access_external_airlocks)
|
||||
W.access = list(ACCESS_MAINT_TUNNELS,ACCESS_EXTERNAL_AIRLOCKS)
|
||||
W.assignment = "Civilian"
|
||||
W.access += get_access("Civilian")
|
||||
W.access += list(access_medical, access_engine, access_cargo, access_research)
|
||||
W.access += list(ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CARGO, ACCESS_RESEARCH)
|
||||
if(flag_mgmt)
|
||||
W.assignment = "Syndicate Management Consultant"
|
||||
W.access += get_syndicate_access("Syndicate Commando")
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
GLOBAL_LIST_INIT(open_logging_views, list())
|
||||
|
||||
/client/proc/cmd_admin_open_logging_view()
|
||||
set category = "Admin"
|
||||
set name = "Open Logging View"
|
||||
set desc = "Opens the detailed logging viewer"
|
||||
|
||||
if(!GLOB.open_logging_views[usr.client.ckey])
|
||||
GLOB.open_logging_views[usr.client.ckey] = new /datum/log_viewer()
|
||||
var/datum/log_viewer/LV = GLOB.open_logging_views[usr.client.ckey]
|
||||
LV.show_ui(usr)
|
||||
@@ -6,10 +6,10 @@
|
||||
return
|
||||
var/datum/map_template/template
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in map_templates
|
||||
var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in GLOB.map_templates
|
||||
if(!map)
|
||||
return
|
||||
template = map_templates[map]
|
||||
template = GLOB.map_templates[map]
|
||||
|
||||
var/turf/T = get_turf(mob)
|
||||
if(!T)
|
||||
@@ -48,7 +48,7 @@
|
||||
var/datum/map_template/M = new(map=map, rename="[map]")
|
||||
if(M.preload_size(map))
|
||||
to_chat(usr, "Map template '[map]' ready to place ([M.width]x[M.height])")
|
||||
map_templates[M.name] = M
|
||||
GLOB.map_templates[M.name] = M
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has uploaded a map template ([map]). Took [stop_watch(timer)]s.</span>")
|
||||
else
|
||||
to_chat(usr, "Map template '[map]' failed to load properly")
|
||||
|
||||
+185
-185
@@ -1,185 +1,185 @@
|
||||
//- Are all the floors with or without air, as they should be? (regular or airless)
|
||||
//- Does the area have an APC?
|
||||
//- Does the area have an Air Alarm?
|
||||
//- Does the area have a Request Console?
|
||||
//- Does the area have lights?
|
||||
//- Does the area have a light switch?
|
||||
//- Does the area have enough intercoms?
|
||||
//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug)
|
||||
//- Is the area connected to the scrubbers air loop?
|
||||
//- Is the area connected to the vent air loop? (vent pumps)
|
||||
//- Is everything wired properly?
|
||||
//- Does the area have a fire alarm and firedoors?
|
||||
//- Do all pod doors work properly?
|
||||
//- Are accesses set properly on doors, pod buttons, etc.
|
||||
//- Are all items placed properly? (not below vents, scrubbers, tables)
|
||||
//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room?
|
||||
//- Check for any misplaced or stacked piece of pipe (air and disposal)
|
||||
//- Check for any misplaced or stacked piece of wire
|
||||
//- Identify how hard it is to break into the area and where the weak points are
|
||||
//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
|
||||
|
||||
var/camera_range_display_status = 0
|
||||
var/intercom_range_display_status = 0
|
||||
|
||||
/obj/effect/debugging/camera_range
|
||||
icon = 'icons/480x480.dmi'
|
||||
icon_state = "25percent"
|
||||
|
||||
New()
|
||||
src.pixel_x = -224
|
||||
src.pixel_y = -224
|
||||
|
||||
/obj/effect/debugging/mapfix_marker
|
||||
name = "map fix marker"
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "mapfixmarker"
|
||||
desc = "I am a mappers mistake."
|
||||
|
||||
/obj/effect/debugging/marker
|
||||
icon = 'icons/turf/areas.dmi'
|
||||
icon_state = "yellow"
|
||||
|
||||
/obj/effect/debugging/marker/Move()
|
||||
return 0
|
||||
|
||||
/client/proc/camera_view()
|
||||
set category = "Mapping"
|
||||
set name = "Camera Range Display"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
if(camera_range_display_status)
|
||||
camera_range_display_status = 0
|
||||
else
|
||||
camera_range_display_status = 1
|
||||
|
||||
for(var/obj/effect/debugging/camera_range/C in world)
|
||||
qdel(C)
|
||||
|
||||
if(camera_range_display_status)
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
new/obj/effect/debugging/camera_range(C.loc)
|
||||
feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/sec_camera_report()
|
||||
set category = "Mapping"
|
||||
set name = "Camera Report"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/list/obj/machinery/camera/CL = list()
|
||||
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
CL += C
|
||||
|
||||
var/output = {"<B>CAMERA ANOMALIES REPORT</B><HR>
|
||||
<B>The following anomalies have been detected. The ones in red need immediate attention: Some of those in black may be intentional.</B><BR><ul>"}
|
||||
|
||||
for(var/obj/machinery/camera/C1 in CL)
|
||||
for(var/obj/machinery/camera/C2 in CL)
|
||||
if(C1 != C2)
|
||||
if(C1.c_tag == C2.c_tag)
|
||||
output += "<li><font color='red'>c_tag match for sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) and \[[C2.x], [C2.y], [C2.z]\] ([C2.loc.loc]) - c_tag is [C1.c_tag]</font></li>"
|
||||
if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
|
||||
output += "<li><font color='red'>FULLY overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
|
||||
if(C1.loc == C2.loc)
|
||||
output += "<li>overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
|
||||
var/turf/T = get_step(C1,turn(C1.dir,180))
|
||||
if(!T || !isturf(T) || !T.density )
|
||||
if(!(locate(/obj/structure/grille,T)))
|
||||
var/window_check = 0
|
||||
for(var/obj/structure/window/W in T)
|
||||
if(W.dir == turn(C1.dir,180) || W.fulltile)
|
||||
window_check = 1
|
||||
break
|
||||
if(!window_check)
|
||||
output += "<li><font color='red'>Camera not connected to wall at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Network: [C1.network]</color></li>"
|
||||
|
||||
output += "</ul>"
|
||||
usr << browse(output,"window=airreport;size=1000x500")
|
||||
feedback_add_details("admin_verb","mCRP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/intercom_view()
|
||||
set category = "Mapping"
|
||||
set name = "Intercom Range Display"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
if(intercom_range_display_status)
|
||||
intercom_range_display_status = 0
|
||||
else
|
||||
intercom_range_display_status = 1
|
||||
|
||||
for(var/obj/effect/debugging/marker/M in world)
|
||||
qdel(M)
|
||||
|
||||
if(intercom_range_display_status)
|
||||
for(var/obj/item/radio/intercom/I in world)
|
||||
for(var/turf/T in orange(7,I))
|
||||
var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
|
||||
if(!(F in view(7,I.loc)))
|
||||
qdel(F)
|
||||
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/count_objects_on_z_level()
|
||||
set category = "Mapping"
|
||||
set name = "Count Objects On Level"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/level = clean_input("Which z-level?","Level?")
|
||||
if(!level) return
|
||||
var/num_level = text2num(level)
|
||||
if(!num_level) return
|
||||
if(!isnum(num_level)) return
|
||||
|
||||
var/type_text = clean_input("Which type path?","Path?")
|
||||
if(!type_text) return
|
||||
var/type_path = text2path(type_text)
|
||||
if(!type_path) return
|
||||
|
||||
var/count = 0
|
||||
|
||||
var/list/atom/atom_list = list()
|
||||
|
||||
for(var/atom/A in world)
|
||||
if(istype(A,type_path))
|
||||
var/atom/B = A
|
||||
while(!(isturf(B.loc)))
|
||||
if(B && B.loc)
|
||||
B = B.loc
|
||||
else
|
||||
break
|
||||
if(B)
|
||||
if(B.z == num_level)
|
||||
count++
|
||||
atom_list += A
|
||||
|
||||
to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level].")
|
||||
feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/count_objects_all()
|
||||
set category = "Mapping"
|
||||
set name = "Count Objects All"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/type_text = clean_input("Which type path?","")
|
||||
if(!type_text) return
|
||||
var/type_path = text2path(type_text)
|
||||
if(!type_path) return
|
||||
|
||||
var/count = 0
|
||||
|
||||
for(var/atom/A in world)
|
||||
if(istype(A,type_path))
|
||||
count++
|
||||
|
||||
to_chat(world, "There are [count] objects of type [type_path] in the game world.")
|
||||
feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
//- Are all the floors with or without air, as they should be? (regular or airless)
|
||||
//- Does the area have an APC?
|
||||
//- Does the area have an Air Alarm?
|
||||
//- Does the area have a Request Console?
|
||||
//- Does the area have lights?
|
||||
//- Does the area have a light switch?
|
||||
//- Does the area have enough intercoms?
|
||||
//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug)
|
||||
//- Is the area connected to the scrubbers air loop?
|
||||
//- Is the area connected to the vent air loop? (vent pumps)
|
||||
//- Is everything wired properly?
|
||||
//- Does the area have a fire alarm and firedoors?
|
||||
//- Do all pod doors work properly?
|
||||
//- Are accesses set properly on doors, pod buttons, etc.
|
||||
//- Are all items placed properly? (not below vents, scrubbers, tables)
|
||||
//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room?
|
||||
//- Check for any misplaced or stacked piece of pipe (air and disposal)
|
||||
//- Check for any misplaced or stacked piece of wire
|
||||
//- Identify how hard it is to break into the area and where the weak points are
|
||||
//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
|
||||
|
||||
GLOBAL_VAR_INIT(camera_range_display_status, 0)
|
||||
GLOBAL_VAR_INIT(intercom_range_display_status, 0)
|
||||
|
||||
/obj/effect/debugging/camera_range
|
||||
icon = 'icons/480x480.dmi'
|
||||
icon_state = "25percent"
|
||||
|
||||
New()
|
||||
src.pixel_x = -224
|
||||
src.pixel_y = -224
|
||||
|
||||
/obj/effect/debugging/mapfix_marker
|
||||
name = "map fix marker"
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "mapfixmarker"
|
||||
desc = "I am a mappers mistake."
|
||||
|
||||
/obj/effect/debugging/marker
|
||||
icon = 'icons/turf/areas.dmi'
|
||||
icon_state = "yellow"
|
||||
|
||||
/obj/effect/debugging/marker/Move()
|
||||
return 0
|
||||
|
||||
/client/proc/camera_view()
|
||||
set category = "Mapping"
|
||||
set name = "Camera Range Display"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
if(GLOB.camera_range_display_status)
|
||||
GLOB.camera_range_display_status = 0
|
||||
else
|
||||
GLOB.camera_range_display_status = 1
|
||||
|
||||
for(var/obj/effect/debugging/camera_range/C in world)
|
||||
qdel(C)
|
||||
|
||||
if(GLOB.camera_range_display_status)
|
||||
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
new/obj/effect/debugging/camera_range(C.loc)
|
||||
feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/sec_camera_report()
|
||||
set category = "Mapping"
|
||||
set name = "Camera Report"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/list/obj/machinery/camera/CL = list()
|
||||
|
||||
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
CL += C
|
||||
|
||||
var/output = {"<B>CAMERA ANOMALIES REPORT</B><HR>
|
||||
<B>The following anomalies have been detected. The ones in red need immediate attention: Some of those in black may be intentional.</B><BR><ul>"}
|
||||
|
||||
for(var/obj/machinery/camera/C1 in CL)
|
||||
for(var/obj/machinery/camera/C2 in CL)
|
||||
if(C1 != C2)
|
||||
if(C1.c_tag == C2.c_tag)
|
||||
output += "<li><font color='red'>c_tag match for sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) and \[[C2.x], [C2.y], [C2.z]\] ([C2.loc.loc]) - c_tag is [C1.c_tag]</font></li>"
|
||||
if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
|
||||
output += "<li><font color='red'>FULLY overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
|
||||
if(C1.loc == C2.loc)
|
||||
output += "<li>overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
|
||||
var/turf/T = get_step(C1,turn(C1.dir,180))
|
||||
if(!T || !isturf(T) || !T.density )
|
||||
if(!(locate(/obj/structure/grille,T)))
|
||||
var/window_check = 0
|
||||
for(var/obj/structure/window/W in T)
|
||||
if(W.dir == turn(C1.dir,180) || W.fulltile)
|
||||
window_check = 1
|
||||
break
|
||||
if(!window_check)
|
||||
output += "<li><font color='red'>Camera not connected to wall at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Network: [C1.network]</color></li>"
|
||||
|
||||
output += "</ul>"
|
||||
usr << browse(output,"window=airreport;size=1000x500")
|
||||
feedback_add_details("admin_verb","mCRP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/intercom_view()
|
||||
set category = "Mapping"
|
||||
set name = "Intercom Range Display"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
if(GLOB.intercom_range_display_status)
|
||||
GLOB.intercom_range_display_status = 0
|
||||
else
|
||||
GLOB.intercom_range_display_status = 1
|
||||
|
||||
for(var/obj/effect/debugging/marker/M in world)
|
||||
qdel(M)
|
||||
|
||||
if(GLOB.intercom_range_display_status)
|
||||
for(var/obj/item/radio/intercom/I in world)
|
||||
for(var/turf/T in orange(7,I))
|
||||
var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
|
||||
if(!(F in view(7,I.loc)))
|
||||
qdel(F)
|
||||
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/count_objects_on_z_level()
|
||||
set category = "Mapping"
|
||||
set name = "Count Objects On Level"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/level = clean_input("Which z-level?","Level?")
|
||||
if(!level) return
|
||||
var/num_level = text2num(level)
|
||||
if(!num_level) return
|
||||
if(!isnum(num_level)) return
|
||||
|
||||
var/type_text = clean_input("Which type path?","Path?")
|
||||
if(!type_text) return
|
||||
var/type_path = text2path(type_text)
|
||||
if(!type_path) return
|
||||
|
||||
var/count = 0
|
||||
|
||||
var/list/atom/atom_list = list()
|
||||
|
||||
for(var/atom/A in world)
|
||||
if(istype(A,type_path))
|
||||
var/atom/B = A
|
||||
while(!(isturf(B.loc)))
|
||||
if(B && B.loc)
|
||||
B = B.loc
|
||||
else
|
||||
break
|
||||
if(B)
|
||||
if(B.z == num_level)
|
||||
count++
|
||||
atom_list += A
|
||||
|
||||
to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level].")
|
||||
feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/count_objects_all()
|
||||
set category = "Mapping"
|
||||
set name = "Count Objects All"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/type_text = clean_input("Which type path?","")
|
||||
if(!type_text) return
|
||||
var/type_path = text2path(type_text)
|
||||
if(!type_path) return
|
||||
|
||||
var/count = 0
|
||||
|
||||
for(var/atom/A in world)
|
||||
if(istype(A,type_path))
|
||||
count++
|
||||
|
||||
to_chat(world, "There are [count] objects of type [type_path] in the game world.")
|
||||
feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -1,272 +1,272 @@
|
||||
/client/proc/cmd_mass_modify_object_variables(atom/A, var/var_name)
|
||||
set category = "Debug"
|
||||
set name = "Mass Edit Variables"
|
||||
set desc="(target) Edit all instances of a target item's variables"
|
||||
|
||||
var/method = 0 //0 means strict type detection while 1 means this type and all subtypes (IE: /obj/item with this set to 1 will set it to ALL itms)
|
||||
|
||||
if(!check_rights(R_VAREDIT)) return
|
||||
|
||||
if(A && A.type)
|
||||
if(typesof(A.type))
|
||||
switch(input("Strict object type detection?") as null|anything in list("Strictly this type","This type and subtypes", "Cancel"))
|
||||
if("Strictly this type")
|
||||
method = 0
|
||||
if("This type and subtypes")
|
||||
method = 1
|
||||
if("Cancel")
|
||||
return
|
||||
if(null)
|
||||
return
|
||||
|
||||
src.massmodify_variables(A, var_name, method)
|
||||
feedback_add_details("admin_verb","MEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/massmodify_variables(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 VVckey_edit)
|
||||
to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.")
|
||||
return
|
||||
if(variable in VVlocked)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
if(variable in VVicon_edit_lock)
|
||||
if(!check_rights(R_EVENT | R_DEBUG))
|
||||
return
|
||||
if(variable in 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/cmd_mass_modify_object_variables(atom/A, var/var_name)
|
||||
set category = "Debug"
|
||||
set name = "Mass Edit Variables"
|
||||
set desc="(target) Edit all instances of a target item's variables"
|
||||
|
||||
var/method = 0 //0 means strict type detection while 1 means this type and all subtypes (IE: /obj/item with this set to 1 will set it to ALL itms)
|
||||
|
||||
if(!check_rights(R_VAREDIT)) return
|
||||
|
||||
if(A && A.type)
|
||||
if(typesof(A.type))
|
||||
switch(input("Strict object type detection?") as null|anything in list("Strictly this type","This type and subtypes", "Cancel"))
|
||||
if("Strictly this type")
|
||||
method = 0
|
||||
if("This type and subtypes")
|
||||
method = 1
|
||||
if("Cancel")
|
||||
return
|
||||
if(null)
|
||||
return
|
||||
|
||||
src.massmodify_variables(A, var_name, method)
|
||||
feedback_add_details("admin_verb","MEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/massmodify_variables(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_EVENT | 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
File diff suppressed because it is too large
Load Diff
+104
-104
@@ -1,104 +1,104 @@
|
||||
/client/proc/only_one()
|
||||
if(!SSticker)
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
|
||||
var/list/incompatible_species = list(/datum/species/plasmaman, /datum/species/vox)
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(H.stat == DEAD || !(H.client))
|
||||
continue
|
||||
if(is_special_character(H))
|
||||
continue
|
||||
if(is_type_in_list(H.dna.species, incompatible_species))
|
||||
H.set_species(/datum/species/human)
|
||||
var/datum/preferences/A = new() // Randomize appearance
|
||||
A.copy_to(H)
|
||||
|
||||
SSticker.mode.traitors += H.mind
|
||||
H.mind.special_role = SPECIAL_ROLE_TRAITOR
|
||||
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.owner = H.mind
|
||||
H.mind.objectives += hijack_objective
|
||||
|
||||
to_chat(H, "<B>You are a Highlander. Kill all other Highlanders. There can be only one.</B>")
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
to_chat(H, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
|
||||
obj_count++
|
||||
|
||||
for(var/obj/item/I in H)
|
||||
if(istype(I, /obj/item/implant))
|
||||
continue
|
||||
if(istype(I, /obj/item/organ))
|
||||
continue
|
||||
qdel(I)
|
||||
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(H), slot_w_uniform)
|
||||
H.equip_to_slot_or_del(new /obj/item/radio/headset/heads/captain(H), slot_l_ear)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
|
||||
H.equip_to_slot_or_del(new /obj/item/claymore/highlander(H), slot_r_hand)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/pinpointer(H.loc), slot_l_store)
|
||||
|
||||
var/obj/item/card/id/W = new(H)
|
||||
W.name = "[H.real_name]'s ID Card"
|
||||
W.icon_state = "centcom"
|
||||
W.access = get_all_accesses()
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Highlander"
|
||||
W.registered_name = H.real_name
|
||||
H.equip_to_slot_or_del(W, slot_wear_id)
|
||||
H.dna.species.after_equip_job(null, H)
|
||||
H.regenerate_icons()
|
||||
|
||||
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
|
||||
log_admin("[key_name(usr)] used there can be only one.")
|
||||
nologevent = 1
|
||||
world << sound('sound/music/thunderdome.ogg')
|
||||
|
||||
/client/proc/only_me()
|
||||
if(!SSticker)
|
||||
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>")
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
to_chat(H, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
|
||||
obj_count++
|
||||
|
||||
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_by_slot(slot_r_hand)
|
||||
H.unEquip(slot_item_hand)
|
||||
|
||||
var /obj/item/multisword/pure_evil/multi = new(H)
|
||||
H.equip_to_slot_or_del(multi, slot_r_hand)
|
||||
|
||||
var/obj/item/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)
|
||||
|
||||
H.update_icons()
|
||||
|
||||
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ME! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
|
||||
log_admin("[key_name(usr)] used there can be only me.")
|
||||
nologevent = 1
|
||||
world << sound('sound/music/thunderdome.ogg')
|
||||
/client/proc/only_one()
|
||||
if(!SSticker)
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
|
||||
var/list/incompatible_species = list(/datum/species/plasmaman, /datum/species/vox)
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(H.stat == DEAD || !(H.client))
|
||||
continue
|
||||
if(is_special_character(H))
|
||||
continue
|
||||
if(is_type_in_list(H.dna.species, incompatible_species))
|
||||
H.set_species(/datum/species/human)
|
||||
var/datum/preferences/A = new() // Randomize appearance
|
||||
A.copy_to(H)
|
||||
|
||||
SSticker.mode.traitors += H.mind
|
||||
H.mind.special_role = SPECIAL_ROLE_TRAITOR
|
||||
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.owner = H.mind
|
||||
H.mind.objectives += hijack_objective
|
||||
|
||||
to_chat(H, "<B>You are a Highlander. Kill all other Highlanders. There can be only one.</B>")
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
to_chat(H, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
|
||||
obj_count++
|
||||
|
||||
for(var/obj/item/I in H)
|
||||
if(istype(I, /obj/item/implant))
|
||||
continue
|
||||
if(istype(I, /obj/item/organ))
|
||||
continue
|
||||
qdel(I)
|
||||
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(H), slot_w_uniform)
|
||||
H.equip_to_slot_or_del(new /obj/item/radio/headset/heads/captain(H), slot_l_ear)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
|
||||
H.equip_to_slot_or_del(new /obj/item/claymore/highlander(H), slot_r_hand)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/pinpointer(H.loc), slot_l_store)
|
||||
|
||||
var/obj/item/card/id/W = new(H)
|
||||
W.name = "[H.real_name]'s ID Card"
|
||||
W.icon_state = "centcom"
|
||||
W.access = get_all_accesses()
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Highlander"
|
||||
W.registered_name = H.real_name
|
||||
H.equip_to_slot_or_del(W, slot_wear_id)
|
||||
H.dna.species.after_equip_job(null, H)
|
||||
H.regenerate_icons()
|
||||
|
||||
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
|
||||
log_admin("[key_name(usr)] used there can be only one.")
|
||||
GLOB.nologevent = 1
|
||||
world << sound('sound/music/thunderdome.ogg')
|
||||
|
||||
/client/proc/only_me()
|
||||
if(!SSticker)
|
||||
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>")
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
to_chat(H, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
|
||||
obj_count++
|
||||
|
||||
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_by_slot(slot_r_hand)
|
||||
H.unEquip(slot_item_hand)
|
||||
|
||||
var /obj/item/multisword/pure_evil/multi = new(H)
|
||||
H.equip_to_slot_or_del(multi, slot_r_hand)
|
||||
|
||||
var/obj/item/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)
|
||||
|
||||
H.update_icons()
|
||||
|
||||
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ME! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
|
||||
log_admin("[key_name(usr)] used there can be only me.")
|
||||
GLOB.nologevent = 1
|
||||
world << sound('sound/music/thunderdome.ogg')
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes)
|
||||
|
||||
if(!team_toggle)
|
||||
team_alpha += H
|
||||
GLOB.team_alpha += H
|
||||
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/color/red/dodgeball(H), slot_w_uniform)
|
||||
var/obj/item/card/id/W = new(H)
|
||||
@@ -42,7 +42,7 @@
|
||||
H.equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
else
|
||||
team_bravo += H
|
||||
GLOB.team_bravo += H
|
||||
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/color/blue/dodgeball(H), slot_w_uniform)
|
||||
var/obj/item/card/id/W = new(H)
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
message_admins("[key_name_admin(usr)] used DODGEBAWWWWWWWL! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
|
||||
log_admin("[key_name(usr)] used dodgeball.")
|
||||
nologevent = 1
|
||||
GLOB.nologevent = 1
|
||||
|
||||
/obj/item/beach_ball/dodgeball
|
||||
name = "dodgeball"
|
||||
@@ -76,13 +76,13 @@
|
||||
if(H.r_hand == src) return
|
||||
if(H.l_hand == src) return
|
||||
var/mob/A = H.LAssailant
|
||||
if((H in team_alpha) && (A in team_alpha))
|
||||
if((H in GLOB.team_alpha) && (A in GLOB.team_alpha))
|
||||
to_chat(A, "<span class='warning'>He's on your team!</span>")
|
||||
return
|
||||
else if((H in team_bravo) && (A in team_bravo))
|
||||
else if((H in GLOB.team_bravo) && (A in GLOB.team_bravo))
|
||||
to_chat(A, "<span class='warning'>He's on your team!</span>")
|
||||
return
|
||||
else if(!A in team_alpha && !A in team_bravo)
|
||||
else if(!(A in GLOB.team_alpha) && !(A in GLOB.team_bravo))
|
||||
to_chat(A, "<span class='warning'>You're not part of the dodgeball game, sorry!</span>")
|
||||
return
|
||||
else
|
||||
|
||||
@@ -1,153 +1,153 @@
|
||||
var/list/sounds_cache = list()
|
||||
|
||||
/client/proc/stop_global_admin_sounds()
|
||||
set category = "Event"
|
||||
set name = "Stop Global Admin Sounds"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
var/sound/awful_sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN)
|
||||
|
||||
log_admin("[key_name(src)] stopped admin sounds.")
|
||||
message_admins("[key_name_admin(src)] stopped admin sounds.", 1)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M << awful_sound
|
||||
|
||||
/client/proc/play_sound(S as sound)
|
||||
set category = "Event"
|
||||
set name = "Play Global Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = CHANNEL_ADMIN)
|
||||
uploaded_sound.priority = 250
|
||||
|
||||
sounds_cache += S
|
||||
|
||||
if(alert("Are you sure?\nSong: [S]\nNow you can also play this sound using \"Play Server Sound\".", "Confirmation request" ,"Play", "Cancel") == "Cancel")
|
||||
return
|
||||
|
||||
log_admin("[key_name(src)] played sound [S]")
|
||||
message_admins("[key_name_admin(src)] played sound [S]", 1)
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client.prefs.sound & SOUND_MIDI)
|
||||
if(isnewplayer(M) && (M.client.prefs.sound & SOUND_LOBBY))
|
||||
M.stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
||||
SEND_SOUND(M, uploaded_sound)
|
||||
|
||||
feedback_add_details("admin_verb","PGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/client/proc/play_local_sound(S as sound)
|
||||
set category = "Event"
|
||||
set name = "Play Local Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
log_admin("[key_name(src)] played a local sound [S]")
|
||||
message_admins("[key_name_admin(src)] played a local sound [S]", 1)
|
||||
playsound(get_turf(src.mob), S, 50, 0, 0)
|
||||
feedback_add_details("admin_verb","PLS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/play_server_sound()
|
||||
set category = "Event"
|
||||
set name = "Play Server Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/list/sounds = file2list("sound/serversound_list.txt");
|
||||
sounds += sounds_cache
|
||||
|
||||
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
|
||||
if(!melody) return
|
||||
|
||||
play_sound(melody)
|
||||
feedback_add_details("admin_verb","PSS") //If you are copy-pasting this, ensure the 2nd paramter is unique to the new proc!
|
||||
|
||||
/client/proc/play_intercomm_sound()
|
||||
set category = "Event"
|
||||
set name = "Play Sound via Intercomms"
|
||||
set desc = "Plays a sound at every intercomm on the station z level. Works best with small sounds."
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/A = alert("This will play a sound at every intercomm, are you sure you want to continue? This works best with short sounds, beware.","Warning","Yep","Nope")
|
||||
if(A != "Yep") return
|
||||
|
||||
var/list/sounds = file2list("sound/serversound_list.txt");
|
||||
sounds += sounds_cache
|
||||
|
||||
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
|
||||
if(!melody) return
|
||||
|
||||
var/cvol = 35
|
||||
var/inputvol = input("How loud would you like this to be? (1-70)", "Volume", "35") as num | null
|
||||
if(!inputvol) return
|
||||
if(inputvol && inputvol >= 1 && inputvol <= 70)
|
||||
cvol = inputvol
|
||||
|
||||
//Allows for override to utilize intercomms on all z-levels
|
||||
var/B = alert("Do you want to play through intercomms on ALL Z-levels, or just the station?", "Override", "All", "Station")
|
||||
var/ignore_z = 0
|
||||
if(B == "All")
|
||||
ignore_z = 1
|
||||
|
||||
//Allows for override to utilize incomplete and unpowered intercomms
|
||||
var/C = alert("Do you want to play through unpowered / incomplete intercomms, so the crew can't silence it?", "Override", "Yep", "Nope")
|
||||
var/ignore_power = 0
|
||||
if(C == "Yep")
|
||||
ignore_power = 1
|
||||
|
||||
for(var/O in GLOB.global_intercoms)
|
||||
var/obj/item/radio/intercom/I = O
|
||||
if(!is_station_level(I.z) && !ignore_z)
|
||||
continue
|
||||
if(!I.on && !ignore_power)
|
||||
continue
|
||||
playsound(I, melody, cvol)
|
||||
|
||||
/*
|
||||
/client/proc/cuban_pete()
|
||||
set category = "Event"
|
||||
set name = "Cuban Pete Time"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has declared Cuban Pete Time!", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'cubanpetetime.ogg'
|
||||
|
||||
for(var/mob/living/carbon/human/CP in world)
|
||||
if(CP.real_name=="Cuban Pete" && CP.key!="Rosham")
|
||||
C << "Your body can't contain the rhumba beat"
|
||||
CP.gib()
|
||||
|
||||
|
||||
/client/proc/bananaphone()
|
||||
set category = "Event"
|
||||
set name = "Banana Phone"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has activated Banana Phone!", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'bananaphone.ogg'
|
||||
|
||||
|
||||
client/proc/space_asshole()
|
||||
set category = "Event"
|
||||
set name = "Space Asshole"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has played the Space Asshole Hymn.", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'sound/music/space_asshole.ogg'
|
||||
|
||||
|
||||
client/proc/honk_theme()
|
||||
set category = "Event"
|
||||
set name = "Honk"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has creeped everyone out with Blackest Honks.", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'honk_theme.ogg'*/
|
||||
GLOBAL_LIST_EMPTY(sounds_cache)
|
||||
|
||||
/client/proc/stop_global_admin_sounds()
|
||||
set category = "Event"
|
||||
set name = "Stop Global Admin Sounds"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
var/sound/awful_sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN)
|
||||
|
||||
log_admin("[key_name(src)] stopped admin sounds.")
|
||||
message_admins("[key_name_admin(src)] stopped admin sounds.", 1)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M << awful_sound
|
||||
|
||||
/client/proc/play_sound(S as sound)
|
||||
set category = "Event"
|
||||
set name = "Play Global Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = CHANNEL_ADMIN)
|
||||
uploaded_sound.priority = 250
|
||||
|
||||
GLOB.sounds_cache += S
|
||||
|
||||
if(alert("Are you sure?\nSong: [S]\nNow you can also play this sound using \"Play Server Sound\".", "Confirmation request" ,"Play", "Cancel") == "Cancel")
|
||||
return
|
||||
|
||||
log_admin("[key_name(src)] played sound [S]")
|
||||
message_admins("[key_name_admin(src)] played sound [S]", 1)
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client.prefs.sound & SOUND_MIDI)
|
||||
if(isnewplayer(M) && (M.client.prefs.sound & SOUND_LOBBY))
|
||||
M.stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
||||
SEND_SOUND(M, uploaded_sound)
|
||||
|
||||
feedback_add_details("admin_verb","PGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/client/proc/play_local_sound(S as sound)
|
||||
set category = "Event"
|
||||
set name = "Play Local Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
log_admin("[key_name(src)] played a local sound [S]")
|
||||
message_admins("[key_name_admin(src)] played a local sound [S]", 1)
|
||||
playsound(get_turf(src.mob), S, 50, 0, 0)
|
||||
feedback_add_details("admin_verb","PLS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/play_server_sound()
|
||||
set category = "Event"
|
||||
set name = "Play Server Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/list/sounds = file2list("sound/serversound_list.txt");
|
||||
sounds += GLOB.sounds_cache
|
||||
|
||||
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
|
||||
if(!melody) return
|
||||
|
||||
play_sound(melody)
|
||||
feedback_add_details("admin_verb","PSS") //If you are copy-pasting this, ensure the 2nd paramter is unique to the new proc!
|
||||
|
||||
/client/proc/play_intercomm_sound()
|
||||
set category = "Event"
|
||||
set name = "Play Sound via Intercomms"
|
||||
set desc = "Plays a sound at every intercomm on the station z level. Works best with small sounds."
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/A = alert("This will play a sound at every intercomm, are you sure you want to continue? This works best with short sounds, beware.","Warning","Yep","Nope")
|
||||
if(A != "Yep") return
|
||||
|
||||
var/list/sounds = file2list("sound/serversound_list.txt");
|
||||
sounds += GLOB.sounds_cache
|
||||
|
||||
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
|
||||
if(!melody) return
|
||||
|
||||
var/cvol = 35
|
||||
var/inputvol = input("How loud would you like this to be? (1-70)", "Volume", "35") as num | null
|
||||
if(!inputvol) return
|
||||
if(inputvol && inputvol >= 1 && inputvol <= 70)
|
||||
cvol = inputvol
|
||||
|
||||
//Allows for override to utilize intercomms on all z-levels
|
||||
var/B = alert("Do you want to play through intercomms on ALL Z-levels, or just the station?", "Override", "All", "Station")
|
||||
var/ignore_z = 0
|
||||
if(B == "All")
|
||||
ignore_z = 1
|
||||
|
||||
//Allows for override to utilize incomplete and unpowered intercomms
|
||||
var/C = alert("Do you want to play through unpowered / incomplete intercomms, so the crew can't silence it?", "Override", "Yep", "Nope")
|
||||
var/ignore_power = 0
|
||||
if(C == "Yep")
|
||||
ignore_power = 1
|
||||
|
||||
for(var/O in GLOB.global_intercoms)
|
||||
var/obj/item/radio/intercom/I = O
|
||||
if(!is_station_level(I.z) && !ignore_z)
|
||||
continue
|
||||
if(!I.on && !ignore_power)
|
||||
continue
|
||||
playsound(I, melody, cvol)
|
||||
|
||||
/*
|
||||
/client/proc/cuban_pete()
|
||||
set category = "Event"
|
||||
set name = "Cuban Pete Time"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has declared Cuban Pete Time!", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'cubanpetetime.ogg'
|
||||
|
||||
for(var/mob/living/carbon/human/CP in world)
|
||||
if(CP.real_name=="Cuban Pete" && CP.key!="Rosham")
|
||||
C << "Your body can't contain the rhumba beat"
|
||||
CP.gib()
|
||||
|
||||
|
||||
/client/proc/bananaphone()
|
||||
set category = "Event"
|
||||
set name = "Banana Phone"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has activated Banana Phone!", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'bananaphone.ogg'
|
||||
|
||||
|
||||
client/proc/space_asshole()
|
||||
set category = "Event"
|
||||
set name = "Space Asshole"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has played the Space Asshole Hymn.", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'sound/music/space_asshole.ogg'
|
||||
|
||||
|
||||
client/proc/honk_theme()
|
||||
set category = "Event"
|
||||
set name = "Honk"
|
||||
|
||||
message_admins("[key_name_admin(usr)] has creeped everyone out with Blackest Honks.", 1)
|
||||
for(var/mob/M in world)
|
||||
if(M.client)
|
||||
if(M.client.midis)
|
||||
M << 'honk_theme.ogg'*/
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
/mob/living/verb/pray(msg as text)
|
||||
set category = "IC"
|
||||
set name = "Pray"
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(usr.client)
|
||||
if(usr.client.prefs.muted & MUTE_PRAY)
|
||||
to_chat(usr, "<span class='warning'>You cannot pray (muted).</span>")
|
||||
return
|
||||
if(client.handle_spam_prevention(msg, MUTE_PRAY, OOC_COOLDOWN))
|
||||
return
|
||||
|
||||
var/image/cross = image('icons/obj/storage.dmi',"bible")
|
||||
var/font_color = "purple"
|
||||
var/prayer_type = "PRAYER"
|
||||
var/deity
|
||||
if(usr.job == "Chaplain")
|
||||
if(SSticker && SSticker.Bible_deity_name)
|
||||
deity = SSticker.Bible_deity_name
|
||||
cross = image('icons/obj/storage.dmi',"kingyellow")
|
||||
font_color = "blue"
|
||||
prayer_type = "CHAPLAIN PRAYER"
|
||||
else if(iscultist(usr))
|
||||
cross = image('icons/obj/storage.dmi',"tome")
|
||||
font_color = "red"
|
||||
prayer_type = "CULTIST PRAYER"
|
||||
deity = SSticker.cultdat.entity_name
|
||||
|
||||
log_say("(PRAYER) [msg]", usr)
|
||||
msg = "<span class='notice'>[bicon(cross)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""][mind && mind.isholy ? " (blessings: [mind.num_blessed])" : ""]:</font> [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_TP(src,"TP")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) ([ADMIN_SC(src,"SC")]) (<A HREF='?_src_=holder;Bless=[UID()]'>BLESS</A>) (<A HREF='?_src_=holder;Smite=[UID()]'>SMITE</A>):</b> [msg]</span>"
|
||||
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
to_chat(usr, "Your prayers have been received by the gods.")
|
||||
|
||||
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/Centcomm_announce(var/text , var/mob/Sender)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='boldnotice'><font color=orange>CENTCOMM: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_CENTCOM_REPLY(Sender,"RPLY")])):</span> [msg]"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(R_EVENT & X.holder.rights)
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/Syndicate_announce(var/text , var/mob/Sender)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='boldnotice'><font color='#DC143C'>SYNDICATE: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_SYNDICATE_REPLY(Sender,"RPLY")]):</span> [msg]"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/HONK_announce(var/text , var/mob/Sender)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='boldnotice'><font color=pink>HONK: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) (<A HREF='?_src_=holder;HONKReply=[Sender.UID()]'>RPLY</A>):</span> [msg]"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(R_EVENT & X.holder.rights)
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/ERT_Announce(var/text , var/mob/Sender, var/repeat_warning)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='adminnotice'><b><font color=orange>ERT REQUEST: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) (<A HREF='?_src_=holder;ErtReply=[Sender.UID()]'>RESPOND</A>):</b> [msg]</span>"
|
||||
if(repeat_warning)
|
||||
msg += "<BR><span class='adminnotice'><b>WARNING: ERT request has gone 5 minutes with no reply!</b></span>"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/Nuke_request(text , mob/Sender)
|
||||
var/nuke_code = get_nuke_code()
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST: </font>[key_name(Sender)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_CENTCOM_REPLY(Sender,"RPLY")]):</b> [msg]</span>"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
to_chat(X, "<span class='adminnotice'><b>The nuke code is [nuke_code].</b></span>")
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
/mob/living/verb/pray(msg as text)
|
||||
set category = "IC"
|
||||
set name = "Pray"
|
||||
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(usr.client)
|
||||
if(usr.client.prefs.muted & MUTE_PRAY)
|
||||
to_chat(usr, "<span class='warning'>You cannot pray (muted).</span>")
|
||||
return
|
||||
if(client.handle_spam_prevention(msg, MUTE_PRAY, OOC_COOLDOWN))
|
||||
return
|
||||
|
||||
var/image/cross = image('icons/obj/storage.dmi',"bible")
|
||||
var/font_color = "purple"
|
||||
var/prayer_type = "PRAYER"
|
||||
var/deity
|
||||
if(usr.job == "Chaplain")
|
||||
if(SSticker && SSticker.Bible_deity_name)
|
||||
deity = SSticker.Bible_deity_name
|
||||
cross = image('icons/obj/storage.dmi',"kingyellow")
|
||||
font_color = "blue"
|
||||
prayer_type = "CHAPLAIN PRAYER"
|
||||
else if(iscultist(usr))
|
||||
cross = image('icons/obj/storage.dmi',"tome")
|
||||
font_color = "red"
|
||||
prayer_type = "CULTIST PRAYER"
|
||||
deity = SSticker.cultdat.entity_name
|
||||
|
||||
log_say("(PRAYER) [msg]", usr)
|
||||
msg = "<span class='notice'>[bicon(cross)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""][mind && mind.isholy ? " (blessings: [mind.num_blessed])" : ""]:</font> [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_TP(src,"TP")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) ([ADMIN_SC(src,"SC")]) (<A HREF='?_src_=holder;Bless=[UID()]'>BLESS</A>) (<A HREF='?_src_=holder;Smite=[UID()]'>SMITE</A>):</b> [msg]</span>"
|
||||
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
to_chat(usr, "Your prayers have been received by the gods.")
|
||||
|
||||
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/Centcomm_announce(var/text , var/mob/Sender)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='boldnotice'><font color=orange>CENTCOMM: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_CENTCOM_REPLY(Sender,"RPLY")])):</span> [msg]"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(R_EVENT & X.holder.rights)
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/Syndicate_announce(var/text , var/mob/Sender)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='boldnotice'><font color='#DC143C'>SYNDICATE: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_SYNDICATE_REPLY(Sender,"RPLY")]):</span> [msg]"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/HONK_announce(var/text , var/mob/Sender)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='boldnotice'><font color=pink>HONK: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) (<A HREF='?_src_=holder;HONKReply=[Sender.UID()]'>RPLY</A>):</span> [msg]"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(R_EVENT & X.holder.rights)
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/ERT_Announce(var/text , var/mob/Sender, var/repeat_warning)
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='adminnotice'><b><font color=orange>ERT REQUEST: </font>[key_name(Sender, 1)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) (<A HREF='?_src_=holder;ErtReply=[Sender.UID()]'>RESPOND</A>):</b> [msg]</span>"
|
||||
if(repeat_warning)
|
||||
msg += "<BR><span class='adminnotice'><b>WARNING: ERT request has gone 5 minutes with no reply!</b></span>"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
/proc/Nuke_request(text , mob/Sender)
|
||||
var/nuke_code = get_nuke_code()
|
||||
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
|
||||
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST: </font>[key_name(Sender)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_CENTCOM_REPLY(Sender,"RPLY")]):</b> [msg]</span>"
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
to_chat(X, msg)
|
||||
to_chat(X, "<span class='adminnotice'><b>The nuke code is [nuke_code].</b></span>")
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
+1161
-1159
File diff suppressed because it is too large
Load Diff
@@ -23,4 +23,4 @@
|
||||
|
||||
var/json_text = input("Enter the JSON code:","Text") as message|null
|
||||
if(json_text)
|
||||
json_to_object(json_text, get_turf(usr))
|
||||
json_to_object(json_text, get_turf(usr))
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
message_admins("[key_name_admin(usr)] re-assigned all space transitions")
|
||||
space_manager.do_transition_setup()
|
||||
GLOB.space_manager.do_transition_setup()
|
||||
log_admin("[key_name(usr)] re-assigned all space transitions")
|
||||
|
||||
feedback_add_details("admin_verb","SPCRST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -37,5 +37,5 @@
|
||||
message_admins("[key_name_admin(usr)] made a space map")
|
||||
|
||||
|
||||
space_manager.map_as_turfs(get_turf(usr))
|
||||
GLOB.space_manager.map_as_turfs(get_turf(usr))
|
||||
log_admin("[key_name(usr)] made a space map")
|
||||
|
||||
@@ -1,204 +1,206 @@
|
||||
//STRIKE TEAMS
|
||||
|
||||
var/const/commandos_possible = 6 //if more Commandos are needed in the future
|
||||
var/global/sent_strike_team = 0
|
||||
|
||||
/client/proc/strike_team()
|
||||
if(!SSticker)
|
||||
to_chat(usr, "<span class='userdanger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
if(sent_strike_team == 1)
|
||||
to_chat(usr, "<span class='userdanger'>CentComm is already sending a team.</span>")
|
||||
return
|
||||
if(alert("Do you want to send in the CentComm death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes")
|
||||
return
|
||||
alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned commandos have internals cameras which are viewable through a monitor inside the Spec. Ops. Office. The first one selected/spawned will be the team leader.")
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has started to spawn a CentComm DeathSquad.</span>", 1)
|
||||
|
||||
var/input = null
|
||||
while(!input)
|
||||
input = sanitize(copytext(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN))
|
||||
if(!input)
|
||||
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
|
||||
return
|
||||
|
||||
if(sent_strike_team)
|
||||
to_chat(usr, "Looks like someone beat you to it.")
|
||||
return
|
||||
|
||||
// Find the nuclear auth code
|
||||
var/nuke_code
|
||||
var/temp_code
|
||||
for(var/obj/machinery/nuclearbomb/N in world)
|
||||
temp_code = text2num(N.r_code)
|
||||
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
|
||||
nuke_code = N.r_code
|
||||
break
|
||||
|
||||
// Find ghosts willing to be DS
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, commandos_possible, "Join the DeathSquad?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE)
|
||||
if(!commando_ghosts.len)
|
||||
to_chat(usr, "<span class='userdanger'>Nobody volunteered to join the DeathSquad.</span>")
|
||||
return
|
||||
|
||||
sent_strike_team = 1
|
||||
|
||||
// Spawns commandos and equips them.
|
||||
var/commando_number = commandos_possible //for selecting a leader
|
||||
var/is_leader = TRUE // set to FALSE after leader is spawned
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
|
||||
if(commando_number <= 0)
|
||||
break
|
||||
|
||||
if(L.name == "Commando")
|
||||
|
||||
if(!commando_ghosts.len)
|
||||
break
|
||||
|
||||
var/use_ds_borg = FALSE
|
||||
var/mob/ghost_mob = pick(commando_ghosts)
|
||||
commando_ghosts -= ghost_mob
|
||||
if(!ghost_mob || !ghost_mob.key || !ghost_mob.client)
|
||||
continue
|
||||
|
||||
if(!is_leader)
|
||||
var/new_dstype = alert(ghost_mob.client, "Select Deathsquad Type.", "DS Character Generation", "Organic", "Cyborg")
|
||||
if(new_dstype == "Cyborg")
|
||||
use_ds_borg = TRUE
|
||||
|
||||
if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) // Have to re-check this due to the above alert() call
|
||||
continue
|
||||
|
||||
if(use_ds_borg)
|
||||
var/mob/living/silicon/robot/deathsquad/R = new()
|
||||
R.forceMove(get_turf(L))
|
||||
var/rnum = rand(1,1000)
|
||||
var/borgname = "Epsilon [rnum]"
|
||||
R.name = borgname
|
||||
R.custom_name = borgname
|
||||
R.real_name = R.name
|
||||
R.mind = new
|
||||
R.mind.current = R
|
||||
R.mind.original = R
|
||||
R.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
R.mind.offstation_role = TRUE
|
||||
if(!(R.mind in SSticker.minds))
|
||||
SSticker.minds += R.mind
|
||||
SSticker.mode.traitors += R.mind
|
||||
R.key = ghost_mob.key
|
||||
if(nuke_code)
|
||||
R.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code].</span>")
|
||||
R.mind.store_memory("<B>Mission:</B> <span class='warning'>[input].</span>")
|
||||
to_chat(R, "<span class='userdanger'>You are a Special Operations cyborg, in the service of Central Command. \nYour current mission is: <span class='danger'>[input]</span></span>")
|
||||
else
|
||||
var/mob/living/carbon/human/new_commando = create_death_commando(L, is_leader)
|
||||
new_commando.mind.key = ghost_mob.key
|
||||
new_commando.key = ghost_mob.key
|
||||
new_commando.internal = new_commando.s_store
|
||||
new_commando.update_action_buttons_icon()
|
||||
if(nuke_code)
|
||||
new_commando.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code].</span>")
|
||||
new_commando.mind.store_memory("<B>Mission:</B> <span class='warning'>[input].</span>")
|
||||
to_chat(new_commando, "<span class='userdanger'>You are a Special Ops [is_leader ? "<B>TEAM LEADER</B>" : "commando"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: <span class='danger'>[input]</span></span>")
|
||||
|
||||
is_leader = FALSE
|
||||
commando_number--
|
||||
|
||||
//Spawns the rest of the commando gear.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
if(L.name == "Commando_Manual")
|
||||
//new /obj/item/gun/energy/pulse_rifle(L.loc)
|
||||
var/obj/item/paper/P = new(L.loc)
|
||||
P.info = "<p><b>Good morning soldier!</b>. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:<br>#1 Work as a team.<br>#2 Accomplish your objective at all costs.<br>#3 Leave no witnesses.<br>You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.<br>If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.</p><p>In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations <b>LEADER</b> is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.</p><p>Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.<br>First and foremost, <b>DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.</b> Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.<br>To make the device functional:<br>#1 Place bomb in designated detonation zone<br> #2 Extend and anchor bomb (attack with hand).<br>#3 Insert Nuclear Auth. Disk into slot.<br>#4 Type numeric code into keypad ([nuke_code]).<br>Note: If you make a mistake press R to reset the device.<br>#5 Press the E button to log onto the device.<br>You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.<br>Note: Toggle off the <b>SAFETY</b>.<br>Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.<br>Note: <b>THE BOMB IS STILL SET AND WILL DETONATE</b><br>Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.</p><p>The nuclear authorization code is: <b>[nuke_code ? nuke_code : "None provided"]</b></p><p><b>Good luck, soldier!</b></p>"
|
||||
P.name = "Spec. Ops Manual"
|
||||
P.icon = "pamphlet-ds"
|
||||
var/obj/item/stamp/centcom/stamp = new
|
||||
P.stamp(stamp)
|
||||
qdel(stamp)
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
if(L.name == "Commando-Bomb")
|
||||
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
|
||||
qdel(L)
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has spawned a CentComm DeathSquad.</span>", 1)
|
||||
log_admin("[key_name(usr)] used Spawn Death Squad.")
|
||||
return 1
|
||||
|
||||
/client/proc/create_death_commando(obj/spawn_location, is_leader = FALSE)
|
||||
var/mob/living/carbon/human/new_commando = new(spawn_location.loc)
|
||||
var/commando_leader_rank = pick("Lieutenant", "Captain", "Major")
|
||||
var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
|
||||
var/commando_name = pick(GLOB.last_names)
|
||||
|
||||
var/datum/preferences/A = new()//Randomize appearance for the commando.
|
||||
if(is_leader)
|
||||
A.age = rand(35,45)
|
||||
A.real_name = "[commando_leader_rank] [commando_name]"
|
||||
else
|
||||
A.real_name = "[commando_rank] [commando_name]"
|
||||
A.copy_to(new_commando)
|
||||
|
||||
|
||||
new_commando.dna.ready_dna(new_commando)//Creates DNA.
|
||||
|
||||
//Creates mind stuff.
|
||||
new_commando.mind_initialize()
|
||||
new_commando.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
new_commando.mind.special_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
SSticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list.
|
||||
new_commando.equip_death_commando(is_leader)
|
||||
return new_commando
|
||||
|
||||
/mob/living/carbon/human/proc/equip_death_commando(is_leader = FALSE)
|
||||
|
||||
var/obj/item/radio/R = new /obj/item/radio/headset/alt(src)
|
||||
R.set_frequency(DTH_FREQ)
|
||||
equip_to_slot_or_del(R, slot_l_ear)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/color/green(src), slot_w_uniform)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/advance(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/suit/space/deathsquad(src), slot_wear_suit)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/sechailer/swat(src), slot_wear_mask)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/storage/backpack/security(src), slot_back)
|
||||
equip_to_slot_or_del(new /obj/item/storage/box(src), slot_in_backpack)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/a357(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/reagent_containers/hypospray/combat/nanites(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/storage/box/flashbangs(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/flashlight(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/pinpointer(src), slot_in_backpack)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/disk/nuclear/unrestricted(src), slot_in_backpack)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(src), slot_in_backpack)
|
||||
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/melee/energy/sword/saber(src), slot_l_store)
|
||||
equip_to_slot_or_del(new /obj/item/shield/energy(src), slot_r_store)
|
||||
equip_to_slot_or_del(new /obj/item/tank/emergency_oxygen/double/full(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/revolver/mateba(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/gun/energy/pulse(src), slot_r_hand)
|
||||
|
||||
var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(src)
|
||||
L.implant(src)
|
||||
|
||||
var/obj/item/card/id/W = new(src)
|
||||
W.name = "[real_name]'s ID Card"
|
||||
W.icon_state = "deathsquad"
|
||||
W.assignment = "Death Commando"
|
||||
W.access = get_centcom_access(W.assignment)
|
||||
W.registered_name = real_name
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
return 1
|
||||
//STRIKE TEAMS
|
||||
|
||||
#define COMMANDOS_POSSIBLE 6 //if more Commandos are needed in the future
|
||||
GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
|
||||
/client/proc/strike_team()
|
||||
if(!SSticker)
|
||||
to_chat(usr, "<span class='userdanger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
if(GLOB.sent_strike_team == 1)
|
||||
to_chat(usr, "<span class='userdanger'>CentComm is already sending a team.</span>")
|
||||
return
|
||||
if(alert("Do you want to send in the CentComm death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes")
|
||||
return
|
||||
alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned commandos have internals cameras which are viewable through a monitor inside the Spec. Ops. Office. The first one selected/spawned will be the team leader.")
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has started to spawn a CentComm DeathSquad.</span>", 1)
|
||||
|
||||
var/input = null
|
||||
while(!input)
|
||||
input = sanitize(copytext(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN))
|
||||
if(!input)
|
||||
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
|
||||
return
|
||||
|
||||
if(GLOB.sent_strike_team)
|
||||
to_chat(usr, "Looks like someone beat you to it.")
|
||||
return
|
||||
|
||||
// Find the nuclear auth code
|
||||
var/nuke_code
|
||||
var/temp_code
|
||||
for(var/obj/machinery/nuclearbomb/N in world)
|
||||
temp_code = text2num(N.r_code)
|
||||
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
|
||||
nuke_code = N.r_code
|
||||
break
|
||||
|
||||
// Find ghosts willing to be DS
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, COMMANDOS_POSSIBLE, "Join the DeathSquad?",, 21, 600, 1, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE)
|
||||
if(!commando_ghosts.len)
|
||||
to_chat(usr, "<span class='userdanger'>Nobody volunteered to join the DeathSquad.</span>")
|
||||
return
|
||||
|
||||
GLOB.sent_strike_team = 1
|
||||
|
||||
// Spawns commandos and equips them.
|
||||
var/commando_number = COMMANDOS_POSSIBLE //for selecting a leader
|
||||
var/is_leader = TRUE // set to FALSE after leader is spawned
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
|
||||
if(commando_number <= 0)
|
||||
break
|
||||
|
||||
if(L.name == "Commando")
|
||||
|
||||
if(!commando_ghosts.len)
|
||||
break
|
||||
|
||||
var/use_ds_borg = FALSE
|
||||
var/mob/ghost_mob = pick(commando_ghosts)
|
||||
commando_ghosts -= ghost_mob
|
||||
if(!ghost_mob || !ghost_mob.key || !ghost_mob.client)
|
||||
continue
|
||||
|
||||
if(!is_leader)
|
||||
var/new_dstype = alert(ghost_mob.client, "Select Deathsquad Type.", "DS Character Generation", "Organic", "Cyborg")
|
||||
if(new_dstype == "Cyborg")
|
||||
use_ds_borg = TRUE
|
||||
|
||||
if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) // Have to re-check this due to the above alert() call
|
||||
continue
|
||||
|
||||
if(use_ds_borg)
|
||||
var/mob/living/silicon/robot/deathsquad/R = new()
|
||||
R.forceMove(get_turf(L))
|
||||
var/rnum = rand(1,1000)
|
||||
var/borgname = "Epsilon [rnum]"
|
||||
R.name = borgname
|
||||
R.custom_name = borgname
|
||||
R.real_name = R.name
|
||||
R.mind = new
|
||||
R.mind.current = R
|
||||
R.mind.original = R
|
||||
R.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
R.mind.offstation_role = TRUE
|
||||
if(!(R.mind in SSticker.minds))
|
||||
SSticker.minds += R.mind
|
||||
SSticker.mode.traitors += R.mind
|
||||
R.key = ghost_mob.key
|
||||
if(nuke_code)
|
||||
R.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code].</span>")
|
||||
R.mind.store_memory("<B>Mission:</B> <span class='warning'>[input].</span>")
|
||||
to_chat(R, "<span class='userdanger'>You are a Special Operations cyborg, in the service of Central Command. \nYour current mission is: <span class='danger'>[input]</span></span>")
|
||||
else
|
||||
var/mob/living/carbon/human/new_commando = create_death_commando(L, is_leader)
|
||||
new_commando.mind.key = ghost_mob.key
|
||||
new_commando.key = ghost_mob.key
|
||||
new_commando.internal = new_commando.s_store
|
||||
new_commando.update_action_buttons_icon()
|
||||
if(nuke_code)
|
||||
new_commando.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code].</span>")
|
||||
new_commando.mind.store_memory("<B>Mission:</B> <span class='warning'>[input].</span>")
|
||||
to_chat(new_commando, "<span class='userdanger'>You are a Special Ops [is_leader ? "<B>TEAM LEADER</B>" : "commando"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: <span class='danger'>[input]</span></span>")
|
||||
|
||||
is_leader = FALSE
|
||||
commando_number--
|
||||
|
||||
//Spawns the rest of the commando gear.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
if(L.name == "Commando_Manual")
|
||||
//new /obj/item/gun/energy/pulse_rifle(L.loc)
|
||||
var/obj/item/paper/P = new(L.loc)
|
||||
P.info = "<p><b>Good morning soldier!</b>. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:<br>#1 Work as a team.<br>#2 Accomplish your objective at all costs.<br>#3 Leave no witnesses.<br>You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.<br>If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.</p><p>In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations <b>LEADER</b> is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.</p><p>Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.<br>First and foremost, <b>DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.</b> Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.<br>To make the device functional:<br>#1 Place bomb in designated detonation zone<br> #2 Extend and anchor bomb (attack with hand).<br>#3 Insert Nuclear Auth. Disk into slot.<br>#4 Type numeric code into keypad ([nuke_code]).<br>Note: If you make a mistake press R to reset the device.<br>#5 Press the E button to log onto the device.<br>You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.<br>Note: Toggle off the <b>SAFETY</b>.<br>Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.<br>Note: <b>THE BOMB IS STILL SET AND WILL DETONATE</b><br>Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.</p><p>The nuclear authorization code is: <b>[nuke_code ? nuke_code : "None provided"]</b></p><p><b>Good luck, soldier!</b></p>"
|
||||
P.name = "Spec. Ops Manual"
|
||||
P.icon = "pamphlet-ds"
|
||||
var/obj/item/stamp/centcom/stamp = new
|
||||
P.stamp(stamp)
|
||||
qdel(stamp)
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
if(L.name == "Commando-Bomb")
|
||||
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
|
||||
qdel(L)
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has spawned a CentComm DeathSquad.</span>", 1)
|
||||
log_admin("[key_name(usr)] used Spawn Death Squad.")
|
||||
return 1
|
||||
|
||||
/client/proc/create_death_commando(obj/spawn_location, is_leader = FALSE)
|
||||
var/mob/living/carbon/human/new_commando = new(spawn_location.loc)
|
||||
var/commando_leader_rank = pick("Lieutenant", "Captain", "Major")
|
||||
var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
|
||||
var/commando_name = pick(GLOB.last_names)
|
||||
|
||||
var/datum/preferences/A = new()//Randomize appearance for the commando.
|
||||
if(is_leader)
|
||||
A.age = rand(35,45)
|
||||
A.real_name = "[commando_leader_rank] [commando_name]"
|
||||
else
|
||||
A.real_name = "[commando_rank] [commando_name]"
|
||||
A.copy_to(new_commando)
|
||||
|
||||
|
||||
new_commando.dna.ready_dna(new_commando)//Creates DNA.
|
||||
|
||||
//Creates mind stuff.
|
||||
new_commando.mind_initialize()
|
||||
new_commando.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
new_commando.mind.special_role = SPECIAL_ROLE_DEATHSQUAD
|
||||
SSticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list.
|
||||
new_commando.equip_death_commando(is_leader)
|
||||
return new_commando
|
||||
|
||||
/mob/living/carbon/human/proc/equip_death_commando(is_leader = FALSE)
|
||||
|
||||
var/obj/item/radio/R = new /obj/item/radio/headset/alt(src)
|
||||
R.set_frequency(DTH_FREQ)
|
||||
R.requires_tcomms = FALSE
|
||||
R.instant = TRUE
|
||||
equip_to_slot_or_del(R, slot_l_ear)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/color/green(src), slot_w_uniform)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/advance(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/suit/space/deathsquad(src), slot_wear_suit)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/sechailer/swat(src), slot_wear_mask)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/storage/backpack/security(src), slot_back)
|
||||
equip_to_slot_or_del(new /obj/item/storage/box(src), slot_in_backpack)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/a357(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/reagent_containers/hypospray/combat/nanites(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/storage/box/flashbangs(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/flashlight(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/pinpointer(src), slot_in_backpack)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/disk/nuclear/unrestricted(src), slot_in_backpack)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(src), slot_in_backpack)
|
||||
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/melee/energy/sword/saber(src), slot_l_store)
|
||||
equip_to_slot_or_del(new /obj/item/shield/energy(src), slot_r_store)
|
||||
equip_to_slot_or_del(new /obj/item/tank/emergency_oxygen/double/full(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/revolver/mateba(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/gun/energy/pulse(src), slot_r_hand)
|
||||
|
||||
var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(src)
|
||||
L.implant(src)
|
||||
|
||||
var/obj/item/card/id/W = new(src)
|
||||
W.name = "[real_name]'s ID Card"
|
||||
W.icon_state = "deathsquad"
|
||||
W.assignment = "Death Commando"
|
||||
W.access = get_centcom_access(W.assignment)
|
||||
W.registered_name = real_name
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -1,169 +1,169 @@
|
||||
//STRIKE TEAMS
|
||||
|
||||
var/const/syndicate_commandos_possible = 6 //if more Commandos are needed in the future
|
||||
var/global/sent_syndicate_strike_team = 0
|
||||
/client/proc/syndicate_strike_team()
|
||||
set category = "Event"
|
||||
set name = "Spawn Syndicate Strike Team"
|
||||
set desc = "Spawns a squad of commandos in the Syndicate Mothership if you want to run an admin event."
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
if(!SSticker)
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
if(sent_syndicate_strike_team == 1)
|
||||
alert("The Syndicate are already sending a team, Mr. Dumbass.")
|
||||
return
|
||||
if(alert("Do you want to send in the Syndicate Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No")
|
||||
return
|
||||
alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned syndicates have internals cameras which are viewable through a monitor inside the Syndicate Mothership Bridge. Assigning the team's detailed task is recommended from there. The first one selected/spawned will be the team leader.")
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has started to spawn a Syndicate Strike Team.</span>", 1)
|
||||
|
||||
var/input = null
|
||||
while(!input)
|
||||
input = sanitize(copytext(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN))
|
||||
if(!input)
|
||||
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
|
||||
return
|
||||
|
||||
if(sent_syndicate_strike_team)
|
||||
to_chat(src, "Looks like someone beat you to it.")
|
||||
return
|
||||
|
||||
var/syndicate_commando_number = syndicate_commandos_possible //for selecting a leader
|
||||
var/is_leader = TRUE // set to FALSE after leader is spawned
|
||||
|
||||
// Find the nuclear auth code
|
||||
var/nuke_code
|
||||
var/temp_code
|
||||
for(var/obj/machinery/nuclearbomb/N in world)
|
||||
temp_code = text2num(N.r_code)
|
||||
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
|
||||
nuke_code = N.r_code
|
||||
break
|
||||
|
||||
// Find ghosts willing to be SST
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, syndicate_commandos_possible, "Join the Syndicate Strike Team?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE)
|
||||
if(!commando_ghosts.len)
|
||||
to_chat(usr, "<span class='userdanger'>Nobody volunteered to join the SST.</span>")
|
||||
return
|
||||
|
||||
sent_syndicate_strike_team = 1
|
||||
|
||||
//Spawns commandos and equips them.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
|
||||
if(syndicate_commando_number <= 0)
|
||||
break
|
||||
|
||||
if(L.name == "Syndicate-Commando")
|
||||
|
||||
if(!commando_ghosts.len)
|
||||
break
|
||||
|
||||
var/mob/ghost_mob = pick(commando_ghosts)
|
||||
commando_ghosts -= ghost_mob
|
||||
|
||||
if(!ghost_mob || !ghost_mob.key || !ghost_mob.client)
|
||||
continue
|
||||
|
||||
var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, is_leader)
|
||||
|
||||
if(!new_syndicate_commando)
|
||||
continue
|
||||
|
||||
new_syndicate_commando.key = ghost_mob.key
|
||||
new_syndicate_commando.internal = new_syndicate_commando.s_store
|
||||
new_syndicate_commando.update_action_buttons_icon()
|
||||
|
||||
//So they don't forget their code or mission.
|
||||
if(nuke_code)
|
||||
new_syndicate_commando.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code]</span>.")
|
||||
new_syndicate_commando.mind.store_memory("<B>Mission:</B> <span class='warning'>[input]</span>.")
|
||||
|
||||
to_chat(new_syndicate_commando, "<span class='notice'>You are an Elite Syndicate [is_leader ? "<B>TEAM LEADER</B>" : "commando"] in the service of the Syndicate. \nYour current mission is: <span class='userdanger'>[input]</span></span>")
|
||||
new_syndicate_commando.faction += "syndicate"
|
||||
var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS]
|
||||
opshud.join_hud(new_syndicate_commando.mind.current)
|
||||
set_antag_hud(new_syndicate_commando.mind.current, "hudoperative")
|
||||
new_syndicate_commando.regenerate_icons()
|
||||
is_leader = FALSE
|
||||
syndicate_commando_number--
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has spawned a Syndicate strike squad.</span>", 1)
|
||||
log_admin("[key_name(usr)] used Spawn Syndicate Squad.")
|
||||
feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/create_syndicate_death_commando(obj/spawn_location, is_leader = FALSE)
|
||||
var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc)
|
||||
var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major")
|
||||
var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
|
||||
var/syndicate_commando_name = pick(GLOB.last_names)
|
||||
|
||||
var/datum/preferences/A = new()//Randomize appearance for the commando.
|
||||
if(is_leader)
|
||||
A.age = rand(35,45)
|
||||
A.real_name = "[syndicate_commando_leader_rank] [syndicate_commando_name]"
|
||||
else
|
||||
A.real_name = "[syndicate_commando_rank] [syndicate_commando_name]"
|
||||
A.copy_to(new_syndicate_commando)
|
||||
|
||||
new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA.
|
||||
|
||||
//Creates mind stuff.
|
||||
new_syndicate_commando.mind_initialize()
|
||||
new_syndicate_commando.mind.assigned_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
|
||||
new_syndicate_commando.mind.special_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
|
||||
new_syndicate_commando.mind.offstation_role = TRUE
|
||||
SSticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list.
|
||||
new_syndicate_commando.equip_syndicate_commando(is_leader)
|
||||
qdel(spawn_location)
|
||||
return new_syndicate_commando
|
||||
|
||||
/mob/living/carbon/human/proc/equip_syndicate_commando(is_leader = FALSE, full_gear = FALSE)
|
||||
var/obj/item/radio/R = new /obj/item/radio/headset/syndicate/alt/syndteam(src)
|
||||
R.set_frequency(SYNDTEAM_FREQ)
|
||||
equip_to_slot_or_del(R, slot_l_ear)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(src), slot_w_uniform)
|
||||
if(!full_gear)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/storage/backpack/security(src), slot_back)
|
||||
equip_to_slot_or_del(new /obj/item/storage/box/survival_syndi(src), slot_in_backpack)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/revolver(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/a357(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/reagent_containers/hypospray/combat/nanites(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(src), slot_in_backpack)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/pinpointer(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/disk/nuclear/unrestricted(src), slot_in_backpack)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/card/emag(src), slot_r_store)
|
||||
equip_to_slot_or_del(new /obj/item/melee/energy/sword/saber/red(src), slot_l_store)
|
||||
|
||||
if(full_gear)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(src), slot_wear_mask)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/suit/space/hardsuit/syndi/elite/sst(src), slot_wear_suit)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses)
|
||||
equip_to_slot_or_del(new /obj/item/storage/belt/military/sst(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/tank/jetpack/oxygen/harness(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/syndie/advance(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/automatic/l6_saw(src), slot_r_hand)
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/magazine/mm556x45(src), slot_in_backpack)
|
||||
|
||||
var/obj/item/implant/dust/D = new /obj/item/implant/dust(src)
|
||||
D.implant(src)
|
||||
var/obj/item/card/id/syndicate/W = new(src) //Untrackable by AI
|
||||
W.name = "[real_name]'s ID Card"
|
||||
W.icon_state = "syndie"
|
||||
W.assignment = "Syndicate Commando"
|
||||
W.access += get_syndicate_access(W.assignment)
|
||||
W.registered_name = real_name
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
return 1
|
||||
//STRIKE TEAMS
|
||||
|
||||
#define SYNDICATE_COMMANDOS_POSSIBLE 6 //if more Commandos are needed in the future
|
||||
GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0)
|
||||
/client/proc/syndicate_strike_team()
|
||||
set category = "Event"
|
||||
set name = "Spawn Syndicate Strike Team"
|
||||
set desc = "Spawns a squad of commandos in the Syndicate Mothership if you want to run an admin event."
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
if(!SSticker)
|
||||
alert("The game hasn't started yet!")
|
||||
return
|
||||
if(GLOB.sent_syndicate_strike_team == 1)
|
||||
alert("The Syndicate are already sending a team, Mr. Dumbass.")
|
||||
return
|
||||
if(alert("Do you want to send in the Syndicate Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No")
|
||||
return
|
||||
alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned syndicates have internals cameras which are viewable through a monitor inside the Syndicate Mothership Bridge. Assigning the team's detailed task is recommended from there. The first one selected/spawned will be the team leader.")
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has started to spawn a Syndicate Strike Team.</span>", 1)
|
||||
|
||||
var/input = null
|
||||
while(!input)
|
||||
input = sanitize(copytext(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN))
|
||||
if(!input)
|
||||
if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes")
|
||||
return
|
||||
|
||||
if(GLOB.sent_syndicate_strike_team)
|
||||
to_chat(src, "Looks like someone beat you to it.")
|
||||
return
|
||||
|
||||
var/syndicate_commando_number = SYNDICATE_COMMANDOS_POSSIBLE //for selecting a leader
|
||||
var/is_leader = TRUE // set to FALSE after leader is spawned
|
||||
|
||||
// Find the nuclear auth code
|
||||
var/nuke_code
|
||||
var/temp_code
|
||||
for(var/obj/machinery/nuclearbomb/N in world)
|
||||
temp_code = text2num(N.r_code)
|
||||
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
|
||||
nuke_code = N.r_code
|
||||
break
|
||||
|
||||
// Find ghosts willing to be SST
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, SYNDICATE_COMMANDOS_POSSIBLE, "Join the Syndicate Strike Team?",, 21, 600, 1, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE)
|
||||
if(!commando_ghosts.len)
|
||||
to_chat(usr, "<span class='userdanger'>Nobody volunteered to join the SST.</span>")
|
||||
return
|
||||
|
||||
GLOB.sent_syndicate_strike_team = 1
|
||||
|
||||
//Spawns commandos and equips them.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
|
||||
if(syndicate_commando_number <= 0)
|
||||
break
|
||||
|
||||
if(L.name == "Syndicate-Commando")
|
||||
|
||||
if(!commando_ghosts.len)
|
||||
break
|
||||
|
||||
var/mob/ghost_mob = pick(commando_ghosts)
|
||||
commando_ghosts -= ghost_mob
|
||||
|
||||
if(!ghost_mob || !ghost_mob.key || !ghost_mob.client)
|
||||
continue
|
||||
|
||||
var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, is_leader)
|
||||
|
||||
if(!new_syndicate_commando)
|
||||
continue
|
||||
|
||||
new_syndicate_commando.key = ghost_mob.key
|
||||
new_syndicate_commando.internal = new_syndicate_commando.s_store
|
||||
new_syndicate_commando.update_action_buttons_icon()
|
||||
|
||||
//So they don't forget their code or mission.
|
||||
if(nuke_code)
|
||||
new_syndicate_commando.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code]</span>.")
|
||||
new_syndicate_commando.mind.store_memory("<B>Mission:</B> <span class='warning'>[input]</span>.")
|
||||
|
||||
to_chat(new_syndicate_commando, "<span class='notice'>You are an Elite Syndicate [is_leader ? "<B>TEAM LEADER</B>" : "commando"] in the service of the Syndicate. \nYour current mission is: <span class='userdanger'>[input]</span></span>")
|
||||
new_syndicate_commando.faction += "syndicate"
|
||||
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
|
||||
opshud.join_hud(new_syndicate_commando.mind.current)
|
||||
set_antag_hud(new_syndicate_commando.mind.current, "hudoperative")
|
||||
new_syndicate_commando.regenerate_icons()
|
||||
is_leader = FALSE
|
||||
syndicate_commando_number--
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has spawned a Syndicate strike squad.</span>", 1)
|
||||
log_admin("[key_name(usr)] used Spawn Syndicate Squad.")
|
||||
feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/create_syndicate_death_commando(obj/spawn_location, is_leader = FALSE)
|
||||
var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc)
|
||||
var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major")
|
||||
var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
|
||||
var/syndicate_commando_name = pick(GLOB.last_names)
|
||||
|
||||
var/datum/preferences/A = new()//Randomize appearance for the commando.
|
||||
if(is_leader)
|
||||
A.age = rand(35,45)
|
||||
A.real_name = "[syndicate_commando_leader_rank] [syndicate_commando_name]"
|
||||
else
|
||||
A.real_name = "[syndicate_commando_rank] [syndicate_commando_name]"
|
||||
A.copy_to(new_syndicate_commando)
|
||||
|
||||
new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA.
|
||||
|
||||
//Creates mind stuff.
|
||||
new_syndicate_commando.mind_initialize()
|
||||
new_syndicate_commando.mind.assigned_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
|
||||
new_syndicate_commando.mind.special_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
|
||||
new_syndicate_commando.mind.offstation_role = TRUE
|
||||
SSticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list.
|
||||
new_syndicate_commando.equip_syndicate_commando(is_leader)
|
||||
qdel(spawn_location)
|
||||
return new_syndicate_commando
|
||||
|
||||
/mob/living/carbon/human/proc/equip_syndicate_commando(is_leader = FALSE, full_gear = FALSE)
|
||||
var/obj/item/radio/R = new /obj/item/radio/headset/syndicate/alt/syndteam(src)
|
||||
R.set_frequency(SYNDTEAM_FREQ)
|
||||
equip_to_slot_or_del(R, slot_l_ear)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(src), slot_w_uniform)
|
||||
if(!full_gear)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/storage/backpack/security(src), slot_back)
|
||||
equip_to_slot_or_del(new /obj/item/storage/box/survival_syndi(src), slot_in_backpack)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/revolver(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/a357(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/reagent_containers/hypospray/combat/nanites(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(src), slot_in_backpack)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/pinpointer(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/disk/nuclear/unrestricted(src), slot_in_backpack)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/card/emag(src), slot_r_store)
|
||||
equip_to_slot_or_del(new /obj/item/melee/energy/sword/saber/red(src), slot_l_store)
|
||||
|
||||
if(full_gear)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(src), slot_wear_mask)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/suit/space/hardsuit/syndi/elite/sst(src), slot_wear_suit)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses)
|
||||
equip_to_slot_or_del(new /obj/item/storage/belt/military/sst(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/tank/jetpack/oxygen/harness(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/syndie/advance(src), slot_shoes)
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/automatic/l6_saw(src), slot_r_hand)
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/magazine/mm556x45(src), slot_in_backpack)
|
||||
|
||||
var/obj/item/implant/dust/D = new /obj/item/implant/dust(src)
|
||||
D.implant(src)
|
||||
var/obj/item/card/id/syndicate/W = new(src) //Untrackable by AI
|
||||
W.name = "[real_name]'s ID Card"
|
||||
W.icon_state = "syndie"
|
||||
W.assignment = "Syndicate Commando"
|
||||
W.access += get_syndicate_access(W.assignment)
|
||||
W.registered_name = real_name
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
//Merged Doohl's and the existing ticklag as they both had good elements about them ~Carn
|
||||
|
||||
/client/proc/ticklag()
|
||||
set category = "Debug"
|
||||
set name = "Set Ticklag"
|
||||
set desc = "Sets a new tick lag. Recommend you don't mess with this too much! Stable, time-tested ticklag value is 0.9"
|
||||
|
||||
if(!check_rights(R_DEBUG)) return
|
||||
|
||||
var/newtick = input("Sets a new tick lag. Please don't mess with this too much! The stable, time-tested ticklag value is 0.9","Lag of Tick", world.tick_lag) as num|null
|
||||
//I've used ticks of 2 before to help with serious singulo lags
|
||||
if(newtick && newtick <= 2 && newtick > 0)
|
||||
log_admin("[key_name(src)] has modified world.tick_lag to [newtick]", 0)
|
||||
message_admins("[key_name_admin(src)] has modified world.tick_lag to [newtick]", 0)
|
||||
world.tick_lag = newtick
|
||||
feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
else
|
||||
to_chat(src, "<span class='warning'>Error: ticklag(): Invalid world.ticklag value. No changes made.</span>")
|
||||
|
||||
|
||||
//Merged Doohl's and the existing ticklag as they both had good elements about them ~Carn
|
||||
|
||||
/client/proc/ticklag()
|
||||
set category = "Debug"
|
||||
set name = "Set Ticklag"
|
||||
set desc = "Sets a new tick lag. Recommend you don't mess with this too much! Stable, time-tested ticklag value is 0.9"
|
||||
|
||||
if(!check_rights(R_DEBUG)) return
|
||||
|
||||
var/newtick = input("Sets a new tick lag. Please don't mess with this too much! The stable, time-tested ticklag value is 0.9","Lag of Tick", world.tick_lag) as num|null
|
||||
//I've used ticks of 2 before to help with serious singulo lags
|
||||
if(newtick && newtick <= 2 && newtick > 0)
|
||||
log_admin("[key_name(src)] has modified world.tick_lag to [newtick]", 0)
|
||||
message_admins("[key_name_admin(src)] has modified world.tick_lag to [newtick]", 0)
|
||||
world.tick_lag = newtick
|
||||
feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
else
|
||||
to_chat(src, "<span class='warning'>Error: ticklag(): Invalid world.ticklag value. No changes made.</span>")
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var/list/admin_verbs_show_debug_verbs = list(
|
||||
GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list(
|
||||
/client/proc/camera_view,
|
||||
/client/proc/sec_camera_report,
|
||||
/client/proc/intercom_view,
|
||||
@@ -22,7 +22,7 @@ var/list/admin_verbs_show_debug_verbs = list(
|
||||
/client/proc/admin_redo_space_transitions,
|
||||
/client/proc/make_turf_space_map,
|
||||
/client/proc/vv_by_ref
|
||||
)
|
||||
))
|
||||
|
||||
// Would be nice to make this a permanent admin pref so we don't need to click it each time
|
||||
/client/proc/enable_debug_verbs()
|
||||
@@ -32,6 +32,6 @@ var/list/admin_verbs_show_debug_verbs = list(
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
verbs += admin_verbs_show_debug_verbs
|
||||
verbs += GLOB.admin_verbs_show_debug_verbs
|
||||
|
||||
feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/client/proc/triple_ai()
|
||||
set category = "Event"
|
||||
set name = "Create AI Triumvirate"
|
||||
|
||||
if(SSticker.current_state > GAME_STATE_PREGAME)
|
||||
to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.")
|
||||
return
|
||||
|
||||
if(SSjobs && SSticker)
|
||||
var/datum/job/job = SSjobs.GetJob("AI")
|
||||
if(!job)
|
||||
to_chat(usr, "Unable to locate the AI job")
|
||||
return
|
||||
if(SSticker.triai)
|
||||
SSticker.triai = 0
|
||||
to_chat(usr, "Only one AI will be spawned at round start.")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has toggled off triple AIs at round start.</span>", 1)
|
||||
else
|
||||
SSticker.triai = 1
|
||||
to_chat(usr, "There will be an AI Triumvirate at round start.")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has toggled on triple AIs at round start.</span>", 1)
|
||||
return
|
||||
/client/proc/triple_ai()
|
||||
set category = "Event"
|
||||
set name = "Create AI Triumvirate"
|
||||
|
||||
if(SSticker.current_state > GAME_STATE_PREGAME)
|
||||
to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.")
|
||||
return
|
||||
|
||||
if(SSjobs && SSticker)
|
||||
var/datum/job/job = SSjobs.GetJob("AI")
|
||||
if(!job)
|
||||
to_chat(usr, "Unable to locate the AI job")
|
||||
return
|
||||
if(SSticker.triai)
|
||||
SSticker.triai = 0
|
||||
to_chat(usr, "Only one AI will be spawned at round start.")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has toggled off triple AIs at round start.</span>", 1)
|
||||
else
|
||||
SSticker.triai = 1
|
||||
to_chat(usr, "There will be an AI Triumvirate at round start.")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has toggled on triple AIs at round start.</span>", 1)
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var/global/vox_tick = 1
|
||||
GLOBAL_VAR_INIT(vox_tick, 1)
|
||||
|
||||
/mob/living/carbon/human/proc/equip_vox_raider()
|
||||
|
||||
@@ -10,7 +10,7 @@ var/global/vox_tick = 1
|
||||
equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(src), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES.
|
||||
equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow/vox(src), slot_gloves) // AS ABOVE.
|
||||
|
||||
switch(vox_tick)
|
||||
switch(GLOB.vox_tick)
|
||||
if(1) // Vox raider!
|
||||
equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(src), slot_wear_suit)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(src), slot_head)
|
||||
@@ -59,7 +59,7 @@ var/global/vox_tick = 1
|
||||
W.registered_user = src
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
vox_tick++
|
||||
if(vox_tick > 4) vox_tick = 1
|
||||
GLOB.vox_tick++
|
||||
if(GLOB.vox_tick > 4) GLOB.vox_tick = 1
|
||||
|
||||
return 1
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
if(!new_ckey)
|
||||
return
|
||||
new_ckey = sanitizeSQL(new_ckey)
|
||||
var/DBQuery/query_watchfind = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
|
||||
var/DBQuery/query_watchfind = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
|
||||
if(!query_watchfind.Execute())
|
||||
var/err = query_watchfind.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
|
||||
@@ -29,7 +29,7 @@
|
||||
if(!adminckey)
|
||||
return
|
||||
var/admin_sql_ckey = sanitizeSQL(adminckey)
|
||||
var/DBQuery/query_watchadd = dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp) VALUES ('[target_sql_ckey]', '[reason]', '[admin_sql_ckey]', '[timestamp]')")
|
||||
var/DBQuery/query_watchadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp) VALUES ('[target_sql_ckey]', '[reason]', '[admin_sql_ckey]', '[timestamp]')")
|
||||
if(!query_watchadd.Execute())
|
||||
var/err = query_watchadd.ErrorMsg()
|
||||
log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n")
|
||||
@@ -43,7 +43,7 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/target_sql_ckey = sanitizeSQL(target_ckey)
|
||||
var/DBQuery/query_watchdel = dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_watchdel = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_watchdel.Execute())
|
||||
var/err = query_watchdel.ErrorMsg()
|
||||
log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n")
|
||||
@@ -57,7 +57,7 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/target_sql_ckey = sanitizeSQL(target_ckey)
|
||||
var/DBQuery/query_watchreason = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_watchreason = GLOB.dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_watchreason.Execute())
|
||||
var/err = query_watchreason.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n")
|
||||
@@ -71,7 +71,7 @@
|
||||
var/sql_ckey = sanitizeSQL(usr.ckey)
|
||||
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[watch_reason]\" to \"[new_reason]\""
|
||||
edit_text = sanitizeSQL(edit_text)
|
||||
var/DBQuery/query_watchupdate = dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_watchupdate = GLOB.dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_watchupdate.Execute())
|
||||
var/err = query_watchupdate.ErrorMsg()
|
||||
log_game("SQL ERROR editing watchlist reason. Error : \[[err]\]\n")
|
||||
@@ -96,7 +96,7 @@
|
||||
else
|
||||
search = "^."
|
||||
search = sanitizeSQL(search)
|
||||
var/DBQuery/query_watchlist = dbcon.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
|
||||
var/DBQuery/query_watchlist = GLOB.dbcon.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
|
||||
if(!query_watchlist.Execute())
|
||||
var/err = query_watchlist.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey, reason, adminckey, timestamp, last_editor from watch table. Error : \[[err]\]\n")
|
||||
@@ -113,11 +113,9 @@
|
||||
output += "<br>[reason]<hr style='background:#000000; border:0; height:1px'>"
|
||||
usr << browse(output, "window=watchwin;size=900x500")
|
||||
|
||||
/client/proc/check_watchlist(target_ckey)
|
||||
if(!check_rights(R_ADMIN,0))
|
||||
return
|
||||
/proc/check_watchlist(target_ckey)
|
||||
var/target_sql_ckey = sanitizeSQL(target_ckey)
|
||||
var/DBQuery/query_watch = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
|
||||
var/DBQuery/query_watch = GLOB.dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
|
||||
if(!query_watch.Execute())
|
||||
var/err = query_watch.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n")
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/datum/alarm_handler/camera
|
||||
category = "Camera Alarms"
|
||||
category = "Camera Alarms"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/datum/alarm_handler/motion
|
||||
category = "Motion Alarms"
|
||||
category = "Motion Alarms"
|
||||
|
||||
@@ -134,4 +134,4 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
//Displayed at the end of roundend_category section
|
||||
/datum/antagonist/proc/roundend_report_footer()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
continue
|
||||
var/datum/team/T = A.get_team()
|
||||
if(!team_type || istype(T, team_type))
|
||||
. |= T
|
||||
. |= T
|
||||
|
||||
@@ -47,11 +47,11 @@
|
||||
newhud.join_hud(current)
|
||||
|
||||
/datum/mind/proc/leave_all_huds()
|
||||
for(var/datum/atom_hud/antag/hud in huds)
|
||||
for(var/datum/atom_hud/antag/hud in GLOB.huds)
|
||||
if(current in hud.hudusers)
|
||||
hud.leave_hud(current)
|
||||
|
||||
for(var/datum/atom_hud/data/hud in huds)
|
||||
for(var/datum/atom_hud/data/hud in GLOB.huds)
|
||||
if(current in hud.hudusers)
|
||||
hud.remove_hud_from(current)
|
||||
|
||||
@@ -77,4 +77,4 @@
|
||||
|
||||
/datum/mindslaves/proc/leave_serv_hud(datum/mind/free_mind)
|
||||
thrallhud.leave_hud(free_mind.current)
|
||||
set_antag_hud(free_mind.current, null)
|
||||
set_antag_hud(free_mind.current, null)
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
to_chat(user, "<span class='notice'>The sludge does not respond to your attempt to awake it. Perhaps you should try again later.</span>")
|
||||
|
||||
/obj/item/antag_spawner/morph/spawn_antag(client/C, turf/T, type = "", mob/user)
|
||||
var/mob/living/simple_animal/hostile/morph/wizard/M = new /mob/living/simple_animal/hostile/morph/wizard(pick(xeno_spawn))
|
||||
var/mob/living/simple_animal/hostile/morph/wizard/M = new /mob/living/simple_animal/hostile/morph/wizard(pick(GLOB.xeno_spawn))
|
||||
M.key = C.key
|
||||
M.mind.assigned_role = SPECIAL_ROLE_MORPH
|
||||
M.mind.special_role = SPECIAL_ROLE_MORPH
|
||||
|
||||
@@ -38,4 +38,4 @@
|
||||
var/datum/objective/steal_five_of_type/summon_magic/magic = new
|
||||
magic.owner = owner
|
||||
objectives += magic
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
owner.objectives -= O
|
||||
|
||||
/datum/antagonist/mindslave/proc/update_mindslave_icons_added()
|
||||
var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR]
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudmindslave")
|
||||
|
||||
/datum/antagonist/mindslave/proc/update_mindslave_icons_removed()
|
||||
var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR]
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.leave_hud(owner.current, null)
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||
|
||||
var/objective_amount = config.traitor_objectives_amount
|
||||
|
||||
|
||||
if(is_hijacker && objective_count <= objective_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
|
||||
if (!(locate(/datum/objective/hijack) in objectives))
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
@@ -152,8 +152,7 @@
|
||||
var/objective_count = 0
|
||||
var/try_again = TRUE
|
||||
|
||||
if(prob(30))
|
||||
objective_count += forge_single_objective()
|
||||
objective_count += forge_single_objective()
|
||||
|
||||
for(var/i = objective_count, i < config.traitor_objectives_amount)
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
@@ -188,7 +187,7 @@
|
||||
destroy_objective.owner = owner
|
||||
destroy_objective.find_target()
|
||||
if("[destroy_objective]" in assigned_targets) // Is this target already in their list of assigned targets? If so, don't add this objective and return
|
||||
return 0
|
||||
return 0
|
||||
else if(destroy_objective.target) // Is the target a real one and not null? If so, add it to our list of targets to avoid duplicate targets
|
||||
assigned_targets.Add("[destroy_objective.target]") // This logic is applied to all traitor objectives including steal objectives
|
||||
add_objective(destroy_objective)
|
||||
@@ -222,7 +221,7 @@
|
||||
else if(kill_objective.target)
|
||||
assigned_targets.Add("[kill_objective.target]")
|
||||
add_objective(kill_objective)
|
||||
|
||||
|
||||
else
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = owner
|
||||
@@ -232,32 +231,13 @@
|
||||
else if(steal_objective.steal_target)
|
||||
assigned_targets.Add("[steal_objective.steal_target]")
|
||||
add_objective(steal_objective)
|
||||
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/forge_single_AI_objective()
|
||||
. = 1
|
||||
var/special_pick = rand(1,2)
|
||||
switch(special_pick)
|
||||
if(1) // AI hijack
|
||||
var/datum/objective/block/block_objective = new
|
||||
block_objective.owner = owner
|
||||
add_objective(block_objective)
|
||||
if(2) // Protect and strand a target
|
||||
var/datum/objective/protect/yandere_one = new
|
||||
yandere_one.owner = owner
|
||||
yandere_one.find_target()
|
||||
|
||||
if("[yandere_one.target]" in assigned_targets)
|
||||
return 0
|
||||
else if(yandere_one.target)
|
||||
assigned_targets.Add("[yandere_one.target]")
|
||||
|
||||
add_objective(yandere_one)
|
||||
var/datum/objective/maroon/yandere_two = new
|
||||
yandere_two.owner = owner
|
||||
yandere_two.target = yandere_one.target
|
||||
yandere_two.explanation_text = "Prevent [yandere_one.target], the [yandere_one.target.assigned_role] from escaping alive."
|
||||
add_objective(yandere_two)
|
||||
var/datum/objective/block/block_objective = new
|
||||
block_objective.owner = owner
|
||||
add_objective(block_objective)
|
||||
|
||||
|
||||
/datum/antagonist/traitor/greet()
|
||||
@@ -271,13 +251,13 @@
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/update_traitor_icons_added(datum/mind/traitor_mind)
|
||||
var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR]
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudsyndicate")
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/update_traitor_icons_removed(datum/mind/traitor_mind)
|
||||
var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR]
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.leave_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, null)
|
||||
|
||||
@@ -293,7 +273,7 @@
|
||||
if(should_equip)
|
||||
equip_traitor()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/give_codewords()
|
||||
if(!owner.current)
|
||||
@@ -329,7 +309,7 @@
|
||||
|
||||
if(traitor_kind == TRAITOR_HUMAN)
|
||||
var/mob/living/carbon/human/traitor_mob = owner.current
|
||||
|
||||
|
||||
// find a radio! toolbox(es), backpack, belt, headset
|
||||
var/obj/item/R = locate(/obj/item/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio
|
||||
if(!R)
|
||||
|
||||
@@ -22,57 +22,57 @@
|
||||
if(!istype(H))
|
||||
return
|
||||
H.ignore_gene_stability = TRUE
|
||||
H.dna.SetSEState(HULKBLOCK, TRUE)
|
||||
genemutcheck(H, HULKBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.hulkblock, TRUE)
|
||||
genemutcheck(H, GLOB.hulkblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(XRAYBLOCK, TRUE)
|
||||
genemutcheck(H, XRAYBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.xrayblock, TRUE)
|
||||
genemutcheck(H, GLOB.xrayblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(FIREBLOCK, TRUE)
|
||||
genemutcheck(H, FIREBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.fireblock, TRUE)
|
||||
genemutcheck(H, GLOB.fireblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(COLDBLOCK, TRUE)
|
||||
genemutcheck(H, COLDBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.coldblock, TRUE)
|
||||
genemutcheck(H, GLOB.coldblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(TELEBLOCK, TRUE)
|
||||
genemutcheck(H, TELEBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.teleblock, TRUE)
|
||||
genemutcheck(H, GLOB.teleblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(INCREASERUNBLOCK, TRUE)
|
||||
genemutcheck(H, INCREASERUNBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.increaserunblock, TRUE)
|
||||
genemutcheck(H, GLOB.increaserunblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(BREATHLESSBLOCK, TRUE)
|
||||
genemutcheck(H, BREATHLESSBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.breathlessblock, TRUE)
|
||||
genemutcheck(H, GLOB.breathlessblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(REGENERATEBLOCK, TRUE)
|
||||
genemutcheck(H, REGENERATEBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.regenerateblock, TRUE)
|
||||
genemutcheck(H, GLOB.regenerateblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(SHOCKIMMUNITYBLOCK, TRUE)
|
||||
genemutcheck(H, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.shockimmunityblock, TRUE)
|
||||
genemutcheck(H, GLOB.shockimmunityblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(SMALLSIZEBLOCK, TRUE)
|
||||
genemutcheck(H, SMALLSIZEBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.smallsizeblock, TRUE)
|
||||
genemutcheck(H, GLOB.smallsizeblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(SOBERBLOCK, TRUE)
|
||||
genemutcheck(H, SOBERBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.soberblock, TRUE)
|
||||
genemutcheck(H, GLOB.soberblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(PSYRESISTBLOCK, TRUE)
|
||||
genemutcheck(H, PSYRESISTBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.psyresistblock, TRUE)
|
||||
genemutcheck(H, GLOB.psyresistblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(SHADOWBLOCK, TRUE)
|
||||
genemutcheck(H, SHADOWBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.shadowblock, TRUE)
|
||||
genemutcheck(H, GLOB.shadowblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(CRYOBLOCK, TRUE)
|
||||
genemutcheck(H, CRYOBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.cryoblock, TRUE)
|
||||
genemutcheck(H, GLOB.cryoblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(EATBLOCK, TRUE)
|
||||
genemutcheck(H, EATBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.eatblock, TRUE)
|
||||
genemutcheck(H, GLOB.eatblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(JUMPBLOCK, TRUE)
|
||||
genemutcheck(H, JUMPBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.jumpblock, TRUE)
|
||||
genemutcheck(H, GLOB.jumpblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.dna.SetSEState(IMMOLATEBLOCK, TRUE)
|
||||
genemutcheck(H, IMMOLATEBLOCK, null, MUTCHK_FORCED)
|
||||
H.dna.SetSEState(GLOB.immolateblock, TRUE)
|
||||
genemutcheck(H, GLOB.immolateblock, null, MUTCHK_FORCED)
|
||||
|
||||
H.mutations.Add(LASER)
|
||||
H.update_mutations()
|
||||
H.update_body()
|
||||
H.update_body()
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
tokens += 1
|
||||
return
|
||||
if(panel_open && component_parts && istype(O, /obj/item/crowbar))
|
||||
default_deconstruction_crowbar(O)
|
||||
default_deconstruction_crowbar(user, O)
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
opening = 1
|
||||
playsound(src.loc, 'sound/items/bubblewrap.ogg', 30, 1, extrarange = -4, falloff = 10)
|
||||
icon_state = "prizeconfetti"
|
||||
src.color = pick(random_color_list)
|
||||
src.color = pick(GLOB.random_color_list)
|
||||
var/prize_inside = pick(possible_contents)
|
||||
spawn(10)
|
||||
user.unEquip(src)
|
||||
@@ -85,4 +85,4 @@
|
||||
if(25 to 74)
|
||||
icon_state = "tickets_3" // Buncha tickets
|
||||
else
|
||||
icon_state = "tickets_4" // Ticket snake
|
||||
icon_state = "tickets_4" // Ticket snake
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/var/claw_game_html = null
|
||||
GLOBAL_VAR(claw_game_html)
|
||||
|
||||
/obj/machinery/arcade/claw
|
||||
name = "Claw Game"
|
||||
@@ -30,8 +30,8 @@
|
||||
component_parts += new /obj/item/stack/sheet/glass(null, 1)
|
||||
RefreshParts()
|
||||
|
||||
if(!claw_game_html)
|
||||
claw_game_html = file2text('code/modules/arcade/crane.html')
|
||||
if(!GLOB.claw_game_html)
|
||||
GLOB.claw_game_html = file2text('code/modules/arcade/crane.html')
|
||||
|
||||
/obj/machinery/arcade/claw/RefreshParts()
|
||||
var/bin_upgrades = 0
|
||||
@@ -58,14 +58,14 @@
|
||||
atom_say("WINNER!")
|
||||
new /obj/item/toy/prizeball(get_turf(src))
|
||||
playsound(src.loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
|
||||
addtimer(CALLBACK(src, .update_icon), 10)
|
||||
addtimer(CALLBACK(src, .proc/update_icon), 10)
|
||||
|
||||
/obj/machinery/arcade/claw/start_play(mob/user as mob)
|
||||
..()
|
||||
user << browse_rsc('page.css')
|
||||
for(var/i in 1 to img_resources.len)
|
||||
user << browse_rsc(img_resources[i])
|
||||
var/my_game_html = replacetext(claw_game_html, "/* ref src */", UID())
|
||||
var/my_game_html = replacetext(GLOB.claw_game_html, "/* ref src */", UID())
|
||||
user << browse(my_game_html, "window=[window_name];size=915x600;can_resize=0")
|
||||
|
||||
/obj/machinery/arcade/claw/Topic(href, list/href_list)
|
||||
@@ -76,4 +76,4 @@
|
||||
if(!isnull(prize_won))
|
||||
close_game()
|
||||
if(prize_won == "1")
|
||||
win()
|
||||
win()
|
||||
|
||||
@@ -302,4 +302,4 @@
|
||||
to_chat(user, "<span class='warning'>This mob is already at maximum health!</span>")
|
||||
return
|
||||
patient.mob_data.cur_health = patient.mob_data.max_health
|
||||
to_chat(user, "<span class='notify'>[patient.mob_data.nickname ? patient.mob_data.nickname : patient.mob_data.mob_name] has been restored to full health!</span>")
|
||||
to_chat(user, "<span class='notify'>[patient.mob_data.nickname ? patient.mob_data.nickname : patient.mob_data.mob_name] has been restored to full health!</span>")
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
desc = "A random Nano-Mob Trading Card from a Booster Pack. Wonder what it is?"
|
||||
|
||||
/obj/item/nanomob_card/booster/New()
|
||||
..()
|
||||
var/datum/mob_hunt/mob_info = pick(subtypesof(/datum/mob_hunt))
|
||||
mob_data = new mob_info(0,null,1)
|
||||
update_info()
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
/datum/mob_hunt/proc/get_possible_areas()
|
||||
var/list/possible_areas = list()
|
||||
//setup, sets all station areas (and subtypes) to weight 1
|
||||
for(var/A in the_station_areas)
|
||||
for(var/A in GLOB.the_station_areas)
|
||||
if(A == /area/holodeck) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on z2 as well
|
||||
continue
|
||||
if(A in possible_areas)
|
||||
@@ -498,4 +498,4 @@
|
||||
turf_blacklist = list()
|
||||
area_whitelist = list()
|
||||
turf_whitelist = list()
|
||||
lifetime = 2000
|
||||
lifetime = 2000
|
||||
|
||||
@@ -253,4 +253,4 @@
|
||||
TYPE_FLYING,
|
||||
TYPE_BLUESPACE,
|
||||
TYPE_STEEL)
|
||||
immunity = list(TYPE_POISON)
|
||||
immunity = list(TYPE_POISON)
|
||||
|
||||
@@ -89,4 +89,4 @@ body {
|
||||
|
||||
.button {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
if(component_parts && istype(O, /obj/item/crowbar))
|
||||
if(tickets) //save the tickets!
|
||||
print_tickets()
|
||||
default_deconstruction_crowbar(O)
|
||||
default_deconstruction_crowbar(user, O)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -140,11 +140,11 @@ th.cost.toomuch {background:maroon;}
|
||||
<tbody>
|
||||
"}
|
||||
|
||||
for(var/datum/prize_item/item in global_prizes.prizes)
|
||||
for(var/datum/prize_item/item in GLOB.global_prizes.prizes)
|
||||
var/cost_class="affordable"
|
||||
if(item.cost>tickets)
|
||||
cost_class="toomuch"
|
||||
var/itemID = global_prizes.prizes.Find(item)
|
||||
var/itemID = GLOB.global_prizes.prizes.Find(item)
|
||||
var/row_color="light"
|
||||
if(itemID%2 == 0)
|
||||
row_color="dark"
|
||||
@@ -185,12 +185,12 @@ th.cost.toomuch {background:maroon;}
|
||||
|
||||
if(href_list["buy"])
|
||||
var/itemID = text2num(href_list["buy"])
|
||||
var/datum/prize_item/item = global_prizes.prizes[itemID]
|
||||
var/datum/prize_item/item = GLOB.global_prizes.prizes[itemID]
|
||||
var/sure = alert(usr,"Are you sure you wish to purchase [item.name] for [item.cost] tickets?","You sure?","Yes","No") in list("Yes","No")
|
||||
if(sure=="No")
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!global_prizes.PlaceOrder(src, itemID))
|
||||
if(!GLOB.global_prizes.PlaceOrder(src, itemID))
|
||||
to_chat(usr, "<span class='warning'>Unable to complete the exchange.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>You've successfully purchased the item.</span>")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
var/global/datum/prizes/global_prizes = new
|
||||
GLOBAL_DATUM_INIT(global_prizes, /datum/prizes, new())
|
||||
|
||||
/datum/prizes
|
||||
var/list/prizes = list()
|
||||
@@ -14,7 +13,7 @@ var/global/datum/prizes/global_prizes = new
|
||||
return
|
||||
if(!prize_counter)
|
||||
return 0
|
||||
var/datum/prize_item/item = global_prizes.prizes[itemID]
|
||||
var/datum/prize_item/item = GLOB.global_prizes.prizes[itemID]
|
||||
if(!item)
|
||||
return 0
|
||||
if(prize_counter.tickets >= item.cost)
|
||||
|
||||
+150
-146
@@ -1,146 +1,150 @@
|
||||
/obj/item/assembly
|
||||
name = "assembly"
|
||||
desc = "A small electronic device that should never exist."
|
||||
icon = 'icons/obj/assemblies/new_assemblies.dmi'
|
||||
icon_state = ""
|
||||
flags = CONDUCT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL = 100)
|
||||
throwforce = 2
|
||||
throw_speed = 3
|
||||
throw_range = 10
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
toolspeed = 1
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
|
||||
var/bomb_name = "bomb" // used for naming bombs / mines
|
||||
|
||||
var/secured = TRUE
|
||||
var/list/attached_overlays = null
|
||||
var/obj/item/assembly_holder/holder = null
|
||||
var/cooldown = FALSE //To prevent spam
|
||||
var/wires = WIRE_RECEIVE | WIRE_PULSE
|
||||
var/datum/wires/connected = null // currently only used by timer/signaler
|
||||
|
||||
var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate()
|
||||
var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder
|
||||
var/const/WIRE_PULSE_SPECIAL = 4 //Allows Pulse(0) to act on the holders special assembly
|
||||
var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate()
|
||||
var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message
|
||||
|
||||
/obj/item/assembly/proc/activate() //What the device does when turned on
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/pulsed(radio = FALSE) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/pulse(radio = FALSE) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/attach_assembly(obj/A, mob/user) //Called when an assembly is attacked by another
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/process_cooldown() //Called via spawn(10) to have it count down the cooldown var
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/holder_movement() //Called when the holder is moved
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc)
|
||||
return "The trigger assembly looks broken!"
|
||||
|
||||
/obj/item/assembly/interact(mob/user) //Called when attack_self is called
|
||||
return
|
||||
|
||||
/obj/item/assembly/process_cooldown()
|
||||
cooldown--
|
||||
if(cooldown <= 0)
|
||||
return FALSE
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/Destroy()
|
||||
if(istype(loc, /obj/item/assembly_holder) || istype(holder))
|
||||
var/obj/item/assembly_holder/A = loc
|
||||
if(A.a_left == src)
|
||||
A.a_left = null
|
||||
else if(A.a_right == src)
|
||||
A.a_right = null
|
||||
holder = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/pulsed(radio = FALSE)
|
||||
if(holder && (wires & WIRE_RECEIVE))
|
||||
activate()
|
||||
if(radio && (wires & WIRE_RADIO_RECEIVE))
|
||||
activate()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/pulse(radio = FALSE)
|
||||
if(holder && (wires & WIRE_PULSE))
|
||||
holder.process_activation(src, 1, 0)
|
||||
if(holder && (wires & WIRE_PULSE_SPECIAL))
|
||||
holder.process_activation(src, 0, 1)
|
||||
if(istype(loc, /obj/item/grenade)) // This is a hack. Todo: Manage this better -Sayu
|
||||
var/obj/item/grenade/G = loc
|
||||
G.prime() // Adios, muchachos
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/activate()
|
||||
if(!secured || cooldown > 0)
|
||||
return FALSE
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/toggle_secure()
|
||||
secured = !secured
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/attach_assembly(obj/item/assembly/A, mob/user)
|
||||
holder = new /obj/item/assembly_holder(get_turf(src))
|
||||
if(holder.attach(A, src, user))
|
||||
to_chat(user, "<span class='notice'>You attach [A] to [src]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/attackby(obj/item/W, mob/user, params)
|
||||
if(isassembly(W))
|
||||
var/obj/item/assembly/A = W
|
||||
if(!A.secured && !secured)
|
||||
attach_assembly(A, user)
|
||||
return
|
||||
if(isscrewdriver(W))
|
||||
if(toggle_secure())
|
||||
to_chat(user, "<span class='notice'>[src] is ready!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] can now be attached!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/process()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/assembly/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(src, user) || loc == user)
|
||||
if(secured)
|
||||
. += "[src] is ready!"
|
||||
else
|
||||
. += "[src] can be attached!"
|
||||
|
||||
/obj/item/assembly/attack_self(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/interact(mob/user)
|
||||
return
|
||||
/obj/item/assembly
|
||||
name = "assembly"
|
||||
desc = "A small electronic device that should never exist."
|
||||
icon = 'icons/obj/assemblies/new_assemblies.dmi'
|
||||
icon_state = ""
|
||||
flags = CONDUCT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL = 100)
|
||||
throwforce = 2
|
||||
throw_speed = 3
|
||||
throw_range = 10
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
toolspeed = 1
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
|
||||
var/bomb_name = "bomb" // used for naming bombs / mines
|
||||
|
||||
var/secured = TRUE
|
||||
var/list/attached_overlays = null
|
||||
var/obj/item/assembly_holder/holder = null
|
||||
var/cooldown = FALSE //To prevent spam
|
||||
var/wires = WIRE_RECEIVE | WIRE_PULSE
|
||||
var/datum/wires/connected = null // currently only used by timer/signaler
|
||||
|
||||
var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate()
|
||||
var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder
|
||||
var/const/WIRE_PULSE_SPECIAL = 4 //Allows Pulse(0) to act on the holders special assembly
|
||||
var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate()
|
||||
var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message
|
||||
|
||||
/obj/item/assembly/proc/activate() //What the device does when turned on
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/pulsed(radio = FALSE) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/pulse(radio = FALSE) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/attach_assembly(obj/A, mob/user) //Called when an assembly is attacked by another
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/process_cooldown() //Called via spawn(10) to have it count down the cooldown var
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/holder_movement() //Called when the holder is moved
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc)
|
||||
return "The trigger assembly looks broken!"
|
||||
|
||||
/obj/item/assembly/interact(mob/user) //Called when attack_self is called
|
||||
return
|
||||
|
||||
/obj/item/assembly/process_cooldown()
|
||||
cooldown--
|
||||
if(cooldown <= 0)
|
||||
return FALSE
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/Destroy()
|
||||
if(istype(loc, /obj/item/assembly_holder) || istype(holder))
|
||||
var/obj/item/assembly_holder/A = loc
|
||||
if(A.a_left == src)
|
||||
A.a_left = null
|
||||
else if(A.a_right == src)
|
||||
A.a_right = null
|
||||
holder = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/pulsed(radio = FALSE)
|
||||
if(holder && (wires & WIRE_RECEIVE))
|
||||
activate()
|
||||
if(radio && (wires & WIRE_RADIO_RECEIVE))
|
||||
activate()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/pulse(radio = FALSE)
|
||||
if(holder && (wires & WIRE_PULSE))
|
||||
holder.process_activation(src, 1, 0)
|
||||
if(holder && (wires & WIRE_PULSE_SPECIAL))
|
||||
holder.process_activation(src, 0, 1)
|
||||
if(istype(loc, /obj/item/grenade)) // This is a hack. Todo: Manage this better -Sayu
|
||||
var/obj/item/grenade/G = loc
|
||||
G.prime() // Adios, muchachos
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/activate()
|
||||
if(!secured || cooldown > 0)
|
||||
return FALSE
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/toggle_secure()
|
||||
secured = !secured
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/attach_assembly(obj/item/assembly/A, mob/user)
|
||||
holder = new /obj/item/assembly_holder(get_turf(src))
|
||||
if(holder.attach(A, src, user))
|
||||
to_chat(user, "<span class='notice'>You attach [A] to [src]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/attackby(obj/item/W, mob/user, params)
|
||||
if(isassembly(W))
|
||||
var/obj/item/assembly/A = W
|
||||
if(!A.secured && !secured)
|
||||
attach_assembly(A, user)
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/screwdriver_act(mob/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
||||
return
|
||||
if(toggle_secure())
|
||||
to_chat(user, "<span class='notice'>[src] is ready!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] can now be attached!</span>")
|
||||
|
||||
/obj/item/assembly/process()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/assembly/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(src, user) || loc == user)
|
||||
if(secured)
|
||||
. += "[src] is ready!"
|
||||
else
|
||||
. += "[src] can be attached!"
|
||||
|
||||
/obj/item/assembly/attack_self(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/interact(mob/user)
|
||||
return
|
||||
|
||||
+180
-177
@@ -1,177 +1,180 @@
|
||||
/obj/item/onetankbomb
|
||||
name = "bomb"
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
item_state = "assembly"
|
||||
throwforce = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 4
|
||||
flags = CONDUCT //Copied this from old code, so this may or may not be necessary
|
||||
var/status = 0 //0 - not readied //1 - bomb finished with welder
|
||||
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
origin_tech = "materials=1;engineering=1"
|
||||
|
||||
/obj/item/onetankbomb/examine(mob/user)
|
||||
. = ..()
|
||||
. += bombtank.examine(user)
|
||||
|
||||
/obj/item/onetankbomb/update_icon()
|
||||
if(bombtank)
|
||||
icon_state = bombtank.icon_state
|
||||
if(bombassembly)
|
||||
overlays += bombassembly.icon_state
|
||||
overlays += bombassembly.overlays
|
||||
overlays += "bomb_assembly"
|
||||
|
||||
/obj/item/onetankbomb/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/analyzer))
|
||||
bombtank.attackby(W, user, params)
|
||||
return
|
||||
if(iswrench(W) && !status) //This is basically bomb assembly code inverted. apparently it works.
|
||||
|
||||
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
|
||||
|
||||
bombassembly.loc = user.loc
|
||||
bombassembly.master = null
|
||||
bombassembly = null
|
||||
|
||||
bombtank.loc = user.loc
|
||||
bombtank.master = null
|
||||
bombtank = null
|
||||
|
||||
qdel(src)
|
||||
return
|
||||
if(iswelder(W))
|
||||
var/obj/item/weldingtool/WT = W
|
||||
if(WT.welding)
|
||||
if(!status)
|
||||
status = TRUE
|
||||
investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
|
||||
msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW)
|
||||
log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.</span>")
|
||||
else
|
||||
status = FALSE
|
||||
investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
|
||||
to_chat(user, "<span class='notice'>The hole has been closed.</span>")
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
|
||||
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
|
||||
bombassembly.attack_self(user, 1)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
|
||||
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
sleep(10)
|
||||
if(!src)
|
||||
return
|
||||
if(status)
|
||||
bombtank.detonate() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
|
||||
else
|
||||
bombtank.release()
|
||||
|
||||
/obj/item/onetankbomb/HasProximity(atom/movable/AM)
|
||||
if(bombassembly)
|
||||
bombassembly.HasProximity(AM)
|
||||
|
||||
/obj/item/onetankbomb/Crossed(atom/movable/AM, oldloc) //for mousetraps
|
||||
if(bombassembly)
|
||||
bombassembly.Crossed(AM, oldloc)
|
||||
|
||||
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
|
||||
if(bombassembly)
|
||||
bombassembly.on_found(finder)
|
||||
|
||||
/obj/item/onetankbomb/hear_talk(mob/living/M, list/message_pieces)
|
||||
if(bombassembly)
|
||||
bombassembly.hear_talk(M, message_pieces)
|
||||
|
||||
/obj/item/onetankbomb/hear_message(mob/living/M, msg)
|
||||
if(bombassembly)
|
||||
bombassembly.hear_message(M, msg)
|
||||
|
||||
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
|
||||
|
||||
/obj/item/tank/proc/bomb_assemble(W,user) //Bomb assembly proc. This turns assembly+tank into a bomb
|
||||
var/obj/item/assembly_holder/S = W
|
||||
var/mob/M = user
|
||||
if(!S.secured) //Check if the assembly is secured
|
||||
return
|
||||
if(isigniter(S.a_left) == isigniter(S.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
|
||||
return
|
||||
|
||||
var/obj/item/onetankbomb/R = new /obj/item/onetankbomb(loc)
|
||||
|
||||
M.drop_item() //Remove the assembly from your hands
|
||||
M.remove_from_mob(src) //Remove the tank from your character,in case you were holding it
|
||||
M.put_in_hands(R) //Equips the bomb if possible, or puts it on the floor.
|
||||
|
||||
R.bombassembly = S //Tell the bomb about its assembly part
|
||||
S.master = R //Tell the assembly about its new owner
|
||||
S.loc = R //Move the assembly out of the fucking way
|
||||
|
||||
R.bombtank = src //Same for tank
|
||||
master = R
|
||||
loc = R
|
||||
R.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/tank/proc/detonate() //This happens when a bomb is told to explode
|
||||
var/fuel_moles = air_contents.toxins + air_contents.oxygen/6
|
||||
var/strength = 1
|
||||
|
||||
var/turf/ground_zero = get_turf(loc)
|
||||
loc = null
|
||||
|
||||
if(air_contents.temperature > (T0C + 400))
|
||||
strength = (fuel_moles/15)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1))
|
||||
else if(strength >=0.5)
|
||||
explosion(ground_zero, 0, 1, 2, 4)
|
||||
else if(strength >=0.2)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(air_contents.temperature > (T0C + 250))
|
||||
strength = (fuel_moles/20)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1))
|
||||
else if(strength >=0.5)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(air_contents.temperature > (T0C + 100))
|
||||
strength = (fuel_moles/25)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
air_update_turf()
|
||||
if(master)
|
||||
qdel(master)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
|
||||
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/simulated/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(removed)
|
||||
air_update_turf()
|
||||
/obj/item/onetankbomb
|
||||
name = "bomb"
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
item_state = "assembly"
|
||||
throwforce = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 4
|
||||
flags = CONDUCT //Copied this from old code, so this may or may not be necessary
|
||||
var/status = 0 //0 - not readied //1 - bomb finished with welder
|
||||
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
origin_tech = "materials=1;engineering=1"
|
||||
|
||||
/obj/item/onetankbomb/examine(mob/user)
|
||||
. = ..()
|
||||
. += bombtank.examine(user)
|
||||
|
||||
/obj/item/onetankbomb/update_icon()
|
||||
if(bombtank)
|
||||
icon_state = bombtank.icon_state
|
||||
if(bombassembly)
|
||||
overlays += bombassembly.icon_state
|
||||
overlays += bombassembly.overlays
|
||||
overlays += "bomb_assembly"
|
||||
|
||||
/obj/item/onetankbomb/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/analyzer))
|
||||
bombtank.attackby(W, user, params)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/onetankbomb/wrench_act(mob/user, obj/item/I) //This is basically bomb assembly code inverted. apparently it works.
|
||||
if(status)
|
||||
return
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
|
||||
bombassembly.loc = user.loc
|
||||
bombassembly.master = null
|
||||
bombassembly = null
|
||||
bombtank.loc = user.loc
|
||||
bombtank.master = null
|
||||
bombtank = null
|
||||
qdel(src)
|
||||
|
||||
/obj/item/onetankbomb/welder_act(mob/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, volume = I.tool_volume))
|
||||
return
|
||||
if(!status)
|
||||
status = TRUE
|
||||
investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
|
||||
msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW)
|
||||
log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.</span>")
|
||||
else
|
||||
status = FALSE
|
||||
investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
|
||||
to_chat(user, "<span class='notice'>The hole has been closed.</span>")
|
||||
|
||||
|
||||
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
|
||||
bombassembly.attack_self(user, 1)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
|
||||
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
sleep(10)
|
||||
if(!src)
|
||||
return
|
||||
if(status)
|
||||
bombtank.detonate() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
|
||||
else
|
||||
bombtank.release()
|
||||
|
||||
/obj/item/onetankbomb/HasProximity(atom/movable/AM)
|
||||
if(bombassembly)
|
||||
bombassembly.HasProximity(AM)
|
||||
|
||||
/obj/item/onetankbomb/Crossed(atom/movable/AM, oldloc) //for mousetraps
|
||||
if(bombassembly)
|
||||
bombassembly.Crossed(AM, oldloc)
|
||||
|
||||
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
|
||||
if(bombassembly)
|
||||
bombassembly.on_found(finder)
|
||||
|
||||
/obj/item/onetankbomb/hear_talk(mob/living/M, list/message_pieces)
|
||||
if(bombassembly)
|
||||
bombassembly.hear_talk(M, message_pieces)
|
||||
|
||||
/obj/item/onetankbomb/hear_message(mob/living/M, msg)
|
||||
if(bombassembly)
|
||||
bombassembly.hear_message(M, msg)
|
||||
|
||||
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
|
||||
|
||||
/obj/item/tank/proc/bomb_assemble(W,user) //Bomb assembly proc. This turns assembly+tank into a bomb
|
||||
var/obj/item/assembly_holder/S = W
|
||||
var/mob/M = user
|
||||
if(!S.secured) //Check if the assembly is secured
|
||||
return
|
||||
if(isigniter(S.a_left) == isigniter(S.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
|
||||
return
|
||||
|
||||
var/obj/item/onetankbomb/R = new /obj/item/onetankbomb(loc)
|
||||
|
||||
M.drop_item() //Remove the assembly from your hands
|
||||
M.remove_from_mob(src) //Remove the tank from your character,in case you were holding it
|
||||
M.put_in_hands(R) //Equips the bomb if possible, or puts it on the floor.
|
||||
|
||||
R.bombassembly = S //Tell the bomb about its assembly part
|
||||
S.master = R //Tell the assembly about its new owner
|
||||
S.loc = R //Move the assembly out of the fucking way
|
||||
|
||||
R.bombtank = src //Same for tank
|
||||
master = R
|
||||
loc = R
|
||||
R.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/tank/proc/detonate() //This happens when a bomb is told to explode
|
||||
var/fuel_moles = air_contents.toxins + air_contents.oxygen/6
|
||||
var/strength = 1
|
||||
|
||||
var/turf/ground_zero = get_turf(loc)
|
||||
loc = null
|
||||
|
||||
if(air_contents.temperature > (T0C + 400))
|
||||
strength = (fuel_moles/15)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1))
|
||||
else if(strength >=0.5)
|
||||
explosion(ground_zero, 0, 1, 2, 4)
|
||||
else if(strength >=0.2)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(air_contents.temperature > (T0C + 250))
|
||||
strength = (fuel_moles/20)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1))
|
||||
else if(strength >=0.5)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(air_contents.temperature > (T0C + 100))
|
||||
strength = (fuel_moles/25)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else
|
||||
ground_zero.assume_air(air_contents)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
air_update_turf()
|
||||
if(master)
|
||||
qdel(master)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
|
||||
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/simulated/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(removed)
|
||||
air_update_turf()
|
||||
|
||||
@@ -28,17 +28,16 @@
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/health/attackby(obj/item/W, mob/user)
|
||||
if(ismultitool(W))
|
||||
if(alarm_health == 0)
|
||||
alarm_health = -90
|
||||
user.show_message("You toggle [src] to \"detect death\" mode.")
|
||||
else
|
||||
alarm_health = 0
|
||||
user.show_message("You toggle [src] to \"detect critical state\" mode.")
|
||||
/obj/item/assembly/health/multitool_act(mob/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
||||
return
|
||||
if(alarm_health == 0)
|
||||
alarm_health = -90
|
||||
user.show_message("You toggle [src] to \"detect death\" mode.")
|
||||
else
|
||||
return ..()
|
||||
alarm_health = 0
|
||||
user.show_message("You toggle [src] to \"detect critical state\" mode.")
|
||||
|
||||
/obj/item/assembly/health/process()
|
||||
if(!scanning || !secured)
|
||||
@@ -105,4 +104,4 @@
|
||||
return
|
||||
|
||||
attack_self(user)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
/proc/isassembly(O)
|
||||
if(istype(O, /obj/item/assembly))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/isigniter(O)
|
||||
if(istype(O, /obj/item/assembly/igniter))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/isinfared(O)
|
||||
if(istype(O, /obj/item/assembly/infra))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/isprox(O)
|
||||
if(istype(O, /obj/item/assembly/prox_sensor))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/issignaler(O)
|
||||
if(istype(O, /obj/item/assembly/signaler))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/istimer(O)
|
||||
if(istype(O, /obj/item/assembly/timer))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/*
|
||||
Name: IsSpecialAssembly
|
||||
Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door
|
||||
*/
|
||||
|
||||
/obj/proc/IsSpecialAssembly()
|
||||
return 0
|
||||
|
||||
/*
|
||||
Name: IsAssemblyHolder
|
||||
Desc: If true is an object that can hold an assemblyholder object
|
||||
*/
|
||||
/obj/proc/IsAssemblyHolder()
|
||||
return 0
|
||||
/proc/isassembly(O)
|
||||
if(istype(O, /obj/item/assembly))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/isigniter(O)
|
||||
if(istype(O, /obj/item/assembly/igniter))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/isinfared(O)
|
||||
if(istype(O, /obj/item/assembly/infra))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/isprox(O)
|
||||
if(istype(O, /obj/item/assembly/prox_sensor))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/issignaler(O)
|
||||
if(istype(O, /obj/item/assembly/signaler))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/istimer(O)
|
||||
if(istype(O, /obj/item/assembly/timer))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/*
|
||||
Name: IsSpecialAssembly
|
||||
Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door
|
||||
*/
|
||||
|
||||
/obj/proc/IsSpecialAssembly()
|
||||
return 0
|
||||
|
||||
/*
|
||||
Name: IsAssemblyHolder
|
||||
Desc: If true is an object that can hold an assemblyholder object
|
||||
*/
|
||||
/obj/proc/IsAssemblyHolder()
|
||||
return 0
|
||||
|
||||
+197
-200
@@ -1,200 +1,197 @@
|
||||
/obj/item/assembly_holder
|
||||
name = "Assembly"
|
||||
icon = 'icons/obj/assemblies/new_assemblies.dmi'
|
||||
icon_state = "holder"
|
||||
item_state = "assembly"
|
||||
flags = CONDUCT
|
||||
throwforce = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throw_speed = 3
|
||||
throw_range = 10
|
||||
|
||||
var/secured = FALSE
|
||||
var/obj/item/assembly/a_left = null
|
||||
var/obj/item/assembly/a_right = null
|
||||
|
||||
/obj/item/assembly_holder/proc/attach(obj/item/D, obj/item/D2, mob/user)
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/proc/process_activation(var/obj/item/D)
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/IsAssemblyHolder()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly_holder/Destroy()
|
||||
if(a_left)
|
||||
a_left.holder = null
|
||||
if(a_right)
|
||||
a_right.holder = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly_holder/attach(obj/item/D, obj/item/D2, mob/user)
|
||||
if(!D || !D2)
|
||||
return FALSE
|
||||
if(!isassembly(D) || !isassembly(D2))
|
||||
return FALSE
|
||||
var/obj/item/assembly/A1 = D
|
||||
var/obj/item/assembly/A2 = D2
|
||||
if(A1.secured || A2.secured)
|
||||
return FALSE
|
||||
if(!A1.remove_item_from_storage(src))
|
||||
if(user)
|
||||
user.remove_from_mob(A1)
|
||||
A1.loc = src
|
||||
if(!A2.remove_item_from_storage(src))
|
||||
if(user)
|
||||
user.remove_from_mob(A2)
|
||||
A2.loc = src
|
||||
A1.holder = src
|
||||
A2.holder = src
|
||||
a_left = A1
|
||||
a_right = A2
|
||||
name = "[A1.name]-[A2.name] assembly"
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly_holder/update_icon()
|
||||
overlays.Cut()
|
||||
if(a_left)
|
||||
overlays += "[a_left.icon_state]_left"
|
||||
for(var/O in a_left.attached_overlays)
|
||||
overlays += "[O]_l"
|
||||
if(a_right)
|
||||
overlays += "[a_right.icon_state]_right"
|
||||
for(var/O in a_right.attached_overlays)
|
||||
overlays += "[O]_r"
|
||||
if(master)
|
||||
master.update_icon()
|
||||
|
||||
|
||||
/obj/item/assembly_holder/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(src, user) || loc == user)
|
||||
if(secured)
|
||||
. += "[src] is ready!"
|
||||
else
|
||||
. += "[src] can be attached!"
|
||||
|
||||
|
||||
/obj/item/assembly_holder/HasProximity(atom/movable/AM)
|
||||
if(a_left)
|
||||
a_left.HasProximity(AM)
|
||||
if(a_right)
|
||||
a_right.HasProximity(AM)
|
||||
|
||||
|
||||
/obj/item/assembly_holder/Crossed(atom/movable/AM, oldloc)
|
||||
if(a_left)
|
||||
a_left.Crossed(AM, oldloc)
|
||||
if(a_right)
|
||||
a_right.Crossed(AM, oldloc)
|
||||
|
||||
/obj/item/assembly_holder/on_found(mob/finder)
|
||||
if(a_left)
|
||||
a_left.on_found(finder)
|
||||
if(a_right)
|
||||
a_right.on_found(finder)
|
||||
|
||||
|
||||
/obj/item/assembly_holder/hear_talk(mob/living/M, list/message_pieces)
|
||||
if(a_left)
|
||||
a_left.hear_talk(M, message_pieces)
|
||||
if(a_right)
|
||||
a_right.hear_talk(M, message_pieces)
|
||||
|
||||
/obj/item/assembly_holder/hear_message(mob/living/M, msg)
|
||||
if(a_left)
|
||||
a_left.hear_message(M, msg)
|
||||
if(a_right)
|
||||
a_right.hear_message(M, msg)
|
||||
|
||||
/obj/item/assembly_holder/proc/process_movement() // infrared beams and prox sensors
|
||||
if(a_left && a_right)
|
||||
a_left.holder_movement()
|
||||
a_right.holder_movement()
|
||||
|
||||
/obj/item/assembly_holder/Move()
|
||||
. = ..()
|
||||
process_movement()
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/pickup()
|
||||
. = ..()
|
||||
process_movement()
|
||||
|
||||
/obj/item/assembly_holder/Bump()
|
||||
..()
|
||||
process_movement()
|
||||
|
||||
/obj/item/assembly_holder/throw_impact() // called when a throw stops
|
||||
..()
|
||||
process_movement()
|
||||
|
||||
/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
|
||||
if(a_left && a_right)
|
||||
a_left.holder_movement()
|
||||
a_right.holder_movement()
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/attackby(obj/item/W, mob/user, params)
|
||||
if(isscrewdriver(W))
|
||||
if(!a_left || !a_right)
|
||||
to_chat(user, "<span class='warning'>BUG:Assembly part missing, please report this!</span>")
|
||||
return
|
||||
a_left.toggle_secure()
|
||||
a_right.toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
to_chat(user, "<span class='notice'>[src] is ready!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] can now be taken apart!</span>")
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/assembly_holder/attack_self(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(secured)
|
||||
if(!a_left || !a_right)
|
||||
to_chat(user, "<span class='warning'>Assembly part missing!</span>")
|
||||
return
|
||||
if(istype(a_left, a_right.type))//If they are the same type it causes issues due to window code
|
||||
switch(alert("Which side would you like to use?",,"Left","Right"))
|
||||
if("Left")
|
||||
a_left.attack_self(user)
|
||||
if("Right")
|
||||
a_right.attack_self(user)
|
||||
return
|
||||
else
|
||||
a_left.attack_self(user)
|
||||
a_right.attack_self(user)
|
||||
else
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return FALSE
|
||||
if(a_left)
|
||||
a_left.holder = null
|
||||
a_left.loc = T
|
||||
if(a_right)
|
||||
a_right.holder = null
|
||||
a_right.loc = T
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/assembly_holder/process_activation(obj/D, normal = TRUE, special = TRUE)
|
||||
if(!D)
|
||||
return FALSE
|
||||
if(normal && a_right && a_left)
|
||||
if(a_right != D)
|
||||
a_right.pulsed(0)
|
||||
if(a_left != D)
|
||||
a_left.pulsed(0)
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return TRUE
|
||||
/obj/item/assembly_holder
|
||||
name = "Assembly"
|
||||
icon = 'icons/obj/assemblies/new_assemblies.dmi'
|
||||
icon_state = "holder"
|
||||
item_state = "assembly"
|
||||
flags = CONDUCT
|
||||
throwforce = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throw_speed = 3
|
||||
throw_range = 10
|
||||
|
||||
var/secured = FALSE
|
||||
var/obj/item/assembly/a_left = null
|
||||
var/obj/item/assembly/a_right = null
|
||||
|
||||
/obj/item/assembly_holder/proc/attach(obj/item/D, obj/item/D2, mob/user)
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/proc/process_activation(var/obj/item/D)
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/IsAssemblyHolder()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly_holder/Destroy()
|
||||
if(a_left)
|
||||
a_left.holder = null
|
||||
if(a_right)
|
||||
a_right.holder = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly_holder/attach(obj/item/D, obj/item/D2, mob/user)
|
||||
if(!D || !D2)
|
||||
return FALSE
|
||||
if(!isassembly(D) || !isassembly(D2))
|
||||
return FALSE
|
||||
var/obj/item/assembly/A1 = D
|
||||
var/obj/item/assembly/A2 = D2
|
||||
if(A1.secured || A2.secured)
|
||||
return FALSE
|
||||
if(!A1.remove_item_from_storage(src))
|
||||
if(user)
|
||||
user.remove_from_mob(A1)
|
||||
A1.loc = src
|
||||
if(!A2.remove_item_from_storage(src))
|
||||
if(user)
|
||||
user.remove_from_mob(A2)
|
||||
A2.loc = src
|
||||
A1.holder = src
|
||||
A2.holder = src
|
||||
a_left = A1
|
||||
a_right = A2
|
||||
name = "[A1.name]-[A2.name] assembly"
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly_holder/update_icon()
|
||||
overlays.Cut()
|
||||
if(a_left)
|
||||
overlays += "[a_left.icon_state]_left"
|
||||
for(var/O in a_left.attached_overlays)
|
||||
overlays += "[O]_l"
|
||||
if(a_right)
|
||||
overlays += "[a_right.icon_state]_right"
|
||||
for(var/O in a_right.attached_overlays)
|
||||
overlays += "[O]_r"
|
||||
if(master)
|
||||
master.update_icon()
|
||||
|
||||
|
||||
/obj/item/assembly_holder/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(src, user) || loc == user)
|
||||
if(secured)
|
||||
. += "[src] is ready!"
|
||||
else
|
||||
. += "[src] can be attached!"
|
||||
|
||||
|
||||
/obj/item/assembly_holder/HasProximity(atom/movable/AM)
|
||||
if(a_left)
|
||||
a_left.HasProximity(AM)
|
||||
if(a_right)
|
||||
a_right.HasProximity(AM)
|
||||
|
||||
|
||||
/obj/item/assembly_holder/Crossed(atom/movable/AM, oldloc)
|
||||
if(a_left)
|
||||
a_left.Crossed(AM, oldloc)
|
||||
if(a_right)
|
||||
a_right.Crossed(AM, oldloc)
|
||||
|
||||
/obj/item/assembly_holder/on_found(mob/finder)
|
||||
if(a_left)
|
||||
a_left.on_found(finder)
|
||||
if(a_right)
|
||||
a_right.on_found(finder)
|
||||
|
||||
|
||||
/obj/item/assembly_holder/hear_talk(mob/living/M, list/message_pieces)
|
||||
if(a_left)
|
||||
a_left.hear_talk(M, message_pieces)
|
||||
if(a_right)
|
||||
a_right.hear_talk(M, message_pieces)
|
||||
|
||||
/obj/item/assembly_holder/hear_message(mob/living/M, msg)
|
||||
if(a_left)
|
||||
a_left.hear_message(M, msg)
|
||||
if(a_right)
|
||||
a_right.hear_message(M, msg)
|
||||
|
||||
/obj/item/assembly_holder/proc/process_movement() // infrared beams and prox sensors
|
||||
if(a_left && a_right)
|
||||
a_left.holder_movement()
|
||||
a_right.holder_movement()
|
||||
|
||||
/obj/item/assembly_holder/Move()
|
||||
. = ..()
|
||||
process_movement()
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/pickup()
|
||||
. = ..()
|
||||
process_movement()
|
||||
|
||||
/obj/item/assembly_holder/Bump()
|
||||
..()
|
||||
process_movement()
|
||||
|
||||
/obj/item/assembly_holder/throw_impact() // called when a throw stops
|
||||
..()
|
||||
process_movement()
|
||||
|
||||
/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
|
||||
if(a_left && a_right)
|
||||
a_left.holder_movement()
|
||||
a_right.holder_movement()
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/I)
|
||||
if(!a_left || !a_right)
|
||||
to_chat(user, "<span class='warning'>BUG:Assembly part missing, please report this!</span>")
|
||||
return
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
||||
return
|
||||
a_left.toggle_secure()
|
||||
a_right.toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
to_chat(user, "<span class='notice'>[src] is ready!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] can now be taken apart!</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/assembly_holder/attack_self(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(secured)
|
||||
if(!a_left || !a_right)
|
||||
to_chat(user, "<span class='warning'>Assembly part missing!</span>")
|
||||
return
|
||||
if(istype(a_left, a_right.type))//If they are the same type it causes issues due to window code
|
||||
switch(alert("Which side would you like to use?",,"Left","Right"))
|
||||
if("Left")
|
||||
a_left.attack_self(user)
|
||||
if("Right")
|
||||
a_right.attack_self(user)
|
||||
return
|
||||
else
|
||||
a_left.attack_self(user)
|
||||
a_right.attack_self(user)
|
||||
else
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return FALSE
|
||||
if(a_left)
|
||||
a_left.holder = null
|
||||
a_left.loc = T
|
||||
if(a_right)
|
||||
a_right.holder = null
|
||||
a_right.loc = T
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/assembly_holder/process_activation(obj/D, normal = TRUE, special = TRUE)
|
||||
if(!D)
|
||||
return FALSE
|
||||
if(normal && a_right && a_left)
|
||||
if(a_right != D)
|
||||
a_right.pulsed(0)
|
||||
if(a_left != D)
|
||||
a_left.pulsed(0)
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return TRUE
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
/obj/item/assembly/igniter
|
||||
name = "igniter"
|
||||
desc = "A small electronic device able to ignite combustable substances."
|
||||
icon_state = "igniter"
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
origin_tech = "magnets=1"
|
||||
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
|
||||
|
||||
/obj/item/assembly/igniter/New()
|
||||
..()
|
||||
sparks.set_up(2, 0, src)
|
||||
sparks.attach(src)
|
||||
|
||||
/obj/item/assembly/igniter/Destroy()
|
||||
QDEL_NULL(sparks)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/describe()
|
||||
return "The igniter is [secured ? "secured." : "unsecured."]"
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
var/turf/location = get_turf(loc)
|
||||
if(location)
|
||||
location.hotspot_expose(1000,1000)
|
||||
if(istype(loc, /obj/item/assembly_holder))
|
||||
if(istype(loc.loc, /obj/structure/reagent_dispensers/fueltank))
|
||||
var/obj/structure/reagent_dispensers/fueltank/tank = loc.loc
|
||||
if(tank)
|
||||
tank.boom(TRUE)
|
||||
if(istype(loc.loc, /obj/item/reagent_containers/glass/beaker))
|
||||
var/obj/item/reagent_containers/glass/beaker/beakerbomb = loc.loc
|
||||
if(beakerbomb)
|
||||
beakerbomb.heat_beaker()
|
||||
sparks.start()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/attack_self(mob/user)
|
||||
activate()
|
||||
add_fingerprint(user)
|
||||
return
|
||||
/obj/item/assembly/igniter
|
||||
name = "igniter"
|
||||
desc = "A small electronic device able to ignite combustable substances."
|
||||
icon_state = "igniter"
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
origin_tech = "magnets=1"
|
||||
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
|
||||
|
||||
/obj/item/assembly/igniter/New()
|
||||
..()
|
||||
sparks.set_up(2, 0, src)
|
||||
sparks.attach(src)
|
||||
|
||||
/obj/item/assembly/igniter/Destroy()
|
||||
QDEL_NULL(sparks)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/describe()
|
||||
return "The igniter is [secured ? "secured." : "unsecured."]"
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
var/turf/location = get_turf(loc)
|
||||
if(location)
|
||||
location.hotspot_expose(1000,1000)
|
||||
if(istype(loc, /obj/item/assembly_holder))
|
||||
if(istype(loc.loc, /obj/structure/reagent_dispensers/fueltank))
|
||||
var/obj/structure/reagent_dispensers/fueltank/tank = loc.loc
|
||||
if(tank)
|
||||
tank.boom(TRUE)
|
||||
if(istype(loc.loc, /obj/item/reagent_containers/glass/beaker))
|
||||
var/obj/item/reagent_containers/glass/beaker/beakerbomb = loc.loc
|
||||
if(beakerbomb)
|
||||
beakerbomb.heat_beaker()
|
||||
sparks.start()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/attack_self(mob/user)
|
||||
activate()
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
+286
-286
@@ -1,286 +1,286 @@
|
||||
/obj/item/assembly/infra
|
||||
name = "infrared emitter"
|
||||
desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted."
|
||||
icon_state = "infrared"
|
||||
materials = list(MAT_METAL=1000, MAT_GLASS=500)
|
||||
origin_tech = "magnets=2;materials=2"
|
||||
|
||||
bomb_name = "tripwire mine"
|
||||
|
||||
secured = FALSE // toggle_secure()'ed in New() for correct adding to processing_objects, won't work otherwise
|
||||
dir = EAST
|
||||
var/on = FALSE
|
||||
var/visible = TRUE
|
||||
var/obj/effect/beam/i_beam/first = null
|
||||
var/obj/effect/beam/i_beam/last = null
|
||||
var/max_nesting_level = 10
|
||||
var/turf/fire_location
|
||||
var/emission_cycles = 0
|
||||
var/emission_cap = 20
|
||||
|
||||
/obj/item/assembly/infra/Destroy()
|
||||
if(first)
|
||||
QDEL_NULL(first)
|
||||
last = null
|
||||
fire_location = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/infra/describe()
|
||||
return "The assembly is [secured ? "secure" : "not secure"]. The infrared trigger is [on ? "on" : "off"]."
|
||||
|
||||
/obj/item/assembly/infra/examine(mob/user)
|
||||
. = ..()
|
||||
. += describe()
|
||||
|
||||
/obj/item/assembly/infra/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
on = !on
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/infra/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
on = FALSE
|
||||
if(first)
|
||||
qdel(first)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/infra/New()
|
||||
..()
|
||||
if(!secured)
|
||||
toggle_secure()
|
||||
|
||||
/obj/item/assembly/infra/proc/arm() // Forces the device to arm no matter its current state.
|
||||
if(!secured) // Checked because arm() might be called sometime after the object is spawned.
|
||||
toggle_secure()
|
||||
on = 1
|
||||
|
||||
/obj/item/assembly/infra/update_icon()
|
||||
overlays.Cut()
|
||||
attached_overlays = list()
|
||||
if(on)
|
||||
overlays += "infrared_on"
|
||||
attached_overlays += "infrared_on"
|
||||
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/infra/process()
|
||||
var/turf/T = get_turf(src)
|
||||
if(first && (!on || !fire_location || fire_location != T || emission_cycles >= emission_cap))
|
||||
qdel(first)
|
||||
return
|
||||
if(!on)
|
||||
return
|
||||
if(!secured)
|
||||
return
|
||||
if(first && last)
|
||||
last.process()
|
||||
emission_cycles++
|
||||
return
|
||||
if(T)
|
||||
fire_location = T
|
||||
emission_cycles = 0
|
||||
var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(T)
|
||||
I.master = src
|
||||
I.density = 1
|
||||
I.dir = dir
|
||||
I.update_icon()
|
||||
first = I
|
||||
step(I, I.dir)
|
||||
if(first)
|
||||
I.density = FALSE
|
||||
I.vis_spread(visible)
|
||||
I.limit = 8
|
||||
I.process()
|
||||
|
||||
/obj/item/assembly/infra/attack_hand()
|
||||
qdel(first)
|
||||
..()
|
||||
|
||||
/obj/item/assembly/infra/Move()
|
||||
var/t = dir
|
||||
. = ..()
|
||||
dir = t
|
||||
qdel(first)
|
||||
|
||||
/obj/item/assembly/infra/holder_movement()
|
||||
if(!holder)
|
||||
return FALSE
|
||||
qdel(first)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/infra/equipped(var/mob/user, var/slot)
|
||||
qdel(first)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/infra/pickup(mob/user)
|
||||
qdel(first)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/infra/proc/trigger_beam()
|
||||
if(!secured || !on || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
audible_message("[bicon(src)] *beep* *beep*", null, 3)
|
||||
if(first)
|
||||
qdel(first)
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
/obj/item/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel
|
||||
if(!secured) return
|
||||
user.set_machine(src)
|
||||
var/dat = {"<TT><B>Infrared Laser</B>
|
||||
<B>Status</B>: [on ? "<A href='?src=[UID()];state=0'>On</A>" : "<A href='?src=[UID()];state=1'>Off</A>"]<BR>
|
||||
<B>Visibility</B>: [visible ? "<A href='?src=[UID()];visible=0'>Visible</A>" : "<A href='?src=[UID()];visible=1'>Invisible</A>"]<BR>
|
||||
<B>Current Direction</B>: <A href='?src=[UID()];rotate=1'>[capitalize(dir2text(dir))]</A><BR>
|
||||
</TT>
|
||||
<BR><BR><A href='?src=[UID()];refresh=1'>Refresh</A>
|
||||
<BR><BR><A href='?src=[UID()];close=1'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "infra", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "infra")
|
||||
|
||||
/obj/item/assembly/infra/Topic(href, href_list)
|
||||
..()
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=infra")
|
||||
onclose(usr, "infra")
|
||||
return
|
||||
if(href_list["state"])
|
||||
on = !(on)
|
||||
update_icon()
|
||||
if(href_list["visible"])
|
||||
visible = !(visible)
|
||||
if(first)
|
||||
first.vis_spread(visible)
|
||||
if(href_list["rotate"])
|
||||
rotate()
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=infra")
|
||||
return
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/assembly/infra/verb/rotate()//This could likely be better
|
||||
set name = "Rotate Infrared Laser"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
|
||||
if(usr.stat || !usr.canmove || usr.restrained())
|
||||
return
|
||||
|
||||
dir = turn(dir, 90)
|
||||
|
||||
if(usr.machine == src)
|
||||
interact(usr)
|
||||
|
||||
if(first)
|
||||
qdel(first)
|
||||
|
||||
|
||||
|
||||
/obj/item/assembly/infra/armed/New()
|
||||
..()
|
||||
spawn(3)
|
||||
if(holder)
|
||||
if(holder.master)
|
||||
dir = holder.master.dir
|
||||
arm()
|
||||
|
||||
/obj/item/assembly/infra/armed/stealth
|
||||
visible = FALSE
|
||||
|
||||
|
||||
/***************************IBeam*********************************/
|
||||
|
||||
/obj/effect/beam/i_beam
|
||||
name = "i beam"
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "ibeam"
|
||||
var/obj/effect/beam/i_beam/next = null
|
||||
var/obj/effect/beam/i_beam/previous = null
|
||||
var/obj/item/assembly/infra/master = null
|
||||
var/limit = null
|
||||
var/visible = FALSE
|
||||
var/left = null
|
||||
var/life_cycles = 0
|
||||
var/life_cap = 20
|
||||
anchored = TRUE
|
||||
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
|
||||
|
||||
|
||||
/obj/effect/beam/i_beam/proc/hit()
|
||||
if(master)
|
||||
master.trigger_beam()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/beam/i_beam/proc/vis_spread(v)
|
||||
visible = v
|
||||
if(next)
|
||||
next.vis_spread(v)
|
||||
|
||||
/obj/effect/beam/i_beam/update_icon()
|
||||
transform = turn(matrix(), dir2angle(dir))
|
||||
|
||||
/obj/effect/beam/i_beam/process()
|
||||
life_cycles++
|
||||
if(loc.density || !master || life_cycles >= life_cap)
|
||||
qdel(src)
|
||||
return
|
||||
if(left > 0)
|
||||
left--
|
||||
if(left < 1)
|
||||
if(!(visible))
|
||||
invisibility = 101
|
||||
else
|
||||
invisibility = FALSE
|
||||
else
|
||||
invisibility = FALSE
|
||||
|
||||
if(!next && (limit > 0))
|
||||
var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(loc)
|
||||
I.master = master
|
||||
I.density = 1
|
||||
I.dir = dir
|
||||
I.update_icon()
|
||||
I.previous = src
|
||||
next = I
|
||||
step(I, I.dir)
|
||||
if(next)
|
||||
I.density = FALSE
|
||||
I.vis_spread(visible)
|
||||
I.limit = limit - 1
|
||||
master.last = I
|
||||
I.process()
|
||||
|
||||
/obj/effect/beam/i_beam/Bump()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/beam/i_beam/Bumped()
|
||||
hit()
|
||||
|
||||
/obj/effect/beam/i_beam/Crossed(atom/movable/AM, oldloc)
|
||||
if(!isobj(AM) && !isliving(AM))
|
||||
return
|
||||
if(istype(AM, /obj/effect))
|
||||
return
|
||||
hit()
|
||||
|
||||
/obj/effect/beam/i_beam/Destroy()
|
||||
if(master.first == src)
|
||||
master.first = null
|
||||
QDEL_NULL(next)
|
||||
if(previous)
|
||||
previous.next = null
|
||||
master.last = previous
|
||||
return ..()
|
||||
/obj/item/assembly/infra
|
||||
name = "infrared emitter"
|
||||
desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted."
|
||||
icon_state = "infrared"
|
||||
materials = list(MAT_METAL=1000, MAT_GLASS=500)
|
||||
origin_tech = "magnets=2;materials=2"
|
||||
|
||||
bomb_name = "tripwire mine"
|
||||
|
||||
secured = FALSE // toggle_secure()'ed in New() for correct adding to processing_objects, won't work otherwise
|
||||
dir = EAST
|
||||
var/on = FALSE
|
||||
var/visible = TRUE
|
||||
var/obj/effect/beam/i_beam/first = null
|
||||
var/obj/effect/beam/i_beam/last = null
|
||||
var/max_nesting_level = 10
|
||||
var/turf/fire_location
|
||||
var/emission_cycles = 0
|
||||
var/emission_cap = 20
|
||||
|
||||
/obj/item/assembly/infra/Destroy()
|
||||
if(first)
|
||||
QDEL_NULL(first)
|
||||
last = null
|
||||
fire_location = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/infra/describe()
|
||||
return "The assembly is [secured ? "secure" : "not secure"]. The infrared trigger is [on ? "on" : "off"]."
|
||||
|
||||
/obj/item/assembly/infra/examine(mob/user)
|
||||
. = ..()
|
||||
. += describe()
|
||||
|
||||
/obj/item/assembly/infra/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
on = !on
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/infra/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
on = FALSE
|
||||
if(first)
|
||||
qdel(first)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/infra/New()
|
||||
..()
|
||||
if(!secured)
|
||||
toggle_secure()
|
||||
|
||||
/obj/item/assembly/infra/proc/arm() // Forces the device to arm no matter its current state.
|
||||
if(!secured) // Checked because arm() might be called sometime after the object is spawned.
|
||||
toggle_secure()
|
||||
on = 1
|
||||
|
||||
/obj/item/assembly/infra/update_icon()
|
||||
overlays.Cut()
|
||||
attached_overlays = list()
|
||||
if(on)
|
||||
overlays += "infrared_on"
|
||||
attached_overlays += "infrared_on"
|
||||
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/infra/process()
|
||||
var/turf/T = get_turf(src)
|
||||
if(first && (!on || !fire_location || fire_location != T || emission_cycles >= emission_cap))
|
||||
qdel(first)
|
||||
return
|
||||
if(!on)
|
||||
return
|
||||
if(!secured)
|
||||
return
|
||||
if(first && last)
|
||||
last.process()
|
||||
emission_cycles++
|
||||
return
|
||||
if(T)
|
||||
fire_location = T
|
||||
emission_cycles = 0
|
||||
var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(T)
|
||||
I.master = src
|
||||
I.density = 1
|
||||
I.dir = dir
|
||||
I.update_icon()
|
||||
first = I
|
||||
step(I, I.dir)
|
||||
if(first)
|
||||
I.density = FALSE
|
||||
I.vis_spread(visible)
|
||||
I.limit = 8
|
||||
I.process()
|
||||
|
||||
/obj/item/assembly/infra/attack_hand()
|
||||
qdel(first)
|
||||
..()
|
||||
|
||||
/obj/item/assembly/infra/Move()
|
||||
var/t = dir
|
||||
. = ..()
|
||||
dir = t
|
||||
qdel(first)
|
||||
|
||||
/obj/item/assembly/infra/holder_movement()
|
||||
if(!holder)
|
||||
return FALSE
|
||||
qdel(first)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/infra/equipped(var/mob/user, var/slot)
|
||||
qdel(first)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/infra/pickup(mob/user)
|
||||
qdel(first)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/infra/proc/trigger_beam()
|
||||
if(!secured || !on || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
audible_message("[bicon(src)] *beep* *beep*", null, 3)
|
||||
if(first)
|
||||
qdel(first)
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
/obj/item/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel
|
||||
if(!secured) return
|
||||
user.set_machine(src)
|
||||
var/dat = {"<TT><B>Infrared Laser</B>
|
||||
<B>Status</B>: [on ? "<A href='?src=[UID()];state=0'>On</A>" : "<A href='?src=[UID()];state=1'>Off</A>"]<BR>
|
||||
<B>Visibility</B>: [visible ? "<A href='?src=[UID()];visible=0'>Visible</A>" : "<A href='?src=[UID()];visible=1'>Invisible</A>"]<BR>
|
||||
<B>Current Direction</B>: <A href='?src=[UID()];rotate=1'>[capitalize(dir2text(dir))]</A><BR>
|
||||
</TT>
|
||||
<BR><BR><A href='?src=[UID()];refresh=1'>Refresh</A>
|
||||
<BR><BR><A href='?src=[UID()];close=1'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "infra", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "infra")
|
||||
|
||||
/obj/item/assembly/infra/Topic(href, href_list)
|
||||
..()
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=infra")
|
||||
onclose(usr, "infra")
|
||||
return
|
||||
if(href_list["state"])
|
||||
on = !(on)
|
||||
update_icon()
|
||||
if(href_list["visible"])
|
||||
visible = !(visible)
|
||||
if(first)
|
||||
first.vis_spread(visible)
|
||||
if(href_list["rotate"])
|
||||
rotate()
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=infra")
|
||||
return
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/assembly/infra/verb/rotate()//This could likely be better
|
||||
set name = "Rotate Infrared Laser"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
|
||||
if(usr.stat || !usr.canmove || usr.restrained())
|
||||
return
|
||||
|
||||
dir = turn(dir, 90)
|
||||
|
||||
if(usr.machine == src)
|
||||
interact(usr)
|
||||
|
||||
if(first)
|
||||
qdel(first)
|
||||
|
||||
|
||||
|
||||
/obj/item/assembly/infra/armed/New()
|
||||
..()
|
||||
spawn(3)
|
||||
if(holder)
|
||||
if(holder.master)
|
||||
dir = holder.master.dir
|
||||
arm()
|
||||
|
||||
/obj/item/assembly/infra/armed/stealth
|
||||
visible = FALSE
|
||||
|
||||
|
||||
/***************************IBeam*********************************/
|
||||
|
||||
/obj/effect/beam/i_beam
|
||||
name = "i beam"
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "ibeam"
|
||||
var/obj/effect/beam/i_beam/next = null
|
||||
var/obj/effect/beam/i_beam/previous = null
|
||||
var/obj/item/assembly/infra/master = null
|
||||
var/limit = null
|
||||
var/visible = FALSE
|
||||
var/left = null
|
||||
var/life_cycles = 0
|
||||
var/life_cap = 20
|
||||
anchored = TRUE
|
||||
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
|
||||
|
||||
|
||||
/obj/effect/beam/i_beam/proc/hit()
|
||||
if(master)
|
||||
master.trigger_beam()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/beam/i_beam/proc/vis_spread(v)
|
||||
visible = v
|
||||
if(next)
|
||||
next.vis_spread(v)
|
||||
|
||||
/obj/effect/beam/i_beam/update_icon()
|
||||
transform = turn(matrix(), dir2angle(dir))
|
||||
|
||||
/obj/effect/beam/i_beam/process()
|
||||
life_cycles++
|
||||
if(loc.density || !master || life_cycles >= life_cap)
|
||||
qdel(src)
|
||||
return
|
||||
if(left > 0)
|
||||
left--
|
||||
if(left < 1)
|
||||
if(!(visible))
|
||||
invisibility = 101
|
||||
else
|
||||
invisibility = FALSE
|
||||
else
|
||||
invisibility = FALSE
|
||||
|
||||
if(!next && (limit > 0))
|
||||
var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(loc)
|
||||
I.master = master
|
||||
I.density = 1
|
||||
I.dir = dir
|
||||
I.update_icon()
|
||||
I.previous = src
|
||||
next = I
|
||||
step(I, I.dir)
|
||||
if(next)
|
||||
I.density = FALSE
|
||||
I.vis_spread(visible)
|
||||
I.limit = limit - 1
|
||||
master.last = I
|
||||
I.process()
|
||||
|
||||
/obj/effect/beam/i_beam/Bump()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/beam/i_beam/Bumped()
|
||||
hit()
|
||||
|
||||
/obj/effect/beam/i_beam/Crossed(atom/movable/AM, oldloc)
|
||||
if(!isobj(AM) && !isliving(AM))
|
||||
return
|
||||
if(istype(AM, /obj/effect))
|
||||
return
|
||||
hit()
|
||||
|
||||
/obj/effect/beam/i_beam/Destroy()
|
||||
if(master.first == src)
|
||||
master.first = null
|
||||
QDEL_NULL(next)
|
||||
if(previous)
|
||||
previous.next = null
|
||||
master.last = previous
|
||||
return ..()
|
||||
|
||||
+144
-144
@@ -1,144 +1,144 @@
|
||||
/obj/item/assembly/mousetrap
|
||||
name = "mousetrap"
|
||||
desc = "A handy little spring-loaded trap for catching pesty rodents."
|
||||
icon_state = "mousetrap"
|
||||
materials = list(MAT_METAL=100)
|
||||
origin_tech = "combat=1;materials=2;engineering=1"
|
||||
var/armed = FALSE
|
||||
|
||||
bomb_name = "contact mine"
|
||||
|
||||
/obj/item/assembly/mousetrap/examine(mob/user)
|
||||
. = ..()
|
||||
if(armed)
|
||||
. += "It looks like it's armed."
|
||||
|
||||
/obj/item/assembly/mousetrap/activate()
|
||||
if(..())
|
||||
armed = !armed
|
||||
if(!armed)
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))
|
||||
to_chat(user, "Your hand slips, setting off the trigger.")
|
||||
pulse(0)
|
||||
update_icon()
|
||||
if(usr)
|
||||
playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
|
||||
|
||||
/obj/item/assembly/mousetrap/describe()
|
||||
return "The pressure switch is [armed ? "primed" : "safe"]."
|
||||
|
||||
/obj/item/assembly/mousetrap/update_icon()
|
||||
if(armed)
|
||||
icon_state = "mousetraparmed"
|
||||
else
|
||||
icon_state = "mousetrap"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/mousetrap/proc/triggered(mob/target, type = "feet")
|
||||
if(!armed)
|
||||
return
|
||||
var/obj/item/organ/external/affecting = null
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(PIERCEIMMUNE in H.dna.species.species_traits)
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
|
||||
armed = FALSE
|
||||
update_icon()
|
||||
pulse(FALSE)
|
||||
return FALSE
|
||||
switch(type)
|
||||
if("feet")
|
||||
if(!H.shoes)
|
||||
affecting = H.get_organ(pick("l_leg", "r_leg"))
|
||||
H.Weaken(3)
|
||||
if("l_hand", "r_hand")
|
||||
if(!H.gloves)
|
||||
affecting = H.get_organ(type)
|
||||
H.Stun(3)
|
||||
if(affecting)
|
||||
affecting.receive_damage(1, 0)
|
||||
else if(ismouse(target))
|
||||
var/mob/living/simple_animal/mouse/M = target
|
||||
visible_message("<span class='danger'>SPLAT!</span>")
|
||||
M.splat()
|
||||
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
layer = MOB_LAYER - 0.2
|
||||
armed = FALSE
|
||||
update_icon()
|
||||
pulse(0)
|
||||
|
||||
/obj/item/assembly/mousetrap/attack_self(mob/living/user)
|
||||
if(!armed)
|
||||
to_chat(user, "<span class='notice'>You arm [src].</span>")
|
||||
else
|
||||
if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))
|
||||
var/which_hand = "l_hand"
|
||||
if(!user.hand)
|
||||
which_hand = "r_hand"
|
||||
triggered(user, which_hand)
|
||||
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking [user.p_their()] fingers.</span>", \
|
||||
"<span class='warning'>You accidentally trigger [src]!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You disarm [src].</span>")
|
||||
armed = !armed
|
||||
update_icon()
|
||||
playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
|
||||
|
||||
/obj/item/assembly/mousetrap/attack_hand(mob/living/user)
|
||||
if(armed)
|
||||
if((user.getBrainLoss() >= 60 || CLUMSY in user.mutations) && prob(50))
|
||||
var/which_hand = "l_hand"
|
||||
if(!user.hand)
|
||||
which_hand = "r_hand"
|
||||
triggered(user, which_hand)
|
||||
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking [user.p_their()] fingers.</span>", \
|
||||
"<span class='warning'>You accidentally trigger [src]!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/assembly/mousetrap/Crossed(atom/movable/AM, oldloc)
|
||||
if(armed)
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/H = AM
|
||||
if(H.m_intent == MOVE_INTENT_RUN)
|
||||
triggered(H)
|
||||
H.visible_message("<span class='warning'>[H] accidentally steps on [src].</span>", \
|
||||
"<span class='warning'>You accidentally step on [src]</span>")
|
||||
else if(ismouse(AM))
|
||||
triggered(AM)
|
||||
else if(AM.density) // For mousetrap grenades, set off by anything heavy
|
||||
triggered(AM)
|
||||
..()
|
||||
|
||||
/obj/item/assembly/mousetrap/on_found(mob/finder)
|
||||
if(armed)
|
||||
finder.visible_message("<span class='warning'>[finder] accidentally sets off [src], breaking [finder.p_their()] fingers.</span>", \
|
||||
"<span class='warning'>You accidentally trigger [src]!</span>")
|
||||
triggered(finder, finder.hand ? "l_hand" : "r_hand")
|
||||
return TRUE //end the search!
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/mousetrap/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
if(!armed)
|
||||
return ..()
|
||||
visible_message("<span class='warning'>[src] is triggered by [AM].</span>")
|
||||
triggered(null)
|
||||
|
||||
/obj/item/assembly/mousetrap/armed
|
||||
icon_state = "mousetraparmed"
|
||||
armed = 1
|
||||
|
||||
|
||||
/obj/item/assembly/mousetrap/verb/hide_under()
|
||||
set src in oview(1)
|
||||
set name = "Hide"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
layer = TURF_LAYER+0.2
|
||||
to_chat(usr, "<span class='notice'>You hide [src].</span>")
|
||||
/obj/item/assembly/mousetrap
|
||||
name = "mousetrap"
|
||||
desc = "A handy little spring-loaded trap for catching pesty rodents."
|
||||
icon_state = "mousetrap"
|
||||
materials = list(MAT_METAL=100)
|
||||
origin_tech = "combat=1;materials=2;engineering=1"
|
||||
var/armed = FALSE
|
||||
|
||||
bomb_name = "contact mine"
|
||||
|
||||
/obj/item/assembly/mousetrap/examine(mob/user)
|
||||
. = ..()
|
||||
if(armed)
|
||||
. += "It looks like it's armed."
|
||||
|
||||
/obj/item/assembly/mousetrap/activate()
|
||||
if(..())
|
||||
armed = !armed
|
||||
if(!armed)
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))
|
||||
to_chat(user, "Your hand slips, setting off the trigger.")
|
||||
pulse(0)
|
||||
update_icon()
|
||||
if(usr)
|
||||
playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
|
||||
|
||||
/obj/item/assembly/mousetrap/describe()
|
||||
return "The pressure switch is [armed ? "primed" : "safe"]."
|
||||
|
||||
/obj/item/assembly/mousetrap/update_icon()
|
||||
if(armed)
|
||||
icon_state = "mousetraparmed"
|
||||
else
|
||||
icon_state = "mousetrap"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/mousetrap/proc/triggered(mob/target, type = "feet")
|
||||
if(!armed)
|
||||
return
|
||||
var/obj/item/organ/external/affecting = null
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(PIERCEIMMUNE in H.dna.species.species_traits)
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
|
||||
armed = FALSE
|
||||
update_icon()
|
||||
pulse(FALSE)
|
||||
return FALSE
|
||||
switch(type)
|
||||
if("feet")
|
||||
if(!H.shoes)
|
||||
affecting = H.get_organ(pick("l_leg", "r_leg"))
|
||||
H.Weaken(3)
|
||||
if("l_hand", "r_hand")
|
||||
if(!H.gloves)
|
||||
affecting = H.get_organ(type)
|
||||
H.Stun(3)
|
||||
if(affecting)
|
||||
affecting.receive_damage(1, 0)
|
||||
else if(ismouse(target))
|
||||
var/mob/living/simple_animal/mouse/M = target
|
||||
visible_message("<span class='danger'>SPLAT!</span>")
|
||||
M.splat()
|
||||
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
layer = MOB_LAYER - 0.2
|
||||
armed = FALSE
|
||||
update_icon()
|
||||
pulse(0)
|
||||
|
||||
/obj/item/assembly/mousetrap/attack_self(mob/living/user)
|
||||
if(!armed)
|
||||
to_chat(user, "<span class='notice'>You arm [src].</span>")
|
||||
else
|
||||
if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))
|
||||
var/which_hand = "l_hand"
|
||||
if(!user.hand)
|
||||
which_hand = "r_hand"
|
||||
triggered(user, which_hand)
|
||||
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking [user.p_their()] fingers.</span>", \
|
||||
"<span class='warning'>You accidentally trigger [src]!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You disarm [src].</span>")
|
||||
armed = !armed
|
||||
update_icon()
|
||||
playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
|
||||
|
||||
/obj/item/assembly/mousetrap/attack_hand(mob/living/user)
|
||||
if(armed)
|
||||
if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))
|
||||
var/which_hand = "l_hand"
|
||||
if(!user.hand)
|
||||
which_hand = "r_hand"
|
||||
triggered(user, which_hand)
|
||||
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking [user.p_their()] fingers.</span>", \
|
||||
"<span class='warning'>You accidentally trigger [src]!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/assembly/mousetrap/Crossed(atom/movable/AM, oldloc)
|
||||
if(armed)
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/H = AM
|
||||
if(H.m_intent == MOVE_INTENT_RUN)
|
||||
triggered(H)
|
||||
H.visible_message("<span class='warning'>[H] accidentally steps on [src].</span>", \
|
||||
"<span class='warning'>You accidentally step on [src]</span>")
|
||||
else if(ismouse(AM))
|
||||
triggered(AM)
|
||||
else if(AM.density) // For mousetrap grenades, set off by anything heavy
|
||||
triggered(AM)
|
||||
..()
|
||||
|
||||
/obj/item/assembly/mousetrap/on_found(mob/finder)
|
||||
if(armed)
|
||||
finder.visible_message("<span class='warning'>[finder] accidentally sets off [src], breaking [finder.p_their()] fingers.</span>", \
|
||||
"<span class='warning'>You accidentally trigger [src]!</span>")
|
||||
triggered(finder, finder.hand ? "l_hand" : "r_hand")
|
||||
return TRUE //end the search!
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/mousetrap/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
if(!armed)
|
||||
return ..()
|
||||
visible_message("<span class='warning'>[src] is triggered by [AM].</span>")
|
||||
triggered(null)
|
||||
|
||||
/obj/item/assembly/mousetrap/armed
|
||||
icon_state = "mousetraparmed"
|
||||
armed = 1
|
||||
|
||||
|
||||
/obj/item/assembly/mousetrap/verb/hide_under()
|
||||
set src in oview(1)
|
||||
set name = "Hide"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
layer = TURF_LAYER+0.2
|
||||
to_chat(usr, "<span class='notice'>You hide [src].</span>")
|
||||
|
||||
+134
-134
@@ -1,134 +1,134 @@
|
||||
/obj/item/assembly/prox_sensor
|
||||
name = "proximity sensor"
|
||||
desc = "Used for scanning and alerting when someone enters a certain proximity."
|
||||
icon_state = "prox"
|
||||
materials = list(MAT_METAL = 800, MAT_GLASS = 200)
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
|
||||
secured = 0
|
||||
|
||||
bomb_name = "proximity mine"
|
||||
|
||||
var/scanning = 0
|
||||
var/timing = 0
|
||||
var/time = 10
|
||||
|
||||
/obj/item/assembly/prox_sensor/describe()
|
||||
if(timing)
|
||||
return "<span class='notice'>The proximity sensor is arming.</span>"
|
||||
return "The proximity sensor is [scanning ? "armed" : "disarmed"]."
|
||||
|
||||
/obj/item/assembly/prox_sensor/activate()
|
||||
if(!..())
|
||||
return FALSE //Cooldown check
|
||||
timing = !timing
|
||||
update_icon()
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/prox_sensor/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
scanning = 0
|
||||
timing = 0
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/prox_sensor/HasProximity(atom/movable/AM)
|
||||
if(!isobj(AM) && !isliving(AM))
|
||||
return
|
||||
if(istype(AM, /obj/effect))
|
||||
return
|
||||
if(AM.move_speed < 12)
|
||||
sense()
|
||||
|
||||
/obj/item/assembly/prox_sensor/proc/sense()
|
||||
if(!secured || !scanning || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
/obj/item/assembly/prox_sensor/process()
|
||||
if(timing && (time >= 0))
|
||||
time--
|
||||
if(timing && time <= 0)
|
||||
timing = 0
|
||||
toggle_scan()
|
||||
time = 10
|
||||
|
||||
/obj/item/assembly/prox_sensor/dropped()
|
||||
..()
|
||||
spawn(0)
|
||||
sense()
|
||||
return
|
||||
|
||||
/obj/item/assembly/prox_sensor/proc/toggle_scan()
|
||||
if(!secured)
|
||||
return FALSE
|
||||
scanning = !scanning
|
||||
update_icon()
|
||||
|
||||
/obj/item/assembly/prox_sensor/update_icon()
|
||||
overlays.Cut()
|
||||
attached_overlays = list()
|
||||
if(timing)
|
||||
overlays += "prox_timing"
|
||||
attached_overlays += "prox_timing"
|
||||
if(scanning)
|
||||
overlays += "prox_scanning"
|
||||
attached_overlays += "prox_scanning"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/prox_sensor/Move()
|
||||
..()
|
||||
sense()
|
||||
|
||||
/obj/item/assembly/prox_sensor/holder_movement()
|
||||
sense()
|
||||
|
||||
/obj/item/assembly/prox_sensor/interact(mob/user)//TODO: Change this to the wires thingy
|
||||
if(!secured)
|
||||
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
|
||||
return FALSE
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/dat = text("<TT><B>Proximity Sensor</B>\n[] []:[]\n<A href='?src=[UID()];tp=-30'>-</A> <A href='?src=[UID()];tp=-1'>-</A> <A href='?src=[UID()];tp=1'>+</A> <A href='?src=[UID()];tp=30'>+</A>\n</TT>", (timing ? "<A href='?src=[UID()];time=0'>Arming</A>" : "<A href='?src=[UID()];time=1'>Not Arming</A>"), minute, second)
|
||||
dat += "<BR><A href='?src=[UID()];scanning=1'>[scanning?"Armed":"Unarmed"]</A> (Movement sensor active when armed!)"
|
||||
dat += "<BR><BR><A href='?src=[UID()];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[UID()];close=1'>Close</A>"
|
||||
var/datum/browser/popup = new(user, "prox", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "prox")
|
||||
|
||||
/obj/item/assembly/prox_sensor/Topic(href, href_list)
|
||||
..()
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=prox")
|
||||
onclose(usr, "prox")
|
||||
return
|
||||
|
||||
if(href_list["scanning"])
|
||||
toggle_scan()
|
||||
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
update_icon()
|
||||
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 600)
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=prox")
|
||||
return
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
/obj/item/assembly/prox_sensor
|
||||
name = "proximity sensor"
|
||||
desc = "Used for scanning and alerting when someone enters a certain proximity."
|
||||
icon_state = "prox"
|
||||
materials = list(MAT_METAL = 800, MAT_GLASS = 200)
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
|
||||
secured = 0
|
||||
|
||||
bomb_name = "proximity mine"
|
||||
|
||||
var/scanning = 0
|
||||
var/timing = 0
|
||||
var/time = 10
|
||||
|
||||
/obj/item/assembly/prox_sensor/describe()
|
||||
if(timing)
|
||||
return "<span class='notice'>The proximity sensor is arming.</span>"
|
||||
return "The proximity sensor is [scanning ? "armed" : "disarmed"]."
|
||||
|
||||
/obj/item/assembly/prox_sensor/activate()
|
||||
if(!..())
|
||||
return FALSE //Cooldown check
|
||||
timing = !timing
|
||||
update_icon()
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/prox_sensor/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
scanning = 0
|
||||
timing = 0
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/prox_sensor/HasProximity(atom/movable/AM)
|
||||
if(!isobj(AM) && !isliving(AM))
|
||||
return
|
||||
if(istype(AM, /obj/effect))
|
||||
return
|
||||
if(AM.move_speed < 12)
|
||||
sense()
|
||||
|
||||
/obj/item/assembly/prox_sensor/proc/sense()
|
||||
if(!secured || !scanning || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
/obj/item/assembly/prox_sensor/process()
|
||||
if(timing && (time >= 0))
|
||||
time--
|
||||
if(timing && time <= 0)
|
||||
timing = 0
|
||||
toggle_scan()
|
||||
time = 10
|
||||
|
||||
/obj/item/assembly/prox_sensor/dropped()
|
||||
..()
|
||||
spawn(0)
|
||||
sense()
|
||||
return
|
||||
|
||||
/obj/item/assembly/prox_sensor/proc/toggle_scan()
|
||||
if(!secured)
|
||||
return FALSE
|
||||
scanning = !scanning
|
||||
update_icon()
|
||||
|
||||
/obj/item/assembly/prox_sensor/update_icon()
|
||||
overlays.Cut()
|
||||
attached_overlays = list()
|
||||
if(timing)
|
||||
overlays += "prox_timing"
|
||||
attached_overlays += "prox_timing"
|
||||
if(scanning)
|
||||
overlays += "prox_scanning"
|
||||
attached_overlays += "prox_scanning"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/prox_sensor/Move()
|
||||
..()
|
||||
sense()
|
||||
|
||||
/obj/item/assembly/prox_sensor/holder_movement()
|
||||
sense()
|
||||
|
||||
/obj/item/assembly/prox_sensor/interact(mob/user)//TODO: Change this to the wires thingy
|
||||
if(!secured)
|
||||
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
|
||||
return FALSE
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/dat = text("<TT><B>Proximity Sensor</B>\n[] []:[]\n<A href='?src=[UID()];tp=-30'>-</A> <A href='?src=[UID()];tp=-1'>-</A> <A href='?src=[UID()];tp=1'>+</A> <A href='?src=[UID()];tp=30'>+</A>\n</TT>", (timing ? "<A href='?src=[UID()];time=0'>Arming</A>" : "<A href='?src=[UID()];time=1'>Not Arming</A>"), minute, second)
|
||||
dat += "<BR><A href='?src=[UID()];scanning=1'>[scanning?"Armed":"Unarmed"]</A> (Movement sensor active when armed!)"
|
||||
dat += "<BR><BR><A href='?src=[UID()];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[UID()];close=1'>Close</A>"
|
||||
var/datum/browser/popup = new(user, "prox", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "prox")
|
||||
|
||||
/obj/item/assembly/prox_sensor/Topic(href, href_list)
|
||||
..()
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=prox")
|
||||
onclose(usr, "prox")
|
||||
return
|
||||
|
||||
if(href_list["scanning"])
|
||||
toggle_scan()
|
||||
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
update_icon()
|
||||
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 600)
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=prox")
|
||||
return
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
/obj/item/assembly/shock_kit
|
||||
name = "electrohelmet assembly"
|
||||
desc = "This appears to be made from both an electropack and a helmet."
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "shock_kit"
|
||||
var/obj/item/clothing/head/helmet/part1 = null
|
||||
var/obj/item/radio/electropack/part2 = null
|
||||
var/status = 0
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags = CONDUCT
|
||||
|
||||
/obj/item/assembly/shock_kit/Destroy()
|
||||
QDEL_NULL(part1)
|
||||
QDEL_NULL(part2)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/shock_kit/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
if(istype(W, /obj/item/wrench) && !status)
|
||||
var/turf/T = loc
|
||||
if(ismob(T))
|
||||
T = T.loc
|
||||
part1.loc = T
|
||||
part2.loc = T
|
||||
part1.master = null
|
||||
part2.master = null
|
||||
part1 = null
|
||||
part2 = null
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
status = !status
|
||||
to_chat(user, "<span class='notice'>[src] is now [status ? "secured" : "unsecured"]!</span>")
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/assembly/shock_kit/attack_self(mob/user as mob)
|
||||
part1.attack_self(user, status)
|
||||
part2.attack_self(user, status)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/assembly/shock_kit/receive_signal()
|
||||
if(istype(loc, /obj/structure/chair/e_chair))
|
||||
var/obj/structure/chair/e_chair/C = loc
|
||||
C.shock()
|
||||
return
|
||||
/obj/item/assembly/shock_kit
|
||||
name = "electrohelmet assembly"
|
||||
desc = "This appears to be made from both an electropack and a helmet."
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "shock_kit"
|
||||
var/obj/item/clothing/head/helmet/part1 = null
|
||||
var/obj/item/radio/electropack/part2 = null
|
||||
var/status = 0
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags = CONDUCT
|
||||
|
||||
/obj/item/assembly/shock_kit/Destroy()
|
||||
QDEL_NULL(part1)
|
||||
QDEL_NULL(part2)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/shock_kit/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
if(istype(W, /obj/item/wrench) && !status)
|
||||
var/turf/T = loc
|
||||
if(ismob(T))
|
||||
T = T.loc
|
||||
part1.loc = T
|
||||
part2.loc = T
|
||||
part1.master = null
|
||||
part2.master = null
|
||||
part1 = null
|
||||
part2 = null
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
status = !status
|
||||
to_chat(user, "<span class='notice'>[src] is now [status ? "secured" : "unsecured"]!</span>")
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/assembly/shock_kit/attack_self(mob/user as mob)
|
||||
part1.attack_self(user, status)
|
||||
part2.attack_self(user, status)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/assembly/shock_kit/receive_signal()
|
||||
if(istype(loc, /obj/structure/chair/e_chair))
|
||||
var/obj/structure/chair/e_chair/C = loc
|
||||
C.shock()
|
||||
return
|
||||
|
||||
+177
-177
@@ -1,177 +1,177 @@
|
||||
/obj/item/assembly/signaler
|
||||
name = "remote signaling device"
|
||||
desc = "Used to remotely activate devices."
|
||||
icon_state = "signaller"
|
||||
item_state = "signaler"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=120)
|
||||
origin_tech = "magnets=1;bluespace=1"
|
||||
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
|
||||
|
||||
secured = 1
|
||||
var/receiving = FALSE
|
||||
|
||||
bomb_name = "remote-control bomb"
|
||||
|
||||
var/code = 30
|
||||
var/frequency = RSD_FREQ
|
||||
var/delay = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/airlock_wire = null
|
||||
|
||||
/obj/item/assembly/signaler/New()
|
||||
..()
|
||||
if(SSradio)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/assembly/signaler/Initialize()
|
||||
..()
|
||||
if(SSradio)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/assembly/signaler/Destroy()
|
||||
if(SSradio)
|
||||
SSradio.remove_object(src, frequency)
|
||||
radio_connection = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/signaler/describe()
|
||||
return "[src]'s power light is [receiving ? "on" : "off"]"
|
||||
|
||||
/obj/item/assembly/signaler/activate()
|
||||
if(cooldown > 0)
|
||||
return FALSE
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
signal()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/update_icon()
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/interact(mob/user, flag1)
|
||||
var/t1 = "-------"
|
||||
var/dat = {"
|
||||
<TT>
|
||||
"}
|
||||
if(!flag1)
|
||||
dat += {"
|
||||
<A href='byond://?src=[UID()];send=1'>Send Signal</A><BR>
|
||||
Receiver is <A href='byond://?src=[UID()];receive=1'>[receiving?"on":"off"]</A><BR>
|
||||
"}
|
||||
dat += {"
|
||||
<B>Frequency/Code</B> for signaler:<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=[UID()];freq=-10'>-</A>
|
||||
<A href='byond://?src=[UID()];freq=-2'>-</A>
|
||||
[format_frequency(frequency)]
|
||||
<A href='byond://?src=[UID()];freq=2'>+</A>
|
||||
<A href='byond://?src=[UID()];freq=10'>+</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=[UID()];code=-5'>-</A>
|
||||
<A href='byond://?src=[UID()];code=-1'>-</A>
|
||||
[code]
|
||||
<A href='byond://?src=[UID()];code=1'>+</A>
|
||||
<A href='byond://?src=[UID()];code=5'>+</A><BR>
|
||||
[t1]
|
||||
</TT>
|
||||
"}
|
||||
var/datum/browser/popup = new(user, "radio", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "radio")
|
||||
|
||||
/obj/item/assembly/signaler/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=radio")
|
||||
onclose(usr, "radio")
|
||||
return
|
||||
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
||||
if(new_frequency < RADIO_LOW_FREQ || new_frequency > RADIO_HIGH_FREQ)
|
||||
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
|
||||
set_frequency(new_frequency)
|
||||
|
||||
if(href_list["code"])
|
||||
code += text2num(href_list["code"])
|
||||
code = round(code)
|
||||
code = min(100, code)
|
||||
code = max(1, code)
|
||||
if(href_list["receive"])
|
||||
receiving = !receiving
|
||||
|
||||
if(href_list["send"])
|
||||
spawn( 0 )
|
||||
signal()
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/assembly/signaler/proc/signal()
|
||||
if(!radio_connection)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.source = src
|
||||
signal.encryption = code
|
||||
signal.data["message"] = "ACTIVATE"
|
||||
radio_connection.post_signal(src, signal)
|
||||
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
var/turf/T = get_turf(src)
|
||||
if(usr)
|
||||
lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
|
||||
|
||||
/obj/item/assembly/signaler/pulse(var/radio = FALSE)
|
||||
if(connected && wires)
|
||||
connected.Pulse(src)
|
||||
else
|
||||
return ..(radio)
|
||||
|
||||
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
|
||||
if(!receiving || !signal)
|
||||
return FALSE
|
||||
|
||||
if(signal.encryption != code)
|
||||
return FALSE
|
||||
|
||||
if(!(wires & WIRE_RADIO_RECEIVE))
|
||||
return FALSE
|
||||
pulse(1)
|
||||
|
||||
for(var/mob/O in hearers(1, loc))
|
||||
O.show_message("[bicon(src)] *beep* *beep*", 3, "*beep* *beep*", 2)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/proc/set_frequency(new_frequency)
|
||||
if(!SSradio)
|
||||
sleep(20)
|
||||
if(!SSradio)
|
||||
return
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT)
|
||||
|
||||
// Embedded signaller used in anomalies.
|
||||
/obj/item/assembly/signaler/anomaly
|
||||
name = "anomaly core"
|
||||
desc = "The neutralized core of an anomaly. It'd probably be valuable for research."
|
||||
icon_state = "anomaly core"
|
||||
item_state = "electronic"
|
||||
resistance_flags = FIRE_PROOF
|
||||
receiving = TRUE
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
|
||||
if(..())
|
||||
for(var/obj/effect/anomaly/A in orange(0, src))
|
||||
A.anomalyNeutralize()
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/attack_self()
|
||||
return
|
||||
/obj/item/assembly/signaler
|
||||
name = "remote signaling device"
|
||||
desc = "Used to remotely activate devices."
|
||||
icon_state = "signaller"
|
||||
item_state = "signaler"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=120)
|
||||
origin_tech = "magnets=1;bluespace=1"
|
||||
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
|
||||
|
||||
secured = 1
|
||||
var/receiving = FALSE
|
||||
|
||||
bomb_name = "remote-control bomb"
|
||||
|
||||
var/code = 30
|
||||
var/frequency = RSD_FREQ
|
||||
var/delay = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/airlock_wire = null
|
||||
|
||||
/obj/item/assembly/signaler/New()
|
||||
..()
|
||||
if(SSradio)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/assembly/signaler/Initialize()
|
||||
..()
|
||||
if(SSradio)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/assembly/signaler/Destroy()
|
||||
if(SSradio)
|
||||
SSradio.remove_object(src, frequency)
|
||||
radio_connection = null
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/signaler/describe()
|
||||
return "[src]'s power light is [receiving ? "on" : "off"]"
|
||||
|
||||
/obj/item/assembly/signaler/activate()
|
||||
if(cooldown > 0)
|
||||
return FALSE
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
signal()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/update_icon()
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/interact(mob/user, flag1)
|
||||
var/t1 = "-------"
|
||||
var/dat = {"
|
||||
<TT>
|
||||
"}
|
||||
if(!flag1)
|
||||
dat += {"
|
||||
<A href='byond://?src=[UID()];send=1'>Send Signal</A><BR>
|
||||
Receiver is <A href='byond://?src=[UID()];receive=1'>[receiving?"on":"off"]</A><BR>
|
||||
"}
|
||||
dat += {"
|
||||
<B>Frequency/Code</B> for signaler:<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=[UID()];freq=-10'>-</A>
|
||||
<A href='byond://?src=[UID()];freq=-2'>-</A>
|
||||
[format_frequency(frequency)]
|
||||
<A href='byond://?src=[UID()];freq=2'>+</A>
|
||||
<A href='byond://?src=[UID()];freq=10'>+</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=[UID()];code=-5'>-</A>
|
||||
<A href='byond://?src=[UID()];code=-1'>-</A>
|
||||
[code]
|
||||
<A href='byond://?src=[UID()];code=1'>+</A>
|
||||
<A href='byond://?src=[UID()];code=5'>+</A><BR>
|
||||
[t1]
|
||||
</TT>
|
||||
"}
|
||||
var/datum/browser/popup = new(user, "radio", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "radio")
|
||||
|
||||
/obj/item/assembly/signaler/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=radio")
|
||||
onclose(usr, "radio")
|
||||
return
|
||||
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
||||
if(new_frequency < RADIO_LOW_FREQ || new_frequency > RADIO_HIGH_FREQ)
|
||||
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
|
||||
set_frequency(new_frequency)
|
||||
|
||||
if(href_list["code"])
|
||||
code += text2num(href_list["code"])
|
||||
code = round(code)
|
||||
code = min(100, code)
|
||||
code = max(1, code)
|
||||
if(href_list["receive"])
|
||||
receiving = !receiving
|
||||
|
||||
if(href_list["send"])
|
||||
spawn( 0 )
|
||||
signal()
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/assembly/signaler/proc/signal()
|
||||
if(!radio_connection)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.source = src
|
||||
signal.encryption = code
|
||||
signal.data["message"] = "ACTIVATE"
|
||||
radio_connection.post_signal(src, signal)
|
||||
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
var/turf/T = get_turf(src)
|
||||
if(usr)
|
||||
GLOB.lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
|
||||
|
||||
/obj/item/assembly/signaler/pulse(var/radio = FALSE)
|
||||
if(connected && wires)
|
||||
connected.Pulse(src)
|
||||
else
|
||||
return ..(radio)
|
||||
|
||||
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
|
||||
if(!receiving || !signal)
|
||||
return FALSE
|
||||
|
||||
if(signal.encryption != code)
|
||||
return FALSE
|
||||
|
||||
if(!(wires & WIRE_RADIO_RECEIVE))
|
||||
return FALSE
|
||||
pulse(1)
|
||||
|
||||
for(var/mob/O in hearers(1, loc))
|
||||
O.show_message("[bicon(src)] *beep* *beep*", 3, "*beep* *beep*", 2)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/proc/set_frequency(new_frequency)
|
||||
if(!SSradio)
|
||||
sleep(20)
|
||||
if(!SSradio)
|
||||
return
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT)
|
||||
|
||||
// Embedded signaller used in anomalies.
|
||||
/obj/item/assembly/signaler/anomaly
|
||||
name = "anomaly core"
|
||||
desc = "The neutralized core of an anomaly. It'd probably be valuable for research."
|
||||
icon_state = "anomaly core"
|
||||
item_state = "electronic"
|
||||
resistance_flags = FIRE_PROOF
|
||||
receiving = TRUE
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
|
||||
if(..())
|
||||
for(var/obj/effect/anomaly/A in orange(0, src))
|
||||
A.anomalyNeutralize()
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/attack_self()
|
||||
return
|
||||
|
||||
+127
-127
@@ -1,127 +1,127 @@
|
||||
/obj/item/assembly/timer
|
||||
name = "timer"
|
||||
desc = "Used to time things. Works well with contraptions which has to count down. Tick tock."
|
||||
icon_state = "timer"
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
|
||||
secured = FALSE
|
||||
|
||||
bomb_name = "time bomb"
|
||||
|
||||
var/timing = FALSE
|
||||
var/time = 10
|
||||
var/repeat = FALSE
|
||||
var/set_time = 10
|
||||
|
||||
/obj/item/assembly/timer/describe()
|
||||
if(timing)
|
||||
return "The timer is counting down from [time]!"
|
||||
return "The timer is set for [time] seconds."
|
||||
|
||||
/obj/item/assembly/timer/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
timing = !timing
|
||||
update_icon()
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/timer/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
timing = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/timer/proc/timer_end()
|
||||
if(!secured || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
if(loc)
|
||||
loc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
/obj/item/assembly/timer/process()
|
||||
if(timing && (time > 0))
|
||||
time -= 2 // 2 seconds per process()
|
||||
if(timing && time <= 0)
|
||||
timing = repeat
|
||||
timer_end()
|
||||
time = set_time
|
||||
|
||||
/obj/item/assembly/timer/update_icon()
|
||||
overlays.Cut()
|
||||
attached_overlays = list()
|
||||
if(timing)
|
||||
overlays += "timer_timing"
|
||||
attached_overlays += "timer_timing"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/timer/interact(mob/user as mob)//TODO: Have this use the wires
|
||||
if(!secured)
|
||||
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
|
||||
return FALSE
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/set_second = set_time % 60
|
||||
var/set_minute = (set_time - set_second) / 60
|
||||
if(second < 10) second = "0[second]"
|
||||
if(set_second < 10) set_second = "0[set_second]"
|
||||
|
||||
var/dat = {"
|
||||
<TT>
|
||||
<center><h2>Timing Unit</h2>
|
||||
[minute]:[second] <a href='?src=[UID()];time=1'>[timing?"Stop":"Start"]</a> <a href='?src=[UID()];reset=1'>Reset</a><br>
|
||||
Repeat: <a href='?src=[UID()];repeat=1'>[repeat?"On":"Off"]</a><br>
|
||||
Timer set for
|
||||
<A href='?src=[UID()];tp=-30'>-</A> <A href='?src=[UID()];tp=-1'>-</A> [set_minute]:[set_second] <A href='?src=[UID()];tp=1'>+</A> <A href='?src=[UID()];tp=30'>+</A>
|
||||
</center>
|
||||
</TT>
|
||||
<BR><BR>
|
||||
<A href='?src=[UID()];refresh=1'>Refresh</A>
|
||||
<BR><BR>
|
||||
<A href='?src=[UID()];close=1'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "timer", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "timer")
|
||||
|
||||
/obj/item/assembly/timer/Topic(href, href_list)
|
||||
..()
|
||||
if(usr.incapacitated() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=timer")
|
||||
onclose(usr, "timer")
|
||||
return
|
||||
|
||||
if(href_list["time"])
|
||||
timing = !timing
|
||||
if(timing && istype(holder, /obj/item/transfer_valve))
|
||||
message_admins("[key_name_admin(usr)] activated [src] attachment on [holder].")
|
||||
investigate_log("[key_name(usr)] activated [src] attachment for [loc]", INVESTIGATE_BOMB)
|
||||
log_game("[key_name(usr)] activated [src] attachment for [loc]")
|
||||
update_icon()
|
||||
if(href_list["reset"])
|
||||
time = set_time
|
||||
|
||||
if(href_list["repeat"])
|
||||
repeat = !repeat
|
||||
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
set_time += tp
|
||||
set_time = min(max(round(set_time), 6), 600)
|
||||
if(!timing)
|
||||
time = set_time
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=timer")
|
||||
return
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
/obj/item/assembly/timer
|
||||
name = "timer"
|
||||
desc = "Used to time things. Works well with contraptions which has to count down. Tick tock."
|
||||
icon_state = "timer"
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
|
||||
secured = FALSE
|
||||
|
||||
bomb_name = "time bomb"
|
||||
|
||||
var/timing = FALSE
|
||||
var/time = 10
|
||||
var/repeat = FALSE
|
||||
var/set_time = 10
|
||||
|
||||
/obj/item/assembly/timer/describe()
|
||||
if(timing)
|
||||
return "The timer is counting down from [time]!"
|
||||
return "The timer is set for [time] seconds."
|
||||
|
||||
/obj/item/assembly/timer/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
timing = !timing
|
||||
update_icon()
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly/timer/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
timing = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/timer/proc/timer_end()
|
||||
if(!secured || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
if(loc)
|
||||
loc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
|
||||
/obj/item/assembly/timer/process()
|
||||
if(timing && (time > 0))
|
||||
time -= 2 // 2 seconds per process()
|
||||
if(timing && time <= 0)
|
||||
timing = repeat
|
||||
timer_end()
|
||||
time = set_time
|
||||
|
||||
/obj/item/assembly/timer/update_icon()
|
||||
overlays.Cut()
|
||||
attached_overlays = list()
|
||||
if(timing)
|
||||
overlays += "timer_timing"
|
||||
attached_overlays += "timer_timing"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/timer/interact(mob/user as mob)//TODO: Have this use the wires
|
||||
if(!secured)
|
||||
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
|
||||
return FALSE
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/set_second = set_time % 60
|
||||
var/set_minute = (set_time - set_second) / 60
|
||||
if(second < 10) second = "0[second]"
|
||||
if(set_second < 10) set_second = "0[set_second]"
|
||||
|
||||
var/dat = {"
|
||||
<TT>
|
||||
<center><h2>Timing Unit</h2>
|
||||
[minute]:[second] <a href='?src=[UID()];time=1'>[timing?"Stop":"Start"]</a> <a href='?src=[UID()];reset=1'>Reset</a><br>
|
||||
Repeat: <a href='?src=[UID()];repeat=1'>[repeat?"On":"Off"]</a><br>
|
||||
Timer set for
|
||||
<A href='?src=[UID()];tp=-30'>-</A> <A href='?src=[UID()];tp=-1'>-</A> [set_minute]:[set_second] <A href='?src=[UID()];tp=1'>+</A> <A href='?src=[UID()];tp=30'>+</A>
|
||||
</center>
|
||||
</TT>
|
||||
<BR><BR>
|
||||
<A href='?src=[UID()];refresh=1'>Refresh</A>
|
||||
<BR><BR>
|
||||
<A href='?src=[UID()];close=1'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "timer", name, 400, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "timer")
|
||||
|
||||
/obj/item/assembly/timer/Topic(href, href_list)
|
||||
..()
|
||||
if(usr.incapacitated() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=timer")
|
||||
onclose(usr, "timer")
|
||||
return
|
||||
|
||||
if(href_list["time"])
|
||||
timing = !timing
|
||||
if(timing && istype(holder, /obj/item/transfer_valve))
|
||||
message_admins("[key_name_admin(usr)] activated [src] attachment on [holder].")
|
||||
investigate_log("[key_name(usr)] activated [src] attachment for [loc]", INVESTIGATE_BOMB)
|
||||
log_game("[key_name(usr)] activated [src] attachment for [loc]")
|
||||
update_icon()
|
||||
if(href_list["reset"])
|
||||
time = set_time
|
||||
|
||||
if(href_list["repeat"])
|
||||
repeat = !repeat
|
||||
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
set_time += tp
|
||||
set_time = min(max(round(set_time), 6), 600)
|
||||
if(!timing)
|
||||
time = set_time
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=timer")
|
||||
return
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
@@ -74,4 +74,4 @@
|
||||
/obj/item/assembly/voice/noise/hear_message(mob/living/M as mob, msg)
|
||||
pulse(0)
|
||||
var/turf/T = get_turf(src) //otherwise it won't work in hand
|
||||
T.visible_message("<span class='warning'>[bicon(src)] beeps!</span>")
|
||||
T.visible_message("<span class='warning'>[bicon(src)] beeps!</span>")
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/selectValidChildFor(datum/automation/parent, mob/user, list/valid_returntypes)
|
||||
var/list/choices=list()
|
||||
for(var/childtype in automation_types)
|
||||
for(var/childtype in GLOB.automation_types)
|
||||
var/datum/automation/A = new childtype(src)
|
||||
if(A.returntype == null)
|
||||
continue
|
||||
@@ -217,7 +217,7 @@
|
||||
testing("AAC: Null cData in root JS array.")
|
||||
continue
|
||||
var/Atype=text2path(cData["type"])
|
||||
if(!(Atype in automation_types))
|
||||
if(!(Atype in GLOB.automation_types))
|
||||
testing("AAC: Unrecognized Atype [Atype].")
|
||||
continue
|
||||
var/datum/automation/A = new Atype(src)
|
||||
|
||||
@@ -41,4 +41,4 @@
|
||||
return
|
||||
valve = input("Select a valve:", "Sensor Data", valve) as null|anything in valves
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -39,4 +39,4 @@
|
||||
return
|
||||
emitter = input("Select an emitter:", "Emitter", emitter) as null|anything in emitters
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -80,4 +80,4 @@
|
||||
injector_names|=I.id_tag
|
||||
injector = input("Select an injector:", "Sensor Data", injector) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -84,13 +84,13 @@
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
var/global/list/gas_labels=list(
|
||||
GLOBAL_LIST_INIT(gas_labels, list(
|
||||
"co2" = "CO<sub>2</sub>",
|
||||
"tox" = "Plasma",
|
||||
"n2o" = "N<sub>2</sub>O",
|
||||
"o2" = "O<sub>2</sub>",
|
||||
"n2" = "N<sub>2</sub>"
|
||||
)
|
||||
))
|
||||
/datum/automation/set_scrubber_gasses
|
||||
name="Scrubber: Gasses"
|
||||
|
||||
@@ -131,7 +131,7 @@ var/global/list/gas_labels=list(
|
||||
GetText()
|
||||
var/txt = "Set Scrubber <a href=\"?src=[UID()];set_scrubber=1\">[fmtString(scrubber)]</a> to scrub "
|
||||
for(var/gas in gasses)
|
||||
txt += " [gas_labels[gas]] (<a href=\"?src=[UID()];tog_gas=[gas]\">[gasses[gas] ? "on" : "off"]</a>),"
|
||||
txt += " [GLOB.gas_labels[gas]] (<a href=\"?src=[UID()];tog_gas=[gas]\">[gasses[gas] ? "on" : "off"]</a>),"
|
||||
return txt
|
||||
|
||||
Topic(href,href_list)
|
||||
@@ -150,4 +150,4 @@ var/global/list/gas_labels=list(
|
||||
injector_names|=S.id_tag
|
||||
scrubber = input("Select a scrubber:", "Scrubbers", scrubber) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
field = json["field"]
|
||||
|
||||
Evaluate()
|
||||
if(sensor && field && sensor in parent.sensor_information)
|
||||
if(sensor && field && (sensor in parent.sensor_information))
|
||||
return parent.sensor_information[sensor][field]
|
||||
return 0
|
||||
|
||||
@@ -53,4 +53,4 @@
|
||||
sensor_list|=M.id_tag
|
||||
sensor = input("Select a sensor:", "Sensor Data", field) as null|anything in sensor_list
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var/global/automation_types = subtypesof(/datum/automation)
|
||||
GLOBAL_LIST_INIT(automation_types, subtypesof(/datum/automation))
|
||||
|
||||
#define AUTOM_RT_NULL 0
|
||||
#define AUTOM_RT_NUM 1
|
||||
@@ -56,7 +56,7 @@ var/global/automation_types = subtypesof(/datum/automation)
|
||||
if(isnull(cData) || !("type" in cData))
|
||||
return null
|
||||
var/Atype=text2path(cData["type"])
|
||||
if(!(Atype in automation_types))
|
||||
if(!(Atype in GLOB.automation_types))
|
||||
return null
|
||||
var/datum/automation/A = new Atype(parent)
|
||||
A.Import(cData)
|
||||
@@ -70,7 +70,7 @@ var/global/automation_types = subtypesof(/datum/automation)
|
||||
. += null
|
||||
continue
|
||||
var/Atype=text2path(cData["type"])
|
||||
if(!(Atype in automation_types))
|
||||
if(!(Atype in GLOB.automation_types))
|
||||
continue
|
||||
var/datum/automation/A = new Atype(parent)
|
||||
A.Import(cData)
|
||||
@@ -454,4 +454,4 @@ var/global/automation_types = subtypesof(/datum/automation)
|
||||
if(href_list["set_value"])
|
||||
value = input("Set a value:", "Static Value", value) as num
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user