ID:268446
 
Thanks Spuzzum for the GM controls, and thanks AJX for editting them :P
/*
/////////////////////////////////////////////////////////////////////
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////////////////////////////////
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////////////////////////////////
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/////////////////////////////////////////////////////////////////////
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\


*****************************************************
*****************************************************
AJX's Modification of Spuzzum's Administrative Library
Modified Version - v3.0
by AJ "AJX"
*****************************************************
*****************************************************
******************************************************
This is my modification of the great Spuzzum's Admin code...
IMPORTANT NOTE: This was made by Spuzzum, NOT AJX!
All I did was change some stuff around, and add some more stuff!
I TAKE NO CREDIT FOR MOST OF THIS LIBRARY!!!
Although,
Copyright ©2002-2003 AJ "AJX" Huntington. Refer to
A_Admin.html for more copyright information.
/*********************************************/

Spuzzum's Administrative Library v2.2
by Jeremy "Spuzzum" Gibson
/**********************************************/

Refer to the included A_Admin.html for more information
on how to get this library up and running for your world.

Copyright ©2000-2001 Jeremy "Spuzzum" Gibson. Refer to
A_Admin.html for more copyright information.

*********************************************/
//GM PREFIXES AND SUFFIXES

// This is added to the beginning of a GM's name.
// For your convenience, you can set a different
// prefix for the Master GM rather than Admin or
// regular GMs.
//
// If you dislike having the prefix, it can be
// disabled by setting it to 'null'
// Eg. var/const/MASTER_GM_PREFIX = null


var/const/MASTER_GM_PREFIX = "\[M-GM] "
var/const/ADMIN_GM_PREFIX = "\[A-GM] "
var/const/GM_PREFIX = "\[GM] "


// The suffix works like the prefix, but it is
// added to the end of the name rather than the
// beginning.
// For your convenience, you can set a different
// suffix for the Master GM rather than Admin or
// regular GMs.
// By default, these are disabled (see above).

var/const/MASTER_GM_SUFFIX = null
var/const/ADMIN_GM_SUFFIX = null
var/const/GM_SUFFIX = null


/********************************************/
//!!! [MASTER KEY((S))] !!!

// The master key determines who the master GM is.
// The person with the master GM key gains verbs
// that allow him or her to add, remove, and modify
// GMs in addition to the standard functions.
//
// The master GM should usually be the person who
// made the world itself, though it doesn't have to
// be.


//AJ EDITITATION!(If thats a word) I switched some stuff around so
//there could be 5 Masta GMs! Although, u could just make all your
//keys be them... }-p
var/const/MASTER_KEY = "Hell Ramen" //(change my key to yours!)
var/const/MASTER_KEY2 = "Hell Ramen"
var/const/MASTER_KEY3 = "Hell Ramen"
var/const/MASTER_KEY4 = "Hell Ramen"
var/const/MASTER_KEY5 = "Hell Ramen"
//This change is only made in this version for my RPG demo, not any
//others. 5 MORE Master keys, this is for server hosters.
var/const/MASTER_KEY6 = "Hell Ramen"
var/const/MASTER_KEY7 = "Hell Ramen"
var/const/MASTER_KEY8 = "Hell Ramen"
var/const/MASTER_KEY9 = "Hell Ramen "
var/const/MASTER_KEY10 = "Hell Ramen"
/********************************************/
//INACTIVITY BOOTER

// The inactivity setting will occasionally check a player's
// client to see how long it has been inactive. If so, it
// will Logout() the player.
// Times are in seconds. If you don't want this to happen,
// set this equal to zero.
var/const/MAX_INACTIVITY_TIME = 1800//allow 30 mins. (1800 seconds) of AFK

// Note that this is not an exacting figure; the proc that checks clients
// loops itself very, very slowly to prevent lag. They are guaranteed at LEAST
// that amount of time.

/********************************************/
//Hide Report Bad GM Command

//Removed this for this particular game

/********************************************/


/********************************************/
//GM_EDIT SETTINGS

// Though it is a perceivable security risk, if you wish you can allow
// non-master GM types to edit themselves. This feature was partially
// disabled due to both foresight and an error in the code.
// If you wish to allow them to edit themselves, set this to 1.
var/const/ALLOW_GM_SELF_EDIT = 1

/********************************************/

// These are initialised later, so no need to initialize yet.
var/list/GMs
var/list/Admins
//var/list/Bad_GM <--- bye bye


// This is initialised later too. It contains a list of all keys that aren't allowed.
var/list/banned



world
New()
..() //do any other user-provided things first
world.log << "Instance opened at approx. [ReportDate(world.realtime)]."
var/savefile/F = new ("s_admin.sav")

F["banned"] >> banned //load banned list
if(isnull(banned)) //if first time starting
banned = new /list //initialise the list

F["GMs"] >> GMs //load the GM list
if(isnull(GMs)) //if this is the first time starting up
GMs = new /list //initialise.

F["Admins"] >> Admins //load the Admin list
if(isnull(Admins)) //if this is the first time starting up
Admins = new /list //initialise.

F["completelist"] >> completelist //load the player history list
if(isnull(completelist)) //if this is the first time starting up
completelist = new /list //initialise.

Del()
var/savefile/F = new ("s_admin.sav")
F["GMs"] << GMs //save the GM list
F["completelist"] << completelist //save the player history list
F["banned"] << banned //save the banned list
// F["Bad GM"] << Bad_GM <--- bye

world.log << "Instance closed at approx. [ReportDate(world.realtime)]."
..() //and finish closing with other user-provided procs



mob/GM_verbs
// The GM verbs mob contains all of the verbs. Players should
// NOT be able to be this type of mob.
verb
GM_Announce(message as message)
set desc = "() Announce something globally"
set category = "GM"
world << "<font color=red><center>________________________________<br>\..."
world << "<b>Announcement:</b><br>[message]<br>\..."
world << "________________________________</center></font>"
world.log << "[src.name] announced, \"[message]\""


