anchor.diff:  		))
   	if(!SSdbcore.MassInsert(format_table_name("ban"), sql_ban, warn = 1))
   		return
  -	var/msg = "has created a [isnull(duration) ? "permanent" : "temporary [time_message]"] [applies_to_admins ? "admin " : ""][roles_to_ban[1] == "Server" ? "server ban" : "role ban from [roles_to_ban.len] roles"] for [player_key]."
  +	var/target = ban_target_string(player_key, player_ip, player_cid)
  +	var/msg = "has created a [isnull(duration) ? "permanent" : "temporary [time_message]"] [applies_to_admins ? "admin " : ""][roles_to_ban[1] == "Server" ? "server ban" : "role ban from [roles_to_ban.len] roles"] for [target]."
   	log_admin_private("[kn] [msg][roles_to_ban[1] == "Server" ? "" : " Roles: [roles_to_ban.Join(", ")]"] Reason: [reason]")
   	message_admins("[kna] [msg][roles_to_ban[1] == "Server" ? "" : " Roles: [roles_to_ban.Join("\n")]"]\nReason: [reason]")
   	if(applies_to_admins)
   		send2irc("BAN ALERT","[kn] [msg]")
  -	create_message("note", player_ckey, admin_ckey, note_reason, null, null, 0, 0, null, 0, severity)
  +	if(player_ckey)
  +		create_message("note", player_ckey, admin_ckey, note_reason, null, null, 0, 0, null, 0, severity)
   	var/client/C = GLOB.directory[player_ckey]
   	var/datum/admin_help/AH = admin_ticket_log(player_ckey, msg)
   	var/appeal_url = "No ban appeal url set!"
   	appeal_url = CONFIG_GET(string/banappeals)
  +	var/is_admin = FALSE
   	if(C)
   		build_ban_cache(C)
   		to_chat(C, "<span class='boldannounce'>You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason]</span><br><span class='danger'>This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id].</span><br><span class='danger'>To appeal this ban go to [appeal_url]</span>")
  -		if(roles_to_ban[1] == "Server")
  +		if(GLOB.admin_datums[C.ckey] || GLOB.deadmins[C.ckey])
  +			is_admin = TRUE
  +		if(roles_to_ban[1] == "Server" && (!is_admin || (is_admin && applies_to_admins)))
   			qdel(C)
   	if(roles_to_ban[1] == "Server" && AH)
   		AH.Resolve()
  
positive.code: 			if("server")
  				roles_to_ban += "Server"
  			if("role")
  				if(href_list[href_list.len] == "roleban_delimiter")
  					error_state += "Role ban was selected but no roles to ban were selected."
  				else
  					href_list.Remove("Command", "Security", "Engineering", "Medical", "Science", "Supply", "Silicon", "Abstract", "Civilian", "Ghost and Other Roles", "Antagonist Positions") //remove the role banner hidden input values
  					var/delimiter_pos = href_list.Find("roleban_delimiter")
  					href_list.Cut(1, delimiter_pos+1)//remove every list element before and including roleban_delimiter so we have a list of only the roles to ban
  					for(var/key in href_list) //flatten into a list of only unique keys
  
negative.code: 			output += "<div class='column'><label class='rolegroup [ckey(department)]'><input type='checkbox' name='[department]' class='hidden' [usr.client.prefs.tgui_fancy ? " onClick='toggle_checkboxes(this, \"_com\")'" : ""]>[department]</label><div class='content'>"
  			break_counter = 0
  			for(var/job in headless_job_lists[department])
  				if(break_counter > 0 && (break_counter % 3 == 0))
  					output += "<br>"
  				output += {"<label class='inputlabel checkbox'>[job]
  							<input type='checkbox' name='[job]' class='[department]' value='1'>
  