diff --git a/esoui/ingame/voicechat/console/zo_voicechat_manager.lua b/esoui/ingame/voicechat/console/zo_voicechat_manager.lua
index 949489c..2630891 100755
--- a/esoui/ingame/voicechat/console/zo_voicechat_manager.lua
+++ b/esoui/ingame/voicechat/console/zo_voicechat_manager.lua
@@ -1,19 +1,30 @@
+--Global voice chat related functions and data
 function ZO_VoiceChat_GetChannelDataFromName(channelName)
     local channelType, guildId, guildRoomNumber = VoiceChatGetChannelInfo(channelName)
 
     local channelData = {
         channelType = channelType,
-        guildId = guildId,
+        guildId = guildId, --this value is invalid when retrieved for a guild channel that is no longer available
         guildRoomNumber = guildRoomNumber
     }
 
     return channelData
 end
 
+function ZO_VoiceChat_IsNameLocalPlayers(displayName)
+    return displayName == GetDisplayName()
+end
+
+VOICE_CHAT_OFFICERS_ROOM_NUMBER = 0 --The guild channel # we use to represent the special Officer's channel.
+
+VOICE_CHAT_ICON_MUTED_PLAYER = "EsoUI/Art/VOIP/Gamepad/gp_VOIP_muted.dds"
+VOICE_CHAT_ICON_LISTENING_CHANNEL = "EsoUI/Art/VOIP/Gamepad/gp_VOIP_listening.dds"
+
 
---------------------------------------------
+--------------------------------------------------------------------------------
 -- VoiceChat History Data
---------------------------------------------
+--      Helper class for saving and sorting the speaker history of each channel.
+--------------------------------------------------------------------------------
 local HISTORY_ENTRY_LIMIT = 15
 
 
@@ -22,7 +33,7 @@ local HistoryData = ZO_Object:Subclass()
 function HistoryData:New()
     local obj = ZO_Object.New(self)
 
-    obj.list = {}
+    obj.list = {} --entries toward the end of the list are considered newer
     obj.map = {}
 
     return obj
@@ -57,10 +68,10 @@ function HistoryData:UpdateUserMute(displayName, isMuted)
     end
 end
 
-function HistoryData:UpdateMutes(muteMap)
+function HistoryData:UpdateMutes(mutedUsers)
     for i = 1, #self.list do
         local speakerData = self.list[i]
-        speakerData.isMuted = muteMap[speakerData.displayName]
+        speakerData.isMuted = mutedUsers[speakerData.displayName]
     end
 end
 
@@ -77,9 +88,10 @@ end
 
 
 
---------------------------------------------
+--------------------------------------------------------------------------------
 -- VoiceChat Participants Data
