Shadow Mode: Anonymous Moderating Tool

About

Currently, developers and admins don’t have access to an anonymous mode, like requested in this feature request:

(Please support if you think this feature would be useful!)

This resource provides a way for admins to hide from players they are moderating. This is useful because malicious players often leave when moderators join, or moderators are pestered by regular players. This also allows game creators to get an accurate feel for how players interact with their game.

How It Works

This module has a server sided module and a client script. The module signals to the client scripts to set the designated player’s Instance’s parent to nil, which makes them invisible to the client. The module can also signal to the client to add the designated player back to Players to make them visible again.

This might possibly break after the change below is added, though it has been around for a very long time. In the case this change does break this module, the impact will likely be fairly low.

Disconnect Player on Removal from DataModel

Pictures


(The admin player has shadow mode on. The second player can’t see the admin in either of their player lists.)


(Admins can use shadow mode in combination with disguise and invisibility commands.)

Installation

You can try out the system here:

You can get the tool based version of the model here:

Update! You can also get the GUI based version here:

ShadowMode (Gui Version) - Roblox


(Thanks to ForeverHD for his TopbarPlus module!)

Once you get the model, just place it into Workspace. You can edit the admins inside the “IsAdmin” module.

This model has example usage of the shadow mode functionality (gives admins a shadow mode toggle tool, an invisible toggle tool, a disguise toggle tool, and a speed toggle tool). You can set the admins (by user ID or group rank) in the IsAdmin module.

If you’re planning on possibly incorporating this into your existing admin system, you might find it useful to test out this code in your game using the model above.

If you want to add shadow mode to your admin system

The code for shadow mode is in a ModuleScript named “SetShadowMode” which returns the function setShadowMode(player : Player, shadowMode : bool). The module requires the client script, ShadowModeClient. You can set the path to the client script with the ObjectValue inside the ModuleScript.

33 Likes

Okay, this is super cool, and I am using it

But my tools duplicate when the round ends and I get teleported back to the lobby
Any fix?

1 Like

The code adds the tools to the player’s backpack when their character spawns. It seems to work fine with the character dying and respawning for me.

Do you have code that duplicates the player’s tools when the player dies? Probably so that dying doesn’t remove their tools?

You could add this code to a server script in StarterCharacterScripts and see if that solves the problem:

local character = script.Parent
local player = game:GetService("Players"):GetPlayerFromCharacter(character)
local humanoid = character:WaitForChild("Humanoid")

local namesOfToolsToDestroy = {
	"Shadow Mode: ON";
	"Shadow Mode: OFF";
	
	"Disguise Mode: ON";
	"Disguise Mode: OFF";
	
	"Invisible Mode: ON";
	"Invisible Mode: OFF";
	
	"Speed Mode: ON";
	"Speed Mode: OFF";
}

local function destroyIfValid(tool)
	if tool and tool:IsA("Tool") and table.find(namesOfToolsToDestroy, tool.Name) then
		tool:Destroy()
	end
end

humanoid.Died:Connect(function()
	local equippedTool = character:FindFirstChildOfClass("Tool")
	if equippedTool then
		destroyIfValid(equippedTool)
	end
	
	for _, backpackTool in ipairs(player.Backpack:GetChildren()) do
		destroyIfValid(backpackTool)
	end
end)

(The code destroys the player’s admin tools when they die.)

The player does not die, it just teleports back, It takes away the sword, but duplicates the admin tools

1 Like

Huh, I don’t know why that is happening. The code only creates new tools when the character spawns:

local setShadowMode = require(script.SetShadowMode)
local isAdmin = require(script.IsAdmin)

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
	if isAdmin(player) then
		local isShadow = false
		setShadowMode(player, isShadow)
		
		player.CharacterAdded:Connect(function(character)
			-- (Creates shadow toggle tool)
			
			-- (Creates disguise toggle tool)

			-- (Creates invisible toggle tool)

			-- (Creates speed toggle tool)
		end)
	end
end)
Full Code
local setShadowMode = require(script.SetShadowMode)
local isAdmin = require(script.IsAdmin)

local Players = game:GetService("Players")

