diff --git a/BondageClub/Icons/Rectangle/ClearFocus.png b/BondageClub/Icons/Rectangle/ClearFocus.png
new file mode 100644
index 0000000000000000000000000000000000000000..bab262887cdafae43afbdb078c712e62540bf06a
Binary files /dev/null and b/BondageClub/Icons/Rectangle/ClearFocus.png differ
diff --git a/BondageClub/Icons/Small/FocusEnabledWarning.png b/BondageClub/Icons/Small/FocusEnabledWarning.png
new file mode 100644
index 0000000000000000000000000000000000000000..c73ec8f686e31b60514afcad509a63527aa53056
Binary files /dev/null and b/BondageClub/Icons/Small/FocusEnabledWarning.png differ
diff --git a/BondageClub/Screens/Online/ChatRoom/ChatRoom.js b/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
index ce64f92f0b5461f34031b62199511fc95ae17c14..e6d49fadb1c5556f4adea198be54b7c84dec4445 100644
--- a/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
+++ b/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
@@ -86,6 +86,18 @@ var ChatRoomChatHidden = false;
  * @type {Character[]}
  */
 var ChatRoomCharacterDrawlist = [];
+/**
+ * If non-empty, ChatRoomCharacterDrawlist will be filtered (after immersion removals) to only include the player and these character(s).
+ * Used for the /focus command. List will be automatically removed if characters are removed from the room.
+ * @type {Character[]}
+ */
+var ChatRoomDrawFocusList = [];
+/**
+ * The list of characters currently impacted (not drawn) by sensory deprivation in the chat room
+ * Used as a check for whether to apply further sense dep effects to a given character (i.e. name removal, message, hiding, etc). Characters from {@link ChatRoomCharacter}
+ * @type {Character[]}
+ */
+var ChatRoomImpactedBySenseDep = [];
 var ChatRoomSenseDepBypass = false;
 var ChatRoomGetUpTimer = 0;
 /**
@@ -442,6 +454,11 @@ function ChatRoomCanGiveMoneyForOwner() { return (CurrentCharacter != null && Pl
  * @returns {boolean} - TRUE if the player is an admin of the current chatroom.
  */
 function ChatRoomPlayerIsAdmin() { return ((ChatRoomData != null && ChatRoomData.Admin != null) && (ChatRoomData.Admin.indexOf(Player.MemberNumber) >= 0)); }
+/**
+ * Checks if the player is currently in focus mode (non-empty {@link ChatRoomDrawFocusList})
+ * @returns {boolean} - TRUE if the player is in focus mode
+ */
+function ChatRoomPlayerIsInDrawFocus() { return ChatRoomDrawFocusList.length > 0; }
 /**
  * Checks if the current character is an admin of the chatroom.
  * @returns {boolean} - TRUE if the current character is an admin.
@@ -457,6 +474,11 @@ function ChatRoomPlayerIsWhitelisted() { return ((ChatRoomData != null && ChatRo
  * @returns {boolean} - TRUE if the current character is in the chatroom whitelist.
  */
 function ChatRoomCurrentCharacterIsWhitelisted() { return ((CurrentCharacter != null) && (ChatRoomData.Whitelist != null) && (ChatRoomData.Whitelist.indexOf(CurrentCharacter.MemberNumber) >= 0)); }