GM_Assimilate(mob/M in world)
set desc = "(NPC) Take over the body of an NPC (Caution!)"
set category = "GM"

if(M.key)
usr << "You can't take over PCs' mobs."
return

//Prevents a possible security breach.
if(istype(M,/mob/admin_GM_verbs) || istype(M,/mob/GM_verbs) \
|| istype(M,/mob/master_GM_verbs))
del(M) //delete the mob. There should never be a mob of those types, ever.

world.log << "[src.name] assimilated [M]."

M.key = src.key

GM_Ban(mob/M in world)
set desc = "(person) Remove a player from your world and don't let them return"
set category = "GM"

if(M == src) return

if(!M.key)
usr << "That is not a player."
return

var/hash = 0

if(GMCheck() && (M.GMCheck() || M.AdminGMCheck() || M.MasterGMCheck())) hash = 1
else if(AdminGMCheck() && (M.AdminGMCheck() || M.MasterGMCheck())) hash = 1
else if(MasterGMCheck() && M.MasterGMCheck()) hash = 1
if(hash)
usr << "You can't ban GMs equal to or higher than you in rank!"
M<<alert("[src] tried to ban you.")
return

if(alert("Are you sure?","Ban [M]:","Yes","No") == "Yes")
banned += M.key
if(M.client)
banned += M.client.address
del(M.client)
for(var/mob/O)
if(O.GMCheck() || O.AdminGMCheck() || O.MasterGMCheck())
O << "[src] banned [M]."
world.log << "[src.name] banned [M] ([M.key]) from the world."
del(M)


GM_Unban()
set desc = "() Remove banned keys and IPs from the banned list"
set category = "GM"

var/removal = input("Remove which IP/key from the ban list?","Unban:") as null|anything \
in banned
if(!removal) return
banned -= removal
for(var/mob/M)
if(M.GMCheck() || M.AdminGMCheck() || M.MasterGMCheck())
M << "[src] removed [removal] from the banned list."


GM_Carboncopy(atom/movable/O in world)
set desc = "() Create an exact duplicate of a given object"
set category = "GM"

var/mob/M = O
if(istype(M) && M:key)
usr << "You can't duplicate PCs' mobs."
return

//Prevents possible security breach.
if(istype(O,/mob/GM_verbs) || istype(O,/mob/admin_GM_verbs) \
|| istype(O,/mob/master_GM_verbs))
del(O)

var/atom/new_O = new O.type(O.loc)
for(var/V in O.vars)
if(issaved(O.vars[V])) new_O.vars[V] = O.vars[V]
usr << "[O] was duplicated."
world.log << "[src.name] duplicated \an [O]."


GM_Lock_All_Movement()
set category = "GM"
for(var/mob/M in world)
M._GM_lockmove = 1
M<<"Your Movement Has Been Locked By [usr]."
if((!M.GMCheck() || !M.AdminGMCheck() || !M.MasterGMCheck()))
M._GM_lockmove = 0
M<<"Your Movement Is Restored Because You Are A GM"
GM_UnLock_All_Movement()
set category = "GM"
for(var/mob/M in world)
M._GM_lockmove = 0
M<<"Your Movement Has Been UnLocked By [usr]."
GM_Create()
set desc = "() Create an object of any type"
set category = "GM"
var/html = "<html><body bgcolor=gray text=#CCCCCC link=white vlink=white alink=white>"
var/L[] = typesof(/atom)

//BYOND BUG
/*
//strip out illegal options
if(L.Find(/atom)) L -= /atom
if(L.Find(/atom/movable)) L -= /atom/movable
//don't allow these three types, either
if(L.Find(/mob/GM_verbs)) L -= /mob/GM_verbs
if(L.Find(/mob/master_GM_verbs)) L -= /mob/master_GM_verbs
if(L.Find(/mob/admin_GM_verbs)) L -= /mob/admin_GM_verbs*/


for(var/X in L)
//WORKAROUND FOR ABOVE BUG
switch("[X]")
if("/atom", "/atom/movable", "/mob/GM_verbs", "/mob/master_GM_verbs",
"/mob/admin_GM_verbs") continue //ignore options of these types
//END OF WORKAROUND

html += "<a href=byond://?src=\ref[src];action=create;type=[X]>[X]</a><br>"

usr << browse(html)
GM_Dissappear()
set desc = "() Toggle invisibility and lack of density"
set category = "GM"
src.density = !density
src.invisibility = !invisibility

if(!density)
oview() << "[src] dematerializes and vanishes!"
src << "You dematerialize and vanish."
src.overlays += 'Invis.dmi'
world.log << "[src.name] becomes invisible."
else
oview() << "[src] suddenly rematerializes and appears!"
src << "You materialize and appear."
src.overlays -= 'Invis.dmi'
world.log << "[src.name] becomes visible."
GM_Eradicate(atom/M as mob|obj|turf|area in world)
set desc = "(target) Destroy an mob, obj, or turf"
set category = "GM"

//If they're a player, we should take special consideration and make
//sure that we really do want to boot this person.
var/mob/mob = M
if(istype(mob) && mob.key)

if(mob == src) //don't let people delete themselves!
return

//If the target is a GM that is equal or higher in rank, it sets hash. When hash is
//checked, it'll stop if the GM can't do that.
var/hash = 0
if(GMCheck() && (mob.GMCheck() || mob.AdminGMCheck() || mob.MasterGMCheck())) hash = 1
else if(AdminGMCheck() && (mob.AdminGMCheck() || mob.MasterGMCheck())) hash = 1
else if(MasterGMCheck() && !mob.MasterGMCheck()) hash = 1
if(hash)
usr << "You can't eradicate GMs equal to or higher than you in rank!"
M << "[src] tried to boot you." //tell them there's dissention among the ranks!
return