-- Example code.
-- Gives admins shadow toggle tool, disguise toggle tool, invisible toggle tool, and speed toggle tool.
-- This is mostly for demostration. You probably want to add these to your admin commands if this works well for you.
Players.PlayerAdded:Connect(function(player)
	if isAdmin(player) then
		local isShadow = false
		setShadowMode(player, isShadow)
		
		player.CharacterAdded:Connect(function(character)
			local shadowToggleTool = Instance.new("Tool")
			shadowToggleTool.RequiresHandle = false
			shadowToggleTool.Name = "Shadow Mode: "..(isShadow and "ON" or "OFF")
			shadowToggleTool.ToolTip = "Toggle Shadow Mode"
			shadowToggleTool.Activated:Connect(function()
				isShadow = not isShadow
				setShadowMode(player, isShadow)
				shadowToggleTool.Name = "Shadow Mode: "..(isShadow and "ON" or "OFF")
			end)
			shadowToggleTool.Parent = player.Backpack
			
			local disguiseUserIds = {
				1; -- Roblox
				2; -- Joe Doe
				3; -- Jane Doe
			}
			
			local disguiseDescriptions = {}
			do
				for index, userId in ipairs(disguiseUserIds) do
					disguiseDescriptions[index] = Players:GetHumanoidDescriptionFromUserId(userId)
				end
			end
			
			local userId = math.clamp(player.UserId, 1, math.huge)
			
			local playerDescription = Players:GetHumanoidDescriptionFromUserId(userId)
			
			local isDisguise = false
			local disguiseToggleTool = Instance.new("Tool")
			disguiseToggleTool.RequiresHandle = false
			disguiseToggleTool.Name = "Disguise Mode: "..(isDisguise and "ON" or "OFF")
			disguiseToggleTool.ToolTip = "Toggle Disguise Mode"
			disguiseToggleTool.Activated:Connect(function()
				local humanoid = character:FindFirstChild("Humanoid")
				if humanoid then
					if isDisguise then
						humanoid:ApplyDescription(playerDescription)
					else
						humanoid:ApplyDescription(disguiseDescriptions[math.random(1, #disguiseDescriptions)])
					end
					
					isDisguise = not isDisguise
					disguiseToggleTool.Name = "Disguise Mode: "..(isDisguise and "ON" or "OFF")
				end
			end)
			disguiseToggleTool.Parent = player.Backpack 
			
			local isInvisible = false
			local uninvisibleBindable = nil
			
			local invisibleToggleTool = Instance.new("Tool")
			invisibleToggleTool.RequiresHandle = false
			invisibleToggleTool.Name = "Invisible Mode: "..(isInvisible and "ON" or "OFF")
			invisibleToggleTool.ToolTip = "Toggle Invisible Mode"
			invisibleToggleTool.Activated:Connect(function()
				if isInvisible then
					uninvisibleBindable:Fire()
					uninvisibleBindable:Destroy()
				else
					uninvisibleBindable = Instance.new("BindableEvent")
					local event = uninvisibleBindable.Event
					
					local tool = character:FindFirstChildOfClass("Tool")
					
					for _, descendant in ipairs(character:GetDescendants()) do
						if tool and descendant:IsDescendantOf(tool) then
							continue
						end
						
						if descendant:IsA("BasePart") or descendant:IsA("Decal") then
							local oldTransparency = descendant.Transparency
							descendant.Transparency = 1
							event:Connect(function()
								descendant.Transparency = oldTransparency
							end)
						elseif descendant:IsA("ParticleEmitter") then
							local oldEnabled = descendant.Enabled
							descendant.Enabled = false
							event:Connect(function()
								descendant.Enabled = oldEnabled
							end)
						end
					end
				end
				
				isInvisible = not isInvisible
				invisibleToggleTool.Name = "Invisible Mode: "..(isInvisible and "ON" or "OFF")
			end)
			invisibleToggleTool.Parent = player.Backpack 
			
			
			local isSpeed = false
			local increaseFactor = 6
			local speedToggleTool = Instance.new("Tool")
			speedToggleTool.RequiresHandle = false
			speedToggleTool.Name = "Speed Mode: "..(isSpeed and "ON" or "OFF")
			speedToggleTool.ToolTip = "Toggle Speed Mode"
			speedToggleTool.Activated:Connect(function()
				local humanoid = character:FindFirstChild("Humanoid")
				if humanoid then
					if isSpeed then
						humanoid.WalkSpeed /= increaseFactor
						humanoid.JumpPower /= math.sqrt(increaseFactor)
						humanoid.JumpHeight /= increaseFactor
					else
						humanoid.WalkSpeed *= increaseFactor
						humanoid.JumpPower *= math.sqrt(increaseFactor)
						humanoid.JumpHeight *= increaseFactor
					end

					isSpeed = not isSpeed
					speedToggleTool.Name = "Speed Mode: "..(isSpeed and "ON" or "OFF")
				end
			end)
			speedToggleTool.Parent = player.Backpack
		end)
	end
end)

You should turn this into a gui instead of some tools. Also GitHub repository if you can so mobile users who can’t access their computers at the time can read the code.

1 Like

Amazing resource! Very smart about hiding admin from the player list.

This is something that my moderation team has been waiting for, and I appreciate that you made this for communities needing shadow mode for their staff members.

1 Like

Its ok, I can still make it work
My solution was to make myself have the ability to remove tools

1 Like

I took your advice and made a GUI based version:

It’s basically the same thing but with GUI:

Credit to ForeverHD and his TopbarPlus module.


@Coolsbloxian If the tools are still being wonky you might want to check out the GUI based version.

3 Likes

This is what I needed :slight_smile: thank you

1 Like

This does solve my problem
AND it looks so much better, thanks

1 Like

how do i set this up? is there a video to set it up or something?

1 Like

Just put the model folder into the workspace

1 Like

I have recently used this system in my hangout game (with friends) and it actually works but for one small detail. It still says Your friend has joined the server. Is it possible for you to remove them for admins? (I’m not experienced in using Roblox CoreUI so I dont know)

1 Like

Wouldn’t advise to use player.Parent = nil, bad usage and may break certain game features

1 Like

it isn’t working i put it in workspace

1 Like

Generally it works fine. I haven’t found any code that gets broken because of it, though if you find any I would like to know.

You can remove that by following this post:

Doing that just removes system messages.

You just need to insert the model into Workspace like Drew said.

1 Like

Are you trying to use the tool based one or the GUI based one?

1 Like

no i trying to use the gui one

For the GUI based on I have a feature idea. You can spaw in a UI (Using one of the top buttons) that allows you to add people to this mode (who are in server) without being on admin list. Helpful for special visitors who dont have dev perms but have admin perms. I would make my own but I have never used TopBarPlus Extension. And also lot’s of people would probably like this.

1 Like