+/**
+ * Checks if the current character is in the player's focuslist (/focus).
+ * @returns {boolean} - TRUE if the current character is in the player's focuslist.
+ */
+function ChatRoomCurrentCharacterInDrawFocusList() { return ((CurrentCharacter != null) && (ChatRoomDrawFocusList.indexOf(CurrentCharacter) >= 0)); }
 /**
  * Checks if the room allows the photograph feature to be used.
  * @returns {boolean} - TRUE if the player can take a photo.
@@ -1340,6 +1362,7 @@ function ChatRoomMenuBuild() {
 	ChatRoomMenuButtons.push("Exit");
 	ChatRoomMenuButtons.push("Kneel");
 	ChatRoomMenuButtons.push("Icons");
+	if (ChatRoomPlayerIsInDrawFocus()) ChatRoomMenuButtons.push("ClearFocus");
 	if (DialogCanTakePhotos()) ChatRoomMenuButtons.push("Camera");
 	ChatRoomMenuButtons.push("Cut");
 	if (ChatRoomMapViewIsActive() && ((ChatRoomData == null) || (ChatRoomData.MapData == null) || (ChatRoomData.MapData.Type == null) || (ChatRoomData.MapData.Type != "Always"))) ChatRoomMenuButtons.push("CharacterView");
@@ -1373,14 +1396,17 @@ function ChatRoomUpdateDisplay() {
 	ChatRoomCharacterDrawlist = ChatRoomCharacter;
 	ChatRoomSenseDepBypass = false;
 	if (Player.Effect.includes("VRAvatars")) {
+		ChatRoomImpactedBySenseDep = ChatRoomCharacterDrawlist.slice();
 		ChatRoomCharacterDrawlist = [];
 		ChatRoomSenseDepBypass = true;
 		for (let CC = 0; CC < ChatRoomCharacter.length; CC++) {
 			if (ChatRoomCharacter[CC].Effect.includes("VRAvatars")) {
 				ChatRoomCharacterDrawlist.push(ChatRoomCharacter[CC]);
+				ChatRoomImpactedBySenseDep.splice(ChatRoomImpactedBySenseDep.indexOf(ChatRoomCharacter[CC]), 1);
 			}
 		}
 	} else if (Player.GetBlindLevel() > 0 && Player.GetBlindLevel() < 3 && Player.ImmersionSettings.BlindAdjacent) {
+		ChatRoomImpactedBySenseDep = ChatRoomCharacterDrawlist.slice();
 		// We hide all players except those who are adjacent
 		ChatRoomCharacterDrawlist = [];
 		ChatRoomSenseDepBypass = true;
@@ -1396,10 +1422,16 @@ function ChatRoomUpdateDisplay() {
 		for (let CC = 0; CC < ChatRoomCharacter.length; CC++) {
 			if (Math.abs(CC - PlayerIndex) <= 1) {
 				ChatRoomCharacterDrawlist.push(ChatRoomCharacter[CC]);
+				ChatRoomImpactedBySenseDep.splice(ChatRoomImpactedBySenseDep.indexOf(ChatRoomCharacter[CC]), 1);
 			}
 		}
 	}
 
+	// If we're in focus (focuslist exists), filter out any players not in it (/focus)
+	if (ChatRoomPlayerIsInDrawFocus()) {
+		ChatRoomCharacterDrawlist = ChatRoomCharacterDrawlist.filter(C => C.IsPlayer() || ChatRoomDrawFocusList.includes(C));
+	}
+
 	// Keeps the current character count and total
 	ChatRoomCharacterViewCharacterCount = RenderSingle ? 1 : ChatRoomCharacterDrawlist.length;
 	ChatRoomCharacterViewCharacterCountTotal = RenderSingle ? 1 : ChatRoomCharacterDrawlist.length;
@@ -1460,6 +1492,12 @@ function ChatRoomDrawCharacterStatusIcons(C, CharX, CharY, Zoom)
 	} else if (Player.BlackList.includes(C.MemberNumber)) {
 		DrawImageResize("Icons/Small/BlackList.png", CharX + 70 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
 	}
+	// Unobtrusive but prominent warnings to alert user they are in focus mode -- drawn on player and all focused (visible) characters
+	if (ChatRoomPlayerIsInDrawFocus() && (C.IsPlayer() || ChatRoomDrawFocusList.includes(C)))
+	{
+		DrawImageResize("Icons/Small/FocusEnabledWarning.png", CharX + 30 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
+		DrawImageResize("Icons/Small/FocusEnabledWarning.png", CharX + 30 * Zoom, CharY + 950 * Zoom, 40 * Zoom, 40 * Zoom);
+	}
 	if (Player.GhostList.includes(C.MemberNumber)) {
 		DrawImageResize("Icons/Small/GhostList.png", CharX + 110 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
 	} else if (Player.FriendList.includes(C.MemberNumber)) {
@@ -2542,6 +2580,10 @@ function ChatRoomMenuClick(event) {
 					ChatRoomHideIconState += 1;
 					if (ChatRoomHideIconState > 3) ChatRoomHideIconState = 0;
 					break;
+				case "ClearFocus":
+					// When the user wants to exit focus mode (clear their focus list)
+					ChatRoomDrawFocusListClear();
+					break;
 				case "Camera":
 					// When the user takes a photo of the room
 					ChatRoomPhotoFullRoom();
@@ -2730,6 +2772,7 @@ function ChatRoomLeave(clearCharacters = false) {
 	Player.MapData = null;
 	ChatRoomGame = "";
 	ChatRoomCharacter = [];
+	ChatRoomDrawFocusList = [];
 	ChatRoomMapViewTileFog = "";
 	ChatRoomMapViewObjectFog = "";
 	ChatRoomSetTarget(-1);
@@ -3312,7 +3355,7 @@ function ChatRoomMessageInvolvesPlayer(data) {
  * @returns true if the player is sensory-deprived from character, false otherwise.
  */
 function ChatRoomIsCharacterImpactedBySensoryDeprivation(character) {
-	return PreferenceIsPlayerInSensDep() && character.MemberNumber != Player.MemberNumber && (!ChatRoomSenseDepBypass || !ChatRoomCharacterDrawlist.includes(character));
+	return PreferenceIsPlayerInSensDep() && character.MemberNumber != Player.MemberNumber && (!ChatRoomSenseDepBypass || ChatRoomImpactedBySenseDep.includes(character));
 }
 
 /** @type {ChatRoomMessageExtractor[]} */