//If they input yes,
if((input("Are you sure?") in list("Yes","No")) == "Yes")
var/reason = input("Enter a reason if desired.","Reason?") as \
null|text
if(reason)
//This just randomly chooses some "flavour" text. Your reason should generally
//be generic, not suited to any of these, because otherwise it won't make any
//sense.
//An alternate implementation is beneath these.

///*
world << pick(
"A giant hand swoops down to the ground, plucks [mob] into the sky, and \
promptly tosses \him away, whilst shouting <b>\"
[reason]\"</b>",
"A vat of liquid nitrogen materialises from nowhere and dumps itself on [mob]. \
The label reads, <b>\"
[reason]\"</b>",
"[mob] looks up to see a giant hand. It grabs \him between its fingers and \
smushes him like an ant, booming <b>\"
[reason]\"</b>",
"[mob] turns around to see a sniper in the bushes, who promptly puts a hole \
through \his head and says, <b>\"
[reason]\"</b>",
"An arrow suddenly flies straight through [mob]'s heart. A note attached to \
the arrow says, <b>\"
[reason]\"</b>",
"[mob]'s eyes glaze over as a scroll appears in front of \him that reads \
<b>\"
[reason]\"</b> [mob] promptly screams and then vanishes.",
"[mob], suddenly compelled by supernatural forces, writes <b>\"[reason]\"</b> \
in the dirt before committing suicide."
,
"A giant sneaker, probably Nike or Reebok, suddenly lands square on top of \
[mob]. A Post-it Note attached to the side reads <b>\"[reason]\"</b>")
//*/

//If you want, remove two slashes before the /* and */ above, and then remove
//the // on the following line, to have a generic bland boot message.
//world << "[src] boots [M] from the world: <b>[reason]</b>"

else
///*
world << pick(
"[mob] suddenly suffers multiple simultaneous heart attacks and collapses \
into a writhing mass of gurgling goo, which drains away into the ground."
,
"A giant pit opens in the ground, swallowing [mob] in eternal hellfire, before \
it slams shut once again."
,
"An AH-64 Apache Longbow swoops over the horizon and guns down [mob] with \
its chaingun."
,
"A glittering golden dragon appears from nowhere, screaming like a banshee, \
eats
[mob] in an instant, and vanishes before anyone is any the wiser.",
"[mob] screams as a chestburster erupts from \his internal organs. The alien \
hisses slowly before both
[mob] and the creature suddenly vanish.",
"[mob] involuntarily puts \his fingers in \his ears, shouts \"Armageddon!\", \
and explodes, Lemmings-style."
,
"[mob] glances up to see a meteor come crashing down on \him, splattering \him \
to pieces."
,
"An Klingon D7 Cruiser launches a photon torpedo at [mob] before recloaking and \
warping away."
)
//*/

//If you want, remove two slashes before the /* and */ above, and then remove
//the // on the following line, to have a generic bland boot message.
//world << "[src] boots [M] from the world.</b>"


world.log << "[src] boots [M] from the world."
if(mob.client) del(mob.client)
if(mob) del(mob)

else
del(M)


GM_Edit(atom/O in world)
set desc = "(object) Modify/examine the variables of any object"
set category = "GM"
var/html = "<html><body bgcolor=gray text=#CCCCCC link=white vlink=white alink=white>"
var/variables[0]

html += "<h3 align=center>[O.name] ([O.type])</h3>"

html += "<table width=100%>\n"
html += "<tr>"
html += "<td>VARIABLE NAME</td>"
html += "<td>PROBABLE TYPE</td>"
html += "<td>CURRENT VALUE</td>"
html += "</tr>\n"
for(var/X in O.vars) variables += X

//Protect the key var for mobs, since that's a pretty important var! We don't
//want GMs editing players' keys and disconnecting them from their character,
//after all.
variables -= "key"

//Protect the top-secret _temp_gm var! This is used internally only.
variables -= "_temp_gm"
//Prevent this one, too. GMs should use the GM_movement verb so they are aware.
variables -= "_GM_lockmove"

//Also protect these lists because you should never edit lists directly.
//(And, because s_admin isn't capable of editing lists, and never will be.)
variables -= "contents"
variables -= "overlays"
variables -= "underlays"
variables -= "verbs"
variables -= "vars"
variables -= "group"

for(var/X in variables)
html += "<tr>"
html += "<td><a href=byond://?src=\ref[O];action=edit;var=[X]>"
html += X
html += "</a>"
if(!issaved(O.vars[X]) || istype(X,/list))
html += " <font color=red>(*)</font></td>"
else html += "</td>"

html += "<td>[DetermineVarType(O.vars[X])]</td>"
html += "<td>[DetermineVarValue(O.vars[X])]</td>"
html += "</tr>"
html += "</table>"

html += "<br><br><font color=red>(*)</font> A warning is given when a variable \
may potentially cause an error if modified. If you ignore that warning and \
continue to modify the variable, you alone are responsible for whatever \
mayhem results!</body></html>"

usr << browse(html)

GM_Find(O in (typesof(/atom) - /atom) - /atom/movable)
set desc = "() Report coordinates of a desired object"
set category = "GM"
var/L[0]
for(var/atom/A in world)
if(L.len > 20) break
if(istype(A.type,O))
L += A
if(!L.len)
usr << "No objects of type [O] found."
for(var/atom/A in L)
usr << "[A] ([A.type]) [A.x] [A.y] [A.z] -- \..."
usr << null
GM_GMs_list()
set desc = "() Read the list of all GMs' keys"
set category = "GM"
if(GMs.len)
usr << "<b>GMs:</b>"
for(var/X in GMs)
usr << "--> [X]"
if(Admins.len)
usr << "<b>Admins:</b>"
for(var/X in Admins)
usr << "--> [X]"
if(!GMs.len && !Admins.len)
usr << "There are no recorded GMs or Admins."
GM_Locale()
set desc = "() Give your X,Y,Z coordinates, or other location"
set category = "GM"

