local _, addonTbl = ...; local issecure = issecure; local forceinsecure = forceinsecure; local allowedCommandsSet = nil; local excludedCommandsSet = nil; -- These are all the pre-defined generic slash commands that are filtered per -- game mode. Additional slash commands may be added directly by addons. -- Anything that needs to be disallowed for different game modes should be added here. SLASH_COMMAND = { TARGET = "TARGET", INSPECT = "INSPECT", STOPATTACK = "STOPATTACK", CAST = "CAST", USE = "USE", STOPCASTING = "STOPCASTING", STOPSPELLTARGET = "STOPSPELLTARGET", CANCELAURA = "CANCELAURA", CANCELFORM = "CANCELFORM", EQUIP = "EQUIP", EQUIP_TO_SLOT = "EQUIP_TO_SLOT", CHANGEACTIONBAR = "CHANGEACTIONBAR", SWAPACTIONBAR = "SWAPACTIONBAR", TARGET_EXACT = "TARGET_EXACT", TARGET_NEAREST_ENEMY = "TARGET_NEAREST_ENEMY", TARGET_NEAREST_ENEMY_PLAYER = "TARGET_NEAREST_ENEMY_PLAYER", TARGET_NEAREST_FRIEND = "TARGET_NEAREST_FRIEND", TARGET_NEAREST_FRIEND_PLAYER = "TARGET_NEAREST_FRIEND_PLAYER", TARGET_NEAREST_PARTY = "TARGET_NEAREST_PARTY", TARGET_NEAREST_RAID = "TARGET_NEAREST_RAID", CLEARTARGET = "CLEARTARGET", TARGET_LAST_TARGET = "TARGET_LAST_TARGET", TARGET_LAST_ENEMY = "TARGET_LAST_ENEMY", TARGET_LAST_FRIEND = "TARGET_LAST_FRIEND", ASSIST = "ASSIST", FOCUS = "FOCUS", CLEARFOCUS = "CLEARFOCUS", MAINTANKON = "MAINTANKON", MAINTANKOFF = "MAINTANKOFF", MAINASSISTON = "MAINASSISTON", MAINASSISTOFF = "MAINASSISTOFF", DUEL = "DUEL", MAKGORA = "MAKGORA", DUEL_CANCEL = "DUEL_CANCEL", PET_ATTACK = "PET_ATTACK", PET_FOLLOW = "PET_FOLLOW", PET_MOVE_TO = "PET_MOVE_TO", PET_STAY = "PET_STAY", PET_PASSIVE = "PET_PASSIVE", PET_DEFENSIVE = "PET_DEFENSIVE", PET_DEFENSIVEASSIST = "PET_DEFENSIVEASSIST", PET_AGGRESSIVE = "PET_AGGRESSIVE", STOPMACRO = "STOPMACRO", CANCELQUEUEDSPELL = "CANCELQUEUEDSPELL", CLICK = "CLICK", PET_DISMISS = "PET_DISMISS", LOGOUT = "LOGOUT", QUIT = "QUIT", GUILD_UNINVITE = "GUILD_UNINVITE", GUILD_PROMOTE = "GUILD_PROMOTE", GUILD_DEMOTE = "GUILD_DEMOTE", GUILD_LEADER = "GUILD_LEADER", GUILD_LEAVE = "GUILD_LEAVE", GUILD_DISBAND = "GUILD_DISBAND", EQUIP_SET = "EQUIP_SET", WORLD_MARKER = "WORLD_MARKER", CLEAR_WORLD_MARKER = "CLEAR_WORLD_MARKER", STARTATTACK = "STARTATTACK", CONSOLE = "CONSOLE", CHATLOG = "CHATLOG", COMBATLOG = "COMBATLOG", UNINVITE = "UNINVITE", PROMOTE = "PROMOTE", REPLY = "REPLY", HELP = "HELP", MACROHELP = "MACROHELP", TIME = "TIME", PLAYED = "PLAYED", FOLLOW = "FOLLOW", TRADE = "TRADE", JOIN = "JOIN", LEAVE = "LEAVE", LIST_CHANNEL = "LIST_CHANNEL", CHAT_HELP = "CHAT_HELP", CHAT_PASSWORD = "CHAT_PASSWORD", CHAT_OWNER = "CHAT_OWNER", CHAT_MODERATOR = "CHAT_MODERATOR", CHAT_UNMODERATOR = "CHAT_UNMODERATOR", CHAT_CINVITE = "CHAT_CINVITE", CHAT_KICK = "CHAT_KICK", CHAT_BAN = "CHAT_BAN", CHAT_UNBAN = "CHAT_UNBAN", CHAT_ANNOUNCE = "CHAT_ANNOUNCE", GUILD_INVITE = "GUILD_INVITE", GUILD_MOTD = "GUILD_MOTD", GUILD_INFO = "GUILD_INFO", CHAT_DND = "CHAT_DND", WHO = "WHO", CHANNEL = "CHANNEL", FRIENDS = "FRIENDS", REMOVEFRIEND = "REMOVEFRIEND", IGNORE = "IGNORE", UNIGNORE = "UNIGNORE", SCRIPT = "SCRIPT", RANDOM = "RANDOM", MACRO = "MACRO", PVP = "PVP", READYCHECK = "READYCHECK", BENCHMARK = "BENCHMARK", DISMOUNT = "DISMOUNT", RESETCHAT = "RESETCHAT", ENABLE_ADDONS = "ENABLE_ADDONS", DISABLE_ADDONS = "DISABLE_ADDONS", STOPWATCH = "STOPWATCH", ACHIEVEMENTUI = "ACHIEVEMENTUI", UI_ERRORS_OFF = "UI_ERRORS_OFF", UI_ERRORS_ON = "UI_ERRORS_ON", EVENTTRACE = "EVENTTRACE", TABLEINSPECT = "TABLEINSPECT", DUMP = "DUMP", RELOAD = "RELOAD", WARGAME = "WARGAME", TARGET_MARKER = "TARGET_MARKER", OPEN_LOOT_HISTORY = "OPEN_LOOT_HISTORY", RAIDFINDER = "RAIDFINDER", API = "API", COMMENTATOR_OVERRIDE = "COMMENTATOR_OVERRIDE", COMMENTATOR_NAMETEAM = "COMMENTATOR_NAMETEAM", COMMENTATOR_ASSIGNPLAYER = "COMMENTATOR_ASSIGNPLAYER", RESET_COMMENTATOR_SETTINGS = "RESET_COMMENTATOR_SETTINGS", VOICECHAT = "VOICECHAT", TEXTTOSPEECH = "TEXTTOSPEECH", COMBATAUDIOALERTS = "CAA", COUNTDOWN = "COUNTDOWN", PET_ASSIST = "PET_ASSIST", PET_AUTOCASTON = "PET_AUTOCASTON", PET_AUTOCASTOFF = "PET_AUTOCASTOFF", PET_AUTOCASTTOGGLE = "PET_AUTOCASTTOGGLE", SUMMON_BATTLE_PET = "SUMMON_BATTLE_PET", RANDOMPET = "RANDOMPET", RANDOMFAVORITEPET = "RANDOMFAVORITEPET", DISMISSBATTLEPET = "DISMISSBATTLEPET", USE_TOY = "USE_TOY", PING = "PING", PING_SPELL = "PING_SPELL", PING_ITEM = "PING_ITEM", ABANDON = "ABANDON", INVITE = "INVITE", REQUEST_INVITE = "REQUEST_INVITE", CHAT_AFK = "CHAT_AFK", RAID_INFO = "RAID_INFO", DUNGEONS = "DUNGEONS", LEAVEVEHICLE = "LEAVEVEHICLE", CALENDAR = "CALENDAR", SET_TITLE = "SET_TITLE", FRAMESTACK = "FRAMESTACK", SOLOSHUFFLE_WARGAME = "SOLOSHUFFLE_WARGAME", SOLORBG_WARGAME = "SOLORBG_WARGAME", SPECTATOR_WARGAME = "SPECTATOR_WARGAME", SPECTATOR_SOLOSHUFFLE_WARGAME = "SPECTATOR_SOLOSHUFFLE_WARGAME", SPECTATOR_SOLORBG_WARGAME = "SPECTATOR_SOLORBG_WARGAME", GUILDFINDER = "GUILDFINDER", TRANSMOG_CUSTOM_SET = "TRANSMOG_CUSTOM_SET", TRANSMOG_OUTFIT = "TRANSMOG_OUTFIT", COMMUNITY = "COMMUNITY", RAF = "RAF", EDITMODE = "EDITMODE", COOLDOWN_MANAGER = "COOLDOWNMANAGER", CLICK_CASTING = "CLICKCASTING", MAPPIN = "MAPPIN", }; SLASH_COMMAND_CATEGORY = { -- SLASH_COMMAND_CATEGORY.ALL should only be used by itself since other includes -- would be redundant. ALL = 1, TARGETING = 2, FOCUS_TARGETING = 3, PLAYER_INTERACTION = 4, CHAT_COMMAND = 5, -- Generic commands like /dnd, /logout, /reload etc. CHAT_CHANNEL = 6, COMBAT = 7, PET_COMMAND = 8, EQUIPMENT = 9, ACTION_BAR = 10, ROLES = 11, GUILD = 13, WORLD_MARKER = 14, DEBUG_COMMAND = 15, LOGGING = 16, GROUP_COMMAND = 17, MACRO = 18, SOCIAL = 19, PVP = 20, ADDON = 21, ACHIEVEMENT = 22, TARGET_MARKER = 23, LOOT_HISTORY = 24, RAID_FINDER = 25, COMMENTATOR = 26, VOICE_CHAT = 27, PET_BATTLE = 28, TOY = 29, PING = 30, RAID = 31, DUNGEON = 32, VEHICLE = 33, CALENDAR = 34, TITLE = 35, TRANSMOG = 36, COMMUNITY = 37, EDIT_MODE = 38, MAP = 39, }; --[[ Commands table should be formatted as: [Enum.GameMode.Foo] = { INCLUDE = { -- Include entire categories. SLASH_COMMAND_CATEGORY.COMBAT, -- Include single commands explicitly. SLASH_COMMAND.PING }, EXCLUDE = { -- Exclude specific commands from included categories. SLASH_COMMAND.USE, }, }, --]] local COMMANDS_BY_GAME_MODE = { [Enum.GameMode.Standard] = { INCLUDE = { SLASH_COMMAND_CATEGORY.ALL, }, }, [Enum.GameMode.Plunderstorm] = { INCLUDE = { SLASH_COMMAND_CATEGORY.FOCUS_TARGETING, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, SLASH_COMMAND_CATEGORY.SOCIAL, SLASH_COMMAND_CATEGORY.TARGET_MARKER, SLASH_COMMAND_CATEGORY.VOICE_CHAT, SLASH_COMMAND_CATEGORY.PING, }, }, [Enum.GameMode.WoWHack] = { INCLUDE = { SLASH_COMMAND_CATEGORY.FOCUS_TARGETING, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, SLASH_COMMAND_CATEGORY.SOCIAL, SLASH_COMMAND_CATEGORY.TARGET_MARKER, SLASH_COMMAND_CATEGORY.VOICE_CHAT, SLASH_COMMAND_CATEGORY.PING, SLASH_COMMAND_CATEGORY.CALENDAR, SLASH_COMMAND_CATEGORY.ACHIEVEMENT, SLASH_COMMAND_CATEGORY.WORLD_MARKER, SLASH_COMMAND_CATEGORY.LOGGING, SLASH_COMMAND_CATEGORY.GROUP_COMMAND, SLASH_COMMAND_CATEGORY.PLAYER_INTERACTION, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, }, }, }; if IsGMClient() then for _gameMode, commands in pairs(COMMANDS_BY_GAME_MODE) do if commands.INCLUDE then table.insert(commands.INCLUDE, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND); else commands.INCLUDE = { SLASH_COMMAND_CATEGORY.DEBUG_COMMAND }; end end end local function GetOrCreateCommandsSets() if allowedCommandsSet and excludedCommandsSet then return allowedCommandsSet, excludedCommandsSet; end allowedCommandsSet = {}; excludedCommandsSet = {}; local gameMode = C_GameRules.GetActiveGameMode(); local commands = COMMANDS_BY_GAME_MODE[gameMode]; if commands then if commands.INCLUDE then for _i, categoryOrCommand in ipairs(commands.INCLUDE) do if categoryOrCommand == SLASH_COMMAND_CATEGORY.ALL then for _categoryName, categoryKey in pairs(SLASH_COMMAND_CATEGORY) do allowedCommandsSet[categoryKey] = true; end else allowedCommandsSet[categoryOrCommand] = true; end end -- Note: there's no need to exclude anything if nothing is included. if commands.EXCLUDE then for _i, categoryOrCommand in ipairs(commands.EXCLUDE) do excludedCommandsSet[categoryOrCommand] = true; end end end end return allowedCommandsSet, excludedCommandsSet; end local function ShouldAddCommand(commandKey, category) local allowedSet, excludedSet = GetOrCreateCommandsSets(); if not allowedSet[commandKey] and not allowedSet[category] then return false; end return not excludedSet[commandKey] and not excludedSet[category]; end SlashCommandUtil = {}; function SlashCommandUtil.CheckAddSecureSlashCommand(commandKey, category, callback) -- Insecure code is not allowed to register secure slash commands. if not issecure() then SlashCommandUtil.CheckAddSlashCommand(commandKey, category, callback); return; end if not ShouldAddCommand(commandKey, category) then return; end addonTbl.SecureCmdList[commandKey] = callback; end function SlashCommandUtil.CheckAddSlashCommand(commandKey, category, callback) if not ShouldAddCommand(commandKey, category) then return; end SlashCmdList[commandKey] = callback; end SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.STARTATTACK, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target or target == "target" ) then target = action; end StartAttack(target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.STOPATTACK, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then StopAttack(); end end); -- We want to prefer spells for /cast and items for /use but we can use either SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CAST, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then local spellExists = C_Spell.DoesSpellExist(action) local name, bag, slot = SecureCmdItemParse(action); if ( spellExists ) then CastSpellByName(action, target); elseif ( slot or C_Item.GetItemInfo(name) ) then SecureCmdUseItem(name, bag, slot, target); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.USE, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then local name, bag, slot = SecureCmdItemParse(action); if ( slot or C_Item.GetItemInfo(name) ) then SecureCmdUseItem(name, bag, slot, target); else CastSpellByName(action, target); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.STOPCASTING, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then SpellStopCasting(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.STOPSPELLTARGET, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then SpellStopTargeting(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CANCELAURA, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) local spell = SecureCmdOptionParse(msg); local spellID = tonumber(spell); if spellID then C_Spell.CancelSpellByID(spellID); elseif spell then CancelSpellByName(spell); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CANCELFORM, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then CancelShapeshiftForm(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.EQUIP, SLASH_COMMAND_CATEGORY.EQUIPMENT, function(msg) local item = SecureCmdOptionParse(msg); if ( item ) then local parsedItem = SecureCmdItemParse(item); C_Item.EquipItemByName(parsedItem); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.EQUIP_TO_SLOT, SLASH_COMMAND_CATEGORY.EQUIPMENT, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then local slot, item = strmatch(action, "^(%d+)%s+(.*)"); if ( item ) then if ( PaperDoll_IsEquippedSlot(slot) ) then local parsedItem = SecureCmdItemParse(item); C_Item.EquipItemByName(parsedItem, slot); else -- user specified a bad slot number (slot that you can't equip an item to) ChatFrameUtil.DisplayUsageError(format(ERROR_SLASH_EQUIP_TO_SLOT, INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED)); end elseif ( slot ) then -- user specified a slot but not an item ChatFrameUtil.DisplayUsageError(format(ERROR_SLASH_EQUIP_TO_SLOT, INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED)); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CHANGEACTIONBAR, SLASH_COMMAND_CATEGORY.ACTION_BAR, function(msg) local page = SecureCmdOptionParse(msg); if ( page and page ~= "" ) then page = tonumber(page); if (page and page >= 1 and page <= NUM_ACTIONBAR_PAGES) then C_ActionBar.SetActionBarPage(page); else ChatFrameUtil.DisplayUsageError(format(ERROR_SLASH_CHANGEACTIONBAR, 1, NUM_ACTIONBAR_PAGES)); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.SWAPACTIONBAR, SLASH_COMMAND_CATEGORY.ACTION_BAR, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then local a, b = strmatch(action, "(%d+)%s+(%d+)"); if ( a and b ) then a = tonumber(a); b = tonumber(b); if ( ( a and a >= 1 and a <= NUM_ACTIONBAR_PAGES ) and ( b and b >= 1 and b <= NUM_ACTIONBAR_PAGES ) ) then if ( C_ActionBar.GetActionBarPage() == a ) then C_ActionBar.SetActionBarPage(b); else C_ActionBar.SetActionBarPage(a); end else ChatFrameUtil.DisplayUsageError(format(ERROR_SLASH_SWAPACTIONBAR, 1, NUM_ACTIONBAR_PAGES)); end end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target or target == "target" ) then target = action; end TargetUnit(target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_EXACT, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target or target == "target" ) then target = action; end TargetUnit(target, true); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_NEAREST_ENEMY, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetNearestEnemy(ValueToBoolean(action, false)); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_NEAREST_ENEMY_PLAYER, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetNearestEnemyPlayer(ValueToBoolean(action, false)); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_NEAREST_FRIEND, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetNearestFriend(ValueToBoolean(action, false)); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_NEAREST_FRIEND_PLAYER, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetNearestFriendPlayer(ValueToBoolean(action, false)); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_NEAREST_PARTY, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetNearestPartyMember(ValueToBoolean(action, false)); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_NEAREST_RAID, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetNearestRaidMember(ValueToBoolean(action, false)); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CLEARTARGET, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) if ( SecureCmdOptionParse(msg) ) then ClearTarget(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_LAST_TARGET, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) if ( SecureCmdOptionParse(msg) ) then TargetLastTarget(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_LAST_ENEMY, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetLastEnemy(action); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.TARGET_LAST_FRIEND, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) local action = SecureCmdOptionParse(msg); if ( action ) then TargetLastFriend(action); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.ASSIST, SLASH_COMMAND_CATEGORY.TARGETING, function(msg) if ( msg == "" ) then AssistUnit(); else local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target ) then target = action; end AssistUnit(target); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.FOCUS, SLASH_COMMAND_CATEGORY.FOCUS_TARGETING, function(msg) if ( msg == "" ) then FocusUnit(); else local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target or target == "focus" ) then target = action; end FocusUnit(target); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CLEARFOCUS, SLASH_COMMAND_CATEGORY.FOCUS_TARGETING, function(msg) if ( SecureCmdOptionParse(msg) ) then ClearFocus(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.MAINTANKON, SLASH_COMMAND_CATEGORY.ROLES, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target ) then target = action; end if ( target == "" ) then target = "target"; end SetPartyAssignment("MAINTANK", target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.MAINTANKOFF, SLASH_COMMAND_CATEGORY.ROLES, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target ) then target = action; end if ( target == "" ) then target = "target"; end ClearPartyAssignment("MAINTANK", target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.MAINASSISTON, SLASH_COMMAND_CATEGORY.ROLES, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target ) then target = action; end if ( target == "" ) then target = "target"; end SetPartyAssignment("MAINASSIST", target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.MAINASSISTOFF, SLASH_COMMAND_CATEGORY.ROLES, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target ) then target = action; end if ( target == "" ) then target = "target"; end ClearPartyAssignment("MAINASSIST", target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.DUEL, SLASH_COMMAND_CATEGORY.PLAYER_INTERACTION, function(msg) StartDuel(msg) end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.DUEL_CANCEL, SLASH_COMMAND_CATEGORY.PLAYER_INTERACTION, function(msg) ForfeitDuel() end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_ATTACK, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then if ( not target or target == "pettarget" ) then target = action; end PetAttack(target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_FOLLOW, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( SecureCmdOptionParse(msg) ) then PetFollow(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_MOVE_TO, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) local action, target = SecureCmdOptionParse(msg); if ( action ) then PetMoveTo(target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_STAY, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( SecureCmdOptionParse(msg) ) then PetWait(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_PASSIVE, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( SecureCmdOptionParse(msg) ) then PetPassiveMode(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_DEFENSIVE, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( SecureCmdOptionParse(msg) ) then PetDefensiveMode(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_DEFENSIVEASSIST, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( SecureCmdOptionParse(msg) ) then PetDefensiveAssistMode(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_AGGRESSIVE, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( SecureCmdOptionParse(msg) ) then PetAggressiveMode(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.STOPMACRO, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then StopMacro(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CANCELQUEUEDSPELL, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then SpellCancelQueuedSpell(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CLICK, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) local action = SecureCmdOptionParse(msg); if ( action and action ~= "" ) then local name, mouseButton, down = strmatch(action, "([^%s]+)%s+([^%s]+)%s*(.*)"); if ( not name ) then name = action; end if ( not mouseButton ) then mouseButton = "LeftButton"; end down = StringToBoolean(down or "", false); local button = GetClickFrame(name); if ( button and button:IsObjectType("Button") and not button:HasAccessConstraints() and not button:HasAnyForbiddenAspects(Enum.ForbiddenAspect.ScriptedInput) ) then button:Click(mouseButton, down); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.PET_DISMISS, SLASH_COMMAND_CATEGORY.PET_COMMAND, function(msg) if ( PetCanBeAbandoned() ) then CastSpellByID(Constants.SpellBookSpellIDs.SPELL_ID_DISMISS_PET); else PetDismiss(); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.LOGOUT, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) if Kiosk.IsEnabled() then return; end Logout(); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.QUIT, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) if (Kiosk.IsEnabled()) then return; end Quit(); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.GUILD_UNINVITE, SLASH_COMMAND_CATEGORY.GUILD, function(msg) if(msg == "") then msg = UnitName("target"); end if( msg and (strlen(msg) > Constants.ChatFrameConstants.MaxCharacterNameBytes) ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end C_GuildInfo.Uninvite(msg); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.GUILD_PROMOTE, SLASH_COMMAND_CATEGORY.GUILD, function(msg) if( msg and (strlen(msg) > Constants.ChatFrameConstants.MaxCharacterNameBytes) ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end C_GuildInfo.Promote(msg); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.GUILD_DEMOTE, SLASH_COMMAND_CATEGORY.GUILD, function(msg) if( msg and (strlen(msg) > Constants.ChatFrameConstants.MaxCharacterNameBytes) ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end C_GuildInfo.Demote(msg); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.GUILD_LEADER, SLASH_COMMAND_CATEGORY.GUILD, function(msg) if( msg and (strlen(msg) > Constants.ChatFrameConstants.MaxCharacterNameBytes) ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end C_GuildInfo.SetLeader(msg); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.GUILD_LEAVE, SLASH_COMMAND_CATEGORY.GUILD, function(msg) C_GuildInfo.Leave(); end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.GUILD_DISBAND, SLASH_COMMAND_CATEGORY.GUILD, function(msg) if ( IsGuildLeader() ) then StaticPopup_Show("CONFIRM_GUILD_DISBAND"); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.EQUIP_SET, SLASH_COMMAND_CATEGORY.EQUIPMENT, function(msg) local set = SecureCmdOptionParse(msg); if ( set and set ~= "" ) then local equipmentSetID = C_EquipmentSet.GetEquipmentSetID(set); if equipmentSetID ~= nil then C_EquipmentSet.UseEquipmentSet(equipmentSetID); end end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.WORLD_MARKER, SLASH_COMMAND_CATEGORY.WORLD_MARKER, function(msg) local marker, target = SecureCmdOptionParse(msg); if ( tonumber(marker) ) then PlaceRaidMarker(tonumber(marker), target); end end); SlashCommandUtil.CheckAddSecureSlashCommand(SLASH_COMMAND.CLEAR_WORLD_MARKER, SLASH_COMMAND_CATEGORY.WORLD_MARKER, function(msg) local marker = SecureCmdOptionParse(msg); if ( tonumber(marker) ) then ClearRaidMarker(tonumber(marker)); elseif ( type(marker) == "string" and strtrim(strlower(marker)) == strlower(ALL) ) then ClearRaidMarker(nil); --Clear all world markers. end end); -- Non-secure commands. SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CONSOLE, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) forceinsecure(); ConsoleExec(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHATLOG, SLASH_COMMAND_CATEGORY.LOGGING, function(msg) local info = ChatTypeInfo["SYSTEM"]; if ( LoggingChat() ) then LoggingChat(false); DEFAULT_CHAT_FRAME:AddMessage(CHATLOGDISABLED, info.r, info.g, info.b, info.id); else LoggingChat(true); DEFAULT_CHAT_FRAME:AddMessage(CHATLOGENABLED, info.r, info.g, info.b, info.id); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.COMBATLOG, SLASH_COMMAND_CATEGORY.LOGGING, function(msg) local info = ChatTypeInfo["SYSTEM"]; if ( LoggingCombat() ) then LoggingCombat(false); DEFAULT_CHAT_FRAME:AddMessage(COMBATLOGDISABLED, info.r, info.g, info.b, info.id); else LoggingCombat(true); DEFAULT_CHAT_FRAME:AddMessage(COMBATLOGENABLED, info.r, info.g, info.b, info.id); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.UNINVITE, SLASH_COMMAND_CATEGORY.GROUP_COMMAND, function(msg) if(msg == "") then msg = GetUnitName("target", true); end if(msg == nil) then ChatFrameUtil.DisplayUsageError(ERR_NO_TARGET_OR_NAME); return; end C_PartyInfo.UninviteUnit(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.PROMOTE, SLASH_COMMAND_CATEGORY.GROUP_COMMAND, function(msg) C_PartyInfo.PromoteToLeader(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.REPLY, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg, editBox) local lastTell = ChatFrameUtil.GetLastTellTarget(); if ( lastTell ) then msg = ChatFrameUtil.SubstituteChatMessageBeforeSend(msg); C_ChatInfo.SendChatMessage(msg, "WHISPER", editBox.languageID, lastTell); else -- error message end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.HELP, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) ChatFrameUtil.DisplayHelpText(DEFAULT_CHAT_FRAME); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.MACROHELP, SLASH_COMMAND_CATEGORY.MACRO, function(msg) ChatFrameUtil.DisplayMacroHelpText(DEFAULT_CHAT_FRAME); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TIME, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) ChatFrameUtil.DisplayGameTime(DEFAULT_CHAT_FRAME); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.PLAYED, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) RequestTimePlayed(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.FOLLOW, SLASH_COMMAND_CATEGORY.PLAYER_INTERACTION, function(msg) FollowUnit(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TRADE, SLASH_COMMAND_CATEGORY.PLAYER_INTERACTION, function(msg) InitiateTrade("target"); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.INSPECT, SLASH_COMMAND_CATEGORY.EQUIPMENT, function (_msg) InspectUnit("target"); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.JOIN, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local name = gsub(msg, "%s*([^%s]+).*", "%1"); local password = gsub(msg, "%s*([^%s]+)%s*(.*)", "%2"); if(name == "") then local joinhelp = CHAT_JOIN_HELP; local info = ChatTypeInfo["SYSTEM"]; DEFAULT_CHAT_FRAME:AddMessage(joinhelp, info.r, info.g, info.b, info.id); else local zoneChannel, channelName = JoinPermanentChannel(name, password, DEFAULT_CHAT_FRAME:GetID(), 1); if ( channelName ) then name = channelName; end if ( not zoneChannel ) then local info = ChatTypeInfo["CHANNEL"]; DEFAULT_CHAT_FRAME:AddMessage(CHAT_INVALID_NAME_NOTICE, info.r, info.g, info.b, info.id); return; end local i = 1; while ( DEFAULT_CHAT_FRAME.channelList[i] ) do i = i + 1; end DEFAULT_CHAT_FRAME.channelList[i] = name; DEFAULT_CHAT_FRAME.zoneChannelList[i] = zoneChannel; end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.LEAVE, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local name = strmatch(msg, "%s*([^%s]+)"); if ( name ) then LeaveChannelByName(name); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.LIST_CHANNEL, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local name = strmatch(msg, "%s*([^%s]+)"); if ( name ) then ListChannelByName(name); else ListChannels(); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_HELP, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) ChatFrameUtil.DisplayChatHelp(DEFAULT_CHAT_FRAME); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_PASSWORD, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local name = gsub(msg, "%s*([^%s]+).*", "%1"); local password = gsub(msg, "%s*([^%s]+)%s*(.*)", "%2"); SetChannelPassword(name, password); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_OWNER, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel = gsub(msg, "%s*([^%s]+).*", "%1"); local newOwner = gsub(msg, "%s*([^%s]+)%s*(.*)", "%2"); if ( not channel or not newOwner ) then return; end local newOwnerLen = strlen(newOwner); if ( newOwnerLen > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end if ( channel ~= "" ) then if ( newOwnerLen > 0 ) then SetChannelOwner(channel, newOwner); else DisplayChannelOwner(channel); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_MODERATOR, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if ( not channel or not player ) then return; end if ( strlen(player) > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end ChannelModerator(channel, player); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_UNMODERATOR, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if ( not channel or not player ) then return; end if ( strlen(player) > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end if ( channel and player ) then ChannelUnmoderator(channel, player); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_CINVITE, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if ( not channel or not player ) then return; end if ( channel and player ) then if ( strlen(player) > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end ChannelInvite(channel, player); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_KICK, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if ( not channel or not player ) then return; end if ( strlen(player) > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end if ( channel and player ) then ChannelKick(channel, player); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_BAN, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if ( not channel or not player ) then return; end if ( strlen(player) > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end if ( channel and player ) then ChannelBan(channel, player); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_UNBAN, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if ( not channel or not player ) then return; end if ( strlen(player) > Constants.ChatFrameConstants.MaxCharacterNameBytes ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end if ( channel and player ) then ChannelUnban(channel, player); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_ANNOUNCE, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg) local channel = strmatch(msg, "%s*([^%s]+)"); if ( channel ) then ChannelToggleAnnouncements(channel); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.GUILD_INVITE, SLASH_COMMAND_CATEGORY.GUILD, function(msg) if(msg == "") then msg = GetUnitName("target", true); end if( msg and (strlen(msg) > Constants.ChatFrameConstants.MaxCharacterNameBytes) ) then ChatFrameUtil.DisplayUsageError(ERR_NAME_TOO_LONG2); return; end C_GuildInfo.Invite(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.GUILD_MOTD, SLASH_COMMAND_CATEGORY.GUILD, function(msg) C_GuildInfo.SetMOTD(msg) end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.GUILD_INFO, SLASH_COMMAND_CATEGORY.GUILD, function(msg) GuildInfo(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHAT_DND, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) C_ChatInfo.SendChatMessage(msg, "DND"); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.WHO, SLASH_COMMAND_CATEGORY.SOCIAL, function(msg) local inGameWhoListDisabled = C_GameRules.IsGameRuleActive(Enum.GameRule.IngameWhoListDisabled); if (Kiosk.IsEnabled() or inGameWhoListDisabled) then return; end if ( msg == "" ) then msg = WhoFrame_GetDefaultWhoCommand(); ShowWhoPanel(); end WhoFrameEditBox:SetText(msg); C_FriendList.SendWho(msg, Enum.SocialWhoOrigin.Chat); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.CHANNEL, SLASH_COMMAND_CATEGORY.CHAT_CHANNEL, function(msg, editBox) msg = ChatFrameUtil.SubstituteChatMessageBeforeSend(msg); C_ChatInfo.SendChatMessage(msg, "CHANNEL", editBox.languageID, editBox:GetChannelTarget()); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.FRIENDS, SLASH_COMMAND_CATEGORY.SOCIAL, function(msg) local inGameFriendsListDisabled = C_GameRules.IsGameRuleActive(Enum.GameRule.IngameFriendsListDisabled); if inGameFriendsListDisabled then return; end if msg == "" and UnitIsHumanPlayer("target") then msg = GetUnitName("target", true) end if not msg or msg == "" then ToggleFriendsPanel(); else local player, note = strmatch(msg, "%s*([^%s]+)%s*(.*)"); if player and C_FriendList.IsLegacyFriendSystemEnabled() then C_FriendList.AddOrRemoveFriend(player, note); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.REMOVEFRIEND, SLASH_COMMAND_CATEGORY.SOCIAL, function(msg) if C_FriendList.IsLegacyFriendSystemEnabled() then C_FriendList.RemoveFriend(msg); end end); local function ShouldPreferCharacterIgnoreForName(name) if C_Glue.IsOnGlueScreen() then return false; end -- Prefer character ignore if the name matches the current target's full name exactly if UnitIsHumanPlayer("target") then local targetName = NameUtil.GetUnmodifiedUnitFullName("target"); local matchesTargetName = targetName and strcmputf8i(name, targetName) == 0; if matchesTargetName then return true; end end -- If the name contains a surname separator (a space) and regional unique names are not enabled, it's probably not a character name local hasSurnameSeparator = string.find(name, Constants.CharacterNameSeparatorConsts.CHARACTERNAME_SURNAME_SEPARATOR, 1, true) ~= nil; if hasSurnameSeparator and not RegionalUniqueNamesEnabled() then return false; end -- If the name looks like Name-Realm, prefer character ignore local characterName, realmName, extraNamePart = string.split(Constants.CharacterNameSeparatorConsts.CHARACTERNAME_REALMNAME_SEPARATOR, name); local hasCharacterName = characterName ~= ""; local hasRealmName = (realmName ~= nil) and (realmName ~= ""); local hasExactlyOneSeparator = extraNamePart == nil; -- Double check other misc invalid characters like whitespace, # and | local hasOnlyNameRealmCharacters = string.find(name, "[%s#|]") == nil; local hasRealmQualifiedNameFormat = hasCharacterName and hasRealmName and hasExactlyOneSeparator and hasOnlyNameRealmCharacters; if hasRealmQualifiedNameFormat then return true; end -- Finally, prefer character ignore if autocomplete recognizes the name as a character local characterOnlyAutoCompleteFilter = AUTOCOMPLETE_LIST_TEMPLATES.ALL_CHARS; return C_AutoComplete.IsRecognizedName(name, characterOnlyAutoCompleteFilter.include, characterOnlyAutoCompleteFilter.exclude); end SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.IGNORE, SLASH_COMMAND_CATEGORY.SOCIAL, function(msg) if ( msg ~= "" ) then local shouldPreferCharacterIgnore = ShouldPreferCharacterIgnoreForName(msg); if shouldPreferCharacterIgnore then C_FriendList.AddOrDelIgnore(msg); return; end local bNetIDAccount = BNet_GetBNetIDAccount(msg); if ( bNetIDAccount ) then if ( BNIsFriend(bNetIDAccount) ) then SendSystemMessage(ERR_CANNOT_IGNORE_BN_FRIEND); else C_BattleNet.SetBlocked(bNetIDAccount, not BNIsBlocked(bNetIDAccount)); end else C_FriendList.AddOrDelIgnore(msg); end elseif ( UnitIsHumanPlayer("target") ) then local targetName = NameUtil.GetUnmodifiedUnitFullName("target"); C_FriendList.AddOrDelIgnore(targetName); else ToggleIgnorePanel(); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.UNIGNORE, SLASH_COMMAND_CATEGORY.SOCIAL, function(msg) if ( msg ~= "" ) then C_FriendList.DelIgnore(msg); elseif ( UnitIsHumanPlayer("target") ) then local targetName = NameUtil.GetUnmodifiedUnitFullName("target"); C_FriendList.DelIgnore(targetName); else ToggleIgnorePanel(); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.SCRIPT, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) if Kiosk.IsEnabled() then return; end local userScriptsDisabled = C_GameRules.IsGameRuleActive(Enum.GameRule.UserScriptsDisabled); if ( not C_AddOns.GetScriptsDisallowedForBeta() and not userScriptsDisabled ) then if ( not AreDangerousScriptsAllowed() ) then StaticPopup_Show("DANGEROUS_SCRIPTS_WARNING"); return; end RunScript(msg); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RANDOM, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) local num1 = gsub(msg, "(%s*)(%d+)(.*)", "%2", 1); local rest = gsub(msg, "(%s*)(%d+)(.*)", "%3", 1); local num2 = ""; local numSubs; if ( rest ~= "" ) then num2, numSubs = gsub(msg, "(%s*)(%d+)([-%s]+)(%d+)(.*)", "%4", 1); if ( numSubs == 0 ) then num2 = ""; end end if ( num1 == "" and num2 == "" ) then RandomRoll("1", "100"); elseif ( num2 == "" ) then RandomRoll("1", num1); else RandomRoll(num1, num2); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.MACRO, SLASH_COMMAND_CATEGORY.MACRO, function(msg) if Kiosk.IsEnabled() or DISALLOW_FRAME_TOGGLING then return; end if C_GameRules.IsGameRuleActive(Enum.GameRule.MacrosDisabled) then return; end ShowMacroFrame(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.PVP, SLASH_COMMAND_CATEGORY.PVP, function(msg) C_PvP.TogglePVP(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.READYCHECK, SLASH_COMMAND_CATEGORY.GROUP_COMMAND, function(msg) if ( UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") ) then C_PartyInfo.DoReadyCheck(); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.BENCHMARK, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) SetTaxiBenchmarkMode(ValueToBoolean(msg), true); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.DISMOUNT, SLASH_COMMAND_CATEGORY.COMBAT, function(msg) if ( SecureCmdOptionParse(msg) ) then Dismount(); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RESETCHAT, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) FCF_ResetAllWindows(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.ENABLE_ADDONS, SLASH_COMMAND_CATEGORY.ADDON, function(msg) C_AddOns.EnableAllAddOns(msg); ReloadUI(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.DISABLE_ADDONS, SLASH_COMMAND_CATEGORY.ADDON, function(msg) C_AddOns.DisableAllAddOns(msg); ReloadUI(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.STOPWATCH, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) if ( not C_AddOns.IsAddOnLoaded("Blizzard_TimeManager") ) then TimeManager_LoadUI(); end if ( StopwatchFrame ) then local text = strmatch(msg, "%s*([^%s]+)%s*"); if ( text ) then text = strlower(text); -- in any of the following cases, the stopwatch will be shown StopwatchFrame:Show(); -- try to match a command local function MatchCommand(param, text) local i, compare; i = 1; repeat compare = _G[param..i]; if ( compare and compare == text ) then return true; end i = i + 1; until ( not compare ); return false; end if ( MatchCommand("SLASH_STOPWATCH_PARAM_PLAY", text) ) then Stopwatch_Play(); return; end if ( MatchCommand("SLASH_STOPWATCH_PARAM_PAUSE", text) ) then Stopwatch_Pause(); return; end if ( MatchCommand("SLASH_STOPWATCH_PARAM_STOP", text) ) then Stopwatch_Clear(); return; end -- try to match a countdown local hour, minute, second = strmatch(msg, "(%d+):(%d+):(%d+)"); if ( not hour ) then minute, second = strmatch(msg, "(%d+):(%d+)"); if ( not minute ) then second = strmatch(msg, "(%d+)"); end end Stopwatch_StartCountdown(tonumber(hour), tonumber(minute), tonumber(second)); else Stopwatch_Toggle(); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.ACHIEVEMENTUI, SLASH_COMMAND_CATEGORY.ACHIEVEMENT, function(msg) if Kiosk.IsEnabled() then return; end if DISALLOW_FRAME_TOGGLING then return; end if not ((HasCompletedAnyAchievement() or IsInGuild()) and CanShowAchievementUI()) then return; end ToggleAchievementFrame(); end); -- easier method to turn on/off errors for macros SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.UI_ERRORS_OFF, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE"); SetCVar("Sound_EnableSFX", "0"); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.UI_ERRORS_ON, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE"); SetCVar("Sound_EnableSFX", "1"); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.EVENTTRACE, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) EventTrace_LoadUI(); EventTrace:ProcessChatCommand(msg); end); if IsGMClient() then SLASH_COMMAND.TEXELVIS = "TEXELVIS"; SLASH_TEXELVIS1 = "/texelvis"; SLASH_TEXELVIS2 = "/tvis"; SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TEXELVIS, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) DebugTools_LoadUI(); TexelSnappingVisualizer:Show(); end); end SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TABLEINSPECT, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) local userScriptsDisabled = C_GameRules.IsGameRuleActive(Enum.GameRule.UserScriptsDisabled); if ( Kiosk.IsEnabled() or C_AddOns.GetScriptsDisallowedForBeta() or userScriptsDisabled ) then return; end if ( not AreDangerousScriptsAllowed() ) then StaticPopup_Show("DANGEROUS_SCRIPTS_WARNING"); return; end forceinsecure(); DebugTools_LoadUI(); local focusedTable = nil; if msg ~= "" and msg ~= " " then local focusedFunction = loadstring(("return %s"):format(msg)); focusedTable = focusedFunction and focusedFunction(); end if focusedTable and type(focusedTable) == "table" then DisplayTableInspectorWindow(focusedTable); else local highlightFrame = FrameStackTooltip:SetFrameStack(); if highlightFrame then DisplayTableInspectorWindow(highlightFrame); else DisplayTableInspectorWindow(UIParent); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.DUMP, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) local userScriptsDisabled = C_GameRules.IsGameRuleActive(Enum.GameRule.UserScriptsDisabled); if (not Kiosk.IsEnabled() and not C_AddOns.GetScriptsDisallowedForBeta() and not userScriptsDisabled) then if ( not AreDangerousScriptsAllowed() ) then StaticPopup_Show("DANGEROUS_SCRIPTS_WARNING"); return; end DebugTools_LoadUI(); DevTools_DumpCommand(msg); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RELOAD, SLASH_COMMAND_CATEGORY.CHAT_COMMAND, function(msg) ReloadUI(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.WARGAME, SLASH_COMMAND_CATEGORY.PVP, function(msg) -- Parameters are (playername, area, isTournamentMode). Since the player name can be multiple words, -- we pass in theses parameters as a whitespace delimited string and let the C side tokenize it StartWarGameByName(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TARGET_MARKER, SLASH_COMMAND_CATEGORY.TARGET_MARKER, function(msg) local marker, target = SecureCmdOptionParse(msg); if ( not target ) then target = "target"; end -- Prefixing with an "!" will prevent toggling the marker if it's already assigned. if ( marker and string.find(marker, "^!") ) then marker = tonumber(string.match(marker, "%d+")); if ( GetRaidTargetIndex(target) == marker ) then return; end -- Prefixing with a "~" will prevent setting the marker if the unit already has any marker. elseif ( marker and string.find(marker, "^~") ) then marker = tonumber(string.match(marker, "%d+")); if ( GetRaidTargetIndex(target) ~= nil ) then return; end else marker = tonumber(marker); end if ( marker ) then SetRaidTarget(target, tonumber(marker)); --Using /tm 0 will clear the target marker. end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.OPEN_LOOT_HISTORY, SLASH_COMMAND_CATEGORY.LOOT_HISTORY, function(msg) ToggleLootHistoryFrame(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RAIDFINDER, SLASH_COMMAND_CATEGORY.RAID_FINDER, function(msg) if C_LFGInfo.IsLFREnabled() then ToggleGroupFinderFrame("GroupFinderFrame", RaidFinderFrame); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.API, SLASH_COMMAND_CATEGORY.DEBUG_COMMAND, function(msg) APIDocumentation_LoadUI(); APIDocumentation:HandleSlashCommand(msg); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.COMMENTATOR_OVERRIDE, SLASH_COMMAND_CATEGORY.COMMENTATOR, function(msg) if not C_AddOns.IsAddOnLoaded("Blizzard_Commentator") then return; end local originalName, overrideName = msg:match("^(%S-)%s+(.+)"); if not originalName or not overrideName then DEFAULT_CHAT_FRAME:AddMessage(ERROR_SLASH_COMMENTATOROVERRIDE, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); DEFAULT_CHAT_FRAME:AddMessage(ERROR_SLASH_COMMENTATOROVERRIDE_EXAMPLE, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); return; end originalName = originalName:sub(1, 1):upper() .. originalName:sub(2, -1); DEFAULT_CHAT_FRAME:AddMessage((SLASH_COMMENTATOROVERRIDE_SUCCESS):format(originalName, overrideName), YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); C_Commentator.AddPlayerOverrideName(originalName, overrideName); -- Also add character name without the realm if we got CharacterName-Realm. -- Prepend possible realm separators with % so they are matched literally local realmSeparateMatchList = string.gsub(REALM_SEPARATORS, ".", "%%%1"); local characterName = string.match(originalName, "(..-)["..realmSeparateMatchList.."]."); if characterName and characterName ~= originalName then DEFAULT_CHAT_FRAME:AddMessage((SLASH_COMMENTATOROVERRIDE_SUCCESS):format(characterName, overrideName), YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); C_Commentator.AddPlayerOverrideName(characterName, overrideName); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.COMMENTATOR_NAMETEAM, SLASH_COMMAND_CATEGORY.COMMENTATOR, function(msg) if not C_AddOns.IsAddOnLoaded("Blizzard_Commentator") then return; end local teamIndex, teamName = msg:match("^(%d+) (.+)"); teamIndex = tonumber(teamIndex); if not teamIndex or not teamName then DEFAULT_CHAT_FRAME:AddMessage(ERROR_SLASH_COMMENTATOR_NAMETEAM, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); DEFAULT_CHAT_FRAME:AddMessage(ERROR_SLASH_COMMENTATOR_NAMETEAM_EXAMPLE, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); return; end if not C_Commentator.IsSpectating() then DEFAULT_CHAT_FRAME:AddMessage(CONTEXT_ERROR_SLASH_COMMENTATOR_NAMETEAM, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); return; else DEFAULT_CHAT_FRAME:AddMessage((SLASH_COMMENTATOR_NAMETEAM_SUCCESS):format(teamIndex, teamName), YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); end C_Commentator.AssignPlayersToTeamInCurrentInstance(teamIndex, teamName); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.COMMENTATOR_ASSIGNPLAYER, SLASH_COMMAND_CATEGORY.COMMENTATOR, function(msg) if not C_AddOns.IsAddOnLoaded("Blizzard_Commentator") then return; end local playerName, teamName = msg:match("^(%S-)%s+(.+)"); if not playerName or not teamName then DEFAULT_CHAT_FRAME:AddMessage(ERROR_SLASH_COMMENTATOR_ASSIGNPLAYER, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); DEFAULT_CHAT_FRAME:AddMessage(ERROR_SLASH_COMMENTATOR_ASSIGNPLAYER_EXAMPLE, YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); return; end DEFAULT_CHAT_FRAME:AddMessage((SLASH_COMMENTATOR_ASSIGNPLAYER_SUCCESS):format(playerName, teamName), YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b); C_Commentator.AssignPlayerToTeam(playerName, teamName); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RESET_COMMENTATOR_SETTINGS, SLASH_COMMAND_CATEGORY.COMMENTATOR, function(msg) if not C_AddOns.IsAddOnLoaded("Blizzard_Commentator") then return; end C_Commentator.ResetSettings(); end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.VOICECHAT, SLASH_COMMAND_CATEGORY.VOICE_CHAT, function(msg) if msg == "" then local info = ChatTypeInfo["SYSTEM"]; DEFAULT_CHAT_FRAME:AddMessage(VOICE_COMMAND_SYNTAX, info.r, info.g, info.b, info.id); return; end local name = msg; local lowerName = string.lower(name); if lowerName == string.lower(VOICE_LEAVE_COMMAND) then local channelID = C_VoiceChat.GetActiveChannelID(); if channelID then C_VoiceChat.DeactivateChannel(channelID); end return; end local channelType; local communityID; local streamID; if lowerName == string.lower(PARTY) then channelType = Enum.ChatChannelType.PrivateParty; if C_VoiceChat.GetActiveVoiceProviderID() == Enum.VoiceProviderID.Discord then channelType = Enum.ChatChannelType.DiscordParty; end elseif lowerName == string.lower(INSTANCE) then channelType = Enum.ChatChannelType.PublicParty; elseif lowerName == string.lower(GUILD) then communityID, streamID = CommunitiesUtil.FindGuildStreamByType(Enum.ClubStreamType.Guild); elseif lowerName == string.lower(OFFICER) then communityID, streamID = CommunitiesUtil.FindGuildStreamByType(Enum.ClubStreamType.Officer); else local communityName, streamName = string.split(":", name); communityID, streamID = CommunitiesUtil.FindCommunityAndStreamByName(communityName, streamName); end if channelType then if channelType ~= C_VoiceChat.GetActiveChannelType() then local activate = true; ChannelFrame:TryJoinVoiceChannelByType(channelType, activate); end elseif communityID and streamID then local activeChannelID = C_VoiceChat.GetActiveChannelID(); local communityStreamChannel = C_VoiceChat.GetChannelForCommunityStream(communityID, streamID); local communityStreamChannelID = communityStreamChannel and communityStreamChannel.channelID; if not activeChannelID or activeChannelID ~= communityStreamChannelID then ChannelFrame:TryJoinCommunityStreamChannel(communityID, streamID); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TEXTTOSPEECH, SLASH_COMMAND_CATEGORY.VOICE_CHAT, function(msg) local cmd, success, failureText, failureTextNarrated = TextToSpeechCommands:EvaluateTextToSpeechCommand(msg); if cmd == nil then TextToSpeechCommands:SpeakConfirmation(TEXTTOSPEECH_COMMAND_SYNTAX_ERROR); elseif success then TextToSpeechFrame_Update(TextToSpeechFrame); else if not failureText then failureText, failureTextNarrated = TextToSpeechCommands:GetCommandHelpText(cmd); end if failureText then TextToSpeechCommands:SpeakConfirmation(failureText, failureTextNarrated); else TextToSpeechCommands:SpeakConfirmation(CAA_COMMAND_SYNTAX_ERROR, CAA_COMMAND_SYNTAX_ERROR_NARRATED); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.COMBATAUDIOALERTS, SLASH_COMMAND_CATEGORY.VOICE_CHAT, function(msg) local cmd, success, failureText, failureTextNarrated = CAACommands:EvaluateTextToSpeechCommand(msg); if cmd == nil then CAACommands:SpeakConfirmation(CAA_COMMAND_SYNTAX_ERROR, CAA_COMMAND_SYNTAX_ERROR_NARRATED); elseif success then if not cmd.isMainToggle and not GetCVarBool("CAAEnabled") then CAACommands:SpeakConfirmation(SLASH_CAA_DISABLED_WARNING, SLASH_CAA_DISABLED_WARNING_NARRATED); end else if not failureText then local failureTextInfo = CAACommands:GetCommandHelpText(cmd); if not TableIsEmpty(failureTextInfo) then failureText = failureTextInfo[1].displayText; failureTextNarrated = failureTextInfo[1].narratedText; end end if failureText then CAACommands:SpeakConfirmation(failureText, failureTextNarrated); else CAACommands:SpeakConfirmation(CAA_COMMAND_SYNTAX_ERROR, CAA_COMMAND_SYNTAX_ERROR_NARRATED); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.COUNTDOWN, SLASH_COMMAND_CATEGORY.GROUP_COMMAND, function(msg) local num1 = gsub(msg, "(%s*)(%d+)", "%2"); local number = tonumber(num1); if(number and number <= Constants.PartyCountdownConstants.MaxCountdownSeconds) then C_PartyInfo.DoCountdown(number); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.SUMMON_BATTLE_PET, SLASH_COMMAND_CATEGORY.PET_BATTLE, function(msg) -- GAME RULES TODO:: This should be an explicit game rule. if C_GameRules.GetActiveGameMode() == Enum.GameMode.Plunderstorm then return; end local pet = SecureCmdOptionParse(msg); if ( type(pet) == "string" ) then local _, petID = C_PetJournal.FindPetIDByName(string.trim(pet)); if ( petID ) then C_PetJournal.SummonPetByGUID(petID); else C_PetJournal.SummonPetByGUID(pet); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RANDOMPET, SLASH_COMMAND_CATEGORY.PET_BATTLE, function(msg) -- GAME RULES TODO:: This should be an explicit game rule. if C_GameRules.GetActiveGameMode() == Enum.GameMode.Plunderstorm then return; end if ( SecureCmdOptionParse(msg) ) then C_PetJournal.SummonRandomPet(false); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RANDOMFAVORITEPET, SLASH_COMMAND_CATEGORY.PET_BATTLE, function(msg) -- GAME RULES TODO:: This should be an explicit game rule. if C_GameRules.GetActiveGameMode() == Enum.GameMode.Plunderstorm then return; end if ( SecureCmdOptionParse(msg) ) then C_PetJournal.SummonRandomPet(true); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.DISMISSBATTLEPET, SLASH_COMMAND_CATEGORY.PET_BATTLE, function(msg) -- GAME RULES TODO:: This should be an explicit game rule. if C_GameRules.GetActiveGameMode() == Enum.GameMode.Plunderstorm then return; end if ( SecureCmdOptionParse(msg) ) then local petID = C_PetJournal.GetSummonedPetGUID(); if ( petID ) then C_PetJournal.SummonPetByGUID(petID); end end end); local isRaidInfoNotificationPending = false; SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.RAID_INFO, SLASH_COMMAND_CATEGORY.RAID, function(msg) if SocialUIControl and SocialUIControl.IsEnabled() then -- The raid list can be shut off by its kill switch, and in that case there is no raid list UI for us to open if not C_PartyInfo.IsRaidListEnabled() then UIErrorsFrame:AddExternalErrorMessage(ERR_SYSTEM_DISABLED); return; end local hasRaidLockoutData = GetNumSavedInstances() + GetNumSavedWorldBosses() > 0; if hasRaidLockoutData then SocialUIControl.ToggleToTabAndSideWindow(SocialUITabType.RaidList, SocialUISideWindowType.RaidInfoFrame); else SocialUIControl.ToggleToTab(SocialUITabType.RaidList); end -- If the player is using this slash command to open the raid info frame but doesn't have raid info we want to show a message in chat if not isRaidInfoNotificationPending then isRaidInfoNotificationPending = true; EventUtil.RegisterOnceFrameEventAndCallback("UPDATE_INSTANCE_INFO", function() isRaidInfoNotificationPending = false; local hasRaidLockoutData = GetNumSavedInstances() + GetNumSavedWorldBosses() > 0; if not hasRaidLockoutData then ChatFrameUtil.DisplaySystemMessageInPrimary(NO_RAID_INSTANCES_SAVED); end end); end return; end RaidFrame.slashCommand = 1; if ( ( GetNumSavedInstances() + GetNumSavedWorldBosses() > 0 ) and not RaidInfoFrame:IsVisible() ) then ToggleRaidFrame(); RaidInfoFrame:Show(); elseif ( not RaidFrame:IsVisible() ) then ToggleRaidFrame(); end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.TRANSMOG_OUTFIT, SLASH_COMMAND_CATEGORY.TRANSMOG, function(msg) local parsedIndex = SecureCmdOptionParse(msg); if parsedIndex == "" then -- If run with no arguments, act as a clear. C_TransmogOutfitInfo.ClearOutfit(); elseif parsedIndex ~= nil then -- Note if applying the same outfit that is already applied, it will be treated as a clear unless the index is prefixed by '!'. local allowRemoveOutfit = true; if string.sub(parsedIndex, 1, 1) == "!" then allowRemoveOutfit = false; parsedIndex = string.sub(parsedIndex, 2, #parsedIndex); end -- playerFacingOutfitIndex is slightly different from outfitID that the transmog system uses, as it's a bit more player friendly (outfitIDs may have gaps). -- 0 - Trial of Style outfit (if available). -- 1+ - Corresponding outfit (if unlocked). local playerFacingOutfitIndex = tonumber(parsedIndex); if playerFacingOutfitIndex then C_TransmogOutfitInfo.ChangeToOutfit(playerFacingOutfitIndex, allowRemoveOutfit); end end end); SlashCommandUtil.CheckAddSlashCommand(SLASH_COMMAND.MAKGORA, SLASH_COMMAND_CATEGORY.PVP, function(msg) if(not msg or msg == "") then msg = GetUnitName("target", true); end if (msg == "" or not msg or not C_GameRules.IsHardcoreActive()) then return; end local text2 = nil; local data = {unit = "target"}; StaticPopup_Show("DUEL_TO_THE_DEATH_CHALLENGE_CONFIRM", msg, text2, data); end);