@@ -3535,7 +3578,7 @@ var ChatRoomMessageHandlers = [
 			const IsPlayerInSensoryDep = Player.ImmersionSettings.SenseDepMessages
 				&& PreferenceIsPlayerInSensDep()
 				&& Player.GetDeafLevel() >= 4
-				&& (!ChatRoomSenseDepBypass || !ChatRoomCharacterDrawlist.includes(sender));
+				&& (!ChatRoomSenseDepBypass || ChatRoomImpactedBySenseDep.includes(sender));
 
 			// When the player is in total sensory deprivation, hide non-whisper messages if the player is not involved
 			const IsPlayerMentioned = ChatRoomMessageMentionsCharacter(Player, msg);
@@ -4268,7 +4311,7 @@ function ChatRoomMessageDisplay(data, msg, SenderCharacter, metadata) {
 function ChatRoomHideIdentity(C) {
 	return PreferenceIsPlayerInSensDep()
 		&& C.MemberNumber != Player.MemberNumber
-		&& (!ChatRoomSenseDepBypass || !ChatRoomCharacterDrawlist.includes(C));
+		&& (!ChatRoomSenseDepBypass || ChatRoomImpactedBySenseDep.includes(C));
 }
 
 /**
@@ -4384,6 +4427,9 @@ function ChatRoomSync(data) {
 		ChatRoomCharacter.push(Char);
 	}
 
+	// Reset when creating/joining a room, in case it wasn't by ChatRoomLeave() for whatever reason
+	ChatRoomDrawFocusList = [];
+
 	// If there's a game running in that chatroom, save it and perform a reset
 	if (ChatRoomData.Game != null) {
 		ChatRoomGame = ChatRoomData.Game;
@@ -4482,6 +4528,7 @@ function ChatRoomSyncMemberLeave(data) {
 
 	// Remove the character
 	ChatRoomCharacter = ChatRoomCharacter.filter(x => x.MemberNumber != data.SourceMemberNumber);
+	ChatRoomDrawFocusList = ChatRoomDrawFocusList.filter(x => x.MemberNumber != data.SourceMemberNumber);
 	ChatRoomData.Character = ChatRoomData.Character.filter(x => x.MemberNumber != data.SourceMemberNumber);
 
 	// Check whether the player's last chatroom data needs updating
@@ -5030,12 +5077,18 @@ function ChatRoomCurrentTime() {
 /**
  * Adds or removes an online member to/from a specific list. (From the dialog menu)
  * @param {"Add" | "Remove"} Operation - Operation to perform.
- * @param {"WhiteList" | "FriendList" | "BlackList" | "GhostList"} ListType - Name of the list to alter. (Whitelist, friendlist, blacklist, ghostlist)
+ * @param {"WhiteList" | "FriendList" | "BlackList" | "GhostList" | "DrawFocusList"} ListType - Name of the list to alter. (Whitelist, friendlist, blacklist, ghostlist, drawfocuslist)
  * @returns {void} - Nothing
  */
 function ChatRoomListManage(Operation, ListType) {
-	if (CurrentCharacter && CurrentCharacter.MemberNumber && Array.isArray(Player[ListType])) {
-		ChatRoomListUpdate(Player[ListType], Operation == "Add", CurrentCharacter.MemberNumber);
+	if (CurrentCharacter) {
+		const isAdd = Operation === "Add";
+		if (ListType === "DrawFocusList"){
+			if (isAdd) ChatRoomDrawFocusListAdd([CurrentCharacter]);
+			else ChatRoomDrawFocusListRemove([CurrentCharacter]);
+		} else if (CurrentCharacter.MemberNumber && Array.isArray(Player[ListType])) {
+			ChatRoomListUpdate(Player[ListType], isAdd, CurrentCharacter.MemberNumber);
+		}
 	}
 }
 
@@ -5086,6 +5139,51 @@ function ChatRoomListUpdate(list, adding, memberNumber) {
 	setTimeout(() => ChatRoomCharacterUpdate(Player), 5000);
 }
 
+/**
+ * Adds a list of character(s) into the Focus List
+ * @param {Character[]} characters - Characters to add
+ * @param {boolean} [enableMessage=true] - If enabled, will tell (warn) the user when the focus feature becomes enabled (empty -> non-empty)
+ * @returns {Character[]} - Characters that were actually added (not already in the list)
+ */
+function ChatRoomDrawFocusListAdd(characters, enableMessage=true) {
+	const added = [];
+	const wasInFocus = ChatRoomPlayerIsInDrawFocus();
+	characters.forEach(c => {
+		if (!ChatRoomDrawFocusList.includes(c)) {
+			ChatRoomDrawFocusList.push(c);
+			added.push(c);
+		}
+	});
+	if (enableMessage && !wasInFocus && ChatRoomPlayerIsInDrawFocus()) {
+		const enableMessageText = TextGet("FocusEnabled").replaceAll('FocusEnabledWarningIcon', TextGet("FocusEnabledWarningIcon"));
+		ChatRoomSendLocal(`<span style="color: deepskyblue">${enableMessageText}</span>`, 60_000);
+	}
+	return added;
+}
+
+/**
+ * Removes a list of character(s) from the Focus List
+ * @param {Character[]} characters - Characters to remove
+ * @returns {Character[]} - Characters that were actually removed (were in the list)
+ */
+function ChatRoomDrawFocusListRemove(characters) {
+	const removed = [];
+	characters.forEach(c => {
+		if (ChatRoomDrawFocusList.includes(c)) {
+			ChatRoomDrawFocusList.splice(ChatRoomDrawFocusList.indexOf(c), 1);
+			removed.push(c);
+		}
+	});
+	return removed;
+}
+
+/**
+ * Clears the Focus List
+ */
+function ChatRoomDrawFocusListClear() {
+	ChatRoomDrawFocusList = [];
+}
+
 /**
  * Handles reception of data pertaining to if applying an item is allowed.
  * @param {ServerChatRoomAllowItemResponse} data - Data object containing if the player is allowed to interact with a character.
diff --git a/BondageClub/Screens/Online/ChatRoom/Commands.js b/BondageClub/Screens/Online/ChatRoom/Commands.js
index a7f98c5d837a204fa428c66cfd49aa76e650824a..ac1542c00a21bdc79fcf1bf214ac6bb8f57381ef 100644
--- a/BondageClub/Screens/Online/ChatRoom/Commands.js
+++ b/BondageClub/Screens/Online/ChatRoom/Commands.js
@@ -678,6 +678,136 @@ const CommonCommands = [
 		Prerequisite: () => ChatRoomPlayerIsAdmin(),
 		Action: args => ChatRoomAdminChatAction("Unwhitelist", args),
 	},
+	{
+		Tag: 'focus',
+		Prerequisite: () => ServerPlayerIsInChatRoom(),
+		Action: (args) => {
+			const parts = args.split(' ');
+
+			const subcommand = parts.length > 0 ? parts[0].toLowerCase() : 'help';
+			if (/^(add|remove)$/.test(subcommand)) {
+				if (parts.length === 1) {
+					ChatRoomSendLocal(TextGet("CommandFocusNoTargets"), 30_000);
+					return;
+				}
+
+				/** @type {Character[]} */
+				const matchingCharacters = [];
+				parts.slice(1).forEach(targeter => { // For each targeter the user provided
+					const memberNumber = parseInt(targeter);
+					const targeterSanitized = ChatRoomHTMLEntities(targeter);
+
+					let targeterResult = ChatRoomCharacter.find(C => // Attempt to first find an exact match
+						!C.IsPlayer() &&
+						(
+							C.MemberNumber === memberNumber ||
+							C.Name.toLowerCase() === targeter.toLowerCase() ||
+							C.Nickname?.toLowerCase() === targeter.toLowerCase()
+						)
+					);
+					if (!targeterResult) { // If no exact match, attempt a partial match
+						const partialMatches = ChatRoomCharacter.filter(C =>
+							!C.IsPlayer() &&
+							(
+								C.Name.toLowerCase().includes(targeter.toLowerCase()) ||
+								C.Nickname?.toLowerCase().includes(targeter.toLowerCase())
+							)
+						);
+
+						if (partialMatches.length === 1) { // If only one partial match, use it
+							targeterResult = partialMatches[0];
+						} else if (partialMatches.length > 1) { // If multiple partial matches, inform the user
+							ChatRoomSendLocal(TextGet("CommandFocusTargeterAmbiguous").replace("Targeter", targeterSanitized), 5_000);
+							return;
+						}
+					}
+
+					if (targeterResult) {
+						if (matchingCharacters.includes(targeterResult)) { // If the targeter is already in the list, don't add it again
+							ChatRoomSendLocal(TextGet("CommandFocusTargeterDuplicate").replace("Targeter", targeterSanitized), 5_000);
+						} else {
+							matchingCharacters.push(targeterResult);
+						}
+					} else {
+						ChatRoomSendLocal(TextGet("CommandFocusTargeterNoMatch").replace("Targeter", targeterSanitized), 5_000);
+					}
+				});
+
+				if (matchingCharacters.length === 0) {
+					ChatRoomSendLocal(TextGet("CommandFocusNoTargets"), 10_000);
+					return;
+				}
+
+				/** @type {Character[]} */
+				let changed;
+				if (subcommand === 'add') {
+					changed = ChatRoomDrawFocusListAdd(matchingCharacters);
+				} else if (subcommand === 'remove') {
+					changed = ChatRoomDrawFocusListRemove(matchingCharacters);
+				} else { // Shouldn't happen, but sanity check
+					return;
+				}
+				ChatRoomSendLocal(
+					TextGet(`CommandFocusSuccess${subcommand.charAt(0).toUpperCase()}${subcommand.slice(1)}`)
+						.replace("Changed", changed.map(C => `${CharacterNickname(C)} (${C.MemberNumber})`).join(", ")),
+					10_000
+				);
+			} else if (/^(list|clear)$/.test(subcommand) && parts.length === 1) {
+				if (subcommand === 'list') {
+					ChatRoomSendLocal(TextGet("CommandFocusList") + "<br>" + ChatRoomDrawFocusList.map(C => `${CharacterNickname(C)} (${C.MemberNumber})`).join("<br>"), 30_000);
+				} else if (subcommand === 'clear') {
+					ChatRoomDrawFocusListClear();
+					ChatRoomSendLocal(TextGet("CommandFocusSuccessClear"), 10_000);
+				}
+			} else { // If the subcommand is not recognized (also handles the "help" subcommand implicitly)
+				ChatRoomSendLocal(
+					`<code>${TextGet("CommandFocusHelpSyntax")}</code>` +
+					"<br><br>" +
+					TextGet("CommandFocusHelpSummary").replaceAll("FocusEnabledWarningIcon", TextGet("FocusEnabledWarningIcon")) +
+					"<br><br>" +
+					TextGet("CommandFocusHelpNotesHeader") +
+					"<br><ul>" +
+					TextGet("CommandFocusHelpNotes") +
+					"</ul><br>" +
+					TextGet("CommandFocusHelpSubcommandsHeader") +
+					"<br><ul>" +
+					`<li><code>add [targeter(s)]</code>: ${TextGet("CommandFocusHelpAdd")}</li>` +
+					`<li><code>remove [targeter(s)]</code>: ${TextGet("CommandFocusHelpRemove")}</li>` +
+					`<li><code>list</code>: ${TextGet("CommandFocusHelpList")}</li>` +
+					`<li><code>clear</code>: ${TextGet("CommandFocusHelpClear")}</li>` +
+					`<li><code>help</code>: ${TextGet("CommandFocusHelpHelp")}</li>` +
+					"</ul><br>" +
+					TextGet("CommandFocusHelpTargeters"),
+					120_000
+				);
+			}
+		}
+	},
+	{
+		Tag: 'focusadd',
+		Prerequisite: () => ServerPlayerIsInChatRoom(),
+		Action: (args) => CommandExecute("/focus add " + args),
+	},
+	{
+		Tag: 'focusremove',
+		Prerequisite: () => ServerPlayerIsInChatRoom(),
+		Action: (args) => CommandExecute("/focus remove " + args),
+	},
+	{
+		Tag: 'focuslist',
+		Prerequisite: () => ServerPlayerIsInChatRoom(),
+		Action: () => CommandExecute("/focus list"),
+	},
+	{
+		Tag: 'focusclear',
+		Prerequisite: () => ServerPlayerIsInChatRoom(),
+		Action: () => CommandExecute("/focus clear"),
+	},
+	{
+		Tag: 'focushelp',
+		Prerequisite: () => ServerPlayerIsInChatRoom(),
+		Action: () => CommandExecute("/focus help"),
+	},
 	{
 		Tag: 'me',
 		Action: (_, msg) => {
diff --git a/BondageClub/Screens/Online/ChatRoom/Dialog_Online.csv b/BondageClub/Screens/Online/ChatRoom/Dialog_Online.csv
index 8fe05fafbd9b7ba4c28f1cd940ebb6a10cd8428a..0aa4a517f4a2cce24a0bab35682d849a34627611 100644
--- a/BondageClub/Screens/Online/ChatRoom/Dialog_Online.csv
+++ b/BondageClub/Screens/Online/ChatRoom/Dialog_Online.csv
@@ -93,6 +93,8 @@ ReleaseLoverConfirm,0,"(Cancel)",(Main menu),,
 40,,,(Possible character actions.),,
 40,0,(Whisper to DialogCharacterObject.),,StartWhisper(),CanStartWhisper()
 40,0,(Stop whispering to DialogCharacterObject.),,StopWhisper(),CanStopWhisper()
+40,,(Add to focuslist.),(This member was added to your focus list. You will only be able to visually see DialogCharacterObject and others on your focus list in the room. See /focus for more details.),"ListManage(""Add"", ""DrawFocusList"")",!CurrentCharacterInDrawFocusList()
+40,,(Remove from focuslist.),(This member was removed from your focus list. See /focus for more details.),"ListManage(""Remove"", ""DrawFocusList"")",CurrentCharacterInDrawFocusList()
 40,,(Hold on to DialogCharacterPossessive leash.),,HoldLeash(),CanHoldLeash()
 40,,(Let go of DialogCharacterPossessive leash.),,StopHoldLeash(),CanStopHoldLeash()
 40,0,(Help DialogCharacterObject stand.),(You help DialogCharacterObject up on DialogCharacterPossessive feet.),KneelStandAssist(),CanAssistStand()
diff --git a/BondageClub/Screens/Online/ChatRoom/Text_ChatRoom.csv b/BondageClub/Screens/Online/ChatRoom/Text_ChatRoom.csv
index 96cffab56d2ed3a38cc7e17ceb1eaa5e3bb09d79..9be88d1d23460a6ba57b8a3696672c906aa30315 100644
--- a/BondageClub/Screens/Online/ChatRoom/Text_ChatRoom.csv
+++ b/BondageClub/Screens/Online/ChatRoom/Text_ChatRoom.csv
@@ -38,6 +38,27 @@ CommandFriendlist,Friendlist:
 CommandGhostlist,Ghostlist:
 CommandWhitelist,Whitelist:
 CommandBlacklist,Blacklist:
+FocusEnabledWarningIcon,"<img src='Icons/Small/FocusEnabledWarning.png' style='display: inline-block; height: 1em; vertical-align: middle; transform: translateY(-0.15em);' aria-hidden='true'>"
+FocusEnabled,"<strong>NOTICE</strong>: The FocusEnabledWarningIcon <strong>focus list</strong> FocusEnabledWarningIcon is now <strong>enabled</strong>. <i>Only characters on your focus list will be visible to you in the chatroom</i>. To disable this, use <code>/focus clear</code> or the button in the menu bar."
+CommandFocusTargeterAmbiguous,"IGNORING 'Targeter': multiple matches found."
+CommandFocusTargeterDuplicate,"IGNORING 'Targeter': result was previously matched."
+CommandFocusTargeterNoMatch,"IGNORING 'Targeter': no match was found."
+CommandFocusNoTargets,"<strong>FAIL</strong>: no targets were found (targeters did not match or were not provided) -- no changes were made."
+CommandFocusSuccessAdd,"<strong>SUCCESS</strong>: The following targets were added to your focus list: Changed."
+CommandFocusSuccessRemove,"<strong>SUCCESS</strong>: The following targets were removed from your focus list: Changed."
+CommandFocusSuccessClear,"<strong>SUCCESS</strong>: Your focus list was cleared."
+CommandFocusList,"Focus List:"
+CommandFocusHelpSyntax,/focus add/remove/list/clear/help [targeter(s)]
+CommandFocusHelpSummary,"Modifies your focus list. When you have users on your focus list, the characters you can visually see in the chatroom are filtered to only those on your focus list. When your focus list is enabled, you will see the FocusEnabledWarningIcon icon on all characters. To go back to viewing all characters, use <code>/focus clear</code> or the button in the menu bar."
+CommandFocusHelpNotesHeader,"Notes:"
+CommandFocusHelpNotes,"<li>If you normally would not be able to see a character on your focus list (e.g. sensory deprivation), they still will not be visible to you.</li><li>Neither chat messages nor map rooms are affected by the focus list.</li><li>If a player on your focus list leaves the room, they are removed from the list.</li>"
+CommandFocusHelpSubcommandsHeader,"Subcommands:"
+CommandFocusHelpAdd,Add the members to your focus list
+CommandFocusHelpRemove,Removes the members from your focus list
+CommandFocusHelpList,Shows the members on your focus list
+CommandFocusHelpClear,Clears your focus list (returns to viewing all members)
+CommandFocusHelpHelp,Display this help message
+CommandFocusHelpTargeters,"Targeters: A list of names or member numbers to target in a subcommand, separated by spaces. Names can be partial, but must be unique. Exact name matches will take precedence over partial matches."
 CommandChangeLogClear,Clear changelog
 CommandChangeLogCollapse,Collapse section
 CommandChangeLogCollapseShift,{shift} to collapse all
diff --git a/BondageClub/Screens/Online/ChatRoom/Text_Commands.csv b/BondageClub/Screens/Online/ChatRoom/Text_Commands.csv
index 4c08e165c49a345294b6e0495f6b4d1ca60b59e6..3712ea389d9192c2d1ae93046903df0713d87f6d 100644
--- a/BondageClub/Screens/Online/ChatRoom/Text_Commands.csv
+++ b/BondageClub/Screens/Online/ChatRoom/Text_Commands.csv
@@ -13,6 +13,12 @@ demote,[MemberNumber]: Demote the player from room administrator
 dice,[Number]: Roll a 6-sided die. Adding “[Number]” after the command for any number between 2 and 100 will roll a die of that many sides instead. Adding “[Number]d[Number]” will roll multiple dice and sum the total.
 expr,[0-5]: Clear or load facial expression. ”0” after the command will clear current expression. ”1” to ”5” will load expression from the saved slot. Giving no number opens the saved expression menu.
 eyes,"[o|c][l|r] or [expression]: Open or close eyes or change expression. ”c” will close, ”o” will open, using ”l” or ”r” will target only one eye. Giving no action opens the expression menu, using one of ”default”, ”dazed”, ”shy”, ”sad”, ”horny”, ”lewd”, ”verylewd”, ”heart”, ”heartpink”, ”lewdheart”, ”lewdheartpink”, ”dizzy” (or ”@@”), ”daydream” (or ”><”), ”shylyhappy” (or ”^^”), ”angry” (or ”èé”), ”surprised” (or ”éè”) or ”scared” will change expression."
+focus,add/remove/list/clear/help [targeter(s)]: Modifies your focus list (which allows you to selectively view players in a chatroom). Run '/focus' for more information.
+focusadd,[targeter(s)]: Alias for /focus add [targeter(s)]
+focusremove,[targeter(s)]: Alias for /focus remove [targeter(s)]
+focuslist,: Alias for /focus list
+focusclear,: Alias for /focus clear
+focushelp,: Alias for /focus help
 friendlistadd,[MemberNumber]: Add the player to your friendlist
 friendlistremove,[MemberNumber]: Remove the player from your friendlist
 ghostadd,[MemberNumber]: Add the player to your ghostlist