Merge remote-tracking branch 'upstream/dev' into 150703-Uplinkery

Conflicts:
	code/datums/datacore.dm
	code/defines/obj.dm
This commit is contained in:
PsiOmegaDelta
2015-08-13 08:11:32 +02:00
425 changed files with 9891 additions and 8955 deletions

View File

@@ -302,7 +302,11 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
output += "<option value='[j]'>[j]</option>"
for(var/j in nonhuman_positions)
output += "<option value='[j]'>[j]</option>"
for(var/j in list("traitor","changeling","operative","revolutionary","cultist","wizard"))
var/list/bantypes = list("traitor","changeling","operative","revolutionary","cultist","wizard") //For legacy bans.
for(var/antag_type in all_antag_types) // Grab other bans.
var/datum/antagonist/antag = all_antag_types[antag_type]
bantypes |= antag.bantype
for(var/j in bantypes)
output += "<option value='[j]'>[j]</option>"
output += "</select></td></tr></table>"
output += "<b>Reason:<br></b><textarea name='dbbanreason' cols='50'></textarea><br>"

View File

@@ -23,7 +23,7 @@
/proc/ToRban_update()
spawn(0)
log_misc("Downloading updated ToR data...")
var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
var/http[] = world.Export("https://check.torproject.org/exit-addresses")
var/list/rawlist = file2list(http["CONTENT"])
if(rawlist.len)

View File

