EXPANSION_LEVEL = GetExpansionLevel(); --This can change while logged in, when an expansion releases
LFD_MAX_REWARDS = 2;
NUM_LFD_CHOICE_BUTTONS = 15;
NUM_LFD_MEMBERS = 5;
LFD_STATISTIC_CHANGE_TIME = 10; --In secs.
LFD_PROPOSAL_FAILED_CLOSE_TIME = 5;
LFD_NUM_ROLES = 3;
LFD_MAX_SHOWN_LEVEL_DIFF = 15;
-------------------------------------
-----------LFD Frame--------------
-------------------------------------
--General functions
function LFDFrame_OnLoad(self)
--self:RegisterEvent("LFG_PROPOSAL_UPDATE");
--self:RegisterEvent("LFG_PROPOSAL_SHOW");
--self:RegisterEvent("LFG_PROPOSAL_FAILED");
--self:RegisterEvent("LFG_PROPOSAL_SUCCEEDED");
--self:RegisterEvent("LFG_UPDATE");
self:RegisterEvent("PLAYER_ENTERING_WORLD");
self:RegisterEvent("LFG_ROLE_CHECK_SHOW");
self:RegisterEvent("LFG_ROLE_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");
ButtonFrameTemplate_HideAttic(self);
self.Inset:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 2, 284);
self.Inset:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -2, 26);
end
function LFDFrame_OnEvent(self, event, ...)
if ( event == "LFG_ROLE_CHECK_SHOW" ) then
StaticPopupSpecial_Show(LFDRoleCheckPopup);
LFDQueueFrameSpecificList_Update();
elseif ( event == "LFG_ROLE_CHECK_HIDE" ) then
StaticPopupSpecial_Hide(LFDRoleCheckPopup);
LFDQueueFrameSpecificList_Update();
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
StaticPopup_Show("VOTE_BOOT_PLAYER", targetName, reason);
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 ( 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
elseif ( event == "LFG_OPEN_FROM_GOSSIP" ) then
local dungeonID = ...;
PVEFrame_ShowFrame("GroupFinderFrame", LFDParentFrame);
LFDQueueFrame_SetType(dungeonID);
elseif ( event == "UPDATE_EXPANSION_LEVEL" ) then
EXPANSION_LEVEL = GetExpansionLevel();
end
end
function LFDFrame_OnShow(self)
LFGBackfillCover_Update(LFDQueueFrame.PartyBackfill, true);
end
--Role-related functions
function LFDQueueFrame_SetRoles()
SetLFGRoles(LFDQueueFrameRoleButtonLeader.checkButton:GetChecked(),
LFDQueueFrameRoleButtonTank.checkButton:GetChecked(),
LFDQueueFrameRoleButtonHealer.checkButton:GetChecked(),
LFDQueueFrameRoleButtonDPS.checkButton:GetChecked());
end
function LFDQueueFrame_GetRoles()
return LFDQueueFrameRoleButtonLeader.checkButton:GetChecked(),
LFDQueueFrameRoleButtonTank.checkButton:GetChecked(),
LFDQueueFrameRoleButtonHealer.checkButton:GetChecked(),
LFDQueueFrameRoleButtonDPS.checkButton:GetChecked();
end
function LFDFrameRoleCheckButton_OnClick(self)
LFDQueueFrame_SetRoles();
LFDQueueFrameRandom_UpdateFrame(); --We may show or hide shortage rewards.
end
function LFDQueueFrame_UpdateRoleIncentives()
local dungeonID = LFDQueueFrame.type;
LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonTank, nil);
LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonHealer, nil);
LFG_SetRoleIconIncentive(LFDQueueFrameRoleButtonDPS, nil);
if ( type(dungeonID) == "number" ) 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
end
--Role-check popup functions
function LFDRoleCheckPopupAccept_OnClick()
PlaySound("igCharacterInfoTab");
local oldLeader = GetLFGRoles();
SetLFGRoles(oldLeader,
LFDRoleCheckPopupRoleButtonTank.checkButton:GetChecked(),
LFDRoleCheckPopupRoleButtonHealer.checkButton:GetChecked(),
LFDRoleCheckPopupRoleButtonDPS.checkButton:GetChecked());
if ( CompleteLFGRoleCheck(true) ) then
StaticPopupSpecial_Hide(LFDRoleCheckPopup);
end
end
function LFDRoleCheckPopupDecline_OnClick()
PlaySound("igCharacterInfoTab");
StaticPopupSpecial_Hide(LFDRoleCheckPopup);
CompleteLFGRoleCheck(false);
end
function LFDRoleCheckPopup_Update()
LFGDungeonList_Setup();
LFG_UpdateAllRoleCheckboxes();
local inProgress, slots, members = GetLFGRoleUpdate();
local displayName;
if ( 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 = NORMAL_FONT_COLOR_CODE..displayName.."|r";
LFDRoleCheckPopupDescriptionText:SetFormattedText(QUEUED_FOR, displayName);
LFDRoleCheckPopupDescription:SetWidth(LFDRoleCheckPopupDescriptionText:GetWidth()+10);
LFDRoleCheckPopupDescription:SetHeight(LFDRoleCheckPopupDescriptionText:GetHeight());
end
function LFDRoleCheckPopupDescription_OnEnter(self)
local inProgress, slots, members = GetLFGRoleUpdate();
if ( slots <= 1 ) then
return;
end
GameTooltip:SetOwner(self, "ANCHOR_BOTTOM");
GameTooltip:AddLine(QUEUED_FOR_SHORT);
for i=1, slots do
local dungeonID, dungeonType, dungeonSubType = GetLFGRoleUpdateSlot(i);
local displayName;
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
GameTooltip:AddLine(" "..displayName);
end
GameTooltip:Show();
end
--List functions
function LFDQueueFrameSpecificList_Update()
if ( LFGDungeonList_Setup() ) then
return; --Setup will update the list.
end
FauxScrollFrame_Update(LFDQueueFrameSpecificListScrollFrame, LFDGetNumDungeons(), NUM_LFD_CHOICE_BUTTONS, 16);
local offset = FauxScrollFrame_GetOffset(LFDQueueFrameSpecificListScrollFrame);
local areButtonsBig = not LFDQueueFrameSpecificListScrollFrame:IsShown();
local enabled, queued = LFGDungeonList_EvaluateListState(LE_LFG_CATEGORY_LFD);
local checkedList;
if ( queued ) then
checkedList = LFGQueuedForList[LE_LFG_CATEGORY_LFD];
else
checkedList = LFGEnabledList;
end
for i = 1, NUM_LFD_CHOICE_BUTTONS do
local button = _G["LFDQueueFrameSpecificListButton"..i];
local dungeonID = LFDDungeonList[i+offset];
if ( dungeonID ) then
button:Show();
if ( areButtonsBig ) then
button:SetWidth(315);
else
button:SetWidth(295);
end
LFGDungeonListButton_SetDungeon(button, dungeonID, enabled, checkedList);
else
button:Hide();
end
end
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();
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 LFDQueueFrameTypeDropDown_SetUp(self)
UIDropDownMenu_SetWidth(self, 180);
UIDropDownMenu_Initialize(self, LFDQueueFrameTypeDropDown_Initialize);
UIDropDownMenu_SetSelectedValue(LFDQueueFrameTypeDropDown, LFDQueueFrame.type);
end
function LFDQueueFrameTypeDropDown_Initialize()
local info = UIDropDownMenu_CreateInfo();
info.text = SPECIFIC_DUNGEONS;
info.value = "specific";
info.func = LFDQueueFrameTypeDropDownButton_OnClick;
info.checked = LFDQueueFrame.type == info.value;
UIDropDownMenu_AddButton(info);
for i=1, GetNumRandomDungeons() do
local id, name = GetLFGRandomDungeonInfo(i);
if ( LFG_IsRandomDungeonDisplayable(id) ) then
local isAvailable = IsLFGDungeonJoinable(id);
if ( isAvailable ) then
info.text = name;
info.value = id;
info.isTitle = nil;
info.func = LFDQueueFrameTypeDropDownButton_OnClick;
info.disabled = nil;
info.checked = (LFDQueueFrame.type == info.value);
info.tooltipWhileDisabled = nil;
info.tooltipOnButton = nil;
info.tooltipTitle = nil;
info.tooltipText = nil;
UIDropDownMenu_AddButton(info);
else
info.text = name;
info.value = id;
info.isTitle = nil;
info.func = nil;
info.disabled = 1;
info.checked = nil;
info.tooltipWhileDisabled = 1;
info.tooltipOnButton = 1;
info.tooltipTitle = YOU_MAY_NOT_QUEUE_FOR_THIS;
info.tooltipText = LFGConstructDeclinedMessage(id);
UIDropDownMenu_AddButton(info);
end
end
end
end
function LFDQueueFrameTypeDropDownButton_OnClick(self)
LFDQueueFrame_SetType(self.value);
end
function LFDQueueFrame_SetType(value) --"specific" for the list or the record id for a single dungeon
LFDQueueFrame.type = value;
UIDropDownMenu_SetSelectedValue(LFDQueueFrameTypeDropDown, value);
if ( value == "specific" ) then
LFDQueueFrame_SetTypeSpecificDungeon();
else
local name, typeID, subtypeID, minLevel, maxLevel, recLevel, minRecLevel, maxRecLevel, expansionLevel, groupID, textureFilename, difficulty, maxPlayers, description, isHoliday = GetLFGDungeonInfo(value);
LFDQueueFrame_SetTypeRandomDungeon(isHoliday);
LFDQueueFrameRandom_UpdateFrame();
end
LFDQueueFrame_UpdateRoleIncentives();
end
function LFDQueueFrame_SetTypeRandomDungeon(isHoliday)
LFDQueueFrameBackground:SetTexture("Interface\\LFGFrame\\UI-LFG-BACKGROUND-QUESTPAPER")
LFDQueueFrameSpecific:Hide();
LFDQueueFrameRandom:Show();
LFGCooldownCover_ChangeSettings(LFDQueueFrame.CooldownFrame, true, not isHoliday);
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_UpdateRoleIncentives();
end
function LFDQueueFrameRandomRandomList_OnEnter(self)
local randomID = LFDQueueFrame.type;
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
GameTooltip:SetText(INCLUDED_DUNGEONS, 1, 1, 1);
local numDungeons = GetNumDungeonForRandomSlot(randomID);
if ( numDungeons == 0 ) then
GameTooltip:AddLine(INCLUDED_DUNGEONS_EMPTY, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, true);
else
GameTooltip:AddLine(INCLUDED_DUNGEONS_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
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("UNIT_AURA"); --The cooldown is still technically a debuff
self:RegisterEvent("GROUP_ROSTER_UPDATE");
end
function LFDQueueFrameRandomCooldownFrame_OnEvent(self, event, ...)
local arg1 = ...;
if ( event ~= "UNIT_AURA" or arg1 == "player" or strsub(arg1, 1, 5) == "party" ) then
LFDQueueFrameRandomCooldownFrame_Update();
end
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, UnitName("party"..i));
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);
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 ( 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();
else
LFDQueueFrameFindGroupButton:Disable();
end
LFRQueueFrameNoLFRWhileLFDLeaveQueueButton:Enable();
else
LFDQueueFrameFindGroupButton:Disable();
end
if ( LFD_IsEmpowered() and mode ~= "proposal" and mode ~= "queued" and mode ~= "suspended" and mode ~= "rolecheck" ) then
LFDQueueFramePartyBackfillBackfillButton:Enable();
else
LFDQueueFramePartyBackfillBackfillButton:Disable();
end
end
LFDHiddenByCollapseList = {};
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
LFDDungeonList = GetLFDChoiceOrder(LFDDungeonList);
LFGQueueFrame_UpdateLFGDungeonList(LFDDungeonList, LFDHiddenByCollapseList, checkedList, LFD_CURRENT_FILTER, LFD_MAX_SHOWN_LEVEL_DIFF);
LFDQueueFrameSpecificList_Update();
end
LFD_CURRENT_FILTER = LFGList_DefaultFilterFunction;