Merge remote-tracking branch 'upstream/master' into hypoglycemia

# Conflicts:
#	code/datums/diseases/critical.dm
#	code/modules/mob/living/carbon/human/examine.dm
#	code/modules/mob/living/carbon/human/life.dm
This commit is contained in:
Fox McCloud
2020-03-19 13:47:31 -04:00
1627 changed files with 185858 additions and 186501 deletions
File diff suppressed because it is too large Load Diff
+232 -232
View File
@@ -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)
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)
+89 -89
View File
@@ -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 -1094
View File
File diff suppressed because it is too large Load Diff
+160 -160
View File
@@ -1,160 +1,160 @@
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
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
File diff suppressed because it is too large Load Diff
+179 -179
View File
@@ -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>")
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>")
+9 -9
View File
@@ -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")
/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")
+23 -23
View File
@@ -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")
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")
+1 -1
View File
@@ -199,4 +199,4 @@ function onload() {
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
+9 -9
View File
@@ -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")
/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")
+108 -108
View File
@@ -1,108 +1,108 @@
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
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
+1 -1
View File
@@ -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,170 +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])
flag_account_for_forum_sync(adm_ckey)
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 [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 = 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 [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(!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
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 = 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 [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 = 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 [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(!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()
flag_account_for_forum_sync(sql_ckey)
/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])
flag_account_for_forum_sync(adm_ckey)
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 [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 = 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 [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(!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
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 = 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 [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 = 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 [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(!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()
flag_account_for_forum_sync(sql_ckey)
+1 -1
View File
@@ -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>&nbsp;&nbsp;
<BR>
<B>Coder Secrets</B><BR>
+3490 -3491
View File
File diff suppressed because it is too large Load Diff
+36 -36
View File
@@ -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]")
+187 -187
View File
@@ -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!
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
+161 -161
View File
@@ -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
+82 -82
View File
@@ -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 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")
+63 -63
View File
@@ -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 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)]")
+1 -1
View File
@@ -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)
+49 -49
View File
@@ -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)
File diff suppressed because it is too large Load Diff
+178 -178
View File
@@ -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 += "&nbsp;&nbsp;<b>ERROR</b><br>"
continue
for(var/filter in fqs.devices)
var/list/f = fqs.devices[filter]
if(!f)
output += "&nbsp;&nbsp;[filters[filter]]: ERROR<br>"
continue
output += "&nbsp;&nbsp;[filters[filter]]: [f.len]<br>"
for(var/device in f)
if(isobj(device))
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])<br>"
else
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device]<br>"
usr << browse(output,"window=radioreport")
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 [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 += "&nbsp;&nbsp;<b>ERROR</b><br>"
continue
for(var/filter in fqs.devices)
var/list/f = fqs.devices[filter]
if(!f)
output += "&nbsp;&nbsp;[filters[filter]]: ERROR<br>"
continue
output += "&nbsp;&nbsp;[filters[filter]]: [f.len]<br>"
for(var/device in f)
if(isobj(device))
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])<br>"
else
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device]<br>"
usr << browse(output,"window=radioreport")
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)
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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
+4 -4
View File
@@ -1,6 +1,6 @@
//HONKsquad
var/const/honksquad_possible = 6 //if more Commandos are needed in the future
#define HONKSQUAD_POSSIBLE 6 //if more Commandos are needed in the future
var/global/sent_honksquad = 0
/client/proc/honksquad()
@@ -31,7 +31,7 @@ var/global/sent_honksquad = 0
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)
@@ -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")
+185 -185
View File
@@ -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.
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!
+272 -272
View File
@@ -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 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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+104 -104
View File
@@ -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.")
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')
+153 -153
View File
@@ -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'*/
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'*/
+89 -89
View File
@@ -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'
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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))
+204 -204
View File
@@ -1,204 +1,204 @@
//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
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
+169 -169
View File
@@ -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
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
+21 -21
View File
@@ -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>")
+22 -22
View File
@@ -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 -1
View File
@@ -1,2 +1,2 @@
/datum/alarm_handler/camera
category = "Camera Alarms"
category = "Camera Alarms"
+1 -1
View File
@@ -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
@@ -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)
@@ -38,4 +38,4 @@
var/datum/objective/steal_five_of_type/summon_magic/magic = new
magic.owner = owner
objectives += magic
..()
..()
@@ -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
@@ -236,28 +235,9 @@
/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()
@@ -75,4 +75,4 @@
H.mutations.Add(LASER)
H.update_mutations()
H.update_body()
H.update_body()
+1 -1
View File
@@ -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 -1
View File
@@ -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>")
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -89,4 +89,4 @@ body {
.button {
cursor: pointer;
}
}
+150 -150
View File
@@ -1,150 +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
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
/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 -180
View File
@@ -1,180 +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
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()
/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()
+1 -1
View File
@@ -104,4 +104,4 @@
return
attack_self(user)
return
return
+44 -44
View File
@@ -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 -197
View File
@@ -1,197 +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/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
/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
+45 -45
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+46 -46
View File
@@ -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
View File
@@ -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)
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
View File
@@ -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)
+1 -1
View File
@@ -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>")
@@ -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
@@ -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
@@ -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 -1
View File
@@ -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
File diff suppressed because it is too large Load Diff
+44 -44
View File
@@ -1,44 +1,44 @@
//Exile implants will allow you to use the station gate, but not return home.
//This will allow security to exile badguys/for badguys to exile their kill targets
/obj/item/implant/exile
name = "exile implant"
desc = "Prevents you from returning from away missions"
origin_tech = "materials=2;biotech=3;magnets=2;bluespace=3"
activated = 0
/obj/item/implant/exile/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
<b>Name:</b> Nanotrasen Employee Exile Implant<BR>
<b>Implant Details:</b> The onboard gateway system has been modified to reject entry by individuals containing this implant<BR>"}
return dat
/obj/item/implanter/exile
name = "implanter (exile)"
/obj/item/implanter/exile/New()
imp = new /obj/item/implant/exile( src )
..()
/obj/item/implantcase/exile
name = "implant case - 'Exile'"
desc = "A glass case containing an exile implant."
/obj/item/implantcase/exile/New()
imp = new /obj/item/implant/exile(src)
..()
/obj/structure/closet/secure_closet/exile
name = "exile implants"
req_access = list(access_armory)
/obj/structure/closet/secure_closet/exile/New()
..()
new /obj/item/implanter/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
//Exile implants will allow you to use the station gate, but not return home.
//This will allow security to exile badguys/for badguys to exile their kill targets
/obj/item/implant/exile
name = "exile implant"
desc = "Prevents you from returning from away missions"
origin_tech = "materials=2;biotech=3;magnets=2;bluespace=3"
activated = 0
/obj/item/implant/exile/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
<b>Name:</b> Nanotrasen Employee Exile Implant<BR>
<b>Implant Details:</b> The onboard gateway system has been modified to reject entry by individuals containing this implant<BR>"}
return dat
/obj/item/implanter/exile
name = "implanter (exile)"
/obj/item/implanter/exile/New()
imp = new /obj/item/implant/exile( src )
..()
/obj/item/implantcase/exile
name = "implant case - 'Exile'"
desc = "A glass case containing an exile implant."
/obj/item/implantcase/exile/New()
imp = new /obj/item/implant/exile(src)
..()
/obj/structure/closet/secure_closet/exile
name = "exile implants"
req_access = list(ACCESS_ARMORY)
/obj/structure/closet/secure_closet/exile/New()
..()
new /obj/item/implanter/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
+295 -295
View File
@@ -1,295 +1,295 @@
var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
icon = 'icons/obj/machines/gateway.dmi'
icon_state = "off"
density = 1
anchored = 1
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/active = 0
/obj/machinery/gateway/Initialize()
..()
update_icon()
update_density_from_dir()
/obj/machinery/gateway/proc/update_density_from_dir()
if(dir == 2)
density = 0
/obj/machinery/gateway/update_icon()
if(active)
icon_state = "on"
return
icon_state = "off"
//this is da important part wot makes things go
/obj/machinery/gateway/centerstation
density = 1
icon_state = "offcenter"
use_power = IDLE_POWER_USE
//warping vars
var/list/linked = list()
var/ready = 0 //have we got all the parts for a gateway?
var/wait = 0 //this just grabs world.time at world start
var/obj/machinery/gateway/centeraway/awaygate = null
/obj/machinery/gateway/centerstation/New()
..()
if(!the_gateway)
the_gateway = src
/obj/machinery/gateway/centerstation/Initialize()
..()
update_icon()
wait = world.time + config.gateway_delay //+ thirty minutes default
awaygate = locate(/obj/machinery/gateway/centeraway) in world
/obj/machinery/gateway/centerstation/update_density_from_dir()
return
/obj/machinery/gateway/centerstation/Destroy()
if(the_gateway == src)
the_gateway = null
return ..()
/obj/machinery/gateway/centerstation/update_icon()
if(active)
icon_state = "oncenter"
return
icon_state = "offcenter"
/obj/machinery/gateway/centerstation/process()
if(stat & (NOPOWER))
if(active) toggleoff()
return
if(active)
use_power(5000)
/obj/machinery/gateway/centerstation/proc/detect()
linked = list() //clear the list
var/turf/T = loc
for(var/i in alldirs)
T = get_step(loc, i)
var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T
if(G)
linked.Add(G)
continue
//this is only done if we fail to find a part
ready = 0
toggleoff()
break
if(linked.len == 8)
ready = 1
/obj/machinery/gateway/centerstation/proc/toggleon(mob/user as mob)
if(!ready)
return
if(linked.len != 8)
return
if(!powered())
return
if(!awaygate)
awaygate = locate(/obj/machinery/gateway/centeraway) in world
if(!awaygate)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
if(world.time < wait)
to_chat(user, "<span class='notice'>Error: Warpspace triangulation in progress. Estimated time to completion: [round(((wait - world.time) / 10) / 60)] minutes.</span>")
return
for(var/obj/machinery/gateway/G in linked)
G.active = 1
G.update_icon()
active = 1
update_icon()
/obj/machinery/gateway/centerstation/proc/toggleoff()
for(var/obj/machinery/gateway/G in linked)
G.active = 0
G.update_icon()
active = 0
update_icon()
/obj/machinery/gateway/centerstation/attack_hand(mob/user as mob)
if(!ready)
detect()
return
if(!active)
toggleon(user)
return
toggleoff()
//okay, here's the good teleporting stuff
/obj/machinery/gateway/centerstation/Bumped(atom/movable/M as mob|obj)
if(!ready)
return
if(!active)
return
if(!awaygate)
return
if(awaygate.calibrated)
M.forceMove(get_step(awaygate.loc, SOUTH))
M.dir = SOUTH
return
else
var/obj/effect/landmark/dest = pick(awaydestinations)
if(dest)
M.forceMove(dest.loc)
M.dir = SOUTH
use_power(5000)
return
/obj/machinery/gateway/centerstation/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/multitool))
to_chat(user, "The gate is already calibrated, there is no work for you to do here.")
return
return ..()
/////////////////////////////////////Away////////////////////////
/obj/machinery/gateway/centeraway
density = 1
icon_state = "offcenter"
use_power = NO_POWER_USE
var/calibrated = 1
var/list/linked = list() //a list of the connected gateway chunks
var/ready = 0
var/obj/machinery/gateway/centeraway/stationgate = null
/obj/machinery/gateway/centeraway/Initialize()
..()
update_icon()
stationgate = locate(/obj/machinery/gateway/centerstation) in world
/obj/machinery/gateway/centeraway/update_density_from_dir()
return
/obj/machinery/gateway/centeraway/update_icon()
if(active)
icon_state = "oncenter"
return
icon_state = "offcenter"
/obj/machinery/gateway/centeraway/proc/detect()
linked = list() //clear the list
var/turf/T = loc
for(var/i in alldirs)
T = get_step(loc, i)
var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T
if(G)
linked.Add(G)
continue
//this is only done if we fail to find a part
ready = 0
toggleoff()
break
if(linked.len == 8)
ready = 1
/obj/machinery/gateway/centeraway/proc/toggleon(mob/user as mob)
if(!ready)
return
if(linked.len != 8)
return
if(!stationgate)
stationgate = locate(/obj/machinery/gateway/centerstation) in world
if(!stationgate)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
for(var/obj/machinery/gateway/G in linked)
G.active = 1
G.update_icon()
active = 1
update_icon()
/obj/machinery/gateway/centeraway/proc/toggleoff()
for(var/obj/machinery/gateway/G in linked)
G.active = 0
G.update_icon()
active = 0
update_icon()
/obj/machinery/gateway/centeraway/attack_hand(mob/user as mob)
if(!ready)
detect()
return
if(!active)
toggleon(user)
return
toggleoff()
/obj/machinery/gateway/centeraway/Bumped(atom/movable/AM)
if(!ready)
return
if(!active)
return
if(!stationgate || QDELETED(stationgate))
return
if(isliving(AM))
if(exilecheck(AM))
return
else
for(var/mob/living/L in AM.contents)
if(exilecheck(L))
atom_say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return
if(AM.has_buckled_mobs())
for(var/mob/living/L in AM.buckled_mobs)
if(exilecheck(L))
atom_say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
return
AM.forceMove(get_step(stationgate.loc, SOUTH))
AM.setDir(SOUTH)
if(ismob(AM))
var/mob/M = AM
if(M.client)
M.client.move_delay = max(world.time + 5, M.client.move_delay)
/obj/machinery/gateway/centeraway/proc/exilecheck(var/mob/living/carbon/M)
for(var/obj/item/implant/exile/E in M)//Checking that there is an exile implant in the contents
if(E.imp_in == M)//Checking that it's actually implanted vs just in their pocket
to_chat(M, "<span class='notice'>The station gate has detected your exile implant and is blocking your entry.</span>")
return 1
return 0
/obj/machinery/gateway/centeraway/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/multitool))
if(calibrated)
to_chat(user, "<span class='notice'>The gate is already calibrated, there is no work for you to do here.</span>")
return
else
to_chat(user, "<span class='boldnotice'>Recalibration successful!</span><span class='notice'>: This gate's systems have been fine tuned. Travel to this gate will now be on target.</span>")
calibrated = 1
return
return ..()
var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
icon = 'icons/obj/machines/gateway.dmi'
icon_state = "off"
density = 1
anchored = 1
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/active = 0
/obj/machinery/gateway/Initialize()
..()
update_icon()
update_density_from_dir()
/obj/machinery/gateway/proc/update_density_from_dir()
if(dir == 2)
density = 0
/obj/machinery/gateway/update_icon()
if(active)
icon_state = "on"
return
icon_state = "off"
//this is da important part wot makes things go
/obj/machinery/gateway/centerstation
density = 1
icon_state = "offcenter"
use_power = IDLE_POWER_USE
//warping vars
var/list/linked = list()
var/ready = 0 //have we got all the parts for a gateway?
var/wait = 0 //this just grabs world.time at world start
var/obj/machinery/gateway/centeraway/awaygate = null
/obj/machinery/gateway/centerstation/New()
..()
if(!the_gateway)
the_gateway = src
/obj/machinery/gateway/centerstation/Initialize()
..()
update_icon()
wait = world.time + config.gateway_delay //+ thirty minutes default
awaygate = locate(/obj/machinery/gateway/centeraway) in world
/obj/machinery/gateway/centerstation/update_density_from_dir()
return
/obj/machinery/gateway/centerstation/Destroy()
if(the_gateway == src)
the_gateway = null
return ..()
/obj/machinery/gateway/centerstation/update_icon()
if(active)
icon_state = "oncenter"
return
icon_state = "offcenter"
/obj/machinery/gateway/centerstation/process()
if(stat & (NOPOWER))
if(active) toggleoff()
return
if(active)
use_power(5000)
/obj/machinery/gateway/centerstation/proc/detect()
linked = list() //clear the list
var/turf/T = loc
for(var/i in alldirs)
T = get_step(loc, i)
var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T
if(G)
linked.Add(G)
continue
//this is only done if we fail to find a part
ready = 0
toggleoff()
break
if(linked.len == 8)
ready = 1
/obj/machinery/gateway/centerstation/proc/toggleon(mob/user as mob)
if(!ready)
return
if(linked.len != 8)
return
if(!powered())
return
if(!awaygate)
awaygate = locate(/obj/machinery/gateway/centeraway) in world
if(!awaygate)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
if(world.time < wait)
to_chat(user, "<span class='notice'>Error: Warpspace triangulation in progress. Estimated time to completion: [round(((wait - world.time) / 10) / 60)] minutes.</span>")
return
for(var/obj/machinery/gateway/G in linked)
G.active = 1
G.update_icon()
active = 1
update_icon()
/obj/machinery/gateway/centerstation/proc/toggleoff()
for(var/obj/machinery/gateway/G in linked)
G.active = 0
G.update_icon()
active = 0
update_icon()
/obj/machinery/gateway/centerstation/attack_hand(mob/user as mob)
if(!ready)
detect()
return
if(!active)
toggleon(user)
return
toggleoff()
//okay, here's the good teleporting stuff
/obj/machinery/gateway/centerstation/Bumped(atom/movable/M as mob|obj)
if(!ready)
return
if(!active)
return
if(!awaygate)
return
if(awaygate.calibrated)
M.forceMove(get_step(awaygate.loc, SOUTH))
M.dir = SOUTH
return
else
var/obj/effect/landmark/dest = pick(awaydestinations)
if(dest)
M.forceMove(dest.loc)
M.dir = SOUTH
use_power(5000)
return
/obj/machinery/gateway/centerstation/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/multitool))
to_chat(user, "The gate is already calibrated, there is no work for you to do here.")
return
return ..()
/////////////////////////////////////Away////////////////////////
/obj/machinery/gateway/centeraway
density = 1
icon_state = "offcenter"
use_power = NO_POWER_USE
var/calibrated = 1
var/list/linked = list() //a list of the connected gateway chunks
var/ready = 0
var/obj/machinery/gateway/centeraway/stationgate = null
/obj/machinery/gateway/centeraway/Initialize()
..()
update_icon()
stationgate = locate(/obj/machinery/gateway/centerstation) in world
/obj/machinery/gateway/centeraway/update_density_from_dir()
return
/obj/machinery/gateway/centeraway/update_icon()
if(active)
icon_state = "oncenter"
return
icon_state = "offcenter"
/obj/machinery/gateway/centeraway/proc/detect()
linked = list() //clear the list
var/turf/T = loc
for(var/i in alldirs)
T = get_step(loc, i)
var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T
if(G)
linked.Add(G)
continue
//this is only done if we fail to find a part
ready = 0
toggleoff()
break
if(linked.len == 8)
ready = 1
/obj/machinery/gateway/centeraway/proc/toggleon(mob/user as mob)
if(!ready)
return
if(linked.len != 8)
return
if(!stationgate)
stationgate = locate(/obj/machinery/gateway/centerstation) in world
if(!stationgate)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
for(var/obj/machinery/gateway/G in linked)
G.active = 1
G.update_icon()
active = 1
update_icon()
/obj/machinery/gateway/centeraway/proc/toggleoff()
for(var/obj/machinery/gateway/G in linked)
G.active = 0
G.update_icon()
active = 0
update_icon()
/obj/machinery/gateway/centeraway/attack_hand(mob/user as mob)
if(!ready)
detect()
return
if(!active)
toggleon(user)
return
toggleoff()
/obj/machinery/gateway/centeraway/Bumped(atom/movable/AM)
if(!ready)
return
if(!active)
return
if(!stationgate || QDELETED(stationgate))
return
if(isliving(AM))
if(exilecheck(AM))
return
else
for(var/mob/living/L in AM.contents)
if(exilecheck(L))
atom_say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return
if(AM.has_buckled_mobs())
for(var/mob/living/L in AM.buckled_mobs)
if(exilecheck(L))
atom_say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
return
AM.forceMove(get_step(stationgate.loc, SOUTH))
AM.setDir(SOUTH)
if(ismob(AM))
var/mob/M = AM
if(M.client)
M.client.move_delay = max(world.time + 5, M.client.move_delay)
/obj/machinery/gateway/centeraway/proc/exilecheck(var/mob/living/carbon/M)
for(var/obj/item/implant/exile/E in M)//Checking that there is an exile implant in the contents
if(E.imp_in == M)//Checking that it's actually implanted vs just in their pocket
to_chat(M, "<span class='notice'>The station gate has detected your exile implant and is blocking your entry.</span>")
return 1
return 0
/obj/machinery/gateway/centeraway/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/multitool))
if(calibrated)
to_chat(user, "<span class='notice'>The gate is already calibrated, there is no work for you to do here.</span>")
return
else
to_chat(user, "<span class='boldnotice'>Recalibration successful!</span><span class='notice'>: This gate's systems have been fine tuned. Travel to this gate will now be on target.</span>")
calibrated = 1
return
return ..()
+25 -25
View File
@@ -1,25 +1,25 @@
/obj/effect/spawner/away/lootdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x2"
var/lootcount = 1 //how many items will be spawned
var/lootdoubles = 0 //if the same item can be spawned twice
var/loot = "" //a list of possible items to spawn- a string of paths
/obj/effect/spawner/away/lootdrop/Initialize()
..()
var/list/things = params2list(loot)
if(things && things.len)
for(var/i = lootcount, i > 0, i--)
if(!things.len)
return
var/loot_spawn = pick(things)
var/loot_path = text2path(loot_spawn)
if(!loot_path || !lootdoubles)
things.Remove(loot_spawn)
continue
new loot_path(get_turf(src))
qdel(src)
/obj/effect/spawner/away/lootdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x2"
var/lootcount = 1 //how many items will be spawned
var/lootdoubles = 0 //if the same item can be spawned twice
var/loot = "" //a list of possible items to spawn- a string of paths
/obj/effect/spawner/away/lootdrop/Initialize()
..()
var/list/things = params2list(loot)
if(things && things.len)
for(var/i = lootcount, i > 0, i--)
if(!things.len)
return
var/loot_spawn = pick(things)
var/loot_path = text2path(loot_spawn)
if(!loot_path || !lootdoubles)
things.Remove(loot_spawn)
continue
new loot_path(get_turf(src))
qdel(src)
@@ -70,4 +70,4 @@ dmm_suite{
// map_name: A valid name for the map to be saved, such as "castle" (Required).
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
}
}
}
@@ -224,7 +224,7 @@
name = "ID Upgrade Machine"
icon_state = "guest"
icon_screen = "pass"
var/list/access_to_give = list(access_away01)
var/list/access_to_give = list(ACCESS_AWAY01)
var/beenused = 0
var/door_to_open = "UO71_Start"
@@ -25,4 +25,4 @@
W.dir = dir
spawn(1)
W.loc = get_step(W, dir)
water_timer = addtimer(CALLBACK(src, .proc/drip), water_frequency, TIMER_STOPPABLE)
water_timer = addtimer(CALLBACK(src, .proc/drip), water_frequency, TIMER_STOPPABLE)
@@ -23,4 +23,4 @@
/area/awaymission/BMPship/Gate
name = "\improper Gateway Block"
icon_state = "away4"
requires_power = TRUE
requires_power = TRUE
@@ -60,4 +60,4 @@
teams never did figure out what happened that last time... and I can't wrap my head \
around it myself. Why would a shuttle full of evacuees all snap and beat each other \
to death the moment they reached safety?<br>\
- D. Cereza"
- D. Cereza"
@@ -20,4 +20,4 @@
Couldn't make it back to my shack. That gun would have helped, if only I brought it...<br> \
Cave-in has me trapped in here, I just hope the distress signal reaches help in time... <br> \
<br> \
He knows. He knows. He knows. He knows. He knows. He knows. He knows. He knows. He knows."
He knows. He knows. He knows. He knows. He knows. He knows. He knows. He knows. He knows."
@@ -107,4 +107,4 @@
/obj/structure/showcase/machinery/oldpod/used
name = "opened cryogenic pod"
desc = "A cryogenic pod that has recently discharged its occupant. The pod appears non-functional."
desc = "A cryogenic pod that has recently discharged its occupant. The pod appears non-functional."
@@ -18,7 +18,7 @@
desc = "A perfectly retrograde identification card. Looks like it could use some flavor."
icon = 'icons/obj/card.dmi'
icon_state = "retro"
access = list(access_away01)
access = list(ACCESS_AWAY01)
/obj/item/card/id/away/old/sec
name = "Security Officer ID"
@@ -44,7 +44,7 @@
name = "APC Access ID"
desc = "A special ID card that allows access to APC terminals."
icon_state = "centcom_old"
access = list(access_engine_equip)
access = list(ACCESS_ENGINE_EQUIP)
/obj/item/storage/backpack/old
max_combined_w_class = 12
@@ -364,4 +364,4 @@
/area/ruin/space/ancientstation/hivebot
name = "Hivebot Mothership"
icon_state = "teleporter"
icon_state = "teleporter"
@@ -14,4 +14,4 @@
/obj/item/spellbook/oneuse/summonitem = 20,
/obj/item/spellbook/oneuse/forcewall = 10,
/obj/item/soulstone = 15 //spooky wizard stuff
)
)
@@ -32,4 +32,4 @@
name = "\improper Syndicate Fighter"
/area/awaymission/spacebattle/secret
name = "\improper Hidden Chamber"
name = "\improper Hidden Chamber"
@@ -276,4 +276,4 @@
spawn(300)
if(D.occupant == deadbeat)
// they still haven't checked out...
checkout(roomid)
checkout(roomid)
@@ -199,4 +199,4 @@ var/sc_safecode5 = "[rand(0,9)]"
return
/obj/singularity/narsie/sc_Narsie/ex_act()
return
return
+38 -38
View File
@@ -1,38 +1,38 @@
/obj/item/paper/pamphlet
name = "pamphlet"
icon_state = "pamphlet"
info = "<b>Welcome to the Nanotrasen Gateway project...</b><br>\
Congratulations! If you're reading this, you and your superiors have decided that you're \
ready to commit to a life spent colonising the rolling hills of far away worlds. You \
must be ready for a lifetime of adventure, a little bit of hard work, and an award \
winning dental plan- but that's not all the Nanotrasen Gateway project has to offer.<br>\
<br>Because we care about you, we feel it is only fair to make sure you know the risks \
before you commit to joining the Nanotrasen Gateway project. All away destinations have \
been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \
We've even left a case of space beer along with the basic materials you'll need to expand \
Nanotrasen's operational area and start your new life.<br><br>\
<b>Gateway Operation Basics</b><br>\
All Nanotrasen approved Gateways operate on the same basic principals. They operate off \
area equipment power as you would expect, but they also require a backup wire with at least \
128, 000 Watts of power running through it. Without this supply, it cannot safely function \
and will reject all attempts at operation.<br><br>\
Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \
searching for an output location. The amount of time this takes is variable, but the Gateway \
interface will give you an estimate accurate to the minute. Power loss will not interrupt the \
searching process. Influenza will not interrupt the searching process. Temporal anomalies \
may cause the estimate to be inaccurate, but will not interrupt the searching process.<br><br> \
<b>Life On The Other Side</b><br>\
Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \
This is a normal side effect of travelling vast distances in a short period of time. You should \
survey the immediate area, and attempt to locate your complimentary case of space beer. Our \
expeditionary teams have ensured the complete safety of all away locations, but in a small \
number of cases, the Gateway they have established may not be immediately obvious. \
Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \
<br><br><b>A New World</b><br>\
As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \
Though complete safety is assured, participants are advised to prepare for inhospitable \
environs."
//we don't want the silly text overlay!
/obj/item/paper/pamphlet/update_icon()
return
/obj/item/paper/pamphlet
name = "pamphlet"
icon_state = "pamphlet"
info = "<b>Welcome to the Nanotrasen Gateway project...</b><br>\
Congratulations! If you're reading this, you and your superiors have decided that you're \
ready to commit to a life spent colonising the rolling hills of far away worlds. You \
must be ready for a lifetime of adventure, a little bit of hard work, and an award \
winning dental plan- but that's not all the Nanotrasen Gateway project has to offer.<br>\
<br>Because we care about you, we feel it is only fair to make sure you know the risks \
before you commit to joining the Nanotrasen Gateway project. All away destinations have \
been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \
We've even left a case of space beer along with the basic materials you'll need to expand \
Nanotrasen's operational area and start your new life.<br><br>\
<b>Gateway Operation Basics</b><br>\
All Nanotrasen approved Gateways operate on the same basic principals. They operate off \
area equipment power as you would expect, but they also require a backup wire with at least \
128, 000 Watts of power running through it. Without this supply, it cannot safely function \
and will reject all attempts at operation.<br><br>\
Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \
searching for an output location. The amount of time this takes is variable, but the Gateway \
interface will give you an estimate accurate to the minute. Power loss will not interrupt the \
searching process. Influenza will not interrupt the searching process. Temporal anomalies \
may cause the estimate to be inaccurate, but will not interrupt the searching process.<br><br> \
<b>Life On The Other Side</b><br>\
Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \
This is a normal side effect of travelling vast distances in a short period of time. You should \
survey the immediate area, and attempt to locate your complimentary case of space beer. Our \
expeditionary teams have ensured the complete safety of all away locations, but in a small \
number of cases, the Gateway they have established may not be immediately obvious. \
Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \
<br><br><b>A New World</b><br>\
As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \
Though complete safety is assured, participants are advised to prepare for inhospitable \
environs."
//we don't want the silly text overlay!
/obj/item/paper/pamphlet/update_icon()
return
+1 -1
View File
@@ -370,4 +370,4 @@
screen_loc = "CENTER[ox >= 0 ? "+" : ""][ox],CENTER[oy >= 0 ? "+" : ""][oy]"
/obj/effect/view_portal_dummy/attack_ghost(mob/user)
owner.attack_ghost(user)
owner.attack_ghost(user)
+1 -1
View File
@@ -294,4 +294,4 @@ Existing varieties:
+ *Left click a location*:
Cause an explosion where you clicked.
Cause an explosion where you clicked.
+1 -1
View File
@@ -84,4 +84,4 @@
deselect_region()
/datum/buildmode_mode/proc/handle_selected_region(mob/user, params)
return
return
+1 -1
View File
@@ -125,4 +125,4 @@
#undef BM_SWITCHSTATE_NONE
#undef BM_SWITCHSTATE_MODE
#undef BM_SWITCHSTATE_DIR
#undef BM_SWITCHSTATE_DIR
+1 -1
View File
@@ -85,4 +85,4 @@
/obj/screen/buildmode/quit/Click()
bd.quit()
return TRUE
return TRUE
+1 -1
View File
@@ -25,4 +25,4 @@
cl.images -= I
cl = null
QDEL_NULL(I)
return ..()
return ..()
+1 -1
View File
@@ -56,4 +56,4 @@
if(isobj(object))
log_admin("Build Mode: [key_name(user)] deleted [object] at ([object.x],[object.y],[object.z])")
qdel(object)
+1 -1
View File
@@ -69,4 +69,4 @@
T.air_update_turf()
// admin log
log_admin("Build Mode: [key_name(user)] changed the atmos of region [COORD(cornerA)] to [COORD(cornerB)]. T: [temperature], P: [pressure], Ox: [oxygen]%, N2: [nitrogen]%, Plsma: [plasma]%, CO2: [cdiox]%, N2O: [nitrox]%. [ctrl_click ? "Overwrote base unsimulated turf gases." : ""]")
log_admin("Build Mode: [key_name(user)] changed the atmos of region [COORD(cornerA)] to [COORD(cornerB)]. T: [temperature], P: [pressure], Ox: [oxygen]%, N2: [nitrogen]%, Plsma: [plasma]%, CO2: [cdiox]%, N2O: [nitrox]%. [ctrl_click ? "Overwrote base unsimulated turf gases." : ""]")

Some files were not shown because too many files have changed in this diff Show More