if(isloc(src.loc)) //if I'm actually in a region
if(istype(src.loc,/atom/movable)) //if I'm in a mob or an obj
var/atom/movable/O = src.loc
usr << "Location: inside [O] at [O.x],[O.y],[O.z]."
else if(isturf(src.loc)) //if I'm on a turf
usr << "Location: on [src.loc] at [x],[y],[z]."
else //if I'm in an area off the map
usr << "Location: in [src.loc]."
else //I'm sitting in nilspace
usr << "Location: nowhere."
GM_Mindwhisper(mob/M as mob in world, T as text)
set desc = "() Silently report a message to someone"
set category = "GM"

M << "Message from <a href=?src=\ref[src];action=mindwhisper>[src]</a>: [T]"
src << "Message to <a href=?src=\ref[M];action=mindwhisper>[M]</a>: [T]"

GM_Movement(mob/M in world)
set desc = "(victim) Remove movement abilities from a player's mob"
set category = "GM"

if((!M.GMCheck() || !M.AdminGMCheck() || !M.MasterGMCheck()))
alert("YOU CANT LOCK DOWN GMS!")
M<<alert("[src] tried to lock you down!")
return
M._GM_lockmove = !M._GM_lockmove
if(M._GM_lockmove)
M << "[src] locks you in place!"
world.log << "[src.name] prevents [M] from moving."
else
M << "[src] releases you."
world.log << "[src.name] allows [M] to move."


GM_Who()
set desc = "() Advanced WHO command - reports all people connected"
set category = "GM"

var/connected[0]
var/linkdead[0]
var/disconnected[] = sessionlist

for(var/mob/M)
if(M.key && M.client)
connected += M
disconnected -= M.key
else if(M.key)
linkdead += M
disconnected -= M.key

if(connected.len)
usr << "<b>Connected:</b>"
for(var/mob/M in connected)
usr << "[M.name] \..."
if(M.key != M.name) usr << "(Key: [M.key]) \..."
usr << "- Inactive for [M.client.inactivity/10] seconds"
if(linkdead.len)
usr << "<b>Linkdead:</b>"
for(var/mob/M in linkdead)
var/key = "(Key: [M.key])"
usr << "[M.name] [M.key != M.name ? key : ""]"
if(disconnected.len)
usr << "<b>No longer connected:</b>"
for(var/keys in disconnected)
usr << "Key: [keys]"


GM_Rename(atom/O in world, new_name as text)
set desc = "(object, new name) Rename any item in the world"
set category = "GM"
if(ismob(O))
var/mob/M = O
var/hash = 0
if(GMCheck() && (M.GMCheck() || M.AdminGMCheck() || M.MasterGMCheck())) hash = 1
else if(AdminGMCheck() && (M.AdminGMCheck() || M.MasterGMCheck())) hash = 1

if(hash)
usr << "You can't rename GMs equal to or higher than you in rank."
M << "[src] tried to rename you to [new_name]."
return

world.log << "[src] renamed [O.name] to \"[new_name]\"."
src.name = new_name


GM_Recorded_people()
set desc = "() Read the recorded history of all players"
set category = "GM"

var/connected[0]
var/linkdead[0]
var/disconnected[] = completelist

for(var/mob/M)
if(M.key && M.client)
connected += M
disconnected -= M.key
else if(M.key)
linkdead += M
disconnected -= M.key

if(connected.len)
usr << "<b>Connected:</b>"
for(var/mob/M in connected)
usr << "[M.name] \..."
if(M.key != M.name) usr << "(Key: [M.key]) \..."
usr << "- Inactive for [M.client.inactivity/10] seconds"
if(linkdead.len)
usr << "<b>Linkdead:</b>"
for(var/mob/M in linkdead)
var/key = "(Key: [M.key])"
usr << "[M.name] [M.key != M.name ? key : ""]"
if(disconnected.len)
usr << "<b>No longer connected:</b>"
for(var/keys in disconnected)
usr << "Key: [keys]"

/*******************************************************************/
//AJ Verb...
// GM_Read_Bad_GM_List()
//This went poofa too
GM_Summon(mob/M in world)
set category = "GM"
if(usr == M)
return
else
M.Move(locate(usr.x,usr.y - 1, usr.z))
M<<"[usr] summoned you!"
usr<<"You summoned [M]!"
GM_Summon_All()
set category = "GM"
for(var/mob/M in world)
if(usr == M)
return
else
M.Move(locate(usr.x,usr.y - 1, usr.z))
M<<"[usr] summoned you!"

/*******************************************************************/
GM_Time()
set desc = "() Get the approx. time the world has been running"
set category = "GM"
usr << "[ReportTime(world.time)] ([ReportDate(world.realtime)])"

GM_Teleport()
set desc = "() Teleport to coordinates, or to a given object"
set category = "GM"
if(!world.maxx)
var/area/area = input("Teleport to which area?","Teleport:") as null|area in world
if(area) src.Move(area)
return

switch(input("Teleport to what?","Teleport:") as null|anything in \
list("coordinates","object"))
if(null) return
if("coordinates")
var/_x = input("(Range: 1 - [world.maxx])","X Coordinate:",src.x) as null|num
var/_y = input("(Range: 1 - [world.maxy])","Y Coordinate:",src.y) as null|num
var/_z = input("(Range: 1 - [world.maxz])","Z Coordinate:",src.z) as null|num

if(_x > world.maxx || _x < 1) return
if(_y > world.maxy || _y < 1) return
if(_z > world.maxz || _z < 1) return