@@ -1097,7 +1097,7 @@ proc/admin_notice(var/message, var/rights)
else
new chosen(usr.loc)
log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])")
log_and_message_admins("spawned [chosen] at ([usr.x],[usr.y],[usr.z])")
feedback_add_details("admin_verb","SA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -83,10 +83,13 @@ var/list/admin_verbs_admin = list(
/client/proc/allow_character_respawn, /* Allows a ghost to respawn */
/client/proc/event_manager_panel,
/client/proc/empty_ai_core_toggle_latejoin,
/client/proc/empty_ai_core_toggle_latejoin,
/client/proc/aooc,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
/client/proc/change_security_level
/client/proc/change_security_level,
/client/proc/view_chemical_reaction_logs,
/client/proc/makePAI
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,

View File

@@ -1,147 +1,147 @@
//This stuff was originally intended to be integrated into the ban-system I was working on
//but it's safe to say that'll never be finished. So I've merged it into the current player panel.
//enjoy ~Carn
/*
#define NOTESFILE "data/player_notes.sav" //where the player notes are saved
datum/admins/proc/notes_show(var/ckey)
usr << browse("<head><title>Player Notes</title></head><body>[notes_gethtml(ckey)]</body>","window=player_notes;size=700x400")
datum/admins/proc/notes_gethtml(var/ckey)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return "<font color='red'>Error: Cannot access [NOTESFILE]</font>"
if(ckey)
. = "<b>Notes for <a href='?src=\ref[src];notes=show'>[ckey]</a>:</b> <a href='?src=\ref[src];notes=add;ckey=[ckey]'>\[+\]</a> <a href='?src=\ref[src];notes=remove;ckey=[ckey]'>\[-\]</a><br>"
notesfile.cd = "/[ckey]"
var/index = 1
while( !notesfile.eof )
var/note
notesfile >> note
. += "[note] <a href='?src=\ref[src];notes=remove;ckey=[ckey];from=[index]'>\[-\]</a><br>"
index++
else
. = "<b>All Notes:</b> <a href='?src=\ref[src];notes=add'>\[+\]</a> <a href='?src=\ref[src];notes=remove'>\[-\]</a><br>"
notesfile.cd = "/"
for(var/dir in notesfile.dir)
. += "<a href='?src=\ref[src];notes=show;ckey=[dir]'>[dir]</a><br>"
return
//handles removing entries from the buffer, or removing the entire directory if no start_index is given
/proc/notes_remove(var/ckey, var/start_index, var/end_index)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return
if(!ckey)
notesfile.cd = "/"
ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir)
if(!ckey) return
if(start_index)
notesfile.cd = "/[ckey]"
var/list/noteslist = list()
if(!end_index) end_index = start_index
var/index = 0
while( !notesfile.eof )
index++
var/temp
notesfile >> temp
if( (start_index <= index) && (index <= end_index) )
continue
noteslist += temp
notesfile.eof = -2 //Move to the start of the buffer and then erase.
for( var/note in noteslist )
notesfile << note
else
notesfile.cd = "/"
if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes")
notesfile.dir.Remove(ckey)
return
#undef NOTESFILE
*/
//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky.
//This stuff was originally intended to be integrated into the ban-system I was working on
//but it's safe to say that'll never be finished. So I've merged it into the current player panel.
//enjoy ~Carn
/*
#define NOTESFILE "data/player_notes.sav" //where the player notes are saved
datum/admins/proc/notes_show(var/ckey)
usr << browse("<head><title>Player Notes</title></head><body>[notes_gethtml(ckey)]</body>","window=player_notes;size=700x400")
datum/admins/proc/notes_gethtml(var/ckey)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return "<font color='red'>Error: Cannot access [NOTESFILE]</font>"
if(ckey)
. = "<b>Notes for <a href='?src=\ref[src];notes=show'>[ckey]</a>:</b> <a href='?src=\ref[src];notes=add;ckey=[ckey]'>\[+\]</a> <a href='?src=\ref[src];notes=remove;ckey=[ckey]'>\[-\]</a><br>"
notesfile.cd = "/[ckey]"
var/index = 1
while( !notesfile.eof )
var/note
notesfile >> note
. += "[note] <a href='?src=\ref[src];notes=remove;ckey=[ckey];from=[index]'>\[-\]</a><br>"
index++
else
. = "<b>All Notes:</b> <a href='?src=\ref[src];notes=add'>\[+\]</a> <a href='?src=\ref[src];notes=remove'>\[-\]</a><br>"
notesfile.cd = "/"
for(var/dir in notesfile.dir)
. += "<a href='?src=\ref[src];notes=show;ckey=[dir]'>[dir]</a><br>"
return
//handles removing entries from the buffer, or removing the entire directory if no start_index is given
/proc/notes_remove(var/ckey, var/start_index, var/end_index)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return
if(!ckey)
notesfile.cd = "/"
ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir)
if(!ckey) return
if(start_index)
notesfile.cd = "/[ckey]"
var/list/noteslist = list()
if(!end_index) end_index = start_index
var/index = 0
while( !notesfile.eof )
index++
var/temp
notesfile >> temp
if( (start_index <= index) && (index <= end_index) )
continue
noteslist += temp
notesfile.eof = -2 //Move to the start of the buffer and then erase.
for( var/note in noteslist )
notesfile << note
else
notesfile.cd = "/"
if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes")
notesfile.dir.Remove(ckey)
return
#undef NOTESFILE
*/
//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky.
/proc/notes_add(var/key, var/note, var/mob/user)
if (!key || !note)
return
//Loading list of notes for this key
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos) infos = list()
//Overly complex timestamp creation
var/modifyer = "th"
switch(time2text(world.timeofday, "DD"))
if("01","21","31")
modifyer = "st"
if("02","22",)
modifyer = "nd"
if("03","23")
modifyer = "rd"
var/day_string = "[time2text(world.timeofday, "DD")][modifyer]"
if(copytext(day_string,1,2) == "0")
day_string = copytext(day_string,2)
var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY")
var/day_loc = findtext(full_date, time2text(world.timeofday, "DD"))
var/datum/player_info/P = new
if (!key || !note)
return
//Loading list of notes for this key
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos) infos = list()
//Overly complex timestamp creation
var/modifyer = "th"
switch(time2text(world.timeofday, "DD"))
if("01","21","31")
modifyer = "st"
if("02","22",)
modifyer = "nd"
if("03","23")
modifyer = "rd"
var/day_string = "[time2text(world.timeofday, "DD")][modifyer]"
if(copytext(day_string,1,2) == "0")
day_string = copytext(day_string,2)
var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY")
var/day_loc = findtext(full_date, time2text(world.timeofday, "DD"))
var/datum/player_info/P = new
if (user)
P.author = user.key
P.rank = user.client.holder.rank
else
P.author = "Adminbot"
P.rank = "Friendly Robot"
P.content = note
P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]"
infos += P
info << infos
else
P.author = "Adminbot"
P.rank = "Friendly Robot"
P.content = note
P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]"
infos += P
info << infos
message_admins("\blue [key_name_admin(user)] has edited [key]'s notes.")
log_admin("[key_name(user)] has edited [key]'s notes.")
qdel(info)
//Updating list of keys with notes on them
var/savefile/note_list = new("data/player_notes.sav")
var/list/note_keys
note_list >> note_keys
if(!note_keys) note_keys = list()
if(!note_keys.Find(key)) note_keys += key
note_list << note_keys
qdel(note_list)
/proc/notes_del(var/key, var/index)
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos || infos.len < index) return
var/datum/player_info/item = infos[index]
infos.Remove(item)
info << infos
message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.")
log_admin("[key_name(usr)] deleted one of [key]'s notes.")
qdel(info)
/proc/show_player_info_irc(var/key as text)
var/dat = " Info on [key]%0D%0A"
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos)
dat = "No information found on the given key."
else
for(var/datum/player_info/I in infos)
dat += "[I.content]%0D%0Aby [I.author] ([I.rank]) on [I.timestamp]%0D%0A%0D%0A"
return dat
qdel(info)
//Updating list of keys with notes on them
var/savefile/note_list = new("data/player_notes.sav")
var/list/note_keys
note_list >> note_keys
if(!note_keys) note_keys = list()
if(!note_keys.Find(key)) note_keys += key
note_list << note_keys
qdel(note_list)
/proc/notes_del(var/key, var/index)
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos || infos.len < index) return
var/datum/player_info/item = infos[index]
infos.Remove(item)
info << infos
message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.")
log_admin("[key_name(usr)] deleted one of [key]'s notes.")
qdel(info)
/proc/show_player_info_irc(var/key as text)
var/dat = " Info on [key]\n"
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos)
dat = "No information found on the given key."
else
for(var/datum/player_info/I in infos)
dat += "[I.content]\nby [I.author] ([I.rank]) on [I.timestamp]\n\n"
return list2params(list(dat))

