diff --git a/.vscode/settings.json b/.vscode/settings.json index f8d9bb4..de13935 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,10 +16,14 @@ // Due to the merge nature of this there are some duplication issues. "duplicate-doc-field", "duplicate-doc-alias", + // Some string concatenations are done in a way that confuses the type checker. + "ambiguity-1", // Not all type annotations are accurate in the WoW API, so we disable these type mismatch warnings. "return-type-mismatch", // Not all type annotations are accurate in the WoW API, so we disable these type mismatch warnings. "param-type-mismatch", + // The Lua checker sometimes gets a number assignment but somewhere else it gets assigned nil. + "assign-type-mismatch", // Because we add casts after the fact to satisfy the type checker, we disable this warning. "cast-local-type", // Classes do not like injecting fields but that requires refactoring which we can't do. @@ -32,5 +36,7 @@ "Lua.workspace.ignoreDir": [ ".vscode", "generator", - ] + ], + "Lua.workspace.maxPreload": 5000, + "Lua.workspace.preloadFileSize": 3000, } \ No newline at end of file diff --git a/WoW-API/.luarc.json b/WoW-API/.luarc.json new file mode 100644 index 0000000..a5181e5 --- /dev/null +++ b/WoW-API/.luarc.json @@ -0,0 +1,73 @@ +{ + // This is the config file used for manual LuaLS runs + // cd WoW-API + // lua-language-server --check=. --check_format=json --metapath=../.lua-data/meta --logpath=../.lua-data/log --configpath=./.luarc.json + "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json", + "workspace.ignoreDir": [ + ".git", + ".vscode" + ], + "workspace.preloadFileSize": 3000, + "workspace.maxPreload": 2000, + "diagnostics.ignoredFiles": "Opened", + "diagnostics.libraryFiles": "Opened", + "workspace.useGitIgnore": false, + "diagnostics.groupFileStatus": { + "await": "Any" + }, + "diagnostics.severity": {}, + "diagnostics.disable": [ + // We don't care about undefined globals because the WoW API defines a lot of them. + "undefined-global", + // A lot of the code at blizzard has a ton of redundant parameters for some reason. + "redundant-parameter", + // Some languages support multiple assignment counts, but Lua does not. (e.g. local a, b = 1) + "unbalanced-assignments", + // Some functions say the don't support certain parameters, but they actually do. (GetAchievementCriteriaInfo vs GetAchievementCriteriaInfoByID) + // So we disable this check. + "missing-parameter", + // Some of Blizzard's code uses lowercase globals, which is against Lua conventions. + "lowercase-global", + // Deprecated functions and features are common in the WoW API, so we disable this warning. + "deprecated", + // Due to the merge nature of this there are some duplication issues. + "duplicate-doc-field", + "duplicate-doc-alias", + // Some string concatenations are done in a way that confuses the type checker. + "ambiguity-1", + // Not all type annotations are accurate in the WoW API, so we disable these type mismatch warnings. + "return-type-mismatch", + // Not all type annotations are accurate in the WoW API, so we disable these type mismatch warnings. + "param-type-mismatch", + // The Lua checker sometimes gets a number assignment but somewhere else it gets assigned nil. + "assign-type-mismatch", + // Because we add casts after the fact to satisfy the type checker, we disable this warning. + "cast-local-type", + // Classes do not like injecting fields but that requires refactoring which we can't do. + "inject-field", + // Not checking nil values is common in WoW API code. + "need-check-nil", + // Trailing spaces are not a big deal. + "trailing-space", + + // Only for WoW API LuaLanguageServer settings: + // We haven't defined all fields for all objects yet. + "undefined-field" + ], + "diagnostics.enable": true, + "runtime.version": "Lua 5.1", + "runtime.builtin": { + "basic": "enable", + "debug": "enable", + "io": "enable", + "math": "enable", + "os": "enable", + "package": "enable", + "string": "enable", + "table": "enable", + "utf8": "disable", + "builtin": "enable" + }, + "diagnostics.globals": [], + "hint.enable": false +} \ No newline at end of file diff --git a/WoW-API/COMMIT_HASHES.md b/WoW-API/COMMIT_HASHES.md index db898f3..8425be7 100644 --- a/WoW-API/COMMIT_HASHES.md +++ b/WoW-API/COMMIT_HASHES.md @@ -5,4 +5,4 @@ This API documentation was generated using the following commit hashes: - **vscode-wow-api**: `master` @ `a2e82582ac3f38c096ecc192fe701c3ba901d95d` - **WoWUI**: `vanilla` @ `b6262ddd722e41b0757e7c6ae2e2a83563044152` -Generated on: 2025-12-08 16:37:50 +Generated on: 2025-12-10 15:12:04 diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_11_1_7.lua b/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_11_1_7.lua deleted file mode 100644 index 92fbe31..0000000 --- a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_11_1_7.lua +++ /dev/null @@ -1,11 +0,0 @@ ----@meta _ - ----@deprecated ----Deprecated by [ActionButtonSpellAlertManager:ShowAlert](https://www.townlong-yak.com/framexml/go/ActionButtonSpellAlertManager:ShowAlert) ----@param button table -function ActionButton_ShowOverlayGlow(button) end - ----@deprecated ----Deprecated by [ActionButtonSpellAlertManager:HideAlert](https://www.townlong-yak.com/framexml/go/ActionButtonSpellAlertManager:HideAlert) ----@param button table -function ActionButton_HideOverlayGlow(button) end diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_SpellBook.lua.lua b/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_SpellBook.lua.lua deleted file mode 100644 index bb96465..0000000 --- a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_SpellBook.lua.lua +++ /dev/null @@ -1,21 +0,0 @@ ----@meta _ - ----@deprecated ----Deprecated by [C_SpellBook.IsSpellKnown](https://warcraft.wiki.gg/wiki/API_C_SpellBook.IsSpellKnown) ----@param spellID number ----@return boolean isKnown -function IsPlayerSpell(spellID) end - ----@deprecated ----Deprecated by [C_SpellBook.IsSpellInSpellBook](https://warcraft.wiki.gg/wiki/API_C_SpellBook.IsSpellInSpellBook) ----@param spellID number ----@param isPet boolean ----@return boolean isInSpellBook -function IsSpellKnown(spellID, isPet) end - ----@deprecated ----Deprecated by [C_SpellBook.IsSpellInSpellBook](https://warcraft.wiki.gg/wiki/API_C_SpellBook.IsSpellInSpellBook) ----@param spellID number ----@param isPet boolean ----@return boolean isInSpellBook -function IsSpellKnownOrOverridesKnown(spellID, isPet) end diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_UnitScript.lua b/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_UnitScript.lua deleted file mode 100644 index 828cb45..0000000 --- a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_UnitScript.lua +++ /dev/null @@ -1,7 +0,0 @@ ----@meta _ - ----@deprecated ----Deprecated by [UnitIsVisible](https://warcraft.wiki.gg/wiki/API_UnitIsVisible) ----@param unit? UnitToken Default = WOWGUID_NULL ----@return boolean result -function ShowBossFrameWhenUninteractable(unit) end diff --git a/WoW-API/FrameXML/Blizzard_FrameXML/AuraUtil.lua b/WoW-API/FrameXML/Blizzard_FrameXML/AuraUtil.lua index 6547a2c..46325c0 100644 --- a/WoW-API/FrameXML/Blizzard_FrameXML/AuraUtil.lua +++ b/WoW-API/FrameXML/Blizzard_FrameXML/AuraUtil.lua @@ -1,30 +1,5 @@ ---@meta _ -AuraUtil = {} - ----[FrameXML](https://github.com/Gethe/wow-ui-source/blob/live/Interface/FrameXML/AuraUtil.lua#L32) --- Finds the first aura that matches the name ----@param auraName string ----@param unit string ----@param filter? string ----@return string name ----@return number icon ----@return number count ----@return string? dispelType ----@return number duration ----@return number expirationTime ----@return string source ----@return boolean isStealable ----@return boolean nameplateShowPersonal ----@return number spellId ----@return boolean canApplyAura ----@return boolean isBossDebuff ----@return boolean castByPlayer ----@return boolean nameplateShowAll ----@return number timeMod ----@return ... -function AuraUtil.FindAuraByName(auraName, unit, filter) end - ---[FrameXML](https://github.com/Gethe/wow-ui-source/blob/live/Interface/FrameXML/AuraUtil.lua#L51) --- Iterates over a filtered list of auras ---@param unit string diff --git a/WoW-API/FrameXML/Blizzard_FrameXML/ItemUtil.lua b/WoW-API/FrameXML/Blizzard_FrameXML/ItemUtil.lua deleted file mode 100644 index 0bfa0b8..0000000 --- a/WoW-API/FrameXML/Blizzard_FrameXML/ItemUtil.lua +++ /dev/null @@ -1,26 +0,0 @@ ----@meta _ - ----[Documentation](https://warcraft.wiki.gg/wiki/ItemTransmogInfoMixin) ----@class ItemTransmogInfoMixin -ItemTransmogInfoMixin = {} - ---- See [CreateAndInitFromMixin](https://www.townlong-yak.com/framexml/go/CreateAndInitFromMixin) ----@param appearanceID number ----@param secondaryAppearanceID number? ----@param illusionID number? -function ItemTransmogInfoMixin:Init(appearanceID, secondaryAppearanceID, illusionID) end - ----@param itemTransmogInfo table ----@return boolean -function ItemTransmogInfoMixin:IsEqual(itemTransmogInfo) end - -function ItemTransmogInfoMixin:Clear() end - ----@param isLegionArtifact boolean -function ItemTransmogInfoMixin:ConfigureSecondaryForMainHand(isLegionArtifact) end - ----@return boolean -function ItemTransmogInfoMixin:IsMainHandIndividualWeapon() end - ----@return boolean -function ItemTransmogInfoMixin:IsMainHandPairedWeapon() end diff --git a/WoW-API/FrameXML/Blizzard_FrameXML/ReportFrame.lua b/WoW-API/FrameXML/Blizzard_FrameXML/ReportFrame.lua index fd010a4..0f57787 100644 --- a/WoW-API/FrameXML/Blizzard_FrameXML/ReportFrame.lua +++ b/WoW-API/FrameXML/Blizzard_FrameXML/ReportFrame.lua @@ -4,39 +4,3 @@ ---@class ReportInfoMixin ReportInfoMixin = {} -function ReportInfoMixin:Clear() end - ----@param mailIndex number -function ReportInfoMixin:SetMailIndex(mailIndex) end - ----@param clubFinderGUID string -function ReportInfoMixin:SetClubFinderGUID(clubFinderGUID) end - ----@param reportTarget string -function ReportInfoMixin:SetReportTarget(reportTarget) end - ----@param comment string -function ReportInfoMixin:SetComment(comment) end - ----@param groupFinderSearchResultID number -function ReportInfoMixin:SetGroupFinderSearchResultID(groupFinderSearchResultID) end - ----@param groupFinderApplicantID number -function ReportInfoMixin:SetGroupFinderApplicantID(groupFinderApplicantID) end - ----@param reportType Enum.ReportType -function ReportInfoMixin:SetReportType(reportType) end - ----@param majorCategory Enum.ReportMajorCategory -function ReportInfoMixin:SetReportMajorCategory(majorCategory) end - ----@param minorCategoryFlags Enum.ReportMinorCategory -function ReportInfoMixin:SetMinorCategoryFlags(minorCategoryFlags) end - ----@param petGUID string -function ReportInfoMixin:SetPetGUID(petGUID) end - ----@param reportType? Enum.ReportType ----@param majorCategory Enum.ReportMajorCategory ----@param minorCategoryFlags Enum.ReportMinorCategory -function ReportInfoMixin:SetBasicReportInfo(reportType, majorCategory, minorCategoryFlags) end diff --git a/WoW-API/FrameXML/Blizzard_FrameXML/TransmogUtil.lua b/WoW-API/FrameXML/Blizzard_FrameXML/TransmogUtil.lua index a0d5ddb..fa24289 100644 --- a/WoW-API/FrameXML/Blizzard_FrameXML/TransmogUtil.lua +++ b/WoW-API/FrameXML/Blizzard_FrameXML/TransmogUtil.lua @@ -1,59 +1,7 @@ ---@meta _ ----[Documentation](https://warcraft.wiki.gg/wiki/TransmogLocationMixin) ----@class TransmogPendingInfoMixin -TransmogPendingInfoMixin = {} - ---- See [CreateAndInitFromMixin](https://www.townlong-yak.com/framexml/go/CreateAndInitFromMixin) ----@param pendingType Enum.TransmogPendingType ----@param transmogID number ----@param category number -function TransmogPendingInfoMixin:Init(pendingType, transmogID, category) end - ---@class TransmogLocationType ---@field slotID? InventorySlots ---@field type? Enum.TransmogType ---@field modification? Enum.TransmogModification ----[Documentation](https://warcraft.wiki.gg/wiki/TransmogLocationMixin) ----@class TransmogLocationMixin : TransmogLocationType -TransmogLocationMixin = {} - ----@param slotID number ----@param transmogType Enum.TransmogType ----@param modification Enum.TransmogModification -function TransmogLocationMixin:Set(slotID, transmogType, modification) end - ----@return boolean -function TransmogLocationMixin:IsAppearance() end - ----@return boolean -function TransmogLocationMixin:IsIllusion() end - ----@return number slotID -function TransmogLocationMixin:GetSlotID() end - ----@return string slotName -function TransmogLocationMixin:GetSlotName() end - ----@return boolean -function TransmogLocationMixin:IsEitherHand() end - ----@return boolean -function TransmogLocationMixin:IsMainHand() end - ----@return boolean -function TransmogLocationMixin:IsOffHand() end - ----@param transmogLocation TransmogLocationMixin ----@return boolean -function TransmogLocationMixin:IsEqual(transmogLocation) end - ----@return number armorCategoryID -function TransmogLocationMixin:GetArmorCategoryID() end - ----@return number lookupKey -function TransmogLocationMixin:GetLookupKey() end - ----@return boolean -function TransmogLocationMixin:IsSecondary() end diff --git a/WoW-API/FrameXML/Blizzard_FrameXML/UIParent.lua b/WoW-API/FrameXML/Blizzard_FrameXML/UIParent.lua index f909363..ed8cec9 100644 --- a/WoW-API/FrameXML/Blizzard_FrameXML/UIParent.lua +++ b/WoW-API/FrameXML/Blizzard_FrameXML/UIParent.lua @@ -10,43 +10,6 @@ UIParent = {} ---@param force? number function ShowUIPanel(frame, force) end ----[FrameXML](https://www.townlong-yak.com/framexml/go/HideUIPanel) ----@param frame Frame ----@param skipSetPoint? boolean -function HideUIPanel(frame, skipSetPoint) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/UIFrameFade) ---- Generic fade function ----@param frame Frame ----@param fadeInfo table -function UIFrameFade(frame, fadeInfo) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/UIFrameFadeIn) ---- Convenience function to do a simple fade in ----@param frame Frame ----@param timeToFade number ----@param startAlpha number ----@param endAlpha number -function UIFrameFadeIn(frame, timeToFade, startAlpha, endAlpha) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/UIFrameFadeOut) ---- Convenience function to do a simple fade out ----@param frame Frame ----@param timeToFade number ----@param startAlpha number ----@param endAlpha number -function UIFrameFadeOut(frame, timeToFade, startAlpha, endAlpha) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/getglobal) ----@param varr string ----@return any -function getglobal(varr) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/setglobal) ----@param varr string ----@param value any -function setglobal(varr, value) end - ---[FrameXML](https://www.townlong-yak.com/framexml/go/AbbreviateNumbers) ---@param value number ---@return string diff --git a/WoW-API/FrameXML/Blizzard_Menu/Menu.lua b/WoW-API/FrameXML/Blizzard_Menu/Menu.lua deleted file mode 100644 index fb7a3d8..0000000 --- a/WoW-API/FrameXML/Blizzard_Menu/Menu.lua +++ /dev/null @@ -1,37 +0,0 @@ ----@meta _ - -Menu = {} - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.GetManager) ----@return MenuManagerProxy -function Menu.GetManager() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.CreateRootMenuDescription) ----@generic M: table ----@param menuMixin M ----@return RootMenuDescriptionProxy|M rootMenuDescription -function Menu.CreateRootMenuDescription(menuMixin) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.CreateMenuElementDescription) ----@return ElementMenuDescriptionProxy -function Menu.CreateMenuElementDescription() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.PopulateDescription) ----@param menuGenerator fun(ownerRegion: Region, description: RootMenuDescriptionProxy, ...) ----@param ownerRegion Region ----@param description RootMenuDescriptionProxy ----@param ... any? # passed to the generator -function Menu.PopulateDescription(menuGenerator, ownerRegion, description, ...) end - ----Can be used by addons to modify blizzard's menus in a taint-safe manner ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.ModifyMenu) ----@param tag string ----@param callback fun(ownerRegion: Region, description: RootMenuDescriptionProxy, contextData: any?) -function Menu.ModifyMenu(tag, callback) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.GetOpenMenuTags) ----@return string[] tags -function Menu.GetOpenMenuTags() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Menu.PrintOpenMenuTags) -function Menu.PrintOpenMenuTags() end diff --git a/WoW-API/FrameXML/Blizzard_Menu/MenuUtil.lua b/WoW-API/FrameXML/Blizzard_Menu/MenuUtil.lua index a45ea94..22382cd 100644 --- a/WoW-API/FrameXML/Blizzard_Menu/MenuUtil.lua +++ b/WoW-API/FrameXML/Blizzard_Menu/MenuUtil.lua @@ -1,172 +1,11 @@ ----@meta _ - -MenuUtil = {} - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.TraverseMenu) ----@param elementDescription RootMenuDescriptionProxy|ElementMenuDescriptionProxy ----@param op fun(elementDescription: ElementMenuDescriptionProxy): boolean? # return true to stop traversal ----@param condition nil|fun(elementDescription: ElementMenuDescriptionProxy): boolean # return true to apply `op` to the element description; if nil, all elements are processed ----@return boolean stopped # true if the traversal was stopped by `op` returning true -function MenuUtil.TraverseMenu(elementDescription, op, condition) end - ----Return a list of all selected elements, optionally filtered by a condition ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.GetSelections) ----@param elementDescription RootMenuDescriptionProxy|ElementMenuDescriptionProxy ----@param condition nil|fun(elementDescription: ElementMenuDescriptionProxy): boolean # return true to include the element description -function MenuUtil.GetSelections(elementDescription, condition) end - ----Sets up a tooltip anchored to the right of the owner, applying the given function to it, and showing it ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.ShowTooltip) ----@param owner Region ----@param func fun(tooltip: GameTooltip, ...) ----@param ... any? -function MenuUtil.ShowTooltip(owner, func, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.HideTooltip) ----@param owner Region -function MenuUtil.HideTooltip(owner) end - ----Hooks OnEnter and OnLeave for a reagion, configures a tooltip, calls the given function, and shows the tooltip ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.HookTooltipScripts) ----@param owner Region ----@param func fun(tooltip: GameTooltip) # called both in OnEnter and OnLeave -function MenuUtil.HookTooltipScripts(owner, func) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateRootMenuDescription) ----@generic M: table ----@param menuMixin M ----@return RootMenuDescriptionProxy|M rootMenuDescription -function MenuUtil.CreateRootMenuDescription(menuMixin) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateContextMenu) ----@param ownerRegion Region? # if nil, defaults to UIParent ----@param generator fun(ownerRegion: Region, description: RootMenuDescriptionProxy, ...) ----@param ... any? # passed to the generator ----@return MenuProxy? menu -function MenuUtil.CreateContextMenu(ownerRegion, generator, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.SetElementText) ----@param elementDescription ElementMenuDescriptionProxy ----@param text string -function MenuUtil.SetElementText(elementDescription, text) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.GetElementText) ----@param elementDescription ElementMenuDescriptionProxy ----@return string text -function MenuUtil.GetElementText(elementDescription) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateFrame) ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateFrame() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateTemplate) ----@param template Template ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateTemplate(template) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateTitle) ----@param text string ----@param color colorRGBA? # defaults to NORMAL_FONT_COLOR ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateTitle(text, color) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateButton) ----@param text string ----@param callback MenuResponder ----@param data any? # stored as element's data ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateButton(text, callback, data) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateCheckbox) ----@param text string ----@param isSelected fun(data: any): boolean # data = data param -> element:GetData() ----@param setSelected MenuResponder ----@param data any? # stored as element's data ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateCheckbox(text, isSelected, setSelected, data) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateRadio) ----@param text string ----@param isSelected fun(data: any): boolean # data = data param -> element:GetData() ----@param setSelected MenuResponder ----@param data any? # stored as element's data ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateRadio(text, isSelected, setSelected, data) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateColorSwatch) ----@param text string ----@param callback MenuResponder ----@param colorInfo colorRGBA # stored as element's data ----@return ElementMenuDescriptionProxy -function MenuUtil.CreateColorSwatch(text, callback, colorInfo) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuTemplates.CreateDivider) ----@return ElementMenuDescriptionProxy # some inserters and utility functions are missing -function MenuUtil.CreateDivider() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuTemplates.CreateSpacer) ----@param extend number? # height of the spacer, default = 10 ----@return ElementMenuDescriptionProxy # some inserters and utility functions are missing -function MenuUtil.CreateSpacer(extend) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateButtonMenu) ----@param dropdown DropdownButton ----@param ... {[1]:string, [2]: MenuResponder, [3]: any?} # list of {text, callback, data} -function MenuUtil.CreateButtonMenu(dropdown, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateButtonContextMenu) ----@param ownerRegion Region? # if nil, defaults to UIParent ----@param ... {[1]:string, [2]: MenuResponder, [3]: any?} # list of {text, callback, data} ----@return MenuProxy? menu -function MenuUtil.CreateButtonContextMenu(ownerRegion, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateCheckboxMenu) ----@param dropdown DropdownButton ----@param isSelected fun(data: any): boolean # shared between all menu items ----@param setSelected MenuResponder # shared between all menu items ----@param ... {[1]:string, [2]: any?} # list of {text, data} -function MenuUtil.CreateCheckboxMenu(dropdown, isSelected, setSelected, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateCheckboxContextMenu) ----@param ownerRegion Region? # if nil, defaults to UIParent ----@param isSelected fun(data: any): boolean # shared between all menu items ----@param setSelected MenuResponder # shared between all menu items ----@param ... {[1]:string, [2]: any?} # list of {text, data} ----@return MenuProxy? menu -function MenuUtil.CreateCheckboxContextMenu(ownerRegion, isSelected, setSelected, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateRadioMenu) ----@param dropdown DropdownButton ----@param isSelected fun(data: any): boolean # shared between all menu items ----@param setSelected MenuResponder # shared between all menu items ----@param ... {[1]:string, [2]: any?} # list of {text, data} -function MenuUtil.CreateRadioMenu(dropdown, isSelected, setSelected, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateRadioContextMenu) ----@param ownerRegion Region? # if nil, defaults to UIParent ----@param isSelected fun(data: any): boolean # shared between all menu items ----@param setSelected MenuResponder # shared between all menu items ----@param ... {[1]:string, [2]: any?} # list of {text, data} ----@return MenuProxy? menu -function MenuUtil.CreateRadioContextMenu(ownerRegion, isSelected, setSelected, ...) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateEnumRadioMenu) ----@generic V ----@param dropdown DropdownButton ----@param enum table # a list of values; the value is saved as the element's data ----@param enumTranslator fun(enumValue: V): string # translate the enum value into the text to display ----@param isSelected fun(data: any): boolean # data = enum value ----@param setSelected MenuResponder ----@param orderTbl table? # optional table to specify the order of the menu buttons, defaults to ordering by enum value -function MenuUtil.CreateEnumRadioMenu(dropdown, enum, enumTranslator, isSelected, setSelected, orderTbl) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MenuUtil.CreateEnumRadioContextMenu) ----@generic V ----@param dropdown Region? # if nil, defaults to UIParent ----@param enum table # a list of values; the value is saved as the element's data ----@param enumTranslator fun(enumValue: V): string # translate the enum value into the text to display ----@param isSelected fun(data: any): boolean # data = enum value ----@param setSelected MenuResponder ----@param orderTbl table? # optional table to specify the order of the menu buttons, defaults to ordering by enum value ----@return MenuProxy? menu -function MenuUtil.CreateEnumRadioContextMenu(dropdown, enum, enumTranslator, isSelected, setSelected, orderTbl) end +---@meta _ + +---[FrameXML](https://www.townlong-yak.com/framexml/go/MenuTemplates.CreateDivider) +---@return ElementMenuDescriptionProxy # some inserters and utility functions are missing +function MenuUtil.CreateDivider() end + +---[FrameXML](https://www.townlong-yak.com/framexml/go/MenuTemplates.CreateSpacer) +---@param extend number? # height of the spacer, default = 10 +---@return ElementMenuDescriptionProxy # some inserters and utility functions are missing +function MenuUtil.CreateSpacer(extend) end + diff --git a/WoW-API/FrameXML/Blizzard_NamePlates/Blizzard_NamePlates.lua b/WoW-API/FrameXML/Blizzard_NamePlates/Blizzard_NamePlates.lua index 1b94f4c..f10dc19 100644 --- a/WoW-API/FrameXML/Blizzard_NamePlates/Blizzard_NamePlates.lua +++ b/WoW-API/FrameXML/Blizzard_NamePlates/Blizzard_NamePlates.lua @@ -6,30 +6,6 @@ ---@class NamePlateBaseMixin local NamePlateBaseMixin = {} ----@param namePlateUnitToken string ----@param driverFrame NamePlateDriverFrame -function NamePlateBaseMixin:OnAdded(namePlateUnitToken, driverFrame) end - -function NamePlateBaseMixin:OnRemoved() end - -function NamePlateBaseMixin:OnOptionsUpdated() end - -function NamePlateBaseMixin:ApplyOffsets() end - ----@param insetWidth number ----@param insetHeight number ----@return number widthPadding ----@return number heightPadding -function NamePlateBaseMixin:GetAdditionalInsetPadding(insetWidth, insetHeight) end - ----@return number left ----@return number right ----@return number top ----@return number bottom -function NamePlateBaseMixin:GetPreferredInsets() end - -function NamePlateBaseMixin:OnSizeChanged() end - ---@class Nameplate : Frame, NamePlateBaseMixin ---@field UnitFrame Button ---@field driverFrame NamePlateDriverFrame diff --git a/WoW-API/FrameXML/Blizzard_ObjectAPI/Item.lua b/WoW-API/FrameXML/Blizzard_ObjectAPI/Item.lua index 9486db6..4c4e962 100644 --- a/WoW-API/FrameXML/Blizzard_ObjectAPI/Item.lua +++ b/WoW-API/FrameXML/Blizzard_ObjectAPI/Item.lua @@ -1,110 +1,5 @@ ---@meta _ -Item = {} - ----[Documentation](https://warcraft.wiki.gg/wiki/ItemMixin) ----@class ItemMixin -ItemMixin = {} - ----@param itemLocation ItemLocation ----@return ItemMixin -function Item:CreateFromItemLocation(itemLocation) end - ----@param bagID number ----@param slotIndex number ----@return ItemMixin -function Item:CreateFromBagAndSlot(bagID, slotIndex) end - ----@param equipmentSlotIndex number ----@return ItemMixin -function Item:CreateFromEquipmentSlot(equipmentSlotIndex) end - ----@param itemLink string ----@return ItemMixin -function Item:CreateFromItemLink(itemLink) end - ----@param itemID number ----@return ItemMixin -function Item:CreateFromItemID(itemID) end - ----@param itemLocation ItemLocation -function ItemMixin:SetItemLocation(itemLocation) end - ----@param itemLink string -function ItemMixin:SetItemLink(itemLink) end - ----@param itemID number -function ItemMixin:SetItemID(itemID) end - ----@return ItemLocation -function ItemMixin:GetItemLocation() end - ----@return boolean -function ItemMixin:HasItemLocation() end - -function ItemMixin:Clear() end - ----@return boolean -function ItemMixin:IsItemEmpty() end - ----@return string|number -function ItemMixin:GetStaticBackingItem() end - ----@return boolean -function ItemMixin:IsItemInPlayersControl() end - --- Item API ----@return number -function ItemMixin:GetItemID() end - ----@return boolean -function ItemMixin:IsItemLocked() end - -function ItemMixin:LockItem() end - -function ItemMixin:UnlockItem() end - ----@return number -function ItemMixin:GetItemIcon() end - ----@return string -function ItemMixin:GetItemName() end - ----@return string -function ItemMixin:GetItemLink() end - ----@return Enum.ItemQuality -function ItemMixin:GetItemQuality() end - ----@return number -function ItemMixin:GetCurrentItemLevel() end - ----@return table -function ItemMixin:GetItemQualityColor() end - ----@return Enum.InventoryType -function ItemMixin:GetInventoryType() end - ----@return string -function ItemMixin:GetItemGUID() end - ----@return string -function ItemMixin:GetInventoryTypeName() end - ----@return boolean -function ItemMixin:IsItemDataCached() end - ----@return boolean -function ItemMixin:IsDataEvictable() end - ---@return number function ItemMixin:GetStackCount() end ---- Add a callback to be executed when item data is loaded, if the item data is already loaded then execute it immediately ----@param callbackFunction function -function ItemMixin:ContinueOnItemLoad(callbackFunction) end - ---- Same as ContinueOnItemLoad, except it returns a function that when called will cancel the continue ----@param callbackFunction function ----@return function -function ItemMixin:ContinueWithCancelOnItemLoad(callbackFunction) end diff --git a/WoW-API/FrameXML/Blizzard_ObjectAPI/ItemLocation.lua b/WoW-API/FrameXML/Blizzard_ObjectAPI/ItemLocation.lua index 20c86d5..794cadd 100644 --- a/WoW-API/FrameXML/Blizzard_ObjectAPI/ItemLocation.lua +++ b/WoW-API/FrameXML/Blizzard_ObjectAPI/ItemLocation.lua @@ -1,7 +1,5 @@ ---@meta _ -ItemLocation = {} - ---@class ItemLocation : ItemLocationData, ItemLocationMixin ---@class ItemLocationData @@ -9,59 +7,3 @@ ItemLocation = {} ---@field bagID? number ---@field slotIndex? number ----@class ItemLocationMixin ----[Documentation](https://warcraft.wiki.gg/wiki/ItemLocationMixin) -ItemLocationMixin = {} - ----@return ItemLocation -function ItemLocation:CreateEmpty() end - ----@param bagID number ----@param slotIndex number ----@return ItemLocation -function ItemLocation:CreateFromBagAndSlot(bagID, slotIndex) end - ----@param equipmentSlotIndex number ----@return ItemLocation -function ItemLocation:CreateFromEquipmentSlot(equipmentSlotIndex) end - -function ItemLocationMixin:Clear() end - ----@param bagID number ----@param slotIndex number -function ItemLocationMixin:SetBagAndSlot(bagID, slotIndex) end - ----@return number bagID ----@return number slotIndex -function ItemLocationMixin:GetBagAndSlot() end - ----@param equipmentSlotIndex number -function ItemLocationMixin:SetEquipmentSlot(equipmentSlotIndex) end - ----@return number -function ItemLocationMixin:GetEquipmentSlot() end - ----@return boolean -function ItemLocationMixin:IsEquipmentSlot() end - ----@return boolean -function ItemLocationMixin:IsBagAndSlot() end - ----@return boolean -function ItemLocationMixin:HasAnyLocation() end - ----@return boolean -function ItemLocationMixin:IsValid() end - ----@param otherBagID number ----@param otherSlotIndex number ----@return boolean -function ItemLocationMixin:IsEqualToBagAndSlot(otherBagID, otherSlotIndex) end - ----@param otherEquipmentSlotIndex number ----@return boolean -function ItemLocationMixin:IsEqualToEquipmentSlot(otherEquipmentSlotIndex) end - ----@param otherItemLocation ItemLocation ----@return boolean -function ItemLocationMixin:IsEqualTo(otherItemLocation) end diff --git a/WoW-API/FrameXML/Blizzard_ObjectAPI/PlayerLocation.lua b/WoW-API/FrameXML/Blizzard_ObjectAPI/PlayerLocation.lua deleted file mode 100644 index daae734..0000000 --- a/WoW-API/FrameXML/Blizzard_ObjectAPI/PlayerLocation.lua +++ /dev/null @@ -1,159 +0,0 @@ ----@meta _ - -PlayerLocation = {} - ----[Documentation](https://warcraft.wiki.gg/wiki/PlayerLocationMixin) ----@class PlayerLocationMixin ----@field unit? UnitId ----@field chatLineID? number ----@field guid? string ----@field SetGUID? function ----@field IsValid? function ----@field IsGUID? function ----@field IsBattleNetGUID? function ----@field GetGUID? function ----@field SetUnit? function ----@field IsUnit? function ----@field GetUnit? function ----@field SetChatLineID? function ----@field IsChatLineID? function ----@field GetChatLineID? function ----@field SetBattlefieldScoreIndex? function ----@field IsBattlefieldScoreIndex? function ----@field GetBattlefieldScoreIndex? function ----@field SetVoiceID? function ----@field IsVoiceID? function ----@field GetVoiceID? function ----@field SetBattleNetID? function ----@field IsBattleNetID? function ----@field GetBattleNetID? function ----@field SetCommunityData? function ----@field IsCommunityData? function ----@field SetCommunityInvitation? function ----@field IsCommunityInvitation? function ----@field Clear? function ----@field ClearAndSetField? function -PlayerLocationMixin = {} - ----@param guid string ----@return PlayerLocationMixin -function PlayerLocation:CreateFromGUID(guid) end - ----@param unit string ----@return PlayerLocationMixin -function PlayerLocation:CreateFromUnit(unit) end - ----@param lineID number ----@return PlayerLocationMixin -function PlayerLocation:CreateFromChatLineID(lineID) end - ----@param clubID string ----@param streamID string ----@param epoch number ----@param position number ----@return PlayerLocationMixin -function PlayerLocation:CreateFromCommunityChatData(clubID, streamID, epoch, position) end - ----@param clubID string ----@param guid string ----@return PlayerLocationMixin -function PlayerLocation:CreateFromCommunityInvitation(clubID, guid) end - ----@param battlefieldScoreIndex number ----@return PlayerLocationMixin -function PlayerLocation:CreateFromBattlefieldScoreIndex(battlefieldScoreIndex) end - ----@param memberID number ----@param channelID number ----@return PlayerLocationMixin -function PlayerLocation:CreateFromVoiceID(memberID, channelID) end - ----@param battleNetID number ----@return PlayerLocationMixin -function PlayerLocation:CreateFromBattleNetID(battleNetID) end - ---[[public api]] ----@param guid string -function PlayerLocationMixin:SetGUID(guid) end - ----@return boolean -function PlayerLocationMixin:IsValid() end - ----@return boolean -function PlayerLocationMixin:IsGUID() end - ----@return boolean -function PlayerLocationMixin:IsBattleNetGUID() end - ----@return string -function PlayerLocationMixin:GetGUID() end - ----@param unit string -function PlayerLocationMixin:SetUnit(unit) end - ----@return boolean -function PlayerLocationMixin:IsUnit() end - ----@return string -function PlayerLocationMixin:GetUnit() end - ----@param lineID number -function PlayerLocationMixin:SetChatLineID(lineID) end - ----@return boolean -function PlayerLocationMixin:IsChatLineID() end - ----@return number -function PlayerLocationMixin:GetChatLineID() end - ----@param index number -function PlayerLocationMixin:SetBattlefieldScoreIndex(index) end - ----@return boolean -function PlayerLocationMixin:IsBattlefieldScoreIndex() end - ----@return number -function PlayerLocationMixin:GetBattlefieldScoreIndex() end - ----@param memberID number ----@param channelID number -function PlayerLocationMixin:SetVoiceID(memberID, channelID) end - ----@return boolean -function PlayerLocationMixin:IsVoiceID() end - ----@return number voiceMemberID ----@return number voiceChannelID -function PlayerLocationMixin:GetVoiceID() end - ----@param battleNetID number -function PlayerLocationMixin:SetBattleNetID(battleNetID) end - ----@return boolean -function PlayerLocationMixin:IsBattleNetID() end - ----@return number -function PlayerLocationMixin:GetBattleNetID() end - ----@param clubID string ----@param streamID string ----@param epoch number ----@param position number -function PlayerLocationMixin:SetCommunityData(clubID, streamID, epoch, position) end - ----@return boolean -function PlayerLocationMixin:IsCommunityData() end - ----@param clubID string ----@param guid string -function PlayerLocationMixin:SetCommunityInvitation(clubID, guid) end - ----@return boolean -function PlayerLocationMixin:IsCommunityInvitation() end - ---[[private api]] -function PlayerLocationMixin:Clear() end - ----@param fieldName string ----@param field any -function PlayerLocationMixin:ClearAndSetField(fieldName, field) end diff --git a/WoW-API/FrameXML/Blizzard_ObjectAPI/Spell.lua b/WoW-API/FrameXML/Blizzard_ObjectAPI/Spell.lua deleted file mode 100644 index 6792419..0000000 --- a/WoW-API/FrameXML/Blizzard_ObjectAPI/Spell.lua +++ /dev/null @@ -1,43 +0,0 @@ ----@meta _ - -Spell = {} - ----[Documentation](https://warcraft.wiki.gg/wiki/SpellMixin) ----@class SpellMixin -SpellMixin = {} - ----@param spellID number ----@return SpellMixin -function Spell:CreateFromSpellID(spellID) end - ----@param spellID number -function SpellMixin:SetSpellID(spellID) end - ----@return number -function SpellMixin:GetSpellID() end - -function SpellMixin:Clear() end - ----@return boolean -function SpellMixin:IsSpellEmpty() end - ----@return boolean -function SpellMixin:IsSpellDataCached() end - ----@return string -function SpellMixin:GetSpellName() end - ----@return string -function SpellMixin:GetSpellSubtext() end - ----@return string -function SpellMixin:GetSpellDescription() end - --- Add a callback to be executed when spell data is loaded, if the spell data is already loaded then execute it immediately ----@param callbackFunction function -function SpellMixin:ContinueOnSpellLoad(callbackFunction) end - --- Same as ContinueOnSpellLoad, except it returns a function that when called will cancel the continue ----@param callbackFunction function ----@return function -function SpellMixin:ContinueWithCancelOnSpellLoad(callbackFunction) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/Backdrop.lua b/WoW-API/FrameXML/Blizzard_SharedXML/Backdrop.lua index b6e7d99..c590d8e 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/Backdrop.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/Backdrop.lua @@ -20,67 +20,3 @@ local BackdropTemplateMixin = {} _G.BackdropTemplateMixin = BackdropTemplateMixin ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:OnBackdropLoaded) -function BackdropTemplateMixin:OnBackdropLoaded() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:OnBackdropSizeChanged) -function BackdropTemplateMixin:OnBackdropSizeChanged() end - ----@return number ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetEdgeSize) -function BackdropTemplateMixin:GetEdgeSize() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetupTextureCoordinates) -function BackdropTemplateMixin:SetupTextureCoordinates() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetupPieceVisuals) -function BackdropTemplateMixin:SetupPieceVisuals(piece, setupInfo, pieceLayout) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBorderBlendMode) -function BackdropTemplateMixin:SetBorderBlendMode(blendMode) end - ----@param backdropInfo backdropInfo ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:HasBackdropInfo) -function BackdropTemplateMixin:HasBackdropInfo(backdropInfo) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:ClearBackdrop) -function BackdropTemplateMixin:ClearBackdrop() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:ApplyBackdrop) -function BackdropTemplateMixin:ApplyBackdrop() end - ----@param backdropInfo backdropInfo ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBackdrop) -function BackdropTemplateMixin:SetBackdrop(backdropInfo) end - ----@return backdropInfo ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetBackdrop) -function BackdropTemplateMixin:GetBackdrop() end - ----@return number r Returns nil if `self.backdropInfo` is not defined ----@return number g ----@return number b ----@return number a ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetBackdropColor) -function BackdropTemplateMixin:GetBackdropColor() end - ----@param r number ----@param g number ----@param b number ----@param a? number ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBackdropColor) -function BackdropTemplateMixin:SetBackdropColor(r, g, b, a) end - ----@return number r Returns nil if `self.backdropInfo` is not defined ----@return number g ----@return number b ----@return number a ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetBackdropBorderColor) -function BackdropTemplateMixin:GetBackdropBorderColor() end - ----@param r number ----@param g number ----@param b number ----@param a? number ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBackdropBorderColor) -function BackdropTemplateMixin:SetBackdropBorderColor(r, g, b, a) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/CallbackRegistry.lua b/WoW-API/FrameXML/Blizzard_SharedXML/CallbackRegistry.lua deleted file mode 100644 index d92522d..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/CallbackRegistry.lua +++ /dev/null @@ -1,39 +0,0 @@ ----@meta _ - ----@class CallbackRegistryMixin -CallbackRegistryMixin = {} - -function CallbackRegistryMixin:SetUndefinedEventsAllowed(allowed) end - ----@return table -function CallbackRegistryMixin:GetCallbackTables() end - ----@return table -function CallbackRegistryMixin:GetCallbackTable(callbackType) end - ----@return table -function CallbackRegistryMixin:GetCallbacksByEvent(callbackType, event) end - ----@return boolean -function CallbackRegistryMixin:HasRegistrantsForEvent(event) end - -function CallbackRegistryMixin:SecureInsertEvent(event) end - ----@return any owner -function CallbackRegistryMixin:RegisterCallback(event, func, owner, ...) end - ----@return table -function CallbackRegistryMixin:RegisterCallbackWithHandle(event, func, owner, ...) end - -function CallbackRegistryMixin:TriggerEvent(event, ...) end - -function CallbackRegistryMixin:UnregisterCallback(event, owner) end - -function CallbackRegistryMixin:UnregisterEvents(eventTable) end - -function CallbackRegistryMixin:GenerateCallbackEvents(events) end - ----@return boolean -function CallbackRegistryMixin.DoesFrameHaveEvent(frame, event) end - -function CallbackRegistryMixin:OnLoad() end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/Color.lua b/WoW-API/FrameXML/Blizzard_SharedXML/Color.lua index 67b5cc4..9f32e21 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/Color.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/Color.lua @@ -1,88 +1,14 @@ ----@meta _ - ----@class ColorRGBData ----@field r number ----@field g number ----@field b number ----@field colorStr? string - ----@class ColorRGBAData : ColorRGBData ----@field a number - ----@class colorRGB : ColorRGBData, ColorMixin ----@class colorRGBA : ColorRGBAData, colorRGB - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin) ----@class ColorMixin -ColorMixin = {} - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateColor) ----@param r number ----@param g number ----@param b number ----@param a? number ----@return colorRGBA -function CreateColor(r, g, b, a) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:IsEqualTo) ----@param otherColor colorRGBA ----@return boolean -function ColorMixin:IsEqualTo(otherColor) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:GetRGB) ----@return number r ----@return number g ----@return number b -function ColorMixin:GetRGB() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:GetRGBAsBytes) ----@return number r ----@return number g ----@return number b -function ColorMixin:GetRGBAsBytes() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:GetRGBA) ----@return number r ----@return number g ----@return number b ----@return number? a -function ColorMixin:GetRGBA() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:GetRGBAAsBytes) ----@return number r ----@return number g ----@return number b ----@return number? a -function ColorMixin:GetRGBAAsBytes() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:SetRGBA) ----@param r number ----@param g number ----@param b number ----@param a? number -function ColorMixin:SetRGBA(r, g, b, a) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:SetRGB) ----@param r number ----@param g number ----@param b number -function ColorMixin:SetRGB(r, g, b) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:GenerateHexColor) ----@return string -function ColorMixin:GenerateHexColor() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:GenerateHexColorMarkup) ----@return string -function ColorMixin:GenerateHexColorMarkup() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin:WrapTextInColorCode) ----@param text string ----@return string -function ColorMixin:WrapTextInColorCode(text) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/WrapTextInColorCode) ----@param text string ----@param colorHexString string ----@return string -function WrapTextInColorCode(text, colorHexString) end +---@meta _ + +---@class ColorRGBData +---@field r number +---@field g number +---@field b number +---@field colorStr? string + +---@class ColorRGBAData : ColorRGBData +---@field a number + +---@class colorRGB : ColorRGBData, ColorMixin +---@class colorRGBA : ColorRGBAData, colorRGB + diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/ColorUtil.lua b/WoW-API/FrameXML/Blizzard_SharedXML/ColorUtil.lua deleted file mode 100644 index 7979e14..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/ColorUtil.lua +++ /dev/null @@ -1,44 +0,0 @@ ----@meta _ - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateColorFromHexString) ----@param hexColor string ----@return colorRGBA -function CreateColorFromHexString(hexColor) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateColorFromBytes) ----@param r number ----@param g number ----@param b number ----@param a number ----@return colorRGBA -function CreateColorFromBytes(r, g, b, a) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/AreColorsEqual) ----@param left colorRGBA ----@param right colorRGBA ----@return boolean -function AreColorsEqual(left, right) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetClassColor) ----@param classFilename ClassFile ----@return number r ----@return number g ----@return number b ----@return string colorStr -function GetClassColor(classFilename) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetClassColorObj) ----@param classFilename string ----@return colorRGB -function GetClassColorObj(classFilename) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetClassColoredTextForUnit) ----@param unit string ----@param text string ----@return string -function GetClassColoredTextForUnit(unit, text) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetFactionColor) ----@param factionGroupTag string ----@return colorRGBA -function GetFactionColor(factionGroupTag) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/CvarUtil.lua b/WoW-API/FrameXML/Blizzard_SharedXML/CvarUtil.lua deleted file mode 100644 index 2017b41..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/CvarUtil.lua +++ /dev/null @@ -1,63 +0,0 @@ ----@meta _ - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.RegisterCVar) ----@param name CVar ----@param value? string -function RegisterCVar(name, value) - C_CVar.RegisterCVar(name, value); -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.ResetTestCVars) -function ResetTestCvars() - C_CVar.ResetTestCVars(); -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.SetCVar) ----@param name CVar ----@param value? boolean|string|number ----@return boolean success -function SetCVar(name, value) - if type(value) == "boolean" then - return C_CVar.SetCVar(name, value and "1" or "0"); - else - return C_CVar.SetCVar(name, value and tostring(value) or nil); - end -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.GetCVar) ----@param name CVar ----@return string? value -function GetCVar(name) - return C_CVar.GetCVar(name); -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.SetCVarBitfield) ----@param name CVar ----@param index number ----@param value boolean ----@return boolean success -function SetCVarBitfield(name, index, value) - return C_CVar.SetCVarBitfield(name, index, value); -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.GetCVarBitfield) ----@param name CVar ----@param index number ----@return boolean? value -function GetCVarBitfield(name, index) - return C_CVar.GetCVarBitfield(name, index); -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.GetCVarBool) ----@param name CVar ----@return boolean? value -function GetCVarBool(name) - return C_CVar.GetCVarBool(name); -end - ----[Documentation](https://warcraft.wiki.gg/wiki/API_C_CVar.GetCVarDefault) ----@param name CVar ----@return string? defaultValue -function GetCVarDefault(name) - return C_CVar.GetCVarDefault(name); -end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/Dump.lua b/WoW-API/FrameXML/Blizzard_SharedXML/Dump.lua deleted file mode 100644 index fdc84de..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/Dump.lua +++ /dev/null @@ -1,6 +0,0 @@ ----@meta _ - ----[FrameXML](https://www.townlong-yak.com/framexml/go/DevTools_Dump) ----@param value any ----@param startKey? string -function DevTools_Dump(value, startKey) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/FormattingUtil.lua b/WoW-API/FrameXML/Blizzard_SharedXML/FormattingUtil.lua deleted file mode 100644 index de7ea7d..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/FormattingUtil.lua +++ /dev/null @@ -1,73 +0,0 @@ ----@meta _ - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SplitTextIntoLines) ----@param text string ----@param delimiter string ----@return string[] -function SplitTextIntoLines(text, delimiter) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SplitTextIntoHeaderAndNonHeader) ----@param text string ----@return string? header ----@return string? nonHeader -function SplitTextIntoHeaderAndNonHeader(text) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FormatValueWithSign) ----@param value number ----@return string -function FormatValueWithSign(value) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FormatLargeNumber) ----@param amount string|number ----@return string -function FormatLargeNumber(amount) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetMoneyString) ----@param money number ----@param separateThousands? boolean ----@return string -function GetMoneyString(money, separateThousands) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FormatPercentage) ----@param percentage number ----@param roundToNearestInteger? boolean ----@return string -function FormatPercentage(percentage, roundToNearestInteger) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FormatFraction) ----@param numerator number ----@param denominator number ----@return string -function FormatFraction(numerator, denominator) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetHighlightedNumberDifferenceString) ----@param baseString string ----@param newString string ----@return string -function GetHighlightedNumberDifferenceString(baseString, newString) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FormatUnreadMailTooltip) ----@param tooltip GameTooltip ----@param headerText string ----@param senders string[] -function FormatUnreadMailTooltip(tooltip, headerText, senders) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetCurrencyString) ----@param currencyID number ----@param overrideAmount? number ----@param colorCode? string ----@param abbreviate? boolean ----@return string -function GetCurrencyString(currencyID, overrideAmount, colorCode, abbreviate) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetCurrenciesString) ----@param currencies number[] | table[] an array of currencyIDs, or a table with e.g. `{currencyID=x, amount=y} ` ----@return string -function GetCurrenciesString(currencies) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ReplaceGenderTokens) ---- This is a very simple parser that will only handle $G/$g tokens ----@param string string ----@param gender string ----@return string -function ReplaceGenderTokens(string, gender) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/GlobalCallbackRegistry.lua b/WoW-API/FrameXML/Blizzard_SharedXML/GlobalCallbackRegistry.lua index 6073014..d212896 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/GlobalCallbackRegistry.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/GlobalCallbackRegistry.lua @@ -5,26 +5,3 @@ EventRegistry = CreateFromMixins(CallbackRegistryMixin) -- function EventRegistry:OnLoad() end ----@param frameEvent FrameEvent ----@param value number -function EventRegistry:OnAttributeChanged(frameEvent, value) end - ----@param frameEvent FrameEvent -function EventRegistry:RegisterFrameEvent(frameEvent) end - ----@param frameEvent FrameEvent -function EventRegistry:UnregisterFrameEvent(frameEvent) end - ----@param frameEvent FrameEvent ----@return any owner -function EventRegistry:RegisterFrameEventAndCallback(frameEvent, ...) end - ----@param frameEvent FrameEvent ----@return table -function EventRegistry:RegisterFrameEventAndCallbackWithHandle(frameEvent, ...) end - ----@param frameEvent FrameEvent -function EventRegistry:UnregisterFrameEventAndCallback(frameEvent, ...) end - ----@return string -function EventRegistry:GetEventCounts(...) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/Mixin.lua b/WoW-API/FrameXML/Blizzard_SharedXML/Mixin.lua index bfcf536..5560629 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/Mixin.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/Mixin.lua @@ -26,14 +26,3 @@ function CreateFromMixins(mixin, ...) return Mixin({}, mixin, ...) end ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateAndInitFromMixin) ---- Copies mixins into a new object and initializes it ----@generic T ----@param mixin T ----@param ... any ----@return T mixin -function CreateAndInitFromMixin(mixin, ...) - local object = CreateFromMixins(mixin); - object:Init(...); - return object; -end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/TableUtil.lua b/WoW-API/FrameXML/Blizzard_SharedXML/TableUtil.lua index de83440..050d24a 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/TableUtil.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/TableUtil.lua @@ -20,160 +20,6 @@ function ripairs(table) return ripairsiter, table, #table + 1; end ----[FrameXML](https://www.townlong-yak.com/framexml/go/tDeleteItem) --- Removes a value from a sequential table. ----@param tbl table ----@param item any -function tDeleteItem(tbl, item) - local index = 1; - while tbl[index] do - if ( item == tbl[index] ) then - tremove(tbl, index); - else - index = index + 1; - end - end -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tIndexOf) --- Returns the index for a value in a table. ----@param tbl table ----@param item any ----@return number? index -function tIndexOf(tbl, item) - for i, v in ipairs(tbl) do - if item == v then - return i; - end - end -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tContains) --- Returns true if a table contains a value. ----@param tbl table ----@param item any ----@return boolean -function tContains(tbl, item) - for k, v in pairs(tbl) do - if item == v then - return true; - end - end - return false; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tCompare) --- This is a deep compare on the values of the table (based on depth) but not a deep comparison --- of the keys, as this would be an expensive check and won't be necessary in most cases. ----@param lhsTable table ----@param rhsTable table ----@param depth? number ----@return boolean -function tCompare(lhsTable, rhsTable, depth) - depth = depth or 1; - for key, value in pairs(lhsTable) do - if type(value) == "table" then - local rhsValue = rhsTable[key]; - if type(rhsValue) ~= "table" then - return false; - end - if depth > 1 then - if not tCompare(value, rhsValue, depth - 1) then - return false; - end - end - elseif value ~= rhsTable[key] then - return false; - end - end - - -- Check for any keys that are in rhsTable and not lhsTable. - for key, value in pairs(rhsTable) do - if lhsTable[key] == nil then - return false; - end - end - - return true; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tInvert) --- Returns an inverted table. ----@param tbl table ----@return table -function tInvert(tbl) - local inverted = {}; - for k, v in pairs(tbl) do - inverted[v] = k; - end - return inverted; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tFilter) ----@param tbl table ----@param pred function ----@param isIndexTable boolean ----@return table -function tFilter(tbl, pred, isIndexTable) - local out = {}; - - if (isIndexTable) then - local currentIndex = 1; - for i, v in ipairs(tbl) do - if (pred(v)) then - out[currentIndex] = v; - currentIndex = currentIndex + 1; - end - end - else - for k, v in pairs(tbl) do - if (pred(v)) then - out[k] = v; - end - end - end - - return out; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tAppendAll) --- Appends the contents of a sequential table to another table. ----@param table table ----@param addedArray table -function tAppendAll(table, addedArray) - for i, element in ipairs(addedArray) do - tinsert(table, element); - end -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/tUnorderedRemove) ----@param tbl table ----@param index number -function tUnorderedRemove(tbl, index) - if index ~= #tbl then - tbl[index] = tbl[#tbl]; - end - - table.remove(tbl); -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CopyTable) --- Returns a deep copy of a table. ----@param settings table ----@param shallow? boolean ----@return table -function CopyTable(settings, shallow) - local copy = {}; - for k, v in pairs(settings) do - if type(v) == "table" and not shallow then - copy[k] = CopyTable(v); - else - copy[k] = v; - end - end - return copy; -end - ---[FrameXML](https://www.townlong-yak.com/framexml/go/AccumulateIf) ---@param tbl table ---@param pred function @@ -188,47 +34,3 @@ function AccumulateIf(tbl, pred) return count; end ----[FrameXML](https://www.townlong-yak.com/framexml/go/ContainsIf) ----@param tbl table ----@param pred function ----@return boolean -function ContainsIf(tbl, pred) - for k, v in pairs(tbl) do - if (pred(v)) then - return true; - end - end - - return false; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FindInTableIf) ----@param tbl table ----@param pred function ----@return string|number key ----@return any value -function FindInTableIf(tbl, pred) - for k, v in pairs(tbl) do - if (pred(v)) then - return k, v; - end - end - ---@diagnostic disable-next-line: return-type-mismatch - return nil; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SafePack) ----@param ... any ----@return table -function SafePack(...) - local tbl = { ... }; - tbl.n = select("#", ...); - return tbl; -end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SafeUnpack) ----@param tbl table ----@return ... -function SafeUnpack(tbl) - return unpack(tbl, 1, tbl.n); -end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/TextureUtil.lua b/WoW-API/FrameXML/Blizzard_SharedXML/TextureUtil.lua deleted file mode 100644 index 239379c..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/TextureUtil.lua +++ /dev/null @@ -1,149 +0,0 @@ ----@meta _ - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetTextureInfo) ----@param obj Texture ----@return string assetName ----@return string assetType ----@return number ulX ----@return number ulY ----@return number blX ----@return number blY ----@return number urX ----@return number urY ----@return number brX ----@return number brY -function GetTextureInfo(obj) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SetClampedTextureRotation) ----@param texture Texture ----@param rotationDegrees number -function SetClampedTextureRotation(texture, rotationDegrees) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/ClearClampedTextureRotation) ----@param texture Texture -function ClearClampedTextureRotation(texture) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetMicroIconForRole ----@param role string ----@return string icon -function GetMicroIconForRole(role) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetTexCoordsByGrid) ----@param xOffset number ----@param yOffset number ----@param textureWidth number ----@param textureHeight number ----@param gridWidth number ----@param gridHeight number ----@return number minX ----@return number maxX ----@return number minY ----@return number maxY -function GetTexCoordsByGrid(xOffset, yOffset, textureWidth, textureHeight, gridWidth, gridHeight) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetTexCoordsForRole) ----@param role string ----@return number minX ----@return number maxX ----@return number minY ----@return number maxY -function GetTexCoordsForRole(role) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateTextureMarkup) ----@param file number|string ----@param fileWidth number ----@param fileHeight number ----@param width number ----@param height number ----@param left number ----@param right number ----@param top number ----@param bottom number ----@param xOffset? number ----@param yOffset? number ----@return string -function CreateTextureMarkup(file, fileWidth, fileHeight, width, height, left, right, top, bottom, xOffset, yOffset) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateAtlasMarkup) ----@param atlasName number|string ----@param width? number ----@param height? number ----@param offsetX? number ----@param offsetY? number ----@param rVertexColor? number ----@param gVertexColor? number ----@param bVertexColor? number ----@return string -function CreateAtlasMarkup(atlasName, width, height, offsetX, offsetY, rVertexColor, gVertexColor, bVertexColor) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateAtlasMarkupWithAtlasSize) ----@param atlasName number|string ----@param offsetX? number ----@param offsetY? number ----@param rVertexColor? number ----@param gVertexColor? number ----@param bVertexColor? number ----@return string -function CreateAtlasMarkupWithAtlasSize(atlasName, offsetX, offsetY, rVertexColor, gVertexColor, bVertexColor, scale) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SetupAtlasesOnRegions) ---- Pass in a frame and a table containing parentKeys (on frame) as keys and atlas member names as the values ----@param frame Frame ----@param regionsToAtlases table ----@param useAtlasSize? boolean -function SetupAtlasesOnRegions(frame, regionsToAtlases, useAtlasSize) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetFinalNameFromTextureKit) ----@param fmt string ----@param textureKits string|table ----@return string -function GetFinalNameFromTextureKit(fmt, textureKits) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SetupTextureKitOnFrame) ---- Pass in a TextureKit name, a frame and a formatting string. ---- The TextureKit name will be inserted into fmt (at the first %s). The resulting atlas name will be set on frame ---- Use "%s" for fmt if the TextureKit name is the entire atlas element name ----@param textureKit string|table ----@param frame Texture|StatusBar ----@param fmt string ----@param setVisibility boolean ----@param useAtlasSize? boolean -function SetupTextureKitOnFrame(textureKit, frame, fmt, setVisibility, useAtlasSize) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SetupTextureKitOnFrames) ---- Pass in a TextureKit name and a table containing frames as keys and formatting strings as values ---- For each frame key in frames, the TextureKit name will be inserted into fmt (at the first %s). The resulting atlas name will be set on frame ---- Use "%s" for fmt if the TextureKit name is the entire atlas element name ----@param textureKit string|table ----@param frames table ----@param setVisibilityOfRegions boolean ----@param useAtlasSize? boolean -function SetupTextureKitOnFrames(textureKit, frames, setVisibilityOfRegions, useAtlasSize) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SetupTextureKitOnRegions) ---- Pass in a TextureKit name, a frame and a table containing parentKeys (on frame) as keys and formatting strings as values ---- For each frame key in frames, the TextureKit name will be inserted into fmt (at the first %s). The resulting atlas name will be set on frame ---- Use "%s" for fmt if the TextureKit name is the entire atlas element name ----@param textureKit string|table ----@param frame Frame ----@param regions table ----@param setVisibilityOfRegions boolean ----@param useAtlasSize? boolean -function SetupTextureKitOnRegions(textureKit, frame, regions, setVisibilityOfRegions, useAtlasSize) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SetupTextureKitsFromRegionInfo) ---- Pass in a TextureKit name, a frame and a table containing parentKeys (on frame) as keys and a table as values ---- The values table should contain formatString as a member (setVisibility and useAtlasSize can also be added if desired) ---- For each frame key in frames, the TextureKit name will be inserted into formatString (at the first %s). The resulting atlas name will be set on frame ---- Use "%s" for formatString if the TextureKit name is the entire atlas element name ----@param textureKit string|table ----@param frame Frame ----@param regionInfoList table -function SetupTextureKitsFromRegionInfo(textureKit, frame, regionInfoList) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/GetFinalAtlasFromTextureKitIfExists) ---- Pass the texture and the textureKit, if the atlas exists in data then it will return the actual atlas name otherwise, return nil. ----@param texture string ----@param textureKit string|table ----@return string? -function GetFinalAtlasFromTextureKitIfExists(texture, textureKit) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/TimeUtil.lua b/WoW-API/FrameXML/Blizzard_SharedXML/TimeUtil.lua deleted file mode 100644 index e3eb2a3..0000000 --- a/WoW-API/FrameXML/Blizzard_SharedXML/TimeUtil.lua +++ /dev/null @@ -1,51 +0,0 @@ ----@meta _ - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SecondsToMinutes) ----@param seconds number ----@return number -function SecondsToMinutes(seconds) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MinutesToSeconds) ----@param minutes number ----@return number -function MinutesToSeconds(minutes) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/HasTimePassed) ----@param testTime number ----@param amountOfTime number ----@return boolean -function HasTimePassed(testTime, amountOfTime) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SecondsToClock) ----@param seconds number ----@param displayZeroHours? boolean ----@return string -function SecondsToClock(seconds, displayZeroHours) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SecondsToTime) ----@param seconds number ----@param noSeconds? boolean ----@param notAbbreviated? boolean ----@param maxCount? number ----@param roundUp? boolean ----@return string -function SecondsToTime(seconds, noSeconds, notAbbreviated, maxCount, roundUp) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/MinutesToTime) ----@param mins number ----@param hideDays? boolean ----@return string -function MinutesToTime(mins, hideDays) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/SecondsToTimeAbbrev) ----@param seconds number ----@return string format ----@return number time -function SecondsToTimeAbbrev(seconds) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/FormatShortDate) ----@param day number ----@param month number ----@param year number ----@return string -function FormatShortDate(day, month, year) end diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/Vector2D.lua b/WoW-API/FrameXML/Blizzard_SharedXML/Vector2D.lua index a11b804..d863eff 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/Vector2D.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/Vector2D.lua @@ -1,84 +1,6 @@ ----@meta _ - ----@class Vector2DType ----@field x number ----@field y number - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin) ----@class Vector2DMixin : Vector2DType -Vector2DMixin = {} - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateVector2D) ----@param x number ----@param y number ----@return Vector2DMixin -function CreateVector2D(x, y) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/AreVector2DEqual) ----@param left Vector2DMixin ----@param right Vector2DMixin ----@return boolean -function AreVector2DEqual(left, right) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:IsEqualTo) ----@param otherVector Vector2DMixin ----@return boolean -function Vector2DMixin:IsEqualTo(otherVector) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:GetXY) ----@return number x ----@return number y -function Vector2DMixin:GetXY() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:SetXY) ----@param x number ----@param y number -function Vector2DMixin:SetXY(x, y) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:ScaleBy) ----@param scalar number -function Vector2DMixin:ScaleBy(scalar) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:DivideBy) ----@param scalar number -function Vector2DMixin:DivideBy(scalar) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:Add) ----@param other Vector2DMixin -function Vector2DMixin:Add(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:Subtract) ----@param other Vector2DMixin -function Vector2DMixin:Subtract(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:Cross) ----@param other Vector2DMixin -function Vector2DMixin:Cross(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:Dot) ----@param other Vector2DMixin ----@return number -function Vector2DMixin:Dot(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:IsZero) ----@return boolean -function Vector2DMixin:IsZero() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:GetLengthSquared) ----@return number -function Vector2DMixin:GetLengthSquared() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:GetLength) ----@return number -function Vector2DMixin:GetLength() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:Normalize) -function Vector2DMixin:Normalize() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:RotateDirection) ----@param rotationRadians number -function Vector2DMixin:RotateDirection(rotationRadians) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin:Clone) ----@return Vector2DMixin -function Vector2DMixin:Clone() end +---@meta _ + +---@class Vector2DType +---@field x number +---@field y number + diff --git a/WoW-API/FrameXML/Blizzard_SharedXML/Vector3D.lua b/WoW-API/FrameXML/Blizzard_SharedXML/Vector3D.lua index 6cd61f6..4ce770f 100644 --- a/WoW-API/FrameXML/Blizzard_SharedXML/Vector3D.lua +++ b/WoW-API/FrameXML/Blizzard_SharedXML/Vector3D.lua @@ -1,80 +1,7 @@ ----@meta _ - ----@class Vector3DType ----@field x number ----@field y number ----@field z number - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin) ----@class Vector3DMixin : Vector3DType -Vector3DMixin = {} - ----[FrameXML](https://www.townlong-yak.com/framexml/go/CreateVector3D) ----@param x number ----@param y number ----@param z number ----@return Vector3DMixin -function CreateVector3D(x, y, z) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/AreVector3DEqual) ----@param left Vector3DMixin ----@param right Vector3DMixin ----@return boolean -function AreVector3DEqual(left, right) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:IsEqualTo) ----@param otherVector Vector3DMixin ----@return boolean -function Vector3DMixin:IsEqualTo(otherVector) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:GetXYZ) ----@return number x ----@return number y ----@return number z -function Vector3DMixin:GetXYZ() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:SetXYZ) ----@param x number ----@param y number ----@param z number -function Vector3DMixin:SetXYZ(x, y, z) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:ScaleBy) ----@param scalar number -function Vector3DMixin:ScaleBy(scalar) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:DivideBy) ----@param scalar number -function Vector3DMixin:DivideBy(scalar) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:Add) ----@param other Vector3DMixin -function Vector3DMixin:Add(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:Subtract) ----@param other Vector3DMixin -function Vector3DMixin:Subtract(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:Cross) ----@param other Vector3DMixin -function Vector3DMixin:Cross(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:Dot) ----@param other Vector3DMixin ----@return number -function Vector3DMixin:Dot(other) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:GetLengthSquared) ----@return number -function Vector3DMixin:GetLengthSquared() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:GetLength) ----@return number -function Vector3DMixin:GetLength() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:Normalize) -function Vector3DMixin:Normalize() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin:Clone) ----@return Vector3DMixin -function Vector3DMixin:Clone() end +---@meta _ + +---@class Vector3DType +---@field x number +---@field y number +---@field z number + diff --git a/WoW-API/ManualTypes/DropdownButton.lua b/WoW-API/Manual/Types/DropdownButton.lua similarity index 100% rename from WoW-API/ManualTypes/DropdownButton.lua rename to WoW-API/Manual/Types/DropdownButton.lua diff --git a/WoW-API/ManualTypes/EngravingData.lua b/WoW-API/Manual/Types/EngravingData.lua similarity index 100% rename from WoW-API/ManualTypes/EngravingData.lua rename to WoW-API/Manual/Types/EngravingData.lua diff --git a/WoW-API/ManualTypes/README.md b/WoW-API/Manual/Types/README.md similarity index 100% rename from WoW-API/ManualTypes/README.md rename to WoW-API/Manual/Types/README.md diff --git a/WoW-API/ManualTypes/ReforgeStatsInfo.lua b/WoW-API/Manual/Types/ReforgeStatsInfo.lua similarity index 100% rename from WoW-API/ManualTypes/ReforgeStatsInfo.lua rename to WoW-API/Manual/Types/ReforgeStatsInfo.lua diff --git a/WoW-API/ManualTypes/TextureWithStateVisualizationInfo.lua b/WoW-API/Manual/Types/TextureWithStateVisualizationInfo.lua similarity index 100% rename from WoW-API/ManualTypes/TextureWithStateVisualizationInfo.lua rename to WoW-API/Manual/Types/TextureWithStateVisualizationInfo.lua diff --git a/WoW-API/ManualTypes/UndefinedMixins.lua b/WoW-API/Manual/Types/UndefinedMixins.lua similarity index 100% rename from WoW-API/ManualTypes/UndefinedMixins.lua rename to WoW-API/Manual/Types/UndefinedMixins.lua diff --git a/WoW-API/ManualTypes/dstReforgeStats.lua b/WoW-API/Manual/Types/dstReforgeStats.lua similarity index 100% rename from WoW-API/ManualTypes/dstReforgeStats.lua rename to WoW-API/Manual/Types/dstReforgeStats.lua diff --git a/WoW-API/Widget/UIType/Template/Backdrop.lua b/WoW-API/Widget/UIType/Template/Backdrop.lua deleted file mode 100644 index e01600c..0000000 --- a/WoW-API/Widget/UIType/Template/Backdrop.lua +++ /dev/null @@ -1,85 +0,0 @@ ----@meta _ ----@class backdropInfo ----@field bgFile? string ----@field edgeFile? string ----@field tile? boolean ----@field tileSize? number ----@field tileEdge? boolean ----@field edgeSize? number ----@field insets? backdropInsets - ----@class backdropInsets ----@field left number ----@field right number ----@field top number ----@field bottom number - ----@class BackdropTemplate ----[Documentation](https://warcraft.wiki.gg/wiki/BackdropTemplate) -local BackdropTemplateMixin = {} -_G.BackdropTemplateMixin = BackdropTemplateMixin - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:OnBackdropLoaded) -function BackdropTemplateMixin:OnBackdropLoaded() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:OnBackdropSizeChanged) -function BackdropTemplateMixin:OnBackdropSizeChanged() end - ----@return number ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetEdgeSize) -function BackdropTemplateMixin:GetEdgeSize() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetupTextureCoordinates) -function BackdropTemplateMixin:SetupTextureCoordinates() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetupPieceVisuals) -function BackdropTemplateMixin:SetupPieceVisuals(piece, setupInfo, pieceLayout) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBorderBlendMode) -function BackdropTemplateMixin:SetBorderBlendMode(blendMode) end - ----@param backdropInfo backdropInfo ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:HasBackdropInfo) -function BackdropTemplateMixin:HasBackdropInfo(backdropInfo) end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:ClearBackdrop) -function BackdropTemplateMixin:ClearBackdrop() end - ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:ApplyBackdrop) -function BackdropTemplateMixin:ApplyBackdrop() end - ----@param backdropInfo backdropInfo ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBackdrop) -function BackdropTemplateMixin:SetBackdrop(backdropInfo) end - ----@return backdropInfo ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetBackdrop) -function BackdropTemplateMixin:GetBackdrop() end - ----@return number r Returns nil if `self.backdropInfo` is not defined ----@return number g ----@return number b ----@return number a ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetBackdropColor) -function BackdropTemplateMixin:GetBackdropColor() end - ----@param r number ----@param g number ----@param b number ----@param a? number ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBackdropColor) -function BackdropTemplateMixin:SetBackdropColor(r, g, b, a) end - ----@return number r Returns nil if `self.backdropInfo` is not defined ----@return number g ----@return number b ----@return number a ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:GetBackdropBorderColor) -function BackdropTemplateMixin:GetBackdropBorderColor() end - ----@param r number ----@param g number ----@param b number ----@param a? number ----[FrameXML](https://www.townlong-yak.com/framexml/go/BackdropTemplateMixin:SetBackdropBorderColor) -function BackdropTemplateMixin:SetBackdropBorderColor(r, g, b, a) end diff --git a/WoW-API/Widget/UIType/Template/Template.lua b/WoW-API/Widget/UIType/Template/Template.lua deleted file mode 100644 index b216570..0000000 --- a/WoW-API/Widget/UIType/Template/Template.lua +++ /dev/null @@ -1,3 +0,0 @@ ----@meta _ ----@alias Template ----|"BackdropTemplate" diff --git a/WoW-API/_UI/Blizzard_FrameXMLUtil/ItemUtil.lua b/WoW-API/_UI/Blizzard_FrameXMLUtil/ItemUtil.lua index 7b8bc44..5b04bec 100644 --- a/WoW-API/_UI/Blizzard_FrameXMLUtil/ItemUtil.lua +++ b/WoW-API/_UI/Blizzard_FrameXMLUtil/ItemUtil.lua @@ -356,6 +356,7 @@ function ItemUtil.TransformItemLocationItemsToGUIDItems(itemLocations) end ---@class ItemTransmogInfoMixin +---[Documentation](https://warcraft.wiki.gg/wiki/ItemTransmogInfoMixin) ItemTransmogInfoMixin = {}; --- See [CreateAndInitFromMixin](https://www.townlong-yak.com/framexml/go/CreateAndInitFromMixin) diff --git a/WoW-API/_UI/Blizzard_FrameXMLUtil/TransmogUtil.lua b/WoW-API/_UI/Blizzard_FrameXMLUtil/TransmogUtil.lua index e37d419..09f6b1d 100644 --- a/WoW-API/_UI/Blizzard_FrameXMLUtil/TransmogUtil.lua +++ b/WoW-API/_UI/Blizzard_FrameXMLUtil/TransmogUtil.lua @@ -319,6 +319,7 @@ function TransmogUtil.ParseOutfitSlashCommand(msg) end ---@class TransmogPendingInfoMixin +---[Documentation](https://warcraft.wiki.gg/wiki/TransmogLocationMixin) TransmogPendingInfoMixin = {}; --- See [CreateAndInitFromMixin](https://www.townlong-yak.com/framexml/go/CreateAndInitFromMixin) @@ -335,6 +336,7 @@ function TransmogPendingInfoMixin:Init(pendingType, transmogID, category) end ---@class TransmogLocationMixin +---[Documentation](https://warcraft.wiki.gg/wiki/TransmogLocationMixin) TransmogLocationMixin = {}; ---@param slotID number diff --git a/WoW-API/_UI/Blizzard_GroupFinder/LFDFrame.lua b/WoW-API/_UI/Blizzard_GroupFinder/LFDFrame.lua deleted file mode 100644 index 881b02d..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/LFDFrame.lua +++ /dev/null @@ -1,863 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ -------------------------------------- ------------LFD Frame-------------- -------------------------------------- - ---General functions -function LFDFrame_OnLoad(self) - self:RegisterEvent("PLAYER_ENTERING_WORLD"); - self:RegisterEvent("LFG_ROLE_CHECK_SHOW"); - self:RegisterEvent("LFG_ROLE_CHECK_HIDE"); - self:RegisterEvent("LFG_READY_CHECK_SHOW"); - self:RegisterEvent("LFG_READY_CHECK_HIDE"); - self:RegisterEvent("LFG_BOOT_PROPOSAL_UPDATE"); - self:RegisterEvent("VOTE_KICK_REASON_NEEDED"); - self:RegisterEvent("LFG_UPDATE_RANDOM_INFO"); - self:RegisterEvent("LFG_OPEN_FROM_GOSSIP"); - self:RegisterEvent("UPDATE_EXPANSION_LEVEL"); - self:RegisterEvent("AJ_DUNGEON_ACTION"); - - ButtonFrameTemplate_HideAttic(self); - self.Inset:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 2, 284); - self.Inset:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -2, 26); - - local view = CreateScrollBoxListLinearView(); - view:SetElementInitializer("LFDFrameDungeonChoiceTemplate", function(button, elementData) - LFDQueueFrameSpecificList_InitButton(button, elementData); - end); - ScrollUtil.InitScrollBoxListWithScrollBar(LFDQueueFrame.Specific.ScrollBox, LFDQueueFrame.Specific.ScrollBar, view); -end - -function LFDFrame_OnEvent(self, event, ...) - if ( event == "LFG_ROLE_CHECK_SHOW" ) then - local requeue = ...; - LFDRoleCheckPopup.Text:SetText(requeue and REQUEUE_CONFIRM_YOUR_ROLE or CONFIRM_YOUR_ROLE); - LFDRoleCheckPopup_Update(); - - StaticPopupSpecial_Show(LFDRoleCheckPopup); - LFDQueueFrameSpecificList_Update(); - elseif ( event == "LFG_ROLE_CHECK_HIDE" ) then - StaticPopupSpecial_Hide(LFDRoleCheckPopup); - LFDQueueFrameSpecificList_Update(); - elseif ( event == "LFG_READY_CHECK_SHOW" ) then - local _, readyCheckBgQueue = GetLFGReadyCheckUpdate(); - local displayName; - if ( readyCheckBgQueue ) then - displayName = GetLFGReadyCheckUpdateBattlegroundInfo(); - else - displayName = UNKNOWN; - end - LFDReadyCheckPopup.Text:SetFormattedText(CONFIRM_YOU_ARE_READY, displayName); - StaticPopupSpecial_Show(LFDReadyCheckPopup); - elseif ( event == "LFG_READY_CHECK_HIDE" ) then - StaticPopupSpecial_Hide(LFDReadyCheckPopup); - elseif ( event == "LFG_BOOT_PROPOSAL_UPDATE" ) then - local voteInProgress, didVote, myVote, targetName, totalVotes, bootVotes, timeLeft, reason = GetLFGBootProposal(); - if ( voteInProgress and not didVote and targetName ) then - if (reason and reason ~= "") then - StaticPopupDialogs["VOTE_BOOT_PLAYER"].text = VOTE_BOOT_PLAYER; - else - StaticPopupDialogs["VOTE_BOOT_PLAYER"].text = VOTE_BOOT_PLAYER_NO_REASON; - end - -- Person who started the vote voted yes, the person being voted against voted no, so weve seen this before if we have more than 2 votes. - StaticPopup_Show("VOTE_BOOT_PLAYER", targetName, reason, totalVotes > 2 ); - else - StaticPopup_Hide("VOTE_BOOT_PLAYER"); - end - elseif ( event == "VOTE_KICK_REASON_NEEDED" ) then - local targetName, targetGUID = ...; - StaticPopup_Show("VOTE_BOOT_REASON_REQUIRED", targetName, nil, targetGUID); - elseif ( event == "LFG_UPDATE_RANDOM_INFO" ) then - if C_PlayerInfo.IsPlayerNPERestricted() then - -- if the player is NPE restricted, we need to default to specific dungeons - -- for a cleaner tutorial experience - LFDQueueFrame_SetType("specific"); - else - if ( not LFDQueueFrame.type or (type(LFDQueueFrame.type) == "number" and not IsLFGDungeonJoinable(LFDQueueFrame.type)) ) then - local bestChoice = GetRandomDungeonBestChoice(); - if ( bestChoice ) then - LFDQueueFrame_SetType(bestChoice); - end - end - --If we still don't have a value, we should go to specific. - if ( not LFDQueueFrame.type ) then - LFDQueueFrame_SetType("specific"); - end - end - elseif ( event == "LFG_OPEN_FROM_GOSSIP" ) then - local dungeonID = ...; - LFDFrame_DisplayDungeonByID(dungeonID); - PVEFrame_ShowFrame("GroupFinderFrame", LFDParentFrame); - elseif ( event == "UPDATE_EXPANSION_LEVEL" ) then - EXPANSION_LEVEL = GetExpansionLevel(); - elseif ( event == "AJ_DUNGEON_ACTION" ) then - local id = ...; - if ( id ) then - LFDFrame_DisplayDungeonByID(id); - local categoryID = DungeonAppearsInRandomLFD(id); - if ( categoryID ~= LE_LFG_CATEGORY_LFD ) then - LFGDungeonList_DisableEntries(); - LFGDungeonList_SetDungeonEnabled(id, true); - LFGListUpdateHeaderEnabledAndLockedStates(LFDDungeonList, LFGEnabledList, LFDHiddenByCollapseList); - end - end - PVEFrame_ShowFrame("GroupFinderFrame", LFDParentFrame); - end -end - -function LFDFrame_OnShow(self) - LFGBackfillCover_Update(LFDQueueFrame.PartyBackfill, true); -end - -function LFDFrame_DisplayDungeonByID(dungeonID) - if ( DungeonAppearsInRandomLFD(dungeonID) ) then - LFDQueueFrame_SetType(dungeonID); - else - LFDQueueFrame_SetType("specific"); - end -end - ---Role-related functions - -function LFDQueueFrame_SetRoles() - SetLFGRoles(LFGRole_GetChecked(LFDQueueFrameRoleButtonLeader), - LFGRole_GetChecked(LFDQueueFrameRoleButtonTank), - LFGRole_GetChecked(LFDQueueFrameRoleButtonHealer), - LFGRole_GetChecked(LFDQueueFrameRoleButtonDPS)); -end - -function LFDQueueFrame_GetRoles() - return LFGRole_GetChecked(LFDQueueFrameRoleButtonLeader), - LFGRole_GetChecked(LFDQueueFrameRoleButtonTank), - LFGRole_GetChecked(LFDQueueFrameRoleButtonHealer), - LFGRole_GetChecked(LFDQueueFrameRoleButtonDPS); -end - -function LFDFrameRoleCheckButton_OnClick(self) - LFDQueueFrame_SetRoles(); - LFDQueueFrameFindGroupButton_Update(); - LFDQueueFrameRandom_UpdateFrame(); --We may show or hide shortage rewards. -end - -function LFDQueueFrame_UpdateRoleButtons() - local dungeonID = LFDQueueFrame.type; - LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonTank, nil); - LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonHealer, nil); - LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonDPS, nil); - - local tankLocked, healerLocked, dpsLocked; - local restrictedRoles = {[1]={count=0, alert=false}, -- tank - [2]={count=0, alert=false}, -- healer - [3]={count=0, alert=false}} -- dps - if ( type(dungeonID) == "number" ) then - tankLocked, healerLocked, dpsLocked = GetLFDRoleRestrictions(dungeonID); - if ( not IsInGroup(LE_PARTY_CATEGORY_HOME) ) then - for i=1, LFG_ROLE_NUM_SHORTAGE_TYPES do - local eligible, forTank, forHealer, forDamage, itemCount, money, xp = GetLFGRoleShortageRewards(dungeonID, i); - if ( eligible and (itemCount ~= 0 or money ~= 0 or xp ~= 0) ) then --Only show the icon if there is actually a reward. - if ( forTank ) then - LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonTank, i); - end - if ( forHealer ) then - LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonHealer, i); - end - if ( forDamage ) then - LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonDPS, i); - end - end - end - end - elseif( dungeonID == "specific" and LFDDungeonList and LFGEnabledList )then - -- count the number of dungeons a role is locked - local dungeonCount = 0; - for _, id in ipairs(LFDDungeonList) do - local isChecked = LFGEnabledList[id]; - if isChecked and not LFGIsIDHeader(id) then - tankLocked, healerLocked, dpsLocked = GetLFDRoleRestrictions(id); - restrictedRoles[1].count = restrictedRoles[1].count + ((tankLocked and 1) or 0); - restrictedRoles[2].count = restrictedRoles[2].count + ((healerLocked and 1) or 0); - restrictedRoles[3].count = restrictedRoles[3].count + ((dpsLocked and 1) or 0); - dungeonCount = dungeonCount + 1; - end - end - if( dungeonCount > 0 ) then - tankLocked = restrictedRoles[1].count == dungeonCount; - healerLocked = restrictedRoles[2].count == dungeonCount; - dpsLocked = restrictedRoles[3].count == dungeonCount; - end - restrictedRoles[1].alert = not tankLocked and restrictedRoles[1].count > 0; - restrictedRoles[2].alert = not healerLocked and restrictedRoles[2].count > 0; - restrictedRoles[3].alert = not dpsLocked and restrictedRoles[3].count > 0; - end - - LFDQueueFrame_UpdateRoleButton(LFDQueueFrameRoleButtonTank, tankLocked, restrictedRoles[1].alert); - LFDQueueFrame_UpdateRoleButton(LFDQueueFrameRoleButtonHealer, healerLocked, restrictedRoles[2].alert); - LFDQueueFrame_UpdateRoleButton(LFDQueueFrameRoleButtonDPS, dpsLocked, restrictedRoles[3].alert); - - LFDQueueFrameFindGroupButton_Update(); -end - -function LFDQueueFrame_UpdateRoleButton(button, locked, alert) - if( button.permDisabled )then - return; - end - - if( locked ) then - button.lockedIndicator:Show(); - button.checkButton:Hide(); - button.checkButton:Disable(); - button.alert:Hide(); - else - button.lockedIndicator:Hide(); - button.checkButton:Show(); - button.checkButton:Enable(); - - if( alert ) then - button.alert:Show(); - else - button.alert:Hide(); - end - end -end - ---Role-check functions -function LFDQueueCheckRoleSelectionValid(tank, healer, dps) - if not tank and not healer and not dps then - return false; - end - - if not LFDDungeonList or not LFGEnabledList then - return true; - end - - if LFDQueueFrame.type == "specific" then - for _, id in ipairs(LFDDungeonList) do - local isChecked = LFGEnabledList[id]; - if isChecked and not LFGIsIDHeader(id) then - if LFDCheckRolesRestricted( id, tank, healer, dps ) then - return false; - end - end - end - end - - return true; -end - -function LFDCheckRolesRestricted(dungeonID, tank, healer, dps) - local tankSelected, healerSelected, dpsSelected = tank, healer, dps; - local tankLocked, healerLocked, dpsLocked = GetLFDRoleRestrictions(dungeonID); - if ( tankLocked ) then - tankSelected = false; - end - if ( healerLocked ) then - healerSelected = false; - end - if ( dpsLocked ) then - dpsSelected = false; - end - - return not tankSelected and not healerSelected and not dpsSelected; -end - -function LFDPopupRoleCheckButton_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(_G["ROLE_DESCRIPTION_"..self.role], nil, nil, nil, nil, true); - if ( self.permDisabled ) then - if(self.permDisabledTip)then - GameTooltip:AddLine(self.permDisabledTip, 1, 0, 0, true); - end - elseif ( self.disabledTooltip and not self:IsEnabled() ) then - GameTooltip:AddLine(self.disabledTooltip, 1, 0, 0, true); - elseif ( not self:IsEnabled() ) then - local dungeonID = LFDQueueFrame.type; - local roleID = self:GetID(); - GameTooltip:SetText(ERR_ROLE_UNAVAILABLE, 1.0, 1.0, 1.0); - local reasons = GetLFGInviteRoleRestrictions(roleID); - for i = 1, #reasons do - local text = _G["INSTANCE_UNAVAILABLE_SELF_"..(LFG_INSTANCE_INVALID_CODES[reasons[i]] or "OTHER")]; - if( text ) then - GameTooltip:AddLine(text); - end - end - GameTooltip:Show(); - return; - elseif( self.alert:IsShown() ) then - GameTooltip:SetText(INSTANCE_ROLE_WARNING_TITLE, 1.0, 1.0, 1.0, true); - GameTooltip:AddLine(INSTANCE_ROLE_WARNING_TEXT, nil, nil, nil, true); - end - GameTooltip:Show(); - LFGFrameRoleCheckButton_OnEnter(self); -end - ---List functions -function LFDQueueFrameSpecificList_Update() - if ( LFGDungeonList_Setup() ) then - return; --Setup will update the list. - end - - if C_PlayerInfo.IsPlayerNPERestricted() then - if #LFDDungeonList == 0 then - -- no eligible dungeons - EventRegistry:TriggerEvent("LFDQueueFrameSpecificList_Update.EmptyDungeonList"); - else - EventRegistry:TriggerEvent("LFDQueueFrameSpecificList_Update.DungeonListReady"); - end - end - - local dataProvider = CreateDataProviderWithAssignedKey(LFDDungeonList, "dungeonID"); - LFDQueueFrame.Specific.ScrollBox:SetDataProvider(dataProvider, ScrollBoxConstants.RetainScrollPosition); -end - -function LFDQueueFrameSpecificList_InitButton(button, elementData) - local dungeonID = elementData.dungeonID; - local enabled, queued = LFGDungeonList_EvaluateListState(LE_LFG_CATEGORY_LFD); - - local checkedList; - if ( queued ) then - checkedList = LFGQueuedForList[LE_LFG_CATEGORY_LFD]; - else - checkedList = LFGEnabledList; - end - - button:SetWidth(295); - - LFGDungeonListButton_SetDungeon(button, dungeonID, enabled, checkedList); -end - -function LFDQueueFrame_Join() - LFG_JoinDungeon(LE_LFG_CATEGORY_LFD, LFDQueueFrame.type, LFDDungeonList, LFDHiddenByCollapseList); -end - -function LFDQueueFrameDungeonChoiceEnableButton_OnClick(self, button) - LFGDungeonListCheckButton_OnClick(self, LE_LFG_CATEGORY_LFD, LFDDungeonList, LFDHiddenByCollapseList); - LFDQueueFrameSpecificList_Update(); - LFDQueueFrame_UpdateRoleButtons(); -end - -function LFDQueueFrameDungeonListButton_OnEnter(self) - LFGDungeonListButton_OnEnter(self, YOU_MAY_NOT_QUEUE_FOR_DUNGEON); -end - -function LFDQueueFrameExpandOrCollapseButton_OnClick(self, button) - LFGDungeonList_SetHeaderCollapsed(self:GetParent(), LFDDungeonList, LFDHiddenByCollapseList); - LFDQueueFrame_Update(); -end - -function LFDQueueFrame_OnLoad(self) - self.TypeDropdown:SetWidth(200); -end - -function LFDQueueFrame_OnShow(self) - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN); - QueueUpdater:RequestInfo(); - QueueUpdater:AddRef(); - - self.TypeDropdown:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_LFD_FRAME"); - - local function IsSelected(dungeonType) - return LFDQueueFrame.type == dungeonType; - end - - local function SetSelected(dungeonType) - LFDQueueFrame_SetTypeInternal(dungeonType); - end - - rootDescription:CreateRadio(SPECIFIC_DUNGEONS, IsSelected, SetSelected, "specific"); - - for i=1, GetNumRandomDungeons() do - local id, name = GetLFGRandomDungeonInfo(i); - local isAvailableForAll, isAvailableForPlayer, hideIfNotJoinable = IsLFGDungeonJoinable(id); - if isAvailableForPlayer or not hideIfNotJoinable then - if isAvailableForAll then - rootDescription:CreateRadio(name, IsSelected, SetSelected, id); - else - local radio = rootDescription:CreateRadio(name, IsSelected, SetSelected, id); - radio:SetEnabled(false); - radio:SetTooltip(function(tooltip, description) - GameTooltip_SetTitle(tooltip, YOU_MAY_NOT_QUEUE_FOR_THIS); - GameTooltip_AddErrorLine(tooltip, LFGConstructDeclinedMessage(id)); - end); - end - end - end - end); -end - -function LFDQueueFrame_OnHide(self) - QueueUpdater:RemoveRef(); -end - --- "specific" for the list or the record id for a single dungeon -function LFDQueueFrame_SetTypeInternal(value) - LFDQueueFrame.type = value; - - if ( value == "specific" ) then - LFDQueueFrame_SetTypeSpecificDungeon(); - elseif ( value == "follower" ) then - LFDQueueFrame_SetTypeFollowerDungeon(); - else - local name, typeID, subtypeID, minLevel, maxLevel, recLevel, minRecLevel, maxRecLevel, expansionLevel, groupID, textureFilename, difficulty, maxPlayers, description, isHoliday, _, _, isTimeWalker = GetLFGDungeonInfo(value); - LFDQueueFrame_SetTypeRandomDungeon(isHoliday and not isTimeWalker); - LFDQueueFrameRandom_UpdateFrame(); - end - LFDQueueFrame_UpdateRoleButtons(); -end - -function LFDQueueFrame_SetType(value) - LFDQueueFrame_SetTypeInternal(value); - LFDQueueFrame.TypeDropdown:GenerateMenu(); -end - -function LFDQueueFrame_SetTypeRandomDungeon(hideCooldown) - LFDQueueFrameBackground:SetTexture("Interface\\LFGFrame\\UI-LFG-BACKGROUND-QUESTPAPER") - LFDQueueFrameSpecific:Hide(); - LFDQueueFrameRandom:Show(); - LFGCooldownCover_ChangeSettings(LFDQueueFrame.CooldownFrame, true, not hideCooldown); -end - -function LFDQueueFrame_SetTypeSpecificDungeon() - LFDQueueFrameBackground:SetTexture("Interface\\LFGFrame\\UI-LFG-BACKGROUND-DUNGEONWALL"); - LFDQueueFrameRandom:Hide(); - LFDQueueFrameSpecific:Show(); - LFGCooldownCover_ChangeSettings(LFDQueueFrame.CooldownFrame, true, false); -end - -function LFDQueueFrameRandom_UpdateFrame() - local dungeonID = LFDQueueFrame.type; - - if ( type(dungeonID) ~= "number" ) then --We haven't gotten info on available dungeons yet. - return; - end - - LFGRewardsFrame_UpdateFrame(LFDQueueFrameRandomScrollFrameChildFrame, dungeonID, LFDQueueFrameBackground); - LFDQueueFrame_UpdateRoleButtons(); -end - -function LFDQueueFrameRandomCooldownFrame_OnLoad(self) - self:SetFrameLevel(LFDQueueFrame:GetFrameLevel() + 9); --This value also needs to be set when SetParent is called in LFDQueueFrameRandomCooldownFrame_Update. - - self:RegisterEvent("PLAYER_ENTERING_WORLD"); --For logging in/reloading ui - self:RegisterEvent("LFG_COOLDOWNS_UPDATED"); - self:RegisterEvent("GROUP_ROSTER_UPDATE"); -end - -function LFDQueueFrameRandomCooldownFrame_OnEvent(self, event, ...) - LFDQueueFrameRandomCooldownFrame_Update(); -end - -function LFDQueueFrameRandomCooldownFrame_Update() - local cooldownFrame = LFDQueueFrameCooldownFrame; - local shouldShow = false; - local hasDeserter = false; --If we have deserter, we want to show this over the specific frame as well as the random frame. - - local deserterExpiration = GetLFGDeserterExpiration(); - - local myExpireTime; - if ( deserterExpiration ) then - myExpireTime = deserterExpiration; - hasDeserter = true; - else - myExpireTime = GetLFGRandomCooldownExpiration(); - end - - cooldownFrame.myExpirationTime = myExpireTime; - - for i = 1, GetNumSubgroupMembers() do - local nameLabel = _G["LFDQueueFrameCooldownFrameName"..i]; - local statusLabel = _G["LFDQueueFrameCooldownFrameStatus"..i]; - nameLabel:Show(); - statusLabel:Show(); - - local _, classFilename = UnitClass("party"..i); - local classColor = classFilename and RAID_CLASS_COLORS[classFilename] or NORMAL_FONT_COLOR; - nameLabel:SetFormattedText("|cff%.2x%.2x%.2x%s|r", classColor.r * 255, classColor.g * 255, classColor.b * 255, GetUnitName("party"..i, true)); - - local gender = UnitSex("party"..i); - - if ( UnitHasLFGDeserter("party"..i) ) then - statusLabel:SetFormattedText(RED_FONT_COLOR_CODE.."%s|r", GetText("DESERTER", gender)); - shouldShow = true; - hasDeserter = true; - elseif ( UnitHasLFGRandomCooldown("party"..i) ) then - statusLabel:SetFormattedText(RED_FONT_COLOR_CODE.."%s|r", GetText("ON_COOLDOWN", gender)); - shouldShow = true; - else - statusLabel:SetFormattedText(GREEN_FONT_COLOR_CODE.."%s|r", GetText("READY", gender)); - end - end - for i = GetNumSubgroupMembers() + 1, MAX_PARTY_MEMBERS do - local nameLabel = _G["LFDQueueFrameCooldownFrameName"..i]; - local statusLabel = _G["LFDQueueFrameCooldownFrameStatus"..i]; - nameLabel:Hide(); - statusLabel:Hide(); - end - - if ( GetNumSubgroupMembers() == 0 ) then - cooldownFrame.description:SetPoint("TOP", 0, -85); - else - cooldownFrame.description:SetPoint("TOP", 0, -30); - end - - if ( hasDeserter ) then - cooldownFrame:SetParent(LFDQueueFrame); - cooldownFrame:SetFrameLevel(LFDQueueFrame:GetFrameLevel() + 9); --Setting a new parent changes the frame level, so we need to move it back to what we set in OnLoad. - else - cooldownFrame:SetParent(LFDQueueFrameRandom); --If nobody has deserter, the dungeon cooldown only prevents us from queueing for random. - cooldownFrame:SetFrameLevel(LFDQueueFrame:GetFrameLevel() + 9); - end - - if ( myExpireTime and GetTime() < myExpireTime ) then - shouldShow = true; - if ( deserterExpiration ) then - cooldownFrame.description:SetText(LFG_DESERTER_YOU); - else - cooldownFrame.description:SetText(LFG_RANDOM_COOLDOWN_YOU); - end - cooldownFrame.time:SetText(SecondsToTime(ceil(myExpireTime - GetTime()))); - cooldownFrame.time:Show(); - - cooldownFrame:SetScript("OnUpdate", LFDQueueFrameRandomCooldownFrame_OnUpdate); - else - if ( hasDeserter ) then - cooldownFrame.description:SetText(LFG_DESERTER_OTHER); - else - cooldownFrame.description:SetText(LFG_RANDOM_COOLDOWN_OTHER); - end - cooldownFrame.time:Hide(); - - cooldownFrame:SetScript("OnUpdate", nil); - end - - if ( shouldShow and not LFDQueueFramePartyBackfill:IsShown() ) then - cooldownFrame:Show(); - else - cooldownFrame:Hide(); - end -end - -function LFDQueueFrameRandomCooldownFrame_OnUpdate(self, elapsed) - local timeRemaining = self.myExpirationTime - GetTime(); - if ( timeRemaining > 0 ) then - self.time:SetText(SecondsToTime(ceil(timeRemaining))); - else - LFDQueueFrameRandomCooldownFrame_Update(); - end -end - -function LFDQueueFrameFindGroupButton_Update() - local mode, subMode = GetLFGMode(LE_LFG_CATEGORY_LFD); - --Update the text on the button - if ( mode == "queued" or mode == "rolecheck" or mode == "proposal" or mode == "suspended" ) then - LFDQueueFrameFindGroupButton:SetText(LEAVE_QUEUE); - else - if ( IsInGroup() and GetNumGroupMembers() > 1 ) then - LFDQueueFrameFindGroupButton:SetText(JOIN_AS_PARTY); - else - LFDQueueFrameFindGroupButton:SetText(FIND_A_GROUP); - end - end - - if C_PlayerInfo.IsPlayerNPERestricted() then - if not LFDQueueCheckRoleSelectionValid(LFGRole_GetChecked(LFDQueueFrameRoleButtonTank), LFGRole_GetChecked(LFDQueueFrameRoleButtonHealer), LFGRole_GetChecked(LFDQueueFrameRoleButtonDPS)) then - -- the NPE restricted player needs to at least be a DPS role if nothing is selected - LFDQueueFrameRoleButtonDPS.checkButton:SetChecked(true); - LFDFrameRoleCheckButton_OnClick(LFDQueueFrameRoleButtonDPS.checkButton); - end - end - - if ( not LFDQueueCheckRoleSelectionValid( LFGRole_GetChecked(LFDQueueFrameRoleButtonTank), - LFGRole_GetChecked(LFDQueueFrameRoleButtonHealer), - LFGRole_GetChecked(LFDQueueFrameRoleButtonDPS)) ) then - LFDQueueFrameFindGroupButton:Disable(); - LFDQueueFrameFindGroupButton.tooltip = INSTANCE_ROLE_WARNING_TITLE; - return; - end - - --Disable the button if we're not in a state where we can make a change - if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "listed" ) then --During the proposal, they must use the proposal buttons to leave the queue. - if ( (mode == "queued" or mode == "rolecheck" or mode == "suspended") --The players can dequeue even if one of the two cover panels is up. - or (not LFDQueueFramePartyBackfill:IsVisible() and not LFDQueueFrameCooldownFrame:IsVisible()) ) then - LFDQueueFrameFindGroupButton:Enable(); - LFDQueueFrameFindGroupButton.tooltip = nil; - else - LFDQueueFrameFindGroupButton:Disable(); - end - else - LFDQueueFrameFindGroupButton:Disable(); - if ( IsInGroup(LE_PARTY_CATEGORY_HOME) and not UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then - LFDQueueFrameFindGroupButton.tooltip = ERR_NOT_LEADER; - end - end - - --Disable the button if the person is active in LFGList - local lfgListDisabled; - if ( C_LFGList.HasActiveEntryInfo() ) then - lfgListDisabled = CANNOT_DO_THIS_WHILE_LFGLIST_LISTED; - elseif(C_PartyInfo.IsCrossFactionParty()) then - lfgListDisabled = CROSS_FACTION_RAID_DUNGEON_FINDER_ERROR; - end - - if ( lfgListDisabled ) then - LFDQueueFrameFindGroupButton:Disable(); - LFDQueueFrameFindGroupButton.tooltip = lfgListDisabled; - end - - --Update the backfill enable state - if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "queued" and mode ~= "suspended" and mode ~= "rolecheck" ) then - LFDQueueFramePartyBackfillBackfillButton:Enable(); - else - LFDQueueFramePartyBackfillBackfillButton:Disable(); - end -end - ----@class LFDHiddenByCollapseList -LFDHiddenByCollapseList = {}; - -local function UpdateLFDDungeonList() - LFDDungeonList = {}; - - -- Get the list of dungeons, then pull out dungeons that are hidden (due to current Timewalking Campaign, etc) and add the rest to LFDDungeonList - local dungeonList = GetLFDChoiceOrder(); - for _, dungeonID in ipairs(dungeonList) do - if not LFGLockList[dungeonID] or not LFGLockList[dungeonID].hideEntry then - table.insert(LFDDungeonList, dungeonID); - end - end -end - -function LFDQueueFrame_Update() - local mode, submode = GetLFGMode(LE_LFG_CATEGORY_LFD); - - local checkedList; - if ( LFD_IsEmpowered() and mode ~= "queued" and mode ~= "suspended") then - checkedList = LFGEnabledList; - else - checkedList = LFGQueuedForList[LE_LFG_CATEGORY_LFD]; - end - - UpdateLFDDungeonList(); - - LFGQueueFrame_UpdateLFGDungeonList(LFDDungeonList, LFDHiddenByCollapseList, checkedList, LFD_CURRENT_FILTER); - - LFDQueueFrameSpecificList_Update(); -end - -LFD_CURRENT_FILTER = LFGList_DefaultFilterFunction; - ---------------------------------------------------- ------------LFD Role Check Popup Frame-------------- ---------------------------------------------------- -function LFDFramePopupRoleCheckButton_OnClick(self) - LFGRoleCheckPopup_UpdatePvPRoles(); - LFDRoleCheckPopup_UpdateAcceptButton(); -end - -function LFGRoleCheckPopup_UpdatePvPRoles() - local isBGRoleCheck = select(6, GetLFGRoleUpdate()); - if ( isBGRoleCheck ) then - local tankChecked, healerChecked, dpsChecked = LFDRoleCheckPopup_GetRolesChecked(); - SetPVPRoles(tankChecked, healerChecked, dpsChecked); - end -end - -function LFGRoleCheckPopup_UpdateRoleButton(button) - if( button:IsEnabled() )then - local unlocked, alert = GetLFGInviteRoleAvailability(button:GetID()); - if(unlocked)then - LFG_EnableRoleButton(button); - button.lockedIndicator:Hide(); - button.checkButton:Show(); - if(alert) then - button.alert:Show(); - else - button.alert:Hide(); - end - else - button.lockedIndicator:Show(); - LFG_DisableRoleButton(button); - button.checkButton:Hide(); - button.alert:Hide(); - end - end -end - -function LFDPopupRoleCheckButton_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(_G["ROLE_DESCRIPTION_"..self.role], nil, nil, nil, nil, true); - if ( self.permDisabled ) then - if(self.permDisabledTip)then - GameTooltip:AddLine(self.permDisabledTip, 1, 0, 0, true); - end - elseif ( self.disabledTooltip and not self:IsEnabled() ) then - GameTooltip:AddLine(self.disabledTooltip, 1, 0, 0, true); - elseif ( not self:IsEnabled() ) then - local dungeonID = LFDQueueFrame.type; - local roleID = self:GetID(); - GameTooltip:SetText(ERR_ROLE_UNAVAILABLE, 1.0, 1.0, 1.0); - local reasons = GetLFGInviteRoleRestrictions(roleID); - for i = 1, #reasons do - local text = _G["INSTANCE_UNAVAILABLE_SELF_"..(LFG_INSTANCE_INVALID_CODES[reasons[i]] or "OTHER")]; - if( text ) then - GameTooltip:AddLine(text); - end - end - GameTooltip:Show(); - return; - elseif( self.alert:IsShown() ) then - GameTooltip:SetText(INSTANCE_ROLE_WARNING_TITLE, 1.0, 1.0, 1.0, true); - GameTooltip:AddLine(INSTANCE_ROLE_WARNING_TEXT, nil, nil, nil, true); - end - GameTooltip:Show(); - LFGFrameRoleCheckButton_OnEnter(self); -end - -function LFDRoleCheckPopup_OnShow(self) - PlaySound(SOUNDKIT.READY_CHECK); - FlashClientIcon(); - LFDRoleCheckPopup_Update(); - self:RegisterEvent("PVP_BRAWL_INFO_UPDATED"); -end - -function LFDRoleCheckPopup_OnHide(self) - self:UnregisterEvent("PVP_BRAWL_INFO_UPDATED"); -end - -function LFDRoleCheckPopup_OnEvent(self, event) - if (event == "PVP_BRAWL_INFO_UPDATED") then - LFDRoleCheckPopup_Update(); - end -end - -function LFDRoleCheckPopup_Update() - LFGDungeonList_Setup(); - - LFG_UpdateAllRoleCheckboxes(); - - local inProgress, slots, members, category, lfgID, bgQueue = GetLFGRoleUpdate(); - local isLFGList, activityID = C_LFGList.GetRoleCheckInfo(); - - local displayName; - if( isLFGList ) then - displayName = C_LFGList.GetActivityFullName(activityID); - elseif ( bgQueue ) then - displayName = GetLFGRoleUpdateBattlegroundInfo(); - elseif ( slots == 1 ) then - local dungeonID, dungeonType, dungeonSubType = GetLFGRoleUpdateSlot(1); - if ( dungeonSubType == LFG_SUBTYPEID_HEROIC ) then - displayName = format(HEROIC_PREFIX, select(LFG_RETURN_VALUES.name, GetLFGDungeonInfo(dungeonID))); - else - displayName = select(LFG_RETURN_VALUES.name, GetLFGDungeonInfo(dungeonID)); - end - else - displayName = MULTIPLE_DUNGEONS; - end - displayName = displayName and NORMAL_FONT_COLOR:WrapTextInColorCode(displayName) or ""; - - if ( isLFGList ) then - LFDRoleCheckPopupDescriptionText:SetFormattedText(LFG_LIST_APPLYING_TO, displayName); - else - LFDRoleCheckPopupDescriptionText:SetFormattedText(QUEUED_FOR, displayName); - end - - local descSubTextWidth = 0; - local descSubTextHeight = 0; - local maxLevel, isLevelReduced = C_LFGInfo.GetRoleCheckDifficultyDetails(); - if isLevelReduced then - local canDisplayLevel = maxLevel and maxLevel < UnitEffectiveLevel("player"); - if canDisplayLevel then - local formattedString = string.format(bgQueue and LFG_PVP_LEVEL_REDUCED or LFG_LEVEL_REDUCED, maxLevel); - LFDRoleCheckPopupDescription.SubText:SetText(formattedString); - else - LFDRoleCheckPopupDescription.SubText:SetText(LFG_LEVEL_REDUCED_GENERIC); - end - descSubTextWidth = LFDRoleCheckPopupDescription.SubText:GetWidth(); - descSubTextHeight = LFDRoleCheckPopupDescription.SubText:GetHeight(); - end - LFDRoleCheckPopupDescription.SubText:SetShown(isLevelReduced); - - local descTextWidth = LFDRoleCheckPopupDescriptionText:GetWidth(); - local maxTextWidth = math.max(descSubTextWidth, descTextWidth) + 10; - LFDRoleCheckPopupDescription:SetWidth(maxTextWidth); - - local descTextHeight = LFDRoleCheckPopupDescriptionText:GetHeight(); - local totalDescriptionTextHeight = descSubTextHeight + descTextHeight; - LFDRoleCheckPopupDescription:SetHeight(totalDescriptionTextHeight); - - local descriptionTextMargin = isLevelReduced and 35 or 46; - local descriptionOffsetY = LFDRoleCheckPopupDescription:GetHeight() + descriptionTextMargin; - LFDRoleCheckPopupDescription:SetPoint("CENTER", LFDRoleCheckPopup, "BOTTOM", 0, descriptionOffsetY); - - local headerTextHeight = LFDRoleCheckPopup.Text:GetHeight(); - local roleHeight = LFDRoleCheckPopupRoleButtonTank:GetHeight(); - local popupHeight = headerTextHeight + roleHeight + totalDescriptionTextHeight + 85; - LFDRoleCheckPopup:SetHeight(popupHeight); - - LFGRoleCheckPopup_UpdateRoleButton(LFDRoleCheckPopupRoleButtonTank); - LFGRoleCheckPopup_UpdateRoleButton(LFDRoleCheckPopupRoleButtonHealer); - LFGRoleCheckPopup_UpdateRoleButton(LFDRoleCheckPopupRoleButtonDPS); - - LFDRoleCheckPopup_UpdateAcceptButton(); -end - -function LFDRoleCheckPopup_GetRolesChecked() - local tankChecked = LFGRole_GetChecked(LFDRoleCheckPopupRoleButtonTank); - local healerChecked = LFGRole_GetChecked(LFDRoleCheckPopupRoleButtonHealer); - local dpsChecked = LFGRole_GetChecked(LFDRoleCheckPopupRoleButtonDPS); - return tankChecked, healerChecked, dpsChecked; -end - -function LFDRoleCheckPopupAccept_OnClick() - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_TAB); - - --Check if the role check is for a BG or not. - local _, _, _, _, _, isBGRoleCheck = GetLFGRoleUpdate(); - local tankChecked, healerChecked, dpsChecked = LFDRoleCheckPopup_GetRolesChecked(); - if ( isBGRoleCheck ) then - SetPVPRoles(tankChecked, healerChecked, dpsChecked); - else - local oldLeader = GetLFGRoles(); - SetLFGRoles(oldLeader, tankChecked, healerChecked, dpsChecked); - end - - if ( CompleteLFGRoleCheck(true) ) then - StaticPopupSpecial_Hide(LFDRoleCheckPopup); - end -end - -function LFDRoleCheckPopupDecline_OnClick() - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_TAB); - StaticPopupSpecial_Hide(LFDRoleCheckPopup); - CompleteLFGRoleCheck(false); -end - - -function LFDPopupCheckRoleSelectionValid(tank, healer, dps) - if ( not tank and not healer and not dps ) then - return false; - end - - local inProgress, slots, members = GetLFGRoleUpdate(); - for i=1, slots do - local dungeonID = GetLFGRoleUpdateSlot(i); - if ( LFDCheckRolesRestricted(dungeonID, tank, healer, dps) ) then - return false; - end - end - return true; -end - -function LFDRoleCheckPopup_UpdateAcceptButton() - local button = LFDRoleCheckPopupAcceptButton; - if ( LFDPopupCheckRoleSelectionValid( LFGRole_GetChecked(LFDRoleCheckPopupRoleButtonTank), - LFGRole_GetChecked(LFDRoleCheckPopupRoleButtonHealer), - LFGRole_GetChecked(LFDRoleCheckPopupRoleButtonDPS)) ) then - button:Enable(); - button.tooltipText = nil; - else - button:Disable(); - button.tooltipText = INSTANCE_ROLE_WARNING_TITLE; - end -end diff --git a/WoW-API/_UI/Blizzard_GroupFinder/LFDFrame.xml b/WoW-API/_UI/Blizzard_GroupFinder/LFDFrame.xml deleted file mode 100644 index 8eb8104..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/LFDFrame.xml +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - self.enableButton:SetScript("OnClick", LFDQueueFrameDungeonChoiceEnableButton_OnClick); - self.expandOrCollapseButton:SetScript("OnClick", LFDQueueFrameExpandOrCollapseButton_OnClick); - self:SetScript("OnEnter", LFDQueueFrameDungeonListButton_OnEnter); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PlaySound(SOUNDKIT.READY_CHECK); - FlashClientIcon(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --Move the title to deal with an offset so scrolling doesn't look as bad with the LFD border. - self.title:SetPoint("TOPLEFT", 10, -8); - LFGRewardsFrame_OnLoad(self); - - - LFGRewardsFrame_AdjustFont(self); - LFDQueueFrameRandom_UpdateFrame(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LFGBackfillCover_SetUp(self, {LFG_SUBTYPEID_DUNGEON, LFG_SUBTYPEID_HEROIC}, LE_LFG_CATEGORY_LFD, LFDQueueFrameFindGroupButton_Update); - - - - - - - - - - - LFGCooldownCover_SetUp(self, self:GetParent().PartyBackfill); - - - LFDQueueFrameFindGroupButton_Update(); - - - LFDQueueFrameFindGroupButton_Update(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self:SetFrameLevel(16); - - - - - - - - - - - - - - - - - - diff --git a/WoW-API/_UI/Blizzard_GroupFinder/LFGFrame.lua b/WoW-API/_UI/Blizzard_GroupFinder/LFGFrame.lua deleted file mode 100644 index e1a3daa..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/LFGFrame.lua +++ /dev/null @@ -1,2368 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ ------ ---A note on nomenclature: ---LFD is used for Dungeon-specific functions and values ---LFG is used for for generic functions/values that may be used for LFD, LFR, and any other LF_ system we may implement in the future. ------- - -LFG_INVITE_POPUP_DEFAULT_HEIGHT = 180; -LFGLockList = nil; -LFGCollapseList = nil; -LFGEnabledList = nil; - ---DEBUG FIXME: -function LFGDebug(text, ...) - if ( GetCVarBool("lfgDebug") ) then - C_Log.LogMessage("LFGLua: "..format(text, ...)); - end -end - -LFG_ID_TO_ROLES = { "DAMAGER", "TANK", "HEALER" }; ----@class LFG_RETURN_VALUES -LFG_RETURN_VALUES = { - name = 1, - typeID = 2, - subtypeID = 3, - minLevel = 4, - maxLevel = 5, - recLevel = 6, --Recommended level - minRecLevel = 7, --Minimum recommended level - maxRecLevel = 8, --Maximum recommended level - expansionLevel = 9, - groupID = 10, - texture = 11, - difficulty = 12, - maxPlayers = 13, - description = 14, - isHoliday = 15, - bonusRepAmount = 16, - minPlayers = 17, - isTimewalker = 18, - mapName = 19, - minGear = 20, -} - -LFG_INSTANCE_INVALID_RAID_LOCKED = 6; - -LFG_INSTANCE_INVALID_WRONG_FACTION = 10; -LFG_INSTANCE_INVALID_CODES = { --Any other codes are unspecified conditions (e.g. attunements) - "EXPANSION_TOO_LOW", - "LEVEL_TOO_LOW", - "LEVEL_TOO_HIGH", - "GEAR_TOO_LOW", - "GEAR_TOO_HIGH", - "RAID_LOCKED", - nil, --Target level too high - nil, --Target level too low - "AREA_NOT_EXPLORED", - nil, --Wrong faction - "NO_VALID_ROLES", - "ENGAGED_IN_PVP", - "NO_SPEC", - "CANNOT_RUN_ANY_CHILD_DUNGEON", - [10000] = "TEMPORARILY_DISABLED", -} ----@class LFG_INSTANCE_CONDITION_FAILED_CODES -LFG_INSTANCE_CONDITION_FAILED_CODES = { - [1] = "LEVEL_TOO_LOW", - [2] = "LEVEL_TOO_HIGH", - [22] = "QUEST_NOT_COMPLETED", - [25] = "MISSING_ITEM", - -- These are handled separately in LFGConstructDeclinedMessage - -- [29] WRONG_TIME_RANGE - -- [30] WRONG_TIME - -- [31] WRONG_WORLD_STATE_EXPRESSION - [34] = "ACHIEVEMENT_NOT_COMPLETED", -} - -local function GetLFGInstanceErrorString(who, reason, subreason) - local errorKey = LFG_INSTANCE_INVALID_CODES[reason]; - if reason == Enum.LFGSlotInvalidReason.PlayerConditionFailed then - errorKey = LFG_INSTANCE_CONDITION_FAILED_CODES[subreason]; - end - return _G["INSTANCE_UNAVAILABLE_"..who.."_"..(errorKey or "OTHER")]; -end - -LFG_ROLE_SHORTAGE_RARE = 1; -LFG_ROLE_SHORTAGE_UNCOMMON = 2; -LFG_ROLE_SHORTAGE_PLENTIFUL = 3; -LFG_ROLE_NUM_SHORTAGE_TYPES = 3; - -StaticPopupDialogs["LFG_QUEUE_EXPAND"] = { - text = LFG_QUEUE_EXPAND_DESCRIPTION, - button1 = YES, - button2 = NO, - OnAccept = C_LFGInfo.ConfirmLfgExpandSearch, - timeout = 0, - exclusive = 1, - whileDead = 1, - hideOnEscape = 1, -}; ---Variables to store dungeon info in Lua ---local LFDDungeonList, LFRRaidList, LFGCollapseList, LFGEnabledList, LFDHiddenByCollapseList, LFGLockList; - -function LFGEventFrame_OnLoad(self) - self:RegisterEvent("LFG_UPDATE"); - self:RegisterEvent("PLAYER_ENTERING_WORLD"); - self:RegisterEvent("LFG_LOCK_INFO_RECEIVED"); - self:RegisterEvent("GROUP_ROSTER_UPDATE"); - - self:RegisterEvent("LFG_OFFER_CONTINUE"); - self:RegisterEvent("LFG_ROLE_CHECK_ROLE_CHOSEN"); - self:RegisterEvent("LFG_READY_CHECK_PLAYER_IS_READY"); - - self:RegisterEvent("LFG_PROPOSAL_UPDATE"); - self:RegisterEvent("LFG_PROPOSAL_SHOW"); - self:RegisterEvent("LFG_PROPOSAL_DONE"); - self:RegisterEvent("LFG_PROPOSAL_FAILED"); - self:RegisterEvent("LFG_PROPOSAL_SUCCEEDED"); - - self:RegisterEvent("VARIABLES_LOADED"); - - self:RegisterEvent("PLAYER_REGEN_ENABLED"); - - --These just update states (roles changeable, buttons clickable, etc.) - self:RegisterEvent("LFG_ROLE_CHECK_SHOW"); - self:RegisterEvent("LFG_ROLE_CHECK_HIDE"); - self:RegisterEvent("LFG_BOOT_PROPOSAL_UPDATE"); - self:RegisterEvent("LFG_ROLE_UPDATE"); - self:RegisterEvent("LFG_UPDATE_RANDOM_INFO"); - self:RegisterEvent("LFG_INVALID_ERROR_MESSAGE"); - - --Used for disabling buttons when active in LFGList - self:RegisterEvent("LFG_LIST_ACTIVE_ENTRY_UPDATE"); - self:RegisterEvent("LFG_LIST_SEARCH_RESULT_UPDATED"); - - self:RegisterEvent("SHOW_LFG_EXPAND_SEARCH_PROMPT"); -end - ----@class LFGQueuedForList -LFGQueuedForList = {}; -for i=1, NUM_LE_LFG_CATEGORYS do - LFGQueuedForList[i] = {}; -end - -local function GetLFGLockList() - local lockInfo = C_LFGInfo.GetLFDLockStates(); - local lockMap = {}; - for _, lock in ipairs(lockInfo) do - lockMap[lock.lfgID] = lock; - end - return lockMap; -end - -local function ScenariosEnabled() - return (PVEFrameMixin ~= nil and PVEFrame:ScenariosEnabled()) or (PVEFrameMixin == nil and ScenarioQueueFrame); -end - -function LFGEventFrame_OnEvent(self, event, ...) - if ( event == "LFG_UPDATE" ) then - LFG_UpdateAllRoleCheckboxes(); - LFG_UpdateQueuedList(); - local slot = GetPartyLFGID(); - if ( slot ) then - local category = GetLFGCategoryForID(slot); - local mode, subMode = GetLFGMode(category, slot); - if ( mode == "queued" ) then --We're now queued, remove the backfill popup. - self.queuedContinueName = nil; - StaticPopup_Hide("LFG_OFFER_CONTINUE"); - end - end - elseif ( event == "PLAYER_ENTERING_WORLD" ) then - LFG_UpdateQueuedList(); - LFG_UpdateAllRoleCheckboxes(); - LFG_DisplayGroupLeaderWarning(self); - LFGDungeonReadyPopup_Update(); - elseif ( event == "LFG_LOCK_INFO_RECEIVED" ) then - LFGLockList = GetLFGLockList(); - LFG_UpdateFramesIfShown(); - elseif ( event == "GROUP_ROSTER_UPDATE" ) then - LFG_UpdateQueuedList(); - LFG_UpdateFramesIfShown(); - LFG_DisplayGroupLeaderWarning(self); - if ( not CanPartyLFGBackfill() ) then - self.queuedContinueName = nil; - StaticPopup_Hide("LFG_OFFER_CONTINUE"); - end - elseif ( event == "LFG_OFFER_CONTINUE" ) then - local displayName, lfgID, typeID = ...; - if ( not UnitAffectingCombat("player") ) then - local dialog = StaticPopup_Show("LFG_OFFER_CONTINUE", NORMAL_FONT_COLOR_CODE..displayName.."|r"); - if ( dialog ) then - dialog.data = lfgID; - dialog.data2 = typeID; - end - else - self.queuedContinueName = displayName; - self.queuedContinueLfgID = lfgID; - self.queuedContinueTypeID = typeID; - end - elseif ( event == "PLAYER_REGEN_ENABLED" ) then - if ( self.queuedContinueName ) then - if ( CanPartyLFGBackfill() ) then --Make sure we can still backfill. - local dialog = StaticPopup_Show("LFG_OFFER_CONTINUE", NORMAL_FONT_COLOR_CODE..self.queuedContinueName.."|r"); - if ( dialog ) then - dialog.data = self.queuedContinueLfgID; - dialog.data2 = self.queuedContinueTypeID; - end - end - self.queuedContinueName = nil; - end - return; --We don't need to update anything else on this event - elseif ( event == "LFG_ROLE_CHECK_ROLE_CHOSEN" ) then - local player, isTank, isHealer, isDamage = ...; - - --Yes, consecutive string concatenation == bad for garbage collection. But the alternative is either extremely unslightly or localization unfriendly. (Also, this happens fairly rarely) - local roleList; - - if ( isTank ) then - roleList = INLINE_TANK_ICON.." "..TANK; - end - if ( isHealer ) then - if ( roleList ) then - roleList = roleList..PLAYER_LIST_DELIMITER.." "..INLINE_HEALER_ICON.." "..HEALER; - else - roleList = INLINE_HEALER_ICON.." "..HEALER; - end - end - if ( isDamage ) then - if ( roleList ) then - roleList = roleList..PLAYER_LIST_DELIMITER.." "..INLINE_DAMAGER_ICON.." "..DAMAGER; - else - roleList = INLINE_DAMAGER_ICON.." "..DAMAGER; - end - end - assert(roleList); - ChatFrame_DisplaySystemMessageInPrimary(string.format(LFG_ROLE_CHECK_ROLE_CHOSEN, player, roleList)); - elseif ( event == "LFG_READY_CHECK_PLAYER_IS_READY" ) then - local player = ...; - ChatFrame_DisplaySystemMessageInPrimary(string.format(LFG_READY_CHECK_PLAYER_IS_READY, player)); - elseif ( event == "VARIABLES_LOADED" ) then - LFG_UpdateAllRoleCheckboxes(); - elseif ( event == "LFG_ROLE_UPDATE" ) then - LFG_UpdateAllRoleCheckboxes(); - elseif ( event == "LFG_PROPOSAL_UPDATE" ) then - LFGDungeonReadyPopup_Update(); - elseif ( event == "LFG_UPDATE_RANDOM_INFO" ) then - LFG_UpdateFramesIfShown(); - elseif ( event == "LFG_PROPOSAL_SHOW" ) then - LFGDungeonReadyPopup.closeIn = nil; - LFGDungeonReadyPopup:SetScript("OnUpdate", nil); - LFGDungeonReadyStatus_ResetReadyStates(); - StaticPopupSpecial_Show(LFGDungeonReadyPopup); - PlaySound(SOUNDKIT.READY_CHECK); - FlashClientIcon(); - elseif ( event == "LFG_PROPOSAL_DONE" ) then - LFGDebug("Proposal Hidden: Proposal done."); - StaticPopupSpecial_Hide(LFGDungeonReadyPopup); - elseif ( event == "LFG_PROPOSAL_FAILED" ) then - LFGDungeonReadyPopup_OnFail(); - elseif ( event == "LFG_PROPOSAL_SUCCEEDED" ) then - LFGDebug("Proposal Hidden: Proposal succeeded."); - StaticPopupSpecial_Hide(LFGDungeonReadyPopup); - elseif ( event == "LFG_ROLE_CHECK_HIDE" ) then - LFG_UpdateFramesIfShown(); - elseif ( event == "LFG_INVALID_ERROR_MESSAGE" ) then - local reason, reasonArg1, reasonArg2 = ...; - local info = ChatTypeInfo["SYSTEM"]; - DEFAULT_CHAT_FRAME:AddMessage(format(GetLFGInstanceErrorString("SELF", reason, reasonarg1), "", reasonArg1, reasonArg2), info.r, info.g, info.b, info.id); - elseif event == "SHOW_LFG_EXPAND_SEARCH_PROMPT" then - StaticPopup_Show("LFG_QUEUE_EXPAND"); - end - - LFG_UpdateRolesChangeable(); - LFG_UpdateFindGroupButtons(); - LFG_UpdateLockedOutPanels(); - LFGBackfillCover_Update(LFDQueueFrame.PartyBackfill); - if (RaidFinderQueueFrame) then - LFGBackfillCover_Update(RaidFinderQueueFrame.PartyBackfill); - end - - if (ScenariosEnabled()) then - LFGBackfillCover_Update(ScenarioQueueFrame.PartyBackfill); - end -end - -function LFG_IsHeroicScenario(dungeonID) - if ( dungeonID ) then - local difficulty = select(LFG_RETURN_VALUES.difficulty, GetLFGDungeonInfo(dungeonID)); - if ( difficulty ) then - local _, _, isHeroic = GetDifficultyInfo(difficulty); - return isHeroic; - end - end - return false; -end - -function LFG_DisplayGroupLeaderWarning(eventFrame) - local numRaidMembers = GetNumGroupMembers(); - if ( not HasLFGRestrictions() or not IsInGroup() ) then - eventFrame.lastLeader = nil; - return; - end - - if ( not IsInLFGDungeon() ) then - --We only want to display the message if we're actually in the dungeon. - return; - end - - local leaderName; - - if ( IsInRaid() ) then - for i=1, numRaidMembers do - local name, rank = GetRaidRosterInfo(i); - if ( rank == 2 ) then - leaderName = name; - end - end - elseif ( UnitIsGroupLeader("player") ) then - leaderName = UnitName("player"); - else - for i=1, GetNumSubgroupMembers() do - if ( UnitIsGroupLeader("party"..i) ) then - leaderName = UnitName("party"..i); - break; - end - end - end - - if ( leaderName and eventFrame.lastLeader ~= leaderName ) then - --We'll hold this message a little bit longer than most. - RaidNotice_AddMessage(RaidWarningFrame, format(LFG_LEADER_CHANGED_WARNING, leaderName), ChatTypeInfo["RAID_WARNING"], 18); - if ( not eventFrame.lastLeader ) then - local info = ChatTypeInfo["SYSTEM"]; - DEFAULT_CHAT_FRAME:AddMessage(format(LFG_LEADER_CHANGED_WARNING, leaderName), info.r, info.g, info.b, info.id); - end - - end - eventFrame.lastLeader = leaderName; -end - -function LFG_UpdateLockedOutPanels() - --[[ - local mode, submode = GetLFGMode(); - - if ( mode == "listed" ) then - LFDQueueFrameNoLFDWhileLFR:Show(); - LFDQueueFrameNoLFDWhileLFRDescription:SetText(NO_LFD_WHILE_LFR); - elseif ( mode == "queued" or mode == "rolecheck" or mode == "proposal" or mode == "suspended" ) then - local queueType = GetLFGModeType(); - if ( queueType == "raid" ) then - LFDQueueFrameNoLFDWhileLFR:Show(); - LFDQueueFrameNoLFDWhileLFRDescription:SetText(NO_LFD_WHILE_RF); - else - LFDQueueFrameNoLFDWhileLFR:Hide(); - end - else - LFDQueueFrameNoLFDWhileLFR:Hide(); - end - - if ( mode == "queued" or mode == "proposal" or mode == "rolecheck" or mode == "suspended" ) then - LFRQueueFrameNoLFRWhileLFD:Show(); - else - LFRQueueFrameNoLFRWhileLFD:Hide(); - end - --]] -end - -function LFG_UpdateFindGroupButtons() - LFDQueueFrameFindGroupButton_Update(); - if(RaidFinderFrameFindRaidButton_Update) then - RaidFinderFrameFindRaidButton_Update(); - end - - if ScenariosEnabled() and ScenarioQueueFrameFindGroupButton_Update then - ScenarioQueueFrameFindGroupButton_Update(); - end -end - -function LFG_UpdateQueuedList() - for i=1, NUM_LE_LFG_CATEGORYS do - LFGQueuedForList[i] = GetLFGQueuedList(i, LFGQueuedForList[i]); --Re-fill table if it already exists, otherwise create - end - LFG_UpdateFramesIfShown(); -end - -function LFG_UpdateFramesIfShown() - if ( LFDParentFrame:IsVisible() ) then - LFDQueueFrame_Update(); - LFDQueueFrameRandom_UpdateFrame(); - end - if ScenariosEnabled() then - if ( ScenarioQueueFrame:IsVisible() ) then - ScenarioQueueFrame_Update(); - end - end -end - -function LFG_PermanentlyDisableRoleButton(button) - button.permDisabled = true; - button:Disable(); - button.checkButton:Hide(); - button.checkButton:Disable(); - button.checkButton:SetChecked(false); - button.alert:Hide(); - if ( button.background ) then - button.background:Hide(); - end - if ( button.shortageBorder ) then - button.shortageBorder:SetVertexColor(0.5, 0.5, 0.5); - button.incentiveIcon.texture:SetVertexColor(0.5, 0.5, 0.5); - button.incentiveIcon.border:SetVertexColor(0.5, 0.5, 0.5); - end -end - -function LFG_DisableRoleButton(button) - button:Disable(); - button.checkButton:Disable(); - if ( button.background ) then - button.background:Hide(); - end - if ( button.shortageBorder ) then - button.shortageBorder:SetVertexColor(0.5, 0.5, 0.5); - button.incentiveIcon.texture:SetVertexColor(0.5, 0.5, 0.5); - button.incentiveIcon.border:SetVertexColor(0.5, 0.5, 0.5); - end -end - -function LFG_EnableRoleButton(button) - button.permDisabled = false; - button:Enable(); - if( button.lockedIndicator:IsShown() ) then - button.checkButton:Hide(); - button.checkButton:Disable(); - else - button.checkButton:Show(); - button.checkButton:Enable(); - end - if ( button.background ) then - button.background:Show(); - end - if ( button.shortageBorder ) then - button.shortageBorder:SetVertexColor(1, 1, 1); - button.incentiveIcon.texture:SetVertexColor(1, 1, 1); - button.incentiveIcon.border:SetVertexColor(1, 1, 1); - end -end - -function LFG_UpdateAvailableRoleButton(button, canBeRole) - if (canBeRole) then - LFG_EnableRoleButton(button); - else - LFG_PermanentlyDisableRoleButton(button); - end -end - -function LFG_UpdateAvailableRoles(tankButton, healButton, dpsButton, leaderButton) - local canBeTank, canBeHealer, canBeDPS = C_LFGList.GetAvailableRoles(); - LFG_UpdateAvailableRoleButton(tankButton, canBeTank); - LFG_UpdateAvailableRoleButton(healButton, canBeHealer); - LFG_UpdateAvailableRoleButton(dpsButton, canBeDPS); - - if ( leaderButton ) then - if (not IsInGroup() or UnitIsGroupLeader("player")) then - LFG_EnableRoleButton(leaderButton); - else - LFG_PermanentlyDisableRoleButton(leaderButton); - end - end -end - -function LFG_UpdateAllRoleCheckboxes() - LFG_UpdateRoleCheckboxes(LE_LFG_CATEGORY_LFD, nil, LFDQueueFrameRoleButtonTank, LFDQueueFrameRoleButtonHealer, LFDQueueFrameRoleButtonDPS, LFDQueueFrameRoleButtonLeader); - - local _, _, _, _, _, isBGRoleCheck = GetLFGRoleUpdate(); - if ( isBGRoleCheck ) then - local tank, healer, dps = GetPVPRoles(); - LFDRoleCheckPopupRoleButtonTank.checkButton:SetChecked(tank); - LFDRoleCheckPopupRoleButtonHealer.checkButton:SetChecked(healer); - LFDRoleCheckPopupRoleButtonDPS.checkButton:SetChecked(dps); - elseif ( not LFDRoleCheckPopup:IsShown() ) then - LFG_UpdateRoleCheckboxes(LE_LFG_CATEGORY_LFD, nil, LFDRoleCheckPopupRoleButtonTank, LFDRoleCheckPopupRoleButtonHealer, LFDRoleCheckPopupRoleButtonDPS); - end - if(RaidFinderQueueFrame) then - LFG_UpdateRoleCheckboxes(LE_LFG_CATEGORY_RF, RaidFinderQueueFrame.raid, RaidFinderQueueFrameRoleButtonTank, RaidFinderQueueFrameRoleButtonHealer, RaidFinderQueueFrameRoleButtonDPS, RaidFinderQueueFrameRoleButtonLeader); - end -end - -function LFG_UpdateRoleCheckboxes(category, lfgID, tankButton, healButton, dpsButton, leaderButton) - local mode, submode = GetLFGMode(category, lfgID); - local inParty, joined, queued, noPartialClear, achievements, lfgComment, slotCount, _category, leader, tank, healer, dps = GetLFGInfoServer(category, lfgID); - if ( mode ~= "queued" and mode ~= "listed" and mode ~= "suspended" ) then - leader, tank, healer, dps = GetLFGRoles(); - end - - LFGRole_SetChecked(tankButton, tank); - LFGRole_SetChecked(healButton, healer); - LFGRole_SetChecked(dpsButton, dps); - - if ( leaderButton ) then - leaderButton.checkButton:SetChecked(leader); - end -end - -function LFG_UpdateRolesChangeable() - local mode, subMode = GetLFGMode(LE_LFG_CATEGORY_LFD); - if ( mode == "queued" or mode == "listed" or mode == "rolecheck" or mode == "proposal" or mode == "suspended" ) then - LFG_DisableRoleButton(LFDQueueFrameRoleButtonTank, true); - LFG_DisableRoleButton(LFDQueueFrameRoleButtonHealer, true); - LFG_DisableRoleButton(LFDQueueFrameRoleButtonDPS, true); - LFG_DisableRoleButton(LFDQueueFrameRoleButtonLeader, true); - else - LFG_UpdateAvailableRoles(LFDQueueFrameRoleButtonTank, LFDQueueFrameRoleButtonHealer, LFDQueueFrameRoleButtonDPS, LFDQueueFrameRoleButtonLeader); - end - - if(RaidFinderQueueFrame) then - mode, subMode = GetLFGMode(LE_LFG_CATEGORY_RF, RaidFinderQueueFrame.raid); - if ( mode == "queued" or mode == "listed" or mode == "rolecheck" or mode == "proposal" or mode == "suspended" ) then - LFG_DisableRoleButton(RaidFinderQueueFrameRoleButtonTank, true); - LFG_DisableRoleButton(RaidFinderQueueFrameRoleButtonHealer, true); - LFG_DisableRoleButton(RaidFinderQueueFrameRoleButtonDPS, true); - LFG_DisableRoleButton(RaidFinderQueueFrameRoleButtonLeader, true); - else - LFG_UpdateAvailableRoles(RaidFinderQueueFrameRoleButtonTank, RaidFinderQueueFrameRoleButtonHealer, RaidFinderQueueFrameRoleButtonDPS, RaidFinderQueueFrameRoleButtonLeader); - end - end - --Always update the role check popup - LFG_UpdateAvailableRoles(LFDRoleCheckPopupRoleButtonTank, LFDRoleCheckPopupRoleButtonHealer, LFDRoleCheckPopupRoleButtonDPS, nil); -end - -function LFG_SetRoleIconIncentive(roleButton, incentiveIndex) - if ( incentiveIndex ) then - local tex; - if ( incentiveIndex == LFG_ROLE_SHORTAGE_PLENTIFUL ) then - tex = "Interface\\Icons\\INV_Misc_Coin_19"; - elseif ( incentiveIndex == LFG_ROLE_SHORTAGE_UNCOMMON ) then - tex = "Interface\\Icons\\INV_Misc_Coin_18"; - elseif ( incentiveIndex == LFG_ROLE_SHORTAGE_RARE ) then - tex = "Interface\\Icons\\INV_Misc_Coin_17"; - end - SetPortraitToTexture(roleButton.incentiveIcon.texture, tex); - roleButton.incentiveIcon:Show(); - roleButton.shortageBorder:Show(); - else - roleButton.incentiveIcon:Hide(); - roleButton.shortageBorder:Hide(); - end -end - -function LFGRoleIconIncentive_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(format(LFG_CALL_TO_ARMS, _G[self:GetParent().role]), 1, 1, 1); - GameTooltip:AddLine(LFG_CALL_TO_ARMS_EXPLANATION, nil, nil, nil, true); - GameTooltip:Show(); -end - -function LFDRoleButton_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(_G["ROLE_DESCRIPTION_"..self.role], nil, nil, nil, nil, true); - if ( self.permDisabled ) then - if(self.permDisabledTip)then - GameTooltip:AddLine(self.permDisabledTip, 1, 0, 0, true); - end - elseif ( self.disabledTooltip and not self:IsEnabled() ) then - GameTooltip:AddLine(self.disabledTooltip, 1, 0, 0, true); - elseif ( self.lockedIndicator:IsShown() ) then - local queueDungeonID = LFDQueueFrame.type; - local roleID = self:GetID(); - local reasons; - GameTooltip:SetText(ERR_ROLE_UNAVAILABLE, 1.0, 1.0, 1.0, true); - if ( type(queueDungeonID) == "number" ) then - local textTable = LFGRoleButton_LockReasonsTextTable(queueDungeonID, roleID); - for text,_ in pairs( textTable ) do - GameTooltip:AddLine(text, nil, nil, nil, true); - end - else - local textTable = {}; - for dungeonID, isChecked in pairs(LFGEnabledList) do - if( not LFGIsIDHeader(dungeonID) and isChecked and not LFGLockList[dungeonID] ) then - LFGRoleButton_LockReasonsTextTable(dungeonID, roleID, textTable); - end - end - for text, _ in pairs( textTable ) do - GameTooltip:AddLine(text, nil, nil, nil, true); - end - end - GameTooltip:Show(); - return; - elseif ( self.alert:IsShown() ) then - GameTooltip:SetText(INSTANCE_ROLE_WARNING_TITLE, 1.0, 1.0, 1.0, true); - GameTooltip:AddLine(INSTANCE_ROLE_WARNING_TEXT, nil, nil, nil, true); - end - GameTooltip:Show(); - LFGFrameRoleCheckButton_OnEnter(self); -end - -function LFGSpecificChoiceEnableButton_SetIsRadio(button, isRadio) - if ( isRadio ) then - button:SetSize(17, 17) - else - button:SetSize(20, 20); - end - SetCheckButtonIsRadio(button, isRadio); -end - ---More functions - -function LFGFrameRoleCheckButton_OnEnter(self) - if ( self.checkButton:IsEnabled() ) then - self.checkButton:LockHighlight(); - end -end - -function LFGConstructDeclinedMessage(dungeonID) - local returnVal = ""; - local hasTimeRestriction = false; - for i=1, GetLFDLockPlayerCount() do - local playerName, lockedReason, subReason1, subReason2, secondReasonID, secondReasonString = GetLFDLockInfo(dungeonID, i); - if ( lockedReason == Enum.LFGSlotInvalidReason.PlayerConditionFailed and (subReason1 == 29 or subReason1 == 30 or subReason1 == 31) ) then --WRONG_TIME_RANGE, WRONG_TIME, WRONG_WORLD_STATE_EXPRESSION - hasTimeRestriction = true; - elseif ( lockedReason ~= 0 ) then - local who; - if ( i == 1 ) then - who = "SELF"; - else - who = "OTHER"; - end - local text = secondReasonString; - if( not text ) then - local id = secondReasonID or lockedReason; - text = format(GetLFGInstanceErrorString(who, lockedReason, subReason1), playerName, subReason1, subReason2) - end - if ( returnVal ) then - returnVal = returnVal.."\n"..text; - else - returnVal = text; - end - end - end - if ( hasTimeRestriction ) then - --Since time applies for all players, no reason to display it once for each. - --We may have to change this if we let players group with their past selves via time travel. - return INSTANCE_UNAVAILABLE_OTHER_TOO_SOON; - end - return returnVal; -end - ---Ready popup functions - -function LFGDungeonReadyPopup_OnFail() - PlaySound(SOUNDKIT.LFG_DENIED); - if ( LFGDungeonReadyDialog:IsShown() ) then - LFGDebug("Proposal Hidden: Proposal failed."); - StaticPopupSpecial_Hide(LFGDungeonReadyPopup); - elseif ( LFGDungeonReadyPopup:IsShown() ) then - LFGDungeonReadyPopup.closeIn = LFD_PROPOSAL_FAILED_CLOSE_TIME; - LFGDungeonReadyPopup:SetScript("OnUpdate", LFGDungeonReadyPopup_OnUpdate); - end -end - -function LFGDungeonReadyPopup_OnUpdate(self, elapsed) - self.closeIn = self.closeIn - elapsed; - if ( self.closeIn < 0 ) then --We remove the OnUpdate and closeIn OnHide - LFGDebug("Proposal Hidden: Failure close timer expired."); - StaticPopupSpecial_Hide(LFGDungeonReadyPopup); - end -end - -function LFGDungeonReadyPopup_Update() - local proposalExists, id, typeID, subtypeID, name, backgroundTexture, role, hasResponded, totalEncounters, completedEncounters, numMembers, isLeader, _, _, isSilent = GetLFGProposal(); - if ( not proposalExists ) then - LFGDebug("Proposal Hidden: No proposal exists."); - StaticPopupSpecial_Hide(LFGDungeonReadyPopup); - return; - elseif ( isSilent ) then - LFGDebug("Proposal Hidden: Proposal is silent."); - StaticPopupSpecial_Hide(LFGDungeonReadyPopup); - return; - end - - --When the group doesn't require a role (like scenarios and legacy raids), we get "NONE" as the role - if ( role == "NONE" ) then - role = "DAMAGER"; - end - - LFGDungeonReadyPopup.dungeonID = id; - - local leaveText = LEAVE_QUEUE; - if ( subtypeID == LFG_SUBTYPEID_RAID or subtypeID == LFG_SUBTYPEID_FLEXRAID ) then - LFGDungeonReadyDialog.enterButton:SetText(ENTER_LFG); - elseif ( subtypeID == LFG_SUBTYPEID_SCENARIO ) then - if ( numMembers > 1 ) then - LFGDungeonReadyDialog.enterButton:SetText(ENTER_LFG); - else - LFGDungeonReadyDialog.enterButton:SetText(ACCEPT); - leaveText = CANCEL; - end - else - LFGDungeonReadyDialog.enterButton:SetText(ENTER_LFG); - end - LFGDungeonReadyDialog.leaveButton:SetText(leaveText); - - if ( hasResponded ) then - if ( subtypeID == LFG_SUBTYPEID_SCENARIO or subtypeID == LFG_SUBTYPEID_FLEXRAID or subtypeID == LFG_SUBTYPEID_WORLDPVP) then - LFGDungeonReadyDialog:Hide(); - -- there may be solo scenarios - if ( numMembers > 1 ) then - LFGDungeonReadyStatus:Show(); - LFGDungeonReadyStatusIndividual:Hide(); - LFGDungeonReadyStatusGrouped:Hide(); - LFGDungeonReadyStatusRoleless:Show(); - LFGDungeonReadyStatusRoleless_UpdateCount(LFGDungeonReadyStatusRoleless.ready, numMembers); - else - LFGDungeonReadyStatus:Hide(); - end - elseif ( numMembers > 5 or subtypeID == LFG_SUBTYPEID_RAID ) then - LFGDungeonReadyStatus:Show(); - LFGDungeonReadyStatusIndividual:Hide(); - LFGDungeonReadyStatusRoleless:Hide(); - LFGDungeonReadyStatusGrouped:Show(); - LFGDungeonReadyDialog:Hide(); - - LFGDungeonReadyStatusGrouped_UpdateIcon(LFGDungeonReadyStatusGroupedTank, "TANK", numMembers); - LFGDungeonReadyStatusGrouped_UpdateIcon(LFGDungeonReadyStatusGroupedHealer, "HEALER", numMembers); - LFGDungeonReadyStatusGrouped_UpdateIcon(LFGDungeonReadyStatusGroupedDamager, "DAMAGER", numMembers); - - if ( not LFGDungeonReadyPopup:IsShown() or StaticPopup_IsLastDisplayedFrame(LFGDungeonReadyPopup) ) then - LFGDungeonReadyPopup:SetHeight(LFGDungeonReadyStatus:GetHeight()); - end - else - LFGDungeonReadyStatus:Show(); - LFGDungeonReadyStatusGrouped:Hide(); - LFGDungeonReadyStatusRoleless:Hide(); - LFGDungeonReadyStatusIndividual:Show(); - LFGDungeonReadyDialog:Hide(); - - for i=1, numMembers do - LFGDungeonReadyStatusIndividual_UpdateIcon(_G["LFGDungeonReadyStatusIndividualPlayer"..i]); - end - for i=numMembers+1, NUM_LFD_MEMBERS do - _G["LFGDungeonReadyStatusIndividualPlayer"..i]:Hide(); - end - - if ( not LFGDungeonReadyPopup:IsShown() or StaticPopup_IsLastDisplayedFrame(LFGDungeonReadyPopup) ) then - LFGDungeonReadyPopup:SetHeight(LFGDungeonReadyStatus:GetHeight()); - end - end - else - LFGDungeonReadyDialog:Show(); - LFGDungeonReadyStatus:Hide(); - - local LFGDungeonReadyDialog = LFGDungeonReadyDialog; --Make a local copy. - - -- there's almost no difference between specific and random scenario display - if ( typeID == TYPEID_RANDOM_DUNGEON and subtypeID ~= LFG_SUBTYPEID_SCENARIO ) then - LFGDungeonReadyDialog.background:SetDrawLayer("BACKGROUND"); - LFGDungeonReadyDialog.background:SetWidth(294); - LFGDungeonReadyDialog.instanceInfo.underline:Show(); - - LFGDungeonReadyDialog.label:SetText(RANDOM_DUNGEON_IS_READY); - - LFGDungeonReadyDialog.instanceInfo:Hide(); - - if ( completedEncounters > 0 ) then - LFGDungeonReadyDialog.randomInProgress:Show(); - LFGDungeonReadyPopup:SetHeight(223); - LFGDungeonReadyDialog.background:SetTexCoord(0, 1, 0, 1); - else - LFGDungeonReadyDialog.randomInProgress:Hide(); - LFGDungeonReadyPopup:SetHeight(193); - LFGDungeonReadyDialog.background:SetTexCoord(0, 1, 0, 118/128); - end - else - LFGDungeonReadyDialog.randomInProgress:Hide(); - LFGDungeonReadyPopup:SetHeight(223); - LFGDungeonReadyDialog.background:SetTexCoord(0, 1, 0, 1); - if ( subtypeID == LFG_SUBTYPEID_SCENARIO ) then - LFGDungeonReadyDialog.background:SetDrawLayer("BORDER"); - LFGDungeonReadyDialog.background:SetWidth(290); - LFGDungeonReadyDialog.instanceInfo.underline:Hide(); - else - LFGDungeonReadyDialog.background:SetDrawLayer("BACKGROUND"); - LFGDungeonReadyDialog.background:SetWidth(294); - LFGDungeonReadyDialog.instanceInfo.underline:Show(); - end - - if ( numMembers > 1 ) then - LFGDungeonReadyDialog.label:SetText(SPECIFIC_DUNGEON_IS_READY); - else - LFGDungeonReadyDialog.label:SetText(SPECIFIC_INSTANCE_IS_READY); - end - LFGDungeonReadyDialog_UpdateInstanceInfo(name, completedEncounters, totalEncounters); - LFGDungeonReadyDialog.instanceInfo:Show(); - end - if ( not LFGDungeonReadyDialog.background:SetTexture(backgroundTexture) ) then --We haven't added this texture yet. Default to the Deadmines. - LFGDungeonReadyDialog.background:SetTexture("Interface\\LFGFrame\\UI-LFG-BACKGROUND-Deadmines"); --DEBUG FIXME Default probably shouldn't be Deadmines - end - - local showRole = true; -- scenarios will set this to false - if ( subtypeID == LFG_SUBTYPEID_SCENARIO or subtypeID == LFG_SUBTYPEID_FLEXRAID ) then - showRole = false; - end - - if ( showRole ) then - LFGDungeonReadyDialogRoleIcon:Show(); - LFGDungeonReadyDialogYourRoleDescription:Show(); - LFGDungeonReadyDialogRoleLabel:SetText(_G[role]); - local showDisabled = false; - LFGDungeonReadyDialogRoleIconTexture:SetAtlas(GetIconForRole(role, showDisabled), TextureKitConstants.IgnoreAtlasSize); - if ( isLeader ) then - LFGDungeonReadyDialogRoleIconLeaderIcon:Show(); - else - LFGDungeonReadyDialogRoleIconLeaderIcon:Hide(); - end - else - LFGDungeonReadyDialogRoleIcon:Hide(); - LFGDungeonReadyDialogYourRoleDescription:Hide(); - LFGDungeonReadyDialogRoleLabel:SetText(nil); - LFGDungeonReadyDialogRoleIconLeaderIcon:Hide(); - end - - LFGDungeonReadyDialog_UpdateRewards(id, role); - LFGDungeonReadyDialogRewardsFrame:ClearAllPoints(); - if ( subtypeID == LFG_SUBTYPEID_SCENARIO or subtypeID == LFG_SUBTYPEID_FLEXRAID ) then - LFGDungeonReadyDialogRewardsFrame:SetPoint("BOTTOM", LFGDungeonReadyDialogRoleIcon, "BOTTOM", 0, 14); - else - LFGDungeonReadyDialogRewardsFrame:SetPoint("BOTTOMLEFT", LFGDungeonReadyDialogRoleIcon, "BOTTOMRIGHT", 19, 14); - end - end -end - -function LFGDungeonReadyDialog_UpdateRewards(dungeonID, role) - local doneToday, moneyAmount, moneyVar, experienceGained, experienceVar, numRewards, spellID = GetLFGDungeonRewards(dungeonID); - - local frameID = 1; - - if ( moneyAmount > 0 or experienceGained > 0 ) then --hasMiscReward ) then - LFGDungeonReadyDialogReward_SetMisc(LFGDungeonReadyDialogRewardsFrameReward1); - frameID = 2; - end - - if ( moneyAmount == 0 and experienceGained == 0 and numRewards == 0 ) then - LFGDungeonReadyDialogRewardsFrameLabel:Hide(); - else - LFGDungeonReadyDialogRewardsFrameLabel:Show(); - end - - for i = 1, numRewards do - local _, _, _, isBonusReward = GetLFGDungeonRewardInfo(dungeonID, i); - if ( not isBonusReward ) then - local frame = LFGDungeonReadyDialogRewardsFrame.Rewards[frameID]; - if ( not frame ) then - frame = CreateFrame("FRAME", "LFGDungeonReadyDialogRewardsFrameReward"..frameID, LFGDungeonReadyDialogRewardsFrame, "LFGDungeonReadyRewardTemplate"); - frame:SetID(frameID); - LFD_MAX_REWARDS = frameID; - end - LFGDungeonReadyDialogReward_SetReward(frame, dungeonID, i, "reward") - frameID = frameID + 1; - end - end - - if ( not IsInGroup(LE_PARTY_CATEGORY_HOME) ) then - for shortageIndex = 1, LFG_ROLE_NUM_SHORTAGE_TYPES do - local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(dungeonID, shortageIndex); - if ( eligible and ((role == "TANK" and forTank) or (role == "HEALER" and forHealer) or (role == "DAMAGER" and forDamage)) ) then - for rewardIndex=1, itemCount do - local frame = LFGDungeonReadyDialogRewardsFrame.Rewards[frameID]; - if ( not frame ) then - frame = CreateFrame("FRAME", "LFGDungeonReadyDialogRewardsFrameReward"..frameID, LFGDungeonReadyDialogRewardsFrame, "LFGDungeonReadyRewardTemplate"); - frame:SetID(frameID); - LFD_MAX_REWARDS = frameID; - end - LFGDungeonReadyDialogReward_SetReward(frame, dungeonID, rewardIndex, "shortage", shortageIndex); - frameID = frameID + 1; - end - end - end - end - - --Hide the unused ones - for i = frameID, LFD_MAX_REWARDS do - LFGDungeonReadyDialogRewardsFrame.Rewards[i]:Hide(); - end - - local usedButtons= frameID - 1; - - if ( usedButtons > 0 ) then - local DOUBLE_ROW_MIN_THRESHOLD = 4; - local rowSize = math.floor((usedButtons + 1) / 2); - local numRows = usedButtons < DOUBLE_ROW_MIN_THRESHOLD and 1 or 2; - for row = 1, numRows do - local numInRow = row == 1 and rowSize or (usedButtons - rowSize); - local firstIndex = (row - 1) * rowSize + 1; - local baseReward = LFGDungeonReadyDialogRewardsFrame.Rewards[firstIndex]; - --Set up positions - local iconOffset = -5; - local areaWidth = numInRow * baseReward:GetWidth() + (numInRow - 1) * iconOffset; - - local yOffset; - if numRows > 1 and row == 1 then - yOffset = baseReward:GetHeight(); - else - yOffset = 5; - end - - baseReward:SetPoint("LEFT", LFGDungeonReadyDialogRewardsFrame, "CENTER", -areaWidth/2, yOffset); - for i = 2, numInRow do - local index = firstIndex + i - 1; - LFGDungeonReadyDialogRewardsFrame.Rewards[index]:SetPoint("LEFT", LFGDungeonReadyDialogRewardsFrame.Rewards[index - 1], "RIGHT", iconOffset, 0); - end - end - end -end - -function LFGDungeonReadyDialogReward_SetMisc(button) - SetPortraitToTexture(button.texture, "Interface\\Icons\\inv_misc_coin_02"); - button.rewardType = "misc"; - button:Show(); -end - -function LFGDungeonReadyDialogReward_SetReward(button, dungeonID, rewardIndex, rewardType, rewardArg) - local name, texturePath, quantity; - if ( rewardType == "reward" ) then - name, texturePath, quantity = GetLFGDungeonRewardInfo(dungeonID, rewardIndex); - elseif ( rewardType == "shortage" ) then - name, texturePath, quantity = GetLFGDungeonShortageRewardInfo(dungeonID, rewardArg, rewardIndex); - end - if ( texturePath ) then --Otherwise, we may be waiting on the item data to come from the server. - SetPortraitToTexture(button.texture, texturePath); - end - button.rewardType = rewardType; - button.rewardID = rewardIndex; - button.rewardArg = rewardArg; - button:Show(); -end - -function LFGDungeonReadyDialogReward_OnEnter(self, dungeonID) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - if ( self.rewardType == "misc" ) then - GameTooltip:AddLine(REWARD_ITEMS_ONLY); - local doneToday, moneyAmount, moneyVar, experienceGained, experienceVar, numRewards, spellID = GetLFGDungeonRewards(LFGDungeonReadyPopup.dungeonID); - - if ( experienceGained > 0 ) then - GameTooltip:AddLine(string.format(GAIN_EXPERIENCE, experienceGained)); - end - if ( moneyAmount > 0 ) then - SetTooltipMoney(GameTooltip, moneyAmount, nil); - end - elseif ( self.rewardType == "reward" ) then - GameTooltip:SetLFGDungeonReward(LFGDungeonReadyPopup.dungeonID, self.rewardID); - elseif ( self.rewardType == "shortage" ) then - GameTooltip:SetLFGDungeonShortageReward(LFGDungeonReadyPopup.dungeonID, self.rewardArg, self.rewardID); - end - GameTooltip:Show(); -end - -function LFGDungeonReadyDialog_UpdateInstanceInfo(name, completedEncounters, totalEncounters) - local instanceInfoFrame = LFGDungeonReadyDialogInstanceInfoFrame; - instanceInfoFrame.name:SetFontObject(GameFontNormalLarge); - instanceInfoFrame.name:SetText(name); - if ( instanceInfoFrame.name:GetStringWidth() + 20 > LFGDungeonReadyDialog:GetWidth() ) then - instanceInfoFrame.name:SetFontObject(GameFontNormal); - end - - if ( totalEncounters > 0 ) then - instanceInfoFrame.statusText:SetFormattedText(BOSSES_KILLED, completedEncounters, totalEncounters); - else - instanceInfoFrame.statusText:SetText(nil); - end -end - -function LFGDungeonReadyDialogInstanceInfo_OnEnter(self) - local numBosses = select(9, GetLFGProposal()); - local isHoliday = select(13, GetLFGProposal()); - - if ( numBosses == 0 or isHoliday) then - return; - end - - GameTooltip:SetOwner(self, "ANCHOR_BOTTOM"); - GameTooltip:AddLine(BOSSES) - for i=1, numBosses do - local bossName, _, isKilled = GetLFGProposalEncounter(i); - if ( isKilled ) then - GameTooltip:AddDoubleLine(bossName, BOSS_DEAD, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - else - GameTooltip:AddDoubleLine(bossName, BOSS_ALIVE, GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b, GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); - end - end - GameTooltip:Show(); -end - -function LFGDungeonReadyStatus_ResetReadyStates() - for i=1, NUM_LFD_MEMBERS do - local button = _G["LFGDungeonReadyStatusIndividualPlayer"..i]; - button.readyStatus = "unknown"; - end -end - -function LFGDungeonReadyStatusIndividual_UpdateIcon(button) - local isLeader, role, level, responded, accepted, name, class = GetLFGProposalMember(button:GetID()); - - local showDisabled = false; - button.texture:SetAtlas(GetIconForRole(role, showDisabled), TextureKitConstants.IgnoreAtlasSize); - - if ( not responded ) then - button.statusIcon:SetAtlas(READY_CHECK_WAITING_ATLAS, TextureKitConstants.IgnoreAtlasSize); - elseif ( accepted ) then - if ( button.readyStatus ~= "accepted" ) then - button.readyStatus = "accepted"; - PlaySound(SOUNDKIT.LFG_ROLE_CHECK); - end - button.statusIcon:SetAtlas(READY_CHECK_READY_ATLAS, TextureKitConstants.IgnoreAtlasSize); - else - button.statusIcon:SetAtlas(READY_CHECK_NOT_READY_ATLAS, TextureKitConstants.IgnoreAtlasSize); - end - - button:Show(); -end - -function LFGDungeonReadyStatusGrouped_UpdateIcon(button, buttonRole, numMembers) - local showDisabled = false; - button.texture:SetAtlas(GetIconForRole(buttonRole, showDisabled), TextureKitConstants.IgnoreAtlasSize); - - local numTotal, numAccepted = 0, 0; - local didDecline = false; - for i=1, numMembers do - local isLeader, role, level, responded, accepted, name, class = GetLFGProposalMember(i); - if ( role == buttonRole ) then - numTotal = numTotal + 1; - if ( responded ) then - if ( accepted ) then - numAccepted = numAccepted + 1; - else - didDecline = true; - end - end - end - end - - button.count:SetFormattedText(PLAYERS_FOUND_OUT_OF_MAX, numAccepted, numTotal); - - if ( didDecline ) then - button.statusIcon:SetAtlas(READY_CHECK_NOT_READY_ATLAS, TextureKitConstants.IgnoreAtlasSize); - elseif ( numAccepted == numTotal ) then - button.statusIcon:SetAtlas(READY_CHECK_READY_ATLAS, TextureKitConstants.IgnoreAtlasSize); - else - button.statusIcon:SetAtlas(READY_CHECK_WAITING_ATLAS, TextureKitConstants.IgnoreAtlasSize); - end -end - -function LFGDungeonReadyStatusRoleless_UpdateCount(readyButton, numMembers) - local numAccepted = 0; - for i=1, numMembers do - local isLeader, role, level, responded, accepted, name, class = GetLFGProposalMember(i); - if ( responded ) then - if ( accepted ) then - numAccepted = numAccepted + 1; - end - end - end - readyButton.count:SetFormattedText(PLAYERS_FOUND_OUT_OF_MAX, numAccepted, numMembers); -end - --------Utility functions----------- -function LFDGetNumDungeons() - return #LFDDungeonList; -end - -function LFGIsIDHeader(id) - return id < 0; -end - -function ScenariosGetNumDungeons() - return #ScenariosList; -end --------List filtering functions----------- -local hasSetUp = false; -function LFGDungeonList_Setup() - if ( not hasSetUp ) then - hasSetUp = true; - LFGCollapseList = GetLFDChoiceCollapseState(LFGCollapseList); --We maintain this list in Lua - LFGEnabledList = GetLFDChoiceEnabledState(LFGEnabledList); --We maintain this list in Lua - LFGLockList = GetLFGLockList(); - - LFDQueueFrame_Update(); - if ScenariosEnabled() then - ScenarioQueueFrame_Update(); - end - return true; - end - return false; -end - -function LFGQueueFrame_UpdateLFGDungeonList(dungeonList, hiddenByCollapseList, checkedList, filterFunc, filterMaxLevelDiff) - if ( LFGDungeonList_Setup() ) then - return; - end - - local enableList = checkedList; - - table.wipe(hiddenByCollapseList); - - --1. Remove all choices that don't match the filter. - LFGListFilterChoices(dungeonList, filterFunc, filterMaxLevelDiff); - - --2. Remove all headers that have no entries below them. - LFGListRemoveHeadersWithoutChildren(dungeonList); - - --3. Update the enabled state of headers. - LFGListUpdateHeaderEnabledAndLockedStates(dungeonList, enableList, hiddenByCollapseList); - - --4. Move the children of collapsed headers into the hiddenByCollapse list. - LFGListRemoveCollapsedChildren(dungeonList, hiddenByCollapseList); -end - ---filterFunc returns true if the object should be shown. -function LFGListFilterChoices(list, filterFunc, filterMaxLevelDiff) - local currentPosition = 1; - while ( currentPosition <= #list ) do - local id = list[currentPosition]; - local isHeader = LFGIsIDHeader(id); - if ( isHeader or filterFunc(id, filterMaxLevelDiff) ) then - currentPosition = currentPosition + 1; - else - tremove(list, currentPosition); - end - end -end - -function LFGListRemoveHeadersWithoutChildren(list) - --This relies on unparented children coming first. - local currentPosition = 1; - --The discrepency between nextObject>IsChild< and >isHeader< is due to the way we want to handle empty values. - local nextObjectIsChild = not LFGIsIDHeader(list[1] or 0); - while ( currentPosition <= #list ) do - local isHeader = not nextObjectIsChild; - nextObjectIsChild = currentPosition < #list and not LFGIsIDHeader(list[currentPosition+1]); - if ( isHeader and not nextObjectIsChild ) then - tremove(list, currentPosition); - else - currentPosition = currentPosition + 1; - end - end -end - ---false = no children so far ---0 = all children unchecked ---1 = some children checked, some unchecked ---2 = all children checked -function LFGListUpdateHeaderEnabledAndLockedStates(dungeonList, enabledList, hiddenByCollapseList) - for i=1, #dungeonList do - local id = dungeonList[i]; - if ( LFGIsIDHeader(id) ) then - enabledList[id] = false; - LFGLockList[id] = {lfgID = id, reason = 0}; - elseif ( not LFGLockList[id] ) then - local groupID = select(LFG_RETURN_VALUES.groupID, GetLFGDungeonInfo(id)); - LFGLockList[groupID] = nil; - local idState = enabledList[id]; - local groupState = enabledList[groupID]; - if ( idState ) then - if ( not groupState or groupState == 2 ) then --This code handles the 3 states of headers (enabled, disabled, someandsome) - enabledList[groupID] = 2; - elseif ( groupState == 0 or groupState == 1 ) then - enabledList[groupID] = 1; - end - else - if ( not groupState or groupState == 0 ) then - enabledList[groupID] = 0; - elseif ( groupState == 1 or groupState == 2 ) then - enabledList[groupID] = 1; - end - end - end - end - for i=1, #hiddenByCollapseList do - local id = hiddenByCollapseList[i]; - if ( LFGIsIDHeader(id) ) then - enabledList[id] = false; - LFGLockList[id] = {lfgID = id, reason = 0}; - elseif ( not LFGLockList[id] ) then - local groupID = select(LFG_RETURN_VALUES.groupID, GetLFGDungeonInfo(id)); - LFGLockList[groupID] = nil; - local idState = enabledList[id]; - local groupState = enabledList[groupID]; - if ( idState ) then - if ( not groupState or groupState == 2 ) then - enabledList[groupID] = 2; - elseif ( groupState == 0 or groupState == 1 ) then - enabledList[groupID] = 1; - end - else - if ( not groupState or groupState == 0 ) then - enabledList[groupID] = 0; - elseif ( groupState == 1 or groupState == 2 ) then - enabledList[groupID] = 1; - end - end - end - end -end - -function LFGListRemoveCollapsedChildren(list, hiddenByCollapseList) - local currentPosition = 1; - while ( currentPosition <= #list ) do - local id = list[currentPosition]; - if ( not LFGIsIDHeader(id) and LFGCollapseList[id] ) then - tinsert(hiddenByCollapseList, tremove(list, currentPosition)); - else - currentPosition = currentPosition + 1; - end - end -end - ---Reward frame functions - - -function LFGRewardsFrame_AdjustFont(self) - -- overriden in localization files in Classic -end - -function LFGRewardsFrame_OnLoad(self) - self.numRewardFrames = 1; - self.description:SetTextColor(1, 1, 1); - self.rewardsDescription:SetTextColor(1, 1, 1); - self.xpLabel:SetTextColor(1, 1, 1); -end - -function LFGRewardsFrame_UpdateFrame(parentFrame, dungeonID, background) - local parentName = parentFrame:GetName(); - - if ( not dungeonID ) then - parentFrame:Hide(); - return; - end - - parentFrame:Show(); - - local dungeonName, typeID, subtypeID,_,_,_,_,_,_,_,backgroundTexture,difficulty,_,dungeonDescription, isHoliday, bonusRepAmount, _, isTimewalker = GetLFGDungeonInfo(dungeonID); - local isScenario = (subtypeID == LFG_SUBTYPEID_SCENARIO); - local doneToday, moneyAmount, moneyVar, experienceGained, experienceVar, numRewards, spellID = GetLFGDungeonRewards(dungeonID); - - local leaderChecked, tankChecked, healerChecked, damageChecked = LFDQueueFrame_GetRoles(); - - if ( not backgroundTexture ) then - if ( difficulty > 0 ) then - backgroundTexture = "Interface\\LFGFrame\\UI-LFG-BACKGROUND-HEROIC"; - else - backgroundTexture = "Interface\\LFGFrame\\UI-LFG-BACKGROUND-QUESTPAPER"; - end - end - background:SetTexture(backgroundTexture); - - local lastFrame = parentFrame.rewardsLabel; - if ( isTimewalker ) then - parentFrame.rewardsDescription:SetText(LFD_RANDOM_REWARD_EXPLANATION2); - - parentFrame.title:SetText(LFG_TYPE_RANDOM_TIMEWALKER_DUNGEON); - parentFrame.description:SetText(LFD_TIMEWALKER_RANDOM_EXPLANATION); - elseif ( isHoliday ) then - if ( doneToday ) then - parentFrame.rewardsDescription:SetText(LFD_HOLIDAY_REWARD_EXPLANATION2); - else - parentFrame.rewardsDescription:SetText(LFD_HOLIDAY_REWARD_EXPLANATION1); - end - parentFrame.title:SetText(dungeonName); - parentFrame.description:SetText(dungeonDescription); - elseif ( subtypeID == LFG_SUBTYPEID_RAID ) then - if ( doneToday ) then --May not actually be today, but whatever this reset period is. - parentFrame.rewardsDescription:SetText(RF_REWARD_EXPLANATION2); - else - parentFrame.rewardsDescription:SetText(RF_REWARD_EXPLANATION1); - end - parentFrame.title:SetText(dungeonName); - parentFrame.description:SetText(dungeonDescription); - else - local numCompletions, isWeekly = LFGRewardsFrame_EstimateRemainingCompletions(dungeonID); - if ( numCompletions <= 0 ) then - parentFrame.rewardsDescription:SetText(LFD_RANDOM_REWARD_EXPLANATION2); - elseif ( isWeekly ) then - parentFrame.rewardsDescription:SetText(format(LFD_REWARD_DESCRIPTION_WEEKLY, numCompletions)); - else - parentFrame.rewardsDescription:SetText(format(LFD_REWARD_DESCRIPTION_DAILY, numCompletions)); - end - if ( isScenario ) then - if ( LFG_IsHeroicScenario(dungeonID) ) then - parentFrame.title:SetText(LFG_TYPE_RANDOM_HEROIC_SCENARIO); - parentFrame.description:SetText(SCENARIO_RANDOM_HEROIC_EXPLANATION); - else - parentFrame.title:SetText(LFG_TYPE_RANDOM_SCENARIO); - parentFrame.description:SetText(SCENARIO_RANDOM_EXPLANATION); - end - else - parentFrame.title:SetText(LFG_TYPE_RANDOM_DUNGEON); - parentFrame.description:SetText(LFD_RANDOM_EXPLANATION); - end - end - - local itemButtonIndex = 1; - for i=1, numRewards do - local name, texture, numItems, isBonusReward, rewardType, rewardID, quality = GetLFGDungeonRewardInfo(dungeonID, i); - if (isBonusReward == false) then - if rewardType == "currency" and C_CurrencyInfo.IsCurrencyContainer(rewardID, numItems) then - name, texture, numItems, quality = CurrencyContainerUtil.GetCurrencyContainerInfo(rewardID, numItems, name, texture, quality); - end - lastFrame = LFGRewardsFrame_SetItemButton(parentFrame, dungeonID, itemButtonIndex, i, name, texture, numItems, rewardType, rewardID, quality); - itemButtonIndex = itemButtonIndex + 1; - end - end - - if ( not IsInGroup(LE_PARTY_CATEGORY_HOME) ) then - for shortageIndex=1, LFG_ROLE_NUM_SHORTAGE_TYPES do - local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(dungeonID, shortageIndex); - if ( eligible and ((tankChecked and forTank) or (healerChecked and forHealer) or (damageChecked and forDamage)) ) then - for rewardIndex=1, itemCount do - local name, texture, numItems, _, rewardType, rewardID, quality = GetLFGDungeonShortageRewardInfo(dungeonID, shortageIndex, rewardIndex); - if rewardType == "currency" and C_CurrencyInfo.IsCurrencyContainer(rewardID, numItems) then - name, texture, numItems, quality = CurrencyContainerUtil.GetCurrencyContainerInfo(rewardID, numItems, name, texture, quality); - end - lastFrame = LFGRewardsFrame_SetItemButton(parentFrame, dungeonID, itemButtonIndex, rewardIndex, name, texture, numItems, rewardType, rewardID, quality, shortageIndex, forTank, forHealer, forDamage); - itemButtonIndex = itemButtonIndex + 1; - end - end - end - end - - for i=itemButtonIndex, parentFrame.numRewardFrames do - _G[parentName.."Item"..i]:Hide(); - end - - local totalRewards = itemButtonIndex - 1; - - if ( totalRewards > 0 or moneyAmount > 0 or experienceGained > 0 ) then - parentFrame.rewardsLabel:Show(); - parentFrame.rewardsDescription:Show(); - lastFrame = parentFrame.rewardsDescription; - else - parentFrame.rewardsLabel:Hide(); - parentFrame.rewardsDescription:Hide(); - end - - local amountText = parentFrame.MoneyReward.Name; - if ( moneyAmount > 0 ) then - amountText:SetText(GetMoneyString(moneyAmount)); - if ( amountText:IsTruncated() ) then - amountText:SetText(GetMoneyString(moneyAmount - mod(moneyAmount, 100))); - if ( amountText:IsTruncated() ) then - amountText:SetText(GetMoneyString(moneyAmount - mod(moneyAmount, 10000))); - end - end - parentFrame.MoneyReward:ClearAllPoints() - if ( itemButtonIndex > 1 ) then - if ( mod(itemButtonIndex, 2) == 0 ) then - parentFrame.MoneyReward:SetPoint("LEFT", parentName.."Item"..(itemButtonIndex-1), "RIGHT", 0, 0); - else - parentFrame.MoneyReward:SetPoint("TOPLEFT", parentName.."Item"..(itemButtonIndex-2), "BOTTOMLEFT", 0, -8); - end - else - parentFrame.MoneyReward:SetPoint("TOPLEFT", lastFrame, "BOTTOMLEFT", 0, -8); - end - - parentFrame.MoneyReward:Show(); - else - parentFrame.MoneyReward:Hide(); - end - - - if ( mod(totalRewards, 2) == 0 and parentFrame.MoneyReward:IsShown() ) then - lastFrame = parentFrame.MoneyReward; - elseif ( totalRewards > 0 ) then - lastFrame = _G[parentName.."Item"..(totalRewards - mod(totalRewards+1, 2))]; - end - - if ( experienceGained > 0 ) then - parentFrame.xpAmount:SetText(experienceGained); - parentFrame.xpLabel:SetPoint("TOPLEFT", lastFrame, "BOTTOMLEFT", 20, -10); - - parentFrame.xpLabel:Show(); - parentFrame.xpAmount:Show(); - - lastFrame = parentFrame.xpLabel; - else - parentFrame.xpLabel:Hide(); - parentFrame.xpAmount:Hide(); - end - - if ( typeID == TYPEID_RANDOM_DUNGEON ) then - parentFrame.randomList.randomID = dungeonID; - parentFrame.randomList:Show(); - parentFrame.encounterList:SetPoint("LEFT", parentFrame.randomList, "RIGHT", 5, 0); - parentFrame.title:SetPoint("TOPRIGHT", -16, -8); - else - parentFrame.randomList:Hide(); - parentFrame.encounterList:SetPoint("LEFT", parentFrame.randomList, "LEFT", 0, 0); - parentFrame.title:SetPoint("TOPRIGHT", 0, -8); - end - - parentFrame.encounterList.dungeonID = dungeonID; - local numEncounters, numCompleted = GetLFGDungeonNumEncounters(dungeonID); - if ( numCompleted > 0 ) then - parentFrame.encounterList:Show(); - else - parentFrame.encounterList:Hide(); - end - - parentFrame.spacer:SetPoint("TOPLEFT", lastFrame, "BOTTOMLEFT", 0, -10); -end - -function LFGRewardsFrame_SetItemButton(parentFrame, dungeonID, index, id, name, texture, numItems, rewardType, rewardID, quality, shortageIndex, showTankIcon, showHealerIcon, showDamageIcon) - local parentName = parentFrame:GetName(); - local frame = _G[parentName.."Item"..index]; - if ( not frame ) then - frame = CreateFrame("Button", parentName.."Item"..index, _G[parentName], "LFGRewardsLootTemplate"); - parentFrame.numRewardFrames = index; - if ( mod(index, 2) == 0 ) then - frame:SetPoint("LEFT", parentName.."Item"..(index-1), "RIGHT", 0, 0); - else - frame:SetPoint("TOPLEFT", parentName.."Item"..(index-2), "BOTTOMLEFT", 0, -5); - end - end - frame:SetID(id); - - _G[parentName.."Item"..index.."Name"]:SetText(name); - SetItemButtonTexture(frame, texture); - SetItemButtonCount(frame, numItems); - if ( rewardType == "currency" ) then - local currencyColor = GetColorForCurrencyReward(rewardID, numItems) - frame.Count:SetTextColor(currencyColor:GetRGB()); - else - frame.Count:SetTextColor(HIGHLIGHT_FONT_COLOR:GetRGB()); - end - frame.shortageIndex = shortageIndex; - frame.dungeonID = dungeonID; - - if ( shortageIndex ) then - frame.shortageBorder:Show(); - else - frame.shortageBorder:Hide(); - end - - local numRoles = (showTankIcon and 1 or 0) + (showHealerIcon and 1 or 0) + (showDamageIcon and 1 or 0); - - --Show role icons if this reward is specific to a role: - frame.roleIcon1:Hide(); - frame.roleIcon2:Hide(); - - if ( numRoles > 0 and numRoles < 3 ) then --If we give it to all 3 roles, no reason to show icons. - local roleIcon = frame.roleIcon1; - local showDisabled = false; - if ( showTankIcon ) then - roleIcon.texture:SetAtlas(GetMicroIconForRole("TANK", showDisabled), TextureKitConstants.IgnoreAtlasSize); - roleIcon.role = "TANK"; - roleIcon:Show(); - roleIcon = frame.roleIcon2; - end - if ( showHealerIcon ) then - roleIcon.texture:SetAtlas(GetMicroIconForRole("HEALER", showDisabled), TextureKitConstants.IgnoreAtlasSize); - roleIcon.role = "HEALER"; - roleIcon:Show(); - roleIcon = frame.roleIcon2; - end - if ( showDamageIcon ) then - roleIcon.texture:SetAtlas(GetMicroIconForRole("DAMAGER", showDisabled), TextureKitConstants.IgnoreAtlasSize); - roleIcon.role = "DAMAGER"; - roleIcon:Show(); - roleIcon = frame.roleIcon2; - end - - if ( numRoles == 2 ) then - frame.roleIcon1:SetPoint("LEFT", frame, "TOPLEFT", 1, -2); - else - frame.roleIcon1:SetPoint("LEFT", frame, "TOPLEFT", 10, -2); - end - end - - if ( rewardType == "item" ) then - SetItemButtonQuality(frame, quality, rewardID); - frame.IconBorder:Show(); - elseif( rewardType == "currency" ) then - SetItemButtonQuality(frame, quality, rewardID); - frame.IconBorder:Show(); - else - frame.IconBorder:Hide(); - end - - frame:Show(); - return frame; -end - -function LFGRewardsFrame_EstimateRemainingCompletions(dungeonID) - local currencyID, currencyQuantity, specificQuantity, specificLimit, overallQuantity, overallLimit, periodPurseQuantity, periodPurseLimit, purseQuantity, purseLimit, isWeekly = GetLFGDungeonRewardCapInfo(dungeonID); - if(not currencyID) then - return 0, false; - end - - local remainingAllotment = min(specificLimit - specificQuantity, overallLimit - overallQuantity); - if ( periodPurseLimit ~= 0 ) then - remainingAllotment = min(remainingAllotment, periodPurseLimit - periodPurseQuantity); - end - - if (currencyQuantity == 0) then - return 0, isWeekly; - end - - return ceil(remainingAllotment / currencyQuantity), isWeekly; -end - -function LFGRewardsFrameEncounterList_OnEnter(self) - local dungeonID = self.dungeonID; - local numEncounters, numCompleted = GetLFGDungeonNumEncounters(dungeonID); - - if ( numCompleted > 0 ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:AddLine(string.format(ERR_LOOT_GONE, numCompleted, numEncounters), HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); - for i=1, numEncounters do - local bossName, _, isKilled = GetLFGDungeonEncounterInfo(dungeonID, i); - if ( isKilled ) then - GameTooltip:AddLine(bossName, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - else - GameTooltip:AddLine(bossName, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); - end - end - GameTooltip:Show(); - end -end - --- --- LFR/LFD group invite stuff --- -function LFGInvitePopup_UpdateAcceptButton() - if ( LFGRole_GetChecked(LFGInvitePopupRoleButtonTank) or LFGRole_GetChecked(LFGInvitePopupRoleButtonHealer) or LFGRole_GetChecked(LFGInvitePopupRoleButtonDPS) ) then - LFGInvitePopupAcceptButton:Enable(); - else - LFGInvitePopupAcceptButton:Disable(); - end -end - -function LFGInvitePopupCheckButton_OnClick(checkButton) - local popup = LFGInvitePopup; - if ( not popup.allowMultipleRoles ) then - for i=1, #popup.RoleButtons do - local cb = popup.RoleButtons[i].checkButton; - if ( cb ~= checkButton ) then - cb:SetChecked(false); - end - end - end - - LFGInvitePopup_UpdateAcceptButton(); -end - -function LFGInvitePopupAccept_OnClick() - AcceptGroup(LFGRole_GetChecked(LFGInvitePopupRoleButtonTank), LFGRole_GetChecked(LFGInvitePopupRoleButtonHealer), LFGRole_GetChecked(LFGInvitePopupRoleButtonDPS)); - StaticPopupSpecial_Hide(LFGInvitePopup); -end - -function LFGInvitePopupDecline_OnClick() - DeclineGroup(); - StaticPopupSpecial_Hide(LFGInvitePopup); -end - -local function GetWarningText(isQuestSessionActive) - local warningText = {}; - - if WillAcceptInviteRemoveQueues() then - table.insert(warningText, ACCEPTING_INVITE_WILL_REMOVE_QUEUE); - end - - if isQuestSessionActive then - table.insert(warningText, QUEST_SESSION_LFG_WARNING_INVITED_TO_PARTY_WITH_ACTIVE_SYNC); - end - - return #warningText and table.concat(warningText, "\n\n") or nil; -end - -function LFGInvitePopup_Update(inviter, roleTankAvailable, roleHealerAvailable, roleDamagerAvailable, allowMultipleRoles, isQuestSessionActive) - local self = LFGInvitePopup; - local canBeTank, canBeHealer, canBeDamager = C_LFGList.GetAvailableRoles(); - local tankButton = LFGInvitePopupRoleButtonTank; - local healerButton = LFGInvitePopupRoleButtonHealer; - local damagerButton = LFGInvitePopupRoleButtonDPS; - local availableRolesField = 0; --Seems to be a ghetto bit-field - self.timeOut = StaticPopupTimeoutSec; - - local titleMarkup = isQuestSessionActive and CreateAtlasMarkup("QuestSharing-QuestLog-Replay", 19, 16) or ""; - LFGInvitePopupText:SetFormattedText(titleMarkup .. INVITATION, inviter); - - -- tank - if ( not canBeTank ) then - LFG_PermanentlyDisableRoleButton(tankButton); - elseif ( not roleTankAvailable ) then - LFG_DisableRoleButton(tankButton); - tankButton.disabledTooltip = LFG_ROLE_UNAVAILABLE; - else - LFG_EnableRoleButton(tankButton); - tankButton.disabledTooltip = nil; - availableRolesField = availableRolesField + 2; - end - -- healer - if ( not canBeHealer ) then - LFG_PermanentlyDisableRoleButton(healerButton); - elseif ( not roleHealerAvailable ) then - LFG_DisableRoleButton(healerButton); - healerButton.disabledTooltip = LFG_ROLE_UNAVAILABLE; - else - LFG_EnableRoleButton(healerButton); - healerButton.disabledTooltip = nil; - availableRolesField = availableRolesField + 4; - end - -- damage - if ( not canBeDamager ) then - LFG_PermanentlyDisableRoleButton(damagerButton); - elseif ( not roleDamagerAvailable ) then - LFG_DisableRoleButton(damagerButton); - damagerButton.disabledTooltip = LFG_ROLE_UNAVAILABLE; - else - LFG_EnableRoleButton(damagerButton); - damagerButton.disabledTooltip = nil; - availableRolesField = availableRolesField + 8; - end - - -- update whether we can only have 1 role selected - SetCheckButtonIsRadio(tankButton.checkButton, not allowMultipleRoles); - SetCheckButtonIsRadio(healerButton.checkButton, not allowMultipleRoles); - SetCheckButtonIsRadio(damagerButton.checkButton, not allowMultipleRoles); - self.allowMultipleRoles = allowMultipleRoles; - - -- if only 1 role is available, check it otherwise check none - tankButton.checkButton:SetChecked(availableRolesField == 2); - healerButton.checkButton:SetChecked(availableRolesField == 4); - damagerButton.checkButton:SetChecked(availableRolesField == 8); - - local warningText = GetWarningText(isQuestSessionActive); - if warningText then - self.QueueWarningText:SetText(warningText); - self.QueueWarningText:Show(); - self:SetHeight(LFG_INVITE_POPUP_DEFAULT_HEIGHT + self.QueueWarningText:GetHeight() + 8); - end - - LFGInvitePopup_UpdateAcceptButton(); -end - -function LFGInvitePopup_OnUpdate(self, elapsed) - self.timeOut = self.timeOut - elapsed; - if ( self.timeOut <= 0 ) then - LFGInvitePopupDecline_OnClick(); - end -end - -function LFGDungeonList_EvaluateListState(category) - local mode, subMode = GetLFGMode(category); - local enabled, queued; - if ( mode == "rolecheck" or mode == "queued" or mode == "listed" or mode == "suspended" or not LFD_IsEmpowered() ) then - enabled = false; - else - enabled = true; - end - if ( mode == "queued" or mode == "listed" or mode == "suspended" ) then - queued = true; - else - queued = false; - end - return enabled, queued; -end - -local function GetLFGDifficultyColor(level, isScalingDungeon) - if (not isScalingDungeon) then - return GetQuestDifficultyColor(level); - end - - return QuestDifficultyColors["difficult"], QuestDifficultyHighlightColors["difficult"]; -end - -function LFGDungeonListButton_SetDungeon(button, dungeonID, enabled, checkedList) - local name, typeID, subtypeID, minLevel, maxLevel, recLevel, minRecLevel, maxRecLevel, expansionLevel, groupID, textureFilename, difficulty, maxPlayers, description, isHoliday, bonusRepAmount, minPlayers, isRandomTimewalker, mapName, minGear, isScalingDungeon = GetLFGDungeonInfo(dungeonID); - button.id = dungeonID; - if ( LFGIsIDHeader(dungeonID) ) then - button.instanceName:SetText(name); - button.instanceName:SetFontObject(QuestDifficulty_Header); - button.instanceName:SetPoint("RIGHT", button, "RIGHT", 0, 0); - button.level:Hide(); - - if ( subtypeID == LFG_SUBTYPEID_HEROIC ) then - button.heroicIcon:Show(); - button.instanceName:SetPoint("LEFT", button.heroicIcon, "RIGHT", 0, 1); - else - button.heroicIcon:Hide(); - button.instanceName:SetPoint("LEFT", 40, 0); - end - - button.expandOrCollapseButton:Show(); - local isCollapsed = LFGCollapseList[dungeonID]; - button.isCollapsed = isCollapsed; - if ( isCollapsed ) then - button.expandOrCollapseButton:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP"); - else - button.expandOrCollapseButton:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP"); - end - else - button.instanceName:SetText(name); - button.instanceName:SetPoint("RIGHT", button.level, "LEFT", -10, 0); - - button.heroicIcon:Hide(); - button.instanceName:SetPoint("LEFT", 40, 0); - - if ( minLevel == maxLevel ) then - button.level:SetText(format(LFD_LEVEL_FORMAT_SINGLE, minLevel)); - else - button.level:SetText(format(LFD_LEVEL_FORMAT_RANGE, minLevel, maxLevel)); - end - button.level:Show(); - local difficultyColor = GetLFGDifficultyColor(recLevel, isScalingDungeon); - button.level:SetFontObject(difficultyColor.font); - - if ( enabled ) then - button.instanceName:SetFontObject(difficultyColor.font); - else - button.instanceName:SetFontObject(QuestDifficulty_Header); - end - - button.expandOrCollapseButton:Hide(); - button.isCollapsed = false; - end - - if ( LFGLockList[dungeonID] ) then - button.enableButton:Hide(); - button.lockedIndicator:Show(); - else - button.enableButton:Show(); - button.lockedIndicator:Hide(); - end - - local enableState = checkedList[dungeonID]; - - if ( enableState == 1 ) then --Some are checked, some aren't. - button.enableButton:SetCheckedTexture("Interface\\Buttons\\UI-MultiCheck-Up"); - button.enableButton:SetDisabledCheckedTexture("Interface\\Buttons\\UI-MultiCheck-Disabled"); - else - button.enableButton:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check"); - button.enableButton:SetDisabledCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check-Disabled"); - end - button.enableButton:SetChecked(enableState and enableState ~= 0); - - if ( enabled ) then - button.enableButton:Enable(); - else - button.enableButton:Disable(); - end -end - -function LFGList_DefaultFilterFunction(dungeonID, maxLevelDiff) - local name, typeID, subtypeID, minLevel, maxLevel, recLevel, minRecLevel, maxRecLevel, expansionLevel, groupID, textureFilename, difficulty, maxPlayers, description, isHoliday, repAmount = GetLFGDungeonInfo(dungeonID); - local level = UnitLevel("player"); - - --Check whether we're initialized yet - if ( not LFGLockList ) then - return false; - end - - --If the server tells us we can join, we won't argue - if ( not LFGLockList[dungeonID] ) then - return true; - end - - --If this doesn't have a header, we won't display it - if ( groupID == 0 ) then - return false; - end - - --If we don't have the right expansion, we won't display it - if ( EXPANSION_LEVEL < expansionLevel ) then - return false; - end - - --If we're too high above the recommended level, we won't display it - if maxLevelDiff and ( level - maxLevelDiff > recLevel ) then - return false; - end - - -- If we're not within the hard level requirements, we won't display it - if ( level < minRecLevel or level > maxRecLevel ) then - return false; - end - - --If we're the wrong faction, we won't display it. - if ( LFGLockList[dungeonID].reason == LFG_INSTANCE_INVALID_WRONG_FACTION ) then - return false; - end - - local isAvailableForAll, isAvailableForPlayer, hideIfNotJoinable = IsLFGDungeonJoinable(dungeonID); - if (isAvailableForPlayer or not hideIfNotJoinable) then - return true; - else - return false; - end -end - -function LFG_QueueForInstanceIfEnabled(category, queueID) - if ( not LFGIsIDHeader(queueID) and LFGEnabledList[queueID] and not LFGLockList[queueID] ) then - SetLFGDungeon(category, queueID); - return true; - end - return false; -end - -function LFG_JoinDungeon(category, joinType, dungeonList, hiddenByCollapseList) - -- check min group size - local hasReqGroupSize, requiredGroupSize = LFG_HasRequiredGroupSize(category, joinType, dungeonList, hiddenByCollapseList); - if ( not hasReqGroupSize ) then - UIErrorsFrame:AddMessage(format(ERR_LFG_MEMBERS_REQUIRED, requiredGroupSize), 1.0, 0.1, 0.1, 1.0); - return; - end - - if ( joinType == "specific" or joinType == "follower" ) then - ClearAllLFGDungeons(category); - for _, queueID in pairs(dungeonList) do - LFG_QueueForInstanceIfEnabled(category, queueID); - end - for _, queueID in pairs(hiddenByCollapseList) do - LFG_QueueForInstanceIfEnabled(category, queueID); - end - JoinLFG(category); - elseif ( joinType ) then - ClearAllLFGDungeons(category); - SetLFGDungeon(category, joinType); - JoinLFG(category); - end -end - -function LFG_HasRequiredGroupSize(category, joinType, dungeonList, hiddenByCollapseList) - local numGroupMembers, numRequiredPlayers; - if ( IsInGroup() ) then - numGroupMembers = GetNumGroupMembers(); - else - numGroupMembers = 1; - end - if ( joinType == "specific" or joinType == "follower" ) then - for _, queueID in pairs(dungeonList) do - if ( not LFGIsIDHeader(queueID) and LFGEnabledList[queueID] and not LFGLockList[queueID] ) then - numRequiredPlayers = select(LFG_RETURN_VALUES.minPlayers, GetLFGDungeonInfo(queueID)); - if ( numRequiredPlayers and numRequiredPlayers ~= numGroupMembers ) then - return false, numRequiredPlayers; - end - end - end - for _, queueID in pairs(hiddenByCollapseList) do - if ( not LFGIsIDHeader(queueID) and LFGEnabledList[queueID] and not LFGLockList[queueID] ) then - numRequiredPlayers = select(LFG_RETURN_VALUES.minPlayers, GetLFGDungeonInfo(queueID)); - if ( numRequiredPlayers and numRequiredPlayers ~= numGroupMembers ) then - return false, numRequiredPlayers; - end - end - end - else - numRequiredPlayers = select(LFG_RETURN_VALUES.minPlayers, GetLFGDungeonInfo(joinType)); - if ( numRequiredPlayers and numRequiredPlayers ~= numGroupMembers ) then - return false, numRequiredPlayers; - end - end - return true; -end - -function LFGDungeonList_SetHeaderCollapsed(button, dungeonList, hiddenByCollapseList) - local headerID = button.id; - local isCollapsed = not button.isCollapsed; - SetLFGHeaderCollapsed(headerID, isCollapsed); - LFGCollapseList[headerID] = isCollapsed; - for _, dungeonID in pairs(dungeonList) do - if ( select(LFG_RETURN_VALUES.groupID, GetLFGDungeonInfo(dungeonID)) == headerID ) then - LFGCollapseList[dungeonID] = isCollapsed; - end - end - for _, dungeonID in pairs(hiddenByCollapseList) do - if ( select(LFG_RETURN_VALUES.groupID, GetLFGDungeonInfo(dungeonID)) == headerID ) then - LFGCollapseList[dungeonID] = isCollapsed; - end - end -end - -function LFGDungeonList_DisableEntries() - LFGDungeonList_Setup(); - for id,_ in pairs(LFGEnabledList) do - LFGDungeonList_SetDungeonEnabled(id, false); - end -end - -local function IsValidSelectedEntry(entryID) - return LFGEnabledList[entryID] and not LFGIsIDHeader(entryID); -end - -function LFG_BuildSelectedEntriesList(visibleEntryList, hiddenByCollapseEntryList) - local selectedIDsList = {}; - - if visibleEntryList then - for _index, visibleEntryID in pairs(visibleEntryList) do - if IsValidSelectedEntry(visibleEntryID) then - table.insert(selectedIDsList, visibleEntryID); - end - end - end - - if hiddenByCollapseEntryList then - for _index, hiddenByCollapseEntryID in pairs(hiddenByCollapseEntryList) do - if IsValidSelectedEntry(hiddenByCollapseEntryID) then - table.insert(selectedIDsList, hiddenByCollapseEntryID); - end - end - end - - return selectedIDsList; -end - -function LFG_TryGetCrossFactionQueueFailureMessage(selectedEntryIDs) - if not selectedEntryIDs then - return; - end - - local isQueueingForMultiple = #selectedEntryIDs > 1; - for _index, entryID in ipairs(selectedEntryIDs) do - if not C_LFGInfo.AreCrossFactionGroupQueuesAllowed(entryID) then - return isQueueingForMultiple and ERR_LFG_NO_CROSS_FACTION_PARTIES_MULTIPLE or ERR_LFG_NO_CROSS_FACTION_PARTIES; - end - - if C_LFGInfo.DoesCrossFactionQueueRequireFullPremade(entryID) and not C_LFGInfo.DoesActivePartyMeetPremadeLaunchCount(entryID) then - return CROSS_FACTION_RAID_DUNGEON_FINDER_NOT_ENOUGH_MEMBERS_ERROR; - end - end -end - -function LFGDungeonList_SetDungeonEnabled(dungeonID, isEnabled) - - if C_PlayerInfo.IsPlayerNPERestricted() then - if isEnabled then - EventRegistry:TriggerEvent("LFGDungeonList.DungeonEnabled", dungeonID); - else - EventRegistry:TriggerEvent("LFGDungeonList.DungeonDisabled", dungeonID); - end - end - - SetLFGDungeonEnabled(dungeonID, isEnabled); - LFGEnabledList[dungeonID] = isEnabled; -end - -function LFGDungeonList_SetHeaderEnabled(category, headerID, isEnabled, dungeonList, hiddenByCollapseList) - for _, dungeonID in pairs(dungeonList) do - if ( select(LFG_RETURN_VALUES.groupID, GetLFGDungeonInfo(dungeonID)) == headerID ) then - LFGDungeonList_SetDungeonEnabled(dungeonID, isEnabled); - end - end - for _, dungeonID in pairs(hiddenByCollapseList) do - if ( select(LFG_RETURN_VALUES.groupID, GetLFGDungeonInfo(dungeonID)) == headerID ) then - LFGDungeonList_SetDungeonEnabled(dungeonID, isEnabled); - end - end - LFGEnabledList[headerID] = isEnabled; -end - -function LFGDungeonListButton_OnEnter(button, tooltipTitle) - local dungeonID = button.id; - if ( button.lockedIndicator:IsShown() ) then - if ( LFGIsIDHeader(dungeonID) ) then - --GameTooltip:SetOwner(button, "ANCHOR_RIGHT"); - --GameTooltip:AddLine(YOU_MAY_NOT_QUEUE_FOR_CATEGORY, 1.0, 1.0, 1.0); - --GameTooltip:Show(); - else - GameTooltip:SetOwner(button, "ANCHOR_TOP"); - GameTooltip:AddLine(tooltipTitle, 1.0, 1.0, 1.0); - for i=1, GetLFDLockPlayerCount() do - local playerName, lockedReason, subReason1, subReason2, secondReasonID, secondReasonString = GetLFDLockInfo(dungeonID, i); - if ( lockedReason ~= 0 ) then - local text = secondReasonString; - if ( not text ) then - local who; - if ( i == 1 ) then - who = "SELF_"; - else - who = "OTHER_"; - end - local id = secondReasonID or lockedReason; - text = format(_G["INSTANCE_UNAVAILABLE_"..who..(LFG_INSTANCE_INVALID_CODES[id] or "OTHER")], playerName, subReason1, subReason2) - end - GameTooltip:AddLine(text, nil, nil, nil, true); - end - end - GameTooltip:Show(); - end - end -end - -function LFGCooldownCover_SetUp(self, backfillFrame) - self:SetFrameLevel(self:GetParent():GetFrameLevel() + 9); - - self:RegisterEvent("PLAYER_ENTERING_WORLD"); --For logging in/reloading ui - self:RegisterEvent("LFG_COOLDOWNS_UPDATED"); - self:RegisterEvent("GROUP_ROSTER_UPDATE"); - - self.backfillFrame = backfillFrame; -end - -function LFGCooldownCover_ChangeSettings(self, showAll, showCooldown) - --showAll - whether we show people that have no cooldown/deserter - --showCooldown - whether we display "On Cooldown" for people with random dungeon cooldowns. (Only applies to queueing randomly, not to queueing for specifics.) - - self.showAll = showAll; - self.showCooldown = showCooldown; - - LFGCooldownCover_Update(self); -end - -function LFGCooldownCover_OnEvent(self, event, ...) - if ( self:GetParent():IsVisible() ) then --Otherwise, we should be updated when the parent is shown. - LFGCooldownCover_Update(self); - end -end - -function LFGCooldownCover_Update(self) - local shouldShow = false; - local hasDeserter = false; --If we have deserter, we want to show this over the specific frame as well as the random frame. - - local deserterExpiration = GetLFGDeserterExpiration(); - - local myExpireTime; - if ( deserterExpiration ) then - myExpireTime = deserterExpiration; - hasDeserter = true; - elseif ( self.showCooldown ) then - myExpireTime = GetLFGRandomCooldownExpiration(); - end - - self.myExpirationTime = myExpireTime; - - local nextIndex = 1; - local numPlayers, prefix; - if ( IsInRaid() ) then - numPlayers = GetNumGroupMembers(); - prefix = "raid"; - else - numPlayers = GetNumSubgroupMembers(); - prefix = "party"; - end - - for i = 1, numPlayers do - local unit = prefix..i; - - if ( nextIndex > #self.Names ) then - break; - end - - local nameLabel = self.Names[nextIndex]; - local statusLabel = self.Statuses[nextIndex]; - local gender = UnitSex(unit); - - local showLabels = false; - if ( UnitHasLFGDeserter(unit) ) then - statusLabel:SetFormattedText(RED_FONT_COLOR_CODE.."%s|r", GetText("DESERTER", gender)); - shouldShow = true; - hasDeserter = true; - showLabels = true; - nextIndex = nextIndex + 1; - elseif ( self.showCooldown and UnitHasLFGRandomCooldown(unit) ) then - statusLabel:SetFormattedText(RED_FONT_COLOR_CODE.."%s|r", GetText("ON_COOLDOWN", gender)); - shouldShow = true; - showLabels = true; - nextIndex = nextIndex + 1; - elseif ( self.showAll ) then - statusLabel:SetFormattedText(GREEN_FONT_COLOR_CODE.."%s|r", GetText("READY", gender)); - showLabels = true; - nextIndex = nextIndex + 1; - end - - if ( showLabels ) then - nameLabel:Show(); - statusLabel:Show(); - - local _, classFilename = UnitClass(unit); - local classColor = classFilename and RAID_CLASS_COLORS[classFilename] or NORMAL_FONT_COLOR; - nameLabel:SetFormattedText("|cff%.2x%.2x%.2x%s|r", classColor.r * 255, classColor.g * 255, classColor.b * 255, GetUnitName(unit, true)); - end - end - for i = nextIndex, #self.Names do - local nameLabel = self.Names[i]; - local statusLabel = self.Statuses[i]; - nameLabel:Hide(); - statusLabel:Hide(); - end - - if ( nextIndex == 1 ) then --We haven't shown anything - self.description:SetPoint("TOP", 0, -85); - else - self.description:SetPoint("TOP", 0, -30); - end - - if ( myExpireTime and GetTime() < myExpireTime ) then - shouldShow = true; - if ( deserterExpiration ) then - self.description:SetText(LFG_DESERTER_YOU); - else - self.description:SetText(LFG_RANDOM_COOLDOWN_YOU); - end - self.time:SetText(SecondsToTime(ceil(myExpireTime - GetTime()))); - self.time:Show(); - - self:SetScript("OnUpdate", LFGCooldownCover_OnUpdate); - else - if ( hasDeserter ) then - self.description:SetText(LFG_DESERTER_OTHER); - else - self.description:SetText(LFG_RANDOM_COOLDOWN_OTHER); - end - self.time:Hide(); - - self:SetScript("OnUpdate", nil); - end - - if ( shouldShow and ( not self.backfillFrame or not self.backfillFrame:IsShown() ) ) then - self:Show(); - else - self:Hide(); - end -end - -function LFGCooldownCover_OnUpdate(self, elapsed) - local timeRemaining = self.myExpirationTime - GetTime(); - if ( timeRemaining > 0 ) then - self.time:SetText(SecondsToTime(ceil(timeRemaining))); - else - LFGCooldownCover_Update(self); - end -end - -function LFGBackfillCover_SetUp(self, subtypeIDs, lfgCategory, updateFunc) - self.subtypeIDs = subtypeIDs; - self.lfgCategory = lfgCategory; - self.updateFunc = updateFunc; - self:SetFrameLevel(self:GetParent():GetFrameLevel() + 9); -end - -function LFGBackfillCover_Update(self, forceUpdate) - if ( CanPartyLFGBackfill() ) then - local currentSubtypeID = select(LFG_RETURN_VALUES.subtypeID, GetLFGDungeonInfo(GetPartyLFGID())); - if ( tContains(self.subtypeIDs, currentSubtypeID) ) then - local name, lfgID, typeID = GetPartyLFGBackfillInfo(); - self.Description:SetFormattedText(LFG_OFFER_CONTINUE, HIGHLIGHT_FONT_COLOR_CODE..name.."|r"); - local mode, subMode = GetLFGMode(self.lfgCategory); - if ( (forceUpdate or not self:GetParent():IsVisible()) and mode ~= "queued" and mode ~= "suspended" ) then - self:Show(); - end - else - self:Hide(); - end - else - self:Hide(); - end - LFGCooldownCover_Update(self:GetParent().CooldownFrame); --The cooldown frame won't show if the backfill is shown, so we need to update it. -end - -function LFGDungeonListCheckButton_OnClick(button, category, dungeonList, hiddenByCollapseList) - local parent = button:GetParent(); - local dungeonID = parent.id; - local isChecked = button:GetChecked(); - - PlaySound(isChecked and SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON or SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF); - if ( LFGIsIDHeader(dungeonID) ) then - LFGDungeonList_SetHeaderEnabled(category, dungeonID, isChecked, dungeonList, hiddenByCollapseList); - else - LFGDungeonList_SetDungeonEnabled(dungeonID, isChecked); - LFGListUpdateHeaderEnabledAndLockedStates(dungeonList, LFGEnabledList, hiddenByCollapseList); - end -end - -function LFG_IsRandomDungeonDisplayable(id) - local name, typeID, subtypeID, minLevel, maxLevel, _, targetMinLevel, targetMaxLevel, expansionLevel, _, _, _, _, _, _, _, _, isTimewalker = GetLFGDungeonInfo(id); - local myLevel = UnitLevel("player"); - return ((myLevel >= targetMinLevel and myLevel <= targetMaxLevel and EXPANSION_LEVEL >= expansionLevel) or isTimewalker); -end - -function LFGRandomList_OnEnter(self) - local randomID = self.randomID; - local _, _, subtypeID, _, _, _, _, _, _, _, _, _, _, _, _, _, _, isTimewalkerRandom = GetLFGDungeonInfo(randomID); - - local titleText, emptyText, subText; - if ( isTimewalkerRandom ) then - titleText, emptyText, subText = INCLUDED_DUNGEONS, INCLUDED_DUNGEONS_TIMEWALKER_EMPTY, nil; - elseif ( subtypeID == LFG_SUBTYPEID_SCENARIO ) then - titleText, emptyText, subText = INCLUDED_SCENARIOS, INCLUDED_SCENARIOS_EMPTY, INCLUDED_SCENARIOS_SUBTEXT; - else - titleText, emptyText, subText = INCLUDED_DUNGEONS, INCLUDED_DUNGEONS_EMPTY, INCLUDED_DUNGEONS_SUBTEXT; - end - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(titleText, 1, 1, 1); - - local numDungeons = GetNumDungeonForRandomSlot(randomID); - - if ( numDungeons == 0 ) then - GameTooltip:AddLine(emptyText, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, true); - else - if ( subText ) then - GameTooltip:AddLine(subText, nil, nil, nil, true); - end - GameTooltip:AddLine(" "); - for i=1, numDungeons do - local dungeonID = GetDungeonForRandomSlot(randomID, i); - local name, typeID, _subtypeID, minLevel, maxLevel, recLevel, minRecLevel, maxRecLevel, expansionLevel, groupID, textureFilename, difficulty, maxPlayers, description, isHoliday, _, _, isTimewalker = GetLFGDungeonInfo(dungeonID); - local rangeText; - if ( minLevel == maxLevel ) then - rangeText = format(LFD_LEVEL_FORMAT_SINGLE, minLevel); - else - rangeText = format(LFD_LEVEL_FORMAT_RANGE, minLevel, maxLevel); - end - local difficultyColor = GetQuestDifficultyColor(isTimewalker and UnitLevel("player") or recLevel); - - local displayName = name; - if ( LFGLockList[dungeonID] ) then - displayName = "|TInterface\\LFGFrame\\UI-LFG-ICON-LOCK:14:14:0:0:32:32:0:28:0:28|t"..displayName; - end - GameTooltip:AddDoubleLine(displayName, rangeText, difficultyColor.r, difficultyColor.g, difficultyColor.b, difficultyColor.r, difficultyColor.g, difficultyColor.b); - end - end - - GameTooltip:Show(); -end - -function LFGRole_GetChecked(button) - return button.checkButton:GetChecked(); -end - -function LFGRole_SetChecked(button, checked) - button.checkButton:SetChecked(checked); -end - -function LFGRoleButtonTemplate_OnLoad(self) - if self.role then - local showDisabled = false; - self:SetNormalAtlas(GetIconForRole(self.role, showDisabled), TextureKitConstants.IgnoreAtlasSize); - showDisabled = true; - self:SetDisabledAtlas(GetIconForRole(self.role, showDisabled), TextureKitConstants.IgnoreAtlasSize); - end - - local classTank, classHealer, classDPS = UnitGetAvailableRoles("player"); - local id = self.role; - if(self.role == "TANK") then - if( not classTank ) then - self.permDisabledTip = YOUR_CLASS_MAY_NOT_PERFORM_ROLE; - else - self.permDisabledTip = YOU_ARE_NOT_SPECIALIZED_IN_ROLE; - end - elseif(self.role == "HEALER")then - if( not classHealer ) then - self.permDisabledTip = YOUR_CLASS_MAY_NOT_PERFORM_ROLE; - else - self.permDisabledTip = YOU_ARE_NOT_SPECIALIZED_IN_ROLE; - end - elseif(self.role == "DAMAGER")then - if( not classDPS ) then - self.permDisabledTip = YOUR_CLASS_MAY_NOT_PERFORM_ROLE; - else - self.permDisabledTip = YOU_ARE_NOT_SPECIALIZED_IN_ROLE; - end - end -end - -function LFGRoleButtonTemplate_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(_G["ROLE_DESCRIPTION_"..self.role], nil, nil, nil, nil, true); - if ( self.permDisabled ) then - if(self.permDisabledTip)then - GameTooltip:AddLine(self.permDisabledTip, 1, 0, 0, true); - end - elseif ( self.disabledTooltip and not self:IsEnabled() ) then - GameTooltip:AddLine(self.disabledTooltip, 1, 0, 0, true); - end - GameTooltip:Show(); - LFGFrameRoleCheckButton_OnEnter(self); -end - -function LFGRoleButton_LockReasonsTextTable(dungeonID, roleID, textTable) - local reasons = GetLFDRoleLockInfo(dungeonID, roleID); - textTable = textTable or {}; - for i = 1, #reasons do - local text = reasons[i].reason_string or GetLFGInstanceErrorString("SELF", reasons[i].reason_id, reasons[i].sub_reason); - textTable[text] = true; - end - - return textTable; -end - ----@class LFGRoleButtonWithShortageRewardMixin -LFGRoleButtonWithShortageRewardMixin = {}; - -function LFGRoleButtonWithShortageRewardMixin:OnLoad() - LFGRoleButtonTemplate_OnLoad(self); - - if self.onClick then - self.checkButton.onClick = self.onClick; - end - - self:SetUpIconPulseAnim(); - self.enableAnim = false; -end - -function LFGRoleButtonWithShortageRewardMixin:OnShow() - self.RoleShortagePulseAnim:SetPlaying(self.enableAnim); -end - -function LFGRoleButtonWithShortageRewardMixin:OnHide() - self.RoleShortagePulseAnim:SetPlaying(false); -end - -function LFGRoleButtonWithShortageRewardMixin:SetUpIconPulseAnim() - local showDisabled = false; - self.IconPulse:SetAtlas(GetIconForRole(self.role, showDisabled), TextureKitConstants.IgnoreAtlasSize); -end - -function LFGRoleButtonWithShortageRewardMixin:EnableRoleShortagePulseAnim(enableAnim) - self.enableAnim = enableAnim; - local playAnim = self:IsVisible() and enableAnim; - if playAnim and self.RoleShortagePulseAnim:IsPlaying() then - self:RestartRoleShortagePulseAnim(); - return; - end - - self.RoleShortagePulseAnim:SetPlaying(playAnim); -end - -function LFGRoleButtonWithShortageRewardMixin:RestartRoleShortagePulseAnim() - self:CancelPulseEffect(); - self.RoleShortagePulseAnim:Restart(); -end - -function LFGRoleButtonWithShortageRewardMixin:TryPlayPulseEffect() - if not self:IsVisible() or not self.RoleShortagePulseAnim:IsPlaying() then - return; - end - - local roleShortageEffectID, effectSpeed = 164, 0.17; - self.RoleShortagePulseModelScene:SetEffectSpeed(effectSpeed); - self.RoleShortagePulseModelScene:AddEffect(roleShortageEffectID, self); -end - -function LFGRoleButtonWithShortageRewardMixin:CancelPulseEffect() - if self.effectTimer then - self.effectTimer:Cancel(); - end - - self.RoleShortagePulseModelScene:ClearEffects(); -end - ----@class LFGRoleShortagePulseAnimMixin -LFGRoleShortagePulseAnimMixin = {}; - -function LFGRoleShortagePulseAnimMixin:OnLoop() - local parentFrame = self:GetParent(); - -- Play the pulse effect when the role icon is at its brightest - local pulseEffectDelay = 0.9; - parentFrame.effectTimer = C_Timer.NewTimer(pulseEffectDelay, GenerateClosure(parentFrame.TryPlayPulseEffect, parentFrame)); -end - -function LFGRoleShortagePulseAnimMixin:OnStop() - self:GetParent():CancelPulseEffect(); -end - ----@class LFGRewardFrameTemplateTitleMixin -LFGRewardFrameTemplateTitleMixin = {}; -function LFGRewardFrameTemplateTitleMixin:OnLoad() - self:SetFontObject(QuestTitleFontBlackShadow); - self:SetText(LFG_TYPE_RANDOM_DUNGEON); -end \ No newline at end of file diff --git a/WoW-API/_UI/Blizzard_GroupFinder/LFGFrame.xml b/WoW-API/_UI/Blizzard_GroupFinder/LFGFrame.xml deleted file mode 100644 index 9169438..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/LFGFrame.xml +++ /dev/null @@ -1,1134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( GameTooltip:GetOwner() == self ) then - GameTooltip:Hide(); - end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.ready.texture:SetAtlas("UI-LFG-RoleIcon-Generic", TextureKitConstants.IgnoreAtlasSize); - self.ready.statusIcon:Hide(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self:RegisterEvent("LFG_UPDATE_RANDOM_INFO") - - - if ( event == "LFG_UPDATE_RANDOM_INFO" ) then - --The rewards may have changed. - if ( self:IsShown() ) then - LFGDungeonReadyPopup_Update(); - end - end - - - LFGDungeonReadyPopup_Update(); - QueueUpdater:RequestInfo(); - QueueUpdater:AddRef(); - - - QueueUpdater:RemoveRef(); - self.closeIn = nil; - self:SetScript("OnUpdate", nil); - - - - - - - - - - - - - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(format(LFG_CALL_TO_ARMS, _G[self.role]), 1, 1, 1); - GameTooltip:AddLine(LFG_CALL_TO_ARMS_EXPLANATION, nil, nil, nil, true); - GameTooltip:Show(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.Icon:SetTexture("Interface\\Icons\\inv_misc_coin_01"); - self.Name:SetHeight(4); - - - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(LFG_TOOLTIP_MONEY_REWARD, 1, 1, 1); - - - GameTooltip:Hide(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LFGInvitePopupRoleButtonTank.checkButton.onClick = LFGInvitePopupCheckButton_OnClick; - LFGInvitePopupRoleButtonHealer.checkButton.onClick = LFGInvitePopupCheckButton_OnClick; - LFGInvitePopupRoleButtonDPS.checkButton.onClick = LFGInvitePopupCheckButton_OnClick; - - - PlaySound(SOUNDKIT.IG_PLAYER_INVITE); - - - - PlaySound(SOUNDKIT.IG_MAINMENU_CLOSE); - self:SetHeight(LFG_INVITE_POPUP_DEFAULT_HEIGHT); - self.QueueWarningText:Hide(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.updateFunc(); - - - self.updateFunc(); - - - self:SetFrameLevel(14); - - - - diff --git a/WoW-API/_UI/Blizzard_GroupFinder/LFGList.lua b/WoW-API/_UI/Blizzard_GroupFinder/LFGList.lua deleted file mode 100644 index b058039..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/LFGList.lua +++ /dev/null @@ -1,3835 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ -------------------------------------------------------- -----------Constants -------------------------------------------------------- -MAX_LFG_LIST_APPLICATIONS = 5; -MAX_LFG_LIST_SEARCH_AUTOCOMPLETE_ENTRIES = 6; -LFG_LIST_DELISTED_FONT_COLOR = {r=0.3, g=0.3, b=0.3}; -LFG_LIST_COMMENT_FONT_COLOR = {r=0.6, g=0.6, b=0.6}; -GROUP_FINDER_CATEGORY_ID_DUNGEONS = 2; - ----@class ACTIVITY_RETURN_VALUES -ACTIVITY_RETURN_VALUES = { - fullName = 1, - shortName = 2, - categoryID = 3, - groupID = 4, - itemLevel = 5, - filters = 6, - minLevel = 7, - maxPlayers = 8, - displayType = 9, - orderIndex = 10, - useHonorLevel = 11, -}; - ---Hard-coded values. Should probably make these part of the DB, but it gets a little more complicated with the per-expansion textures ----@class LFG_LIST_CATEGORY_TEXTURES -LFG_LIST_CATEGORY_TEXTURES = { - [1] = "questing", - [2] = "dungeons", - [3] = "raids", --Prefix for expansion - [4] = "arenas", - [5] = "scenarios", - [6] = "custom", -- Prefix for "-pve" or "-pvp" - [7] = "skirmishes", - [8] = "battlegrounds", - [9] = "ratedbgs", - [10] = "ashran", - [111] = "islands", - [113] = "torghast", -}; - ----@class LFG_LIST_PER_EXPANSION_TEXTURES -LFG_LIST_PER_EXPANSION_TEXTURES = { - [0] = "classic", - [1] = "bc", - [2] = "wrath", - [3] = "cataclysm", - [4] = "mists", - [5] = "warlords", - [6] = "legion", - [7] = "battleforazeroth", - [8] = "shadowlands", - [9] = "dragonflight", -} - ----@class LFG_LIST_GROUP_DATA_ATLASES -LFG_LIST_GROUP_DATA_ATLASES = { - --Roles - TANK = GetMicroIconForRole("TANK"), - HEALER = GetMicroIconForRole("HEALER"), - DAMAGER = GetMicroIconForRole("DAMAGER"), -}; - ---Fill out classes -for i=1, #CLASS_SORT_ORDER do - LFG_LIST_GROUP_DATA_ATLASES[CLASS_SORT_ORDER[i]] = "groupfinder-icon-class-"..string.lower(CLASS_SORT_ORDER[i]); -end - -LFG_LIST_GROUP_DATA_ROLE_ORDER = { "TANK", "HEALER", "DAMAGER" }; -LFG_LIST_GROUP_DATA_CLASS_ORDER = CLASS_SORT_ORDER; - -local FACTION_STRINGS = { [0] = FACTION_HORDE, [1] = FACTION_ALLIANCE}; - -StaticPopupDialogs["LFG_LIST_INVITING_CONVERT_TO_RAID"] = { - text = LFG_LIST_CONVERT_TO_RAID_WARNING, - button1 = INVITE, - button2 = CANCEL, - OnAccept = function(dialog, applicantID) C_PartyInfo.ConfirmConvertToRaid(); C_LFGList.InviteApplicant(applicantID) end, - timeout = 0, - whileDead = 1, - hideOnEscape = 1, -} - -local function ResolveCategoryFilters(categoryID, filters) - -- Dungeons ONLY display recommended groups. - if categoryID == GROUP_FINDER_CATEGORY_ID_DUNGEONS then - return bit.band(bit.bnot(Enum.LFGListFilter.NotRecommended), bit.bor(filters, Enum.LFGListFilter.Recommended)); - end - - return filters; -end - -local function GetFindGroupRestriction() - if ( C_SocialRestrictions.IsSilenced() ) then - return "SILENCED", RED_FONT_COLOR:WrapTextInColorCode(ERR_ACCOUNT_SILENCED); - elseif ( C_SocialRestrictions.IsSquelched() ) then - return "SQUELCHED", RED_FONT_COLOR:WrapTextInColorCode(ERR_USER_SQUELCHED); - end - - return nil, nil; -end - -local function GetStartGroupRestriction() - return GetFindGroupRestriction(); -end - -------------------------------------------------------- -----------Base Frame -------------------------------------------------------- -LFG_LIST_EDIT_BOX_TAB_CATEGORIES = {}; -function LFGListFrame_OnLoad(self) - self:RegisterEvent("PARTY_LEADER_CHANGED"); - self:RegisterEvent("GROUP_ROSTER_UPDATE"); - self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED"); - self:RegisterEvent("PLAYER_ROLES_ASSIGNED"); - self:RegisterEvent("TRIAL_STATUS_UPDATE"); - self:RegisterEvent("LFG_LIST_AVAILABILITY_UPDATE"); - self:RegisterEvent("LFG_LIST_ACTIVE_ENTRY_UPDATE"); - self:RegisterEvent("LFG_LIST_ENTRY_CREATION_FAILED"); - self:RegisterEvent("LFG_LIST_SEARCH_RESULTS_RECEIVED"); - self:RegisterEvent("LFG_LIST_SEARCH_RESULT_UPDATED"); - self:RegisterEvent("LFG_LIST_UPDATE_SEARCH_RESULTS"); - self:RegisterEvent("LFG_LIST_SEARCH_FAILED"); - self:RegisterEvent("LFG_LIST_APPLICANT_LIST_UPDATED"); - self:RegisterEvent("LFG_LIST_APPLICANT_UPDATED"); - self:RegisterEvent("LFG_LIST_ENTRY_EXPIRED_TOO_MANY_PLAYERS"); - self:RegisterEvent("LFG_LIST_ENTRY_EXPIRED_TIMEOUT"); - self:RegisterEvent("LFG_LIST_APPLICATION_STATUS_UPDATED"); - self:RegisterEvent("UNIT_CONNECTION"); - self:RegisterEvent("LFG_GROUP_DELISTED_LEADERSHIP_CHANGE"); - - for i=1, #LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS do - self:RegisterEvent(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS[i]); - end - LFGListFrame_SetBaseFilters(self, Enum.LFGListFilter.PvE); - LFGListFrame_SetActivePanel(self, self.NothingAvailable); - - self.EventsInBackground = { - LFG_LIST_SEARCH_FAILED = { self.SearchPanel }; - }; -end - -function LFGListFrame_OnEvent(self, event, ...) - if ( event == "LFG_LIST_AVAILABILITY_UPDATE" or event == "TRIAL_STATUS_UPDATE") then - LFGListFrame_FixPanelValid(self); - elseif ( event == "LFG_LIST_ACTIVE_ENTRY_UPDATE" ) then - local createdNew = ...; - LFGListFrame_FixPanelValid(self); --If our current panel isn't valid, change it. - - if ( C_LFGList.HasActiveEntryInfo() ) then - self.EntryCreation.WorkingCover:Hide(); - else - LFGListFrame_CheckPendingQuestIDSearch(self); - end - - if ( createdNew ) then - PlaySound(SOUNDKIT.PVP_ENTER_QUEUE); - end - elseif ( event == "LFG_LIST_ENTRY_CREATION_FAILED" ) then - self.EntryCreation.WorkingCover:Hide(); - elseif ( event == "LFG_LIST_APPLICANT_LIST_UPDATED" ) then - local hasNewPending, hasNewPendingWithData = ...; - if ( hasNewPending and hasNewPendingWithData and LFGListUtil_IsEntryEmpowered() ) then - local isLeader = UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME); - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - local numPings = nil; - if ( not isLeader ) then - numPings = 6; - end - --Non-leaders don't get another ping until they open the panel or we reset the count to 0 - if ( isLeader or not self.stopAssistPings ) then - if ( activeEntryInfo.autoAccept ) then - --Check if we would be auto-inviting more people if we were in a raid - if ( not IsInRaid(LE_PARTY_CATEGORY_HOME) and - GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) + C_LFGList.GetNumInvitedApplicantMembers() + C_LFGList.GetNumPendingApplicantMembers() > (MAX_PARTY_MEMBERS+1) ) then - if ( self.displayedAutoAcceptConvert ) then - if(QueueStatusButton) then - QueueStatusButton:SetGlowLock("lfglist-applicant", true, numPings); - end - self.stopAssistPings = true; - else - self.displayedAutoAcceptConvert = true; - StaticPopup_Show("LFG_LIST_AUTO_ACCEPT_CONVERT_TO_RAID"); - end - end - elseif ( not self:IsVisible() ) then - if(QueueStatusButton) then - QueueStatusButton:SetGlowLock("lfglist-applicant", true, numPings); - end - self.stopAssistPings = true; - end - end - end - elseif ( event == "LFG_LIST_APPLICANT_UPDATED" ) then - local numApps, numActiveApps = C_LFGList.GetNumApplicants(); - if ( numActiveApps == 0 ) then - if(QueueStatusButton) then - QueueStatusButton:SetGlowLock("lfglist-applicant", false); - end - self.stopAssistPings = false; - end - elseif ( event == "LFG_LIST_ENTRY_EXPIRED_TOO_MANY_PLAYERS" ) then - if ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then - StaticPopup_Show("LFG_LIST_ENTRY_EXPIRED_TOO_MANY_PLAYERS"); - end - elseif ( event == "LFG_LIST_ENTRY_EXPIRED_TIMEOUT" ) then - if ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then - StaticPopup_Show("LFG_LIST_ENTRY_EXPIRED_TIMEOUT"); - end - elseif ( event == "LFG_LIST_APPLICATION_STATUS_UPDATED" ) then - local searchResultID, newStatus, oldStatus, kstringGroupName = ...; - local chatMessage = LFGListFrame_GetChatMessageForSearchStatusChange(newStatus); - if ( chatMessage ) then - ChatFrame_DisplaySystemMessageInPrimary(chatMessage:format(kstringGroupName)); - end - elseif ( event == "GROUP_ROSTER_UPDATE" ) then - if ( not IsInGroup(LE_PARTY_CATEGORY_HOME) ) then - self.displayedAutoAcceptConvert = false; - end - elseif ( event == "LFG_GROUP_DELISTED_LEADERSHIP_CHANGE") then - local listingTitle, delistTime = ...; - StaticPopup_Show("PREMADE_GROUP_LEADER_CHANGE_DELIST_WARNING", nil, nil, { listingTitle = listingTitle, delistTime = delistTime, }); - end - - --Dispatch the event to our currently active panel - local onEvent = self.activePanel and self.activePanel:GetScript("OnEvent"); - if ( onEvent ) then - onEvent(self.activePanel, event, ...); - end - - --Dispatch the event to any panels that want the event in the background - local bg = self.EventsInBackground[event]; - if ( bg ) then - for i=1, #bg do - if ( bg[i] ~= self.activePanel ) then - bg[i]:GetScript("OnEvent")(bg[i], event, ...); - end - end - end -end - -function LFGListFrame_OnShow(self) - LFGListFrame_FixPanelValid(self); - C_LFGList.RequestAvailableActivities(); - self.stopAssistPings = false; - if(QueueStatusButton) then - QueueStatusButton:SetGlowLock("lfglist-applicant", false); - end - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN); -end - -function LFGListFrame_OnHide(self) - LFGListFrame_SetPendingQuestIDSearch(self, nil); - LFGListEntryCreation_ClearAutoCreateMode(self.EntryCreation); - self.SearchPanel.shouldAlwaysShowCreateGroupButton = nil; -end - -function LFGListFrame_GetChatMessageForSearchStatusChange(newStatus) - if ( newStatus == "declined" ) then - return LFG_LIST_APP_DECLINED_MESSAGE; - elseif ( newStatus == "declined_full" ) then - return LFG_LIST_APP_DECLINED_FULL_MESSAGE; - elseif ( newStatus == "declined_delisted" ) then - return LFG_LIST_APP_DECLINED_DELISTED_MESSAGE; - elseif ( newStatus == "timedout" ) then - return LFG_LIST_APP_TIMED_OUT_MESSAGE; - end -end - -function LFGListFrame_SetActivePanel(self, panel) - if ( self.activePanel ) then - self.activePanel:Hide(); - end - self.activePanel = panel; - self.activePanel:Show(); -end - -function LFGListFrame_IsPanelValid(self, panel) - local listed = C_LFGList.HasActiveEntryInfo(); - - --If we're listed, make sure we're either viewing applicants or editing our group - if ( listed and panel ~= self.ApplicationViewer and not (panel == self.EntryCreation and LFGListEntryCreation_IsEditMode(self.EntryCreation)) ) then - return false; - end - - --If we're not listed, we can't be viewing applicants or editing our group - if ( not listed and (panel == self.ApplicationViewer or - (panel == self.EntryCreation and LFGListEntryCreation_IsEditMode(self.EntryCreation)) ) ) then - return false; - end - - --Make sure we aren't creating a new entry with different baseFilters - if ( panel == self.EntryCreation ) then - if ( not LFGListEntryCreation_IsEditMode(self.EntryCreation) and self.baseFilters ~= self.EntryCreation.baseFilters ) then - return false; - end - end - - --Make sure we aren't searching with different baseFilters - if ( panel == self.SearchPanel ) then - if ( self.baseFilters ~= self.SearchPanel.preferredFilters ) then - return false; - end - end - - --If we're a trial account, we can only see the NothingAvailable and ApplicationViewer - if ( IsRestrictedAccount() ) then - if ( panel ~= self.NothingAvailable and panel ~= self.ApplicationViewer ) then - return false; - end - end - - --If we don't have any available activities, say so - if ( #C_LFGList.GetAvailableCategories(self.baseFilters) == 0 ) then - if ( panel == self.CategorySelection ) then - return false; - end - else - if ( panel == self.NothingAvailable and not IsRestrictedAccount() ) then - return false; - end - end - - return true; -end - -function LFGListFrame_GetBestPanel(self) - local listed = C_LFGList.HasActiveEntryInfo(); - - if ( listed ) then - return self.ApplicationViewer; - elseif ( IsRestrictedAccount() ) then - return self.NothingAvailable; - elseif ( #C_LFGList.GetAvailableCategories(self.baseFilters) == 0 ) then - return self.NothingAvailable; - else - return self.CategorySelection; - end -end - -function LFGListFrame_FixPanelValid(self) - if ( not LFGListFrame_IsPanelValid(self, self.activePanel) ) then - LFGListFrame_SetActivePanel(self, LFGListFrame_GetBestPanel(self)); - end -end - -function LFGListFrame_SetBaseFilters(self, filters) - self.baseFilters = filters; - - --If we need to change panels, do so - LFGListFrame_FixPanelValid(self); - - --Update the current panel - if ( self.activePanel and self.activePanel.updateAll ) then - self.activePanel.updateAll(self.activePanel); - end -end - -function LFGListFrame_CheckPendingQuestIDSearch(self) - local questID = LFGListFrame_GetPendingQuestIDSearch(self); - if questID and not C_LFGList.HasActiveEntryInfo() then - LFGListFrame_SetPendingQuestIDSearch(self, nil); - - if issecure() then - LFGListFrame_BeginFindQuestGroup(self, questID); - else - StaticPopup_Show("PREMADE_GROUP_INSECURE_SEARCH", QuestUtils_GetQuestName(questID), nil, questID); - end - end -end - -function LFGListFrame_GetPendingQuestIDSearch(self) - return self.pendingQuestIDSearch; -end - -function LFGListFrame_SetPendingQuestIDSearch(self, questID) - self.pendingQuestIDSearch = questID; -end - -function LFGListFrame_BeginFindQuestGroup(self, questID, shouldShowCreateGroupButton) - local activityID, categoryID, filters, questName = LFGListUtil_GetQuestCategoryData(questID); - - if not activityID then - return; - end - - if C_LFGList.HasActiveEntryInfo() then - if LFGListUtil_CanListGroup() then - C_LFGList.RemoveListing(); - LFGListFrame_SetPendingQuestIDSearch(self, questID); - end - return; - end - - self.SearchPanel.shouldAlwaysShowCreateGroupButton = shouldShowCreateGroupButton; - - PVEFrame_ShowFrame("GroupFinderFrame", LFGListPVEStub); - - local panel = self.CategorySelection; - LFGListCategorySelection_SelectCategory(panel, categoryID, filters); - LFGListCategorySelection_StartFindGroup(panel, questID); - LFGListEntryCreation_SetAutoCreateMode(panel:GetParent().EntryCreation, "quest", activityID, questID); -end - -------------------------------------------------------- -----------Nothing available frame -------------------------------------------------------- -function LFGListNothingAvailable_OnEvent(self, event, ...) - --Note: events are dispatched from the base frame. Add RegisterEvent there. - if ( event == "LFG_LIST_AVAILABILITY_UPDATE" ) then - LFGListNothingAvailable_Update(self); - end -end - -function LFGListNothingAvailable_Update(self) - if ( IsRestrictedAccount() ) then - self.Label:SetText(ERR_RESTRICTED_ACCOUNT_LFG_LIST_TRIAL); - elseif ( C_LFGList.HasActivityList() ) then - self.Label:SetText(NO_LFG_LIST_AVAILABLE); - else - self.Label:SetText(LFG_LIST_LOADING); - end -end - -------------------------------------------------------- -----------Category selection -------------------------------------------------------- -function LFGListCategorySelection_OnLoad(self) - LFGListCategorySelection_UpdateNavButtons(self); -end - -function LFGListCategorySelection_OnEvent(self, event, ...) - --Note: events are dispatched from the base frame. Add RegisterEvent there. - if ( event == "LFG_LIST_AVAILABILITY_UPDATE" ) then - LFGListCategorySelection_UpdateCategoryButtons(self); - end - - if ( tContains(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS, event) ) then - LFGListCategorySelection_UpdateNavButtons(self); - end -end - -function LFGListCategorySelection_OnShow(self) - LFGListCategorySelection_UpdateCategoryButtons(self); - LFGListCategorySelection_UpdateNavButtons(self); -end - -function LFGListCategorySelection_UpdateCategoryButtons(self) - local baseFilters = self:GetParent().baseFilters; - local categories = C_LFGList.GetAvailableCategories(baseFilters); - - local nextBtn = 1; - local hasSelected = false; - - --Update category buttons - for i=1, #categories do - local isSelected = false; - local categoryID = categories[i]; - local categoryInfo = C_LFGList.GetLfgCategoryInfo(categoryID); - - if categoryInfo.separateRecommended then - nextBtn, isSelected = LFGListCategorySelection_AddButton(self, nextBtn, categoryID, Enum.LFGListFilter.Recommended); - hasSelected = hasSelected or isSelected; - nextBtn, isSelected = LFGListCategorySelection_AddButton(self, nextBtn, categoryID, Enum.LFGListFilter.NotRecommended); - else - nextBtn, isSelected = LFGListCategorySelection_AddButton(self, nextBtn, categoryID, 0); - end - - hasSelected = hasSelected or isSelected; - end - - --Hide any extra buttons - for i=nextBtn, #self.CategoryButtons do - self.CategoryButtons[i]:Hide(); - end - - --If the selected item isn't in the list, deselect it - if ( self.selectedCategory and not hasSelected ) then - LFGListCategorySelection_SelectCategory(self, nil, nil); - end -end - -function LFGListCategorySelection_AddButton(self, btnIndex, categoryID, filters) - --Check that we have activities with this filter - local baseFilters = self:GetParent().baseFilters; - local allFilters = bit.bor(baseFilters, filters); - - if ( filters ~= 0 and #C_LFGList.GetAvailableActivities(categoryID, nil, allFilters) == 0) then - return btnIndex, false; - end - - local categoryInfo = C_LFGList.GetLfgCategoryInfo(categoryID); - - local button = self.CategoryButtons[btnIndex]; - if ( not button ) then - self.CategoryButtons[btnIndex] = CreateFrame("BUTTON", nil, self, "LFGListCategoryTemplate"); - self.CategoryButtons[btnIndex]:SetPoint("TOP", self.CategoryButtons[btnIndex - 1], "BOTTOM", 0, -3); - button = self.CategoryButtons[btnIndex]; - end - - button:SetText(LFGListUtil_GetDecoratedCategoryName(categoryInfo.name, filters, true)); - button.categoryID = categoryID; - button.filters = filters; - - local atlasName = nil; - if ( bit.band(allFilters, Enum.LFGListFilter.Recommended) ~= 0 ) then - atlasName = "groupfinder-button-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[LFGListUtil_GetCurrentExpansion()]; - elseif ( bit.band(allFilters, Enum.LFGListFilter.NotRecommended) ~= 0 ) then - atlasName = "groupfinder-button-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[math.max(0,LFGListUtil_GetCurrentExpansion() - 1)]; - else - atlasName = "groupfinder-button-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "questing"); - end - - local suffix = ""; - if ( bit.band(allFilters, Enum.LFGListFilter.PvE) ~= 0 ) then - suffix = "-pve"; - elseif ( bit.band(allFilters, Enum.LFGListFilter.PvP) ~= 0 ) then - suffix = "-pvp"; - end - - --Try with the suffix and then without it - if ( not button.Icon:SetAtlas(atlasName..suffix) ) then - button.Icon:SetAtlas(atlasName); - end - - local selected = self.selectedCategory == categoryID and self.selectedFilters == filters; - button.SelectedTexture:SetShown(selected); - button:Show(); - - return btnIndex + 1, selected; -end - -function LFGListCategorySelection_SelectCategory(self, categoryID, filters) - self.selectedCategory = categoryID; - self.selectedFilters = filters; - LFGListCategorySelection_UpdateCategoryButtons(self); - LFGListCategorySelection_UpdateNavButtons(self); -end - -function LFGListCategorySelection_UpdateNavButtons(self) - local findEnabled, startEnabled = true, true; - self.FindGroupButton.tooltip = nil; - self.StartGroupButton.tooltip = nil; - - --Check if the user needs to select a category - if ( not self.selectedCategory ) then - findEnabled = false; - self.FindGroupButton.tooltip = LFG_LIST_SELECT_A_CATEGORY; - startEnabled = false; - self.StartGroupButton.tooltip = LFG_LIST_SELECT_A_CATEGORY; - end - - --Check if the user can't start a group due to not being a leader - if ( IsInGroup(LE_PARTY_CATEGORY_HOME) and not UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then - startEnabled = false; - self.StartGroupButton.tooltip = LFG_LIST_NOT_LEADER; - end - - --Check if the player is currently in some incompatible queue - local messageStart = LFGListUtil_GetActiveQueueMessage(false); - if ( messageStart ) then - startEnabled = false; - self.StartGroupButton.tooltip = messageStart; - end - - local findError, findErrorText = GetFindGroupRestriction(); - if ( findError ~= nil ) then - findEnabled = false; - self.FindGroupButton.tooltip = findErrorText; - end - - local startError, startErrorText = GetStartGroupRestriction(); - if ( startError ~= nil ) then - startEnabled = false; - self.StartGroupButton.tooltip = startErrorText; - end - - self.FindGroupButton:SetEnabled(findEnabled); - self.StartGroupButton:SetEnabled(startEnabled); -end - -function LFGListCategorySelectionStartGroupButton_OnClick(self) - local panel = self:GetParent(); - if ( not panel.selectedCategory ) then - return; - end - - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - - local baseFilters = panel:GetParent().baseFilters; - - local entryCreation = panel:GetParent().EntryCreation; - - LFGListEntryCreation_Show(entryCreation, baseFilters, panel.selectedCategory, panel.selectedFilters); -end - -function LFGListCategorySelectionFindGroupButton_OnClick(self) - local panel = self:GetParent(); - if ( not panel.selectedCategory ) then - return; - end - - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - LFGListCategorySelection_StartFindGroup(panel); -end - -function LFGListCategorySelection_StartFindGroup(self, questID) - local baseFilters = self:GetParent().baseFilters; - local searchPanel = self:GetParent().SearchPanel; - LFGListSearchPanel_Clear(searchPanel); - if questID then - C_LFGList.SetSearchToQuestID(questID); - end - LFGListSearchPanel_SetCategory(searchPanel, self.selectedCategory, self.selectedFilters, baseFilters); - LFGListSearchPanel_DoSearch(searchPanel); - LFGListFrame_SetActivePanel(self:GetParent(), searchPanel); -end - ---The individual category buttons -function LFGListCategorySelectionButton_OnClick(self) - local panel = self:GetParent(); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - LFGListCategorySelection_SelectCategory(panel, self.categoryID, self.filters); - LFGListEntryCreation_ClearAutoCreateMode(panel:GetParent().EntryCreation); -end - -------------------------------------------------------- -----------List Entry Creation -------------------------------------------------------- -function LFGListEntryCreation_OnLoad(self) - self.Name.Instructions:SetText(LFG_LIST_ENTER_NAME); - self.Description.EditBox:SetScript("OnEnterPressed", nop); - - self.GroupDropdown:SetWidth(141); - - -- Group dropdown has a "More" option that requires us to set the text - -- manually if the option is not in the selected list. - self.GroupDropdown:SetSelectionText(function(currentSelections) - -- overrideName assigned when an option is picked from the dialog. - if self.GroupDropdown.overrideName then - return self.GroupDropdown.overrideName; - end - - local currentSelection = currentSelections[1]; - if currentSelection then - return MenuUtil.GetElementText(currentSelection); - end - - return nil; - end); - - self.ActivityDropdown:SetWidth(138); - - -- ActivityDropdown dropdown has a "More" option that requires us to set the text - -- manually if the option is not in the selected list. - self.ActivityDropdown:SetSelectionText(function(currentSelections) - -- overrideName assigned when an option is picked from the dialog. - if self.ActivityDropdown.overrideName then - return self.ActivityDropdown.overrideName; - end - - local currentSelection = currentSelections[1]; - if currentSelection then - return MenuUtil.GetElementText(currentSelection); - end - - return nil; - end); - - self.PlayStyleDropdown:SetWidth(144); - - LFGListEntryCreation_SetBaseFilters(self, 0); -end - -function LFGListEntryCreation_SetupGroupDropdown(self) - self.GroupDropdown.overrideName = nil; - self.GroupDropdown:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_LFG_FRAME_GROUP"); - - if ( not self.selectedCategory ) then - --We don't have a category, so we can't fill out groups. - return; - end - - local function IsGroupSelected(groupID) - return self.selectedGroup == groupID; - end - - local function SetGroupSelected(groupID) - LFGListEntryCreation_Select(self, self.selectedFilters, self.selectedCategory, groupID); - end - - --In classic we want to display all the groups, so we don't have a "more" button here. - local groups = C_LFGList.GetAvailableActivityGroups(self.selectedCategory, bit.bor(self.baseFilters, self.selectedFilters)); - for groupIndex = 1, #groups do - local groupID = groups[groupIndex]; - local name = C_LFGList.GetActivityGroupInfo(groupID); - rootDescription:CreateRadio(name, IsGroupSelected, SetGroupSelected, groupID); - end - end); -end - -function LFGListEntryCreation_SetupActivityDropdown(self) - self.ActivityDropdown.overrideName = nil; - self.ActivityDropdown:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_LFG_FRAME_GROUP_ACTIVITY"); - - local filters = bit.bor(self.baseFilters, self.selectedFilters); - - --Start out displaying everything - local activities = C_LFGList.GetAvailableActivities(self.selectedCategory, self.selectedGroup, filters); - - local function IsActivitySelected(activityID) - return self.selectedActivity == activityID; - end - - local function SetActivitySelected(activityID) - LFGListEntryCreation_Select(self, nil, nil, nil, activityID); - end - - LFGListUtil_SortActivitiesByShortname(activities); - - --In classic we want to display all the groups, so we don't have a "more" button here. - for i=1, #activities do - local activityID = activities[i]; - local activityInfo = C_LFGList.GetActivityInfoTable(activityID); - local shortName = activityInfo and activityInfo.shortName; - rootDescription:CreateRadio(shortName, IsActivitySelected, SetActivitySelected, activityID); - end - end); -end - -function LFGListEntryCreation_SetupPlayStyleDropdown(self) - local activityInfo = C_LFGList.GetActivityInfoTable(self.selectedActivity); - local categoryInfo = C_LFGList.GetLfgCategoryInfo(self.selectedCategory); - local shouldShowPlayStyleDropdown = categoryInfo.showPlaystyleDropdown and (activityInfo.isMythicPlusActivity or activityInfo.isRatedPvpActivity or activityInfo.isCurrentRaidActivity or activityInfo.isMythicActivity); - self.PlayStyleDropdown:SetShown(shouldShowPlayStyleDropdown); - self.PlayStyleLabel:SetShown(shouldShowPlayStyleDropdown); - - local function IsSelected(playstyle) - return self.selectedPlaystyle == playstyle; - end - - local function SetSelected(playstyle) - LFGListEntryCreation_OnPlayStyleSelectedInternal(self, playstyle); - local previousPlaystyle = self.selectedPlaystyle; - self.selectedPlaystyle = playstyle; - if(C_LFGList.DoesEntryTitleMatchPrebuiltTitle(self.selectedActivity, self.selectedGroup, previousPlaystyle)) then - LFGListEntryCreation_SetTitleFromActivityInfo(self); - end - end - - local function CreateRadio(rootDescription, activityInfo, playstyle) - local text = C_LFGList.GetPlaystyleString(playstyle, activityInfo); - rootDescription:CreateRadio(text, IsSelected, SetSelected, playstyle); - end - - LFGListEntryCreation_SetPlaystyleLabelTextFromActivityInfo(self, activityInfo); - self.PlayStyleDropdown:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_LFG_FRAME_GROUP_PLAYSTYLE"); - - if(not self.selectedActivity or not self.selectedCategory) then - return; - end - local activityInfo = C_LFGList.GetActivityInfoTable(self.selectedActivity); - CreateRadio(rootDescription, activityInfo, Enum.LFGEntryPlaystyle.Standard); - CreateRadio(rootDescription, activityInfo, Enum.LFGEntryPlaystyle.Casual); - CreateRadio(rootDescription, activityInfo, Enum.LFGEntryPlaystyle.Hardcore); - end); -end - -function LFGListEntryCreation_OnEvent(self, event, ...) - if ( event == "GROUP_ROSTER_UPDATE" ) then - LFGListEntryCreation_UpdateValidState(self); - elseif ( tContains(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS, event) ) then - LFGListEntryCreation_UpdateValidState(self); - end -end - -function LFGListEntryCreation_OnShow(self) - LFGListEntryCreation_UpdateValidState(self); - LFGListEntryCreation_SetupGroupDropdown(self); - LFGListEntryCreation_SetupActivityDropdown(self); - LFGListEntryCreation_SetupPlayStyleDropdown(self); -end - -function LFGListEntryCreation_Show(self, baseFilters, selectedCategory, selectedFilters) - --If this was what the player selected last time, just leave it filled out with the same info. - --Also don't save it for categories that try to set it to the current area. - local categoryInfo = C_LFGList.GetLfgCategoryInfo(selectedCategory); - local keepOldData = not categoryInfo.preferCurrentArea and self.selectedCategory == selectedCategory and baseFilters == self.baseFilters and self.selectedFilters == selectedFilters; - LFGListEntryCreation_SetBaseFilters(self, baseFilters); - if ( not keepOldData ) then - LFGListEntryCreation_Clear(self); - LFGListEntryCreation_Select(self, selectedFilters, selectedCategory); - end - LFGListEntryCreation_OnPlayStyleSelected(self, Enum.LFGEntryPlaystyle.Standard); - LFGListEntryCreation_SetEditMode(self, false); - - LFGListEntryCreation_UpdateValidState(self); - - LFGListFrame_SetActivePanel(self:GetParent(), self); - self.Name:SetFocus(); - self.Label:SetText(categoryInfo.name); - - LFGListEntryCreation_CheckAutoCreate(self); -end - -function LFGListEntryCreation_Clear(self) - --Clear selections - self.selectedGroup = nil; - self.selectedActivity = nil; - self.selectedFilters = nil; - self.selectedCategory = nil; - self.selectedPlaystyle = nil; - - --Reset widgets - C_LFGList.ClearCreationTextFields(); - self.ItemLevel.CheckButton:SetChecked(false); - self.ItemLevel.EditBox:SetText(""); - self.PvpItemLevel.CheckButton:SetChecked(false); - self.PvpItemLevel.EditBox:SetText(""); - self.PVPRating.CheckButton:SetChecked(false); - self.PVPRating.EditBox:SetText(""); - self.MythicPlusRating.CheckButton:SetChecked(false); - self.MythicPlusRating.EditBox:SetText(""); - self.VoiceChat.CheckButton:SetChecked(false); - --self.VoiceChat.EditBox:SetText(""); --Cleared in ClearCreationTextFields - self.PrivateGroup.CheckButton:SetChecked(false); - self.CrossFactionGroup.CheckButton:SetChecked(false); - - self.ActivityFinder:Hide(); -end - -function LFGListEntryCreation_ClearFocus(self) - self.Name:ClearFocus(); - self.ItemLevel.EditBox:ClearFocus(); - self.PvpItemLevel.EditBox:ClearFocus(); - self.MythicPlusRating.EditBox:ClearFocus(); - self.PVPRating.EditBox:ClearFocus(); - self.VoiceChat.EditBox:ClearFocus(); - self.Description.EditBox:ClearFocus(); -end - ---This function accepts any or all of categoryID, groupId, and activityID -function LFGListEntryCreation_Select(self, filters, categoryID, groupID, activityID) - filters, categoryID, groupID, activityID = LFGListUtil_AugmentWithBest(bit.bor(self.baseFilters or 0, filters or 0), categoryID, groupID, activityID); - self.selectedCategory = categoryID; - self.selectedGroup = groupID; - self.selectedActivity = activityID; - self.selectedFilters = filters; - - --Update the category dropdown - local categoryInfo = C_LFGList.GetLfgCategoryInfo(categoryID); - - --Update the activity dropdown - local activityInfo = C_LFGList.GetActivityInfoTable(activityID); - if(not activityInfo) then - return; - end - - --Update the group dropdown. If the group dropdown is showing an activity, hide the activity dropdown - local groupName = C_LFGList.GetActivityGroupInfo(groupID); - self.ActivityDropdown.overrideName = activityInfo and activityInfo.shortName; - self.GroupDropdown.overrideName = groupName or activityInfo.shortName; - - self.ActivityDropdown:SetShown(groupName and not categoryInfo.autoChooseActivity); - self.ActivityDropdown:GenerateMenu(); - - self.GroupDropdown:SetShown(not categoryInfo.autoChooseActivity); - self.GroupDropdown:GenerateMenu(); - - local shouldShowPlayStyleDropdown = (categoryInfo.showPlaystyleDropdown) and (activityInfo.isMythicPlusActivity or activityInfo.isRatedPvpActivity or activityInfo.isCurrentRaidActivity or activityInfo.isMythicActivity); - local shouldShowCrossFactionToggle = (categoryInfo.allowCrossFaction); - local shouldDisableCrossFactionToggle = (categoryInfo.allowCrossFaction) and not (activityInfo.allowCrossFaction); - if(shouldShowPlayStyleDropdown) then - LFGListEntryCreation_OnPlayStyleSelected(self, self.selectedPlaystyle or Enum.LFGEntryPlaystyle.Standard); - end - - self.PlayStyleDropdown:SetShown(shouldShowPlayStyleDropdown); - self.PlayStyleLabel:SetShown(shouldShowPlayStyleDropdown); - - if(not shouldShowPlayStyleDropdown) then - self.selectedPlaystyle = nil - end - local _, localizedFaction = UnitFactionGroup("player"); - self.CrossFactionGroup.Label:SetText(LFG_LIST_CROSS_FACTION:format(localizedFaction)); - self.CrossFactionGroup.tooltip = LFG_LIST_CROSS_FACTION_TOOLTIP:format(localizedFaction); - self.CrossFactionGroup.disableTooltip = LFG_LIST_CROSS_FACTION_DISABLE_TOOLTIP:format(localizedFaction); - self.CrossFactionGroup:SetShown(shouldShowCrossFactionToggle); - self.CrossFactionGroup.CheckButton:SetEnabled(not shouldDisableCrossFactionToggle); - self.CrossFactionGroup.CheckButton:SetChecked(shouldDisableCrossFactionToggle); - if(shouldDisableCrossFactionToggle) then - self.CrossFactionGroup.Label:SetTextColor(DISABLED_FONT_COLOR:GetRGB()); - else - self.CrossFactionGroup.Label:SetTextColor(HIGHLIGHT_FONT_COLOR:GetRGB()); - end - - self.MythicPlusRating:SetShown(activityInfo.isMythicPlusActivity); - self.PVPRating:SetShown(activityInfo.isRatedPvpActivity); - - --Update the recommended item level box - if ( activityInfo.ilvlSuggestion ~= 0 ) then - self.ItemLevel.EditBox.Instructions:SetFormattedText(LFG_LIST_RECOMMENDED_ILVL, activityInfo.ilvlSuggestion); - else - self.ItemLevel.EditBox.Instructions:SetText(LFG_LIST_ITEM_LEVEL_INSTR_SHORT); - end - - self.NameLabel:ClearAllPoints(); - if (not self.ActivityDropdown:IsShown() and not self.GroupDropdown:IsShown()) then - self.NameLabel:SetPoint("TOPLEFT", 20, -82); - else - self.NameLabel:SetPoint("TOPLEFT", 20, -120); - end - - self.ItemLevel:ClearAllPoints(); - self.PvpItemLevel:ClearAllPoints(); - - self.ItemLevel:SetShown(not activityInfo.isPvpActivity); - self.PvpItemLevel:SetShown(activityInfo.isPvpActivity); - - if (self.MythicPlusRating:IsShown()) then - self.ItemLevel:SetPoint("TOPLEFT", self.MythicPlusRating, "BOTTOMLEFT", 0, -3); - self.PvpItemLevel:SetPoint("TOPLEFT", self.MythicPlusRating, "BOTTOMLEFT", 0, -3); - elseif (self.PVPRating:IsShown()) then - self.ItemLevel:SetPoint("TOPLEFT", self.PVPRating, "BOTTOMLEFT", 0, -3); - self.PvpItemLevel:SetPoint("TOPLEFT", self.PVPRating, "BOTTOMLEFT", 0, -3); - elseif(self.PlayStyleDropdown:IsShown()) then - self.ItemLevel:SetPoint("TOPLEFT", self.PlayStyleLabel, "BOTTOMLEFT", -1, -15); - self.PvpItemLevel:SetPoint("TOPLEFT", self.PlayStyleLabel, "BOTTOMLEFT", -1, -15); - else - self.ItemLevel:SetPoint("TOPLEFT", self.Description, "BOTTOMLEFT", -6, -19); - self.PvpItemLevel:SetPoint("TOPLEFT", self.Description, "BOTTOMLEFT", -6, -19); - end - if(self.ItemLevel:IsShown()) then - LFGListRequirement_Validate(self.ItemLevel, self.ItemLevel.EditBox:GetText()); - else - LFGListRequirement_Validate(self.PvpItemLevel, self.PvpItemLevel.EditBox:GetText()); - end - - LFGListEntryCreation_SetPlaystyleLabelTextFromActivityInfo(self, activityInfo); - LFGListEntryCreation_UpdateValidState(self); - LFGListEntryCreation_SetTitleFromActivityInfo(self); -end - -function LFGListEntryCreation_SetPlaystyleLabelTextFromActivityInfo(self, activityInfo) - if(not activityInfo) then - return; - end - local labelText; - if(activityInfo.isRatedPvpActivity) then - labelText = LFG_PLAYSTYLE_LABEL_PVP - elseif (activityInfo.isMythicPlusActivity) then - labelText = LFG_PLAYSTYLE_LABEL_PVE; - else - labelText = LFG_PLAYSTYLE_LABEL_PVE_MYTHICZERO; - end - self.PlayStyleLabel:SetText(labelText); -end - -function LFGListEntryCreation_OnPlayStyleSelectedInternal(self, playstyle) - local activityInfo = C_LFGList.GetActivityInfoTable(self.selectedActivity); - local previousPlaystyle = self.selectedPlaystyle - self.selectedPlaystyle = playstyle; - if(C_LFGList.DoesEntryTitleMatchPrebuiltTitle(self.selectedActivity, self.selectedGroup, previousPlaystyle)) then - LFGListEntryCreation_SetTitleFromActivityInfo(self); - end -end - -function LFGListEntryCreation_OnPlayStyleSelected(self, playstyle) - LFGListEntryCreation_OnPlayStyleSelectedInternal(self, playstyle); - self.PlayStyleDropdown:GenerateMenu(); -end - -function LFGListEntryCreation_GetSanitizedName(self) - return string.match(self.Name:GetText(), "^%s*(.-)%s*$"); -end - -function LFGListEntryCreation_ListGroupInternal(self, activityID, itemLevel, autoAccept, privateGroup, questID, mythicPlusRating, pvpRating, selectedPlaystyle, isCrossFaction) - -- Arguments struct. - local createData = { - activityIDs = { activityID }, - questID = questID, - isAutoAccept = autoAccept, - isCrossFactionListing = isCrossFaction, - isPrivateGroup = privateGroup, - playstyle = selectedPlaystyle, - requiredDungeonScore = mythicPlusRating, - requiredItemLevel = itemLevel, - requiredPvpRating = pvpRating, - }; - - if ( LFGListEntryCreation_IsEditMode(self) ) then - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - -- Pull these values from the active entry. - createData.isAutoAccept = activeEntryInfo.autoAccept; - createData.questID = activeEntryInfo.questID; - - if activeEntryInfo.isCrossFactionListing == isCrossFaction then - C_LFGList.UpdateListing(createData); - else - -- Changing cross faction setting requires re-listing the group due to how listings are bucketed server side. - C_LFGList.RemoveListing(); - C_LFGList.CreateListing(createData); - end - LFGListFrame_SetActivePanel(self:GetParent(), self:GetParent().ApplicationViewer); - else - if(C_LFGList.CreateListing(createData)) then - self.WorkingCover:Show(); - LFGListEntryCreation_ClearFocus(self); - end - end -end - -function LFGListEntryCreation_ListGroup(self) - - local itemLevel; - if(self.ItemLevel:IsShown()) then - itemLevel = tonumber(self.ItemLevel.EditBox:GetText()) or 0; - else - itemLevel = tonumber(self.PvpItemLevel.EditBox:GetText()) or 0; - end - local pvpRating = tonumber(self.PVPRating.EditBox:GetText()) or 0; - local mythicPlusRating = tonumber(self.MythicPlusRating.EditBox:GetText()) or 0; - local autoAccept = false; - local privateGroup = self.PrivateGroup.CheckButton:GetChecked(); - local isCrossFaction = self.CrossFactionGroup:IsShown() and not self.CrossFactionGroup.CheckButton:GetChecked(); - local selectedPlaystyle = self.PlayStyleDropdown:IsShown() and self.selectedPlaystyle or nil; - - LFGListEntryCreation_ListGroupInternal(self, self.selectedActivity, itemLevel, autoAccept, privateGroup, 0, mythicPlusRating, pvpRating, selectedPlaystyle, isCrossFaction); -end - -function LFGListEntryCreation_SetAutoCreateDataInternal(self, activityType, activityID, contextID) - self.autoCreateActivityType = activityType; - self.autoCreateActivityID = activityID; - self.autoCreateContextID = contextID; -end - -function LFGListEntryCreation_SetAutoCreateMode(self, activityType, activityID, contextID) - LFGListEntryCreation_SetAutoCreateDataInternal(self, activityType, activityID, contextID); -end - -function LFGListEntryCreation_ClearAutoCreateMode(self) - LFGListEntryCreation_SetAutoCreateDataInternal(self, nil, nil, nil); -end - -function LFGListEntryCreation_IsAutoCreateMode(self) - return self.autoCreateActivityType ~= nil; -end - -function LFGListEntryCreation_GetAutoCreateDataQuest(self) - local questID, activityID = self.autoCreateContextID, self.autoCreateActivityID; - - local itemLevel = 0; - local autoAccept = true; - local privateGroup = false; - - return activityID, itemLevel, autoAccept, privateGroup, questID; -end - -function LFGListEntryCreation_GetAutoCreateData(self) - if self.autoCreateActivityType == "quest" then - return LFGListEntryCreation_GetAutoCreateDataQuest(self); - end -end - -function LFGListEntryCreation_CheckAutoCreate(self) - if LFGListEntryCreation_IsAutoCreateMode(self) then - C_LFGList.ClearCreationTextFields(); - LFGListEntryCreation_ListGroupInternal(self, LFGListEntryCreation_GetAutoCreateData(self)); - LFGListEntryCreation_ClearAutoCreateMode(self); - end -end - -function LFGListEntryCreation_UpdateValidState(self) - local errorText; - local activityInfo = C_LFGList.GetActivityInfoTable(self.selectedActivity) - local maxNumPlayers = activityInfo and activityInfo.maxNumPlayers or 0; - local mythicPlusDisableActivity = not C_LFGList.IsPlayerAuthenticatedForLFG(activityInfo.categoryID) and (activityInfo.isMythicPlusActivity and not C_LFGList.GetKeystoneForActivity(self.selectedActivity)); - if ( maxNumPlayers > 0 and GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) >= maxNumPlayers ) then - errorText = string.format(LFG_LIST_TOO_MANY_FOR_ACTIVITY, maxNumPlayers); - elseif (mythicPlusDisableActivity) then - errorText = LFG_AUTHENTICATOR_BUTTON_MYTHIC_PLUS_TOOLTIP; - elseif ( LFGListEntryCreation_GetSanitizedName(self) == "" ) then - errorText = LFG_LIST_MUST_HAVE_NAME; - elseif ( self.ItemLevel.warningText ) then - errorText = self.ItemLevel.warningText; - elseif (self.PvpItemLevel.warningText) then - errorText = self.PvpItemLevel.warningText; - elseif (self.MythicPlusRating.warningText) then - errorText = self.MythicPlusRating.warningText; - elseif (self.PVPRating.warningText) then - errorText = self.PVPRating.warningText; - else - errorText = LFGListUtil_GetActiveQueueMessage(false); - end - - LFGListEntryCreation_UpdateAuthenticatedState(self); - - self.ListGroupButton.DisableStateClickButton:SetShown(mythicPlusDisableActivity); - self.ListGroupButton:SetEnabled(not errorText and not mythicPlusDisableActivity); - self.ListGroupButton.errorText = errorText; -end - -function LFGListEntryCreation_UpdateAuthenticatedState(self) - local isAuthenticated = C_LFGList.IsPlayerAuthenticatedForLFG(self.selectedCategory); - self.Description.EditBox:SetEnabled(isAuthenticated); - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - local isQuestListing = activeEntryInfo and activeEntryInfo.questID or nil; - self.Name:SetEnabled(isAuthenticated and not isQuestListing); - self.VoiceChat.EditBox:SetEnabled(isAuthenticated) -end - -function LFGListEntryCreation_SetBaseFilters(self, baseFilters) - self.baseFilters = baseFilters; -end - -function LFGListEntryCreation_SetTitleFromActivityInfo(self) - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - if(not self.selectedActivity or not self.selectedGroup or not self.selectedCategory) then - return; - end - local activityID = activeEntryInfo and activeEntryInfo.activityIDs[1] or (self.selectedActivity or 0); - local activityInfo = C_LFGList.GetActivityInfoTable(activityID); - if((activityInfo and activityInfo.isMythicPlusActivity) or not C_LFGList.IsPlayerAuthenticatedForLFG(self.selectedCategory)) then - C_LFGList.SetEntryTitle(self.selectedActivity, self.selectedGroup, self.selectedPlaystyle); - end -end - -function LFGListEntryCreation_SetEditMode(self, editMode) - self.editMode = editMode; - - local descInstructions = nil; - local isAccountSecured = C_LFGList.IsPlayerAuthenticatedForLFG(self:GetParent().selectedCategory); - if (not isAccountSecured) then - descInstructions = LFG_AUTHENTICATOR_DESCRIPTION_BOX; - end - - if ( editMode ) then - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - assert(activeEntryInfo); - - --Update the dropdowns - LFGListEntryCreation_Select(self, nil, nil, nil, activeEntryInfo.activityIDs[1]); - - self.GroupDropdown:Disable(); - self.ActivityDropdown:Disable(); - - --Update edit boxes - C_LFGList.CopyActiveEntryInfoToCreationFields(); - self.Name:SetEnabled(activeEntryInfo.questID == nil and isAccountSecured); - if ( activeEntryInfo.questID ) then - self.Description.EditBox.Instructions:SetText(LFGListUtil_GetQuestDescription(activeEntryInfo.questID)); - else - self.Description.EditBox.Instructions:SetText(descInstructions or DESCRIPTION_OF_YOUR_GROUP); - end - - if (self.ItemLevel:IsShown()) then - self.ItemLevel.EditBox:SetText(activeEntryInfo.requiredItemLevel ~= 0 and activeEntryInfo.requiredItemLevel or ""); - else - self.PvpItemLevel.EditBox:SetText(activeEntryInfo.requiredItemLevel ~= 0 and activeEntryInfo.requiredItemLevel or ""); - end - self.MythicPlusRating.EditBox:SetText(activeEntryInfo.requiredDungeonScore or "" ); - self.PVPRating.EditBox:SetText(activeEntryInfo.requiredPvpRating or "" ) - self.PrivateGroup.CheckButton:SetChecked(activeEntryInfo.privateGroup); - self.CrossFactionGroup.CheckButton:SetChecked(not activeEntryInfo.isCrossFactionListing); - if(self.PlayStyleDropdown:IsShown()) then - LFGListEntryCreation_OnPlayStyleSelected(self, self.PlayStyleDropdown, activeEntryInfo.playstyle); - end - - self.ListGroupButton:SetText(DONE_EDITING); - else - self.GroupDropdown:Enable(); - self.ActivityDropdown:Enable(); - self.ListGroupButton:SetText(LIST_GROUP); - self.Name:SetEnabled(isAccountSecured); - self.Description.EditBox.Instructions:SetText(descInstructions or DESCRIPTION_OF_YOUR_GROUP); - local activityInfo = C_LFGList.GetActivityInfoTable(self.selectedActivity); - - if(activityInfo and self.selectedCategory == GROUP_FINDER_CATEGORY_ID_DUNGEONS) then - local activityID, groupID = C_LFGList.GetOwnedKeystoneActivityAndGroupAndLevel(); --Prioritize regular keystones - if(activityID) then - LFGListEntryCreation_Select(self, self.selectedFilters, self.selectedCategory, groupID, activityID); - else - activityID, groupID = C_LFGList.GetOwnedKeystoneActivityAndGroupAndLevel(true); -- Check for a timewalking keystone. - if(activityID) then - LFGListEntryCreation_Select(self, self.selectedFilters, self.selectedCategory, groupID, activityID); - end - end - end - end -end - -function LFGListEntryCreation_IsEditMode(self) - return self.editMode; -end - -function LFGListEntryCreationCancelButton_OnClick(self) - local panel = self:GetParent(); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - if ( LFGListEntryCreation_IsEditMode(panel) ) then - LFGListFrame_SetActivePanel(panel:GetParent(), panel:GetParent().ApplicationViewer); - else - LFGListFrame_SetActivePanel(panel:GetParent(), panel:GetParent().CategorySelection); - end -end - -function LFGListEntryCreationListGroupButton_OnClick(self) - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - LFGListEntryCreation_ListGroup(self:GetParent()); -end - -function LFGListEntryCreationActivityFinder_OnLoad(self) - local view = CreateScrollBoxListLinearView(); - view:SetElementInitializer("LFGListEntryCreationActivityListTemplate", function(button, elementData) - LFGListEntryCreationActivityFinder_InitButton(button, elementData); - end); - - ScrollUtil.InitScrollBoxListWithScrollBar(self.Dialog.ScrollBox, self.Dialog.ScrollBar, view); - - self.matchingActivities = {}; -end - -function LFGListEntryCreationActivityFinder_Show(self, categoryID, groupID, filters) - self.Dialog.EntryBox:SetText(""); - self.categoryID = categoryID; - self.groupID = groupID; - self.filters = filters; - self.selectedActivity = nil; - LFGListEntryCreationActivityFinder_UpdateMatching(self); - self:Show(); - self.Dialog.EntryBox:SetFocus(); -end - -function LFGListEntryCreationActivityFinder_UpdateMatching(self) - local filters = self.filters; - self.matchingActivities = C_LFGList.GetAvailableActivities(self.categoryID, self.groupID, filters, self.Dialog.EntryBox:GetText()); - LFGListUtil_SortActivitiesByRelevancy(self.matchingActivities); - if ( not self.selectedActivity or not tContains(self.matchingActivities, self.selectedActivity) ) then - self.selectedActivity = self.matchingActivities[1]; - end - - local dataProvider = CreateDataProviderWithAssignedKey(self.matchingActivities, "id"); - self.Dialog.ScrollBox:SetDataProvider(dataProvider); -end - -function LFGListEntryCreationActivityFinder_InitButton(button, elementData) - local id = elementData.id; - button.activityID = id; - local activityInfo = C_LFGList.GetActivityInfoTable(id); - if(activityInfo) then - button:SetText(activityInfo.fullName); - LFGListEntryCreationActivityFinder_SetButtonSelected(button, LFGListFrame.EntryCreation.ActivityFinder.selectedActivity == id); - end -end - -function LFGListEntryCreationActivityFinder_SetButtonSelected(button, selected) - button.Selected:SetShown(selected); - if ( selected ) then - button:LockHighlight(); - else - button:UnlockHighlight(); - end -end - -function LFGListEntryCreationActivityFinder_Accept(self) - if ( self.selectedActivity ) then - LFGListEntryCreation_Select(self:GetParent(), nil, nil, nil, self.selectedActivity); - end - self:Hide(); -end - -function LFGListEntryCreationActivityFinder_Cancel(self) - self:Hide(); -end - -function LFGListEntryCreationActivityFinder_Select(self, activityID) - local oldSelectedActivityID = self.selectedActivity; - self.selectedActivity = activityID; - - local function UpdateButtonSelection(id, selected) - if id then - local button = self.Dialog.ScrollBox:FindFrameByPredicate(function(button, elementData) - return elementData.id == id; - end); - if button then - LFGListEntryCreationActivityFinder_SetButtonSelected(button, selected); - end - end - end; - - UpdateButtonSelection(oldSelectedActivityID, false); - UpdateButtonSelection(activityID, true); -end - -------------------------------------------------------- -----------Application Viewing -------------------------------------------------------- -function LFGListApplicationViewer_OnLoad(self) - local view = CreateScrollBoxListLinearView(); - view:SetElementExtentCalculator(function(dataIndex, elementData) - return LFGListApplicationViewerUtil_GetButtonHeight(elementData.numMembers); - end); - view:SetElementInitializer("LFGListApplicantTemplate", function(button, elementData) - LFGListApplicationViewer_InitButton(button, elementData); - end); - - ScrollUtil.InitScrollBoxListWithScrollBar(self.ScrollBox, self.ScrollBar, view); - -end - -function LFGListApplicationViewer_OnEvent(self, event, ...) - if ( event == "LFG_LIST_ACTIVE_ENTRY_UPDATE" ) then - LFGListApplicationViewer_UpdateInfo(self); - elseif ( event == "PARTY_LEADER_CHANGED" ) then - LFGListApplicationViewer_UpdateAvailability(self); - LFGListApplicationViewer_UpdateInfo(self); - LFGListApplicationViewer_UpdateResultList(self); - LFGListApplicationViewer_UpdateResults(self); - elseif ( event == "LFG_LIST_APPLICANT_LIST_UPDATED" ) then - LFGListApplicationViewer_UpdateResultList(self); - LFGListApplicationViewer_UpdateResults(self); - elseif ( event == "LFG_LIST_APPLICANT_UPDATED" ) then - --If we can't make changes, we just remove people immediately - local id = ...; - if ( not LFGListUtil_IsEntryEmpowered() ) then - C_LFGList.RemoveApplicant(id); - LFGListApplicationViewer_UpdateResultList(self); - LFGListApplicationViewer_UpdateResults(self); - else - local frame = self.ScrollBox:FindFrameByPredicate(function(frame, elementData) - return elementData.id == id; - end); - if frame then - LFGListApplicationViewer_UpdateApplicant(frame, id); - end - end - - --Update whether we can invite people - LFGListApplicationViewer_UpdateInviteState(self); - elseif ( event == "GROUP_ROSTER_UPDATE" ) then - LFGListApplicationViewer_UpdateAvailability(self); - LFGListApplicationViewer_UpdateGroupData(self); - LFGListApplicationViewer_UpdateInviteState(self); - LFGListApplicationViewer_UpdateInfo(self); - elseif ( event == "PLAYER_ROLES_ASSIGNED") then - LFGListApplicationViewer_UpdateGroupData(self); - end -end - -function LFGListApplicationViewer_OnShow(self) - C_LFGList.RefreshApplicants(); - LFGListApplicationViewer_UpdateResultList(self); - LFGListApplicationViewer_UpdateResults(self); - LFGListApplicationViewer_UpdateInfo(self); - LFGListApplicationViewer_UpdateAvailability(self); - LFGListApplicationViewer_UpdateGroupData(self); -end - -function LFGListApplicationViewer_UpdateGroupData(self) - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - if ( not activeEntryInfo ) then - return; - end - - local data = GetGroupMemberCountsForDisplay(); - LFGListGroupDataDisplay_Update(self.DataDisplay, activeEntryInfo.activityIDs[1], data); -end - -function LFGListApplicationViewer_UpdateInfo(self) - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - assert(activeEntryInfo); - local activityInfo = C_LFGList.GetActivityInfoTable(activeEntryInfo.activityIDs[1]); - if(not activityInfo) then - return; - end - local categoryInfo = C_LFGList.GetLfgCategoryInfo(activityInfo.categoryID); - - if (not categoryInfo) then - return; - end - - self.RatingColumnHeader:SetShown(activityInfo.isMythicPlusActivity or activityInfo.isRatedPvpActivity); - self.EntryName:SetWidth(0); - self.EntryName:SetText(activeEntryInfo.name); - self.DescriptionFrame.activityName = activityInfo.fullName; - if ( activeEntryInfo.comment == "" and activeEntryInfo.questID ) then - activeEntryInfo.comment = LFGListUtil_GetQuestDescription(activeEntryInfo.questID); - end - self.DescriptionFrame.comment = activeEntryInfo.comment; - if ( activeEntryInfo.comment == "" ) then - self.DescriptionFrame.Text:SetText(self.DescriptionFrame.activityName); - else - self.DescriptionFrame.Text:SetFormattedText("%s |cff888888- %s|r", self.DescriptionFrame.activityName, self.DescriptionFrame.comment); - end - - local hasRestrictions = false; - if (activityInfo.isPvpActivity) then - if ( activeEntryInfo.requiredItemLevel == 0 ) then - self.ItemLevel:SetText(""); - else - self.ItemLevel:SetFormattedText(LFG_LIST_ITEM_LEVEL_CURRENT_PVP, activeEntryInfo.requiredItemLevel); - end - else - if ( activeEntryInfo.requiredItemLevel == 0 ) then - self.ItemLevel:SetText(""); - else - self.ItemLevel:SetFormattedText(LFG_LIST_ITEM_LEVEL_CURRENT, activeEntryInfo.requiredItemLevel); - end - end - - if ( activeEntryInfo.privateGroup ) then - self.PrivateGroup:SetText(LFG_LIST_PRIVATE); - self.ItemLevel:ClearAllPoints(); - self.ItemLevel:SetPoint("LEFT", self.PrivateGroup, "RIGHT", 3, 0); - else - self.PrivateGroup:SetText(""); - self.ItemLevel:ClearAllPoints(); - self.ItemLevel:SetPoint("TOPLEFT", self.InfoBackground, "TOPLEFT", 12, -52); - end - - if ( activeEntryInfo.voiceChat == "" ) then - self.VoiceChatFrame.tooltip = nil; - self.VoiceChatFrame:Hide(); - else - self.VoiceChatFrame.tooltip = activeEntryInfo.voiceChat; - self.VoiceChatFrame:Show(); - end - - if ( self.EntryName:GetWidth() > 290 ) then - self.EntryName:SetWidth(290); - end - - local filters = activityInfo.filters; - --Set the background - local atlasName = nil; - if ( categoryInfo.separateRecommended and bit.band(filters, Enum.LFGListFilter.Recommended) ~= 0 ) then - atlasName = "groupfinder-background-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[LFGListUtil_GetCurrentExpansion()]; - elseif ( categoryInfo.separateRecommended and bit.band(filters, Enum.LFGListFilter.NotRecommended) ~= 0 ) then - atlasName = "groupfinder-background-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[math.max(0,LFGListUtil_GetCurrentExpansion() - 1)]; - else - atlasName = "groupfinder-background-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "questing"); - end - - local suffix = ""; - if ( bit.band(filters, Enum.LFGListFilter.PvE) ~= 0 ) then - suffix = "-pve"; - elseif ( bit.band(filters, Enum.LFGListFilter.PvP) ~= 0 ) then - suffix = "-pvp"; - end - - --Try with the suffix and then without it - if ( not self.InfoBackground:SetAtlas(atlasName..suffix) ) then - self.InfoBackground:SetAtlas(atlasName); - end - - local isPartyLeader = UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME); - --Update the AutoAccept button - self.AutoAcceptButton:SetChecked(activeEntryInfo.autoAccept); - - self.RemoveEntryButton:ClearAllPoints() - self.BrowseGroupsButton:SetShown(isPartyLeader); - - if (isPartyLeader) then - self.RemoveEntryButton:SetPoint("RIGHT", self.EditButton, "LEFT", 2, 0); - else - self.RemoveEntryButton:SetPoint("BOTTOMLEFT", -3, 4); - end - - if ( not C_LFGList.CanActiveEntryUseAutoAccept() ) then - self.AutoAcceptButton:Hide(); - elseif ( isPartyLeader ) then - self.AutoAcceptButton:Show(); - self.AutoAcceptButton:Enable(); - self.AutoAcceptButton.Label:SetFontObject(GameFontHighlightSmall); - elseif ( UnitIsGroupAssistant("player", LE_PARTY_CATEGORY_HOME) ) then - self.AutoAcceptButton:Show(); - self.AutoAcceptButton:Disable(); - self.AutoAcceptButton.Label:SetFontObject(GameFontDisableSmall); - else - self.AutoAcceptButton:SetShown(activeEntryInfo.autoAccept); - self.AutoAcceptButton:Disable(); - self.AutoAcceptButton.Label:SetFontObject(GameFontDisableSmall); - end -end - -function LFGListApplicationViewer_UpdateAvailability(self) - if ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then - self.RemoveEntryButton:Show(); - self.EditButton:Show(); - else - self.RemoveEntryButton:Hide(); - self.EditButton:Hide(); - end - - if ( IsRestrictedAccount() ) then - self.EditButton:Disable(); - self.EditButton.tooltip = ERR_RESTRICTED_ACCOUNT_LFG_LIST_TRIAL; - else - self.EditButton:Enable(); - self.EditButton.tooltip = nil; - end - - local empowered = LFGListUtil_IsEntryEmpowered(); - self.UnempoweredCover:SetShown(not empowered); - self.ScrollBox.NoApplicants:SetShown(empowered and (not self.applicants or #self.applicants == 0)); -end - -function LFGListApplicationViewer_UpdateResultList(self) - self.applicants = C_LFGList.GetApplicants(); - - --Sort applicants - LFGListUtil_SortApplicants(self.applicants); - - LFGListApplicationViewer_UpdateAvailability(self); -end - -function LFGListApplicationViewer_UpdateInviteState(self) - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - if ( not activeEntryInfo ) then - return; - end - - local activityInfo = C_LFGList.GetActivityInfoTable(activeEntryInfo.activityIDs[1], activeEntryInfo.questID); - local numAllowed = activityInfo and activityInfo.maxNumPlayers or 0; - if ( numAllowed == 0 ) then - numAllowed = MAX_RAID_MEMBERS; - end - - local currentCount = GetNumGroupMembers(LE_PARTY_CATEGORY_HOME); - local numInvited = C_LFGList.GetNumInvitedApplicantMembers(); - - self.ScrollBox:ForEachFrame(function(button) - if ( button.numMembers + currentCount > numAllowed ) then - button.InviteButton:Disable(); - button.InviteButton.tooltip = LFG_LIST_GROUP_TOO_FULL; - elseif ( button.numMembers + currentCount + numInvited > numAllowed ) then - button.InviteButton:Disable(); - button.InviteButton.tooltip = LFG_LIST_INVITED_APP_FILLS_GROUP; - else - button.InviteButton:Enable(); - button.InviteButton.tooltip = nil; - end - - --If our mouse is already over the button, update the tooltip - if ( button.InviteButton:IsMouseOver() ) then - if ( button.InviteButton.tooltip ) then - button.InviteButton:GetScript("OnEnter")(button.InviteButton); - else - GameTooltip:Hide(); - end - end - end); -end - -function LFGListApplicationViewer_InitButton(button, elementData) - local id = elementData.id; - local index = elementData.index; - - button.applicantID = id; - LFGListApplicationViewer_UpdateApplicant(button, id); - button.Background:SetAlpha(index % 2 == 0 and 0.1 or 0.05); -end - -function LFGListApplicationViewer_UpdateResults(self) - --If the mouse is over something in this frame, update it - local mouseovers = GetMouseFoci(); - for _, mouseover in ipairs(mouseovers) do - local mouseoverParent = mouseover and mouseover:GetParent(); - local parentParent = mouseoverParent and mouseoverParent:GetParent(); - if ( mouseoverParent == self.ScrollFrame or parentParent == self.ScrollFrame ) then - --Just hide the tooltip. We should show it again inside the update function. - GameTooltip:Hide(); - break; - end - end - - local dataProvider = CreateDataProvider(); - for index = 1, #self.applicants do - local id = self.applicants[index]; - local info = C_LFGList.GetApplicantInfo(id); - local numMembers = info.numMembers; - dataProvider:Insert({index=index, id=id, numMembers=numMembers}); - end - self.ScrollBox:SetDataProvider(dataProvider, ScrollBoxConstants.RetainScrollPosition); - - LFGListApplicationViewer_UpdateInviteState(self); -end - -function LFGListApplicationViewer_UpdateApplicant(button, id) - local applicantInfo = C_LFGList.GetApplicantInfo(id); - button:SetHeight(LFGListApplicationViewerUtil_GetButtonHeight(applicantInfo.numMembers)); - - --Update individual members - for i=1, applicantInfo.numMembers do - local member = button.Members[i]; - if ( not member ) then - member = CreateFrame("BUTTON", nil, button, "LFGListApplicantMemberTemplate"); - member:SetPoint("TOPLEFT", button.Members[i-1], "BOTTOMLEFT", 0, 0); - button.Members[i] = member; - end - LFGListApplicationViewer_UpdateApplicantMember(member, id, i, applicantInfo.applicationStatus, applicantInfo.pendingApplicationStatus); - member:Show(); - end - - --Hide extra member buttons - for i=applicantInfo.numMembers+1, #button.Members do - button.Members[i]:Hide(); - end - - --Update the Invite and Decline buttons based on group size - if ( applicantInfo.numMembers > 1 ) then - button.DeclineButton:SetHeight(36); - button.InviteButton:SetHeight(36); - else - button.DeclineButton:SetHeight(22); - button.InviteButton:SetHeight(22); - end - - if ( applicantInfo.applicantInfo or applicantInfo.applicationStatus == "applied" ) then - button.Status:Hide(); - elseif ( applicantInfo.applicationStatus == "invited" ) then - button.Status:Show(); - button.Status:SetText(LFG_LIST_APP_INVITED); - button.Status:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); - elseif ( applicantInfo.applicationStatus == "failed" or applicantInfo.applicationStatus == "cancelled" ) then - button.Status:Show(); - button.Status:SetText(LFG_LIST_APP_CANCELLED); - button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); - elseif ( applicantInfo.applicationStatus == "declined" or applicantInfo.applicationStatus == "declined_full" or applicantInfo.applicationStatus == "declined_delisted" ) then - button.Status:Show(); - button.Status:SetText(LFG_LIST_APP_DECLINED); - button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); - elseif ( applicantInfo.applicationStatus == "timedout" ) then - button.Status:Show(); - button.Status:SetText(LFG_LIST_APP_TIMED_OUT); - button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); - elseif ( applicantInfo.applicationStatus == "inviteaccepted" ) then - button.Status:Show(); - button.Status:SetText(LFG_LIST_APP_INVITE_ACCEPTED); - button.Status:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); - elseif ( applicantInfo.applicationStatus == "invitedeclined" ) then - button.Status:Show(); - button.Status:SetText(LFG_LIST_APP_INVITE_DECLINED); - button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); - end - - button.numMembers = applicantInfo.numMembers; - local useSmallInviteButton = LFGApplicationViewerRatingColumnHeader:IsShown(); - button.Status:ClearAllPoints(); - - button.InviteButtonSmall:SetShown(useSmallInviteButton and not applicantInfo.applicantInfo and applicantInfo.applicationStatus == "applied" and LFGListUtil_IsEntryEmpowered()); - button.InviteButton:SetShown(not useSmallInviteButton and not applicantInfo.applicantInfo and applicantInfo.applicationStatus == "applied" and LFGListUtil_IsEntryEmpowered()); - button.DeclineButton:SetShown(not applicantInfo.applicantInfo and applicantInfo.applicationStatus ~= "invited" and LFGListUtil_IsEntryEmpowered()); - button.DeclineButton.isAck = (applicantInfo.applicationStatus ~= "applied" and applicantInfo.applicationStatus ~= "invited"); - if(button.DeclineButton:IsShown()) then - button.Status:SetPoint("RIGHT", button.DeclineButton, "LEFT", -14, 0); - else - button.Status:SetPoint("CENTER", button, "RIGHT", -37, 0); - end - button.Spinner:SetShown(applicantInfo.applicantInfo); -end - -function LFGListApplicationViewer_UpdateRoleIcons(member, grayedOut, tank, healer, damage, noTouchy, assignedRole) - --Update the roles. - if ( grayedOut ) then - member.RoleIcon1:Hide(); - member.RoleIcon2:Hide(); - member.RoleIcon3:Hide(); - else - local role1 = tank and "TANK" or (healer and "HEALER" or (damage and "DAMAGER")); - local role2 = (tank and healer and "HEALER") or ((tank or healer) and damage and "DAMAGER"); - local role3 = (tank and healer and damage and "DAMAGER"); - member.RoleIcon1:GetNormalTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role1]); - member.RoleIcon1:GetHighlightTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role1]); - if ( role2 ) then - member.RoleIcon2:GetNormalTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role2]); - member.RoleIcon2:GetHighlightTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role2]); - end - if ( role3 ) then - member.RoleIcon3:GetNormalTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role3]); - member.RoleIcon3:GetHighlightTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role3]); - end - - member.RoleIcon1:SetEnabled(not noTouchy and role1 ~= assignedRole); - member.RoleIcon1:SetAlpha(role1 == assignedRole and 1 or 0.3); - member.RoleIcon1:Show(); - member.RoleIcon2:SetEnabled(not noTouchy and role2 ~= assignedRole); - member.RoleIcon2:SetAlpha(role2 == assignedRole and 1 or 0.3); - member.RoleIcon2:SetShown(role2); - member.RoleIcon3:SetEnabled(not noTouchy and role3 ~= assignedRole); - member.RoleIcon3:SetAlpha(role3 == assignedRole and 1 or 0.3); - member.RoleIcon3:SetShown(role3); - member.RoleIcon1.role = role1; - member.RoleIcon2.role = role2; - member.RoleIcon3.role = role3; - end -end - -function LFGListApplicationViewer_UpdateApplicantMember(member, appID, memberIdx, status, pendingStatus) - local grayedOut = not pendingStatus and (status == "failed" or status == "cancelled" or status == "declined" or status == "declined_full" or status == "declined_delisted" or status == "invitedeclined" or status == "timedout" or status == "inviteaccepted" or status == "invitedeclined"); - local noTouchy = (status == "invited"); - - local name, class, localizedClass, level, itemLevel, honorLevel, tank, healer, damage, assignedRole, relationship, dungeonScore, pvpItemLevel = C_LFGList.GetApplicantMemberInfo(appID, memberIdx); - - member.memberIdx = memberIdx; - - member.Name:SetWidth(0); - if ( name ) then - local displayName = Ambiguate(name, "short"); - if ( memberIdx > 1 ) then - member.Name:SetText(" "..displayName); - else - member.Name:SetText(displayName); - end - - local classTextColor = grayedOut and GRAY_FONT_COLOR or RAID_CLASS_COLORS[class]; - member.Name:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b); - else - --We might still be requesting the name and class from the server. - member.Name:SetText(""); - end - - member.FriendIcon:SetShown(relationship); - member.FriendIcon.relationship = relationship; - member.FriendIcon.Icon:SetDesaturated(grayedOut); - member.FriendIcon:SetAlpha(grayedOut and 0.5 or 1.0); - - --Adjust name width depending on whether we have the friend icon - local nameLength = 100; - if ( relationship ) then - nameLength = nameLength - 22; - end - if ( member.Name:GetWidth() > nameLength ) then - member.Name:SetWidth(nameLength); - end - - LFGListApplicationViewer_UpdateRoleIcons(member, grayedOut, tank, healer, damage, noTouchy, assignedRole); - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - local activityInfo = C_LFGList.GetActivityInfoTable(activeEntryInfo.activityIDs[1]); - - member.ItemLevel:SetShown(not grayedOut); - if(activityInfo and activityInfo.isPvpActivity) then - member.ItemLevel:SetText(math.floor(pvpItemLevel)); - else - member.ItemLevel:SetText(math.floor(itemLevel)); - end - - local pvpRatingForEntry = C_LFGList.GetApplicantPvpRatingInfoForListing(appID, memberIdx, activeEntryInfo.activityIDs[1]); - - if not grayedOut and LFGApplicationViewerRatingColumnHeader:IsShown() and pvpRatingForEntry then - member.Rating:SetText(pvpRatingForEntry.rating); - member.Rating:Show(); - member:SetWidth(256); - elseif not grayedOut and LFGApplicationViewerRatingColumnHeader:IsShown() and dungeonScore then - local color = C_ChallengeMode.GetDungeonScoreRarityColor(dungeonScore) or HIGHLIGHT_FONT_COLOR; - member.Rating:SetText(color:WrapTextInColorCode(dungeonScore)); - member.Rating:Show(); - member:SetWidth(256); - else - member.Rating:Hide(); - member:SetWidth(200); - end - - local mouseFoci = GetMouseFoci(); - for _, mouseFocus in ipairs(mouseFoci) do - if ( mouseFocus == member ) then - LFGListApplicantMember_OnEnter(member); - break; - elseif ( mouseFocus == member.FriendIcon ) then - member.FriendIcon:GetScript("OnEnter")(member.FriendIcon); - break; - end - end -end - -function LFGListApplicationViewerUtil_GetButtonHeight(numApplicants) - return 20 * numApplicants + 6; -end - -function LFGListApplicationViewerEditButton_OnClick(self) - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - - local panel = self:GetParent(); - local entryCreation = panel:GetParent().EntryCreation; - LFGListEntryCreation_SetEditMode(entryCreation, true); - LFGListFrame_SetActivePanel(panel:GetParent(), entryCreation); -end - ----@class LFGApplicationBrowseGroupsButtonMixin : Button -LFGApplicationBrowseGroupsButtonMixin = { }; -function LFGApplicationBrowseGroupsButtonMixin:OnClick() - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - local panel = self:GetParent(); - local baseFilters = panel:GetParent().baseFilters; - local searchPanel = panel:GetParent().SearchPanel; - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - if(activeEntryInfo) then - local activityInfo = C_LFGList.GetActivityInfoTable(activeEntryInfo.activityIDs[1]); - if(activityInfo) then - LFGListSearchPanel_SetCategory(searchPanel, activityInfo.categoryID, activityInfo.filters, baseFilters); - LFGListFrame_SetActivePanel(panel:GetParent(), searchPanel); - LFGListSearchPanel_DoSearch(searchPanel); - end - end -end - ---Applicant members - -function LFGListApplicantMember_OnMouseDown(self) - MenuUtil.CreateContextMenu(self, function(owner, rootDescription) - rootDescription:SetTag("MENU_LFG_FRAME_MEMBER_APPLY"); - - local applicantID = self:GetParent().applicantID; - local memberIdx = self.memberIdx; - local name, class, localizedClass, level, itemLevel, honorLevel, tank, healer, damage, assignedRole = C_LFGList.GetApplicantMemberInfo(applicantID, memberIdx); - local applicantInfo = C_LFGList.GetApplicantInfo(applicantID); - - rootDescription:CreateTitle(name or ""); - - local whisperButton = rootDescription:CreateButton(WHISPER, function() - ChatFrame_SendTell(name); - end); - - rootDescription:CreateButton(LFG_LIST_REPORT_PLAYER, function() - LFGList_ReportApplicant(applicantID, name or ""); - end); - - local ignoreButton = rootDescription:CreateButton(IGNORE_PLAYER, function() - C_FriendList.AddIgnore(name); - C_LFGList.DeclineApplicant(applicantID); - end); - - if not name then - whisperButton:SetEnabled(false); - ignoreButton:SetEnabled(false); - end - end); -end - -function LFGListApplicantMember_OnEnter(self) - local applicantID = self:GetParent().applicantID; - local memberIdx = self.memberIdx; - - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - if ( not activeEntryInfo ) then - return; - end - - local activityInfo = C_LFGList.GetActivityInfoTable(activeEntryInfo.activityIDs[1]); - if(not activityInfo) then - return; - end - local applicantInfo = C_LFGList.GetApplicantInfo(applicantID); - local name, class, localizedClass, level, itemLevel, honorLevel, tank, healer, damage, assignedRole, relationship, dungeonScore, pvpItemLevel, factionGroup, raceID = C_LFGList.GetApplicantMemberInfo(applicantID, memberIdx); - local bestDungeonScoreForEntry = C_LFGList.GetApplicantDungeonScoreForListing(applicantID, memberIdx, activeEntryInfo.activityIDs[1]); - local pvpRatingForEntry = C_LFGList.GetApplicantPvpRatingInfoForListing(applicantID, memberIdx, activeEntryInfo.activityIDs[1]); - - GameTooltip:SetOwner(self, "ANCHOR_NONE"); - GameTooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 105, 0); - - if ( name ) then - local classTextColor = RAID_CLASS_COLORS[class]; - GameTooltip:SetText(name, classTextColor.r, classTextColor.g, classTextColor.b); - if(UnitFactionGroup("player") ~= PLAYER_FACTION_GROUP[factionGroup]) then - GameTooltip_AddHighlightLine(GameTooltip, UNIT_TYPE_LEVEL_FACTION_TEMPLATE:format(level, localizedClass, FACTION_STRINGS[factionGroup])); - else - GameTooltip_AddHighlightLine(GameTooltip, UNIT_TYPE_LEVEL_TEMPLATE:format(level, localizedClass)); - end - else - GameTooltip:SetText(" "); --Just make it empty until we get the name update - end - - if (activityInfo.isPvpActivity) then - GameTooltip_AddColoredLine(GameTooltip, LFG_LIST_ITEM_LEVEL_CURRENT_PVP:format(pvpItemLevel), HIGHLIGHT_FONT_COLOR); - else - GameTooltip_AddColoredLine(GameTooltip, LFG_LIST_ITEM_LEVEL_CURRENT:format(itemLevel), HIGHLIGHT_FONT_COLOR); - end - - if ( activityInfo.useHonorLevel ) then - GameTooltip:AddLine(string.format(LFG_LIST_HONOR_LEVEL_CURRENT_PVP, honorLevel), 1, 1, 1); - end - if ( applicantInfo.comment and applicantInfo.comment ~= "" ) then - GameTooltip:AddLine(" "); - GameTooltip:AddLine(string.format(LFG_LIST_COMMENT_FORMAT, applicantInfo.comment), LFG_LIST_COMMENT_FONT_COLOR.r, LFG_LIST_COMMENT_FONT_COLOR.g, LFG_LIST_COMMENT_FONT_COLOR.b, true); - end - if(LFGApplicationViewerRatingColumnHeader:IsShown()) then - if(pvpRatingForEntry) then - GameTooltip_AddNormalLine(GameTooltip, PVP_RATING_GROUP_FINDER:format(pvpRatingForEntry.activityName, pvpRatingForEntry.rating, PVPUtil.GetTierName(pvpRatingForEntry.tier))); - else - if(not dungeonScore) then - dungeonScore = 0; - end - GameTooltip_AddBlankLineToTooltip(GameTooltip); - - local color = C_ChallengeMode.GetDungeonScoreRarityColor(dungeonScore); - if(not color) then - color = HIGHLIGHT_FONT_COLOR; - end - GameTooltip_AddNormalLine(GameTooltip, DUNGEON_SCORE_LEADER:format(color:WrapTextInColorCode(dungeonScore))); - if(bestDungeonScoreForEntry) then - color = C_ChallengeMode.GetSpecificDungeonOverallScoreRarityColor(bestDungeonScoreForEntry.mapScore); - if (not color) then - color = HIGHLIGHT_FONT_COLOR; - end - if(bestDungeonScoreForEntry.mapScore == 0) then - GameTooltip_AddNormalLine(GameTooltip, DUNGEON_SCORE_PER_DUNGEON_NO_RATING:format(bestDungeonScoreForEntry.mapName, bestDungeonScoreForEntry.mapScore)); - elseif (bestDungeonScoreForEntry.finishedSuccess) then - GameTooltip_AddNormalLine(GameTooltip, DUNGEON_SCORE_DUNGEON_RATING:format(bestDungeonScoreForEntry.mapName, color:WrapTextInColorCode(bestDungeonScoreForEntry.mapScore), bestDungeonScoreForEntry.bestRunLevel)); - else - GameTooltip_AddNormalLine(GameTooltip, DUNGEON_SCORE_DUNGEON_RATING_OVERTIME:format(bestDungeonScoreForEntry.mapName, color:WrapTextInColorCode(bestDungeonScoreForEntry.mapScore), bestDungeonScoreForEntry.bestRunLevel)); - end - end - end - end - - --Add statistics - local stats = C_LFGList.GetApplicantMemberStats(applicantID, memberIdx); - local lastTitle = nil; - - --Tank proving ground - if ( stats[23690] and stats[23690] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_TANK_GOLD, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - elseif ( stats[23687] and stats[23687] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_TANK_SILVER, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - elseif ( stats[23684] and stats[23684] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_TANK_BRONZE, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - end - - --Healer proving ground - if ( stats[23691] and stats[23691] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_HEALER_GOLD, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - elseif ( stats[23688] and stats[23688] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_HEALER_SILVER, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - elseif ( stats[23685] and stats[23685] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_HEALER_BRONZE, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - end - - --Damage proving ground - if ( stats[23689] and stats[23689] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_DAMAGER_GOLD, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - elseif ( stats[23686] and stats[23686] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_DAMAGER_SILVER, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - elseif ( stats[23683] and stats[23683] > 0 ) then - LFGListUtil_AppendStatistic(LFG_LIST_PROVING_DAMAGER_BRONZE, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle); - lastTitle = LFG_LIST_PROVING_GROUND_TITLE; - end - - GameTooltip:Show(); -end - -------------------------------------------------------- -----------Searching -------------------------------------------------------- -function LFGListSearchPanel_OnLoad(self) - local view = CreateScrollBoxListLinearView(); - view:SetElementFactory(function(factory, elementData) - if elementData.startGroup then - factory("LFGStartGroupButtonListTemplate"); - else - factory("LFGListSearchEntryTemplate", LFGListSearchPanel_InitButton); - end - end); - - ScrollUtil.InitScrollBoxListWithScrollBar(self.ScrollBox, self.ScrollBar, view); - - self.SearchBox.clearButton:SetScript("OnClick", function(btn) - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - local editBox = btn:GetParent(); - C_LFGList.ClearSearchTextFields(); - editBox:ClearFocus(); - - LFGListSearchPanel_DoSearch(self); - end); - - self.FilterButton:SetWidth(93); -end - -function LFGListSearchPanel_OnEvent(self, event, ...) - --Note: events are dispatched from the base frame. Add RegisterEvent there. - if ( event == "LFG_LIST_SEARCH_RESULTS_RECEIVED" ) then - StaticPopupSpecial_Hide(LFGListApplicationDialog); - self.searching = false; - self.searchFailed = false; - LFGListSearchPanel_UpdateResultList(self); - elseif ( event == "LFG_LIST_SEARCH_FAILED" ) then - self.searching = false; - self.searchFailed = true; - LFGListSearchPanel_UpdateResultList(self); - elseif ( event == "LFG_LIST_SEARCH_RESULT_UPDATED" ) then - local id = ...; - if ( self.selectedResult == id ) then - LFGListSearchPanel_ValidateSelected(self); - if ( self.selectedResult ~= id ) then - LFGListSearchPanel_UpdateResults(self); - end - else - local updatedEntryFrame = self.ScrollBox:FindFrameByPredicate(function(frame) - local elementData = frame:GetElementData(); - return elementData and elementData.resultID == id; - end); - if updatedEntryFrame then - LFGListSearchEntry_Update(updatedEntryFrame); - end - end - LFGListSearchPanel_UpdateButtonStatus(self); - elseif ( event == "LFG_LIST_UPDATE_SEARCH_RESULTS" ) then - LFGListSearchPanel_UpdateResultList(self); - elseif ( event == "PARTY_LEADER_CHANGED" ) then - LFGListSearchPanel_UpdateButtonStatus(self); - elseif ( event == "GROUP_ROSTER_UPDATE" ) then - LFGListSearchPanel_UpdateButtonStatus(self); - elseif ( event == "PLAYER_SPECIALIZATION_CHANGED" ) then - local unit = ...; - if ( unit == "player" ) then - LFGListSearchPanel_UpdateButtonStatus(self); - end - elseif ( event == "UNIT_CONNECTION" ) then - LFGListSearchPanel_UpdateButtonStatus(self); - elseif ( event == "LFG_ROLE_CHECK_UPDATE" ) then - LFGListSearchPanel_UpdateResultList(self); - end - - if ( tContains(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS, event) ) then - LFGListSearchPanel_UpdateButtonStatus(self); - end -end - -function LFGListSearchPanel_SetupLanguageFilter(dropdown, rootDescription) - local enabled = C_LFGList.GetLanguageSearchFilter(); - local defaults = C_LFGList.GetDefaultLanguageSearchFilter(); - - local function IsSelected(lang) - return enabled[lang] or defaults[lang]; - end - - local function SetSelected(lang) - enabled[lang] = not IsSelected(lang); - C_LFGList.SaveLanguageSearchFilter(enabled); - end - - for i, lang in ipairs(C_LFGList.GetAvailableLanguageSearchFilter()) do - local text = _G["LFG_LIST_LANGUAGE_"..string.upper(lang)]; - local checkbox = rootDescription:CreateCheckbox(text, IsSelected, SetSelected, lang); - - if defaults[lang] then - checkbox:SetEnabled(false); - end - end -end - -function LFGListSearchPanel_OnShow(self) - LFGListSearchPanel_UpdateResultList(self); - --LFGListSearchPanel_UpdateButtonStatus(self); --Called by UpdateResults - - local availableLanguages = C_LFGList.GetAvailableLanguageSearchFilter(); - local defaultLanguages = C_LFGList.GetDefaultLanguageSearchFilter(); - - local canChangeLanguages = false; - for i=1, #availableLanguages do - if ( not defaultLanguages[availableLanguages[i]] ) then - canChangeLanguages = true; - break; - end - end - - if ( canChangeLanguages ) then - self.SearchBox:SetWidth(228); - self.FilterButton:Show(); - else - self.SearchBox:SetWidth(319); - self.FilterButton:Hide(); - end - - self.FilterButton:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_LFG_FRAME_SEARCH_FILTER"); - - LFGListSearchPanel_SetupLanguageFilter(dropdown, rootDescription); - end); -end - -function LFGListSearchPanel_Clear(self) - C_LFGList.ClearSearchResults(); - C_LFGList.ClearSearchTextFields(); - self.selectedResult = nil; - LFGListSearchPanel_UpdateResultList(self); -end - -function LFGListSearchPanel_EvaluateTutorial(self, mouseOverButton) - local helpTipInfo = { - text = CROSS_FACTION_GROUP_FINDER_HELPTIP, - buttonStyle = HelpTip.ButtonStyle.Close, - cvarBitfield = "closedInfoFrames", - bitfieldFlag = LE_FRAME_TUTORIAL_CROSS_FACTION_GROUP_FINDER, - targetPoint = HelpTip.Point.RightEdgeCenter, - offsetX = 10, - checkCVars = true, - }; - HelpTip:Show(self, helpTipInfo, mouseOverButton); -end - -function LFGListSearchPanel_SetCategory(self, categoryID, filters, preferredFilters) - self.categoryID = categoryID; - self.filters = filters; - self.preferredFilters = preferredFilters or 0; - - local categoryInfo = C_LFGList.GetLfgCategoryInfo(categoryID); - self.SearchBox.Instructions:SetText(categoryInfo.searchPromptOverride or FILTER); - local name = LFGListUtil_GetDecoratedCategoryName(categoryInfo.name, filters, false); - self.CategoryName:SetText(name); -end - -function LFGListSearchPanel_DoSearch(self) - local searchText = self.SearchBox:GetText(); - local languages = C_LFGList.GetLanguageSearchFilter(); - - local filters = ResolveCategoryFilters(self.categoryID, self.filters); - C_LFGList.Search(self.categoryID, filters, self.preferredFilters, languages); - self.searching = true; - self.searchFailed = false; - self.selectedResult = nil; - LFGListSearchPanel_UpdateResultList(self); - - -- If auto-create is desired, then the caller needs to set up that data after the search begins. - -- There's an issue with using OnTextChanged to handle this due to how OnShow processes the update. - if self.previousSearchText ~= searchText then - LFGListEntryCreation_ClearAutoCreateMode(self:GetParent().EntryCreation); - end - - self.previousSearchText = searchText; -end - -function LFGListSearchPanel_CreateGroupInstead(self) - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - local panel = LFGListFrame.SearchPanel; - LFGListEntryCreation_Show(panel:GetParent().EntryCreation, panel.preferredFilters, panel.categoryID, panel.filters); -end - -function LFGListSearchPanel_UpdateResultList(self) - self.totalResults, self.results = C_LFGList.GetFilteredSearchResults(); - self.applications = C_LFGList.GetApplications(); - LFGListUtil_SortSearchResults(self.results); - LFGListSearchPanel_UpdateResults(self); -end - -function LFGListSearchPanel_ValidateSelected(self) - if ( self.selectedResult and not LFGListSearchPanelUtil_CanSelectResult(self.selectedResult)) then - self.selectedResult = nil; - end -end - -function LFGListSearchPanelUtil_CanSelectResult(resultID) - local _, appStatus, pendingStatus, appDuration = C_LFGList.GetApplicationInfo(resultID); - local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID); - if ( appStatus ~= "none" or pendingStatus or searchResultInfo.isDelisted ) then - return false; - end - return true; -end - -function LFGListSearchPanel_InitButton(button, elementData) - button.resultID = elementData.resultID; - LFGListSearchEntry_Update(button); -end - -function LFGListSearchPanel_UpdateResults(self) - --If we have an application selected, deselect it. - LFGListSearchPanel_ValidateSelected(self); - - if ( self.searching ) then - self.SearchingSpinner:Show(); - self.ScrollBox.NoResultsFound:Hide(); - self.ScrollBox.StartGroupButton:Hide(); - self.ScrollBox:RemoveDataProvider(); - else - self.SearchingSpinner:Hide(); - - local dataProvider = CreateDataProvider(); - local results = self.results; - for index = 1, #results do - dataProvider:Insert({resultID=results[index]}); - end - - local apps = self.applications; - local resultSet = tInvert(self.results); - for i, app in ipairs(apps) do - if not resultSet[app] then - dataProvider:Insert({resultID=app}); - end - end - - if(self.totalResults == 0) then - self.ScrollBox.NoResultsFound:Show(); - self.ScrollBox.StartGroupButton:SetShown(not self.searchFailed); - self.ScrollBox.StartGroupButton:ClearAllPoints(); - self.ScrollBox.StartGroupButton:SetPoint("BOTTOM", self.ScrollBox.NoResultsFound, "BOTTOM", 0, - 27); - self.ScrollBox.NoResultsFound:SetText(self.searchFailed and LFG_LIST_SEARCH_FAILED or LFG_LIST_NO_RESULTS_FOUND); - else - self.ScrollBox.NoResultsFound:Hide(); - self.ScrollBox.StartGroupButton:SetShown(false); - - if(self.shouldAlwaysShowCreateGroupButton) then - dataProvider:Insert({startGroup=true}); - end - end - - self.ScrollBox:SetDataProvider(dataProvider, ScrollBoxConstants.RetainScrollPosition); - - --Reanchor the errors to not overlap applications - if not self.ScrollBox:HasScrollableExtent() then - local extent = self.ScrollBox:GetExtent(); - self.ScrollBox.NoResultsFound:SetPoint("TOP", self.ScrollBox, "TOP", 0, -extent - 27); - end - end - LFGListSearchPanel_UpdateButtonStatus(self); -end - -function LFGListSearchPanel_SelectResult(self, resultID) - self.selectedResult = resultID; - LFGListSearchPanel_UpdateResults(self); -end - -function LFGListSearchPanel_UpdateButtonStatus(self) - --Update the SignUpButton - local resultID = self.selectedResult; - local numApplications, numActiveApplications = C_LFGList.GetNumApplications(); - local messageApply = LFGListUtil_GetActiveQueueMessage(true); - local availTank, availHealer, availDPS = C_LFGList.GetAvailableRoles(); - if ( messageApply ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = messageApply; - elseif ( not LFGListUtil_IsAppEmpowered() ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = LFG_LIST_APP_UNEMPOWERED; - elseif ( IsInGroup(LE_PARTY_CATEGORY_HOME) and C_LFGList.IsCurrentlyApplying() ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = LFG_LIST_APP_CURRENTLY_APPLYING; - elseif ( numActiveApplications >= MAX_LFG_LIST_APPLICATIONS ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = string.format(LFG_LIST_HIT_MAX_APPLICATIONS, MAX_LFG_LIST_APPLICATIONS); - elseif ( GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) > MAX_PARTY_MEMBERS + 1 ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = LFG_LIST_MAX_MEMBERS; - elseif ( not (availTank or availHealer or availDPS) ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = LFG_LIST_MUST_CHOOSE_SPEC; - elseif ( GroupHasOfflineMember(LE_PARTY_CATEGORY_HOME) ) then - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = LFG_LIST_OFFLINE_MEMBER; - elseif ( resultID ) then - self.SignUpButton:Enable(); - self.SignUpButton.tooltip = nil; - else - self.SignUpButton:Disable(); - self.SignUpButton.tooltip = LFG_LIST_SELECT_A_SEARCH_RESULT; - end - - local isPartyLeader = UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME); - local canBrowseWhileQueued = C_LFGList.HasActiveEntryInfo() and isPartyLeader; - --Update the StartGroupButton - if ( IsInGroup(LE_PARTY_CATEGORY_HOME) and not isPartyLeader ) then - self.ScrollBox.StartGroupButton:Disable(); - self.ScrollBox.StartGroupButton.tooltip = LFG_LIST_NOT_LEADER; - else - local messageStart = LFGListUtil_GetActiveQueueMessage(false); - local startError, errorText = GetStartGroupRestriction(); - if ( messageStart ) then - self.ScrollBox.StartGroupButton:Disable(); - self.ScrollBox.StartGroupButton.tooltip = messageStart; - elseif ( startError ~= nil ) then - self.ScrollBox.StartGroupButton:Disable(); - self.ScrollBox.StartGroupButton.tooltip = errorText; - elseif (canBrowseWhileQueued) then - self.ScrollBox.StartGroupButton:Disable(); - self.ScrollBox.StartGroupButton.tooltip = CANNOT_DO_THIS_WHILE_LFGLIST_LISTED; - else - self.ScrollBox.StartGroupButton:Enable(); - self.ScrollBox.StartGroupButton.tooltip = nil; - end - end - - self.BackButton:SetShown(not canBrowseWhileQueued); - self.BackToGroupButton:SetShown(canBrowseWhileQueued) -end - -function LFGListSearchPanel_SignUp(self) - LFGListApplicationDialog_Show(LFGListApplicationDialog, self.selectedResult); -end - -function LFGListSearchPanelSearchBox_OnEnterPressed(self) - local parent = self:GetParent(); - if ( parent.AutoCompleteFrame:IsShown() and parent.AutoCompleteFrame.selected ) then - C_LFGList.SetSearchToActivity(parent.AutoCompleteFrame.selected); - end - - LFGListSearchPanel_DoSearch(self:GetParent()); - self:ClearFocus(); -end - -function LFGListSearchPanelSearchBox_OnTabPressed(self) - if ( IsShiftKeyDown() ) then - LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), -1); - else - LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), 1); - end -end - -function LFGListSearchPanelSearchBox_OnArrowPressed(self, key) - if ( key == "UP" ) then - LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), -1); - elseif ( key == "DOWN" ) then - LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), 1); - end -end - -function LFGListSearchPanelSearchBox_OnTextChanged(self) - SearchBoxTemplate_OnTextChanged(self); - LFGListSearchPanel_UpdateAutoComplete(self:GetParent()); -end - -function LFGListSearchAutoCompleteButton_OnClick(self) - local panel = self:GetParent():GetParent(); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - C_LFGList.SetSearchToActivity(self.activityID); - LFGListSearchPanel_DoSearch(panel); - panel.SearchBox:ClearFocus(); -end - -function LFGListSearchPanel_AutoCompleteAdvance(self, offset) - local selected = self.AutoCompleteFrame.selected; - - --Find the index of the current selection and how many results we have displayed - local idx = nil; - local numDisplayed = 0; - for i=1, #self.AutoCompleteFrame.Results do - local btn = self.AutoCompleteFrame.Results[i]; - if ( btn:IsShown() and btn.activityID ) then - numDisplayed = i; - if ( btn.activityID == selected ) then - idx = i; - end - else - break; - end - end - - local newIndex = nil; - if ( not idx ) then - --We had nothing selected, advance from the front or back - if ( offset > 0 ) then - newIndex = offset; - else - newIndex = numDisplayed + 1 + offset; - end - else - --Advance from our old location - newIndex = ((idx - 1 + offset + numDisplayed) % numDisplayed) + 1; - end - - self.AutoCompleteFrame.selected = self.AutoCompleteFrame.Results[newIndex].activityID; - LFGListSearchPanel_UpdateAutoComplete(self); -end - -function LFGListSearchPanel_UpdateAutoComplete(self) - local text = self.SearchBox:GetText(); - if ( text == "" or not self.SearchBox:HasFocus() ) then - self.AutoCompleteFrame:Hide(); - self.AutoCompleteFrame.selected = nil; - return; - end - - --Choose the autocomplete results - local filters = ResolveCategoryFilters(self.categoryID, self.filters); - local matchingActivities = C_LFGList.GetAvailableActivities(self.categoryID, nil, filters, text); - LFGListUtil_SortActivitiesByRelevancy(matchingActivities); - - local numResults = math.min(#matchingActivities, MAX_LFG_LIST_SEARCH_AUTOCOMPLETE_ENTRIES); - - if ( numResults == 0 ) then - self.AutoCompleteFrame:Hide(); - self.AutoCompleteFrame.selected = nil; - return; - end - - --Update the buttons - local foundSelected = false; - for i=1, numResults do - local id = matchingActivities[i]; - - local button = self.AutoCompleteFrame.Results[i]; - if ( not button ) then - button = CreateFrame("BUTTON", nil, self.AutoCompleteFrame, "LFGListSearchAutoCompleteButtonTemplate"); - button:SetPoint("TOPLEFT", self.AutoCompleteFrame.Results[i-1], "BOTTOMLEFT", 0, 0); - button:SetPoint("TOPRIGHT", self.AutoCompleteFrame.Results[i-1], "BOTTOMRIGHT", 0, 0); - self.AutoCompleteFrame.Results[i] = button; - end - - if ( i == numResults and numResults < #matchingActivities ) then - --This is just a "x more" button - button:SetFormattedText(LFG_LIST_AND_MORE, #matchingActivities - numResults + 1); - button:Disable(); - button.Selected:Hide(); - button.activityID = nil; - else - --This is an actual activity - button:SetText( (C_LFGList.GetActivityFullName(id)) ); - button:Enable(); - button.activityID = id; - - if ( id == self.AutoCompleteFrame.selected ) then - button.Selected:Show(); - foundSelected = true; - else - button.Selected:Hide(); - end - end - button:Show(); - end - - if ( not foundSelected ) then - self.selected = nil; - end - - --Hide unused buttons - for i=numResults + 1, #self.AutoCompleteFrame.Results do - self.AutoCompleteFrame.Results[i]:Hide(); - end - - --Update the frames height and show it - self.AutoCompleteFrame:SetHeight(numResults * self.AutoCompleteFrame.Results[1]:GetHeight() + 8); - self.AutoCompleteFrame:Show(); -end - -function LFGListSearchEntry_OnLoad(self) - self:RegisterForClicks("LeftButtonUp", "RightButtonUp"); -end - -function LFGListSearchEntry_Update(self) - local resultID = self.resultID; - - if not C_LFGList.HasSearchResultInfo(resultID) then - return; - end - - local _, appStatus, pendingStatus, appDuration = C_LFGList.GetApplicationInfo(resultID); - - local isApplication = (appStatus ~= "none" or pendingStatus); - local isAppFinished = LFGListUtil_IsStatusInactive(appStatus) or LFGListUtil_IsStatusInactive(pendingStatus); - - --Update visibility based on whether we're an application or not - self.isApplication = isApplication; - self.ApplicationBG:SetShown(isApplication and not isAppFinished); - self.ResultBG:SetShown(not isApplication or isAppFinished); - self.DataDisplay:SetShown(not isApplication); - self.CancelButton:SetShown(isApplication and pendingStatus ~= "applied"); - self.CancelButton:SetEnabled(LFGListUtil_IsAppEmpowered()); - self.CancelButton.Icon:SetDesaturated(not LFGListUtil_IsAppEmpowered()); - self.CancelButton.tooltip = (not LFGListUtil_IsAppEmpowered()) and LFG_LIST_APP_UNEMPOWERED; - self.Spinner:SetShown(pendingStatus == "applied"); - - if ( pendingStatus == "applied" and C_LFGList.GetRoleCheckInfo() ) then - self.PendingLabel:SetText(LFG_LIST_ROLE_CHECK); - self.PendingLabel:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( pendingStatus == "cancelled" or appStatus == "cancelled" or appStatus == "failed" ) then - self.PendingLabel:SetText(LFG_LIST_APP_CANCELLED); - self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( appStatus == "declined" or appStatus == "declined_full" or appStatus == "declined_delisted" ) then - self.PendingLabel:SetText((appStatus == "declined_full") and LFG_LIST_APP_FULL or LFG_LIST_APP_DECLINED); - self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( appStatus == "timedout" ) then - self.PendingLabel:SetText(LFG_LIST_APP_TIMED_OUT); - self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( appStatus == "invited" ) then - self.PendingLabel:SetText(LFG_LIST_APP_INVITED); - self.PendingLabel:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( appStatus == "inviteaccepted" ) then - self.PendingLabel:SetText(LFG_LIST_APP_INVITE_ACCEPTED); - self.PendingLabel:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( appStatus == "invitedeclined" ) then - self.PendingLabel:SetText(LFG_LIST_APP_INVITE_DECLINED); - self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - elseif ( isApplication and pendingStatus ~= "applied" ) then - self.PendingLabel:SetText(LFG_LIST_PENDING); - self.PendingLabel:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); - self.PendingLabel:Show(); - self.ExpirationTime:Show(); - self.CancelButton:Show(); - else - self.PendingLabel:Hide(); - self.ExpirationTime:Hide(); - self.CancelButton:Hide(); - end - - --Center justify if we're on more than one line - if ( self.PendingLabel:GetHeight() > 15 ) then - self.PendingLabel:SetJustifyH("CENTER"); - else - self.PendingLabel:SetJustifyH("RIGHT"); - end - - --Change the anchor of the label depending on whether we have the expiration time - if ( self.ExpirationTime:IsShown() ) then - self.PendingLabel:SetPoint("RIGHT", self.ExpirationTime, "LEFT", -3, 0); - else - self.PendingLabel:SetPoint("RIGHT", self.ExpirationTime, "RIGHT", -3, 0); - end - - self.expiration = GetTime() + appDuration; - - local panel = self:GetParent():GetParent():GetParent(); - - local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID); - local activityName = C_LFGList.GetActivityFullName(searchResultInfo.activityIDs[1], nil, searchResultInfo.isWarMode); - - self.resultID = resultID; - local selected = panel.selectedResult == resultID and not isApplication and not searchResultInfo.isDelisted; - LFGListSearchEntry_SetSelected(self, selected); - - local nameColor = NORMAL_FONT_COLOR; - local activityColor = GRAY_FONT_COLOR; - if ( searchResultInfo.isDelisted or isAppFinished ) then - nameColor = LFG_LIST_DELISTED_FONT_COLOR; - activityColor = LFG_LIST_DELISTED_FONT_COLOR; - elseif ( searchResultInfo.numBNetFriends > 0 or searchResultInfo.numCharFriends > 0 or searchResultInfo.numGuildMates > 0 ) then - nameColor = BATTLENET_FONT_COLOR; - end - self.Name:SetWidth(0); - self.Name:SetText(searchResultInfo.name); - self.Name:SetTextColor(nameColor.r, nameColor.g, nameColor.b); - self.ActivityName:SetText(activityName); - self.ActivityName:SetTextColor(activityColor.r, activityColor.g, activityColor.b); - self.VoiceChat:SetShown(searchResultInfo.voiceChat ~= ""); - self.VoiceChat.tooltip = searchResultInfo.voiceChat; - - local displayData = C_LFGList.GetSearchResultMemberCounts(resultID); - LFGListGroupDataDisplay_Update(self.DataDisplay, searchResultInfo.activityIDs[1], displayData, searchResultInfo.isDelisted); - - local nameWidth = isApplication and 165 or 176; - if ( searchResultInfo.voiceChat ~= "" ) then - nameWidth = nameWidth - 22; - end - if ( self.Name:GetWidth() > nameWidth ) then - self.Name:SetWidth(nameWidth); - end - self.ActivityName:SetWidth(176); - - local mouseFoci = GetMouseFoci(); - for _, mouseFocus in ipairs(mouseFoci) do - if ( mouseFocus == self ) then - LFGListSearchEntry_OnEnter(self); - break - end - if ( mouseFocus == self.VoiceChat ) then - mouseFocus:GetScript("OnEnter")(mouseFocus); - break; - end - end - - if ( isApplication ) then - self:SetScript("OnUpdate", LFGListSearchEntry_UpdateExpiration); - LFGListSearchEntry_UpdateExpiration(self); - else - self:SetScript("OnUpdate", nil); - end -end - -function LFGListSearchEntry_SetSelected(self, selected) - self.Selected:SetShown(selected); -end - -function LFGListSearchEntry_UpdateExpiration(self) - local duration = 0; - local now = GetTime(); - if ( self.expiration and self.expiration > now ) then - duration = self.expiration - now; - end - - local minutes = math.floor(duration / 60); - local seconds = duration % 60; - self.ExpirationTime:SetFormattedText("%d:%.2d", minutes, seconds); -end - -function LFGListSearchEntry_CreateContextMenu(self) - MenuUtil.CreateContextMenu(self, function(owner, rootDescription) - rootDescription:SetTag("MENU_LFG_FRAME_SEARCH_ENTRY"); - - local searchResultInfo = C_LFGList.GetSearchResultInfo(self.resultID); - local _, appStatus = C_LFGList.GetApplicationInfo(self.resultID); - rootDescription:CreateTitle(searchResultInfo.name); - - local whisperButton = rootDescription:CreateButton(WHISPER_LEADER, function() - ChatFrame_SendTell(searchResultInfo.leaderName); - end); - - if not searchResultInfo.leaderName then - whisperButton:SetEnabled(false); - - local applied = (appStatus == "applied" or appStatus == "invited"); - if not applied then - whisperButton:SetTooltip(function(tooltip, description) - GameTooltip_SetTitle(tooltip, WHISPER); - GameTooltip_AddNormalLine(tooltip, LFG_LIST_MUST_SIGN_UP_TO_WHISPER); - end); - end - end - - rootDescription:CreateButton(LFG_LIST_REPORT_GROUP_FOR, function() - LFGList_ReportListing(self.resultID, searchResultInfo.leaderName); - end); - - rootDescription:CreateButton(REPORT_GROUP_FINDER_ADVERTISEMENT, function() - LFGList_ReportAdvertisement(self.resultID); - end); - end); -end - -function LFGListSearchEntry_OnClick(self, button) - local panel = LFGListFrame.SearchPanel; - if ( button == "RightButton" ) then - LFGListSearchEntry_CreateContextMenu(self); - elseif ( panel.selectedResult ~= self.resultID and LFGListSearchPanelUtil_CanSelectResult(self.resultID) ) then - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - LFGListSearchPanel_SelectResult(panel, self.resultID); - end -end - -function LFGListSearchEntry_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT", 25, 0); - local resultID = self.resultID; - LFGListUtil_SetSearchEntryTooltip(GameTooltip, resultID); - - local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID); - if(searchResultInfo.crossFactionListing) then - LFGListSearchPanel_EvaluateTutorial(LFGListFrame.SearchPanel, self); - end - - if not self.Selected:IsShown() then - self.Highlight:Show(); - end -end - -function LFGListSearchEntry_OnLeave(self) - GameTooltip_Hide(); - - self.Highlight:Hide(); -end - -function LFGListSearchEntryUtil_GetFriendList(resultID) - local list = ""; - local bNetFriends, charFriends, guildMates = C_LFGList.GetSearchResultFriends(resultID); - local displayedFirst = false; - - --BNet friends - for i=1, #bNetFriends do - if ( displayedFirst ) then - list = list..PLAYER_LIST_DELIMITER; - else - displayedFirst = true; - end - list = list..FRIENDS_BNET_NAME_COLOR_CODE..bNetFriends[i]..FONT_COLOR_CODE_CLOSE; - end - - --Character friends - for i=1, #charFriends do - if ( displayedFirst ) then - list = list..PLAYER_LIST_DELIMITER; - else - displayedFirst = true; - end - list = list..FRIENDS_WOW_NAME_COLOR_CODE..charFriends[i]..FONT_COLOR_CODE_CLOSE; - end - - --Guild mates - for i=1, #guildMates do - if ( displayedFirst ) then - list = list..PLAYER_LIST_DELIMITER; - else - displayedFirst = true; - end - list = list..RGBTableToColorCode(ChatTypeInfo.GUILD)..guildMates[i]..FONT_COLOR_CODE_CLOSE; - end - return list; -end - -------------------------------------------------------- -----------Application dialog functions -------------------------------------------------------- -function LFGListApplicationDialog_OnLoad(self) - self:RegisterEvent("LFG_ROLE_UPDATE"); - self.Description.EditBox:SetScript("OnEnterPressed", nop); - self.hideOnEscape = true; -end - -function LFGListApplicationDialog_OnEvent(self, event) - if ( event == "LFG_ROLE_UPDATE" ) then - LFGListApplicationDialog_UpdateRoles(self); - end -end - -function LFGListApplicationDialog_Show(self, resultID) - if resultID then - local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID); - if ( searchResultInfo.activityIDs[1] ~= self.activityID ) then - C_LFGList.ClearApplicationTextFields(); - end - - self.resultID = resultID; - self.activityID = searchResultInfo.activityIDs[1]; - end - LFGListApplicationDialog_UpdateRoles(self); - StaticPopupSpecial_Show(self); -end - -function LFGListApplicationDialog_UpdateRoles(self) - local availTank, availHealer, availDPS = C_LFGList.GetAvailableRoles(); - - local avail1, avail2, avail3; - if ( availTank ) then - avail1 = self.TankButton; - end - if ( availHealer ) then - if ( avail1 ) then - avail2 = self.HealerButton; - else - avail1 = self.HealerButton; - end - end - if ( availDPS ) then - if ( avail2 ) then - avail3 = self.DamagerButton; - elseif ( avail1 ) then - avail2 = self.DamagerButton; - else - avail1 = self.DamagerButton; - end - end - - self.TankButton:SetShown(availTank); - self.HealerButton:SetShown(availHealer); - self.DamagerButton:SetShown(availDPS); - - if ( avail3 ) then - avail1:ClearAllPoints(); - avail1:SetPoint("TOPRIGHT", self, "TOP", -53, -35); - avail2:ClearAllPoints(); - avail2:SetPoint("TOP", self, "TOP", 0, -35); - avail3:ClearAllPoints(); - avail3:SetPoint("TOPLEFT", self, "TOP", 53, -35); - elseif ( avail2 ) then - avail1:ClearAllPoints(); - avail1:SetPoint("TOPRIGHT", self, "TOP", -5, -35); - avail2:ClearAllPoints(); - avail2:SetPoint("TOPLEFT", self, "TOP", 5, -35); - elseif ( avail1 ) then - avail1:ClearAllPoints(); - avail1:SetPoint("TOP", self, "TOP", 0, -35); - end - - local _, tank, healer, dps = GetLFGRoles(); - self.TankButton.CheckButton:SetChecked(tank); - self.HealerButton.CheckButton:SetChecked(healer); - self.DamagerButton.CheckButton:SetChecked(dps); - - LFGListApplicationDialog_UpdateValidState(self); -end - -function LFGListApplicationDialog_UpdateValidState(self) - if ( ( self.TankButton:IsShown() and self.TankButton.CheckButton:GetChecked()) - or ( self.HealerButton:IsShown() and self.HealerButton.CheckButton:GetChecked()) - or ( self.DamagerButton:IsShown() and self.DamagerButton.CheckButton:GetChecked()) ) then - self.SignUpButton:Enable(); - self.SignUpButton.errorText = nil; - else - self.SignUpButton:Disable(); - self.SignUpButton.errorText = LFG_LIST_MUST_SELECT_ROLE; - end -end - -function LFGListApplicationDialogSignUpButton_OnClick(button) - local dialog = button:GetParent(); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - C_LFGList.ApplyToGroup(dialog.resultID, dialog.TankButton:IsShown() and dialog.TankButton.CheckButton:GetChecked(), dialog.HealerButton:IsShown() and dialog.HealerButton.CheckButton:GetChecked(), dialog.DamagerButton:IsShown() and dialog.DamagerButton.CheckButton:GetChecked()); - StaticPopupSpecial_Hide(dialog); -end - -function LFGListRoleButtonCheckButton_OnClick(self) - if ( self:GetChecked() ) then - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - else - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF); - end - - local dialog = self:GetParent():GetParent(); - local leader, tank, healer, dps = GetLFGRoles(); - if dialog.exclusive then - local setDPS = false; - local setTank = false; - local setHealer = false; - if self:GetParent().roleID == 1 then - setDPS = true; - elseif self:GetParent().roleID == 2 then - setTank = true; - elseif self:GetParent().roleID == 3 then - setHealer = true; - end - - SetLFGRoles(leader, setTank, setHealer, setDPS); - LFGListApplicationDialog_UpdateRoles(dialog); - else - SetLFGRoles(leader, dialog.TankButton.CheckButton:GetChecked(), dialog.HealerButton.CheckButton:GetChecked(), dialog.DamagerButton.CheckButton:GetChecked()); - end -end - -------------------------------------------------------- -----------Invite dialog functions -------------------------------------------------------- -function LFGListInviteDialog_OnLoad(self) - self:RegisterEvent("LFG_LIST_SEARCH_RESULTS_RECEIVED"); - self:RegisterEvent("LFG_LIST_SEARCH_RESULT_UPDATED"); - self:RegisterEvent("LFG_LIST_JOINED_GROUP"); - self:RegisterEvent("PARTY_LEADER_CHANGED"); - self:RegisterEvent("UNIT_CONNECTION"); -end - -function LFGListInviteDialog_OnEvent(self, event, ...) - if ( event == "LFG_LIST_SEARCH_RESULTS_RECEIVED" ) then - LFGListInviteDialog_CheckPending(self); - elseif ( event == "LFG_LIST_SEARCH_RESULT_UPDATED" ) then - local id = ...; - local _, status, pendingStatus = C_LFGList.GetApplicationInfo(id); - - local empowered = LFGListUtil_IsAppEmpowered(); - if ( self.resultID == id and not self.informational and (status ~= "invited" or not empowered) ) then - --Check if we need to hide the panel - StaticPopupSpecial_Hide(self); - LFGListInviteDialog_CheckPending(self); - elseif ( status == "invited" and not pendingStatus ) then - --Check if we need to show this result - LFGListInviteDialog_CheckPending(self); - end - elseif ( event == "PARTY_LEADER_CHANGED" ) then - --Check if we need to hide the current panel - if ( not LFGListUtil_IsAppEmpowered() and self:IsShown() and not self.informational ) then - StaticPopupSpecial_Hide(self); - end - - --Check if we need to show any panels - LFGListInviteDialog_CheckPending(self); - elseif ( event == "LFG_LIST_JOINED_GROUP" ) then - if ( not LFGListUtil_IsAppEmpowered() ) then - --Show the informational dialog, regardless of whether we already had something up - local id, kstringGroupName = ...; - StaticPopupSpecial_Hide(self); - LFGListInviteDialog_Show(self, id, kstringGroupName); - end - elseif ( event == "UNIT_CONNECTION" ) then - LFGListInviteDialog_UpdateOfflineNotice(self); - end -end - -function LFGListInviteDialog_CheckPending(self) - --If we're already showing one, don't replace it - if ( self:IsShown() ) then - return; - end - - --If we're not empowered to make changes to applications, don't pop up anything. - if ( not LFGListUtil_IsAppEmpowered() ) then - return; - end - - local apps = C_LFGList.GetApplications(); - for i=1, #apps do - local id, status, pendingStatus = C_LFGList.GetApplicationInfo(apps[i]); - if ( status == "invited" and not pendingStatus ) then - LFGListInviteDialog_Show(self, apps[i]); - return; - end - end -end - -function LFGListInviteDialog_Show(self, resultID, kstringGroupName) - local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID); - local activityName = C_LFGList.GetActivityFullName(searchResultInfo.activityIDs[1], nil, searchResultInfo.isWarMode); - local _, status, _, _, role = C_LFGList.GetApplicationInfo(resultID); - - local informational = (status ~= "invited"); - assert(not informational or status == "inviteaccepted"); - - self.resultID = resultID; - self.GroupName:SetText(kstringGroupName or searchResultInfo.name); - self.ActivityName:SetText(activityName); - self.Role:SetText(_G[role]); - local showDisabled = false; - self.RoleIcon:SetAtlas(GetIconForRole(role, showDisabled), TextureKitConstants.IgnoreAtlasSize); - self.Label:SetText(informational and LFG_LIST_JOINED_GROUP_NOTICE or LFG_LIST_INVITED_TO_GROUP); - - self.informational = informational; - self.AcceptButton:SetShown(not informational); - self.DeclineButton:SetShown(not informational); - self.AcknowledgeButton:SetShown(informational); - - if ( not informational and GroupHasOfflineMember(LE_PARTY_CATEGORY_HOME) ) then - self:SetHeight(250); - self.OfflineNotice:Show(); - LFGListInviteDialog_UpdateOfflineNotice(self); - else - self:SetHeight(210); - self.OfflineNotice:Hide(); - end - - StaticPopupSpecial_Show(self); - - PlaySound(SOUNDKIT.READY_CHECK); - FlashClientIcon(); -end - -function LFGListInviteDialog_UpdateOfflineNotice(self) - if ( GroupHasOfflineMember(LE_PARTY_CATEGORY_HOME) ) then - self.OfflineNotice:SetText(LFG_LIST_OFFLINE_MEMBER_NOTICE); - self.OfflineNotice:SetFontObject(GameFontRed); - else - self.OfflineNotice:SetText(LFG_LIST_OFFLINE_MEMBER_NOTICE_GONE); - self.OfflineNotice:SetFontObject(GameFontGreen); - end -end - -function LFGListInviteDialog_Accept(self) - C_LFGList.AcceptInvite(self.resultID); - StaticPopupSpecial_Hide(self); - LFGListInviteDialog_CheckPending(self); -end - -function LFGListInviteDialog_Decline(self) - C_LFGList.DeclineInvite(self.resultID); - StaticPopupSpecial_Hide(self); - LFGListInviteDialog_CheckPending(self); -end - -function LFGListInviteDialog_Acknowledge(self) - StaticPopupSpecial_Hide(self); - LFGListInviteDialog_CheckPending(self); -end - -------------------------------------------------------- -----------Group Data Display functions -------------------------------------------------------- -function LFGListGroupDataDisplay_Update(self, activityID, displayData, disabled) - local activityInfo = C_LFGList.GetActivityInfoTable(activityID); - if(not activityInfo) then - return; - end - if ( activityInfo.displayType == Enum.LFGListDisplayType.RoleCount ) then - self.RoleCount:Show(); - self.Enumerate:Hide(); - self.PlayerCount:Hide(); - LFGListGroupDataDisplayRoleCount_Update(self.RoleCount, displayData, disabled); - elseif ( activityInfo.displayType == Enum.LFGListDisplayType.RoleEnumerate ) then - self.RoleCount:Hide(); - self.Enumerate:Show(); - self.PlayerCount:Hide(); - LFGListGroupDataDisplayEnumerate_Update(self.Enumerate, activityInfo.maxNumPlayers, displayData, disabled, LFG_LIST_GROUP_DATA_ROLE_ORDER); - elseif ( activityInfo.displayType == Enum.LFGListDisplayType.ClassEnumerate ) then - self.RoleCount:Hide(); - self.Enumerate:Show(); - self.PlayerCount:Hide(); - LFGListGroupDataDisplayEnumerate_Update(self.Enumerate, activityInfo.maxNumPlayers, displayData, disabled, LFG_LIST_GROUP_DATA_CLASS_ORDER); - elseif ( activityInfo.displayType == Enum.LFGListDisplayType.PlayerCount ) then - self.RoleCount:Hide(); - self.Enumerate:Hide(); - self.PlayerCount:Show(); - LFGListGroupDataDisplayPlayerCount_Update(self.PlayerCount, displayData, disabled); - elseif ( activityInfo.displayType == Enum.LFGListDisplayType.HideAll ) then - self.RoleCount:Hide(); - self.Enumerate:Hide(); - self.PlayerCount:Hide(); - else - GMError("Unknown display type"); - self.RoleCount:Hide(); - self.Enumerate:Hide(); - self.PlayerCount:Hide(); - end -end - -function LFGListGroupDataDisplayRoleCount_Update(self, displayData, disabled) - self.TankCount:SetText(displayData.TANK); - self.HealerCount:SetText(displayData.HEALER); - self.DamagerCount:SetText(displayData.DAMAGER); - - --Update for the disabled state - local r = disabled and LFG_LIST_DELISTED_FONT_COLOR.r or HIGHLIGHT_FONT_COLOR.r; - local g = disabled and LFG_LIST_DELISTED_FONT_COLOR.g or HIGHLIGHT_FONT_COLOR.g; - local b = disabled and LFG_LIST_DELISTED_FONT_COLOR.b or HIGHLIGHT_FONT_COLOR.b; - self.TankCount:SetTextColor(r, g, b); - self.HealerCount:SetTextColor(r, g, b); - self.DamagerCount:SetTextColor(r, g, b); - self.TankIcon:SetDesaturated(disabled); - self.HealerIcon:SetDesaturated(disabled); - self.DamagerIcon:SetDesaturated(disabled); - self.TankIcon:SetAlpha(disabled and 0.5 or 0.70); - self.HealerIcon:SetAlpha(disabled and 0.5 or 0.70); - self.DamagerIcon:SetAlpha(disabled and 0.5 or 0.70); -end - -function LFGListGroupDataDisplayEnumerate_Update(self, numPlayers, displayData, disabled, iconOrder) - --Show/hide the required icons - for i=1, #self.Icons do - if ( i > numPlayers ) then - self.Icons[i]:Hide(); - else - self.Icons[i]:Show(); - self.Icons[i]:SetDesaturated(disabled); - self.Icons[i]:SetAlpha(disabled and 0.5 or 1.0); - end - end - - --Note that icons are numbered from right to left - local iconIndex = numPlayers; - for i=1, #iconOrder do - for j=1, displayData[iconOrder[i]] do - self.Icons[iconIndex]:SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[iconOrder[i]], false); - iconIndex = iconIndex - 1; - if ( iconIndex < 1 ) then - return; - end - end - end - - for i=1, iconIndex do - self.Icons[i]:SetAtlas("groupfinder-icon-emptyslot", false); - end -end - -function LFGListGroupDataDisplayPlayerCount_Update(self, displayData, disabled) - local numPlayers = displayData.TANK + displayData.HEALER + displayData.DAMAGER + displayData.NOROLE; - - local color = disabled and LFG_LIST_DELISTED_FONT_COLOR or HIGHLIGHT_FONT_COLOR; - self.Count:SetText(numPlayers); - self.Count:SetTextColor(color.r, color.g, color.b); - self.Icon:SetDesaturated(disabled); - self.Icon:SetAlpha(disabled and 0.5 or 1); -end - -------------------------------------------------------- -----------Requirement functions -------------------------------------------------------- -function LFGListRequirement_Validate(self, text) - if ( self.validateFunc ) then - self.warningText = self:validateFunc(text); - self.WarningFrame:SetShown(self.warningText); - self.CheckButton:SetShown(not self.warningText); - end - LFGListEntryCreation_UpdateValidState(self:GetParent()); -end - -------------------------------------------------------- -----------Utility functions -------------------------------------------------------- -function LFGListUtil_AugmentWithBest(filters, categoryID, groupID, activityID) - local myNumMembers = math.max(GetNumGroupMembers(LE_PARTY_CATEGORY_HOME), 1); - local myItemLevel = GetAverageItemLevel(); - if ( not activityID ) then - --Find the best activity by iLevel and recommended flag - local activities = C_LFGList.GetAvailableActivities(categoryID, groupID, filters); - local bestItemLevel, bestRecommended, bestCurrentArea, bestMinLevel, bestMaxPlayers; - for i=1, #activities do - local activityInfo = C_LFGList.GetActivityInfoTable(activities[i]); - local iLevel = activityInfo and activityInfo.ilvlSuggestion or 0; - local isRecommended = bit.band(filters, Enum.LFGListFilter.Recommended) ~= 0; - local currentArea = C_LFGList.GetActivityInfoExpensive(activities[i]); - - local usedItemLevel = myItemLevel; - local isBetter = false; - if ( not activityID ) then - isBetter = true; - elseif ( currentArea ~= bestCurrentArea ) then - isBetter = currentArea; - elseif ( bestRecommended ~= isRecommended ) then - isBetter = isRecommended; - elseif ( bestMinLevel ~= activityInfo.minLevel ) then - isBetter = activityInfo.minLevel > bestMinLevel; - elseif ( iLevel ~= bestItemLevel ) then - isBetter = (iLevel > bestItemLevel and iLevel <= usedItemLevel) or - (iLevel <= usedItemLevel and bestItemLevel > usedItemLevel) or - (iLevel < bestItemLevel and iLevel > usedItemLevel); - elseif ( (myNumMembers < activityInfo.maxNumPlayers) ~= (myNumMembers < bestMaxPlayers) ) then - isBetter = myNumMembers < activityInfo.maxNumPlayers; - end - - if ( isBetter ) then - activityID = activities[i]; - bestItemLevel = iLevel; - bestRecommended = isRecommended; - bestCurrentArea = currentArea; - bestMinLevel = activityInfo.minLevel; - bestMaxPlayers = activityInfo.maxNumPlayers; - end - end - end - - assert(activityID); - - --Update the categoryID and groupID with what we get from the activity - local currentActivityInfo = C_LFGList.GetActivityInfoTable(activityID); - if(not currentActivityInfo) then - return; - end - - --Update the filters if needed - local categoryInfo = C_LFGList.GetLfgCategoryInfo(currentActivityInfo.categoryID); - - -- This function may need to return the recommended or not-recommended state to determine the - -- difficulties options. After a difficulty is selected, a 'nil' filter is passed to - -- LFGListEntryCreation_Select, requiring us to fetch the filter from the activity info. - -- If separateRecommended is not set, then this state is meaningless and we just return 0. - local recFilter = 0; - if ( categoryInfo and categoryInfo.separateRecommended ) then - recFilter = bit.band(filters, bit.bor(Enum.LFGListFilter.Recommended, Enum.LFGListFilter.NotRecommended)); - - if recFilter == 0 then - recFilter = currentActivityInfo.filters; - end - end - - return recFilter, currentActivityInfo.categoryID, currentActivityInfo.groupFinderActivityGroupID, activityID; -end - -function LFGListUtil_ValidateLevelReq(self, text) - local myItemLevel = GetAverageItemLevel(); - if ( text ~= "" and tonumber(text) > myItemLevel) then - return LFG_LIST_ILVL_ABOVE_YOURS .. "\n" .. format(LFG_LIST_ITEM_LEVEL_CURRENT, myItemLevel); - end -end - -function LFGListUtil_ValidatePvPLevelReq(self, text) - local _, _, avgItemLevelPvP = GetAverageItemLevel(); - if ( text ~= "" and tonumber(text) > avgItemLevelPvP) then - return LFG_LIST_PVP_ILVL_ABOVE_YOURS; - end -end - -function LFGListUtil_ValidatePvpRatingReq(self, text) - local selectedActivity = self:GetParent().selectedActivity; - if(text ~= "" and selectedActivity and not C_LFGList.ValidateRequiredPvpRatingForActivity(selectedActivity, tonumber(text))) then - return LFG_LIST_PVP_RATING_ABOVE_YOURS; - end -end - -function LFGListUtil_ValidateMythicPlusRatingReq(self, text) - if(text ~= "" and not C_LFGList.ValidateRequiredDungeonScore(tonumber(text))) then - return LFG_LIST_DUNGEON_SCORE_ABOVE_YOURS; - end -end - -function LFGListUtil_ValidateHonorLevelReq(self, text) - local myHonorLevel = UnitHonorLevel("player"); - if (text ~= "" and tonumber(text) > myHonorLevel) then - return LFG_LIST_HONOR_LEVEL_ABOVE_YOURS; - end -end - --- TODO: Fix for Level Squish -function LFGListUtil_GetCurrentExpansion() - return GetExpansionForLevel(UnitLevel("player")) or LE_EXPANSION_LEVEL_CURRENT; -end - -function LFGListUtil_GetDecoratedCategoryName(categoryName, filter, useColors) - if ( filter == 0 ) then - return categoryName; - end - - local colorStart = ""; - local colorEnd = ""; - if ( useColors ) then - colorStart = "|cffffffff"; - colorEnd = "|r"; - end - - local extraName = ""; - if ( filter == Enum.LFGListFilter.NotRecommended ) then - extraName = LFG_LIST_LEGACY; - elseif ( filter == Enum.LFGListFilter.Recommended ) then - local exp = LFGListUtil_GetCurrentExpansion(); - extraName = _G["EXPANSION_NAME"..exp]; - end - - if(extraName ~= "") then - return string.format(LFG_LIST_CATEGORY_FORMAT, categoryName, colorStart, extraName, colorEnd); - else - return categoryName; - end -end - -local roleRemainingKeyLookup = { - ["TANK"] = "TANK_REMAINING", - ["HEALER"] = "HEALER_REMAINING", - ["DAMAGER"] = "DAMAGER_REMAINING", -}; - -local function HasRemainingSlotsForLocalPlayerRole(lfgSearchResultID) - return false; -end - -function LFGListUtil_SortSearchResultsCB(searchResultID1, searchResultID2) - local searchResultInfo1 = C_LFGList.GetSearchResultInfo(searchResultID1); - local searchResultInfo2 = C_LFGList.GetSearchResultInfo(searchResultID2); - - local hasRemainingRole1 = HasRemainingSlotsForLocalPlayerRole(searchResultID1); - local hasRemainingRole2 = HasRemainingSlotsForLocalPlayerRole(searchResultID2); - - -- Groups with your current role available are preferred - if (hasRemainingRole1 ~= hasRemainingRole2) then - return hasRemainingRole1; - end - - --If one has more friends, do that one first - if ( searchResultInfo1.numBNetFriends ~= searchResultInfo2.numBNetFriends ) then - return searchResultInfo1.numBNetFriends > searchResultInfo2.numBNetFriends; - end - - if ( searchResultInfo1.numCharFriends ~= searchResultInfo2.numCharFriends ) then - return searchResultInfo1.numCharFriends > searchResultInfo2.numCharFriends; - end - - if ( searchResultInfo1.numGuildMates ~= searchResultInfo2.numGuildMates ) then - return searchResultInfo1.numGuildMates > searchResultInfo2.numGuildMates; - end - - if ( searchResultInfo1.isWarMode ~= searchResultInfo2.isWarMode ) then - return searchResultInfo1.isWarMode == C_PvP.IsWarModeDesired(); - end - - --If we aren't sorting by anything else, just go by ID - return searchResultID1 < searchResultID2; -end - -function LFGListUtil_SortSearchResults(results) - table.sort(results, LFGListUtil_SortSearchResultsCB); -end - -function LFGListUtil_SortApplicantsCB(applicantID1, applicantID2) - local applicantInfo1 = C_LFGList.GetApplicantInfo(applicantID1); - local applicantInfo2 = C_LFGList.GetApplicantInfo(applicantID2); - - --New items go to the bottom - if ( applicantInfo1.isNew ~= applicantInfo2.isNew ) then - return applicantInfo2.isNew; - end - - return applicantInfo1.displayOrderID < applicantInfo2.displayOrderID; -end - -function LFGListUtil_SortApplicants(applicants) - table.sort(applicants, LFGListUtil_SortApplicantsCB); -end - -function LFGListUtil_IsAppEmpowered() - return not IsInGroup(LE_PARTY_CATEGORY_HOME) or UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME); -end - -function LFGListUtil_IsEntryEmpowered() - return UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) or UnitIsGroupAssistant("player", LE_PARTY_CATEGORY_HOME); -end - -function LFGListUtil_CanSearchForGroup() - local hasActiveEntry = C_LFGList.HasActiveEntryInfo(); - local canSearch = not hasActiveEntry or (LFGListUtil_IsAppEmpowered() or LFGListUtil_IsEntryEmpowered()); - return canSearch; -end - -function LFGListUtil_CanListGroup() - return LFGListUtil_IsAppEmpowered(); -end - -function LFGListUtil_AppendStatistic(label, value, title, lastTitle) - if ( title ~= lastTitle ) then - GameTooltip:AddLine(" "); - GameTooltip:AddLine(title, 1, 1, 1); - end - - GameTooltip:AddLine(string.format(label, value)); -end - -function LFGList_ReportListing(searchResultID, leaderName) - local reportInfo = ReportInfo:CreateReportInfoFromType(Enum.ReportType.GroupFinderPosting); - reportInfo:SetGroupFinderSearchResultID(searchResultID); - ReportFrame:InitiateReport(reportInfo, leaderName); -end - -function LFGList_ReportAdvertisement(searchResultID) - C_LFGList.ReportGroupAsAdvertisement(searchResultID); -end - -function LFGList_ReportApplicant(applicantID, applicantName) - local reportInfo = ReportInfo:CreateReportInfoFromType(Enum.ReportType.GroupFinderApplicant); - reportInfo:SetGroupFinderApplicantID(applicantID); - ReportFrame:InitiateReport(reportInfo, applicantName); -end - -function LFGListUtil_OpenBestWindow(toggle) - local func = toggle and PVEFrame_ToggleFrame or PVEFrame_ShowFrame; - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - if ( activeEntryInfo ) then - --Open to the window of our active activity - local activityInfo = C_LFGList.GetActivityInfoTable(activeEntryInfo.activityIDs[1]); - if ( activityInfo and bit.band(activityInfo.filters, Enum.LFGListFilter.PvE) ~= 0 ) then - func("GroupFinderFrame", "LFGListPVEStub"); - else - func("PVPUIFrame", "LFGListPVPStub"); - end - else - --Open to the last window we had open - if ( bit.band(LFGListFrame.baseFilters, Enum.LFGListFilter.PvE) ~= 0 ) then - func("GroupFinderFrame", "LFGListPVEStub"); - else - func("PVPUIFrame", "LFGListPVPStub"); - end - end -end - -function LFGListUtil_SortActivitiesByRelevancy(activities) - table.sort(activities, function(activityID1, activityID2) - local activityInfo1 = C_LFGList.GetActivityInfoTable(activityID1); - local activityInfo2 = C_LFGList.GetActivityInfoTable(activityID2); - - if(not activityInfo1 or not activityInfo2) then - return false; - end - - if ( activityInfo1.minLevel ~= activityInfo2.minLevel ) then - return activityInfo1.minLevel > activityInfo2.minLevel; - elseif ( activityInfo1.ilvlSuggestion ~= activityInfo2.ilvlSuggestion ) then - local myILevel = GetAverageItemLevel(); - - if ((activityInfo1.minLevel <= myILevel) ~= (activityInfo2.minLevel <= myILevel) ) then - --If one is below our item level and the other above, choose the one we meet - return activityInfo1.minLevel < myILevel; - else - --If both are above or both are below, choose the one closest to our iLevel - return math.abs(activityInfo1.ilvlSuggestion - myILevel) < math.abs(activityInfo2.ilvlSuggestion - myILevel); - end - else - return strcmputf8i(activityInfo1.fullName, activityInfo2.ilvlSuggestion) < 0; - end - end); -end - -function LFGListUtil_SortActivitiesByShortname(activities) - table.sort(activities, function(activityID1, activityID2) - local activityInfo1 = C_LFGList.GetActivityInfoTable(activityID1); - local activityInfo2 = C_LFGList.GetActivityInfoTable(activityID2); - if activityInfo1 and activityInfo2 then - return activityInfo1.shortName < activityInfo2.shortName; - end - return false; - end); -end - ----@class LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS -LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS = { - "LFG_LIST_ACTIVE_ENTRY_UPDATE", - "LFG_LIST_SEARCH_RESULT_UPDATED", - "UPDATE_BATTLEFIELD_STATUS", - "LFG_UPDATE", - "LFG_ROLE_CHECK_UPDATE", - "LFG_PROPOSAL_UPDATE", - "LFG_PROPOSAL_FAILED", - "LFG_PROPOSAL_SUCCEEDED", - "LFG_PROPOSAL_SHOW", - "LFG_QUEUE_STATUS_UPDATE", -}; - -function LFGListUtil_GetActiveQueueMessage(isApplication) - --Check for applications if we're trying to list - if ( not isApplication and select(2,C_LFGList.GetNumApplications()) > 0 ) then - return CANNOT_DO_THIS_WITH_LFGLIST_APP; - end - - --Check for listings if we have an application - if ( isApplication and C_LFGList.HasActiveEntryInfo() ) then - return CANNOT_DO_THIS_WHILE_LFGLIST_LISTED; - end - - --Check all LFG categories - for category=1, NUM_LE_LFG_CATEGORYS do - local mode = GetLFGMode(category); - if ( mode ) then - if ( mode == "lfgparty" ) then - return CANNOT_DO_THIS_IN_LFG_PARTY; - elseif ( mode == "rolecheck" or (mode and not isApplication) ) then - return CANNOT_DO_THIS_IN_PVE_QUEUE; - end - end - end - - --Check PvP role check - local inProgress, _, _, _, _, isBattleground = GetLFGRoleUpdate(); - if ( inProgress ) then - return isBattleground and CANNOT_DO_THIS_WHILE_PVP_QUEUING or CANNOT_DO_THIS_WHILE_PVE_QUEUING; - end - - for i=1, GetMaxBattlefieldID() do - local status, mapName, teamSize, registeredMatch, suspend, _, _, _, _, _, _, isSoloQueue = GetBattlefieldStatus(i); - if ( status and status ~= "none" ) then - if not isSoloQueue or status == "active" then - return CANNOT_DO_THIS_IN_BATTLEGROUND; - end - end - end -end - -local LFG_LIST_INACTIVE_STATUSES = { - cancelled = true, - failed = true, - declined = true, - timedout = true, - invitedeclined = true, -} - -function LFGListUtil_IsStatusInactive(status) - return LFG_LIST_INACTIVE_STATUSES[status]; -end - -function LFGListUtil_SetAutoAccept(autoAccept) - local activeEntryInfo = C_LFGList.GetActiveEntryInfo(); - - if activeEntryInfo then - C_LFGList.CopyActiveEntryInfoToCreationFields(); - C_LFGList.UpdateListing({ - activityIDs = activeEntryInfo.activityIDs, - questID = activeEntryInfo.questID, - isAutoAccept = autoAccept, - isCrossFactionListing = activeEntryInfo.isCrossFaction, - isPrivateGroup = activeEntryInfo.privateGroup, - playstyle = activeEntryInfo.playstyle, - requiredDungeonScore = activeEntryInfo.requiredDungeonScore, - requiredItemLevel = activeEntryInfo.requiredItemLevel, - requiredPvpRating = activeEntryInfo.requiredPvpRating, - }); - end -end - -LFG_LIST_UTIL_SUPPRESS_AUTO_ACCEPT_LINE = 1; -LFG_LIST_UTIL_ALLOW_AUTO_ACCEPT_LINE = 2; - -function LFGListUtil_SetSearchEntryTooltip(tooltip, resultID, autoAcceptOption) - local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID); - local activityInfo = C_LFGList.GetActivityInfoTable(searchResultInfo.activityIDs[1], nil, searchResultInfo.isWarMode); - local categoryInfo = C_LFGList.GetLfgCategoryInfo(activityInfo.categoryID); - local allowsCrossFaction = (categoryInfo and categoryInfo.allowCrossFaction) and (activityInfo and activityInfo.allowCrossFaction); - - local memberCounts = C_LFGList.GetSearchResultMemberCounts(resultID); - tooltip:SetText(searchResultInfo.name, 1, 1, 1, true); - tooltip:AddLine(activityInfo.fullName); - - if (searchResultInfo.playstyle and searchResultInfo.playstyle > 0) then - local playstyleString = C_LFGList.GetPlaystyleString(searchResultInfo.playstyle, activityInfo); - if(not searchResultInfo.crossFactionListing and allowsCrossFaction) then - GameTooltip_AddColoredLine(tooltip, GROUP_FINDER_CROSS_FACTION_LISTING_WITH_PLAYSTLE:format(playstyleString, FACTION_STRINGS[searchResultInfo.leaderFactionGroup]), GREEN_FONT_COLOR); - else - GameTooltip_AddColoredLine(tooltip, playstyleString, GREEN_FONT_COLOR); - end - elseif(not searchResultInfo.crossFactionListing and allowsCrossFaction) then - GameTooltip_AddColoredLine(tooltip, GROUP_FINDER_CROSS_FACTION_LISTING_WITHOUT_PLAYSTLE:format(FACTION_STRINGS[searchResultInfo.leaderFactionGroup]), GREEN_FONT_COLOR); - end - if ( searchResultInfo.comment and searchResultInfo.comment == "" and searchResultInfo.questID ) then - searchResultInfo.comment = LFGListUtil_GetQuestDescription(searchResultInfo.questID); - end - if ( searchResultInfo.comment ~= "" ) then - tooltip:AddLine(string.format(LFG_LIST_COMMENT_FORMAT, searchResultInfo.comment), LFG_LIST_COMMENT_FONT_COLOR.r, LFG_LIST_COMMENT_FONT_COLOR.g, LFG_LIST_COMMENT_FONT_COLOR.b, true); - end - tooltip:AddLine(" "); - if ( searchResultInfo.requiredDungeonScore and searchResultInfo.requiredDungeonScore > 0 ) then - tooltip:AddLine(GROUP_FINDER_MYTHIC_RATING_REQ_TOOLTIP:format(searchResultInfo.requiredDungeonScore)); - end - if ( searchResultInfo.requiredPvpRating and searchResultInfo.requiredPvpRating > 0 ) then - tooltip:AddLine(GROUP_FINDER_PVP_RATING_REQ_TOOLTIP:format(searchResultInfo.requiredPvpRating)); - end - if ( searchResultInfo.requiredItemLevel > 0 ) then - if(activityInfo.isPvpActivity) then - tooltip:AddLine(LFG_LIST_TOOLTIP_ILVL_PVP:format(searchResultInfo.requiredItemLevel)); - else - tooltip:AddLine(LFG_LIST_TOOLTIP_ILVL:format(searchResultInfo.requiredItemLevel)); - end - end - if ( activityInfo.useHonorLevel and searchResultInfo.requiredHonorLevel > 0 ) then - tooltip:AddLine(LFG_LIST_TOOLTIP_HONOR_LEVEL:format(searchResultInfo.requiredHonorLevel)); - end - if ( searchResultInfo.voiceChat ~= "" ) then - tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_VOICE_CHAT, searchResultInfo.voiceChat), nil, nil, nil, true); - end - if ( (searchResultInfo.requiredItemLevel and searchResultInfo.requiredItemLevel > 0) or (activityInfo.useHonorLevel and searchResultInfo.requiredHonorLevel > 0) or searchResultInfo.voiceChat ~= "" or (searchResultInfo.requiredDungeonScore and searchResultInfo.requiredDungeonScore > 0) or (searchResultInfo.requiredPvpRating and searchResultInfo.requiredPvpRating > 0) ) then - tooltip:AddLine(" "); - end - - if ( searchResultInfo.leaderName ) then - if(searchResultInfo.leaderFactionGroup ~= -1 and (UnitFactionGroup("player") ~= PLAYER_FACTION_GROUP[searchResultInfo.leaderFactionGroup])) then - local factionString = FACTION_STRINGS[searchResultInfo.leaderFactionGroup]; - tooltip:AddLine(LFG_LIST_TOOLTIP_LEADER_FACTION:format(searchResultInfo.leaderName, factionString)) - else - tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_LEADER, searchResultInfo.leaderName)); - end - end - - if( activityInfo.isRatedPvpActivity and #searchResultInfo.leaderPvpRatingInfo > 0) then - local leaderPvpRatingInfo = searchResultInfo.leaderPvpRatingInfo[1]; - GameTooltip_AddNormalLine(tooltip, PVP_RATING_GROUP_FINDER:format(leaderPvpRatingInfo.activityName, leaderPvpRatingInfo.rating, PVPUtil.GetTierName(leaderPvpRatingInfo.tier))); - elseif ( isMythicPlusActivity and searchResultInfo.leaderOverallDungeonScore) then - local color = C_ChallengeMode.GetDungeonScoreRarityColor(searchResultInfo.leaderOverallDungeonScore); - if(not color) then - color = HIGHLIGHT_FONT_COLOR; - end - GameTooltip_AddNormalLine(tooltip, DUNGEON_SCORE_LEADER:format(color:WrapTextInColorCode(searchResultInfo.leaderOverallDungeonScore))); - end - - if(activityInfo.isMythicPlusActivity and #searchResultInfo.leaderDungeonScoreInfo > 0) then - local leaderDungeonScoreInfo = searchResultInfo.leaderDungeonScoreInfo[1]; - local color = C_ChallengeMode.GetSpecificDungeonOverallScoreRarityColor(leaderDungeonScoreInfo.mapScore); - if (not color) then - color = HIGHLIGHT_FONT_COLOR; - end - if(leaderDungeonScoreInfo.mapScore == 0) then - GameTooltip_AddNormalLine(tooltip, DUNGEON_SCORE_PER_DUNGEON_NO_RATING:format(leaderDungeonScoreInfo.mapName, leaderDungeonScoreInfo.mapScore)); - elseif (leaderDungeonScoreInfo.finishedSuccess) then - GameTooltip_AddNormalLine(tooltip, DUNGEON_SCORE_DUNGEON_RATING:format(leaderDungeonScoreInfo.mapName, color:WrapTextInColorCode(leaderDungeonScoreInfo.mapScore), leaderDungeonScoreInfo.bestRunLevel)); - else - GameTooltip_AddNormalLine(tooltip, DUNGEON_SCORE_DUNGEON_RATING_OVERTIME:format(leaderDungeonScoreInfo.mapName, color:WrapTextInColorCode(leaderDungeonScoreInfo.mapScore), leaderDungeonScoreInfo.bestRunLevel)); - end - end - if ( searchResultInfo.age > 0 ) then - tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_AGE, SecondsToTime(searchResultInfo.age, false, false, 1, false))); - end - - if ( searchResultInfo.leaderName or searchResultInfo.age > 0 ) then - tooltip:AddLine(" "); - end - - if ( activityInfo.displayType == Enum.LFGListDisplayType.ClassEnumerate ) then - tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_MEMBERS_SIMPLE, searchResultInfo.numMembers)); - for i=1, searchResultInfo.numMembers do - local memberInfo = C_LFGList.GetSearchResultPlayerInfo(resultID, i); - if (memberInfo) then - local classColor = RAID_CLASS_COLORS[memberInfo.classFilename] or NORMAL_FONT_COLOR; - tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_CLASS_ROLE, memberInfo.className, memberInfo.specName), classColor.r, classColor.g, classColor.b); - end - end - else - tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_MEMBERS, searchResultInfo.numMembers, memberCounts.TANK, memberCounts.HEALER, memberCounts.DAMAGER)); - end - - if ( searchResultInfo.numBNetFriends + searchResultInfo.numCharFriends + searchResultInfo.numGuildMates > 0 ) then - tooltip:AddLine(" "); - tooltip:AddLine(LFG_LIST_TOOLTIP_FRIENDS_IN_GROUP); - tooltip:AddLine(LFGListSearchEntryUtil_GetFriendList(resultID), 1, 1, 1, true); - end - - local completedEncounters = C_LFGList.GetSearchResultEncounterInfo(resultID); - if ( completedEncounters and #completedEncounters > 0 ) then - tooltip:AddLine(" "); - tooltip:AddLine(LFG_LIST_BOSSES_DEFEATED); - for i=1, #completedEncounters do - tooltip:AddLine(completedEncounters[i], RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b); - end - end - - autoAcceptOption = autoAcceptOption or LFG_LIST_UTIL_ALLOW_AUTO_ACCEPT_LINE; - - if autoAcceptOption == LFG_LIST_UTIL_ALLOW_AUTO_ACCEPT_LINE and searchResultInfo.autoAccept then - tooltip:AddLine(" "); - tooltip:AddLine(LFG_LIST_TOOLTIP_AUTO_ACCEPT, LIGHTBLUE_FONT_COLOR:GetRGB()); - end - - if ( searchResultInfo.isDelisted ) then - tooltip:AddLine(" "); - tooltip:AddLine(LFG_LIST_ENTRY_DELISTED, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, true); - end - - tooltip:Show(); -end - -function LFGListUtil_GetQuestCategoryData(questID) - -- Do not allow searches if the quest name cannot be looked up. - local questName = QuestUtils_GetQuestName(questID); - - if not questName then - return; - end - - local activityID = C_LFGList.GetActivityIDForQuestID(questID); - if activityID then - local activityInfo = C_LFGList.GetActivityInfoTable(activityID); - if(not activityInfo) then - return; - end - local filters = activityInfo.filters; - -- NOTE: There's an issue where filters will actually contain ALL of the filters for the given activity. - -- This portion of the UI only cares about the filters for specific categories that get updated when the category buttons are added, - -- and furthermore only cares about them when we're separating a single category into recommended and non-recommended. - -- The baseFilters on the frame contain the rest of the required filters. - -- To solve this so that category selection can be properly driven from the API, only use the filters that would be present on the button. - -- Otherwise the selection will not work, and it won't be possible to create a group automatically. - local categoryInfo = C_LFGList.GetLfgCategoryInfo(activityInfo.categoryID); - if categoryInfo.separateRecommended then - if bit.bor(filters, Enum.LFGListFilter.Recommended) then - filters = Enum.LFGListFilter.Recommended; - elseif bit.bor(filters, Enum.LFGListFilter.NotRecommended) then - filters = Enum.LFGListFilter.NotRecommended; - else - filters = 0; - end - else - filters = 0; - end - - return activityID, activityInfo.categoryID, filters, questName; - end -end - -function LFGListUtil_FindQuestGroup(questID, isFromGreenEyeButton) - if C_LFGList.HasActiveEntryInfo() then - if LFGListUtil_CanListGroup() then - StaticPopup_Show("PREMADE_GROUP_SEARCH_DELIST_WARNING", nil, nil, questID); - else - LFGListUtil_OpenBestWindow(); - end - else - LFGListFrame_BeginFindQuestGroup(LFGListFrame, questID, isFromGreenEyeButton); - end -end - -function LFGListUtil_GetQuestDescription(questID) - local descriptionFormat = AUTO_GROUP_CREATION_NORMAL_QUEST; - if ( QuestUtils_IsQuestWorldQuest(questID) ) then - descriptionFormat = AUTO_GROUP_CREATION_WORLD_QUEST; - end - - return descriptionFormat:format(QuestUtils_GetQuestName(questID)); -end - - - -------------------------------------------------------- -----------Edit Box functions -------------------------------------------------------- - - -function LFGListEditBox_AddToTabCategory(self, tabCategory) - self.tabCategory = tabCategory; - local cat = LFG_LIST_EDIT_BOX_TAB_CATEGORIES[tabCategory]; - if ( not cat ) then - cat = {}; - LFG_LIST_EDIT_BOX_TAB_CATEGORIES[tabCategory] = cat; - end - self.tabCategoryIndex = #cat+1; - cat[self.tabCategoryIndex] = self; -end - -function LFGListEditBox_OnTabPressed(self) - if ( self.tabCategory ) then - local offset = IsShiftKeyDown() and -1 or 1; - local cat = LFG_LIST_EDIT_BOX_TAB_CATEGORIES[self.tabCategory]; - if ( cat ) then - --It's times like this when I wish Lua was 0-based... - cat[((self.tabCategoryIndex - 1 + offset + #cat) % #cat) + 1]:SetFocus(); - end - end -end - ----@class LFGAuthenticatorMessagingMixin -LFGAuthenticatorMessagingMixin = {} -function LFGAuthenticatorMessagingMixin:DisplayTooltip() - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip_AddNormalLine(GameTooltip, LFG_AUTHENTICATOR_BUTTON_TOOLTIP); - GameTooltip:Show(); -end - -function LFGAuthenticatorMessagingMixin:DisplayStaticPopup() - StaticPopup_Show("GROUP_FINDER_AUTHENTICATOR_POPUP"); -end - ----@class LFGEditBoxMixin : EditBox, LFGAuthenticatorMessagingMixin -LFGEditBoxMixin = CreateFromMixins(LFGAuthenticatorMessagingMixin); -function LFGEditBoxMixin:AddToTabCategory(tabCategory, editBox) - local addToTab = editBox or self; - LFGListEditBox_AddToTabCategory(addToTab, tabCategory); -end - -function LFGEditBoxMixin:OnLoad() - if ( self.tabCategory ) then - self:AddToTabCategory(self.tabCategory); - end -end - -function LFGEditBoxMixin:GetSelectedActivityID() - return self:GetParent().selectedActivity or self:GetParent():GetParent().selectedActivity; -end - -function LFGEditBoxMixin:GetSelectedCategoryID() - return self:GetParent().selectedCategory or self:GetParent():GetParent().selectedCategory; -end - -function LFGEditBoxMixin:OnShow() - local isAccountSecured = C_LFGList.IsPlayerAuthenticatedForLFG(self:GetSelectedCategoryID()); - if(self:GetParent().numeric or isAccountSecured) then - self:SetEnabled(true); - self.LockButton:Hide(); - else - self:SetEnabled(false); - self.LockButton:SetShown(not self:GetParent().hideLockButton); - end - self.editBoxEnabled = self:IsEnabled(); -end - -function LFGEditBoxMixin:OnEnter() - if(not C_LFGList.IsPlayerAuthenticatedForLFG(self:GetSelectedCategoryID()) and not self.editBoxEnabled) then - self:DisplayTooltip(); - end -end - -function LFGEditBoxMixin:OnMouseDown(button) - - if(not C_LFGList.IsPlayerAuthenticatedForLFG(self:GetSelectedCategoryID()) and not self.editBoxEnabled) then - self:DisplayStaticPopup(); - end -end - -function LFGEditBoxMixin:OnTabPressed() - LFGListEditBox_OnTabPressed(self); -end - ----@class LFGListLockButtonMixin : Button, LFGAuthenticatorMessagingMixin -LFGListLockButtonMixin = CreateFromMixins(LFGAuthenticatorMessagingMixin); - -function LFGListLockButtonMixin:OnClick() - self:DisplayStaticPopup(); -end - -function LFGListLockButtonMixin:OnEnter() - self:DisplayTooltip(); -end - ----@class LFGListCreationDescriptionMixin : LFGEditBoxMixin -LFGListCreationDescriptionMixin = CreateFromMixins(LFGEditBoxMixin); - -function LFGListCreationDescriptionMixin:OnLoad() - StoreSecureReference("LFGListCreationDescription", self.EditBox); - self.EditBox:SetSecurityDisableSetText(); - self.EditBox:SetSecurityDisablePaste(); - self:AddToTabCategory("ENTRY_CREATION", self.EditBox); - self.EditBox:SetScript("OnTabPressed", LFGListEditBox_OnTabPressed); - self.EditBox:EnableMouse(false); - InputScrollFrame_OnLoad(self); - - local isAccountSecured = C_LFGList.IsPlayerAuthenticatedForLFG(self:GetParent().selectedCategory); - self.EditBox.Instructions:SetText(isAccountSecured and DESCRIPTION_OF_YOUR_GROUP or LFG_AUTHENTICATOR_DESCRIPTION_BOX); - self.EditBox:SetEnabled(isAccountSecured); - self.LockButton:SetShown(not isAccountSecured); - self.editBoxEnabled = isAccountSecured; -end - -function LFGListCreationDescriptionMixin:OnShow() - local isAccountSecured = C_LFGList.IsPlayerAuthenticatedForLFG(self:GetParent().selectedCategory); - self.EditBox.Instructions:SetText(isAccountSecured and DESCRIPTION_OF_YOUR_GROUP or LFG_AUTHENTICATOR_DESCRIPTION_BOX); - self.EditBox:SetEnabled(isAccountSecured); - self.LockButton:SetShown(not isAccountSecured); - self.editBoxEnabled = isAccountSecured; -end - ----@class LFGListCreateGroupDisabledStateButtonMixin : Button, LFGAuthenticatorMessagingMixin -LFGListCreateGroupDisabledStateButtonMixin = CreateFromMixins(LFGAuthenticatorMessagingMixin); - -function LFGListCreateGroupDisabledStateButtonMixin:OnClick() - if(not C_LFGList.IsPlayerAuthenticatedForLFG(self:GetParent().selectedCategory)) then - self:DisplayStaticPopup(); - end -end - -function LFGListCreateGroupDisabledStateButtonMixin:OnEnter() - local parentErrorText = self:GetParent().errorText; - if(parentErrorText) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip_AddNormalLine(GameTooltip, parentErrorText); - GameTooltip:Show(); - end -end - ----@class LFGListSearchBackToGroupButtonMixin : Button -LFGListSearchBackToGroupButtonMixin = { }; - -function LFGListSearchBackToGroupButtonMixin:OnClick() - local frame = self:GetParent():GetParent(); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - LFGListFrame_SetActivePanel(frame, frame.ApplicationViewer); -end - ----@class LFGListSearchBackButtonMixin : Button -LFGListSearchBackButtonMixin = { }; - -function LFGListSearchBackButtonMixin:OnClick() - local frame = self:GetParent():GetParent(); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - LFGListFrame_SetActivePanel(frame, frame.CategorySelection); - self:GetParent().shouldAlwaysShowCreateGroupButton = false; -end diff --git a/WoW-API/_UI/Blizzard_GroupFinder/LFGList.xml b/WoW-API/_UI/Blizzard_GroupFinder/LFGList.xml deleted file mode 100644 index 6f8957b..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/LFGList.xml +++ /dev/null @@ -1,2090 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( self.relationship == "friend" ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(LFG_LIST_FRIEND, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1, true); - GameTooltip:Show(); - elseif ( self.relationship == "guild" ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(LFG_LIST_GUILD_MEMBER, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1, true); - GameTooltip:Show(); - else - GameTooltip:Hide(); - end - - - - - - - - - - - LFGListApplicantMember_OnEnter(self:GetParent()); - - - - self:RegisterForClicks("RightButtonUp"); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( self.tooltip ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(string.format(VOICE_CHAT_COLON, self.tooltip), 1, 1, 1, 1, true); - GameTooltip:Show(); - end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( self:GetChecked() ) then - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - else - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF); - end - - - local tooltip = self:GetParent().tooltip; - local disableTooltip = self:GetParent().disableTooltip; - if ( tooltip and self:IsEnabled()) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(tooltip, nil, nil, nil, nil, true); - GameTooltip:Show(); - elseif (not self:IsEnabled() and disableTooltip) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(disableTooltip, nil, nil, nil, nil, true); - GameTooltip:Show(); - end - - - - - - - - - - - - - self.Label:SetText(self.label); - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( self:GetChecked() ) then - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - self:GetParent().EditBox:SetFocus(); - else - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF); - self:GetParent().EditBox:ClearFocus(); - if not self:GetParent().secureReferenceStr then - self:GetParent().EditBox:SetText(""); - end - end - - - - - - - - - - - - - - - - local parent = self:GetParent(); - if ( self:GetText() ~= "" ) then - parent.CheckButton:SetChecked(true); - end - LFGListRequirement_Validate(parent, self:GetText()); - InputBoxInstructions_OnTextChanged(self); - - - if ( self:GetText() == "" and not self:GetParent().CheckButton:IsMouseOver()) then - self:GetParent().CheckButton:SetChecked(false); - end - - - - - - - - - - - - - - - - local warningText = self:GetParent().warningText; - if ( warningText ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(warningText, nil, nil, nil, nil, true); - GameTooltip:Show(); - end - - - - - - - - self.Label:SetText(self.label); - self.EditBox:SetNumeric(self.numeric); - self.EditBox.Instructions:SetText(self.instructions); - if ( self.maxLetters ) then - self.EditBox:SetMaxLetters(self.maxLetters); - end - if ( self.tabCategory ) then - self.EditBox:AddToTabCategory(self.tabCategory); - end - if ( self.secureReferenceStr ) then - StoreSecureReference(self.secureReferenceStr, self.EditBox); - self.EditBox:SetSecurityDisableSetText(); - self.EditBox:SetSecurityDisablePaste(); - end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StoreSecureReference("LFGListApplicationDescription", self.EditBox); - self.EditBox:SetSecurityDisableSetText(); - self.EditBox:SetSecurityDisablePaste(); - InputScrollFrame_OnLoad(self); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LFGListNothingAvailable_Update(self); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LFGListSearchPanel_UpdateAutoComplete(self:GetParent()); - SearchBoxTemplate_OnEditFocusGained(self); - - - LFGListSearchPanel_UpdateAutoComplete(self:GetParent()); - SearchBoxTemplate_OnEditFocusLost(self); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( self.Text:IsTruncated() ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(self.activityName, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); - if ( self.comment ~= "" ) then - GameTooltip:AddLine(string.format(LFG_LIST_IN_QUOTES, self.comment), LFG_LIST_COMMENT_FONT_COLOR.r, LFG_LIST_COMMENT_FONT_COLOR.g, LFG_LIST_COMMENT_FONT_COLOR.b, true); - end - GameTooltip:Show(); - end - - - - - - - - - - - if ( self.RoleCount:IsShown() or self.PlayerCount:IsShown() ) then - GameTooltip:SetOwner(self, "ANCHOR_TOP"); - GameTooltip:SetText(string.format(LFG_LIST_MEMBER_COUNT, GetNumGroupMembers(LE_PARTY_CATEGORY_HOME))); - GameTooltip:Show(); - end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( self:GetChecked() ) then - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - else - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF); - end - LFGListUtil_SetAutoAccept(self:GetChecked()); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.WaitAnim:Play(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.Instructions:SetText(SEARCH); - - - InputBoxInstructions_OnTextChanged(self); - LFGListEntryCreationActivityFinder_UpdateMatching(self:GetParent():GetParent()); - - - LFGListEntryCreationActivityFinder_Accept(self:GetParent():GetParent()); - PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - InputBoxInstructions_OnTextChanged(self); - LFGListEntryCreation_UpdateValidState(self:GetParent()); - - - self:SetMaxLetters(129); - - - self:SetMaxLetters(31); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - InputScrollFrame_OnMouseDown(self); - self:OnMouseDown(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WoW-API/_UI/Blizzard_GroupFinder/PVEFrame.lua b/WoW-API/_UI/Blizzard_GroupFinder/PVEFrame.lua deleted file mode 100644 index 93b3adb..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/PVEFrame.lua +++ /dev/null @@ -1,384 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ ---------------------------------------------------------------- --- PVE FRAME ---------------------------------------------------------------- - -PVE_FRAME_BASE_WIDTH = 563; - --- TODO: SHARING PASS (PVEFrame is currently forked) --- Note: These need to be uncommented out from PVEFrame.xml as well. -local panels = { - { name = "GroupFinderFrame", addon = nil }, - { name = "PVPQueueFrame", addon = "Blizzard_PVPUI", check = function() return ClassicExpansionAtLeast(LE_EXPANSION_MISTS_OF_PANDARIA); end }, - { name = "ChallengesFrame", addon = "Blizzard_ChallengesUI", check = function() return UnitLevel("player") >= GetMaxLevelForExpansionLevel(GetExpansionLevel()) and C_ChallengeMode.IsChallengeModeEnabled(); end }, -} - -function PVEFrame_OnLoad(self) - -- If there is only 1 tab, then we don't need to show tabs - self.showTabs = (#panels > 1); - - RaiseFrameLevel(self.shadows); - PanelTemplates_SetNumTabs(self, #panels); - - self:RegisterEvent("AJ_PVP_ACTION"); - self:RegisterEvent("AJ_PVP_SKIRMISH_ACTION"); - self:RegisterEvent("AJ_PVP_LFG_ACTION"); - self:RegisterEvent("AJ_PVP_RBG_ACTION"); - self:RegisterEvent("AJ_PVE_LFG_ACTION"); - - self.maxTabWidth = (self:GetWidth() - 19) / #panels; -end - -function PVEFrame_OnShow(self) - if(self.showTabs) then - for index, panel in pairs(panels) do - if (panel.check and not panel.check()) then - PanelTemplates_HideTab(self, index); - else - PanelTemplates_ShowTab(self, index); - end - end - end -end - -function PVEFrame_OnEvent(self, event, ...) - if ( event == "AJ_PVP_ACTION" ) then - local id = ...; - ShowPVPQueueUI(); - HonorFrameSpecificList_FindAndSelectBattleground(id); - HonorFrame_SetType("specific"); - elseif ( event == "AJ_PVP_SKIRMISH_ACTION" ) then - ShowPVPQueueUI(); - HonorFrame_SetType("bonus"); - - HonorFrameBonusFrame_SelectButton(HonorFrame.BonusFrame.Arena1Button); - elseif ( event == "AJ_PVE_LFG_ACTION" ) then - PVEFrame_ShowFrame("GroupFinderFrame", "LFGListPVEStub"); - elseif ( event == "AJ_PVP_LFG_ACTION" ) then - PVEFrame_ShowFrame("PVPUIFrame", "LFGListPVPStub"); - elseif ( event == "AJ_PVP_RBG_ACTION" ) then - ShowPVPQueueUI(); - HonorFrame_SetType("bonus"); - - HonorFrameBonusFrame_SelectButton(HonorFrame.BonusFrame.RandomBGButton); - end -end - -function PVEFrame_ToggleFrame(sidePanelName, selection) - local canUse = C_LFGInfo.CanPlayerUseGroupFinder() and UnitLevel("player") >= SHOW_LFD_LEVEL; - if ( not canUse or Kiosk.IsEnabled() ) then - return; - end - local self = PVEFrame; - if ( self:IsShown() ) then - if ( sidePanelName ) then - local sidePanel = _G[sidePanelName]; - if ( sidePanel ) then - --We know the panel is loaded, so try to dereference the selection - if ( type(selection) == "string" ) then - selection = _G[selection]; - end - if ( sidePanel:IsShown() and (not selection or not sidePanel.getSelection or sidePanel:getSelection() == selection) ) then - HideUIPanel(self); - return; - end - end - else - HideUIPanel(self); - return; - end - end - PVEFrame_ShowFrame(sidePanelName, selection); -end -function PVEFrame_ShowFrame(sidePanelName, selection) - local self = PVEFrame; - -- find side panel - local tabIndex; - if ( sidePanelName ) then - for index, data in pairs(panels) do - if ( data.name == sidePanelName ) then - tabIndex = index; - break; - end - end - else - -- no side panel specified, check current panel - if ( self.activeTabIndex ) then - tabIndex = self.activeTabIndex; - else - -- no current panel, go to the first panel - tabIndex = 1; - end - end - if ( not tabIndex ) then - return; - end - if ( panels[tabIndex].check and not panels[tabIndex].check() ) then - tabIndex = self.activeTabIndex or 1; - end - - -- load addon if needed - if ( panels[tabIndex].addon ) then - UIParentLoadAddOn(panels[tabIndex].addon); - panels[tabIndex].addon = nil; - end - - -- we've loaded the AddOn, so try to dereference the selection if needed - if ( type(selection) == "string" ) then - selection = _G[selection]; - end - - -- show it - ShowUIPanel(self); - self.activeTabIndex = tabIndex; - if(self.showTabs) then - PanelTemplates_SetTab(self, tabIndex); - end - self:SetWidth(PVE_FRAME_BASE_WIDTH); - UpdateUIPanelPositions(PVEFrame); - for index, data in pairs(panels) do - local panel = _G[data.name]; - if ( index == tabIndex ) then - panel:Show(); - if( panel.update ) then - panel:update(selection); - end - elseif ( panel ) then - panel:Hide(); - end - end -end - -function PVEFrame_TabOnClick(self) - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_TAB); - PVEFrame_ShowFrame(panels[self:GetID()].name); -end - -function PVEFrame_HideLeftInset() - PVEFrameLeftInset:Hide(); - PVEFrameBlueBg:Hide(); - PVEFrameTLCorner:Hide(); - PVEFrameTRCorner:Hide(); - PVEFrameBRCorner:Hide(); - PVEFrameBLCorner:Hide(); - PVEFrameLLVert:Hide(); - PVEFrameRLVert:Hide(); - PVEFrameBottomLine:Hide(); - PVEFrameTopLine:Hide(); - PVEFrameTopFiligree:Hide(); - PVEFrameBottomFiligree:Hide(); - PVEFrame.shadows:Hide(); -end - -function PVEFrame_ShowLeftInset() - PVEFrameLeftInset:Show(); - PVEFrameBlueBg:Show(); - PVEFrameTLCorner:Show(); - PVEFrameTRCorner:Show(); - PVEFrameBRCorner:Show(); - PVEFrameBLCorner:Show(); - PVEFrameLLVert:Show(); - PVEFrameRLVert:Show(); - PVEFrameBottomLine:Show(); - PVEFrameTopLine:Show(); - PVEFrameTopFiligree:Show(); - PVEFrameBottomFiligree:Show(); - PVEFrame.shadows:Show(); -end - ---------------------------------------------------------------- --- GROUP FINDER ---------------------------------------------------------------- - -local groupFrames = { "LFDParentFrame", "RaidFinderFrame", "LFGListPVEStub", "ScenarioFinderFrame" } - -function GroupFinderFrame_OnLoad(self) - SetPortraitToTexture(self.groupButton1.icon, "Interface\\Icons\\INV_Helmet_08"); - self.groupButton1.name:SetText(LOOKING_FOR_DUNGEON_PVEFRAME); - SetPortraitToTexture(self.groupButton2.icon, "Interface\\LFGFrame\\UI-LFR-PORTRAIT"); - self.groupButton2.name:SetText(RAID_FINDER_PVEFRAME); - SetPortraitToTexture(self.groupButton3.icon, "Interface\\Icons\\Achievement_General_StayClassy"); - self.groupButton3.name:SetText(LFGLIST_NAME); - SetPortraitToTexture(self.groupButton4.icon, "Interface\\Icons\\Icon_Scenarios"); - self.groupButton4.name:SetText(SCENARIOS_PVEFRAME); - - GroupFinderFrame_EvaluateButtonVisibility(self); - - self:RegisterEvent("LFG_UPDATE_RANDOM_INFO"); - self:RegisterEvent("PLAYER_LEVEL_CHANGED"); - - -- set up accessors - self.getSelection = GroupFinderFrame_GetSelection; - self.update = GroupFinderFrame_Update; -end - -function GroupFinderFrame_EvaluateButtonVisibility(self) - local visible = C_LFGInfo.IsLFDEnabled(); - local canUse, failureReason = C_LFGInfo.CanPlayerUseLFD(); - if not visible then - self.groupButton1:Hide(); - elseif not canUse then - self.groupButton1:Show(); - GroupFinderFrameButton_SetEnabled(self.groupButton1, false); - self.groupButton1.tooltip = failureReason; - else - self.groupButton1:Show(); - self.groupButton1.tooltip = nil; - GroupFinderFrameButton_SetEnabled(self.groupButton1, true); - end - - visible = C_LFGInfo.IsLFREnabled(); - canUse, failureReason = C_LFGInfo.CanPlayerUseLFR(); - if not visible then - self.groupButton2:Hide(); - - -- To avoid a weird gap, move the other buttons around if LFR is off - local altAnchorPoint = self.groupButton1.altAnchorPoint; - local altAnchorRelativePoint = nil; - local altXOffset = tonumber(self.groupButton1.altXOffset); - local altYOffset = tonumber(self.groupButton1.altYOffset); - self.groupButton1:SetPoint(altAnchorPoint, altXOffset, altYOffset); - altAnchorPoint = self.groupButton3.altAnchorPoint; - altAnchorRelativePoint = self.groupButton3.altAnchorRelativePoint; - altXOffset = tonumber(self.groupButton3.altXOffset); - altYOffset = tonumber(self.groupButton3.altYOffset); - self.groupButton3:SetPoint(altAnchorPoint, self.groupButton1, altAnchorRelativePoint, altXOffset, altYOffset); - elseif not canUse then - self.groupButton2:Show(); - GroupFinderFrameButton_SetEnabled(self.groupButton2, false); - self.groupButton2.tooltip = failureReason; - else - self.groupButton2:Show(); - self.groupButton2.tooltip = nil; - GroupFinderFrameButton_SetEnabled(self.groupButton2, true); - end - - visible = C_LFGList.IsPremadeGroupFinderEnabled(); - canUse, failureReason = C_LFGInfo.CanPlayerUsePremadeGroup(); - if not visible then - self.groupButton3:Hide(); - elseif not canUse then - self.groupButton3:Show(); - GroupFinderFrameButton_SetEnabled(self.groupButton3, false); - self.groupButton3.tooltip = failureReason; - else - self.groupButton3:Show(); - self.groupButton3.tooltip = nil; - GroupFinderFrameButton_SetEnabled(self.groupButton3, true); - end - - visible = (ScenariosList and #ScenariosList > 0) or false - canUse, failureReason = C_LFGInfo.CanPlayerUseScenarioFinder(); - if not visible then - self.groupButton4:Hide(); - elseif not canUse then - self.groupButton4:Show(); - GroupFinderFrameButton_SetEnabled(self.groupButton4, false); - self.groupButton4.tooltip = failureReason; - else - self.groupButton4:Show(); - self.groupButton4.tooltip = nil; - GroupFinderFrameButton_SetEnabled(self.groupButton4, true); - end -end - -function GroupFinderFrameButton_SetEnabled(button, enabled) - if ( button:IsEnabled() == enabled ) then - return - end - - if ( enabled ) then - button.bg:SetTexCoord(0.00390625, 0.87890625, 0.75195313, 0.83007813); - button.name:SetFontObject("GameFontNormalLarge"); - else - button.bg:SetTexCoord(0.00390625, 0.87890625, 0.67187500, 0.75000000); - button.name:SetFontObject("GameFontDisableLarge"); - end - SetDesaturation(button.icon, not enabled); - SetDesaturation(button.ring, not enabled); - button:SetEnabled(enabled); -end - -function GroupFinderFrame_OnEvent(self, event, ...) - GroupFinderFrame_EvaluateButtonVisibility(self); -end - -function GroupFinderFrame_GetSelection(self) - return self.selection; -end - -function GroupFinderFrame_GetSelectedIndex(self) - return self.selectionIndex; -end - -function GroupFinderFrame_Update(self, frame) - GroupFinderFrame_ShowGroupFrame(frame); -end - -function GroupFinderFrame_EvaluateHelpTips(self) - if not GetCVarBitfield("closedInfoFrames", LE_FRAME_TUTORIAL_LFG_LIST) and C_LFGInfo.CanPlayerUsePremadeGroup() then - local helpTipInfo = { - text = LFG_LIST_TUTORIAL_ALERT, - buttonStyle = HelpTip.ButtonStyle.Close, - cvarBitfield = "closedInfoFrames", - bitfieldFlag = LE_FRAME_TUTORIAL_LFG_LIST, - targetPoint = HelpTip.Point.TopEdgeCenter, - }; - HelpTip:Show(self, helpTipInfo, GroupFinderFrameGroupButton3); - end -end - -function GroupFinderFrame_OnShow(self) - if(SetPortraitAtlasRaw) then - PVEFrame:SetPortraitAtlasRaw("groupfinder-eye-frame"); - else - PVEFramePortrait:SetAtlas("groupfinder-eye-frame"); - end - PVEFrame:SetTitle(GROUP_FINDER); - GroupFinderFrame_EvaluateButtonVisibility(self); - GroupFinderFrame_EvaluateHelpTips(self); - ScenarioQueueFrame_Update(); -end - -function GroupFinderFrame_ShowGroupFrame(frame) - frame = frame or GroupFinderFrame.selection or (C_LFGInfo.CanPlayerUseLFD() and LFDParentFrame or LFGListPVEStub); - -- hide the other frames and select the right button - for index, frameName in pairs(groupFrames) do - local groupFrame = _G[frameName]; - if ( groupFrame == frame ) then - GroupFinderFrame_SelectGroupButton(index); - else - groupFrame:Hide(); - end - end - frame:Show(); - GroupFinderFrame.selection = frame; -end - -function GroupFinderFrame_SelectGroupButton(index) - local self = GroupFinderFrame; - for i = 1, #groupFrames do - local button = self["groupButton"..i]; - if ( i == index ) then - button.bg:SetTexCoord(0.00390625, 0.87890625, 0.59179688, 0.66992188); - else - button.bg:SetTexCoord(0.00390625, 0.87890625, 0.75195313, 0.83007813); - end - end - - GroupFinderFrame.selectionIndex = index -end - -function GroupFinderFrameGroupButton_OnClick(self) - local frameName = groupFrames[self:GetID()]; - GroupFinderFrame_ShowGroupFrame(_G[frameName]); -end - -function GroupFinderFrameGroupButton_OnEnter(self) - if self.tooltip then - GameTooltip:SetOwner(self, "ANCHOR_TOP"); - GameTooltip_AddNormalLine(GameTooltip, self.tooltip); - GameTooltip:Show(); - end -end diff --git a/WoW-API/_UI/Blizzard_GroupFinder/PVEFrame.xml b/WoW-API/_UI/Blizzard_GroupFinder/PVEFrame.xml deleted file mode 100644 index 1a9daed..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/PVEFrame.xml +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LFGListFrame:SetParent(self); - LFGListFrame:ClearAllPoints(); - LFGListFrame:SetAllPoints(self); - LFGListFrame:SetFrameLevel(self:GetFrameLevel()); - LFGListFrame_SetBaseFilters(LFGListFrame, Enum.LFGListFilter.PvE); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PVEFrame_OnShow(self); - UpdateMicroButtons(); - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN); - - - UpdateMicroButtons(); - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_CLOSE); - - - - - diff --git a/WoW-API/_UI/Blizzard_GroupFinder/RaidFinder.lua b/WoW-API/_UI/Blizzard_GroupFinder/RaidFinder.lua deleted file mode 100644 index 23b0b68..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/RaidFinder.lua +++ /dev/null @@ -1,604 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ -MAX_RAID_FINDER_COOLDOWN_NAMES = 8; - -function RaidFinderFrame_OnLoad(self) - self:RegisterEvent("LFG_LOCK_INFO_RECEIVED"); - self:RegisterEvent("AJ_RAID_ACTION"); - self:RegisterEvent("GROUP_ROSTER_UPDATE"); - self:RegisterEvent("LFG_UPDATE_RANDOM_INFO"); - - EventRegistry:RegisterCallback("LobbyMatchmaker.UpdateQueueState", RaidFinderFrameFindRaidButton_Update); -end - -function RaidFinderFrame_OnEvent(self, event, ...) - if ( event == "LFG_LOCK_INFO_RECEIVED" ) then - if ( not RaidFinderQueueFrame.raid or not IsLFGDungeonJoinable(RaidFinderQueueFrame.raid) ) then - RaidFinderQueueFrame_SetRaid(GetBestRFChoice()); - end - RaidFinderFrame_UpdateAvailability(); - elseif ( event == "AJ_RAID_ACTION" ) then - local raidID = ...; - PVEFrame_ShowFrame("GroupFinderFrame", RaidFinderFrame); - RaidFinderQueueFrame_SetRaid(raidID); - elseif ( event == "GROUP_ROSTER_UPDATE" ) then - if ( self:IsVisible() ) then - RaidFinderQueueFrame_UpdateRoles(); - end - elseif ( event == "LFG_UPDATE_RANDOM_INFO" ) then - if ( self:IsVisible() ) then - RaidFinderQueueFrameRewards_UpdateFrame(); - end - end -end - -function RaidFinderFrame_OnShow(self) - QueueUpdater:RequestInfo(); - QueueUpdater:AddRef(); - RaidFinderFrameFindRaidButton_Update(); - LFGBackfillCover_Update(RaidFinderQueueFrame.PartyBackfill, true); - RaidFinderFrame_UpdateAvailability(); - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN); -end - -function RaidFinderFrame_OnHide(self) - QueueUpdater:RemoveRef(); -end - --- unused now, might need this logic for Group Finder -function RaidFinderFrame_UpdateAvailability() - --Update the cover panel (specifically for when you hit level 86 and can no longer queue - --for any RF raids until you hit level 90). - local available = false; - local nextLevel = nil; - local level = UnitLevel("player"); - for i=1, GetNumRFDungeons() do - local id, name, typeID, subtype, minLevel, maxLevel = GetRFDungeonInfo(i); - if ( level >= minLevel and level <= maxLevel ) then - available = true; - nextLevel = nil; - break; - elseif ( level < minLevel and (not nextLevel or minLevel < nextLevel ) ) then - nextLevel = minLevel; - end - end - if ( available ) then - RaidFinderFrame.NoRaidsCover:Hide(); - else - RaidFinderFrame.NoRaidsCover:Show(); - if ( nextLevel ) then - RaidFinderFrame.NoRaidsCover.Label:SetFormattedText(NO_RF_AVAILABLE_WITH_NEXT_LEVEL, nextLevel); - else - RaidFinderFrame.NoRaidsCover.Label:SetText(NO_RF_AVAILABLE); - end - end - --[[ - local enableTab = false; - local isPlayerEligible = false; - for i = 1, GetNumRFDungeons() do - local id, name = GetRFDungeonInfo(i); - local isAvailable, isAvailableToPlayer = IsLFGDungeonJoinable(id); - if ( isAvailable ) then - -- there is at least one raid that can be selected, make it so - RaidFinderQueueFrameIneligibleFrame_SetIneligibility(false, false); - PanelTemplates_EnableTab(RaidParentFrame, 1); - return; - elseif ( isAvailableToPlayer ) then - enableTab = true; - isPlayerEligible = true; - elseif ( IsRaidFinderDungeonDisplayable(id) ) then - enableTab = true; - end - end - if ( enableTab ) then - -- at least one raid is visible, but none can be selected - PanelTemplates_EnableTab(RaidParentFrame, 1); - if ( isPlayerEligible ) then - RaidFinderQueueFrameIneligibleFrame_SetIneligibility(true, false); - else - RaidFinderQueueFrameIneligibleFrame_SetIneligibility(false, true); - end - else - -- nothing in the dropdown, just block the tab - RaidFinderFrame:Hide(); - PanelTemplates_DisableTab(RaidParentFrame, 1); - if ( RaidParentFrame.selectectTab == 1 ) then - RaidParentFrame_SetView(2); - end - end - ]]-- -end - --- returns true if the inelibile frame is shown -function RaidFinderQueueFrameIneligibleFrame_SetIneligibility(onGroup, onPlayer) - local frame = RaidFinderQueueFrameIneligibleFrame; - if ( onGroup ) then - frame.ineligibleGroup = true; - frame.ineligiblePlayer = false; - elseif ( onPlayer ) then - frame.ineligibleGroup = false; - frame.ineligiblePlayer = true; - else - frame.ineligibleGroup = false; - frame.ineligiblePlayer = false; - end - RaidFinderQueueFrameIneligibleFrame_UpdateFrame(frame); -end - --- returns true if the inelibile frame is shown -function RaidFinderQueueFrameIneligibleFrame_SetQueueRestriction(otherQueue) - local frame = RaidFinderQueueFrameIneligibleFrame; - frame.queueRestriction = otherQueue; - return RaidFinderQueueFrameIneligibleFrame_UpdateFrame(frame); -end - -function RaidFinderQueueFrameIneligibleFrame_UpdateFrame(self) - if ( self.queueRestriction ) then - self.leaveQueueButton:Show(); - if ( self.queueRestriction == "lfd" ) then - self.description:SetText(NO_RF_WHILE_LFD); - self.leaveQueueButton:SetText(LEAVE_QUEUE); - if ( LFD_IsEmpowered() ) then - self.leaveQueueButton:Enable(); - else - self.leaveQueueButton:Disable(); - end - else - self.description:SetText(NO_RF_WHILE_LFR); - if ( IsInGroup() ) then - self.leaveQueueButton:SetText(UNLIST_MY_GROUP); - else - self.leaveQueueButton:SetText(UNLIST_ME); - end - if ( RaidBrowser_IsEmpowered() ) then - self.leaveQueueButton:Enable(); - else - self.leaveQueueButton:Disable(); - end - end - self:Show(); - return true; - elseif ( self.ineligibleGroup ) then - self.description:SetText(LFR_QUEUE_GROUP_INELIGIBLE); - self.leaveQueueButton:Hide(); - self:Show(); - return true; - elseif ( self.ineligiblePlayer ) then - self.description:SetText(LFR_QUEUE_PLAYER_INELIGIBLE); - self.leaveQueueButton:Hide(); - self:Show(); - return true; - else - self:Hide(); - end -end - -local function IsRaidFinderDungeonDisplayable(id) - local name, typeID, subtypeID, minLevel, maxLevel, _, _, _, expansionLevel = GetLFGDungeonInfo(id); - local myLevel = UnitLevel("player"); - return myLevel >= minLevel and myLevel <= maxLevel and EXPANSION_LEVEL >= expansionLevel; -end - -local function IsSelected(dungeonID) - return RaidFinderQueueFrame.raid == dungeonID; -end - -local function SetSelected(dungeonID) - RaidFinderQueueFrame_SetRaidInternal(dungeonID); -end - -function RaidFinderQueueFrame_OnLoad(self) - self.SelectionDropdown:SetWidth(200); - - self.SelectionDropdown:SetSelectionTranslator(function(selection) - return GetLFGDungeonInfo(selection.data); - end); -end - -function RaidFinderQueueFrame_OnShow(self) - self.SelectionDropdown:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_RAID_FINDER_QUEUE_FRAME"); - - local sortedDungeons = { }; - local function InsertDungeonData(id, name, mapName, isAvailable, mapID) - local t = { id = id, name = name, mapName = mapName, isAvailable = isAvailable, mapID = mapID }; - local foundMap = false; - for index, dungeon in ipairs(sortedDungeons) do - if ( dungeon.mapName == mapName ) then - foundMap = true; - else - if ( foundMap ) then - tinsert(sortedDungeons, index, t); - return; - end - end - end - tinsert(sortedDungeons, t); - end - - -- If we ever change this logic, we also need to change the logic in RaidFinderFrame_UpdateAvailability - for i=1, GetNumRFDungeons() do - local dungeonInfo = { GetRFDungeonInfo(i) }; - local id = dungeonInfo[1]; - local name = dungeonInfo[2]; - local mapName = dungeonInfo[20]; - local mapID = dungeonInfo[23]; - local isAvailable, isAvailableToPlayer, hideIfNotJoinable = IsLFGDungeonJoinable(id); - if( not hideIfNotJoinable or isAvailable ) then - if ( isAvailable or isAvailableToPlayer or IsRaidFinderDungeonDisplayable(id) ) then - InsertDungeonData(id, name, mapName, isAvailable, mapID); - end - end - end - - local function GetInstanceData(mapID) - local icon; - local modifiedInstanceTooltipText = ""; - if C_ModifiedInstance and mapID then - local modifiedInstanceInfo = C_ModifiedInstance.GetModifiedInstanceInfoFromMapID(mapID) - if (modifiedInstanceInfo) then - icon = GetFinalNameFromTextureKit("%s-small", modifiedInstanceInfo.uiTextureKit); - modifiedInstanceTooltipText = "|n|n" .. modifiedInstanceInfo.description; - end - end - return icon, modifiedInstanceTooltipText; - end - - local currentMapName = nil; - for index, dungeon in ipairs(sortedDungeons) do - if ( currentMapName ~= dungeon.mapName ) then - currentMapName = dungeon.mapName; - rootDescription:CreateTitle(currentMapName); - end - - local text = dungeon.name; - local iconTexture, modifiedInstanceTooltipText = GetInstanceData(dungeon.mapID); - local radio = rootDescription:CreateRadio(dungeon.name, IsSelected, SetSelected, dungeon.id); - - if iconTexture then - radio:AddInitializer(function(button, description, menu) - local icon = button:AttachTexture(); - icon.noRecurseHierarchy = true; - icon:SetPoint("RIGHT"); - icon:SetSize(16, 16); - icon:SetTexture(iconTexture); - end); - end - - if ( dungeon.isAvailable ) then - local encounters; - for j = 1, GetLFGDungeonNumEncounters(dungeon.id) do - local bossName, _, isKilled = GetLFGDungeonEncounterInfo(dungeon.id, j); - local colorCode = ""; - if ( isKilled ) then - colorCode = RED_FONT_COLOR_CODE; - end - if encounters then - encounters = encounters.."|n"..colorCode..bossName..FONT_COLOR_CODE_CLOSE; - else - encounters = colorCode..bossName..FONT_COLOR_CODE_CLOSE; - end - end - - if encounters then - local tooltipText = encounters .. modifiedInstanceTooltipText; - radio:SetTooltip(function(tooltip, elementDescription) - GameTooltip_SetTitle(tooltip, RAID_BOSSES); - GameTooltip_AddNormalLine(tooltip, tooltipText); - end); - end - else - radio:SetEnabled(false); - radio:SetTooltip(function(tooltip, elementDescription) - GameTooltip_SetTitle(tooltip, YOU_MAY_NOT_QUEUE_FOR_THIS); - GameTooltip_AddNormalLine(tooltip, LFGConstructDeclinedMessage(dungeon.id)..modifiedInstanceTooltipText); - end); - end - end - end); -end - -function RaidFinderQueueFrame_SetRaidInternal(raid) - RaidFinderQueueFrame.raid = raid; - RaidFinderQueueFrameRewards_UpdateFrame(); - LFG_UpdateAllRoleCheckboxes(); - LFG_UpdateFindGroupButtons(); - LFG_UpdateRolesChangeable(); -end - -function RaidFinderQueueFrame_SetRaid(raid) - RaidFinderQueueFrame_SetRaidInternal(raid); - RaidFinderQueueFrame.SelectionDropdown:GenerateMenu(); -end - -function RaidFinderQueueFrame_Join() - if ( RaidFinderQueueFrame.raid ) then - ClearAllLFGDungeons(LE_LFG_CATEGORY_RF); - SetLFGDungeon(LE_LFG_CATEGORY_RF, RaidFinderQueueFrame.raid); - --JoinLFG(LE_LFG_CATEGORY_RF); - JoinSingleLFG(LE_LFG_CATEGORY_RF, RaidFinderQueueFrame.raid); - end -end - -function RaidFinderQueueFrame_UpdateRoles() - local dungeonID = RaidFinderQueueFrame.raid; - LFG_SetRoleIconIncentive(RaidFinderQueueFrameRoleButtonTank, nil); - LFG_SetRoleIconIncentive(RaidFinderQueueFrameRoleButtonHealer, nil); - LFG_SetRoleIconIncentive(RaidFinderQueueFrameRoleButtonDPS, nil); - - if ( type(dungeonID) == "number" ) then - if ( not IsInGroup(LE_PARTY_CATEGORY_HOME) ) then - for i=1, LFG_ROLE_NUM_SHORTAGE_TYPES do - local eligible, forTank, forHealer, forDamage, itemCount, money, xp = GetLFGRoleShortageRewards(dungeonID, i); - if ( eligible and (itemCount ~= 0 or money ~= 0 or xp ~= 0) ) then --Only show the icon if there is actually a reward. - if ( forTank ) then - LFG_SetRoleIconIncentive(RaidFinderQueueFrameRoleButtonTank, i); - end - if ( forHealer ) then - LFG_SetRoleIconIncentive(RaidFinderQueueFrameRoleButtonHealer, i); - end - if ( forDamage ) then - LFG_SetRoleIconIncentive(RaidFinderQueueFrameRoleButtonDPS, i); - end - end - end - end - - local tankLocked, healerLocked, dpsLocked = GetLFDRoleRestrictions(dungeonID); - RaidFinder_UpdateRoleButton(RaidFinderQueueFrameRoleButtonTank, tankLocked); - RaidFinder_UpdateRoleButton(RaidFinderQueueFrameRoleButtonHealer, healerLocked); - RaidFinder_UpdateRoleButton(RaidFinderQueueFrameRoleButtonDPS, dpsLocked); - end -end - -function RaidFinder_UpdateRoleButton( button, locked ) - if( button.permDisabled )then - return; - end - - if( locked ) then - button.lockedIndicator:Show(); - button.checkButton:Hide(); - else - button.lockedIndicator:Hide(); - button.checkButton:Show(); - end -end - -function RaidFinderFrameRoleCheckButton_OnClick(self) - RaidFinderQueueFrame_SetRoles(); - RaidFinderQueueFrameRewards_UpdateFrame(); -end - -function RaidFinderQueueFrame_SetRoles() - SetLFGRoles(LFGRole_GetChecked(RaidFinderQueueFrameRoleButtonLeader), - LFGRole_GetChecked(RaidFinderQueueFrameRoleButtonTank), - LFGRole_GetChecked(RaidFinderQueueFrameRoleButtonHealer), - LFGRole_GetChecked(RaidFinderQueueFrameRoleButtonDPS) ); -end - -function RaidFinderQueueFrameRewards_UpdateFrame() - LFGRewardsFrame_UpdateFrame(RaidFinderQueueFrameScrollFrameChildFrame, RaidFinderQueueFrame.raid, RaidFinderQueueFrameBackground); - RaidFinderQueueFrame_UpdateRoles(); -end - -function RaidFinderFrameFindRaidButton_Update() - if C_LobbyMatchmakerInfo and C_LobbyMatchmakerInfo.IsInQueue() then - RaidFinderFrameFindRaidButton:Disable(); - RaidFinderFrameFindRaidButton.disabledTooltip = WOW_LABS_CANNOT_ENTER_NON_PLUNDER_QUEUE; - return; - end - - local mode, subMode = GetLFGMode(LE_LFG_CATEGORY_RF, RaidFinderQueueFrame.raid); - --Update the text on the button - if ( mode == "queued" or mode == "rolecheck" or mode == "proposal" or mode == "suspended" ) then - RaidFinderFrameFindRaidButton:SetText(LEAVE_QUEUE); - else - if ( IsInGroup() and GetNumGroupMembers() > 1 ) then - RaidFinderFrameFindRaidButton:SetText(JOIN_AS_PARTY); - else - RaidFinderFrameFindRaidButton:SetText(FIND_A_GROUP); - end - end - - --Disable the button if we're not in a state where we can make a change - if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "listed" ) then --During the proposal, they must use the proposal buttons to leave the queue. - if ( (mode == "queued" or mode == "rolecheck" or mode == "suspended") --The players can dequeue even if one of the two cover panels is up. - or (not RaidFinderQueueFramePartyBackfill:IsVisible() and not RaidFinderQueueFrameCooldownFrame:IsVisible()) ) then - RaidFinderFrameFindRaidButton:Enable(); - else - RaidFinderFrameFindRaidButton:Disable(); - end - else - RaidFinderFrameFindRaidButton:Disable(); - end - - --Disable the button if the person is active in LFGList - local lfgListDisabled; - if ( C_LFGList.HasActiveEntryInfo() ) then - lfgListDisabled = CANNOT_DO_THIS_WHILE_LFGLIST_LISTED; - elseif(C_PartyInfo.IsCrossFactionParty()) then - lfgListDisabled = CROSS_FACTION_RAID_DUNGEON_FINDER_ERROR; - end - - if ( lfgListDisabled ) then - RaidFinderFrameFindRaidButton:Disable(); - RaidFinderFrameFindRaidButton.disabledTooltip = lfgListDisabled; - else - RaidFinderFrameFindRaidButton.disabledTooltip = nil; - end - - --Update the backfill enable state - if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "queued" and mode ~= "suspended" and mode ~= "rolecheck" ) then - RaidFinderQueueFramePartyBackfillBackfillButton:Enable(); - else - RaidFinderQueueFramePartyBackfillBackfillButton:Disable(); - end -end - -function RaidFinderRoleButton_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(_G["ROLE_DESCRIPTION_"..self.role], nil, nil, nil, nil, true); - if ( self.permDisabled ) then - if(self.permDisabledTip)then - GameTooltip:AddLine(self.permDisabledTip, 1, 0, 0, true); - end - elseif ( self.disabledTooltip and not self:IsEnabled() ) then - GameTooltip:AddLine(self.disabledTooltip, 1, 0, 0, true); - elseif ( self.lockedIndicator:IsVisible() ) then - local dungeonID = RaidFinderQueueFrame.raid; - local roleID = self:GetID(); - GameTooltip:SetText(ERR_ROLE_UNAVAILABLE, 1.0, 1.0, 1.0, true); - if ( type(dungeonID) == "number" ) then - local textTable = LFGRoleButton_LockReasonsTextTable(dungeonID, roleID); - for text,_ in pairs( textTable ) do - GameTooltip:AddLine(text, nil, nil, nil, true); - end - end - GameTooltip:Show(); - return; - end - GameTooltip:Show(); - LFGFrameRoleCheckButton_OnEnter(self); -end - ---Cooldown panel -function RaidFinderQueueFrameCooldownFrame_OnLoad(self) - self:SetFrameLevel(RaidFinderQueueFrame:GetFrameLevel() + 9); --This value also needs to be set when SetParent is called in LFDQueueFrameRandomCooldownFrame_Update. - - self:RegisterEvent("PLAYER_ENTERING_WORLD"); --For logging in/reloading ui - self:RegisterEvent("LFG_COOLDOWNS_UPDATED"); - self:RegisterEvent("GROUP_ROSTER_UPDATE"); -end - -function RaidFinderQueueFrameCooldownFrame_OnEvent(self, event, ...) - RaidFinderQueueFrameCooldownFrame_Update(); -end - -function RaidFinderQueueFrameCooldownFrame_OnUpdate(self, elapsed) - local timeRemaining = self.myExpirationTime - GetTime(); - if ( timeRemaining > 0 ) then - self.time:SetText(SecondsToTime(ceil(timeRemaining))); - else - RaidFinderQueueFrameCooldownFrame_Update(); - end -end - -function RaidFinderQueueFrameCooldownFrame_Update() - local cooldownFrame = RaidFinderQueueFrameCooldownFrame; - local shouldShow = false; - - local cooldownExpiration = GetLFGDeserterExpiration(); - - cooldownFrame.myExpirationTime = cooldownExpiration; - - local tokenPrefix; - local numMembers; - if ( IsInRaid() ) then - tokenPrefix = "raid"; - numMembers = GetNumGroupMembers(); - else - tokenPrefix = "party"; - numMembers = GetNumSubgroupMembers(); - end - - local numCooldowns = 0; - for i = 1, numMembers do - if ( UnitHasLFGDeserter(tokenPrefix..i) and not UnitIsUnit(tokenPrefix..i, "player") ) then - numCooldowns = numCooldowns + 1; - - if ( numCooldowns <= MAX_RAID_FINDER_COOLDOWN_NAMES ) then - local nameLabel = _G["RaidFinderQueueFrameCooldownFrameName"..numCooldowns]; - nameLabel:Show(); - - local _, classFilename = UnitClass(tokenPrefix..i); - local classColor = classFilename and RAID_CLASS_COLORS[classFilename] or NORMAL_FONT_COLOR; - nameLabel:SetFormattedText("|cff%.2x%.2x%.2x%s|r", classColor.r * 255, classColor.g * 255, classColor.b * 255, UnitName(tokenPrefix..i)); - end - - shouldShow = true; - end - end - for i = numCooldowns + 1, MAX_RAID_FINDER_COOLDOWN_NAMES do - local nameLabel = _G["RaidFinderQueueFrameCooldownFrameName"..i]; - nameLabel:Hide(); - end - - local anchorSide = "LEFT"; --Used to center text when we have 4 or fewer players. - local anchorOffset = 25; - if ( numCooldowns == 0 ) then - cooldownFrame.description:SetPoint("TOP", 0, -85); - cooldownFrame.additionalPlayersFrame:Hide(); - elseif ( numCooldowns <= MAX_RAID_FINDER_COOLDOWN_NAMES / 2 ) then - cooldownFrame.description:SetPoint("TOP", 0, -30); - for i=2, MAX_RAID_FINDER_COOLDOWN_NAMES do - local nameLabel = _G["RaidFinderQueueFrameCooldownFrameName"..i]; - nameLabel:ClearAllPoints(); - nameLabel:SetPoint("TOP", _G["RaidFinderQueueFrameCooldownFrameName"..(i-1)], "BOTTOM", 0, -5); - end - cooldownFrame.additionalPlayersFrame:Hide(); - anchorSide = ""; - anchorOffset = 0; - else - if ( numCooldowns > MAX_RAID_FINDER_COOLDOWN_NAMES ) then - cooldownFrame.additionalPlayersFrame.text:SetFormattedText(RF_COOLDOWN_ADDITIONAL_PEOPLE, numCooldowns - MAX_RAID_FINDER_COOLDOWN_NAMES); - cooldownFrame.additionalPlayersFrame:Show(); - else - cooldownFrame.additionalPlayersFrame:Hide(); - end - cooldownFrame.description:SetPoint("TOP", 0, -30); - for i=2, MAX_RAID_FINDER_COOLDOWN_NAMES do - local nameLabel = _G["RaidFinderQueueFrameCooldownFrameName"..i]; - nameLabel:ClearAllPoints(); - if ( i % 2 == 0 ) then - nameLabel:SetPoint("LEFT", _G["RaidFinderQueueFrameCooldownFrameName"..(i-1)], "RIGHT", 15, 0); - else - nameLabel:SetPoint("TOP", _G["RaidFinderQueueFrameCooldownFrameName"..(i-2)], "BOTTOM", 0, -5); - end - end - end - - RaidFinderQueueFrameCooldownFrameName1:ClearAllPoints(); - if ( cooldownExpiration and GetTime() < cooldownExpiration ) then - shouldShow = true; - cooldownFrame.description:SetText(RF_DESERTER_YOU); - cooldownFrame.time:SetText(SecondsToTime(ceil(cooldownExpiration - GetTime()))); - cooldownFrame.time:Show(); - - cooldownFrame:SetScript("OnUpdate", RaidFinderQueueFrameCooldownFrame_OnUpdate); - - if ( numCooldowns > 0 ) then - cooldownFrame.secondaryDescription:Show(); - RaidFinderQueueFrameCooldownFrameName1:SetPoint("TOP"..anchorSide, cooldownFrame.secondaryDescription, "BOTTOM"..anchorSide, anchorOffset, -20); - else - cooldownFrame.secondaryDescription:Hide(); - RaidFinderQueueFrameCooldownFrameName1:SetPoint("TOP"..anchorSide, cooldownFrame.description, "BOTTOM"..anchorSide, anchorOffset, -20); - end - else - cooldownFrame.description:SetText(RF_DESERTER_OTHER); - cooldownFrame.time:Hide(); - - cooldownFrame:SetScript("OnUpdate", nil); - cooldownFrame.secondaryDescription:Hide(); - RaidFinderQueueFrameCooldownFrameName1:SetPoint("TOP"..anchorSide, cooldownFrame.description, "BOTTOM"..anchorSide, anchorOffset, -20); - end - - if ( shouldShow and not RaidFinderQueueFramePartyBackfill:IsShown() ) then - cooldownFrame:Show(); - else - cooldownFrame:Hide(); - end -end - -function RaidFinderQueueFrameCooldownAdditionalPlayers_OnEnter(self) - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(DESERTER); - if ( IsInRaid() ) then - for i=1, GetNumGroupMembers() do - if ( UnitHasLFGDeserter("raid"..i) ) then - GameTooltip:AddLine(UnitName("raid"..i), 1, 1, 1); - end - end - end - GameTooltip:Show(); -end diff --git a/WoW-API/_UI/Blizzard_GroupFinder/RaidFinder.xml b/WoW-API/_UI/Blizzard_GroupFinder/RaidFinder.xml deleted file mode 100644 index d6e7913..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/RaidFinder.xml +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RaidFinderQueueFrameRewards_UpdateFrame(); - - - - - - - - - - - - - LFGBackfillCover_SetUp(self, {LFG_SUBTYPEID_RAID}, LE_LFG_CATEGORY_RF, RaidFinderFrameFindRaidButton_Update); - - - - - - - - - - - LFGCooldownCover_SetUp(self, self:GetParent().PartyBackfill); - LFGCooldownCover_ChangeSettings(self, false, false); - - - RaidFinderFrameFindRaidButton_Update(); - - - RaidFinderFrameFindRaidButton_Update(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self:SetFrameLevel(RaidFinderQueueFrameCooldownFrame:GetFrameLevel() + 2); - - - - - - - - - - - - - - - - - - diff --git a/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder.lua b/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder.lua deleted file mode 100644 index 3c5f495..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder.lua +++ /dev/null @@ -1,17 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ -function ScenarioQueueFrame_Update() - local mode, submode = GetLFGMode(LE_LFG_CATEGORY_SCENARIO); - local checkedList; - if ( LFD_IsEmpowered() and mode ~= "queued" and mode ~= "suspended") then - checkedList = LFGEnabledList; - else - checkedList = LFGQueuedForList[LE_LFG_CATEGORY_SCENARIO]; - end - - ScenariosList = GetScenariosChoiceOrder(ScenariosList); - - LFGQueueFrame_UpdateLFGDungeonList(ScenariosList, ScenariosHiddenByCollapseList, checkedList, SCENARIOS_CURRENT_FILTER); - - ScenarioQueueFrameSpecific_Update(); -end diff --git a/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder.xml b/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder.xml deleted file mode 100644 index 5931d78..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder.xml +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - self.enableButton:SetScript("OnClick", ScenarioQueueFrameChoiceEnableButton_OnClick); - self.expandOrCollapseButton:SetScript("OnClick", ScenarioQueueFrameExpandOrCollapseButton_OnClick); - self:SetScript("OnEnter", ScenarioQueueFrameChoiceButton_OnEnter); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --Move the title to deal with an offset so scrolling doesn't look as bad with the LFD border. - self.title:SetPoint("TOPLEFT", 10, -8); - LFGRewardsFrame_OnLoad(self); - - - ScenarioQueueFrameRandom_UpdateFrame(); - LFGRewardsFrame_AdjustFont(self); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ScenarioQueueFrame_Update(); - - - - - - - - - - - - - - - - - LFGBackfillCover_SetUp(self, {LFG_SUBTYPEID_SCENARIO}, LE_LFG_CATEGORY_SCENARIO, ScenarioQueueFrameFindGroupButton_Update); - - - - - - - - - - - - - - - - - LFGCooldownCover_SetUp(self, self:GetParent().PartyBackfill); - - - ScenarioQueueFrameFindGroupButton_Update(); - - - ScenarioQueueFrameFindGroupButton_Update(); - - - - - - - - - - QueueUpdater:RemoveRef(); - - - - - - - - - - - diff --git a/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder_Shared.lua b/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder_Shared.lua deleted file mode 100644 index 9c73da2..0000000 --- a/WoW-API/_UI/Blizzard_GroupFinder/ScenarioFinder_Shared.lua +++ /dev/null @@ -1,344 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ ----@class ScenariosList -ScenariosList = {}; -SCENARIOS_CURRENT_FILTER = LFGList_DefaultFilterFunction; - -function ScenarioQueueFrameSpecificList_InitButton(button, elementData) - local dungeonID = elementData.dungeonID; - local enabled, queued = LFGDungeonList_EvaluateListState(LE_LFG_CATEGORY_LFD); - - local checkedList; - if ( queued ) then - checkedList = LFGQueuedForList[LE_LFG_CATEGORY_SCENARIO]; - else - checkedList = LFGEnabledList; - end - - button:SetWidth(295); - - LFGDungeonListButton_SetDungeon(button, dungeonID, enabled, checkedList); -end - -function ScenarioFinderFrame_OnLoad(self) - self:RegisterEvent("LFG_UPDATE_RANDOM_INFO"); - self:RegisterEvent("LFG_UPDATE"); - - local view = CreateScrollBoxListLinearView(); - view:SetElementInitializer("ScenarioSpecificChoiceTemplate", ScenarioQueueFrameSpecificList_InitButton); - ScrollUtil.InitScrollBoxListWithScrollBar(self.Queue.Specific.ScrollFrame, self.Queue.Specific.ScrollBar, view); - - ScenarioQueueFrame_Update(); -end - -function ScenarioFinderFrame_OnEvent(self, event, ...) - if ( event == "LFG_UPDATE_RANDOM_INFO" ) then - local queueFrame = ScenarioQueueFrame; - if ( not queueFrame.type or (type(queueFrame.type) == "number" and not IsLFGDungeonJoinable(queueFrame.type)) ) then - local bestChoice = GetRandomScenarioBestChoice(); - if ( bestChoice ) then - ScenarioQueueFrame_SetType(bestChoice); - end - end - --If we still don't have a value, we should go to specific. - if ( not queueFrame.type ) then - ScenarioQueueFrame_SetType("specific"); - end - ScenarioFinderFrame_UpdateAvailability(); - end - ScenarioQueueFrameFindGroupButton_Update(); -end - -function ScenarioFinderFrame_OnShow(self) - LFGBackfillCover_Update(ScenarioQueueFrame.PartyBackfill, true); - ScenarioFinderFrame_UpdateAvailability(); -end - -local allScenarios = GetScenariosChoiceOrder(); -function ScenarioFinderFrame_UpdateAvailability() - local available = false; - local nextLevel = nil; - local level = C_PartyInfo.GetMinLevel(); - - --We have to look through both random scenarios and specific scenarios. - for i=1, GetNumRandomScenarios() do - local id, name, typeID, subtype, minLevel, maxLevel = GetRandomScenarioInfo(i); - if ( level >= minLevel and level <= maxLevel ) then - available = true; - nextLevel = nil; - break; - elseif ( level < minLevel and (not nextLevel or minLevel < nextLevel ) ) then - nextLevel = minLevel; - end - end - if ( not available ) then - for i=1, #allScenarios do - local id = allScenarios[i]; - if ( id > 0 ) then - local name, typeID, subtype, minLevel, maxLevel = GetLFGDungeonInfo(id); - if ( level >= minLevel and level <= maxLevel ) then - available = true; - nextLevel = nil; - break; - elseif ( level < minLevel and (not nextLevel or minLevel < nextLevel ) ) then - nextLevel = minLevel; - end - end - end - end - if ( available ) then - ScenarioFinderFrame.NoScenariosCover:Hide(); - else - ScenarioFinderFrame.NoScenariosCover:Show(); - if ( nextLevel ) then - ScenarioFinderFrame.NoScenariosCover.Label:SetFormattedText(NO_SCENARIO_AVAILABLE_WITH_NEXT_LEVEL, nextLevel); - else - ScenarioFinderFrame.NoScenariosCover.Label:SetText(NO_SCENARIO_AVAILABLE); - end - end -end - --- Specific ----@class ScenariosHiddenByCollapseList -ScenariosHiddenByCollapseList = { }; - -function ScenarioQueueFrameSpecific_Update() - if ( LFGDungeonList_Setup() ) then - return; --Setup will update the list. - end - - local scrollFrame = ScenarioQueueFrame.Specific.ScrollFrame; - - local enabled, queued = LFGDungeonList_EvaluateListState(LE_LFG_CATEGORY_SCENARIO); - - local numScenarios = (ScenariosList and #ScenariosList) or 0 - - local dataProvider = CreateDataProvider(); - - for i = 1, numScenarios do - local dungeonID = ScenariosList[i]; - dataProvider:Insert({dungeonID = dungeonID}); - end - - scrollFrame:SetDataProvider(dataProvider); - - ScenarioQueueFrameFindGroupButton_Update(); -end - --- Random -function ScenarioQueueFrameRandom_UpdateFrame() - local dungeonID = ScenarioQueueFrame.type; - - if ( type(dungeonID) ~= "number" ) then --We haven't gotten info on available dungeons yet. - return; - end - LFGRewardsFrame_UpdateFrame(ScenarioQueueFrame.Random.ScrollFrame.Child, dungeonID, ScenarioQueueFrame.Bg); -end - -function ScenarioQueueFrameRandomRandomList_OnEnter(self) - local randomID = ScenarioQueueFrame.type; - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(INCLUDED_SCENARIOS, 1, 1, 1); - - local numDungeons = GetNumDungeonForRandomSlot(randomID); - - if ( numDungeons == 0 ) then - GameTooltip:AddLine(INCLUDED_SCENARIOS_EMPTY, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, true); - else - GameTooltip:AddLine(INCLUDED_SCENARIOS_SUBTEXT, nil, nil, nil, true); - GameTooltip:AddLine(" "); - for i=1, numDungeons do - local dungeonID = GetDungeonForRandomSlot(randomID, i); - local name, typeID, subtypeID, minLevel, maxLevel, recLevel, minRecLevel, maxRecLevel, expansionLevel, groupID, textureFilename, difficulty, maxPlayers, description, isHoliday = GetLFGDungeonInfo(dungeonID); - local rangeText; - if ( minLevel == maxLevel ) then - rangeText = format(LFD_LEVEL_FORMAT_SINGLE, minLevel); - else - rangeText = format(LFD_LEVEL_FORMAT_RANGE, minLevel, maxLevel); - end - local difficultyColor = GetQuestDifficultyColor(recLevel); - - local displayName = name; - if ( LFGLockList[dungeonID] ) then - displayName = "|TInterface\\LFGFrame\\UI-LFG-ICON-LOCK:14:14:0:0:32:32:0:28:0:28|t"..displayName; - end - GameTooltip:AddDoubleLine(displayName, rangeText, difficultyColor.r, difficultyColor.g, difficultyColor.b, difficultyColor.r, difficultyColor.g, difficultyColor.b); - end - end - - GameTooltip:Show(); -end - --- Join button -function ScenarioQueueFrame_Join() - LFG_JoinDungeon(LE_LFG_CATEGORY_SCENARIO, ScenarioQueueFrame.type, ScenariosList, ScenariosHiddenByCollapseList); -end - -function ScenarioQueueFrameFindGroupButton_OnClick() - local mode, subMode = GetLFGMode(LE_LFG_CATEGORY_SCENARIO); - if ( mode == "queued" or mode == "listed" or mode == "rolecheck" or mode == "suspended" ) then - LeaveLFG(LE_LFG_CATEGORY_SCENARIO); - else - ScenarioQueueFrame_Join(); - end -end - -function ScenarioQueueFrameFindGroupButton_OnEnter(self) - if ( self.tooltip ) then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); - GameTooltip:SetText(self.tooltip, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1, true); - GameTooltip:Show(); - end -end - -function ScenarioQueueFrameFindGroupButton_Update() - local mode, subMode = GetLFGMode(LE_LFG_CATEGORY_SCENARIO); - --Update the button text - if ( mode == "queued" or mode == "rolecheck" or mode == "proposal" or mode == "suspended" ) then - ScenarioQueueFrameFindGroupButton:SetText(LEAVE_QUEUE); - else - if (IsInGroup() and GetNumGroupMembers() > 1) then - ScenarioQueueFrameFindGroupButton:SetText(JOIN_AS_GROUP); - else - ScenarioQueueFrameFindGroupButton:SetText(FIND_A_GROUP); - end - end - - --Disable the button if we're not in a state where we can make a change - if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "listed" ) then --During the proposal, they must use the proposal buttons to leave the queue. - if ( (mode == "queued" or mode == "rolecheck" or mode == "suspended") --The players can dequeue even if one of the two cover panels is up. - or (not ScenarioQueueFramePartyBackfill:IsVisible() and not ScenarioQueueFrameCooldownFrame:IsVisible()) ) then - ScenarioQueueFrameFindGroupButton:Enable(); - else - ScenarioQueueFrameFindGroupButton:Disable(); - end - else - ScenarioQueueFrameFindGroupButton:Disable(); - end - - --Disable the button if the person is active in LFGList - local lfgListDisabled; - if ( C_LFGList.HasActiveEntryInfo() ) then - lfgListDisabled = CANNOT_DO_THIS_WHILE_LFGLIST_LISTED; - elseif(C_PartyInfo.IsCrossFactionParty()) then - local isScenarioID = ScenarioQueueFrame.type and (type(ScenarioQueueFrame.type) == "number"); - if isScenarioID then - lfgListDisabled = LFG_TryGetCrossFactionQueueFailureMessage({ ScenarioQueueFrame.type }); - elseif ScenarioQueueFrame.type == "specific" then - lfgListDisabled = LFG_TryGetCrossFactionQueueFailureMessage(LFG_BuildSelectedEntriesList(ScenariosList, ScenariosHiddenByCollapseList)); - end - end - - if ( lfgListDisabled ) then - LFDQueueFrameFindGroupButton:Disable(); - LFDQueueFrameFindGroupButton.tooltip = lfgListDisabled; - end - - if ( lfgListDisabled ) then - ScenarioQueueFrameFindGroupButton:Disable(); - ScenarioQueueFrameFindGroupButton.tooltip = lfgListDisabled; - else - ScenarioQueueFrameFindGroupButton.tooltip = nil; - end - - --Update the backfill enable state - if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "queued" and mode ~= "suspended" and mode ~= "rolecheck" ) then - ScenarioQueueFramePartyBackfillBackfillButton:Enable(); - else - ScenarioQueueFramePartyBackfillBackfillButton:Disable(); - end -end - --- List buttons -function ScenarioQueueFrameChoiceEnableButton_OnClick(self) - LFGDungeonListCheckButton_OnClick(self, LE_LFG_CATEGORY_SCENARIO, ScenariosList, ScenariosHiddenByCollapseList); - ScenarioQueueFrameSpecific_Update(); -end - -function ScenarioQueueFrameExpandOrCollapseButton_OnClick(self) - LFGDungeonList_SetHeaderCollapsed(self:GetParent(), ScenariosList, ScenariosHiddenByCollapseList) - ScenarioQueueFrame_Update(); -end - -function ScenarioQueueFrameChoiceButton_OnEnter(self) - LFGDungeonListButton_OnEnter(self, YOU_MAY_NOT_QUEUE_FOR_SCENARIO); -end - -function ScenarioQueueFrame_OnLoad(self) - self.Dropdown:SetWidth(180); -end - -function ScenarioQueueFrame_OnShow(self) - PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN); - QueueUpdater:RequestInfo(); - QueueUpdater:AddRef(); - - local function IsSelected(dungeonID) - return ScenarioQueueFrame.type == dungeonID; - end - - local function SetSelected(dungeonID) - ScenarioQueueFrame_SetTypeInternal(dungeonID); - end - - self.Dropdown:SetupMenu(function(dropdown, rootDescription) - rootDescription:SetTag("MENU_SCENARIO_FINDER"); - - rootDescription:CreateRadio(SPECIFIC_SCENARIOS, IsSelected, SetSelected, "specific"); - - for i=1, GetNumRandomScenarios() do - local dungeonID, name = GetRandomScenarioInfo(i); - local isAvailableForAll, isAvailableForPlayer = IsLFGDungeonJoinable(dungeonID); - if isAvailableForPlayer then - if isAvailableForAll then - rootDescription:CreateRadio(name, IsSelected, SetSelected, dungeonID); - else - local radio = rootDescription:CreateRadio(name, IsSelected, SetSelected, dungeonID); - radio:SetEnabled(false); - radio:SetTooltip(function(tooltip, description) - GameTooltip_SetTitle(tooltip, YOU_MAY_NOT_QUEUE_FOR_THIS); - GameTooltip_AddErrorLine(tooltip, LFGConstructDeclinedMessage(dungeonID)); - end); - end - end - end - end); -end - -function ScenarioQueueFrame_SetTypeInternal(value) - ScenarioQueueFrame.type = value; - - if ( value == "specific" ) then - ScenarioQueueFrame_SetTypeSpecific(); - else - ScenarioQueueFrame_SetTypeRandom(); - ScenarioQueueFrameRandom_UpdateFrame(); - end - ScenarioQueueFrameFindGroupButton_Update(); -end - -function ScenarioQueueFrame_SetType(value) --"specific" for the list or the record id for a single dungeon - ScenarioQueueFrame_SetTypeInternal(value); - ScenarioQueueFrame.Dropdown:GenerateMenu(); -end - -function ScenarioQueueFrame_SetTypeRandom() - local queueFrame = ScenarioQueueFrame; - queueFrame.Bg:ClearAllPoints(); - queueFrame.Bg:SetPoint("TOPLEFT", 5, -77); - queueFrame.Bg:SetPoint("BOTTOMRIGHT", 175, -155); - queueFrame.Specific:Hide(); - queueFrame.Random:Show(); - LFGCooldownCover_ChangeSettings(ScenarioQueueFrame.CooldownFrame, true, true); -end - -function ScenarioQueueFrame_SetTypeSpecific() - local queueFrame = ScenarioQueueFrame; - queueFrame.Bg:SetTexture("Interface\\LFGFrame\\UI-LFG-BACKGROUND-DUNGEONWALL"); - queueFrame.Bg:ClearAllPoints(); - queueFrame.Bg:SetPoint("TOPLEFT", 5, -75); - queueFrame.Bg:SetPoint("BOTTOMRIGHT", 175, 29); - queueFrame.Random:Hide(); - queueFrame.Specific:Show(); - LFGCooldownCover_ChangeSettings(ScenarioQueueFrame.CooldownFrame, true, false); -end diff --git a/WoW-API/_UI/Blizzard_ObjectAPI/Item.lua b/WoW-API/_UI/Blizzard_ObjectAPI/Item.lua index 0ea2912..c7c972f 100644 --- a/WoW-API/_UI/Blizzard_ObjectAPI/Item.lua +++ b/WoW-API/_UI/Blizzard_ObjectAPI/Item.lua @@ -5,6 +5,7 @@ ---@class Item Item = {}; ---@class ItemMixin +---[Documentation](https://warcraft.wiki.gg/wiki/ItemMixin) ItemMixin = {}; local ItemEventListener; diff --git a/WoW-API/_UI/Blizzard_ObjectAPI/ItemLocation.lua b/WoW-API/_UI/Blizzard_ObjectAPI/ItemLocation.lua index e391057..458dc21 100644 --- a/WoW-API/_UI/Blizzard_ObjectAPI/ItemLocation.lua +++ b/WoW-API/_UI/Blizzard_ObjectAPI/ItemLocation.lua @@ -5,6 +5,7 @@ ---@class ItemLocation ItemLocation = {}; ---@class ItemLocationMixin +---[Documentation](https://warcraft.wiki.gg/wiki/ItemLocationMixin) ItemLocationMixin = {}; ---@return ItemLocation diff --git a/WoW-API/_UI/Blizzard_ObjectAPI/PlayerLocation.lua b/WoW-API/_UI/Blizzard_ObjectAPI/PlayerLocation.lua index c678b9e..c314558 100644 --- a/WoW-API/_UI/Blizzard_ObjectAPI/PlayerLocation.lua +++ b/WoW-API/_UI/Blizzard_ObjectAPI/PlayerLocation.lua @@ -5,6 +5,7 @@ ---@class PlayerLocation PlayerLocation = {}; ---@class PlayerLocationMixin +---[Documentation](https://warcraft.wiki.gg/wiki/PlayerLocationMixin) PlayerLocationMixin = {}; ---@param guid string diff --git a/WoW-API/_UI/Blizzard_ObjectAPI/Spell.lua b/WoW-API/_UI/Blizzard_ObjectAPI/Spell.lua index aa29568..f9baa78 100644 --- a/WoW-API/_UI/Blizzard_ObjectAPI/Spell.lua +++ b/WoW-API/_UI/Blizzard_ObjectAPI/Spell.lua @@ -5,6 +5,7 @@ ---@class Spell Spell = {}; ---@class SpellMixin +---[Documentation](https://warcraft.wiki.gg/wiki/SpellMixin) SpellMixin = {}; local SpellEventListener; diff --git a/WoW-API/_UI/Blizzard_SharedXML/Vector2D.lua b/WoW-API/_UI/Blizzard_SharedXML/Vector2D.lua index a195d92..82020da 100644 --- a/WoW-API/_UI/Blizzard_SharedXML/Vector2D.lua +++ b/WoW-API/_UI/Blizzard_SharedXML/Vector2D.lua @@ -55,6 +55,7 @@ function Vector2D_RotateDirection(rotationRadians, x, y) end ---@class Vector2DMixin +---[FrameXML](https://www.townlong-yak.com/framexml/go/Vector2DMixin) Vector2DMixin = {}; ---[FrameXML](https://www.townlong-yak.com/framexml/go/CreateVector2D) diff --git a/WoW-API/_UI/Blizzard_SharedXML/Vector3D.lua b/WoW-API/_UI/Blizzard_SharedXML/Vector3D.lua index 6eb12b5..d98f66a 100644 --- a/WoW-API/_UI/Blizzard_SharedXML/Vector3D.lua +++ b/WoW-API/_UI/Blizzard_SharedXML/Vector3D.lua @@ -93,6 +93,7 @@ function Vector3D_CreateNormalVectorFromYawPitch(yawRadians, pitchRadians) end ---@class Vector3DMixin +---[FrameXML](https://www.townlong-yak.com/framexml/go/Vector3DMixin) Vector3DMixin = {}; ---[FrameXML](https://www.townlong-yak.com/framexml/go/CreateVector3D) diff --git a/WoW-API/_UI/Blizzard_SharedXMLBase/Color.lua b/WoW-API/_UI/Blizzard_SharedXMLBase/Color.lua index e9e8274..e2cbd27 100644 --- a/WoW-API/_UI/Blizzard_SharedXMLBase/Color.lua +++ b/WoW-API/_UI/Blizzard_SharedXMLBase/Color.lua @@ -3,6 +3,7 @@ ---@meta _ ---@class ColorMixin +---[FrameXML](https://www.townlong-yak.com/framexml/go/ColorMixin) ColorMixin = {}; ---[FrameXML](https://www.townlong-yak.com/framexml/go/CreateColor) diff --git a/WoW-API/_UI/Blizzard_SharedXMLGame/Tooltip/TooltipDataHandler.lua b/WoW-API/_UI/Blizzard_SharedXMLGame/Tooltip/TooltipDataHandler.lua deleted file mode 100644 index 09fe5ad..0000000 --- a/WoW-API/_UI/Blizzard_SharedXMLGame/Tooltip/TooltipDataHandler.lua +++ /dev/null @@ -1,547 +0,0 @@ --- Auto-generated LuaLS Annotations, do not edit manually ----@meta _ - --- ======================================================================= --- Tooltip data callback processor --- ======================================================================= - -local issecure = issecure; -local forceinsecure = forceinsecure; - ----@class SecureTooltipPreCalls -local SecureTooltipPreCalls = { }; ----@class SecureTooltipPostCalls -local SecureTooltipPostCalls = { }; ----@class SecureLinePreCalls -local SecureLinePreCalls = { }; ----@class SecureLinePostCalls -local SecureLinePostCalls = { }; - ----@class InsecureTooltipPreCalls -local InsecureTooltipPreCalls = { }; ----@class InsecureTooltipPostCalls -local InsecureTooltipPostCalls = { }; ----@class InsecureLinePreCalls -local InsecureLinePreCalls = { }; ----@class InsecureLinePostCalls -local InsecureLinePostCalls = { }; - -local secureTables = { - tooltipPreCall = SecureTooltipPreCalls, - tooltipPostCall = SecureTooltipPostCalls, - linePreCall = SecureLinePreCalls, - linePostCall = SecureLinePostCalls, -}; - -local insecureTables = { - tooltipPreCall = InsecureTooltipPreCalls, - tooltipPostCall = InsecureTooltipPostCalls, - linePreCall = InsecureLinePreCalls, - linePostCall = InsecureLinePostCalls, -}; - -local function InternalAddCall(tbl, keyType, func) - if not keyType then - return; - end - local calls = tbl[keyType]; - if not calls then - tbl[keyType] = { }; - calls = tbl[keyType]; - end - table.insert(calls, func); -end - -local function MakeSecureCalls(funcTbl, canTerminate, ...) - if not funcTbl then - return; - end - for i, func in ipairs(funcTbl) do - if func(...) and canTerminate then - return true; - end - end -end - -local function MakeInsecureCalls(funcTbl, canTerminate, ...) - if not funcTbl then - return; - end - for i, func in ipairs(funcTbl) do - local result = securecallfunction(func, ...); - if result and canTerminate then - return true; - end - end -end - -local function ProcessSecureCalls(tbl, canTerminate, keyType, ...) - if MakeSecureCalls(tbl[TooltipDataProcessor.AllTypes], canTerminate, ...) and canTerminate then - return true; - end - if MakeSecureCalls(tbl[keyType], canTerminate, ...) and canTerminate then - return true; - end -end - -local function ProcessInsecureCalls(tbl, canTerminate, keyType, ...) - if MakeInsecureCalls(tbl[TooltipDataProcessor.AllTypes], canTerminate, ...) and canTerminate then - return true; - end - if MakeInsecureCalls(tbl[keyType], canTerminate, ...) and canTerminate then - return true; - end -end - -local InsertCallbackAttributes = { - [InsecureTooltipPreCalls] = "insert-tooltip-pre-call", - [InsecureTooltipPostCalls] = "insert-tooltip-post-call", - [InsecureLinePreCalls] = "insert-line-pre-call", - [InsecureLinePostCalls] = "insert-line-post-call", -}; - -local InsertCallbackTables = tInvert(InsertCallbackAttributes); - -local ProcessCallbackAttributes = { - [InsecureTooltipPreCalls] = "process-tooltip-pre-call", - [InsecureTooltipPostCalls] = "process-tooltip-post-call", - [InsecureLinePreCalls] = "process-line-pre-call", - [InsecureLinePostCalls] = "process-line-post-call", -}; - -local ProcessCallbackTables = tInvert(ProcessCallbackAttributes); -local ProcessCallbackResultAttribute = "process-callback-result"; - -local AttributeDelegate = CreateFrame("FRAME"); -AttributeDelegate:SetForbidden(); -AttributeDelegate:SetScript("OnAttributeChanged", function(self, attribute, value) - local callTable = InsertCallbackTables[attribute]; - if callTable then - local keyType, func = securecallfunction(unpack, value); - InternalAddCall(callTable, keyType, func); - end - - local processTable = ProcessCallbackTables[attribute]; - if processTable then - local argCount = securecallfunction(rawget, value, "n"); - AttributeDelegate:SetAttribute(ProcessCallbackResultAttribute, ProcessInsecureCalls(processTable, securecallfunction(unpack, value, 1, argCount))); - end -end); - -local CAN_TERMINATE = true; - -local function ProcessTooltipPreCalls(tooltipType, ...) - local result = ProcessSecureCalls(SecureTooltipPreCalls, CAN_TERMINATE, tooltipType, ...); - if result then - return result; - end - - if next(InsecureTooltipPreCalls) then - AttributeDelegate:SetAttribute(ProcessCallbackAttributes[InsecureTooltipPreCalls], SafePack(CAN_TERMINATE, tooltipType, ...)); - return AttributeDelegate:GetAttribute(ProcessCallbackResultAttribute); - end -end - -local function ProcessTooltipPostCalls(tooltipType, ...) - local result = ProcessSecureCalls(SecureTooltipPostCalls, not CAN_TERMINATE, tooltipType, ...); - if result then - return result; - end - - if next(InsecureTooltipPostCalls) then - AttributeDelegate:SetAttribute(ProcessCallbackAttributes[InsecureTooltipPostCalls], SafePack(not CAN_TERMINATE, tooltipType, ...)); - return AttributeDelegate:GetAttribute(ProcessCallbackResultAttribute); - end -end - -local function ProcessLinePreCalls(lineType, ...) - local result = ProcessSecureCalls(SecureLinePreCalls, CAN_TERMINATE, lineType, ...); - if result then - return result; - end - - if next(InsecureLinePreCalls) then - AttributeDelegate:SetAttribute(ProcessCallbackAttributes[InsecureLinePreCalls], SafePack(CAN_TERMINATE, lineType, ...)); - return AttributeDelegate:GetAttribute(ProcessCallbackResultAttribute); - end -end - -local function ProcessLinePostCalls(lineType, ...) - local result = ProcessSecureCalls(SecureLinePostCalls, not CAN_TERMINATE, lineType, ...); - if result then - return result; - end - - if next(InsecureLinePostCalls) then - AttributeDelegate:SetAttribute(ProcessCallbackAttributes[InsecureLinePostCalls], SafePack(not CAN_TERMINATE, lineType, ...)); - return AttributeDelegate:GetAttribute(ProcessCallbackResultAttribute); - end -end - ----@class TooltipDataProcessor -TooltipDataProcessor = { - AllTypes = "ALL"; -}; - -local function AddCall(callType, keyType, func) - if issecure() then - local tbl = secureTables[callType]; - InternalAddCall(tbl, keyType, func); - else - local tbl = insecureTables[callType]; - local function InsecureCallback(...) - forceinsecure(); - return func(...); - end - AttributeDelegate:SetAttribute(InsertCallbackAttributes[tbl], { keyType, InsecureCallback }); - end -end - -function TooltipDataProcessor.AddTooltipPreCall(tooltipType, func) - AddCall("tooltipPreCall", tooltipType, func); -end - -function TooltipDataProcessor.AddTooltipPostCall(tooltipType, func) - AddCall("tooltipPostCall", tooltipType, func); -end - -function TooltipDataProcessor.AddLinePreCall(lineType, func) - AddCall("linePreCall", lineType, func); -end - -function TooltipDataProcessor.AddLinePostCall(lineType, func) - AddCall("linePostCall", lineType, func); -end - --- ======================================================================= --- Tooltip data parser that should be mixed in by any tooltip that wants :SetX functionality --- ======================================================================= - ---[[ info table layout - getterName : If tooltipData is not set, the C_TooltipInfo function to call. The data returned will be set as tooltipData in this table. - getterArgs : Optional table of arguments for the C_TooltipInfo call. - tooltipData : In some places code already has this data, so it can set this key and leave the getterName nil. - append : If true, the tooltip will not be cleared and the backdrop style (Azerite and Corrupted) will not be set. - appendSpacer : If true and append is true, will add a blank line before appending - compareItem : If true, an item comparison will start automatically. - excludeLines : Table of line types to exclude from the tooltip. - linePreCall : Callback for each line before it's added. - linePostCall : Callback for each line after it's added. - tooltipPostCall : Callback for the tooltip after it has processed the info. - rebuildPreCall : Callback before the tooltip is rebuilt from a TOOLTIP_DATA_UPDATE. Only checked for primary info in the case of multiple. - rebuildPostCall : Callback after the tooltip is rebuilt from a TOOLTIP_DATA_UPDATE. Only checked for primary info in the case of multiple. -]]-- - -function CreateBaseTooltipInfo(getterName, ...) - local tooltipInfo = { - getterName = getterName, - getterArgs = { ... }; - }; - return tooltipInfo; -end - ----@class TooltipDataHandlerMixin -TooltipDataHandlerMixin = { }; - -function TooltipDataHandlerMixin:ProcessInfo(info) - return securecallfunction(self.InternalProcessInfo, self, info); -end - -function TooltipDataHandlerMixin:InternalProcessInfo(info) - if not info then - return false; - end - - if not info.tooltipData then - if not info.getterName then - return false; - end - if info.getterArgs then - info.tooltipData = C_TooltipInfo[info.getterName](unpack(info.getterArgs)); - else - info.tooltipData = C_TooltipInfo[info.getterName](); - end - end - - local tooltipData = info.tooltipData; - if not tooltipData then - if not info.append then - self:Hide(); - end - return false; - end - - if not info.append then - self.infoList = { }; - self:ClearLines(); - elseif not self.infoList then - -- infoList will be missing in append mode if the tooltip needs to start with non-data text - self.infoList = { }; - end - - table.insert(self.infoList, info); - self.processingInfo = info; - - local tooltipType = tooltipData.type; - if ProcessTooltipPreCalls(tooltipType, self, tooltipData) then - return false; - end - - if info.append and info.appendSpacer then - GameTooltip_AddBlankLineToTooltip(self); - end - - self:ProcessLines(); - - if self.processingInfo.tooltipPostCall then - self.processingInfo.tooltipPostCall(self); - end - - ProcessTooltipPostCalls(tooltipType, self, tooltipData); - - self:Show(); - - if not info.append and info.backdropStyle then - SharedTooltip_SetBackdropStyle(self, info.backdropStyle); - end - - return true; -end - -function TooltipDataHandlerMixin:ProcessLines() - local info = self.processingInfo; - local excludeLines = info.excludeLines; - local linePreCall = info.linePreCall; - local linePostCall = info.linePostCall; - for i, lineData in ipairs(info.tooltipData.lines) do - self:ProcessLineData(lineData, excludeLines, linePreCall, linePostCall); - end -end - -function TooltipDataHandlerMixin:ProcessLineData(lineData, excludeLines, linePreCall, linePostCall) - local lineConsumed = excludeLines and tContains(excludeLines, lineData.type) or false; - if not lineConsumed and linePreCall then - lineConsumed = linePreCall(self, lineData); - end - if not lineConsumed then - lineConsumed = ProcessLinePreCalls(lineData.type, self, lineData); - end - - if not lineConsumed then - self:AddLineDataText(lineData); - lineData.lineIndex = self:NumLines(); - if linePostCall then - linePostCall(self, lineData); - end - ProcessLinePostCalls(lineData.type, self, lineData); - end -end - -function TooltipDataHandlerMixin:AddLineDataText(lineData) - local leftText = lineData.leftText; - local leftColor = lineData.leftColor or NORMAL_FONT_COLOR; - local wrapText = lineData.wrapText or false; - local rightText = lineData.rightText; - local leftOffset = lineData.leftOffset; - if rightText then - local rightColor = lineData.rightColor or NORMAL_FONT_COLOR; - GameTooltip_AddColoredDoubleLine(self, leftText, rightText, leftColor, rightColor, wrapText, leftOffset); - elseif leftText then - GameTooltip_AddColoredLine(self, leftText, leftColor, wrapText, leftOffset); - end -end - - -function TooltipDataHandlerMixin:ClearHandlerInfo() - self.infoList = nil; - self.processingInfo = nil; -end - -function TooltipDataHandlerMixin:RebuildFromTooltipInfo() - local oldPrimaryInfo = self:GetPrimaryTooltipInfo(); - if not oldPrimaryInfo then - return; - end - - local infoList = self.infoList; - self.infoList = { }; - - if oldPrimaryInfo.rebuildPreCall then - local skipRebuild = oldPrimaryInfo.rebuildPreCall(self); - if skipRebuild then - return; - end - end - - for i, info in ipairs(infoList) do - -- Remove cached data if there's a getter, otherwise assume that data is complete - if info.getterName then - info.tooltipData = nil; - end - -- It's bad if append is set for the primary info and the rebuild wasn't handled by the rebuildPreCall - -- Usually that mean the tooltip was started with AddLine instead of SetX - -- Clear it out so at least the tooltip doesn't duplicate - if i == 1 then - info.append = false; - end - self:ProcessInfo(info); - end - - if oldPrimaryInfo.rebuildPostCall then - oldPrimaryInfo.rebuildPostCall(self); - end -end - -function TooltipDataHandlerMixin:GetPrimaryTooltipInfo() - return self.infoList and self.infoList[1]; -end - -function TooltipDataHandlerMixin:GetProcessingTooltipInfo() - return self.processingInfo; -end - -function TooltipDataHandlerMixin:SetInfoBackdropStyle(backdropStyle) - local info = self:GetPrimaryTooltipInfo(); - if info then - info.backdropStyle = backdropStyle; - end -end - -function TooltipDataHandlerMixin:GetPrimaryTooltipData() - local info = self:GetPrimaryTooltipInfo(); - return info and info.tooltipData; -end - --- to be deprecated -function TooltipDataHandlerMixin:GetTooltipData() - return self:GetPrimaryTooltipData(); -end - -function TooltipDataHandlerMixin:IsTooltipType(tooltipType) - local primaryInfo = self:GetPrimaryTooltipInfo(); - return primaryInfo and primaryInfo.tooltipData and primaryInfo.tooltipData.type == tooltipType; -end - -function TooltipDataHandlerMixin:HasDataInstanceID(dataInstanceID) - if self.infoList then - for i, info in ipairs(self.infoList) do - if info.tooltipData and info.tooltipData.dataInstanceID == dataInstanceID then - return true; - end - end - end - return false; -end - -function TooltipDataHandlerMixin:AppendInfo(...) - local tooltipInfo = CreateBaseTooltipInfo(...); - tooltipInfo.append = true; - self:ProcessInfo(tooltipInfo); -end - -function TooltipDataHandlerMixin:AppendInfoWithSpacer(...) - local tooltipInfo = CreateBaseTooltipInfo(...); - tooltipInfo.append = true; - tooltipInfo.appendSpacer = true; - self:ProcessInfo(tooltipInfo); -end - -function AddTooltipDataAccessor(handler, accessor, getterName) - handler[accessor] = function(self, ...) - local tooltipInfo = { - getterName = getterName, - getterArgs = { ... }; - }; - return self:ProcessInfo(tooltipInfo); - end -end - -do - local accessors = { - SetMerchantItem = "GetMerchantItem", - SetCurrencyToken = "GetCurrencyToken", - SetItemByID = "GetItemByID", - SetItemByItemModifiedAppearanceID = "GetItemByItemModifiedAppearanceID", - SetInventoryItem = "GetInventoryItem", - SetRecipeReagentItem = "GetRecipeReagentItem", - SetWeeklyReward = "GetWeeklyReward", - SetInboxItem = "GetInboxItem", - SetSendMailItem = "GetSendMailItem", - SetTradePlayerItem = "GetTradePlayerItem", - SetTradeTargetItem = "GetTradeTargetItem", - SetQuestItem = "GetQuestItem", - SetQuestLogItem = "GetQuestLogItem", - SetQuestLogSpecialItem = "GetQuestLogSpecialItem", - SetLootItem = "GetLootItem", - SetLootRollItem = "GetLootRollItem", - SetGuildBankItem = "GetGuildBankItem", - SetHeirloomByItemID = "GetHeirloomByItemID", - SetRuneforgeResultItem = "GetRuneforgeResultItem", - SetTransmogrifyItem = "GetTransmogrifyItem", - SetArtifactItem = "GetArtifactItem", - SetBagItem = "GetBagItem", - SetBagItemChild = "GetBagItemChild", - SetBuybackItem = "GetBuybackItem", - SetExistingSocketGem = "GetExistingSocketGem", - SetInventoryItemByID = "GetInventoryItemByID", - SetItemKey = "GetItemKey", - SetLFGDungeonReward = "GetLFGDungeonReward", - SetLFGDungeonShortageReward = "GetLFGDungeonShortageReward", - SetSocketGem = "GetSocketGem", - SetSocketedItem = "GetSocketedItem", - SetSocketedRelic = "GetSocketedRelic", - SetUpgradeItem = "GetUpgradeItem", - SetBackpackToken = "GetBackpackToken", - SetCurrencyByID = "GetCurrencyByID", - SetLootCurrency = "GetLootCurrency", - SetQuestCurrency = "GetQuestCurrency", - SetQuestLogCurrency = "GetQuestLogCurrency", - SetSpellByID = "GetSpellByID", - SetArtifactPowerByID = "GetArtifactPowerByID", - SetShapeshift = "GetShapeshift", - SetAzeritePower = "GetAzeritePower", - SetAzeriteEssence = "GetAzeriteEssence", - SetAzeriteEssenceSlot = "GetAzeriteEssenceSlot", - SetTalent = "GetTalent", - SetPvpTalent = "GetPvpTalent", - SetMountBySpellID = "GetMountBySpellID", - SetPetAction = "GetPetAction", - SetConduit = "GetConduit", - SetCompanionPet = "GetCompanionPet", - SetPossession = "GetPossession", - SetAchievementByID = "GetAchievementByID", - SetEnhancedConduit = "GetEnhancedConduit", - SetEquipmentSet = "GetEquipmentSet", - SetInstanceLockEncountersComplete = "GetInstanceLockEncountersComplete", - SetPvpBrawl = "GetPvpBrawl", - SetRecipeRankInfo = "GetRecipeRankInfo", - SetTotem = "GetTotem", - SetToyByItemID = "GetToyByItemID", - SetMerchantCostItem = "GetMerchantCostItem", - SetUnit = "GetUnit", - SetTrainerService = "GetTrainerService", - SetRecipeResultItem = "GetRecipeResultItem", - SetRecipeResultItemForOrder = "GetRecipeResultItemForOrder", - SetAction = "GetAction", - SetSpellBookItem = "GetSpellBookItem", - SetOwnedItemByID = "GetOwnedItemByID", - SetQuestPartyProgress = "GetQuestPartyProgress", - SetHyperlink = "GetHyperlink", - SetUnitAura = "GetUnitAura", - SetUnitBuff = "GetUnitBuff", - SetUnitDebuff = "GetUnitDebuff", - SetMinimapMouseover = "GetMinimapMouseover", - SetUnitBuffByAuraInstanceID = "GetUnitBuffByAuraInstanceID", - SetUnitDebuffByAuraInstanceID = "GetUnitDebuffByAuraInstanceID", - SetTraitEntry = "GetTraitEntry", - SetSlottedKeystone = "GetSlottedKeystone", - SetItemInteractionItem = "GetItemInteractionItem", - SetItemByGUID = "GetItemByGUID", - SetWorldLootObject = "GetWorldLootObject", - }; - - local handler = TooltipDataHandlerMixin; - for accessor, getterName in pairs(accessors) do - AddTooltipDataAccessor(handler, accessor, getterName); - end -end \ No newline at end of file diff --git a/generator/AGENTS.md b/generator/AGENTS.md new file mode 100644 index 0000000..6e31c39 --- /dev/null +++ b/generator/AGENTS.md @@ -0,0 +1,78 @@ +# Agent Handover: WoW API Generator + +This document serves as a context dump for AI agents working on the WoW API Generator project. It outlines the architecture, design decisions, and specific behaviors of the tooling. + +## Project Purpose +To create a high-quality Lua Language Server (LuaLS) workspace for World of Warcraft UI addon development. +We combine: +1. **Blizzard's Actual Source Code**: (sourced from `BigWigsMods/WoWUI`) - Provides the *implementation* and truth. +2. **Community Annotations**: (sourced from `Ketho/vscode-wow-api`) - Provides the *types* and documentation (`---@param`, `---@return`). + +The goal is to merge these into a single "API" folder where the real code is annotated with the docs, eliminating "duplicate definition" errors while maximizing Intellisense. + +## Directory Structure & Terminology + +### Root Layout +- `generator/`: Contains all tooling scripts. +- `generator/API-/`: The output folder (e.g., `API-Vanilla`, `API-Wrath`). + +### Key Concepts for `inject_annotations.py` + +* **"Source" (Definitions)**: + * **Path**: `API-/FrameXML` (and subfolders). + * **Origin**: Copied from `vscode-wow-api`. + * **Content**: `.lua` files containing `---@class`, `---@param` tags, usually describing global functions or Mixins. The function bodies are often empty stubs (`function Foo() end`). + * **Role**: The *donor* of documentation. + +* **"Target" (Implementation)**: + * **Path**: `API-/_UI` (and subfolders). + * **Origin**: Extracted from `WoWUI/Interface`. + * **Content**: Real `.lua` files (`Blizzard_ActionBar`, `Blizzard_UnitFrame`, etc.). Function signatures often use `self` instead of explicit names. + * **Role**: The *recipient* of documentation. This is the code we want to preserve. + +## Core Workflows + +### 1. Generation (`WoWUI-generator.py`) +This script initializes the workspace. It parses `.toc` files to understand which Blizzard source files belong to the current version and copies them into the `_UI` structure. + +### 2. Injection & Cleanup (`inject_annotations.py`) +This script performs post-processing to merge the documentation. + +**Design Philosophy: "Inject then Delete"** +We chose to inject annotations into the Target (Implementation) and then **delete the matching definitions from the Source**. +* *Why?* If we keep `FrameXML/Foo.lua` (stub) and `_UI/Foo.lua` (implementation), LuaLS reports "Duplicate Definition". Removing the stub forces the IDE to rely on the single, now-annotated implementation file. + +**Key Logic:** + +1. **Parsing**: Scans "Source" for contiguous annotation blocks preceding `function` definitions or `Mixin = {}` tables. +2. **Function Injection**: + * Finds the matching function in "Target". + * **Smart Parameter Matching**: + * *Problem*: Source doc has `@param button`, Target code has `function(self)`. + * *Solution*: The script compares param counts. If they match but names differ, it rewrites the annotation to `@param self` and appends `-- button` as a comment. This solves "undefined param" diagnostics. + * **Prefix Cleaning**: Handles and strips Blizzard-specific prefixes like `--[[static]]` to ensure clean Lua syntax. +3. **Mixin Injection**: + * Finds matching Global Tables / Mixins. + * **Filtering**: Explicitly strips `---@meta` and `---@class` tags during injection. We assume class definitions are handled by `ManualTypes` or global generation; we only want the field/method docs injected. + * **Skip Patterns**: Checks `inject_mixin_skip.py` to skip specific lines (e.g., fields that collide with implementation details). +4. **Source Cleanup**: + * If a function/mixin is successfully matched in Target, it is removed from Source. + * **Multi-line Removal**: The script is smart enough to remove `function ... end` blocks, not just single lines. + * **Whitespace**: It collapses multiple blank lines left behind by deletions. + * **Empty Files**: If a Source file is left with only whitespace or `---@meta` tags, the file is deleted entirely. + +## Configuration + +* **`inject_mixin_skip.py`**: + * Contains `MIXIN_SKIP_PATTERNS`: Regex patterns to exclude specific lines when injecting into Mixins. + * Contains `FUNCTION_SKIP_PATTERNS`: Regex patterns to exclude specific lines when injecting into Functions. + +## Future Agent Instructions + +If you need to modify this process: +1. **New Skip Rules**: Add regexes to `inject_mixin_skip.py`. Do not hardcode them in the main script. +2. **Debugging Injection**: Use the `--dry-run` flag. It provides detailed output including "Param mismatch fixing" and "Stripping prefix" events. + ```bash + python3 inject_annotations.py --dry-run + ``` +3. **Parsing Edge Cases**: If Blizzard adds new prefixes (e.g., `--[[private]]`), update the `prefix_regex` in `inject_annotations.py`. diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_0_0.lua b/generator/Deprecated/Deprecated_10_0_0.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_0_0.lua rename to generator/Deprecated/Deprecated_10_0_0.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_1_0.lua b/generator/Deprecated/Deprecated_10_1_0.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_1_0.lua rename to generator/Deprecated/Deprecated_10_1_0.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_1_5.lua b/generator/Deprecated/Deprecated_10_1_5.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_1_5.lua rename to generator/Deprecated/Deprecated_10_1_5.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_0.lua b/generator/Deprecated/Deprecated_10_2_0.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_0.lua rename to generator/Deprecated/Deprecated_10_2_0.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_5.lua b/generator/Deprecated/Deprecated_10_2_5.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_5.lua rename to generator/Deprecated/Deprecated_10_2_5.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_6.lua b/generator/Deprecated/Deprecated_10_2_6.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_6.lua rename to generator/Deprecated/Deprecated_10_2_6.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_7.lua b/generator/Deprecated/Deprecated_10_2_7.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_10_2_7.lua rename to generator/Deprecated/Deprecated_10_2_7.lua diff --git a/WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_11_0_0.lua b/generator/Deprecated/Deprecated_11_0_0.lua similarity index 100% rename from WoW-API/FrameXML/Blizzard_Deprecated/Deprecated_11_0_0.lua rename to generator/Deprecated/Deprecated_11_0_0.lua diff --git a/generator/ManualTypes/DropdownButton.lua b/generator/Manual/Types/DropdownButton.lua similarity index 100% rename from generator/ManualTypes/DropdownButton.lua rename to generator/Manual/Types/DropdownButton.lua diff --git a/generator/ManualTypes/EngravingData.lua b/generator/Manual/Types/EngravingData.lua similarity index 100% rename from generator/ManualTypes/EngravingData.lua rename to generator/Manual/Types/EngravingData.lua diff --git a/generator/ManualTypes/README.md b/generator/Manual/Types/README.md similarity index 100% rename from generator/ManualTypes/README.md rename to generator/Manual/Types/README.md diff --git a/generator/ManualTypes/ReforgeStatsInfo.lua b/generator/Manual/Types/ReforgeStatsInfo.lua similarity index 100% rename from generator/ManualTypes/ReforgeStatsInfo.lua rename to generator/Manual/Types/ReforgeStatsInfo.lua diff --git a/generator/ManualTypes/TextureWithStateVisualizationInfo.lua b/generator/Manual/Types/TextureWithStateVisualizationInfo.lua similarity index 100% rename from generator/ManualTypes/TextureWithStateVisualizationInfo.lua rename to generator/Manual/Types/TextureWithStateVisualizationInfo.lua diff --git a/generator/ManualTypes/UndefinedMixins.lua b/generator/Manual/Types/UndefinedMixins.lua similarity index 100% rename from generator/ManualTypes/UndefinedMixins.lua rename to generator/Manual/Types/UndefinedMixins.lua diff --git a/generator/ManualTypes/dstReforgeStats.lua b/generator/Manual/Types/dstReforgeStats.lua similarity index 100% rename from generator/ManualTypes/dstReforgeStats.lua rename to generator/Manual/Types/dstReforgeStats.lua diff --git a/generator/WoWUI-generator.py b/generator/WoWUI-generator.py index 952f965..f9e7df9 100644 --- a/generator/WoWUI-generator.py +++ b/generator/WoWUI-generator.py @@ -481,6 +481,56 @@ def get_git_branch(repo_path): return "Unknown" +def ensure_meta_tag(directory): + print(f"\nEnsuring ---@meta tags in {directory}") + for root, dirs, files in os.walk(directory): + for file in files: + if not file.lower().endswith(".lua"): + continue + + path = os.path.join(root, file) + try: + with open(path, "r", encoding="utf-8") as f: + lines = f.readlines() + except Exception as e: + print(f"Error reading {path}: {e}") + continue + + # Check for existing meta tag in first 5 lines + meta_index = -1 + for i in range(min(5, len(lines))): + if lines[i].startswith("---@meta"): + meta_index = i + break + + modified = False + + if meta_index != -1: + # Meta tag found + if meta_index + 1 < len(lines): + if lines[meta_index + 1].strip(): + lines.insert(meta_index + 1, "\n") + modified = True + else: + # It is the last line. + if not lines[meta_index].endswith("\n"): + lines[meta_index] += "\n" + lines.append("\n") + modified = True + else: + # Meta tag not found + lines.insert(0, "---@meta _\n") + lines.insert(1, "\n") + modified = True + + if modified: + try: + with open(path, "w", encoding="utf-8") as f: + f.writelines(lines) + except Exception as e: + print(f"Error writing {path}: {e}") + + def main(): parser = argparse.ArgumentParser( description="Recreate a copy of the WoWUI folder structure containing only files " @@ -605,15 +655,15 @@ def main(): dest = os.path.join(dest_version, "Functions-AI") shutil.copytree(dest_functions, dest, dirs_exist_ok=True) - # Copy ManualTypes folder - print("\nCopying ManualTypes folder into API folder") - src_manual_types = os.path.join(".", "ManualTypes") - dest_manual_types = os.path.join(dest_version, "ManualTypes") - if os.path.isdir(src_manual_types): - shutil.copytree(src_manual_types, dest_manual_types, dirs_exist_ok=True) - print(f"Copied ManualTypes folder: {src_manual_types} -> {dest_manual_types}") + # Copy Manual folder + print("\nCopying Manual folder into API folder") + src_manual = os.path.join(".", "Manual") + dest_manual = os.path.join(dest_version, "Manual") + if os.path.isdir(src_manual): + shutil.copytree(src_manual, dest_manual, dirs_exist_ok=True) + print(f"Copied Manual folder: {src_manual} -> {dest_manual}") else: - print(f"ManualTypes source folder {src_manual_types} not found.") + print(f"Manual source folder {src_manual} not found.") # Create .vscode/settings.json in the output directory print("\nCreating .vscode/settings.json in output directory") @@ -638,10 +688,14 @@ def main(): // Due to the merge nature of this there are some duplication issues. "duplicate-doc-field", "duplicate-doc-alias", + // Some string concatenations are done in a way that confuses the type checker. + "ambiguity-1", // Not all type annotations are accurate in the WoW API, so we disable these type mismatch warnings. "return-type-mismatch", // Not all type annotations are accurate in the WoW API, so we disable these type mismatch warnings. "param-type-mismatch", + // The Lua checker sometimes gets a number assignment but somewhere else it gets assigned nil. + "assign-type-mismatch", // Because we add casts after the fact to satisfy the type checker, we disable this warning. "cast-local-type", // Classes do not like injecting fields but that requires refactoring which we can't do. @@ -680,6 +734,8 @@ def main(): f.write(commit_hashes_content) print(f"Created COMMIT_HASHES.md: {commit_hashes_path}") + ensure_meta_tag(dest_version) + if __name__ == "__main__": main() diff --git a/generator/WoWUI.md b/generator/WoWUI.md new file mode 100644 index 0000000..20ba0aa --- /dev/null +++ b/generator/WoWUI.md @@ -0,0 +1,72 @@ +# WoW UI Generator + +This directory contains the tools necessary to generate the `API-` folder, which provides Lua Language Server (LuaLS) annotations and source files for World of Warcraft UI development. + +## Overview + +The generator combines official Blizzard UI source code, community-maintained annotations, and manual type definitions into a single, structured workspace ready for IDE use. It handles version-specific logic (Classic, Vanilla, TBC, Wrath, etc.) and automatically injects Lua annotations into the Blizzard source code to improve intellisense for Mixins and Frames. + +## Files + +- **`clone.sh`**: A shell script to initialize the environment. + - Cleans up old directories (`WoWUI`, `vscode-wow-api`). + - Clones the full [BigWigsMods/WoWUI](https://github.com/BigWigsMods/WoWUI) repository (contains Blizzard's UI code). + - Clones a sparse version of [Ketho/vscode-wow-api](https://github.com/Ketho/vscode-wow-api) (contains standard WoW API annotations). +- **`WoWUI-generator.py`**: The main Python script that processes the files and generates the output structure. +- **`inject_annotations.py`**: A dedicated script to inject LuaLS annotations from source definitions (e.g., FrameXML) into the generated implementation files. +- **`inject_mixin_skip.py`**: Configuration file defining regex patterns to skip specific annotations during injection. +- **`ManualTypes/`**: A directory containing manually written Lua annotation files (e.g., for complex types or missing definitions) that are copied directly into the output. + +## Usage + +1. **Prepare Repositories:** + Run the clone script to download the necessary source repositories. + ```bash + ./clone.sh + ``` + +2. **Generate API Structure:** + Run the main generator with a specific version. + ```bash + # Supported versions: classic, vanilla, tbc, wrath, cata, mists + python3 WoWUI-generator.py --version wrath + ``` + This creates the `API-wrath` (or corresponding version) folder. + +3. **Inject Annotations:** + Run the annotation injector to merge docs into the source code and clean up duplicates. + ```bash + # Run in dry-run mode first to see changes + python3 inject_annotations.py --dry-run + + # Apply changes (removes source definitions by default) + python3 inject_annotations.py + ``` + +## How `inject_annotations.py` Works + +This script performs a multi-step post-processing pass on the generated API folder: + +1. **Parse Source Definitions:** + - Scans the `FrameXML` folder (derived from `vscode-wow-api`). + - Identifies all **Functions** (e.g., `function Table.Name()`) and **Mixins** (e.g., `MixinName = {}`). + - Captures contiguous blocks of LuaLS annotations (`---@tag`) preceding them. + +2. **Inject into Target:** + - Scans the generated `_UI` folder (Blizzard source code). + - Matches functions and mixins by name. + - **Smart Injection:** + - Matches parameter names between documentation (`@param button`) and code (`function(self)`). Automatically renames doc parameters to match the code to prevent "undefined param" warnings. + - Appends old parameter names as comments. + - Respects indentation of the target code. + - Supports cleaning prefixes like `--[[static]]`. + - Filters out `---@meta` and `---@class` tags during mixin injection to avoid conflicts with other definitions. + - skips injection if patterns match those defined in `inject_mixin_skip.py`. + +3. **Cleanup Source:** + - If a function or mixin from the Source was successfully found in the Target, it is **removed from the Source file**. + - **Multi-line Removal:** Safely removes entire multi-line function bodies (`function ... end`). + - **Whitespace Cleanup:** Collapses excess blank lines left after removal. + - **Empty File Cleanup:** Deletes source files that become empty (or contain only whitespace/meta tags) after the removal process. + +This ensures that the final API folder contains the "real" Blizzard implementation code annotated with the rich community documentation, without duplicating definitions in separate meta files. diff --git a/generator/inject_annotations.py b/generator/inject_annotations.py index f6b736e..9fffb80 100644 --- a/generator/inject_annotations.py +++ b/generator/inject_annotations.py @@ -2,7 +2,7 @@ import os import re import argparse -import sys +from inject_mixin_skip import MIXIN_SKIP_PATTERNS, FUNCTION_SKIP_PATTERNS def parse_annotations(source_dir): @@ -50,16 +50,15 @@ def parse_annotations(source_dir): m = func_regex.match(line) if m: func_name = m.group(1) - if current_block: - # We found a function with preceding annotations - annotations[func_name] = { - "lines": current_block, - "source": path, - } - # print(f"Found annotations for: {func_name}") - - # Reset block after function definition - current_block = [] + # We found a function. Even if it has no preceding annotations (current_block is empty), + # we record it so we can later check if it exists in the target and remove it from source if so. + annotations[func_name] = { + "lines": current_block, + "source": path, + } + + # Reset block after function definition + current_block = [] elif not stripped: # Empty line. Clear block to avoid attaching disconnected comments. @@ -73,6 +72,265 @@ def parse_annotations(source_dir): return annotations +def parse_mixins(source_dir): + """ + Parses all .lua files in source_dir for mixin definitions. + Returns a dict: { "MixinName": { "lines": ["line1\n", "line2\n"], "source": "/path/to/file.lua" } } + """ + mixins = {} + # Matches: MixinName = {} or MixinName = {}; + # Capture group 1: MixinName + mixin_regex = re.compile(r"^([a-zA-Z0-9_]+)\s*=\s*\{\}\s*;?$", re.MULTILINE) + + print(f"Scanning source directory for mixins: {source_dir}") + + for root, _, files in os.walk(source_dir): + for file in files: + if not file.endswith(".lua"): + continue + + path = os.path.join(root, file) + try: + with open(path, "r", encoding="utf-8") as f: + lines = f.readlines() + except Exception as e: + print(f"Warning: Could not read {path}: {e}") + continue + + current_block = [] + + for line in lines: + stripped = line.strip() + + if stripped.startswith("--"): + current_block.append(stripped + "\n") + + elif "=" in stripped: # Optimization check + m = mixin_regex.match(stripped) + if m: + mixin_name = m.group(1) + # We capture it even if no annotations, same logic as functions + mixins[mixin_name] = { + "lines": current_block, + "source": path, + } + current_block = [] + else: + current_block = [] + elif not stripped: + current_block = [] + else: + current_block = [] + + print(f"Found definitions for {len(mixins)} mixins/tables.") + return mixins + + +def inject_mixins(target_dir, mixins_map, dry_run=False): + """ + Scans target_dir for mixin definitions and injects annotations. + """ + # Same regex for target matching + mixin_regex = re.compile(r"^([a-zA-Z0-9_]+)\s*=\s*\{\}\s*;?$", re.MULTILINE) + + print(f"Scanning target directory for mixins: {target_dir}") + + modified_count = 0 + matched_mixins_set = set() + + for root, _, files in os.walk(target_dir): + for file in files: + if not file.endswith(".lua"): + continue + + path = os.path.join(root, file) + try: + with open(path, "r", encoding="utf-8") as f: + lines = f.readlines() + except Exception as e: + print(f"Warning: Could not read {path}: {e}") + continue + + new_lines = [] + file_modified = False + + for line in lines: + stripped = line.strip() + m = mixin_regex.match(stripped) + + if m: + mixin_name = m.group(1) + if mixin_name in mixins_map: + matched_mixins_set.add(mixin_name) + anno_data = mixins_map[mixin_name] + anno_lines = anno_data["lines"] + source_file = anno_data["source"] + + # Duplicate check (heuristic) + already_present = False + if len(new_lines) >= len(anno_lines): + last_n = new_lines[-len(anno_lines) :] + clean_last_n = [l.strip() for l in last_n] + clean_anno = [l.strip() for l in anno_lines] + if clean_last_n == clean_anno: + already_present = True + + if not already_present and anno_lines: + if dry_run: + print( + f"[Dry Run] Injecting mixin docs for: {mixin_name} in {path} (from {source_file})" + ) + else: + print( + f"Injecting mixin docs for: {mixin_name} in {path} (from {source_file})" + ) + + # Mixins are usually global, assume 0 indentation for docs + # Or matches line indentation? + # stripped matched, so we need indentation from original line + # Fix for potential bug where indent includes part of the line content if trailing whitespace exists + # Use lstrip to calculate indentation correctly + indent = line[: len(line) - len(line.lstrip())] + + # Get skip patterns for this mixin + skip_patterns = [ + re.compile(p) + for p in MIXIN_SKIP_PATTERNS.get(mixin_name, []) + ] + + for al in anno_lines: + # Filter out ---@meta and ---@class tags + if re.match(r"^\s*---@meta", al) or re.match( + r"^\s*---@class", al + ): + continue + + # Check against manual skip patterns + should_skip = False + for pattern in skip_patterns: + if pattern.match(al): + should_skip = True + break + if should_skip: + continue + + new_lines.append(indent + al) + + file_modified = True + modified_count += 1 + + new_lines.append(line) + + if file_modified and not dry_run: + try: + with open(path, "w", encoding="utf-8") as f: + f.writelines(new_lines) + except Exception as e: + print(f"Error writing to {path}: {e}") + + if dry_run: + print(f"[Dry Run] Would have injected docs into {modified_count} mixins.") + else: + print(f"Injected docs into {modified_count} mixins.") + + return matched_mixins_set + + +def remove_source_mixins(mixins_map, matched_mixins, dry_run=False): + """ + Removes mixin definitions and their annotations from source files. + """ + print("Cleaning up source mixins...") + + files_to_process = {} + for name in matched_mixins: + if name in mixins_map: + source_file = mixins_map[name]["source"] + if source_file not in files_to_process: + files_to_process[source_file] = set() + files_to_process[source_file].add(name) + + removed_count = 0 + mixin_regex = re.compile(r"^([a-zA-Z0-9_]+)\s*=\s*\{\}\s*;?$", re.MULTILINE) + + for source_file, mixin_names in files_to_process.items(): + try: + with open(source_file, "r", encoding="utf-8") as f: + lines = f.readlines() + except Exception as e: + print(f"Warning: Could not read {source_file}: {e}") + continue + + new_lines = [] + pending_block = [] + file_modified = False + + for line in lines: + stripped = line.strip() + + if stripped.startswith("--"): + pending_block.append(line) + continue + + m = mixin_regex.match(stripped) + if m: + name = m.group(1) + if name in mixin_names: + # Found mixin to remove + if dry_run: + print( + f"[Dry Run] Removing source mixin definition {name} in {source_file}" + ) + else: + print( + f"Removing source mixin definition {name} in {source_file}" + ) + + file_modified = True + removed_count += 1 + pending_block = [] # Discard annotations + continue # Skip line + + # Not matched or not to remove + if not stripped: + new_lines.extend(pending_block) + pending_block = [] + new_lines.append(line) + continue + + new_lines.extend(pending_block) + pending_block = [] + new_lines.append(line) + + new_lines.extend(pending_block) + + # Cleanup blank lines + cleaned_lines = [] + last_was_blank = False + for line in new_lines: + is_blank = not line.strip() + if is_blank: + if last_was_blank: + continue + cleaned_lines.append(line) + last_was_blank = True + else: + cleaned_lines.append(line) + last_was_blank = False + + if file_modified and not dry_run: + try: + with open(source_file, "w", encoding="utf-8") as f: + f.writelines(cleaned_lines) + except Exception as e: + print(f"Error writing {source_file}: {e}") + + if dry_run: + print(f"[Dry Run] Would have removed {removed_count} mixins.") + else: + print(f"Removed {removed_count} mixins.") + + def inject_annotations(target_dir, annotations_map, dry_run=False): """ Scans target_dir for .lua files. @@ -169,6 +427,12 @@ def inject_annotations(target_dir, annotations_map, dry_run=False): # Inject annotations # We prepend the indentation found on the function line + # Get skip patterns for this function + skip_patterns = [ + re.compile(p) + for p in FUNCTION_SKIP_PATTERNS.get(func_name, []) + ] + # --- Parameter Matching Logic --- # Check if parameters match between code and docs # Target: function Name(p1, p2) -> "p1, p2" @@ -265,6 +529,15 @@ def inject_annotations(target_dir, annotations_map, dry_run=False): ) for anno_line in anno_lines: + # Check against manual skip patterns + should_skip = False + for pattern in skip_patterns: + if pattern.match(anno_line): + should_skip = True + break + if should_skip: + continue + # anno_line has \n but no indent. new_lines.append(indent + anno_line) @@ -437,6 +710,58 @@ def remove_source_annotations(annotations_map, matched_functions, dry_run=False) print(f"Removed {removed_count} function definitions from source.") +def cleanup_empty_files(source_dir, dry_run=False): + """ + Scans the source directory and removes files that contain only whitespace or meta tags. + """ + print("Cleaning up empty source files...") + + # Regex for lines that are allowed (whitespace or meta tags) + # If a line matches this, it counts as "skippable" for deletion purposes. + # If a line does NOT match this, the file is kept. + allowed_line_regex = re.compile(r"^\s*(?:---@meta.*)?$") + + removed_count = 0 + + for root, _, files in os.walk(source_dir): + for file in files: + if not file.endswith(".lua"): + continue + + path = os.path.join(root, file) + + should_remove = True + try: + with open(path, "r", encoding="utf-8") as f: + lines = f.readlines() + for line in lines: + # If we find any line that is NOT whitespace and NOT ---@meta + # then the file contains "real" content and should be kept. + if not allowed_line_regex.match(line): + should_remove = False + break + except Exception as e: + print(f"Warning: Could not read {path}: {e}") + continue + + if should_remove: + if dry_run: + print(f"[Dry Run] Removing empty file: {path}") + else: + print(f"Removing empty file: {path}") + try: + os.remove(path) + except Exception as e: + print(f"Error removing {path}: {e}") + + removed_count += 1 + + if dry_run: + print(f"[Dry Run] Would have removed {removed_count} empty files.") + else: + print(f"Removed {removed_count} empty files.") + + def main(): parser = argparse.ArgumentParser( description="Inject LuaLS annotations from source definitions to implementation files." @@ -479,12 +804,16 @@ def main(): # 1. Load Annotations annotations = parse_annotations(source_path) - if not annotations: - print("No annotations found. Exiting.") + # 1b. Load Mixins + mixins = parse_mixins(source_path) + + if not annotations and not mixins: + print("No annotations or mixins found. Exiting.") return # 2. Inject injected_funcs = inject_annotations(target_path, annotations, dry_run=args.dry_run) + injected_mixins = inject_mixins(target_path, mixins, dry_run=args.dry_run) # 3. Report Missing all_funcs = set(annotations.keys()) @@ -497,10 +826,20 @@ def main(): print(f" - {func} ({source_file})") print("\n") + all_mixins = set(mixins.keys()) + missing_mixins = all_mixins - injected_mixins + if missing_mixins: + print("\nMixins found in Source but NOT found in Target:") + for mixin in sorted(missing_mixins): + source_file = mixins[mixin]["source"] + print(f" - {mixin} ({source_file})") + print("\n") # 4. Cleanup Source if not args.keep_source: remove_source_annotations(annotations, injected_funcs, dry_run=args.dry_run) + remove_source_mixins(mixins, injected_mixins, dry_run=args.dry_run) + cleanup_empty_files(source_path, dry_run=args.dry_run) if __name__ == "__main__": diff --git a/generator/inject_mixin_skip.py b/generator/inject_mixin_skip.py new file mode 100644 index 0000000..41c60ce --- /dev/null +++ b/generator/inject_mixin_skip.py @@ -0,0 +1,43 @@ +# Configuration for matched strings to be skipped when injecting +MIXIN_SKIP_PATTERNS = { + # For some reason Kethos code have all these fields but they automatically gets resolved. + "PlayerLocationMixin": [ + r".*field unit.*", + r".*field chatLineID.*", + r".*field guid.*", + r".*field SetGUID.*", + r".*field IsValid.*", + r".*field IsGUID.*", + r".*field IsBattleNetGUID.*", + r".*field GetGUID.*", + r".*field SetUnit.*", + r".*field IsUnit.*", + r".*field GetUnit.*", + r".*field SetChatLineID.*", + r".*field IsChatLineID.*", + r".*field GetChatLineID.*", + r".*field SetBattlefieldScoreIndex.*", + r".*field IsBattlefieldScoreIndex.*", + r".*field GetBattlefieldScoreIndex.*", + r".*field SetVoiceID.*", + r".*field IsVoiceID.*", + r".*field GetVoiceID.*", + r".*field SetBattleNetID.*", + r".*field IsBattleNetID.*", + r".*field GetBattleNetID.*", + r".*field SetCommunityData.*", + r".*field IsCommunityData.*", + r".*field SetCommunityInvitation.*", + r".*field IsCommunityInvitation.*", + r".*field Clear.*", + r".*field ClearAndSetField.*", + ] +} + +# Configuration for matched strings to be skipped when injecting functions +FUNCTION_SKIP_PATTERNS = { + # Example: + # "SomeFunction": [ + # r".*param self.*", + # ] +}