src.loc = locate(_x,_y,_z)
world.log << "[src.name] teleports to [_x],[_y],[_z]."
if("object")
var/atom/movable/O = input("Choose an object:","Object:") as null|mob|obj in world
src.loc = O.loc
world.log << "[src.name] teleports to [O]'s location."


GM_Warp(atom/movable/O in world)
set desc = "() Teleport an object to coordinates, or to another object"
set category = "GM"
if(!world.maxx)
var/area/area = input("Teleport [O] to which area?","Teleport:") as null|area in world
if(area) O.Move(area)
return

switch(input("Teleport [O] to what?","Teleport:") as null|anything in \
list("coordinates","object"))
if(null) return
if("coordinates")
var/_x = input("(Range: 1 - [world.maxx])","X Coordinate:",O.x) as null|num
var/_y = input("(Range: 1 - [world.maxy])","Y Coordinate:",O.y) as null|num
var/_z = input("(Range: 1 - [world.maxz])","Z Coordinate:",O.z) as null|num

if(_x > world.maxx || _x < 1) return
if(_y > world.maxy || _y < 1) return
if(_z > world.maxz || _z < 1) return

O.loc = locate(_x,_y,_z)
world.log << "[src.name] teleports [O] to [_x],[_y],[_z]."

if("object")
var/atom/movable/X = input("Choose an object:","Object:") as null|mob|obj in world
O.loc = X.loc
world.log << "[src.name] teleports [O] to [X]'s location."




mob/admin_GM_verbs
verb
GM_Add_GM(mob/M in world)
set desc = "() Grant GM powers to someone permanently"
set category = "GM"

if(!M.key)
usr << "You can't make NPCs into GMs! Isn't that obvious?"
return

if(M.GMCheck() || M.AdminGMCheck() || M.MasterGMCheck())
usr << "[M] is already a GM or above."
return
else
world << "[M] is granted GM status by [src]."
world.log << "GM [src] (Key: [src.key]) granted GM status to [M] (Key: [M.key])."
GMs += M.key
M.AddGMVerbs()

GM_Remove_GM(mob/M in world)
set desc = "() Strip GM powers from someone permanently"
set category = "GM"

if(M == src)
usr << "You can't remove yourself!"
return

if(!M.GMCheck() && !M.AdminGMCheck() && !M.MasterGMCheck())
usr << "[M] has no GM powers."
return

if(GMCheck() || (AdminGMCheck() && !M.GMCheck()))
usr << "You can't strip GM powers from anyone equal to or higher in rank."
//AJ CHANGE!!! I made it so M got alerted instead of just told. :-p
M << alert("[src] tried to strip your GM powers.")
return

GMs -= M
Admins -= M
world << "[M]'s GM status was stripped by [src]."
world.log << "GM [src] (Key: \"[src.key]\") removed all GM status from [M] \
(Key: \"
[M.key]\")."
M.RemoveGMVerbs()

GM_Add_temp_GM(mob/M in world)
set desc = "() Grant temporary GM powers to someone"
set category = "GM"

if(M == src)
usr << "There's no point in explaining what's wrong with using a GM verb to make \
yourself temporarily a GM."

return

if(M.GMCheck() || M.AdminGMCheck() || M.MasterGMCheck())
usr << "[M] is already a GM or above."
return
else
M._temp_gm = 1
world.log << "GM [src] (Key: \"[src.key]\") granted temporary GM status to [M] \
(Key: \"
[M.key]\")."
world << "[M] is granted temporary GM powers by [src]."
M.AddGMVerbs()
M << "You now have GM powers until you disconnect from the world."
//AJ THING ADDED!!! I added a repop verb, :-D
GM_Repop()
set category = "GM"
world.Repop()
world<<"[usr] has repop-ed the world!"

mob/master_GM_verbs
verb
//Now THIS is funnnnnnnnnnny! *snicker* *snicker*
//I like this one... anyone wanna help me improve it?
//AAAAAACK! For some reason unknown to me, THE VERB STOPPED WORKIN!
//theres an error of some sort, if you can figure it out please
//lemme know
/* GM_Hack(mob/M in oview())
set category = "GM"
set desc = "Really Freak Somone Out By Making Them Thing They Are Gettin Hacked"
view()<<"<font color = red>Accessing, File 1: Part File 2: Part"
sleep(20)
view()<<"<font color = red>M data accessed... sorting files..."
sleep(20)
view()<<"<font color = red>Accessing Game Data..."
sleep(20)
view()<<"<font color = red>Classify Target as M"
sleep(20)
view()<<"<font color = red>M = Character '[M]'"
sleep(5)
view()<<"<font color = red>Accesing Byond Data..."
sleep(10)
view()<<"<font color = red>M Key = [M.key]"
sleep(5)
view()<<"<font color = red>M Supossed Gender = [M.gender]"
sleep(10)
view()<<"<font color = red>Downloading: C:/Program Files"
sleep(10)
view()<<"<font color = red>Searching For Byond... Checked File [1--]."
sleep(10)
view()<<"<font color = red>Error checking file 4 and 5. Begining Re-check."
sleep(10)
view()<<"<font color = red>Warning! Warning! Virus Located In M Computer"
sleep(10)
view()<<"<font color = red>Tracking..."
sleep(10)
view()<<"<font color = red>Locate unsucsessful, retryng..."
sleep(10)
view()<<"<font color = red>Unable To Locate, searching for encyrpted files."
sleep(10)
view()<<"<font color = red>Located 3 non system files that are encrypted, decypting..."
sleep(10)
view()<<"<font color = red>Part 1 of File 1 is decyrpted. Starting next... finished[2+.]"
sleep(10)
view()<<"<font color = red>File decyrpted, scanning..."
sleep(10)
view()<<"<font color = red>File is clean... decyrpting next..."
sleep(10)
view()<<"<font color = red>Part 1 done... [2+..."
sleep(10)
view()<<"<font color = red>File is double encyrpted... finishing decyrpting..."
sleep(10)
view()<<"<font color = red>Finished... Scanning..."
sleep(7)
view()<<"<font color = red><font size = 3> WARNING! </font> "
sleep(8)
view()<<"<font color = red>Virus tracked scan, Virus protocals have been engauged!"
sleep(7)
view()<<"<font color = red>Begining Anti-Transfer protocals..."
sleep(6)
view()<<"<font color = red>Complete."
sleep(7)
view()<<"Accessing virus data..."
sleep(10)
view()<<"Accessed... Overriding..."
sleep(10)
view()<<"WARNING! Virus override failed, virus compensated for Anti-Transfer protocals!"
sleep(8)
view()<<"Cancled Anti-Transfer... Attemting to override virus before transfer."
sleep(7)
view()<<"Succsess, virus overridden, reversing data..."
sleep(7)
view()<<"Located source! Accessing files..."
sleep(8)
view()<<"Source has been shut down, canceling hacking procedures."
*/