View File

@@ -358,7 +358,7 @@
dat += "<td>NA</td>"
dat += {"<td>[(M.client ? "[M.client]" : "No client")]</td>
dat += {"<td>[M.key ? (M.client ? M.key : "[M.key] (DC)") : "No key"]</td>
<td align=center><A HREF='?src=\ref[src];adminplayeropts=\ref[M]'>X</A></td>
<td align=center><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>
"}

View File

@@ -574,7 +574,13 @@
//JOBBAN'S INNARDS
else if(href_list["jobban3"])
if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN)) return
if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN,0))
usr << "<span class='warning'>You do not have the appropriate permissions to add job bans!</span>"
return
if(check_rights(R_MOD,0) && !check_rights(R_ADMIN,0) && !config.mods_can_job_tempban) // If mod and tempban disabled
usr << "<span class='warning'>Mod jobbanning is disabled!</span>"
return
var/mob/M = locate(href_list["jobban4"])
if(!ismob(M))
@@ -649,13 +655,18 @@
if(notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban.
switch(alert("Temporary Ban?",,"Yes","No", "Cancel"))
if("Yes")
if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return
if(!check_rights(R_MOD,0) && !check_rights(R_BAN, 0))
usr << "<span class='warning'> You Cannot issue temporary job-bans!</span>"
return
if(config.ban_legacy_system)
usr << "\red Your server is using the legacy banning system, which does not support temporary job bans. Consider upgrading. Aborting ban."
return
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
if(!mins)
return
if(check_rights(R_MOD, 0) && !check_rights(R_BAN, 0) && mins > config.mod_job_tempban_max)
usr << "<span class='warning'> Moderators can only job tempban up to [config.mod_job_tempban_max] minutes!</span>"
return
var/reason = sanitize(input(usr,"Reason?","Please State Reason","") as text|null)
if(!reason)
return
@@ -764,7 +775,13 @@
DB_ban_unban(ckey(key), BANTYPE_JOB_PERMA, job)
else if(href_list["newban"])
if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return
if(!check_rights(R_MOD,0) && !check_rights(R_BAN, 0))
usr << "<span class='warning'>You do not have the appropriate permissions to add bans!</span>"
return
if(check_rights(R_MOD,0) && !check_rights(R_ADMIN, 0) && !config.mods_can_job_tempban) // If mod and tempban disabled
usr << "<span class='warning'>Mod jobbanning is disabled!</span>"
return
var/mob/M = locate(href_list["newban"])
if(!ismob(M)) return
@@ -776,6 +793,9 @@
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
if(!mins)
return
if(check_rights(R_MOD, 0) && !check_rights(R_BAN, 0) && mins > config.mod_tempban_max)
usr << "<span class='warning'>Moderators can only job tempban up to [config.mod_tempban_max] minutes!</span>"
return
if(mins >= 525600) mins = 525599
var/reason = sanitize(input(usr,"Reason?","reason","Griefer") as text|null)
if(!reason)
@@ -1314,7 +1334,7 @@
src.owner << "You sent [input] to [L] via a secure channel."
log_admin("[src.owner] replied to [key_name(L)]'s Centcomm message with the message [input].")
message_admins("[src.owner] replied to [key_name(L)]'s Centcom message with: \"[input]\"")
if(!L.isAI())
if(!L.isMobAI())
L << "<span class='info'>You hear something crackle in your headset for a moment before a voice speaks.</span>"
L << "<span class='info'>Please stand by for a message from Central Command.</span>"
L << "<span class='info'>Message as follows.</span>"
@@ -1344,7 +1364,7 @@
var/obj/item/fax = locate(href_list["AdminFaxView"])
if (istype(fax, /obj/item/weapon/paper))
var/obj/item/weapon/paper/P = fax
P.show_content(usr)
P.show_content(usr,1)
else if (istype(fax, /obj/item/weapon/photo))
var/obj/item/weapon/photo/H = fax
H.show(usr)
@@ -1631,18 +1651,7 @@
var/mob/M = O
M.real_name = obj_name
if (number == 1)
log_admin("[key_name(usr)] created a [english_list(paths)]")
for(var/path in paths)
if(ispath(path, /mob))
message_admins("[key_name_admin(usr)] created a [english_list(paths)]", 1)
break
else
log_admin("[key_name(usr)] created [number]ea [english_list(paths)]")
for(var/path in paths)
if(ispath(path, /mob))
message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]", 1)
break
log_and_message_admins("created [number] [english_list(paths)]")
return
else if(href_list["secretsfun"])

