diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 249cd05528b..385f782d552 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -66,7 +66,8 @@ var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
/client/proc/jobbans,
/client/proc/unjobban_panel,
- /client/proc/DB_ban_panel
+ /client/proc/DB_ban_panel,
+ /client/proc/stickybanpanel
)
var/list/admin_verbs_sounds = list(
/client/proc/play_local_sound,
diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm
new file mode 100644
index 00000000000..383b7935f06
--- /dev/null
+++ b/code/modules/admin/stickyban.dm
@@ -0,0 +1,169 @@
+/datum/admins/proc/stickyban(action,data)
+ if(!check_rights(R_BAN))
+ return
+ switch (action)
+ if ("show")
+ stickyban_show()
+ if ("add")
+ var/list/ban = list()
+ ban["admin"] = usr.key
+ ban["type"] = "sticky"
+ ban["reason"] = "(InGameBan)([usr.key])" //this will be display in dd only
+ var/ckey
+ if (data["ckey"])
+ ckey = data["ckey"]
+ else
+ ckey = input(usr,"Ckey","Ckey","") as text|null
+ if (!ckey)
+ return
+ ckey = ckey(ckey)
+ if (ckey in world.GetConfig("ban"))
+ usr << "Can not add a stickyban: User already has a current sticky ban"
+ if (data["reason"])
+ ban["message"] = data["reason"]
+ else
+ var/reason = input(usr,"Reason","Reason","Ban Evasion") as text|null
+ if (!reason)
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban",ckey,list2params(ban))
+
+ log_admin("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+ message_admins("[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+
+ if ("remove")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+
+ if (!(ckey in world.GetConfig("ban")))
+ alert("No sticky ban for [ckey] found!")
+ return
+ var/ban = params2list(world.GetConfig("ban",ckey))
+ if (!is_stickyban_from_game(ban))
+ alert("This user was stickybanned by the host, and can not be un-stickybanned from this panel")
+ return
+ if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No")
+ return
+
+ world.SetConfig("ban",ckey, null)
+
+ log_admin("[key_name(usr)] removed [ckey]'s stickyban")
+ message_admins("[key_name_admin(usr)] removed [ckey]'s stickyban")
+
+ if ("remove_alt")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ if (!data["alt"])
+ return
+ var/alt = ckey(data["alt"])
+ if (!(ckey in world.GetConfig("ban")))
+ alert("No sticky ban for [ckey] found!")
+ return
+
+ if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
+ return
+
+ var/ban = params2list(world.GetConfig("ban",ckey))
+ if (!is_stickyban_from_game(ban))
+ alert("This user was stickybanned by the host, and can not be edited from this panel")
+ return
+
+ var/found = 0
+
+ //we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ found = 1
+ ban["keys"] -= key
+ break
+
+ if (!found)
+ alert("[alt] is not linked to [ckey]'s sticky ban!")
+ return
+
+ world.SetConfig("ban",ckey,list2params(ban))
+
+ log_admin("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+ message_admins("[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+ if ("edit")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+
+ if (!(ckey in world.GetConfig("ban")))
+ alert("No sticky ban for [ckey] found!")
+ return
+ var/ban = params2list(world.GetConfig("ban",ckey))
+ if (!is_stickyban_from_game(ban))
+ alert("This user was stickybanned by the host, and can not be edited from this panel")
+ return
+ var/oldreason = ban["message"]
+ var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
+ if (!reason || reason == oldreason)
+ return
+ //we have to do this again incase something changed while we waited for input
+ ban = params2list(world.GetConfig("ban",ckey))
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban",ckey,list2params(ban))
+
+ log_admin("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+ message_admins("[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+
+/datum/admins/proc/stickyban_gethtml(ckey, ban)
+ . = "\[-\][ckey]
"
+ . += "[ban["message"]] \[Edit\]
"
+ if (!is_stickyban_from_game(ban))
+ . += "HOST
"
+ if (ban["admin"])
+ . += "[ban["admin"]]
"
+ else
+ . += "LEGACY
"
+ . += "Caught keys
\n