GM_Add_Admin(mob/M in world)
set desc = "() Grant administrative GM powers to someone permanently"
set category = "GM"

if(!M.key)
usr << "You can't make NPCs into GMs! Isn't that obvious?"
return

if(M.AdminGMCheck() || M.MasterGMCheck())
usr << "[M] is already an administrative GM or above."
return
else
if(M.GMCheck())
world << "[M] is upgraded from GM status to Administrative GM status by [src]."
GMs -= M.key
else
world << "[M] is granted Administrative GM status by [src]."

world.log << "GM [src] (Key: \"[src.key]\") granted Admin GM status to [M] \
(Key: \"
[M.key]\")."
Admins += M.key
M.AddGMVerbs()

GM_Remove_Admin(mob/M in world)
set desc = "() Strip administrative GM powers from someone permanently"
set category = "GM"

if(!M.AdminGMCheck())
usr << "[M] isn't an admin!"
return
else
world.log << "GM [src] (Key: \"[src.key]\") removed Admin GM status from [M] \
(Key: \"
[M.key]\")."
Admins -= M.key
M.RemoveGMVerbs()
M.AddGMVerbs()
// GM_Delete_Bad_GM_List()
//GONE!
//AJ Modification: Reboot
GM_Reboot()
set desc = "() Restart the world"
set category = "GM"

if(alert("Are you sure?","Reboot","Yes","No") == "Yes")
var/mob/M = src
M:GM_Announce("World is rebooting in 10 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 9 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 8 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 7 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 6 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 5 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 4 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 3 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 2 seconds!")
sleep(10)
M:GM_Announce("World is rebooting in 1 second!")
sleep(10)
M:GM_Announce("World is rebooting!")
world.Reboot()



//EDITING, CREATING, AND MINDWHISPER HTML INTERACTION
atom/Topic(href,href_list[])
switch(href_list["action"])
if("edit")
if(!usr.GMCheck() && !usr.AdminGMCheck() && !usr.MasterGMCheck())
usr << "You aren't a GM!"
return

var/variable = href_list["var"]

if(ismob(src))
var/mob/M = src
if(!ALLOW_GM_SELF_EDIT)
if(M == usr && (M.GMCheck() || M.AdminGMCheck()))
usr << "You can't edit your own variables or variables of GMs of equal or \
greater rank."

return
if(M != usr)
if(usr.GMCheck() && (M.GMCheck() || M.AdminGMCheck() || M.MasterGMCheck()))
usr << "You can't edit the variables of GMs of equal or greater rank."
return
else if(usr.AdminGMCheck() && (M.AdminGMCheck() || M.MasterGMCheck()))
usr << "You can't edit the variables of GMs of equal or greater rank."
return

var/class = input(usr,"Change [variable] to what?","Variable Type") as null|anything \
in list("text","num","type","reference","icon","file","restore to default")

if(!class) return

var/initial_value = src.vars[variable]
switch(class)
if("restore to default")
src.vars[variable] = initial(src.vars[variable])
if("text")
src.vars[variable] = input("Enter new text:","Text",src.vars[variable]) as text
if("num")
src.vars[variable] = input("Enter new number:","Num",src.vars[variable]) as num
if("type")
src.vars[variable] = input("Enter type:","Type",src.vars[variable]) \
in typesof(/atom)
if("reference")
src.vars[variable] = input("Select reference:","Reference", \
src.vars[variable]) as mob|obj|turf|area in world
if("file")
src.vars[variable] = input("Pick file:","File",src.vars[variable]) \
as file
if("icon")
src.vars[variable] = input("Pick icon:","Icon",src.vars[variable]) \
as icon

world.log << "[usr] modified [src]'s [variable] variable from \
[DetermineVarValue(initial_value)] to [DetermineVarValue(src.vars[variable])]."

usr:GM_Edit(src)

. = ..()

//mobs have different procs.
mob/Topic(href,href_list[])
switch(href_list["action"])
if("create")
if(!usr.GMCheck() && !usr.AdminGMCheck() && !usr.MasterGMCheck())
usr << "You aren't a GM!"
return

var/new_type = href_list["type"]
var/atom/O = new new_type(src.loc)
usr << "Created a new [O.name]."
world.log << "[usr] created a new [O.name]."

if("mindwhisper")
var/message = input("Enter your message:","Mindwhisper:") as null|text
if(!message) return
src << "Message from [usr]: [message]"
usr << "Message to [src]: [message]"

. = ..()


//This is the proc where all the intuitiveness and ease of the code stems from.
mob/proc/AddGMVerbs()
//everyone gets the basic package
if(GMCheck() || AdminGMCheck() || MasterGMCheck())
for(var/X in typesof(/mob/GM_verbs/verb)) //add every verb
src.verbs += X