View File

@@ -42,6 +42,12 @@
icon = 'icons/misc/buildmode.dmi'
var/obj/effect/bmode/buildholder/master = null
/obj/effect/bmode/Destroy()
if(master && master.cl)
master.cl.screen -= src
master = null
return ..()
/obj/effect/bmode/builddir
icon_state = "build"
screen_loc = "NORTH,WEST"
@@ -117,6 +123,19 @@
var/obj/effect/bmode/buildquit/buildquit = null
var/atom/movable/throw_atom = null
/obj/effect/bmode/buildholder/Destroy()
qdel(builddir)
builddir = null
qdel(buildhelp)
buildhelp = null
qdel(buildmode)
buildmode = null
qdel(buildquit)
buildquit = null
throw_atom = null
cl = null
return ..()
/obj/effect/bmode/buildmode
icon_state = "buildmode1"
screen_loc = "NORTH,WEST+2"

View File

@@ -21,7 +21,7 @@
var/stafftype = uppertext(holder.rank)
msg = sanitize(msg)
log_admin("[key_name(src)] : [msg]")
log_admin("DSAY: [key_name(src)] : [msg]")
if (!msg)
return

View File

@@ -64,6 +64,28 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procname) return
if(targetselected)
if(!target)
usr << "<span class='danger'>Your target no longer exists.</span>"
return
if(!hascall(target,procname))
usr << "<font color='red'>Error: callproc(): target has no such call [procname].</font>"
return
else
if(copytext(procname, 1, 7) == "/proc/")
// nothing
else if(copytext(procname, 1, 6) == "proc/")
procname = "/[procname]"
else if(copytext(procname, 1, 2) == "/")
procname = "/proc[procname]"
else
procname = "/proc/[procname]"
// Procs have the strange property that text2path will return non-null, but ispath() will return false.
var/path = text2path(procname)
if(!path || ispath(path))
usr << "<span class='danger'>Invalid proc [procname]</span>"
return
var/argnum = input("Number of arguments","Number:",0) as num|null
if(!argnum && (argnum!=0)) return
@@ -117,13 +139,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!target)
usr << "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>"
return
if(!hascall(target,procname))
usr << "<font color='red'>Error: callproc(): target has no such call [procname].</font>"
return
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
@@ -200,7 +218,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!choice)
return 0
if(!istype(choice, /mob/dead/observer))
var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank him out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No")
var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank them out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No")
if(confirm != "Yes")
return 0
var/obj/item/device/paicard/card = new(T)

View File

@@ -441,7 +441,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
//Announces the character on all the systems, based on the record.
if(!issilicon(new_character))//If they are not a cyborg/AI.
if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
if(!record_found && !player_is_antag(new_character.mind, only_offstation_roles = 1)) //If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
//Power to the user!
if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
data_core.manifest_inject(new_character)

View File

@@ -52,4 +52,4 @@ var/const/commandos_possible = 6 //if more Commandos are needed in the future
usr << "Looks like someone beat you to it."
return
team.attempt_spawn(1)
team.attempt_random_spawn()