Quantcast

Merge branch 'master' into mop

F16Gaming [08-14-12 - 09:28]
Merge branch 'master' into mop

Conflicts:
	Events.lua (RESOLVED)
Filename
Command.lua
CommandManager.lua
DuelManager.lua
Events.lua
InviteManager.lua
load.xml
locales/enUS.lua
locales/svSE.lua
diff --git a/Command.lua b/Command.lua
index f3a92a7..6ae5665 100644
--- a/Command.lua
+++ b/Command.lua
@@ -37,10 +37,10 @@ local assert = assert
 Command = {
 	Name = "Command",
 	Version = GetAddOnMetadata("Command", "Version"),
-	VersionNum = 8, -- Increment on every release
+	VersionNum = 9, -- Increment on every release
 	VersionChecked = false, -- Prevent spam of "New Version" notice
 	Loaded = false,
-	VarVersion = 2,
+	VarVersion = 3,
 	Global = {},
 	Settings = {},
 	Events = {},
@@ -56,6 +56,8 @@ local RM
 local AC
 local DM
 local SM
+local IM
+local CDM
 local log

 --- Initialize Command.
@@ -72,6 +74,8 @@ function C:Init()
 	AC = self.AddonComm
 	DM = self.DeathManager
 	SM = self.SummonManager
+	IM = self.InviteManager
+	CDM = self.DuelManager
 	log = self.Logger
 	self:LoadSavedVars()
 	log:Normal(L("ADDON_LOAD"))
@@ -86,12 +90,13 @@ function C:LoadSavedVars()
 		_G["COMMAND"] = {}
 	elseif type(_G["COMMAND"]["VERSION"]) == "number" then
 		if _G["COMMAND"]["VERSION"] < self.VarVersion then
-			log:Normal(L("SVARS_OUTDATED"))
 			wipe(_G["COMMAND"])
 			_G["COMMAND"] = {}
 		end
 	end
+
 	self.Global = _G["COMMAND"]
+
 	if type(self.Global.SETTINGS) ~= "table" then
 		self.Global.SETTINGS = {}
 	end
@@ -102,12 +107,7 @@ function C:LoadSavedVars()
 	if type(self.Settings.ENABLED) ~= "bolean" then
 		self.Settings.ENABLED = true
 	end
-	if type(self.Settings.GROUP_INVITE_ANNOUNCE) ~= "boolean" then
-		self.Settings.GROUP_INVITE_ANNOUNCE = false
-	end
-	if type(self.Settings.GROUP_INVITE_ANNOUNCE_DELAY) ~= "number" then
-		self.Settings.GROUP_INVITE_ANNOUNCE_DELAY = 0
-	end
+
 	L:Init()
 	CM:Init()
 	PM:Init()
@@ -115,6 +115,8 @@ function C:LoadSavedVars()
 	AC:Init()
 	DM:Init()
 	SM:Init()
+	IM:Init()
+	CDM:Init()
 	Cmd:Init()
 	log:SetDebug(self.Settings.DEBUG)
 	self.Global.VERSION = self.VarVersion
@@ -189,42 +191,3 @@ end
 function C:ToggleDebug()
 	return self:SetDebug(not self.Settings.DEBUG)
 end
-
-function C:SetGroupInvite(enabled)
-	self.Settings.GROUP_INVITE_ANNOUNCE = enabled
-	if self.Settings.GROUP_INVITE_ANNOUNCE then
-		return "GI_ENABLED"
-	end
-	return "GI_DISABLED"
-end
-
-function C:EnableGroupInvite()
-	return self:SetGroupInvite(true)
-end
-
-function C:DisableGroupInvite()
-	return self:SetGroupInvite(false)
-end
-
-function C:ToggleGroupInvite()
-	return self:SetGroupInvite(not self.Settings.GROUP_INVITE_ANNOUNCE)
-end
-
-function C:SetGroupInviteDelay(time)
-	if type(time) ~= "number" then
-		return false, "GI_DELAY_NUM"
-	end
-	time = math.ceil(time)
-	if time > 50 then
-		return false, "GI_DELAY_MAX"
-	end
-	self.Settings.GROUP_INVITE_ANNOUNCE_DELAY = time
-	if self.Settings.GROUP_INVITE_ANNOUNCE_DELAY > 0 then
-		return "GI_DELAY_SET", {self.Settings.GROUP_INVITE_ANNOUNCE_DELAY}
-	end
-	return "GI_DELAY_DISABLED"
-end
-
-function C:DisableGroupInviteDelay()
-	return self:SetGroupInviteDelay(0)
-end
diff --git a/CommandManager.lua b/CommandManager.lua
index 92fb740..8ce386f 100644
--- a/CommandManager.lua
+++ b/CommandManager.lua
@@ -68,6 +68,8 @@ local GT = C.GroupTools
 local AM = C.AuthManager
 local DM = C.DeathManager
 local SM = C.SummonManager
+local IM = C.InviteManager
+local CDM = C.DuelManager
 local Chat
 local CES = C.Extensions.String
 local CET = C.Extensions.Table
@@ -245,21 +247,7 @@ CM:Register({"set", "s"}, PM.Access.Groups.Admin.Level, function(args, sender, i
 			return false, "CM_ERR_NOCMDCHAR"
 		end
 		return Chat:SetCmdChar(args[2])
-	elseif mod:match("^g") then -- Group invite (announce)
-		if #args < 2 then
-			return false, "CM_SET_GROUPINVITE_USAGE"
-		end
-		args[2] = args[2]:lower()
-		local delay = tonumber(args[2])
-		if delay then
-			return C:SetGroupInviteDelay(delay)
-		elseif args[2]:match("^[eay]") then -- Enable
-			return C:EnableGroupInvite()
-		elseif args[2]:match("^[dn]") then -- Disable
-			return C:DisableGroupInvite()
-		end
-		return false, "CM_SET_GROUPINVITE_USAGE"
-	elseif mod:match("^d") then -- DeathManager
+	elseif mod:match("^de") then -- DeathManager
 		if #args < 2 then
 			if C.DeathManager:IsEnabled() then
 				return "CM_SET_DM_ISENABLED"
@@ -316,6 +304,103 @@ CM:Register({"set", "s"}, PM.Access.Groups.Admin.Level, function(args, sender, i
 			return SM:SetDelay(newDelay)
 		end
 		return false, "CM_SET_SM_USAGE"
+	elseif mod:match("^i") then -- InviteManager
+		if #args < 2 then
+			if IM:IsEnabled() then
+				return "CM_SET_IM_ISENABLED"
+			end
+			return "CM_SET_IM_ISDISABLED"
+		end
+		if isChat then -- Players are only allowed to check status of InviteManager
+			return false, "CM_ERR_NOCHAT"
+		end
+		local setting = args[2]:lower()
+		if setting:match("^[eay]") then -- Enable
+			return IM:Enable()
+		elseif setting:match("^[dn]") then -- Disable
+			return IM:Disable()
+		elseif setting:match("^t") then -- Toggle
+			return IM:Toggle()
+		elseif setting:match("^gu.*d") or setting:match("¨gu.*s.*d") then -- Set Guild Delay
+			if #args < 3 then
+				return "CM_SET_IM_GUILD_DELAY_CURRENT", {IM:GetGuildDelay()}
+			end
+			local newDelay = tonumber(args[3])
+			if not newDelay then return false, "CM_SET_IM_GUILD_DELAY_USAGE" end
+			return IM:SetGuildDelay(newDelay)
+		elseif setting:match("^gu.*[dn].*d") then -- Disable Guild Delay
+			return IM:DisableGuildDelay()
+		elseif setting:match("^gu.*[eay].*a") then -- Enable Guild Announce
+			return IM:EnableGuildAnnounce()
+		elseif setting:match("^gu.*[dn].*a") then -- Disable Guild Announce
+			return IM:DisableGuildAnnounce()
+		elseif setting:match("^gu.*t.*a") then -- Toggle Guild Announce
+			return IM:ToggleGuildAnnounce()
+		elseif setting:match("^gu.*[eay].*o") then -- Enable Guild Override
+			return IM:EnableGuildOverride()
+		elseif setting:match("^gu.*[dn].*o") then -- Disable Guild Override
+			return IM:DisableGuildOverride()
+		elseif setting:match("^gu.*t.*o") then -- Toggle Guild Override
+			return IM:ToggleGuildOverride()
+		elseif setting:match("^gu.*[eay]") then -- Enable Guild
+			return IM:EnableGuild()
+		elseif setting:match("^gu.*[dn]") then -- Disable Guild
+			return IM:DisableGuild()
+		elseif setting:match("^gu.*t") then -- Toggle Guild
+			return IM:ToggleGuild()
+		elseif setting:match("^g.*d") or setting:match("^g.*s.*d") then -- Set Group Delay
+			if #args < 3 then
+				return "CM_SET_IM_GROUP_DELAY_CURRENT", {IM:GetGroupDelay()}
+			end
+			local newDelay = tonumber(args[3])
+			if not newDelay then return false, "CM_SET_IM_GROUP_DELAY_USAGE" end
+			return IM:SetGroupDelay(newDelay)
+		elseif setting:match("^g.*[dn].*d") then -- Disable Group Delay
+			return IM:DisableGroupDelay()
+		elseif setting:match("^g.*[eay].*a") then -- Enable Group Announce
+			return IM:EnableGroupAnnounce()
+		elseif setting:match("^g.*[dn].*a") then -- Disable Group Announce
+			return IM:DisableGroupAnnounce()
+		elseif setting:match("^g.*t.*a") then -- Toggle Group Announce
+			return IM:ToggleGroupAnnounce()
+		elseif setting:match("^g.*[eay]") then -- Enable Group
+			return IM:EnableGroup()
+		elseif setting:match("^g.*[dn]") then -- Disable Group
+			return IM:DisableGroup()
+		elseif setting:match("^g.*t") then -- Toggle Group
+			return IM:ToggleGroup()
+		end
+		return false, "CM_SET_IM_USAGE"
+	elseif mod:match("^d") then -- DuelManager
+		if #args < 2 then
+			if CDM:IsEnabled() then
+				return "CM_SET_CDM_ISENABLED"
+			end
+			return "CM_SET_CDM_ISDISABLED"
+		end
+		if isChat then -- Players are only allowed to check status of DuelManager
+			return false, "CM_ERR_NOCHAT"
+		end
+		local setting = args[2]:lower()
+		if setting:match("^[eay].*a") then -- Enable Announce
+			return CDM:EnableAnnounce()
+		elseif setting:match("^[dn].*a") then -- Disable Announce
+			return CDM:DisableAnnounce()
+		elseif setting:match("^a.*t") then -- Toggle Announce
+			return CDM:ToggleAnnounce()
+		elseif setting:match("^s.*d") or setting:match("^de") then -- Set Delay
+			if #args < 3 then
+				return "CM_SET_CDM_DELAY_CURRENT", {CDM:GetDelay()}
+			end
+			local newDelay = tonumber(args[3])
+			if not newDelay then return false, "CM_SET_CDM_DELAY_USAGE" end
+			return CDM:SetDelay(newDelay)
+		elseif setting:match("^[eay]") then -- Enable
+			return CDM:Enable()
+		elseif setting:match("^[dn]") then -- Disable
+			return CDM:Disable()
+		end
+		return false, "CM_SET_CDM_USAGE"
 	end
 	return false, "CM_SET_USAGE"
 end, "CM_SET_HELP")
@@ -481,15 +566,33 @@ CM:Register({"authme", "authenticateme", "am"}, PM.Access.Groups.User.Level, fun
 end, "CM_AUTHME_HELP")

 CM:Register({"accept", "acceptinvite", "acceptinv", "join", "joingroup"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
-	if not StaticPopup_Visible("PARTY_INVITE") then
-		return false, "CM_ACCEPTINVITE_NOTACTIVE"
-	elseif GT:IsInGroup() then
-		return false, "CM_ACCEPTINVITE_EXISTS" -- This shouldn't happen
+	if not IM:IsEnabled() or not IM:IsGroupEnabled() then
+		return "CM_ERR_DISABLED"
 	end
-	AcceptGroup()
-	return "CM_ACCEPTINVITE_SUCCESS"
+	return IM:AcceptGroupInvite()
 end, "CM_ACCEPTINVITE_HELP")

+CM:Register({"decline", "declineinvite", "declineinv", "cancelinvite", "cancelinv"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+	if not IM:IsEnabled() or not IM:IsGroupEnabled() then
+		return "CM_ERR_DISABLED"
+	end
+	return IM:DeclineGroupInvite()
+end, "CM_DECLINEINVITE_HELP")
+
+CM:Register({"acceptguildinvite", "acceptginvite", "acceptguildinv", "acceptginv"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+	if not IM:IsEnabled() or not IM:IsGuildEnabled() then
+		return "CM_ERR_DISABLED"
+	end
+	return IM:AcceptGuildInvite()
+end, "CM_ACCEPTGUILDINVITE_HELP")
+
+CM:Register({"declineguildinvite", "declineginvite", "declineguildinv", "declineginv"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+	if not IM:IsEnabled() or not IM:IsGuildEnabled() then
+		return "CM_ERR_DISABLED"
+	end
+	return IM:DeclineGuildInvite()
+end, "CM_DECLINEGUILDINVITE_HELP")
+
 CM:Register({"invite", "inv"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
 	if type(args[1]) == "string" then
 		local player = PM:GetOrCreatePlayer(args[1])
@@ -962,6 +1065,30 @@ CM:Register({"declinesummon", "ds", "declinesumm", "dsumm", "cancelsummon", "csu
 	return SM:DeclineSummon()
 end, "CM_DECLINESUMMON_HELP")

+CM:Register({"acceptduel", "acceptd"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+	if not CDM:IsEnabled() then
+		return false, "CM_ERR_DISABLED"
+	end
+	return CDM:AcceptDuel()
+end, "CM_ACCEPTDUEL_HELP")
+
+CM:Register({"declineduel", "declined"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+	if not CDM:IsEnabled() then
+		return false, "CM_ERR_DISABLED"
+	end
+	return CDM:DeclineDuel()
+end, "CM_DECLINEDUEL_HELP")
+
+CM:Register({"startduel", "startd", "challenge"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+	if not CDM:IsEnabled() then
+		return false, "CM_ERR_DISABLED"
+	end
+	if #args < 1 then
+		return false, "CM_STARTDUEL_USAGE"
+	end
+	return CDM:Challenge(args[1])
+end, "CM_STARTDUEL_HELP")
+
 for i,v in ipairs(CM.Slash) do
 	_G["SLASH_" .. C.Name:upper() .. i] = "/" .. v
 end
diff --git a/DuelManager.lua b/DuelManager.lua
new file mode 100644
index 0000000..374c531
--- /dev/null
+++ b/DuelManager.lua
@@ -0,0 +1,201 @@
+--[[
+	* Copyright (c) 2011-2012 by Adam Hellberg.
+	*
+	* This file is part of Command.
+	*
+	* Command is free software: you can redistribute it and/or modify
+	* it under the terms of the GNU General Public License as published by
+	* the Free Software Foundation, either version 3 of the License, or
+	* (at your option) any later version.
+	*
+	* Command is distributed in the hope that it will be useful,
+	* but WITHOUT ANY WARRANTY; without even the implied warranty of
+	* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	* GNU General Public License for more details.
+	*
+	* You should have received a copy of the GNU General Public License
+	* along with Command. If not, see <http://www.gnu.org/licenses/>.
+--]]
+
+-- Upvalues
+local type = type
+local ceil = math.ceil
+
+-- API Upvalues
+local StartDuel = StartDuel
+local AcceptDuel = AcceptDuel
+local CancelDuel = CancelDuel
+local CreateFrame = CreateFrame
+local StaticPopup_Hide = StaticPopup_Hide
+local StaticPopup_Visible = StaticPopup_Visible
+
+local C = Command
+
+C.DuelManager = {}
+
+local L = C.LocaleManager
+local DM = C.DuelManager
+local PM
+local CM
+
+local DEFAULT_DELAY = 5
+
+local MAX_DELAY = 50
+
+function DM:Init()
+	PM = C.PlayerManager
+	CM = C.ChatManager
+	self:LoadSavedVars()
+end
+
+function DM:LoadSavedVars()
+	if type(C.Global["DUEL_MANAGER"]) ~= "table" then
+		C.Global["DUEL_MANAGER"] = {}
+	end
+
+	self.Settings = C.Global["DUEL_MANAGER"]
+
+	if type(self.Settings.ENABLED) ~= "boolean" then
+		self.Settings.ENABLED = true
+	end
+	if type(self.Settings.ANNOUNCE) ~= "boolean" then
+		self.Settings.ANNOUNCE = true
+	end
+	if type(self.Settings.DELAY) ~= "number" then
+		self.Settings.DELAY = DEFAULT_DELAY
+	end
+end
+
+function DM:OnDuel(sender)
+	if self.Settings.DELAY > 0 then
+		local frame = CreateFrame("Frame")
+		frame.Time = 0
+		frame.Delay = self.Settings.DELAY
+		frame.Sender = sender
+		frame:SetScript("OnUpdate", function(self, elapsed)
+			self.Time = self.Time + elapsed
+			if self.Time >= self.Delay then
+				self:SetScript("OnUpdate", nil)
+				DM:Announce(self.Sender)
+			end
+		end)
+	else
+		self:Announce(sender)
+	end
+end
+
+function DM:Announce(sender)
+	if not self:HasDuel() then return end
+	local locale = PM:GetOrCreatePlayer(sender).Settings.locale
+	local msg = L(locale, "CDM_ANNOUNCE", true)
+	CM:SendMessage(msg, "WHISPER", sender)
+end
+
+function DM:AcceptDuel()
+	if not self:HasDuel() then
+		return false, "CDM_ERR_NODUEL"
+	end
+
+	AcceptDuel()
+
+	if StaticPopup_Visible("DUEL_REQUESTED") then
+		StaticPopup_Hide("DUEL_REQUESTED")
+	end
+
+	return "CDM_ACCEPTED"
+end
+
+function DM:DeclineDuel()
+	if not DM:HasDuel() then
+		return self:CancelDuel()
+	end
+
+	CancelDuel()
+
+	if StaticPopup_Visible("DUEL_REQUESTED") then
+		StaticPopup_Hide("DUEL_REQUESTED")
+	end
+
+	return "CDM_DECLINED"
+end
+
+function DM:CancelDuel()
+	CancelDuel()
+
+	return "CDM_CANCELLED"
+end
+
+function DM:Challenge(target)
+	StartDuel(target)
+
+	return "CDM_CHALLENGED", {target}
+end
+
+function DM:HasDuel()
+	return StaticPopup_Visible("DUEL_REQUESTED")
+end
+
+function DM:Enable()
+	self.Settings.ENABLED = true
+	return "CDM_ENABLED"
+end
+
+function DM:Disable()
+	self.Settings.ENABLED = false
+	return "CDM_DISABLED"
+end
+
+function DM:Toggle()
+	if self:IsEnabled() then
+		return self:Disable()
+	end
+	return self:Enable()
+end
+
+function DM:IsEnabled()
+	return self.Settings.ENABLED
+end
+
+function DM:EnableAnnounce()
+	self.Settings.ANNOUNCE = true
+	return "CDM_ANNOUNCE_ENABLED"
+end
+
+function DM:DisableAnnounce()
+	self.Settings.ANNOUNCE = false
+	return "CDM_ANNOUNCE_DISABLED"
+end
+
+function DM:ToggleAnnounce()
+	if self:IsAnnounceEnabled() then
+		return self:DisableAnnounce()
+	end
+	return self:EnableAnnounce()
+end
+
+function DM:IsAnnounceEnabled()
+	return self.Settings.ANNOUNCE
+end
+
+function DM:SetDelay(delay)
+	if type(delay) ~= "number" then
+		return false, "CDM_DELAY_NUM"
+	end
+	delay = ceil(delay)
+	if delay < 0 or delay > MAX_DELAY then
+		return false, "CDM_DELAY_OUTOFRANGE", {MAX_DELAY}
+	end
+	self.Settings.DELAY = delay
+	if self.Settings.DELAY > 0 then
+		return "CDM_DELAY_SET", {self.Settings.DELAY}
+	end
+	return "CDM_DELAY_DISABLED"
+end
+
+function DM:GetDelay()
+	return self.Settings.DELAY
+end
+
+function DM:DisableDelay()
+	return DM:SetDelay(0)
+end
diff --git a/Events.lua b/Events.lua
index 53ce87f..8e105d0 100644
--- a/Events.lua
+++ b/Events.lua
@@ -35,6 +35,8 @@ local QM = C.QueueManager
 local AC = C.AddonComm
 local DM = C.DeathManager
 local SM = C.SummonManager
+local IM = C.InviteManager
+local CDM = C.DuelManager

 --- Event handler for ADDON_LOADED
 -- @name Command.Events.ADDON_LOADED
@@ -100,28 +102,15 @@ function C.Events.GROUP_ROSTER_UPDATE(self, ...)
 end

 function C.Events.PARTY_INVITE_REQUEST(self, ...)
-	if not self.Settings.GROUP_INVITE_ANNOUNCE then return end
+	if not IM.Settings.GROUP.ANNOUNCE then return end
 	local sender = (select(1, ...))
-	local locale = C.PlayerManager:GetOrCreatePlayer(sender).Settings.Locale
-	local msg = C.LocaleManager:GetLocale(locale, true)["E_GROUPINVITE"]
-	if self.Settings.GROUP_INVITE_ANNOUNCE_DELAY > 0 then
-		local f=CreateFrame("Frame") -- Create temporary frame
-		f.Time = 0 -- Current time
-		f.Delay = self.Settings.GROUP_INVITE_ANNOUNCE_DELAY -- Delay to wait
-		f.Sender = sender -- Name of player who sent invite
-		f.Message = msg -- Message to send
-		f:SetScript("OnUpdate", function(self, elapsed) -- The update script to delay sending of message
-			self.Time = self.Time + elapsed
-			if self.Time > self.Delay then
-				self:SetScript("OnUpdate", nil)
-				if StaticPopup_Visible("PARTY_INVITE") then -- Only send message if the invite popup is still showing
-					CM:SendMessage(self.Message, "WHISPER", self.Sender) -- Send the message!
-				end
-			end
-		end)
-	else
-		CM:SendMessage(msg, "WHISPER", sender)
-	end
+	IM:OnGroupInvite(sender)
+end
+
+function C.Events.GUILD_INVITE_REQUEST(self, ...)
+	if not IM.Settings.GUILD.ANNOUNCE then return end
+	local sender = (select(1, ...))
+	IM:OnGuildInvite(sender)
 end

 function C.Events.PARTY_LEADER_CHANGED(self, ...)
@@ -162,3 +151,7 @@ end
 function C.Events.CONFIRM_SUMMON(self, ...)
 	SM:OnSummon()
 end
+
+function C.Events.DUEL_REQUESTED(self, ...)
+	CDM:OnDuel((select(1, ...)))
+end
diff --git a/InviteManager.lua b/InviteManager.lua
new file mode 100644
index 0000000..c725445
--- /dev/null
+++ b/InviteManager.lua
@@ -0,0 +1,435 @@
+--[[
+	* Copyright (c) 2011-2012 by Adam Hellberg.
+	*
+	* This file is part of Command.
+	*
+	* Command is free software: you can redistribute it and/or modify
+	* it under the terms of the GNU General Public License as published by
+	* the Free Software Foundation, either version 3 of the License, or
+	* (at your option) any later version.
+	*
+	* Command is distributed in the hope that it will be useful,
+	* but WITHOUT ANY WARRANTY; without even the implied warranty of
+	* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	* GNU General Public License for more details.
+	*
+	* You should have received a copy of the GNU General Public License
+	* along with Command. If not, see <http://www.gnu.org/licenses/>.
+--]]
+
+-- Upvalues
+local type = type
+local ceil = math.ceil
+
+-- API Upvalues
+local CreateFrame = CreateFrame
+local AcceptGroup = AcceptGroup
+local AcceptGuild = AcceptGuild
+local DeclineGroup = DeclineGroup
+local DeclineGuild = DeclineGuild
+local StaticPopup_Show = StaticPopup_Show
+local StaticPopup_Hide = StaticPopup_Hide
+local StaticPopup_Visible = StaticPopup_Visible
+local GetGuildFactionInfo = GetGuildFactionInfo
+
+local C = Command
+
+C.InviteManager = {
+	Dialogs = {
+		ConfirmGuildOverride = "COMMAND_GUILD_CONFIRM_OVERRIDE"
+	}
+}
+
+local L = C.LocaleManager
+local IM = C.InviteManager
+local GT = C.GroupTools
+local CM
+local PM
+local log = C.Logger
+
+local DEFAULT_GROUP_DELAY = 5
+local DEFAULT_GUILD_DELAY = 5
+
+local GROUP_MAX_DELAY = 50
+local GUILD_MAX_DELAY = 50
+
+-- Static Popup Dialogs
+StaticPopupDialogs[IM.Dialogs.ConfirmGuildOverride] = {
+	text = "IM_GUILD_CONFIRM_OVERRIDE_POPUP",
+	button1 = "YES",
+	button2 = "NO",
+	OnAccept = function() log:Normal(L(IM:EnableGuildOverride(true))) end,
+	OnCancel = function() log:Normal(L(IM:DisableGuildOverride())) end,
+	timeout = 20,
+	whileDead = true,
+	hideOnEscape = false
+}
+
+local function CloseGuildInvite()
+	local frame = CreateFrame("Frame")
+	frame.Time = 0
+	frame:SetScript("OnUpdate", function(self, elapsed)
+		self.Time = self.Time + elapsed
+		if self.Time >= 0.5 then
+			self:SetScript("OnUpdate", nil)
+			if GuildInviteFrame and GuildInviteFrame:IsShown() then
+				GuildInviteFrame:Hide()
+			end
+		end
+	end)
+end
+
+function IM:Init()
+	CM = C.ChatManager
+	PM = C.PlayerManager
+	self:LoadSavedVars()
+end
+
+function IM:LoadSavedVars()
+	if type(C.Global["INVITE_MANAGER"]) ~= "table" then
+		C.Global["INVITE_MANAGER"] = {}
+	end
+
+	self.Settings = C.Global["INVITE_MANAGER"]
+
+	if type(self.Settings.ENABLED) ~= "boolean" then
+		self.Settings.ENABLED = true
+	end
+
+	if type(self.Settings.GROUP) ~= "table" then
+		self.Settings.GROUP = {}
+	end
+	if type(self.Settings.GROUP.ENABLED) ~= "boolean" then
+		self.Settings.GROUP.ENABLED = true
+	end
+	if type(self.Settings.GROUP.ANNOUNCE) ~= "boolean" then
+		self.Settings.GROUP.ANNOUNCE = true
+	end
+	if type(self.Settings.GROUP.DELAY) ~= "number" then
+		self.Settings.GROUP.DELAY = DEFAULT_GROUP_DELAY
+	end
+
+	if type(self.Settings.GUILD) ~= "table" then
+		self.Settings.GUILD = {}
+	end
+	if type(self.Settings.GUILD.ENABLED) ~= "boolean" then
+		self.Settings.GUILD.ENABLED = true
+	end
+	if type(self.Settings.GUILD.ANNOUNCE) ~= "boolean" then
+		self.Settings.GUILD.ANNOUNCE = true
+	end
+	if type(self.Settings.GUILD.DELAY) ~= "number" then
+		self.Settings.GUILD.DELAY = DEFAULT_GUILD_DELAY
+	end
+	if type(self.Settings.GUILD.OVERRIDE) ~= "boolean" then
+		self.Settings.GUILD.OVERRIDE = false
+	end
+end
+
+function IM:OnGroupInvite(sender)
+	if self.Settings.GROUP.DELAY > 0 then
+		local frame = CreateFrame("Frame")
+		frame.Time = 0
+		frame.Delay = self.Settings.GROUP.DELAY
+		frame.Sender = sender
+		frame:SetScript("OnUpdate", function(self, elapsed)
+			self.Time = self.Time + elapsed
+			if self.Time >= self.Delay then
+				self:SetScript("OnUpdate", nil)
+				IM:AnnounceGroupInvite(self.Sender)
+			end
+		end)
+	else
+		self:AnnounceGroupInvite(sender)
+	end
+end
+
+function IM:OnGuildInvite(sender)
+	if self.Settings.GROUP.DELAY > 0 then
+		local frame = CreateFrame("Frame")
+		frame.Time = 0
+		frame.Delay = self.Settings.GUILD.DELAY
+		frame.Sender = sender
+		frame:SetScript("OnUpdate", function(self, elapsed)
+			self.Time = self.Time + elapsed
+			if self.Time >= self.Delay then
+				self:SetScript("OnUpdate", nil)
+				IM:AnnounceGuildInvite(self.Sender)
+			end
+		end)
+	else
+		self:AnnounceGuildInvite(sender)
+	end
+end
+
+function IM:AnnounceGroupInvite(sender)
+	if not self:HasGroupInvite() then return end
+	local locale = PM:GetOrCreatePlayer(sender).Settings.Locale
+	local msg = L(locale, "IM_GROUP_ANNOUNCE", true)
+	CM:SendMessage(msg, "WHISPER", sender)
+end
+
+function IM:AnnounceGuildInvite(sender)
+	if not self:HasGuildInvite() then return end
+	local locale = PM:GetOrCreatePlayer(sender).Settings.Locale
+	local msg = L(locale, "IM_GUILD_ANNOUNCE", true)
+	CM:SendMessage(msg, "WHISPER", sender)
+end
+
+function IM:AcceptGroupInvite()
+	if not self:HasGroupInvite() then
+		return false, "IM_GROUP_NOINVITE"
+	end
+
+	AcceptGroup()
+
+	if StaticPopup_Visible("PARTY_INVTIE") then
+		StaticPopup_Hide("PARTY_INVITE")
+	end
+
+	return "IM_GROUP_ACCEPTED"
+end
+
+function IM:DeclineGroupInvite()
+	if not self:HasGroupInvite() then
+		return false, "IM_GROUP_NOINVITE"
+	end
+
+	DeclineGroup()
+
+	if StaticPopup_Visible("PARTY_INVTIE") then
+		StaticPopup_Hide("PARTY_INVITE")
+	end
+
+	return "IM_GROUP_DECLINED"
+end
+
+function IM:AcceptGuildInvite()
+	if not self:HasGuildInvite() then
+		return false, "IM_GUILD_NOINVITE"
+	elseif self:HasGuildRep() and not self:IsGuildOverrideEnabled() then
+		return false, "IM_GUILD_HASREP"
+	end
+
+	AcceptGuild()
+
+	CloseGuildInvite()
+
+	return "IM_GUILD_ACCEPTED"
+end
+
+function IM:DeclineGuildInvite()
+	if not self:HasGuildInvite() then
+		return false, "IM_GUILD_NOINVITE"
+	end
+
+	DeclineGuild()
+
+	CloseGuildInvite()
+
+	return "IM_GUILD_DECLINED"
+end
+
+function IM:HasGroupInvite()
+	return StaticPopup_Visible("PARTY_INVITE")
+end
+
+function IM:HasGuildInvite()
+	return GuildInviteFrame and GuildInviteFrame:IsShown()
+end
+
+function IM:HasGuildRep()
+	local _, _, standingID, _, _, value = GetGuildFactionInfo()
+	if value > 0 or standingID ~= 4 then -- More than 0 rep or higher than Neutral status
+		return true
+	end
+	return false
+end
+
+function IM:Enable()
+	self.Settings.ENABLED = true
+	return "IM_ENABLED"
+end
+
+function IM:Disable()
+	self.Settings.ENABLED = false
+	return "IM_DISABLED"
+end
+
+function IM:Toggle()
+	if self:IsEnabled() then
+		return self:Disable()
+	end
+	return self:Enable()
+end
+
+function IM:IsEnabled()
+	return self.Settings.ENABLED
+end
+
+function IM:EnableGroup()
+	self.Settings.GROUP.ENABLED = true
+	return "IM_GROUP_ENABLED"
+end
+
+function IM:DisableGroup()
+	self.Settings.GROUP.ENABLED = false
+	return "IM_GROUP_DISABLED"
+end
+
+function IM:ToggleGroup()
+	if self:IsGroupEnabled() then
+		return self:DisableGroup()
+	end
+	return self:EnableGroup()
+end
+
+function IM:IsGroupEnabled()
+	return self.Settings.GROUP.ENABLED
+end
+
+function IM:EnableGroupAnnounce()
+	self.Settings.GROUP.ANNOUNCE = true
+	return "IM_GROUPANNOUNCE_ENABLED"
+end
+
+function IM:DisableGroupAnnounce()
+	self.Settings.GROUP.ANNOUNCE = false
+	return "IM_GROUPANNOUNCE_DISABLED"
+end
+
+function IM:ToggleGroupAnnounce()
+	if self:IsGroupAnnounceEnabled() then
+		return self:DisableGroupAnnounce()
+	end
+	return self:EnableGroupAnnounce()
+end
+
+function IM:IsGroupAnnounceEnabled()
+	return self.Settings.GROUP.ANNOUNCE
+end
+
+function IM:SetGroupDelay(delay)
+	if type(delay) ~= "number" then
+		return false, "IM_GROUPDELAY_NUM"
+	end
+	delay = ceil(delay)
+	if delay < 0 or delay > GROUP_MAX_DELAY then
+		return false, "IM_GROUPDELAY_OUTOFRANGE", {GROUP_MAX_DELAY}
+	end
+	self.Settings.GROUP.DELAY = delay
+	if self.Settings.GROUP.DELAY > 0 then
+		return "IM_GROUPDELAY_SET", {self.Settings.GROUP.DELAY}
+	end
+	return "IM_GROUPDELAY_DISABLED"
+end
+
+function IM:GetGroupDelay()
+	return self.Settings.GROUP.DELAY
+end
+
+function IM:DisableGroupDelay()
+	return self:SetGroupDelay(0)
+end
+
+function IM:EnableGuild()
+	self.Settings.GUILD.ENABLED = true
+	return "IM_GUILD_ENABLED"
+end
+
+function IM:DisableGuild()
+	self.Settings.GUILD.ENABLED = false
+	return "IM_GUILD_DISABLED"
+end
+
+function IM:ToggleGuild()
+	if self:IsGuildEnabled() then
+		return self:DisableGuild()
+	end
+	return self:EnableGuild()
+end
+
+function IM:IsGuildEnabled()
+	return self.Settings.GUILD.ENABLED
+end
+
+function IM:EnableGuildAnnounce()
+	self.Settings.GUILD.ANNOUNCE = true
+	return "IM_GUILDANNOUNCE_ENABLED"
+end
+
+function IM:DisableGuildAnnounce()
+	self.Settings.GUILD.ANNOUNCE = false
+	return "IM_GUILDANNOUNCE_DISABLED"
+end
+
+function IM:ToggleGuildAnnounce()
+	if self:IsGuildAnnounceEnabled() then
+		return self:DisableGuildAnnounce()
+	end
+	return self.EnableGuildAnnounce()
+end
+
+function IM:IsGuildAnnounceEnabled()
+	return self.Settings.GUILD.ANNOUNCE
+end
+
+function IM:EnableGuildOverride(confirm)
+	if StaticPopup_Visible(self.Dialogs.ConfirmGuildOverride) and not confirm then
+		return false, "IM_GUILDOVERRIDE_PENDING"
+	end
+	if not confirm then
+		StaticPopupDialogs[self.Dialogs.ConfirmGuildOverride].text = L("IM_GUILD_CONFIRM_OVERRIDE_POPUP")
+		StaticPopupDialogs[self.Dialogs.ConfirmGuildOverride].button1 = L("YES")
+		StaticPopupDialogs[self.Dialogs.ConfirmGuildOverride].button2 = L("NO")
+		StaticPopup_Show(self.Dialogs.ConfirmGuildOverride)
+		return "IM_GUILDOVERRIDE_WAITING"
+	end
+	if StaticPopup_Visible(self.Dialogs.ConfirmGuildOverride) then
+		StaticPopup_Hide(self.Dialogs.ConfirmGuildOverride)
+	end
+	self.Settings.GUILD.OVERRIDE = true
+	return "IM_GUILDOVERRIDE_ENABLED"
+end
+
+function IM:DisableGuildOverride()
+	if StaticPopup_Visible(self.Dialogs.ConfirmGuildOverride) then
+		return false, "IM_GUILDOVERRIDE_PENDING"
+	end
+	self.Settings.GUILD.OVERRIDE = false
+	return "IM_GUILDOVERRIDE_DISABLED"
+end
+
+function IM:ToggleGuildOverride()
+	if self:IsGuildOverrideEnabled() then
+		return self:DisableGuildOverride()
+	end
+	return self:EnableGuildOverride()
+end
+
+function IM:IsGuildOverrideEnabled()
+	return self.Settings.GUILD.OVERRIDE
+end
+
+function IM:SetGuildDelay(delay)
+	if type(delay) ~= "number" then
+		return false, "IM_GUILDDELAY_NUM"
+	end
+	delay = ceil(delay)
+	if delay < 0 or delay > GUILD_MAX_DELAY then
+		return false, "IM_GUILDDELAY_OUTOFRANGE", {GUILD_MAX_DELAY}
+	end
+	self.Settings.GUILD.DELAY = delay
+	if self.Settings.GUILD.DELAY > 0 then
+		return "IM_GUILDDELAY_SET", {self.Settings.GUILD.DELAY}
+	end
+	return "IM_GUILDDELAY_DISABLED"
+end
+
+function IM:GetGuildDelay()
+	return self.Settings.GUILD.DELAY
+end
+
+function IM:DisableGuildDelay()
+	return self:SetGuildDelay(0)
+end
diff --git a/load.xml b/load.xml
index da850fb..e52cdbb 100644
--- a/load.xml
+++ b/load.xml
@@ -34,6 +34,8 @@
 	<Script file="AddonComm.lua" />
 	<Script file="DeathManager.lua" />
 	<Script file="SummonManager.lua" />
+	<Script file="InviteManager.lua" />
+	<Script file="DuelManager.lua" />
 	<Script file="CommandManager.lua" />
 	<Script file="ChatManager.lua" />
 	<Script file="Events.lua" />
diff --git a/locales/enUS.lua b/locales/enUS.lua
index 17cc8a0..fbb9852 100644
--- a/locales/enUS.lua
+++ b/locales/enUS.lua
@@ -116,16 +116,27 @@ local L = {
 	CM_VERSION = "%s",

 	CM_SET_HELP = "Control the settings of Command.",
-	CM_SET_USAGE = "Usage: set cmdchar|groupinvite|deathmanager|summonmanager",
-	CM_SET_GROUPINVITE_USAGE = "Usage: set groupinvite enable|disable|<delay>",
+	CM_SET_USAGE = "Usage: set cmdchar|deathmanager|summonmanager|invitemanager|duelmanager",
 	CM_SET_DM_ISENABLED = "DeathManager is enabled.",
 	CM_SET_DM_ISDISABLED = "DeathManager is disabled.",
-	CM_SET_DM_USAGE = "Usage: set dm [enable|disable|toggle|enableress|disableress|toggleress|enablerel|disablerel|togglerel]",
+	CM_SET_DM_USAGE = "Usage: set deathmanager [enable|disable|toggle|enableress|disableress|toggleress|enablerel|disablerel|togglerel]",
 	CM_SET_SM_ISENABLED = "SummonManager is enabled.",
 	CM_SET_SM_ISDISABLED = "SummonManager is disabled.",
 	CM_SET_SM_DELAY_CURRENT = "The current delay for summon announcements is %s.",
 	CM_SET_SM_DELAY_USAGE = "Usage: set sm delay <delay>",
 	CM_SET_SM_USAGE = "Usage: set sm [enable|disable|toggle|delay]",
+	CM_SET_IM_ISENABLED = "InviteManager is enabled.",
+	CM_SET_IM_ISDISABLED = "InviteManager is disabled.",
+	CM_SET_IM_GROUP_DELAY_CURRENT = "Group announce delay is set to %d second(s).",
+	CM_SET_IM_GROUP_DELAY_USAGE = "Usage: set im groupdelay [delay]",
+	CM_SET_IM_GUILD_DELAY_CURRENT = "Guild announce delay is set to %d second(s).",
+	CM_SET_IM_GUILD_DELAY_USAGE = "Usage: set im guilddelay [delay]",
+	CM_SET_IM_USAGE = "Usage: set im [enable|disable|toggle|groupenable|groupdisable|grouptoggle|groupenableannounce|groupdisableannounce|grouptoggleannounce|groupdelay|groupdisabledelay|guildenable|guilddisable|guildtoggle|guildenableannounce|guilddisableannounce|guildtoggleannounce|guildenableoverride|guilddisableoverride|guildtoggleoverride|guilddelay|guilddisabledelay]",
+	CM_SET_CDM_ISENABLED = "DuelManager is enabled.",
+	CM_SET_CDM_ISDISABLED = "DuelManager is disabled.",
+	CM_SET_CDM_DELAY_CURRENT = "Announce delay is set to %d second(s).",
+	CM_SET_CDM_DELAY_USAGE = "Usage: set duelmanager delay [delay]",
+	CM_SET_CDM_USAGE = "Usage: set duelmanager [enable|disable|toggle|enableannounce|disableannounce|toggleannounce|delay]",

 	CM_LOCALE_HELP = "Change locale settings.",
 	CM_LOCALE_USAGE ="Usage: locale [set|reset|usemaster|playerindependent]",
@@ -165,9 +176,9 @@ local L = {
 	CM_AUTHME_USAGE = "Usage: authme <password>",

 	CM_ACCEPTINVITE_HELP = "Accepts a pending group invite.",
-	CM_ACCEPTINVITE_NOTACTIVE = "No pending invites active.",
-	CM_ACCEPTINVITE_EXISTS = "I am already in a group.",
-	CM_ACCEPTINVITE_SUCCESS = "Accepted group invite!",
+	CM_DECLINEINVITE_HELP = "Declines a pending group invite.",
+	CM_ACCEPTGUILDINVITE_HELP = "Accepts a pending guild invite.",
+	CM_DECLINEGUILDINVITE_HELP = "Declines a pending guild invite.",

 	CM_INVITE_HELP = "Invite a player to group.",

@@ -285,6 +296,13 @@ local L = {

 	CM_DECLINESUMMON_HELP = "Player will decline a pending summon request.",

+	CM_ACCEPTDUEL_HELP = "Accepts a pending duel request.",
+
+	CM_DECLINEDUEL_HELP = "Declines a pending duel request or cancels an active duel.",
+
+	CM_STARTDUEL_HELP = "Challenges another player to a duel.",
+	CM_STARTDUEL_USAGE = "Usage: startduel <target>",
+
 	------------
 	-- Events --
 	------------
@@ -292,7 +310,6 @@ local L = {
 	E_LFGPROPOSAL = "Group has been found, type !accept to make me accept the invite.",
 	E_LFGFAIL = "LFG failed, use !queue <type> to requeue.",
 	E_READYCHECK = "%s issued a ready check, type !rc accept to make me accept it or !rc deny to deny it.",
-	E_GROUPINVITE = "Type !acceptinvite to make me accept the group invite.",

 	------------------
 	-- EventHandler --
@@ -300,17 +317,6 @@ local L = {

 	EH_REGISTERED = "%q registered.",

-	----------------------------
-	-- GroupInvite (Core-Sub) --
-	----------------------------
-
-	GI_ENABLED = "Group Invite (Announce) enabled.",
-	GI_DISABLED = "Group Invite (Announce) disabled.",
-	GI_DELAY_NUM = "Delay has to be a number.",
-	GI_DELAY_MAX = "Delay cannot be greater than 50 seconds.",
-	GI_DELAY_SET = "Group Invite (Announce) delay set to %d seconds.",
-	GI_DELAY_DISABLED = "Group Invite (Announce) delay disabled.",
-
 	------------
 	-- Logger --
 	------------
@@ -499,6 +505,83 @@ local L = {
 	SM_SETDELAY_SUCCESS = "Summon announce delay successfully set to %s!",
 	SM_SETDELAY_INSTANT = "Summons will now announce instantly when received.",

+	-------------------
+	-- InviteManager --
+	-------------------
+
+	IM_GUILD_CONFIRM_OVERRIDE_POPUP = "Enabling this will render users able to issue !acceptguild even if you have reputation with a former guild, in which case you lose that reputation.\nAre you sure you want to enable this setting?",
+
+	IM_ENABLED = "InviteManager has been enabled!",
+	IM_DISABLED = "InviteManager has been disabled!",
+
+	IM_GROUP_ENABLED = "InviteManager (Group) has been enabled!",
+	IM_GROUP_DISABLED = "InviteManager (Group) has been disabled!",
+
+	IM_GROUPANNOUNCE_ENABLED = "Group invite announcement has been enabled!",
+	IM_GROUPANNOUNCE_DISABLED = "Group invite announcement has been disabled!",
+
+	IM_GROUPDELAY_NUM = "Group announce delay must be a number.",
+	IM_GROUPDELAY_OUTOFRANGE = "Group announce delay must be between 0 and %d seconds.",
+	IM_GROUPDELAY_SET = "Group announce delay set to %d second(s)!",
+	IM_GROUPDELAY_DISABLED = "Group announce delay disabled, announcement will now be sent instantly!",
+
+	IM_GUILD_ENABLED = "InviteManager (Guild) has been enabled!",
+	IM_GUILD_DISABLED = "InviteManager (Guild) has been disabled!",
+
+	IM_GUILDANNOUNCE_ENABLED = "Guild invite announcement has been enabled!",
+	IM_GUILDANNOUNCE_DISABLED = "Guild invite announcement has been disabled!",
+
+	IM_GUILDOVERRIDE_PENDING = "The guild override setting is currently being modified, please finish modifying it before issuing this command again.",
+	IM_GUILDOVERRIDE_WAITING = "Waiting for user input on guild override setting popup...",
+	IM_GUILDOVERRIDE_ENABLED = "Guild override has been enabled, users will now be able to issue !acceptguildinvite even if you have reputation with a former guild. !! USE WITH CARE !!",
+	IM_GUILDOVERRIDE_DISABLED = "Guild override has been disabled, users will no longer be able to issue !acceptguildinvite if you have reputation with a former guild.",
+
+	IM_GUILDDELAY_NUM = "Guild announce delay must be a number.",
+	IM_GUILDDELAY_OUTOFRANGE = "Guild announce delay must be between 0 and %d seconds.",
+	IM_GUILDDElAY_SET = "Guild announce delay set to %d second(s)!",
+	IM_GUILDDELAY_DISABLED = "Guild announce delay disabled, announcement will now be sent instantly!",
+
+	IM_GROUP_ANNOUNCE = "Type !accept to make me accept the group invite or !decline to decline it!",
+	IM_GUILD_ANNOUNCE = "Type !acceptguildinvite to make me accept the guild invite or !declineguildinvite to declie it!",
+
+	IM_GROUP_NOINVITE = "I do not have an active group invite.",
+	IM_GROUP_ACCEPTED = "Accepted group invite!",
+	IM_GROUP_DECLINED = "Declined group invite.",
+
+	IM_GUILD_NOINVITE = "I do not have an active guild invite.",
+	IM_GUILD_HASREP = "Unable to auto-accept guild invite, I still have reputation with my former guild that would be lost.",
+	IM_GUILD_ACCEPTED = "Accepted guild invite!",
+	IM_GUILD_DECLINED = "Declined guild invite.",
+
+	-----------------
+	-- DuelManager --
+	-----------------
+
+	CDM_ERR_NODUEL = "I do not currently have an active duel request.",
+
+	CDM_ANNOUNCE = "Type !acceptduel to make me accept the duel request or !decline duel to decline it!",
+
+	CDM_ACCEPETED = "Accepted duel request!",
+
+	CDM_DECLINED = "Declined duel request.",
+
+	CDM_CANCELLED = "Cancelled active duel (if any).",
+
+	CDM_CHALLENGED = "Sent a duel request to %s!",
+
+	CDM_ENABLED = "DuelManager has been enabled!",
+
+	CDM_DISABLED = "DuelManager has been disabled.",
+
+	CDM_ANNOUNCE_ENABLED = "DuelManager announce has been enabled!",
+
+	CDM_ANNOUNCE_DISABLED = "DuelManager announce has been disabled.",
+
+	CDM_DELAY_NUM = "Delay has to be a number.",
+	CDM_DELAY_OUTOFRANGE = "Delay has to be between 0 and %d seconds.",
+	CDM_DELAY_SET = "Announce delay set to %d second(s)!",
+	CDM_DELAY_DISABLED = "Announce delay has been disabled, will now announce immediately.",
+
 	-----------------
 	-- AuthManager --
 	-----------------
diff --git a/locales/svSE.lua b/locales/svSE.lua
index 5899f17..850648e 100644
--- a/locales/svSE.lua
+++ b/locales/svSE.lua
@@ -116,16 +116,27 @@ local L = {
 	CM_VERSION = "%s",

 	CM_SET_HELP = "Ändra inställningarna i Command.",
-	CM_SET_USAGE = "Användning: set cmdchar|groupinvite|deathmanager|summonmanager",
-	CM_SET_GROUPINVITE_USAGE = "Användning: set groupinvite enable|disable|<fördröjning>",
+	CM_SET_USAGE = "Användning: set cmdchar|deathmanager|summonmanager|invitemanager|duelmanager",
 	CM_SET_DM_ISENABLED = "DeathManager is enabled.",
 	CM_SET_DM_ISDISABLED = "DeathManager is disabled.",
 	CM_SET_DM_USAGE = "Användning: set dm [enable|disable|toggle|enableress|disableress|toggleress|enablerel|disablerel|togglerel]",
 	CM_SET_SM_ISENABLED = "SummonManager is enabled.",
 	CM_SET_SM_ISDISABLED = "SummonManager is disabled.",
 	CM_SET_SM_DELAY_CURRENT = "The current delay for summon announcements is %s.",
-	CM_SET_SM_DELAY_USAGE = "Usage: set sm delay <delay>",
+	CM_SET_SM_DELAY_USAGE = "Användning: set sm delay <delay>",
 	CM_SET_SM_USAGE = "Användning: set sm [enable|disable|toggle|delay]",
+	CM_SET_IM_ISENABLED = "InviteManager is enabled.",
+	CM_SET_IM_ISDISABLED = "InviteManager is disabled.",
+	CM_SET_IM_GROUP_DELAY_CURRENT = "Group announce delay is set to %d second(s).",
+	CM_SET_IM_GROUP_DELAY_USAGE = "Användning: set im groupdelay [delay]",
+	CM_SET_IM_GUILD_DELAY_CURRENT = "Guild announce delay is set to %d second(s).",
+	CM_SET_IM_GUILD_DELAY_USAGE = "Användning: set im guilddelay [delay]",
+	CM_SET_IM_USAGE = "Användning: set im [enable|disable|toggle|groupenable|groupdisable|grouptoggle|groupenableannounce|groupdisableannounce|grouptoggleannounce|groupdelay|groupdisabledelay|guildenable|guilddisable|guildtoggle|guildenableannounce|guilddisableannounce|guildtoggleannounce|guildenableoverride|guilddisableoverride|guildtoggleoverride|guilddelay|guilddisabledelay]",
+	CM_SET_CDM_ISENABLED = "DuelManager is enabled.",
+	CM_SET_CDM_ISDISABLED = "DuelManager is disabled.",
+	CM_SET_CDM_DELAY_CURRENT = "Announce delay is set to %d second(s).",
+	CM_SET_CDM_DELAY_USAGE = "Usage: set duelmanager delay [delay]",
+	CM_SET_CDM_USAGE = "Usage: set duelmanager [enable|disable|toggle|enableannounce|disableannounce|toggleannounce|delay]",

 	CM_LOCALE_HELP = "Change locale settings.",
 	CM_LOCALE_USAGE ="Användning: locale [set|reset|usemaster|playerindependent]",
@@ -165,9 +176,9 @@ local L = {
 	CM_AUTHME_USAGE = "Användning: authme <password>",

 	CM_ACCEPTINVITE_HELP = "Accepterar en pågående gruppinbjudan.",
-	CM_ACCEPTINVITE_NOTACTIVE = "Inga aktiva inbjudningar just nu.",
-	CM_ACCEPTINVITE_EXISTS = "Jag är redan i en grupp.",
-	CM_ACCEPTINVITE_SUCCESS = "Accepterade gruppinbjudningen!",
+	CM_DECLINEINVITE_HELP = "Declines a pending group invite.",
+	CM_ACCEPTGUILDINVITE_HELP = "Accepts a pending guild invite.",
+	CM_DECLINEGUILDINVITE_HELP = "Declines a pending guild invite.",

 	CM_INVITE_HELP = "Bjuder in en användare till gruppen.",

@@ -285,6 +296,13 @@ local L = {

 	CM_DECLINESUMMON_HELP = "Player will decline a pending summon request.",

+	CM_ACCEPTDUEL_HELP = "Accepts a pending duel request.",
+
+	CM_DECLINEDUEL_HELP = "Declines a pending duel request or cancels an active duel.",
+
+	CM_STARTDUEL_HELP = "Challenges another player to a duel.",
+	CM_STARTDUEL_USAGE = "Usage: startduel <target>",
+
 	------------
 	-- Events --
 	------------
@@ -292,7 +310,6 @@ local L = {
 	E_LFGPROPOSAL = "Group has been found, type !accept to make me accept the invite.",
 	E_LFGFAIL = "LFG failed, use !queue <type> to requeue.",
 	E_READYCHECK = "%s issued a ready check, type !rc accept to make me accept it or !rc deny to deny it.",
-	E_GROUPINVITE = "Type !acceptinvite to make me accept the group invite.",

 	------------------
 	-- EventHandler --
@@ -300,17 +317,6 @@ local L = {

 	EH_REGISTERED = "%q registered.",

-	----------------------------
-	-- GroupInvite (Core-Sub) --
-	----------------------------
-
-	GI_ENABLED = "Group Invite (Announce) enabled.",
-	GI_DISABLED = "Group Invite (Announce) disabled.",
-	GI_DELAY_NUM = "Delay has to be a number.",
-	GI_DELAY_MAX = "Delay cannot be greater than 50 seconds.",
-	GI_DELAY_SET = "Group Invite (Announce) delay set to %d seconds.",
-	GI_DELAY_DISABLED = "Group Invite (Announce) delay disabled.",
-
 	------------
 	-- Logger --
 	------------
@@ -499,6 +505,83 @@ local L = {
 	SM_SETDELAY_SUCCESS = "Summon announce delay successfully set to %s!",
 	SM_SETDELAY_INSTANT = "Summons will now announce instantly when received.",

+	-------------------
+	-- InviteManager --
+	-------------------
+
+	IM_GUILD_CONFIRM_OVERRIDE_POPUP = "Enabling this will render users able to issue !acceptguild even if you have reputation with a former guild, in which case you lose that reputation.\nAre you sure you want to enable this setting?",
+
+	IM_ENABLED = "InviteManager has been enabled!",
+	IM_DISABLED = "InviteManager has been disabled!",
+
+	IM_GROUP_ENABLED = "InviteManager (Group) has been enabled!",
+	IM_GROUP_DISABLED = "InviteManager (Group) has been disabled!",
+
+	IM_GROUPANNOUNCE_ENABLED = "Group invite announcement has been enabled!",
+	IM_GROUPANNOUNCE_DISABLED = "Group invite announcement has been disabled!",
+
+	IM_GROUPDELAY_NUM = "Group announce delay must be a number.",
+	IM_GROUPDELAY_OUTOFRANGE = "Group announce delay must be between 0 and %d seconds.",
+	IM_GROUPDELAY_SET = "Group announce delay set to %d second(s)!",
+	IM_GROUPDELAY_DISABLED = "Group announce delay disabled, announcement will now be sent instantly!",
+
+	IM_GUILD_ENABLED = "InviteManager (Guild) has been enabled!",
+	IM_GUILD_DISABLED = "InviteManager (Guild) has been disabled!",
+
+	IM_GUILDANNOUNCE_ENABLED = "Guild invite announcement has been enabled!",
+	IM_GUILDANNOUNCE_DISABLED = "Guild invite announcement has been disabled!",
+
+	IM_GUILDOVERRIDE_PENDING = "The guild override setting is currently being modified, please finish modifying it before issuing this command again.",
+	IM_GUILDOVERRIDE_WAITING = "Waiting for user input on guild override setting popup...",
+	IM_GUILDOVERRIDE_ENABLED = "Guild override has been enabled, users will now be able to issue !acceptguildinvite even if you have reputation with a former guild. !! USE WITH CARE !!",
+	IM_GUILDOVERRIDE_DISABLED = "Guild override has been disabled, users will no longer be able to issue !acceptguildinvite if you have reputation with a former guild.",
+
+	IM_GUILDDELAY_NUM = "Guild announce delay must be a number.",
+	IM_GUILDDELAY_OUTOFRANGE = "Guild announce delay must be between 0 and %d seconds.",
+	IM_GUILDDElAY_SET = "Guild announce delay set to %d second(s)!",
+	IM_GUILDDELAY_DISABLED = "Guild announce delay disabled, announcement will now be sent instantly!",
+
+	IM_GROUP_ANNOUNCE = "Type !accept to make me accept the group invite or !decline to decline it!",
+	IM_GUILD_ANNOUNCE = "Type !acceptguildinvite to make me accept the guild invite or !declineguildinvite to declie it!",
+
+	IM_GROUP_NOINVITE = "I do not have an active group invite.",
+	IM_GROUP_ACCEPTED = "Accepted group invite!",
+	IM_GROUP_DECLINED = "Declined group invite.",
+
+	IM_GUILD_NOINVITE = "I do not have an active guild invite.",
+	IM_GUILD_HASREP = "Unable to auto-accept guild invite, I still have reputation with my former guild that would be lost.",
+	IM_GUILD_ACCEPTED = "Accepted guild invite!",
+	IM_GUILD_DECLINED = "Declined guild invite.",
+
+	-----------------
+	-- DuelManager --
+	-----------------
+
+	CDM_ERR_NODUEL = "I do not currently have an active duel request.",
+
+	CDM_ANNOUNCE = "Type !acceptduel to make me accept the duel request or !decline duel to decline it!",
+
+	CDM_ACCEPETED = "Accepted duel request!",
+
+	CDM_DECLINED = "Declined duel request.",
+
+	CDM_CANCELLED = "Cancelled active duel (if any).",
+
+	CDM_CHALLENGED = "Sent a duel request to %s!",
+
+	CDM_ENABLED = "DuelManager has been enabled!",
+
+	CDM_DISABLED = "DuelManager has been disabled.",
+
+	CDM_ANNOUNCE_ENABLED = "DuelManager announce has been enabled!",
+
+	CDM_ANNOUNCE_DISABLED = "DuelManager announce has been disabled.",
+
+	CDM_DELAY_NUM = "Delay has to be a number.",
+	CDM_DELAY_OUTOFRANGE = "Delay has to be between 0 and %d seconds.",
+	CDM_DELAY_SET = "Announce delay set to %d second(s)!",
+	CDM_DELAY_DISABLED = "Announce delay has been disabled, will now announce immediately.",
+
 	-----------------
 	-- AuthManager --
 	-----------------