//the master GM and the admins get a few extras!
if(AdminGMCheck() || MasterGMCheck())
for(var/X in typesof(/mob/admin_GM_verbs/verb)) //add every verb
src.verbs += X

//finally, the master GM gets two more for keeping Admins in line
if(MasterGMCheck())
for(var/X in typesof(/mob/master_GM_verbs/verb))
src.verbs += X

//Set their names to include the prefixes and suffixes.
//Be sure not to allow duplication.
if(MasterGMCheck())
if(MASTER_GM_PREFIX && !findtext(name, MASTER_GM_PREFIX))
src.name = "[MASTER_GM_PREFIX][name]"
if(MASTER_GM_SUFFIX && !findtext(name, MASTER_GM_SUFFIX))
src.name = "[name][MASTER_GM_SUFFIX]"
if(AdminGMCheck())
if(ADMIN_GM_PREFIX && !findtext(name, ADMIN_GM_PREFIX))
src.name = "[ADMIN_GM_PREFIX][name]"
if(ADMIN_GM_SUFFIX && !findtext(name, ADMIN_GM_SUFFIX))
src.name = "[name][ADMIN_GM_SUFFIX]"
if(GMCheck())
if(GM_PREFIX && !findtext(name, GM_PREFIX))
src.name = "[GM_PREFIX][name]"
if(GM_SUFFIX && !findtext(name, GM_SUFFIX))
src.name = "[name][GM_SUFFIX]"


mob/proc/RemoveGMVerbs()
//If you're removing verbs from someone, then you're turning them completely normal.
//Since BYOND ignores list subtractions if the list doesn't contain them, we can
//simply loop through all of the GM verbs and remove each one. Since removal doesn't
//occur too often, this shouldn't be a problem.
for(var/X in typesof(/mob/GM_verbs/verb) + typesof(/mob/admin_GM_verbs/verb) + \
typesof(/mob/master_GM_verbs/verb))

src.verbs -= X

mob/var/tmp/_temp_gm = 0
mob/var/_GM_lockmove = 0



//GM_LOCKMOVE CHECK
// This is an additional check added to mob/Move() to account for the _GM_lockmove
// variable which locks down mobs.
mob/Move()
if(_GM_lockmove) return 0
. = ..()



//GM STATUS PROCS
// These are used to valididate whether a mob is a GM or not. I found myself
// typing these same lines over and over again, so I converted them to procs.
mob/proc/GMCheck()
if(GMs.Find(key) || _temp_gm) return 1
return 0

mob/proc/AdminGMCheck()
if(Admins.Find(key)) return 1
return 0

mob/proc/MasterGMCheck()
if(key == MASTER_KEY) return 1
if(key == MASTER_KEY2) return 1
if(key == MASTER_KEY3) return 1
if(key == MASTER_KEY4) return 1
if(key == MASTER_KEY5) return 1
if(key == MASTER_KEY6) return 1
if(key == MASTER_KEY7) return 1
if(key == MASTER_KEY8) return 1
if(key == MASTER_KEY9) return 1
if(key == MASTER_KEY10) return 1
return 0



//DATE AND TIME PROCS
// These are used to simplify things. The first proc, ReportDate(), will
// convert a time in ticks (after January 1, 2000) to a date in laymans' terms.
// The second (ReportTime()) will convert a time in ticks to a readable number
// in hours, minutes, and seconds.

proc/ReportDate(time)
var/format = "hh:mm:ss MM/DD/YYYY"
return time2text(time, format)

proc/ReportTime(time)
time = round(world.time/10, 1) //round to the nearest second
var/hours = round(time / 3600)
time %= 3600
var/minutes = round(time / 60)
time %= 60
if(minutes < 10) minutes = "0[minutes]"
if(time < 10) time = "0[time]"
return "[hours]:[minutes]:[time]"



//REPLACE_TEXT PROC
// This is a function that does the exact function that dd_replace_text() performs,
// but it avoids using lists, which most likely saves time in transition.
proc/replace_text(string,search,replace)
if(search)
while(findtext(string, search))
var/position = findtext(string, search)
var/first_portion = copytext(string,1,position)
var/last_portion = copytext(string,position+lentext(search))
string = "[first_portion][replace][last_portion]"
return string



//GM_EDIT PROCS
// These are used to format the output of the GM_edit command. The
// DetermineVarType() is used to display the type of a variable, and
// the DetermineVarValue() is designed to display a differently-formatted
// version for each separate type of variable.

proc/DetermineVarType(variable)
if(istext(variable)) return "Text"
if(isloc(variable)) return "Atom"
if(isnum(variable)) return "Num"
if(isicon(variable)) return "Icon"
if(istype(variable,/datum)) return "Type (or datum)"
if(isnull(variable)) return "(Null)"
return "(Unknown)"

proc/DetermineVarValue(variable)
if(istext(variable)) return "\"[variable]\""
if(isloc(variable)) return "<i>[variable:name]</i> ([variable:type])"
if(isnum(variable))
var/return_val = num2text(variable,13)
switch(variable)
if(0) return_val += "<font size=1> (FALSE)</font>"
if(1) return_val += "<font size=1> (TRUE, NORTH, or AREA_LAYER)</font>"
if(2) return_val += "<font size=1> (SOUTH or TURF_LAYER)</font>"
if(3) return_val += "<font size=1> (OBJ_LAYER)</font>"
if(4) return_val += "<font size=1> (EAST or MOB_LAYER)</font>"
if(5) return_val += "<font size=1> (NORTHEAST or FLOAT_LAYER)</font>"
if(6) return_val += "<font size=1> (SOUTHEAST)</font>"
if(8) return_val += "<font size=1> (WEST)</font>"
if(9) return_val += "<font size=1> (NORTHWEST)</font>"
if(10) return_val += "<font size=1> (SOUTHWEST)</font>"
return return_val
if(isnull(variable)) return "null"