---------------------------------------------
+--      Helper class for saving and sorting the participants of each channel.
+--------------------------------------------------------------------------------
 
 local SORT_KEYS = {
     displayName = {}
@@ -99,12 +111,12 @@ function ParticipantsData:New(sortByOccurrence)
 
     obj.list = {}
     obj.map = {}
-    obj.sortByOccurrence = sortByOccurrence
+    obj.sortByOccurrence = sortByOccurrence --when true, newer entries occur first in the list
 
     return obj
 end
 
-function ParticipantsData:AddParticipant(displayName, speakStatus, isMuted)
+function ParticipantsData:AddOrUpdateParticipant(displayName, speakStatus, isMuted)
     if self.map[displayName] then
         self:UpdateParticipantStatus(displayName, speakStatus, isMuted)
         return
@@ -154,12 +166,15 @@ function ParticipantsData:UpdateParticipantStatus(displayName, speakStatus, isMu
                 speakerData.lastTimeSpoken = GetFrameTimeMilliseconds()
             end
         end
+
+        --Only update the mute status if an argument was provided
         if isMuted ~= nil then
             speakerData.isMuted = isMuted
         end
     
         if self.sortByOccurrence then
             if speakStatus == VOICE_CHAT_SPEAK_STATE_SPEAKING then
+                --Move the user to the end of the list
                 table.remove(self.list, index)
                 table.insert(self.list, 1, speakerData)
             end
@@ -167,10 +182,10 @@ function ParticipantsData:UpdateParticipantStatus(displayName, speakStatus, isMu
     end
 end
 
-function ParticipantsData:UpdateMutes(muteMap)
+function ParticipantsData:UpdateMutes(mutedUsers)
     for i = 1, #self.list do
         local speakerData = self.list[i]
-        speakerData.isMuted = muteMap[speakerData.displayName]
+        speakerData.isMuted = mutedUsers[speakerData.displayName]
     end
 end
 
@@ -183,34 +198,15 @@ function ParticipantsData:ClearParticipants()
     self.map = {}
 end
 
-function ParticipantsData:ClearAllParticipantSpeakStatus()
-    for i = 1, #self.list do
-        self.list[i].speakStatus = VOICE_CHAT_SPEAK_STATE_IDLE
-    end
-end
-
-function ParticipantsData:ClearParticipantSpeakStatus(displayName)
-    local speakerData = self:GetParticipant(displayName)
-    if speakerData then
-        speakerData.speakStatus = VOICE_CHAT_SPEAK_STATE_IDLE
-    end
-end
-
 
 
---------------------------------------
+--------------------------------------------------------------------------------
 --Voice Chat Manager
---------------------------------------
+--  Data manager for Voice Chat. Also handles the channel joining automation
+--  and 1+1 Active/Passive channel functionality.
+--------------------------------------------------------------------------------
 
-local SKIP_DELAY = true
-
-local OFFICERS_ROOM_NUMBER = 0
-
-local SAVE_SETTINGS_DELAY = 2000
-
-local function IsNameLocalPlayer(displayName)
-    return displayName == GetDisplayName()
-end
+local SAVE_SETTINGS_DELAY = 2000 --the delay until the settings will save after being changed
 
 
 VOICE_CHAT_MANAGER = nil
@@ -224,13 +220,15 @@ function ZO_VoiceChat_Manager:New()
 end
 
 function ZO_VoiceChat_Manager:Initialize()
+    --Use a delayed callback after making a Voice Chat related server request to temporarily lock out
+    --further requests. This is to give the first request a chance to complete.
     self.areRequestsAllowed = true
     self.requestDelayFunction = function()
         self.areRequestsAllowed = true
         self:FireCallbacks("RequestsAllowed")
     end
 
-    --Use callback for saving script settings so we can save just once when multiple settings are changed
+    --Use a delayed callback after changing a setting so that we can save just once for multiple changes.
     self.saveSettingsCount = 0
     self.saveSettingsFunction = function()
         self.saveSettingsCount = math.max(self.saveSettingsCount - 1, 0)
@@ -258,21 +256,26 @@ function ZO_VoiceChat_Manager:Initialize()
             description = GetString(SI_GAMEPAD_VOICECHAT_CHANNEL_DESCRIPTION_GROUP),
             historyData = HistoryData:New(),
         },
-        [VOICE_CHANNEL_GUILD] = {}, --populated based on guild existence
+        [VOICE_CHANNEL_GUILD] = {}, --populates during channel retrieval
     }
 
+    --The guild ids are dirtied and will need to be refreshed for all guild channels whenever a guild is joined or left.
+    self.guildIdsDirty = false
+
+    --The guild ids we can retrieve from engine are invalid for channels that just became unavailable. We'll need to keep
+    --a local cache so we can id guilds for certain channel events.
     self.guildChannelsToIds = {}
 
     self.participantsData = {}
     self.participantsData[VOICE_CHANNEL_AREA] = ParticipantsData:New(SORT_BY_OCCURRENCE)
     self.participantsData[VOICE_CHANNEL_GROUP] = ParticipantsData:New(DONT_SORT_BY_OCCURRENCE)
-    self.participantsData[VOICE_CHANNEL_GUILD] = {} --populated based on guild existence
+    self.participantsData[VOICE_CHANNEL_GUILD] = {} --populates during channel retrieval
 
-    self.muteCache = {}
+    self.mutedUsers = {}
     self:UpdateMutes()
 
-    self.activeChannel = nil
-    self.passiveChannel = nil
+    self.activeChannel = nil --a channel we're joined to and transmitting on
+    self.passiveChannel = nil --a channel we're joined to, but only listening to
     self.desiredPassiveChannel = nil
     self.desiredActiveChannel = nil
 
@@ -281,7 +284,6 @@ end
 
 function ZO_VoiceChat_Manager:RegisterForEvents()
     local function RetrieveParticipants(channel)
-    --TODO: Maybe change engine and ui for updating like other systems by iterating over each participant
         self:GetParticipantData(channel):ClearParticipants()
         VoiceChatRequestChannelUsers(channel.channelName)
     end
@@ -348,9 +350,32 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
         end
     end
 
+    local function SwapOnLosingActiveGuildChannel()
+        local groupChannel = self.channelData[VOICE_CHANNEL_GROUP]
+        if groupChannel.isAvailable then
+            self:SetDesiredActiveChannel(groupChannel)
+        else
+            self:SetDesiredActiveChannel(self.desiredPassiveChannel)
+            self:SetDesiredPassiveChannel(nil)
+        end
+    end
+    
+    local function TryClearPassiveChannel(channel)
+        if self.passiveChannel == channel then
+            self.passiveChannel = nil
+        end
+    end
+    
+    local function TryClearActiveChannel(channel)
+        if self.activeChannel == channel then
+            self.activeChannel = nil
+        end
+    end
+
     --Event Handlers
     local function OnAddOnLoaded(name)
         if name == "ZO_Ingame" then
+            --Load the preferred channel settings
             local defaultSettings = {
                 isFirstRun = true,
                 desiredActiveChannel = {},
@@ -359,18 +384,22 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
             self.savedVars = ZO_SavedVars:New("ZO_Ingame_SavedVariables", 1, "VoiceChat", defaultSettings)
             EVENT_MANAGER:UnregisterForEvent("ZO_VoiceChat_OnAddOnLoaded", EVENT_ADD_ON_LOADED)
             
+            --We wait to request the list of channels until after we've loaded settings
             VoiceChatGetChannels()
         end
     end
 
     local function OnPlayerActivated()
+        --Only automatically join channels on the first activation after logging into the game.
         if VoiceChatGetShouldDoLoginJoins() then
-            --Delayed to give all channels a chance to populate
+            --We can activate at the same time we're receiving the channel events, so delay any
+            --automatic joining until we determine all the available channels.
             zo_callLater(DoLoginJoins, 1500)
+
             VoiceChatSetShouldDoLoginJoins(false)
         end
 
-        --Special case for handling the group being destroyed while zoning
+        --Special case for handling the group being destroyed while zoning.
         if not IsUnitGrouped("player") then
             local groupChannel = self.channelData[VOICE_CHANNEL_GROUP]
             self:ClearAndSwapChannel(groupChannel)
@@ -392,7 +421,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     end
 
     local function OnSelfJoinedGuild(guildServerId, displayName, guildId)
-        --We should only autojoin the guild channel if we're not already in a Group or Guild channel
+        --We should only automatically join this guild's channel if we're not already in a group or guild channel
         local desiredActiveChannel = self.desiredActiveChannel
         if desiredActiveChannel then
             local channelType = desiredActiveChannel.channelType
@@ -408,19 +437,21 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
             end
         end
 
-        --Set the channel, or wait on the VOIP event to initialize it
+        --We'll get this guild join event and the corresponding channel available event in a nondeterminite order. Only join it when it's ready.
         local adHocChannelData = {channelType = VOICE_CHANNEL_GUILD, guildId = guildId, guildRoomNumber = 1} --just choose the first non-officer guild room to join
         if self:DoesChannelExist(adHocChannelData) then
+            --The channel is initialized, so join it
             local channel = self:GetChannel(adHocChannelData)
             self:SetAndSwapDesiredActiveChannel(channel)
         else
+            --The channel isn't initialized yet, so flag to join it once it is
             self.autoJoiningGuildButNotAvailable = true
         end
     end
 
     local function OnSelfLeftGuild(guildServerId, displayName, guildId)
         if self.desiredActiveChannel and self.desiredActiveChannel.guildId == guildId then
-            self:GuildChangeSwapActive()
+            SwapOnLosingActiveGuildChannel()
         elseif self.desiredPassiveChannel and self.desiredPassiveChannel.guildId == guildId then
             self:SetDesiredPassiveChannel(nil)
         end
@@ -431,6 +462,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     end
 
     local function OnGuildRankChanged(guildId, rankIndex)
+        --We can lose permission to access a channel while in it. Leave the channel when this occurs.
         local desiredActiveChannel = self.desiredActiveChannel
         local desiredPassiveChannel = self.desiredPassiveChannel
 
@@ -438,18 +470,18 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
         local hasOfficerPermission = DoesPlayerHaveGuildPermission(guildId, GUILD_PERMISSION_OFFICER_CHAT_WRITE)
 
         if desiredActiveChannel and desiredActiveChannel.guildId == guildId then
-            if desiredActiveChannel.guildRoomNumber == OFFICERS_ROOM_NUMBER then
+            if desiredActiveChannel.guildRoomNumber == VOICE_CHAT_OFFICERS_ROOM_NUMBER then
                 if not hasOfficerPermission then
-                    self:GuildChangeSwapActive()
+                    SwapOnLosingActiveGuildChannel()
                 end
             else
                 if not hasRoomPermission then
-                    self:GuildChangeSwapActive()
+                    SwapOnLosingActiveGuildChannel()
                 end
             end
 
         elseif desiredPassiveChannel and desiredPassiveChannel.guildId == guildId then
-            if desiredPassiveChannel.guildRoomNumber == OFFICERS_ROOM_NUMBER then
+            if desiredPassiveChannel.guildRoomNumber == VOICE_CHAT_OFFICERS_ROOM_NUMBER then
                 if not hasOfficerPermission then
                     self:SetDesiredPassiveChannel(nil)
                 end
@@ -462,7 +494,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     end
 
     local function OnGuildMemberRankChanged(guildId, displayName, rankIndex)
-        if IsNameLocalPlayer(displayName) then
+        if ZO_VoiceChat_IsNameLocalPlayers(displayName) then
             OnGuildRankChanged(guildId, rankIndex)
         end
     end
@@ -470,11 +502,9 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     --Voice Channel Event Handlers
     local function OnVoiceChannelJoined(channelName)
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
-
         if not self:DoesChannelExist(channelData) then
             return
         end
-
         local channel = self:GetChannel(channelData)
 
         channel.isJoined = true
@@ -490,7 +520,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     local function OnVoiceChannelLeft(channelName)
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
         
-        --Handle special case where the guild is unavailable
+        --The guild id in the channel data is invalid for this event, so use the cache
         if channelData.channelType == VOICE_CHANNEL_GUILD then
             channelData.guildId = self.guildChannelsToIds[channelName]
 
@@ -504,8 +534,8 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
         channel.isJoined = false
         channel.isTransmitting = false
 
-        self:TryClearPassiveChannel(channel)
-        self:TryClearActiveChannel(channel)
+        TryClearPassiveChannel(channel)
+        TryClearActiveChannel(channel)
 
         self:FireCallbacks("ChannelsUpdate")
         self:FireCallbacks("ParticipantsUpdate")
@@ -515,7 +545,8 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
         local channelType = channelData.channelType
 
-        --Ignore invalid channels
+        --Ignore invalid channels. Probably not necessary anymore, but it was a quick fix to an
+        --early problem where the engine could send us invalid availability events.
         if channelType == VOICE_CHANNEL_NONE then
             return
         end
@@ -527,6 +558,8 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
 
             self.guildIdsDirty = true
 
+            --Check if we tried to join the channel from the guild join event, but needed to wait
+            --for this channel available event.
             if self.autoJoiningGuildButNotAvailable then
                 self.autoJoiningGuildButNotAvailable = nil
                 self:SetAndSwapDesiredActiveChannel(self:GetChannel(channelData))
@@ -557,7 +590,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     local function OnVoiceChannelUnavailable(channelName)
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
 
-        --Handle special case where the guild is unavailable
+        --The guild id in the channel data is invalid for this event, so use the cache
         if channelData.channelType == VOICE_CHANNEL_GUILD then
             channelData.guildId = self.guildChannelsToIds[channelName]
 
@@ -571,12 +604,11 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
         channel.isJoined = false
         channel.isTransmitting = false
 
-        self:TryClearPassiveChannel(channel)
-        self:TryClearActiveChannel(channel)
+        TryClearPassiveChannel(channel)
+        TryClearActiveChannel(channel)
         
         if channel.channelType == VOICE_CHANNEL_GUILD then
             self:RemoveGuildChannelRoom(channel.channelName, channel.guildId, channel.guildRoomNumber)
-
             self.guildIdsDirty = true
         end
 
@@ -585,22 +617,23 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
 
     local function OnVoiceTransmitChannelChanged(channelName)
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
-
         if not self:DoesChannelExist(channelData) then
             return
         end
-
         local channel = self:GetChannel(channelData)
 
         channel.isTransmitting = true
         
+        --Mark the old active channel as passive
         if self.activeChannel then
             self.activeChannel.isTransmitting = false
             self.passiveChannel = self.activeChannel
         end
+
         self.activeChannel = channel
 
-        self:TryClearPassiveChannel(channel)
+        --If this was our passive channel, then we don't have a passive channel anymore since it's now active
+        TryClearPassiveChannel(channel)
 
         self:FireCallbacks("ChannelsUpdate")
     end
@@ -608,18 +641,14 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     --Voice Participant Event Handlers
     local function OnVoiceUserJoinedChannel(channelName, displayName, characterName, isSpeaking)
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
-
         if not self:DoesChannelExist(channelData) then
             return
         end
-
         local channel = self:GetChannel(channelData)
-        local participantData = self:GetParticipantData(channel)
 
         local speakStatus = isSpeaking and VOICE_CHAT_SPEAK_STATE_SPEAKING or VOICE_CHAT_SPEAK_STATE_IDLE
-        local isMuted = self.muteCache[displayName]
-
-        participantData:AddParticipant(displayName, speakStatus, isMuted)
+        local isMuted = self.mutedUsers[displayName]
+        self:GetParticipantData(channel):AddOrUpdateParticipant(displayName, speakStatus, isMuted)
 
         self:FireCallbacks("ParticipantsUpdate")
     end
@@ -627,7 +656,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
     local function OnVoiceUserLeftChannel(channelName, displayName)
         local channelData = ZO_VoiceChat_GetChannelDataFromName(channelName)
         
-        --Handle special case where the guild is unavailable
+        --The guild id in the channel data is invalid for this event, so use the cache
         if channelData.channelType == VOICE_CHANNEL_GUILD then
             channelData.guildId = self.guildChannelsToIds[channelName]
 
@@ -656,7 +685,7 @@ function ZO_VoiceChat_Manager:RegisterForEvents()
         self:GetParticipantData(channel):UpdateParticipantStatus(displayName, speakStatus, nil)
 
         --Update history
-        if speaking and not IsNameLocalPlayer(displayName) then
+        if speaking and not ZO_VoiceChat_IsNameLocalPlayers(displayName) then
             channel.historyData:UpdateUser(displayName)
         end
 
@@ -702,6 +731,8 @@ end
 
 function ZO_VoiceChat_Manager:TransmitChannel(channel, skipDelay)
     VoiceChatChannelTransmit(channel.channelName)
+
+    --We can skip the delay if we're trying to transmit on a channel already joined (the passive channel)
     if not skipDelay then
         self:StartRequestDelay()
     end
@@ -713,12 +744,12 @@ function ZO_VoiceChat_Manager:LeaveChannel(channel)
 end
 
 function ZO_VoiceChat_Manager:UpdateMutes()
-    local muteMap = {}
+    local mutedUsers = {}
 
     local numMutedUsers = VoiceChatGetNumberMutedPlayers()
     for i = 1, numMutedUsers do
         local displayName = VoiceChatGetMutedPlayerDisplayName(i)
-        muteMap[displayName] = true
+        mutedUsers[displayName] = true
     end
 
     --Update participant data
@@ -726,11 +757,11 @@ function ZO_VoiceChat_Manager:UpdateMutes()
         if channelType == VOICE_CHANNEL_GUILD then
             for _, guildData in pairs(participantData) do
                 for _, roomData in pairs(guildData) do
-                    roomData:UpdateMutes(muteMap)
+                    roomData:UpdateMutes(mutedUsers)
                 end
             end
         else
-            participantData:UpdateMutes(muteMap)
+            participantData:UpdateMutes(mutedUsers)
         end
     end
 
@@ -739,33 +770,39 @@ function ZO_VoiceChat_Manager:UpdateMutes()
         if channelType == VOICE_CHANNEL_GUILD then
             for _, guildData in pairs(channelData) do
                 for _, roomData in pairs(guildData.rooms) do
-                    roomData.historyData:UpdateMutes(muteMap)
+                    roomData.historyData:UpdateMutes(mutedUsers)
                 end
             end
         else
-            channelData.historyData:UpdateMutes(muteMap)
+            channelData.historyData:UpdateMutes(mutedUsers)
         end
     end
 
-    self.muteCache = muteMap
+    self.mutedUsers = mutedUsers
 end
 
 function ZO_VoiceChat_Manager:OnUpdate()
-    if not self:AreRequestsAllowed() then
-        return
-    end
-
     if self.guildIdsDirty then
         self.guildIdsDirty = false
         self:RefreshGuildChannelIds()
     end
 
+    --The desired channels are the ones the user selects from the UI, or that are automatically
+    --set due to specific events occurring (ex. joining a group). The update loop will work
+    --towards joining and transmitting on the desired channels while leaving the old ones.
+    --It will work with the delay restriction we have between making requests, and will only allow
+    --a second channel to be joined if one of them is Area (by design).
+
+    if not self:AreRequestsAllowed() then
+        return
+    end
+
     local activeChannel = self.activeChannel
     local desiredActiveChannel = self.desiredActiveChannel
     local passiveChannel = self.passiveChannel
     local desiredPassiveChannel = self.desiredPassiveChannel
 
-    --Handle Active channel
+    --Update Active channel
     if not desiredActiveChannel then
         if activeChannel then
             self:LeaveChannel(activeChannel)
@@ -773,8 +810,7 @@ function ZO_VoiceChat_Manager:OnUpdate()
         end
     elseif desiredActiveChannel.isAvailable and desiredActiveChannel ~= activeChannel then
         --Enforce not being able to be active and passive in two non-Area channels
-        if desiredActiveChannel.channelType ~= VOICE_CHANNEL_AREA then
-            if desiredActiveChannel ~= passiveChannel then
+        if desiredActiveChannel ~= passiveChannel and desiredActiveChannel.channelType ~= VOICE_CHANNEL_AREA then
             if activeChannel and activeChannel.channelType ~= VOICE_CHANNEL_AREA then
                 self:LeaveChannel(activeChannel)
                 return
@@ -783,14 +819,13 @@ function ZO_VoiceChat_Manager:OnUpdate()
                 return
             end
         end
-        end
 
-        local skipDelay = desiredActiveChannel == passiveChannel
+        local skipDelay = desiredActiveChannel == passiveChannel --we don't need to delay the next request if we're already joined to the channel
         self:TransmitChannel(desiredActiveChannel, skipDelay)
         return
     end
 
-    --Handle Passive channel
+    --Update Passive channel
     if not desiredPassiveChannel then
         if passiveChannel then
             self:LeaveChannel(passiveChannel)
@@ -823,7 +858,7 @@ function ZO_VoiceChat_Manager:AddGuildChannelRoom(channelName, guildId, guildRoo
 
     local name
     local description
-    if guildRoomNumber == 0 then
+    if guildRoomNumber == VOICE_CHAT_OFFICERS_ROOM_NUMBER then
         name = GetString(SI_GAMEPAD_VOICECHAT_ROOM_NAME_OFFICERS)
         description = GetString(SI_GAMEPAD_VOICECHAT_CHANNEL_DESCRIPTION_GUILD_OFFICERS)
     else
@@ -852,9 +887,11 @@ function ZO_VoiceChat_Manager:RemoveGuildChannelRoom(channelName, guildId, guild
     local guildData = guildChannels[guildId]
 
     if guildData then
+        --Destroy the room
         guildData.rooms[guildRoomNumber] = nil
         self.participantsData[VOICE_CHANNEL_GUILD][guildId][guildRoomNumber] = nil
 
+        --Destroy the guild entry
         if NonContiguousCount(guildData.rooms) == 0 then
             guildChannels[guildId] = nil
             self.participantsData[VOICE_CHANNEL_GUILD][guildId] = nil
@@ -869,18 +906,18 @@ function ZO_VoiceChat_Manager:RefreshGuildChannelIds()
     local guildParticipants = self.participantsData[VOICE_CHANNEL_GUILD]
 
     local remappedGuildChannels = {}
-    for guildId, guildData in pairs(guildChannels) do
+    for oldGuildId, guildData in pairs(guildChannels) do
         local newGuildId
-        for guildRoomNumber, roomData in pairs(guildData.rooms) do
+        for roomNumber, roomData in pairs(guildData.rooms) do
             newGuildId = newGuildId or select(2, VoiceChatGetChannelInfo(roomData.channelName))
             roomData.guildId = newGuildId
             self.guildChannelsToIds[roomData.channelName] = newGuildId
         end
 
-        remappedGuildChannels[newGuildId] = guildChannels[guildId]
-        if guildId ~= newGuildId then
-            guildParticipants[newGuildId] = guildParticipants[guildId]
-            guildParticipants[guildId] = nil
+        remappedGuildChannels[newGuildId] = guildChannels[oldGuildId]
+        if oldGuildId ~= newGuildId then
+            guildParticipants[newGuildId] = guildParticipants[oldGuildId]
+            guildParticipants[oldGuildId] = nil
         end
     end
 
@@ -916,16 +953,18 @@ end
 function ZO_VoiceChat_Manager:SetDesiredPassiveChannel(channel)
     self.desiredPassiveChannel = channel
 
+    --Update saved settings
     if channel then
         self.savedVars.desiredPassiveChannel = {
             channelType = channel.channelType,
-            guildName = channel.guildName,
+            guildName = channel.guildName, --we have to use the name and not the id since the id changes
             guildRoomNumber = channel.guildRoomNumber,
         }
     else
         self.savedVars.desiredPassiveChannel = {}
     end
     
+    --The desired channels are often changed in pairs. Delay to prevent double-saving.
     self.saveSettingsCount = self.saveSettingsCount + 1
     zo_callLater(self.saveSettingsFunction, SAVE_SETTINGS_DELAY)
 end
@@ -933,42 +972,22 @@ end
 function ZO_VoiceChat_Manager:SetDesiredActiveChannel(channel)
     self.desiredActiveChannel = channel
 
+    --Update saved settings
     if channel then
         self.savedVars.desiredActiveChannel = {
             channelType = channel.channelType,
-            guildName = channel.guildName,
+            guildName = channel.guildName, --we have to use the name and not the id since the id changes
             guildRoomNumber = channel.guildRoomNumber,
         }
     else
         self.savedVars.desiredActiveChannel = {}
     end
     
+    --The desired channels are often changed in pairs. Delay to prevent double-saving.
     self.saveSettingsCount = self.saveSettingsCount + 1
     zo_callLater(self.saveSettingsFunction, SAVE_SETTINGS_DELAY)
 end
 
-function ZO_VoiceChat_Manager:GuildChangeSwapActive()
-    local groupChannel = self.channelData[VOICE_CHANNEL_GROUP]
-    if groupChannel.isAvailable then
-        self:SetDesiredActiveChannel(groupChannel)
-    else
-        self:SetDesiredActiveChannel(self.desiredPassiveChannel)
-        self:SetDesiredPassiveChannel(nil)
-    end
-end
-
-function ZO_VoiceChat_Manager:TryClearPassiveChannel(channel)
-    if self.passiveChannel == channel then
-        self.passiveChannel = nil
-    end
-end
-
-function ZO_VoiceChat_Manager:TryClearActiveChannel(channel)
-    if self.activeChannel == channel then
-        self.activeChannel = nil
-    end
-end
-
 
 --Intended Public Functions
 function ZO_VoiceChat_Manager:GetChannel(channelData)
@@ -1045,22 +1064,23 @@ function ZO_VoiceChat_Manager:ClearAndSwapChannel(channel)
     end
 end
 
-function ZO_VoiceChat_Manager:SetAndSwapDesiredActiveChannel(channel)
-    if self.desiredActiveChannel == channel then
+function ZO_VoiceChat_Manager:SetAndSwapDesiredActiveChannel(desiredActiveChannel)
+    local previousDesiredActiveChannel = self.desiredActiveChannel
+
+    --Check if it's already active
+    if desiredActiveChannel == previousDesiredActiveChannel then
         return
     end
 
-    if channel.channelType == VOICE_CHANNEL_AREA then
-        self:SetDesiredPassiveChannel(self.desiredActiveChannel)
-    else
-        local areaChannel = self.channelData[VOICE_CHANNEL_AREA]
-        local desiredActiveChannel = self.desiredActiveChannel
-        if desiredActiveChannel == areaChannel then
-            self:SetDesiredPassiveChannel(desiredActiveChannel)
-        end
+    --Determine if the previous active channel should be made passive rather than
+    --leaving it. This is to follow the design of only allowing two joined channels
+    --when one is Area.
+    -- it's possible that the we hadn't set a previous active channel (for one if we don't have a VOIP server to connect to)
+    if desiredActiveChannel.channelType == VOICE_CHANNEL_AREA or (previousDesiredActiveChannel ~= nil and previousDesiredActiveChannel.channelType == VOICE_CHANNEL_AREA) then
+        self:SetDesiredPassiveChannel(previousDesiredActiveChannel)
     end
 
-    self:SetDesiredActiveChannel(channel)
+    self:SetDesiredActiveChannel(desiredActiveChannel)
 end
 
 function ZO_VoiceChat_Manager:GetDesiredActiveChannelType()