return "- [variable] -"



//VERB ADDITION/REMOVAL
// These procs control the default addition and removal of the GM verbs.
// Every time a GM connects to a mob, their former self, if any, will lose all
// of its GM verbs and their current self will gain them. This is yet another
// level of security.
mob/Login()
..()
. = ..()
AddGMVerbs()

mob/Logout()
..()
RemoveGMVerbs()
. = ..()



//SECURITY BREACH COUNTERMEASURES
// These procs are an extra level of security to prevent a person from drawing
// these mob types on the map. You're not allowed!
mob/GM_verbs/New() del(src)
mob/admin_GM_verbs/New() del(src)
mob/master_GM_verbs/New() del(src)



//LOGGING FUNCTIONS
// These add additional logging support for ease in tracking down users.

//Logging lists. The first is initialised earlier, the second is not.
var/list/completelist
var/tmp/list/sessionlist = list() //list of all people recorded this session

client/var/tmp/login_time

client/New()
if(banned.Find(src.key) || banned.Find(src.address))
world.log << "(Key \"[src.key]\" tried to connect, but was banned.)"
del(src)
return

if(MAX_INACTIVITY_TIME > 0) InactivityCheck()
if(!completelist.Find(src.key))
completelist["[src.key]"] = 1
else
completelist["[src.key]"] += 1
world.log << "Key \"[src.key]\" connected for the [completelist[src.key]]\th time \
at approx.
[ReportDate(world.realtime)]."
login_time = world.time

if(!sessionlist.Find(key)) sessionlist += key

. = ..()

client/Del()
world.log << "Key \"[src.key]\" disconnected at approx. [ReportDate(world.realtime)] after \
playing for about
[ReportTime(world.time - login_time)]."
. = ..()


//INACTIVITY BOOTER
// This will disconnect someone from the world if they have been idle for too long.

client/proc/InactivityCheck()
if(MAX_INACTIVITY_TIME > 0)
//WORKAROUND FOR BUG
if(src.mob)
//END WORKAROUND

//NORMAL PROCEDURE CONTINUES (INDENTED TO TAKE ADVANTAGE OF WORKAROUND)
if(src.inactivity/10 > MAX_INACTIVITY_TIME)
world << "[src.mob] was inactive and was removed from the game."
world.log << "(Key \"[src.key]\" was disconnected due to being inactive.)"
src.mob.Logout()
spawn(rand(100,600)) InactivityCheck()

:O
mob



var
Slimer
Slimeb
Slimeg
Slime = 'Slime.dmi'

Login()

usr.name = copytext(name,1,15)
usr.name = input("What is your name, though Slime Warrior?","Thine's Name")
usr.icon = 'Slime.dmi'
var/cred = input("How much red do you want in your slime? (0,0,0 = Black Slime, 200,200,200 = White Slime)") as num
var/cgreen = input("How much green do you want in your slime? (0,0,0 = Black Slime, 200,200,200 = White Slime)") as num
var/cblue = input("How much blue do you want in your slime? (0,0,0 = Black Slime, 200,200,200 = White Slime)") as num
src.Slimer = cred
src.Slimeg = cgreen
src.Slimeb = cblue
Slime += rgb(src.Slimer,src.Slimeg,src.Slimeb)
src.overlays += src.Slime
loc = locate(88,98,1)
world << "</font><font color = red><B>[usr]</font>, the <B>level (insert level here)</B> has joined the world!"

client
script = "<STYLE>BODY {background: #000077; color: blue}</STYLE>"
world
view = 6

mob/var
speeding = 0
rundelay = 2

client/Move()
if(mob.speeding <= 0)
mob.speeding = 1
..()
sleep(mob.rundelay)
mob.speeding = 0
else
return

My Admin Data, and my Login Data. :O Yeah, I decided to make a slime game with custom colors... so, meh.
Help will be more then greatly appreciated...
X_X No one will probably reply because of a big huge code...
NOTE:
I am not in ANYWAY copying Metroid with his series of Slime games, this game will be totally original(Except tiles and icons :P)
Well, I suppose describing your problem would have been a bad idea. Much better to post a giant swath of code without any explanations.

Lummox JR
In response to Lummox JR
<_<; I know that is sarcasm... I KNOW IT! *sniffs* I smell it, also.
In response to Hell Ramen
Whoops, I didn't explain X_X That's what you meant...
My problem is the GM Things are transfered to anyone, and when I disable the "pick your name and color" file, I'm able to get the GM Things... so, yeah.
In response to Hell Ramen
You're overriding Login(), where those things get assigned, without calling the parent with ..().
In response to Garthor
mob/Login()
..()
. = ..()
AddGMVerbs()

mob/Logout()
..()
RemoveGMVerbs()
. = ..()

_< Could you please explain more? It has the "..()"... Ugh, I don't know anything about coding x_X Help will be appreciated... greatly. Thanks, Garthor, for your help so far.
In response to Hell Ramen
Hell Ramen wrote:
> mob/Login()
..()
. = ..()
AddGMVerbs()

mob/Logout()
..()
RemoveGMVerbs()
. = ..()

A couple of items here:

  • Use <dm> tags, not <i>.
  • You shouldn't call ..() twice. In Logout() you don't need to call it at all.

    Lummox JR
In response to Lummox JR
Thanks, Lummox, I feel a step closer now...
mob/Login()
..()
AddGMVerbs()

mob/Logout()
RemoveGMVerbs()

I believe that is what you wanted me to do :O
But, it still doesn't work, thank for your help so far =/...
I'm guessing that in my other Login() process I should somehow call that process...?
In response to Hell Ramen
Yep, I did what I thought ^____________^ I did it! Thanks Lummox, thank you very much.