3603 lines
106 KiB
Lua
3603 lines
106 KiB
Lua
TOOLTIP_UPDATE_TIME = 0.2;
|
|
ROTATIONS_PER_SECOND = .5;
|
|
|
|
-- Alpha animation stuff
|
|
FADEFRAMES = {};
|
|
FLASHFRAMES = {};
|
|
|
|
-- Pulsing stuff
|
|
PULSEBUTTONS = {};
|
|
|
|
-- Shine animation
|
|
SHINES_TO_ANIMATE = {};
|
|
|
|
-- Per panel settings
|
|
UIPanelWindows = {};
|
|
UIPanelWindows["GameMenuFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["VideoOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["AudioOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["InterfaceOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["CharacterFrame"] = { area = "left", pushable = 3 , whileDead = 1 };
|
|
UIPanelWindows["ItemTextFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["SpellBookFrame"] = { area = "left", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["LootFrame"] = { area = "left", pushable = 7 };
|
|
UIPanelWindows["TaxiFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["QuestFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["QuestLogFrame"] = { area = "doublewide", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["QuestLogDetailFrame"] = { area = "left", pushable = 1, whileDead = 1 };
|
|
UIPanelWindows["MerchantFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["TradeFrame"] = { area = "left", pushable = 1 };
|
|
UIPanelWindows["BankFrame"] = { area = "left", pushable = 6, width = 425 };
|
|
UIPanelWindows["FriendsFrame"] = { area = "left", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["WorldMapFrame"] = { area = "full", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["CinematicFrame"] = { area = "full", pushable = 0 };
|
|
UIPanelWindows["TabardFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["PVPBannerFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["GuildRegistrarFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["ArenaRegistrarFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["PetitionFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["HelpFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["GossipFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["MailFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["BattlefieldFrame"] = { area = "left", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["PetStableFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["WorldStateScoreFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["DressUpFrame"] = { area = "left", pushable = 2 };
|
|
UIPanelWindows["MinigameFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["LFGParentFrame"] = { area = "left", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["LFDParentFrame"] = { area = "left", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["LFRParentFrame"] = { area = "left", pushable = 1, whileDead = 1 };
|
|
UIPanelWindows["ArenaFrame"] = { area = "left", pushable = 0 };
|
|
UIPanelWindows["ChatConfigFrame"] = { area = "center", pushable = 0, whileDead = 1 };
|
|
UIPanelWindows["PVPParentFrame"] = { area = "left", pushable = 0, whileDead = 1 };
|
|
|
|
local function GetUIPanelWindowInfo(frame, name)
|
|
if ( not frame:GetAttribute("UIPanelLayout-defined") ) then
|
|
local info = UIPanelWindows[frame:GetName()];
|
|
if ( not info ) then
|
|
return;
|
|
end
|
|
frame:SetAttribute("UIPanelLayout-defined", true);
|
|
for name,value in pairs(info) do
|
|
frame:SetAttribute("UIPanelLayout-"..name, value);
|
|
end
|
|
frame:SetAttribute("UIPanelLayout-enabled", true);
|
|
end
|
|
if ( frame:GetAttribute("UIPanelLayout-enabled") ) then
|
|
return frame:GetAttribute("UIPanelLayout-"..name);
|
|
end
|
|
end
|
|
|
|
-- These are windows that rely on a parent frame to be open. If the parent closes or a pushable frame overlaps them they must be hidden.
|
|
UIChildWindows = {
|
|
"OpenMailFrame",
|
|
"GuildControlPopupFrame",
|
|
"GuildMemberDetailFrame",
|
|
"TokenFramePopup",
|
|
"GuildInfoFrame",
|
|
"PVPTeamDetails",
|
|
"GuildBankPopupFrame",
|
|
"GearManagerDialog",
|
|
};
|
|
|
|
UISpecialFrames = {
|
|
"ItemRefTooltip",
|
|
"ColorPickerFrame"
|
|
};
|
|
|
|
UIMenus = {
|
|
"ChatMenu",
|
|
"EmoteMenu",
|
|
"LanguageMenu",
|
|
"DropDownList1",
|
|
"DropDownList2",
|
|
};
|
|
|
|
ITEM_QUALITY_COLORS = { };
|
|
for i = -1, 6 do
|
|
ITEM_QUALITY_COLORS[i] = { };
|
|
ITEM_QUALITY_COLORS[i].r,
|
|
ITEM_QUALITY_COLORS[i].g,
|
|
ITEM_QUALITY_COLORS[i].b,
|
|
ITEM_QUALITY_COLORS[i].hex = GetItemQualityColor(i);
|
|
end
|
|
|
|
function UIParent_OnLoad(self)
|
|
self:RegisterEvent("PLAYER_LOGIN");
|
|
self:RegisterEvent("PLAYER_DEAD");
|
|
self:RegisterEvent("PLAYER_ALIVE");
|
|
self:RegisterEvent("PLAYER_UNGHOST");
|
|
self:RegisterEvent("RESURRECT_REQUEST");
|
|
self:RegisterEvent("PLAYER_SKINNED");
|
|
self:RegisterEvent("TRADE_REQUEST");
|
|
self:RegisterEvent("CHANNEL_INVITE_REQUEST");
|
|
self:RegisterEvent("CHANNEL_PASSWORD_REQUEST");
|
|
self:RegisterEvent("PARTY_INVITE_REQUEST");
|
|
self:RegisterEvent("PARTY_INVITE_CANCEL");
|
|
self:RegisterEvent("GUILD_INVITE_REQUEST");
|
|
self:RegisterEvent("GUILD_INVITE_CANCEL");
|
|
self:RegisterEvent("ARENA_TEAM_INVITE_REQUEST");
|
|
self:RegisterEvent("PLAYER_CAMPING");
|
|
self:RegisterEvent("PLAYER_QUITING");
|
|
self:RegisterEvent("LOGOUT_CANCEL");
|
|
self:RegisterEvent("LOOT_BIND_CONFIRM");
|
|
self:RegisterEvent("EQUIP_BIND_CONFIRM");
|
|
self:RegisterEvent("AUTOEQUIP_BIND_CONFIRM");
|
|
self:RegisterEvent("USE_BIND_CONFIRM");
|
|
self:RegisterEvent("DELETE_ITEM_CONFIRM");
|
|
self:RegisterEvent("QUEST_ACCEPT_CONFIRM");
|
|
self:RegisterEvent("QUEST_LOG_UPDATE");
|
|
self:RegisterEvent("UNIT_QUEST_LOG_CHANGED");
|
|
self:RegisterEvent("CURSOR_UPDATE");
|
|
self:RegisterEvent("LOCALPLAYER_PET_RENAMED");
|
|
self:RegisterEvent("PLAYER_ENTERING_WORLD");
|
|
self:RegisterEvent("MIRROR_TIMER_START");
|
|
self:RegisterEvent("DUEL_REQUESTED");
|
|
self:RegisterEvent("DUEL_OUTOFBOUNDS");
|
|
self:RegisterEvent("DUEL_INBOUNDS");
|
|
self:RegisterEvent("DUEL_FINISHED");
|
|
self:RegisterEvent("TRADE_REQUEST_CANCEL");
|
|
self:RegisterEvent("CONFIRM_XP_LOSS");
|
|
self:RegisterEvent("CORPSE_IN_RANGE");
|
|
self:RegisterEvent("CORPSE_IN_INSTANCE");
|
|
self:RegisterEvent("CORPSE_OUT_OF_RANGE");
|
|
self:RegisterEvent("AREA_SPIRIT_HEALER_IN_RANGE");
|
|
self:RegisterEvent("AREA_SPIRIT_HEALER_OUT_OF_RANGE");
|
|
self:RegisterEvent("BIND_ENCHANT");
|
|
self:RegisterEvent("REPLACE_ENCHANT");
|
|
self:RegisterEvent("TRADE_REPLACE_ENCHANT");
|
|
self:RegisterEvent("END_REFUND");
|
|
self:RegisterEvent("END_BOUND_TRADEABLE");
|
|
self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
|
|
self:RegisterEvent("MACRO_ACTION_BLOCKED");
|
|
self:RegisterEvent("ADDON_ACTION_BLOCKED");
|
|
self:RegisterEvent("MACRO_ACTION_FORBIDDEN");
|
|
self:RegisterEvent("ADDON_ACTION_FORBIDDEN");
|
|
self:RegisterEvent("PLAYER_CONTROL_LOST");
|
|
self:RegisterEvent("PLAYER_CONTROL_GAINED");
|
|
self:RegisterEvent("START_LOOT_ROLL");
|
|
self:RegisterEvent("CONFIRM_LOOT_ROLL");
|
|
self:RegisterEvent("CONFIRM_DISENCHANT_ROLL");
|
|
self:RegisterEvent("INSTANCE_BOOT_START");
|
|
self:RegisterEvent("INSTANCE_BOOT_STOP");
|
|
self:RegisterEvent("INSTANCE_LOCK_START");
|
|
self:RegisterEvent("INSTANCE_LOCK_STOP");
|
|
self:RegisterEvent("CONFIRM_TALENT_WIPE");
|
|
self:RegisterEvent("CONFIRM_BINDER");
|
|
self:RegisterEvent("CONFIRM_SUMMON");
|
|
self:RegisterEvent("CANCEL_SUMMON");
|
|
self:RegisterEvent("GOSSIP_CONFIRM");
|
|
self:RegisterEvent("GOSSIP_CONFIRM_CANCEL");
|
|
self:RegisterEvent("GOSSIP_ENTER_CODE");
|
|
self:RegisterEvent("GOSSIP_CLOSED");
|
|
self:RegisterEvent("BILLING_NAG_DIALOG");
|
|
self:RegisterEvent("IGR_BILLING_NAG_DIALOG");
|
|
self:RegisterEvent("VARIABLES_LOADED");
|
|
self:RegisterEvent("RAID_ROSTER_UPDATE");
|
|
self:RegisterEvent("RAID_INSTANCE_WELCOME");
|
|
self:RegisterEvent("LEVEL_GRANT_PROPOSED");
|
|
self:RegisterEvent("RAISED_AS_GHOUL");
|
|
|
|
-- Events for auction UI handling
|
|
self:RegisterEvent("AUCTION_HOUSE_SHOW");
|
|
self:RegisterEvent("AUCTION_HOUSE_CLOSED");
|
|
self:RegisterEvent("AUCTION_HOUSE_DISABLED");
|
|
|
|
-- Events for trainer UI handling
|
|
self:RegisterEvent("TRAINER_SHOW");
|
|
self:RegisterEvent("TRAINER_CLOSED");
|
|
|
|
-- Events for trade skill UI handling
|
|
self:RegisterEvent("TRADE_SKILL_SHOW");
|
|
self:RegisterEvent("TRADE_SKILL_CLOSE");
|
|
|
|
-- Events for Item socketing UI
|
|
self:RegisterEvent("SOCKET_INFO_UPDATE");
|
|
|
|
-- Events for taxi benchmarking
|
|
self:RegisterEvent("ENABLE_TAXI_BENCHMARK");
|
|
self:RegisterEvent("DISABLE_TAXI_BENCHMARK");
|
|
|
|
-- Push to talk
|
|
self:RegisterEvent("VOICE_PUSH_TO_TALK_START");
|
|
self:RegisterEvent("VOICE_PUSH_TO_TALK_STOP");
|
|
|
|
-- Events for BarberShop Handling
|
|
self:RegisterEvent("BARBER_SHOP_OPEN");
|
|
self:RegisterEvent("BARBER_SHOP_CLOSE");
|
|
|
|
-- Events for Guild bank UI
|
|
self:RegisterEvent("GUILDBANKFRAME_OPENED");
|
|
self:RegisterEvent("GUILDBANKFRAME_CLOSED");
|
|
|
|
-- Events for Achievements!
|
|
self:RegisterEvent("ACHIEVEMENT_EARNED");
|
|
|
|
-- Events for Glyphs!
|
|
self:RegisterEvent("USE_GLYPH");
|
|
|
|
--Events for GMChatUI
|
|
self:RegisterEvent("CHAT_MSG_WHISPER");
|
|
|
|
-- Events for WoW Mouse
|
|
self:RegisterEvent("WOW_MOUSE_NOT_FOUND");
|
|
|
|
-- Events for talent wipes
|
|
self:RegisterEvent("TALENTS_INVOLUNTARILY_RESET");
|
|
end
|
|
|
|
|
|
-- Addons --
|
|
|
|
local FailedAddOnLoad = {};
|
|
|
|
function UIParentLoadAddOn(name)
|
|
local loaded, reason = LoadAddOn(name);
|
|
if ( not loaded ) then
|
|
if ( not FailedAddOnLoad[name] ) then
|
|
message(format(ADDON_LOAD_FAILED, name, _G["ADDON_"..reason]));
|
|
FailedAddOnLoad[name] = true;
|
|
end
|
|
end
|
|
return loaded;
|
|
end
|
|
|
|
function AuctionFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_AuctionUI");
|
|
end
|
|
|
|
function BattlefieldMinimap_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_BattlefieldMinimap");
|
|
end
|
|
|
|
function ClassTrainerFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_TrainerUI");
|
|
end
|
|
|
|
function CombatLog_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_CombatLog");
|
|
end
|
|
|
|
function GuildBankFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_GuildBankUI");
|
|
end
|
|
|
|
function InspectFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_InspectUI");
|
|
end
|
|
|
|
function KeyBindingFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_BindingUI");
|
|
end
|
|
|
|
function MacroFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_MacroUI");
|
|
end
|
|
function MacroFrame_SaveMacro()
|
|
-- this will be overwritten with the real thing when the addon is loaded
|
|
end
|
|
|
|
function RaidFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_RaidUI");
|
|
end
|
|
|
|
function TalentFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_TalentUI");
|
|
end
|
|
|
|
function TradeSkillFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_TradeSkillUI");
|
|
end
|
|
|
|
function GMSurveyFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_GMSurveyUI");
|
|
end
|
|
|
|
function ItemSocketingFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_ItemSocketingUI");
|
|
end
|
|
|
|
function BarberShopFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_BarberShopUI");
|
|
end
|
|
|
|
function AchievementFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_AchievementUI");
|
|
end
|
|
|
|
function TimeManager_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_TimeManager");
|
|
end
|
|
|
|
function TokenFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_TokenUI");
|
|
end
|
|
|
|
function GlyphFrame_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_GlyphUI");
|
|
end
|
|
|
|
function Calendar_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_Calendar");
|
|
end
|
|
|
|
function GMChatFrame_LoadUI(...)
|
|
if ( IsAddOnLoaded("Blizzard_GMChatUI") ) then
|
|
return;
|
|
else
|
|
UIParentLoadAddOn("Blizzard_GMChatUI");
|
|
if ( select(1, ...) ) then
|
|
GMChatFrame_OnEvent(GMChatFrame, ...);
|
|
end
|
|
end
|
|
end
|
|
|
|
function Arena_LoadUI()
|
|
UIParentLoadAddOn("Blizzard_ArenaUI");
|
|
end
|
|
|
|
function ShowMacroFrame()
|
|
MacroFrame_LoadUI();
|
|
if ( MacroFrame_Show ) then
|
|
MacroFrame_Show();
|
|
end
|
|
end
|
|
|
|
function InspectAchievements (unit)
|
|
AchievementFrame_LoadUI();
|
|
AchievementFrame_DisplayComparison(unit);
|
|
end
|
|
|
|
function ToggleAchievementFrame(stats)
|
|
if ( not CanShowAchievementUI() or not HasCompletedAnyAchievement() ) then
|
|
return;
|
|
end
|
|
AchievementFrame_LoadUI();
|
|
AchievementFrame_ToggleAchievementFrame(stats);
|
|
end
|
|
|
|
function ToggleTalentFrame()
|
|
if ( UnitLevel("player") < SHOW_TALENT_LEVEL ) then
|
|
return;
|
|
end
|
|
|
|
TalentFrame_LoadUI();
|
|
if ( PlayerTalentFrame_Toggle ) then
|
|
PlayerTalentFrame_Toggle(false, GetActiveTalentGroup());
|
|
end
|
|
end
|
|
|
|
function ToggleGlyphFrame()
|
|
if ( UnitLevel("player") < SHOW_INSCRIPTION_LEVEL ) then
|
|
return;
|
|
end
|
|
|
|
GlyphFrame_LoadUI();
|
|
if ( GlyphFrame_Toggle ) then
|
|
GlyphFrame_Toggle();
|
|
end
|
|
end
|
|
|
|
function OpenGlyphFrame()
|
|
if ( UnitLevel("player") < SHOW_INSCRIPTION_LEVEL ) then
|
|
return;
|
|
end
|
|
|
|
GlyphFrame_LoadUI();
|
|
if ( GlyphFrame_Open ) then
|
|
GlyphFrame_Open();
|
|
end
|
|
end
|
|
|
|
function ToggleBattlefieldMinimap()
|
|
BattlefieldMinimap_LoadUI();
|
|
if ( BattlefieldMinimap_Toggle ) then
|
|
BattlefieldMinimap_Toggle();
|
|
end
|
|
end
|
|
|
|
function ToggleTimeManager()
|
|
TimeManager_LoadUI();
|
|
if ( TimeManager_Toggle ) then
|
|
TimeManager_Toggle();
|
|
end
|
|
end
|
|
|
|
function ToggleCalendar()
|
|
Calendar_LoadUI();
|
|
if ( Calendar_Toggle ) then
|
|
Calendar_Toggle();
|
|
end
|
|
end
|
|
|
|
function ToggleLFDParentFrame()
|
|
if ( UnitLevel("player") >= SHOW_LFD_LEVEL ) then
|
|
if ( LFDParentFrame:IsShown() ) then
|
|
HideUIPanel(LFDParentFrame);
|
|
else
|
|
ShowUIPanel(LFDParentFrame);
|
|
end
|
|
end
|
|
end
|
|
|
|
function ToggleLFRParentFrame()
|
|
if ( LFRParentFrame:IsShown() ) then
|
|
HideUIPanel(LFRParentFrame);
|
|
else
|
|
ShowUIPanel(LFRParentFrame);
|
|
end
|
|
end
|
|
|
|
function ToggleHelpFrame()
|
|
if ( HelpFrame:IsShown() ) then
|
|
HideUIPanel(HelpFrame);
|
|
else
|
|
StaticPopup_Hide("HELP_TICKET");
|
|
StaticPopup_Hide("HELP_TICKET_ABANDON_CONFIRM");
|
|
StaticPopup_Hide("GM_RESPONSE_NEED_MORE_HELP");
|
|
StaticPopup_Hide("GM_RESPONSE_RESOLVE_CONFIRM");
|
|
StaticPopup_Hide("GM_RESPONSE_MUST_RESOLVE_RESPONSE");
|
|
HelpFrame_ShowFrame(HELPFRAME_START_PAGE);
|
|
end
|
|
end
|
|
|
|
function InspectUnit(unit)
|
|
InspectFrame_LoadUI();
|
|
if ( InspectFrame_Show ) then
|
|
InspectFrame_Show(unit);
|
|
end
|
|
end
|
|
|
|
|
|
-- UIParent_OnEvent --
|
|
|
|
function UIParent_OnEvent(self, event, ...)
|
|
local arg1, arg2, arg3, arg4, arg5, arg6 = ...;
|
|
if ( event == "VARIABLES_LOADED" ) then
|
|
LocalizeFrames();
|
|
if ( WorldStateFrame_CanShowBattlefieldMinimap() ) then
|
|
if ( not BattlefieldMinimap ) then
|
|
BattlefieldMinimap_LoadUI();
|
|
end
|
|
BattlefieldMinimap:Show();
|
|
end
|
|
if ( not TimeManagerFrame and GetCVar("timeMgrAlarmEnabled") == "1" ) then
|
|
-- We have to load the time manager here if the alarm is enabled because the alarm can go off
|
|
-- even if the clock is not shown. WorldFrame_OnUpdate handles alarm checking while the clock
|
|
-- is hidden.
|
|
TimeManager_LoadUI();
|
|
end
|
|
local lastTalkedToGM = GetCVar("lastTalkedToGM");
|
|
if ( lastTalkedToGM ~= "" ) then
|
|
GMChatFrame_LoadUI();
|
|
GMChatFrame:Show()
|
|
local info = ChatTypeInfo["WHISPER"];
|
|
GMChatFrame:AddMessage(format(GM_CHAT_LAST_SESSION, "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz.blp:0:2:0:-3|t "..
|
|
"|HplayerGM:"..lastTalkedToGM.."|h".."["..lastTalkedToGM.."]".."|h"), info.r, info.g, info.b, info.id);
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_LOGIN" ) then
|
|
-- You can override this if you want a Combat Log replacement
|
|
CombatLog_LoadUI();
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_DEAD" ) then
|
|
if ( not StaticPopup_Visible("DEATH") ) then
|
|
CloseAllWindows(1);
|
|
if ( GetReleaseTimeRemaining() > 0 or GetReleaseTimeRemaining() == -1 ) then
|
|
StaticPopup_Show("DEATH");
|
|
end
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_ALIVE" or event == "RAISED_AS_GHOUL" ) then
|
|
StaticPopup_Hide("DEATH");
|
|
StaticPopup_Hide("RESURRECT_NO_SICKNESS");
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_UNGHOST" ) then
|
|
StaticPopup_Hide("RESURRECT");
|
|
StaticPopup_Hide("RESURRECT_NO_SICKNESS");
|
|
StaticPopup_Hide("RESURRECT_NO_TIMER");
|
|
StaticPopup_Hide("SKINNED");
|
|
StaticPopup_Hide("SKINNED_REPOP");
|
|
return;
|
|
end
|
|
if ( event == "RESURRECT_REQUEST" ) then
|
|
ShowResurrectRequest(arg1);
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_SKINNED" ) then
|
|
StaticPopup_Hide("RESURRECT");
|
|
StaticPopup_Hide("RESURRECT_NO_SICKNESS");
|
|
StaticPopup_Hide("RESURRECT_NO_TIMER");
|
|
|
|
--[[
|
|
if (arg1 == 1) then
|
|
StaticPopup_Show("SKINNED_REPOP");
|
|
else
|
|
StaticPopup_Show("SKINNED");
|
|
end
|
|
]]
|
|
UIErrorsFrame:AddMessage(DEATH_CORPSE_SKINNED, 1.0, 0.1, 0.1, 1.0);
|
|
return;
|
|
end
|
|
if ( event == "TRADE_REQUEST" ) then
|
|
StaticPopup_Show("TRADE", arg1);
|
|
return;
|
|
end
|
|
if ( event == "CHANNEL_INVITE_REQUEST" ) then
|
|
local dialog = StaticPopup_Show("CHAT_CHANNEL_INVITE", arg1, arg2);
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "CHANNEL_PASSWORD_REQUEST" ) then
|
|
local dialog = StaticPopup_Show("CHAT_CHANNEL_PASSWORD", arg1);
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "PARTY_INVITE_REQUEST" ) then
|
|
StaticPopup_Show("PARTY_INVITE", arg1);
|
|
return;
|
|
end
|
|
if ( event == "PARTY_INVITE_CANCEL" ) then
|
|
StaticPopup_Hide("PARTY_INVITE");
|
|
return;
|
|
end
|
|
if ( event == "GUILD_INVITE_REQUEST" ) then
|
|
StaticPopup_Show("GUILD_INVITE", arg1, arg2);
|
|
return;
|
|
end
|
|
if ( event == "GUILD_INVITE_CANCEL" ) then
|
|
StaticPopup_Hide("GUILD_INVITE");
|
|
return;
|
|
end
|
|
if ( event == "ARENA_TEAM_INVITE_REQUEST" ) then
|
|
StaticPopup_Show("ARENA_TEAM_INVITE", arg1, arg2);
|
|
return;
|
|
end
|
|
if ( event == "ARENA_TEAM_INVITE_CANCEL" ) then
|
|
StaticPopup_Hide("ARENA_TEAM_INVITE");
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_CAMPING" ) then
|
|
StaticPopup_Show("CAMP");
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_QUITING" ) then
|
|
StaticPopup_Show("QUIT");
|
|
return;
|
|
end
|
|
if ( event == "LOGOUT_CANCEL" ) then
|
|
StaticPopup_Hide("CAMP");
|
|
StaticPopup_Hide("QUIT");
|
|
return;
|
|
end
|
|
if ( event == "LOOT_BIND_CONFIRM" ) then
|
|
local texture, item, quantity, quality, locked = GetLootSlotInfo(arg1);
|
|
local dialog = StaticPopup_Show("LOOT_BIND", ITEM_QUALITY_COLORS[quality].hex..item.."|r");
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "EQUIP_BIND_CONFIRM" ) then
|
|
StaticPopup_Hide("AUTOEQUIP_BIND");
|
|
local dialog = StaticPopup_Show("EQUIP_BIND");
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "AUTOEQUIP_BIND_CONFIRM" ) then
|
|
StaticPopup_Hide("EQUIP_BIND");
|
|
local dialog = StaticPopup_Show("AUTOEQUIP_BIND");
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "USE_BIND_CONFIRM" ) then
|
|
StaticPopup_Show("USE_BIND");
|
|
return;
|
|
end
|
|
if ( event == "DELETE_ITEM_CONFIRM" ) then
|
|
-- Check quality
|
|
if ( arg2 >= 3 ) then
|
|
StaticPopup_Show("DELETE_GOOD_ITEM", arg1);
|
|
else
|
|
StaticPopup_Show("DELETE_ITEM", arg1);
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "QUEST_ACCEPT_CONFIRM" ) then
|
|
local numEntries, numQuests = GetNumQuestLogEntries();
|
|
if( numQuests >= MAX_QUESTS) then
|
|
StaticPopup_Show("QUEST_ACCEPT_LOG_FULL", arg1, arg2);
|
|
else
|
|
StaticPopup_Show("QUEST_ACCEPT", arg1, arg2);
|
|
end
|
|
return;
|
|
end
|
|
if ( event =="QUEST_LOG_UPDATE" or event == "UNIT_QUEST_LOG_CHANGED" ) then
|
|
local frameName = StaticPopup_Visible("QUEST_ACCEPT_LOG_FULL");
|
|
if( frameName ) then
|
|
local numEntries, numQuests = GetNumQuestLogEntries();
|
|
local button = _G[frameName.."Button1"];
|
|
if( numQuests < MAX_QUESTS ) then
|
|
button:Enable();
|
|
else
|
|
button:Disable();
|
|
end
|
|
end
|
|
end
|
|
|
|
if ( event == "CURSOR_UPDATE" ) then
|
|
if ( not CursorHasItem() ) then
|
|
StaticPopup_Hide("EQUIP_BIND");
|
|
StaticPopup_Hide("AUTOEQUIP_BIND");
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_ENTERING_WORLD" ) then
|
|
-- Get multi-actionbar states (before CloseAllWindows() since that may be hooked by AddOns)
|
|
-- We don't want to call this, as the values GetActionBarToggles() returns are incorrect if it's called before the client mirrors SetActionBarToggles values from the server.
|
|
-- SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2, SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4 = GetActionBarToggles();
|
|
MultiActionBar_Update();
|
|
|
|
-- Close any windows that were previously open
|
|
CloseAllWindows(1);
|
|
|
|
-- Until PVPFrame is checked in, this is placed here.
|
|
for i=1, MAX_ARENA_TEAMS do
|
|
GetArenaTeam(i);
|
|
end
|
|
|
|
VoiceChat_Toggle();
|
|
|
|
-- Fix for Bug 124392
|
|
StaticPopup_Hide("LEVEL_GRANT_PROPOSED");
|
|
|
|
local _, instanceType = IsInInstance();
|
|
if ( instanceType == "arena" ) then
|
|
Arena_LoadUI();
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "RAID_ROSTER_UPDATE" ) then
|
|
-- Hide/Show party member frames
|
|
RaidOptionsFrame_UpdatePartyFrames();
|
|
end
|
|
if ( event == "MIRROR_TIMER_START" ) then
|
|
MirrorTimer_Show(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
return;
|
|
end
|
|
if ( event == "DUEL_REQUESTED" ) then
|
|
StaticPopup_Show("DUEL_REQUESTED", arg1);
|
|
return;
|
|
end
|
|
if ( event == "DUEL_OUTOFBOUNDS" ) then
|
|
StaticPopup_Show("DUEL_OUTOFBOUNDS");
|
|
return;
|
|
end
|
|
if ( event == "DUEL_INBOUNDS" ) then
|
|
StaticPopup_Hide("DUEL_OUTOFBOUNDS");
|
|
return;
|
|
end
|
|
if ( event == "DUEL_FINISHED" ) then
|
|
StaticPopup_Hide("DUEL_REQUESTED");
|
|
StaticPopup_Hide("DUEL_OUTOFBOUNDS");
|
|
return;
|
|
end
|
|
if ( event == "TRADE_REQUEST_CANCEL" ) then
|
|
StaticPopup_Hide("TRADE");
|
|
return;
|
|
end
|
|
if ( event == "CONFIRM_XP_LOSS" ) then
|
|
local resSicknessTime = GetResSicknessDuration();
|
|
if ( resSicknessTime ) then
|
|
local dialog = nil;
|
|
if (UnitLevel("player") <= 10) then
|
|
dialog = StaticPopup_Show("XP_LOSS_NO_DURABILITY", resSicknessTime);
|
|
else
|
|
dialog = StaticPopup_Show("XP_LOSS", resSicknessTime);
|
|
end
|
|
if ( dialog ) then
|
|
dialog.data = resSicknessTime;
|
|
end
|
|
else
|
|
local dialog = nil;
|
|
if (UnitLevel("player") <= 10) then
|
|
dialog = StaticPopup_Show("XP_LOSS_NO_SICKNESS_NO_DURABILITY");
|
|
else
|
|
dialog = StaticPopup_Show("XP_LOSS_NO_SICKNESS");
|
|
end
|
|
if ( dialog ) then
|
|
dialog.data = 1;
|
|
end
|
|
end
|
|
HideUIPanel(GossipFrame);
|
|
return;
|
|
end
|
|
if ( event == "CORPSE_IN_RANGE" ) then
|
|
StaticPopup_Show("RECOVER_CORPSE");
|
|
return;
|
|
end
|
|
if ( event == "CORPSE_IN_INSTANCE" ) then
|
|
StaticPopup_Show("RECOVER_CORPSE_INSTANCE");
|
|
return;
|
|
end
|
|
if ( event == "CORPSE_OUT_OF_RANGE" ) then
|
|
StaticPopup_Hide("RECOVER_CORPSE");
|
|
StaticPopup_Hide("RECOVER_CORPSE_INSTANCE");
|
|
StaticPopup_Hide("XP_LOSS");
|
|
return;
|
|
end
|
|
if ( event == "AREA_SPIRIT_HEALER_IN_RANGE" ) then
|
|
AcceptAreaSpiritHeal();
|
|
StaticPopup_Show("AREA_SPIRIT_HEAL");
|
|
return;
|
|
end
|
|
if ( event == "AREA_SPIRIT_HEALER_OUT_OF_RANGE" ) then
|
|
StaticPopup_Hide("AREA_SPIRIT_HEAL");
|
|
return;
|
|
end
|
|
if ( event == "BIND_ENCHANT" ) then
|
|
StaticPopup_Show("BIND_ENCHANT");
|
|
return;
|
|
end
|
|
if ( event == "REPLACE_ENCHANT" ) then
|
|
StaticPopup_Show("REPLACE_ENCHANT", arg1, arg2);
|
|
return;
|
|
end
|
|
if ( event == "TRADE_REPLACE_ENCHANT" ) then
|
|
StaticPopup_Show("TRADE_REPLACE_ENCHANT", arg1, arg2);
|
|
return;
|
|
end
|
|
if ( event == "END_REFUND" ) then
|
|
local dialog = StaticPopup_Show("END_REFUND");
|
|
if(dialog) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "END_BOUND_TRADEABLE" ) then
|
|
local dialog = StaticPopup_Show("END_BOUND_TRADEABLE", nil, nil, arg1);
|
|
return;
|
|
end
|
|
if ( event == "CURRENT_SPELL_CAST_CHANGED" ) then
|
|
StaticPopup_Hide("BIND_ENCHANT");
|
|
StaticPopup_Hide("REPLACE_ENCHANT");
|
|
StaticPopup_Hide("TRADE_REPLACE_ENCHANT");
|
|
StaticPopup_Hide("END_REFUND");
|
|
StaticPopup_Hide("END_BOUND_TRADEABLE");
|
|
return;
|
|
end
|
|
if ( event == "MACRO_ACTION_BLOCKED" or event == "ADDON_ACTION_BLOCKED" ) then
|
|
if ( not INTERFACE_ACTION_BLOCKED_SHOWN ) then
|
|
local info = ChatTypeInfo["SYSTEM"];
|
|
DEFAULT_CHAT_FRAME:AddMessage(INTERFACE_ACTION_BLOCKED, info.r, info.g, info.b, info.id);
|
|
INTERFACE_ACTION_BLOCKED_SHOWN = true;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "MACRO_ACTION_FORBIDDEN" ) then
|
|
StaticPopup_Show("MACRO_ACTION_FORBIDDEN");
|
|
return;
|
|
end
|
|
if ( event == "ADDON_ACTION_FORBIDDEN" ) then
|
|
local dialog = StaticPopup_Show("ADDON_ACTION_FORBIDDEN", arg1);
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_CONTROL_LOST" ) then
|
|
if ( UnitOnTaxi("player") ) then
|
|
return;
|
|
end
|
|
CloseAllWindows_WithExceptions();
|
|
|
|
--[[
|
|
-- Disable all microbuttons except the main menu
|
|
SetDesaturation(MicroButtonPortrait, 1);
|
|
|
|
Designers previously wanted these disabled when feared, they seem to have changed their minds
|
|
CharacterMicroButton:Disable();
|
|
SpellbookMicroButton:Disable();
|
|
TalentMicroButton:Disable();
|
|
QuestLogMicroButton:Disable();
|
|
SocialsMicroButton:Disable();
|
|
WorldMapMicroButton:Disable();
|
|
]]
|
|
|
|
UIParent.isOutOfControl = 1;
|
|
return;
|
|
end
|
|
if ( event == "PLAYER_CONTROL_GAINED" ) then
|
|
--[[
|
|
-- Enable all microbuttons
|
|
SetDesaturation(MicroButtonPortrait, nil);
|
|
|
|
CharacterMicroButton:Enable();
|
|
SpellbookMicroButton:Enable();
|
|
TalentMicroButton:Enable();
|
|
QuestLogMicroButton:Enable();
|
|
SocialsMicroButton:Enable();
|
|
WorldMapMicroButton:Enable();
|
|
]]
|
|
|
|
UIParent.isOutOfControl = nil;
|
|
return;
|
|
end
|
|
if ( event == "START_LOOT_ROLL" ) then
|
|
GroupLootFrame_OpenNewFrame(arg1, arg2);
|
|
return;
|
|
end
|
|
if ( event == "CONFIRM_LOOT_ROLL" ) then
|
|
local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
|
|
local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
|
|
if ( dialog ) then
|
|
dialog.text:SetFormattedText(LOOT_NO_DROP, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
|
|
StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
|
|
dialog.data = arg1;
|
|
dialog.data2 = arg2;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "CONFIRM_DISENCHANT_ROLL" ) then
|
|
local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
|
|
local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
|
|
if ( dialog ) then
|
|
dialog.text:SetFormattedText(LOOT_NO_DROP_DISENCHANT, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
|
|
StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
|
|
dialog.data = arg1;
|
|
dialog.data2 = arg2;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "INSTANCE_BOOT_START" ) then
|
|
StaticPopup_Show("INSTANCE_BOOT");
|
|
return;
|
|
end
|
|
if ( event == "INSTANCE_BOOT_STOP" ) then
|
|
StaticPopup_Hide("INSTANCE_BOOT");
|
|
return;
|
|
end
|
|
if ( event == "INSTANCE_LOCK_START" ) then
|
|
StaticPopup_Show("INSTANCE_LOCK");
|
|
return;
|
|
end
|
|
if ( event == "INSTANCE_LOCK_STOP" ) then
|
|
StaticPopup_Hide("INSTANCE_LOCK");
|
|
return;
|
|
end
|
|
if ( event == "CONFIRM_TALENT_WIPE" ) then
|
|
local dialog = StaticPopup_Show("CONFIRM_TALENT_WIPE");
|
|
if ( dialog ) then
|
|
MoneyFrame_Update(dialog:GetName().."MoneyFrame", arg1);
|
|
-- open the talent UI to the player's active talent group...just so the player knows
|
|
-- exactly which talent spec he is wiping
|
|
TalentFrame_LoadUI();
|
|
if ( PlayerTalentFrame_Open ) then
|
|
PlayerTalentFrame_Open(false, GetActiveTalentGroup());
|
|
end
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "CONFIRM_BINDER" ) then
|
|
StaticPopup_Show("CONFIRM_BINDER", arg1);
|
|
return;
|
|
end
|
|
if ( event == "CONFIRM_SUMMON" ) then
|
|
StaticPopup_Show("CONFIRM_SUMMON");
|
|
return;
|
|
end
|
|
if ( event == "CANCEL_SUMMON" ) then
|
|
StaticPopup_Hide("CONFIRM_SUMMON");
|
|
return;
|
|
end
|
|
if ( event == "BILLING_NAG_DIALOG" ) then
|
|
StaticPopup_Show("BILLING_NAG", arg1);
|
|
return;
|
|
end
|
|
if ( event == "IGR_BILLING_NAG_DIALOG" ) then
|
|
StaticPopup_Show("IGR_BILLING_NAG");
|
|
return;
|
|
end
|
|
if ( event == "GOSSIP_CONFIRM" ) then
|
|
if ( arg3 > 0 ) then
|
|
StaticPopupDialogs["GOSSIP_CONFIRM"].hasMoneyFrame = 1;
|
|
else
|
|
StaticPopupDialogs["GOSSIP_CONFIRM"].hasMoneyFrame = nil;
|
|
end
|
|
local dialog = StaticPopup_Show("GOSSIP_CONFIRM", arg2);
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
if ( arg3 > 0 ) then
|
|
MoneyFrame_Update(dialog:GetName().."MoneyFrame", arg3);
|
|
end
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "GOSSIP_ENTER_CODE" ) then
|
|
local dialog = StaticPopup_Show("GOSSIP_ENTER_CODE");
|
|
if ( dialog ) then
|
|
dialog.data = arg1;
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "GOSSIP_CONFIRM_CANCEL" or event == "GOSSIP_CLOSED" ) then
|
|
StaticPopup_Hide("GOSSIP_CONFIRM");
|
|
StaticPopup_Hide("GOSSIP_ENTER_CODE");
|
|
return;
|
|
end
|
|
|
|
-- Events for auction UI handling
|
|
if ( event == "AUCTION_HOUSE_SHOW" ) then
|
|
AuctionFrame_LoadUI();
|
|
if ( AuctionFrame_Show ) then
|
|
AuctionFrame_Show();
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "AUCTION_HOUSE_CLOSED" ) then
|
|
if ( AuctionFrame_Hide ) then
|
|
AuctionFrame_Hide();
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "AUCTION_HOUSE_DISABLED" ) then
|
|
StaticPopup_Show("AUCTION_HOUSE_DISABLED");
|
|
end
|
|
|
|
-- Events for trainer UI handling
|
|
if ( event == "TRAINER_SHOW" ) then
|
|
ClassTrainerFrame_LoadUI();
|
|
if ( ClassTrainerFrame_Show ) then
|
|
ClassTrainerFrame_Show();
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "TRAINER_CLOSED" ) then
|
|
if ( ClassTrainerFrame_Hide ) then
|
|
ClassTrainerFrame_Hide();
|
|
end
|
|
return;
|
|
end
|
|
|
|
-- Events for trade skill UI handling
|
|
if ( event == "TRADE_SKILL_SHOW" ) then
|
|
TradeSkillFrame_LoadUI();
|
|
if ( TradeSkillFrame_Show ) then
|
|
TradeSkillFrame_Show();
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "TRADE_SKILL_CLOSE" ) then
|
|
if ( TradeSkillFrame_Hide ) then
|
|
TradeSkillFrame_Hide();
|
|
end
|
|
return;
|
|
end
|
|
|
|
-- Event for item socketing handling
|
|
if ( event == "SOCKET_INFO_UPDATE" ) then
|
|
ItemSocketingFrame_LoadUI();
|
|
ItemSocketingFrame_Update();
|
|
ShowUIPanel(ItemSocketingFrame);
|
|
return;
|
|
end
|
|
|
|
-- Event for BarberShop handling
|
|
if ( event == "BARBER_SHOP_OPEN" ) then
|
|
BarberShopFrame_LoadUI();
|
|
if ( BarberShopFrame ) then
|
|
ShowUIPanel(BarberShopFrame);
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "BARBER_SHOP_CLOSE" ) then
|
|
if ( BarberShopFrame and BarberShopFrame:IsVisible() ) then
|
|
BarberShopFrame:Hide();
|
|
end
|
|
return;
|
|
end
|
|
|
|
-- Event for guildbank handling
|
|
if ( event == "GUILDBANKFRAME_OPENED" ) then
|
|
GuildBankFrame_LoadUI();
|
|
if ( GuildBankFrame ) then
|
|
ShowUIPanel(GuildBankFrame);
|
|
if ( not GuildBankFrame:IsVisible() ) then
|
|
CloseGuildBankFrame();
|
|
end
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "GUILDBANKFRAME_CLOSED" ) then
|
|
if ( GuildBankFrame ) then
|
|
HideUIPanel(GuildBankFrame);
|
|
end
|
|
return;
|
|
end
|
|
|
|
-- Event for barbershop handling
|
|
if ( event == "BARBER_SHOP_OPEN" ) then
|
|
BarberShopFrame_LoadUI();
|
|
if ( BarberShopFrame ) then
|
|
ShowUIPanel(BarberShopFrame);
|
|
end
|
|
elseif ( event == "BARBER_SHOP_CLOSE" ) then
|
|
BarberShopFrame_LoadUI();
|
|
if ( BarberShopFrame ) then
|
|
HideUIPanel(BarberShopFrame);
|
|
end
|
|
end
|
|
|
|
-- Events for achievement handling
|
|
if ( event == "ACHIEVEMENT_EARNED" ) then
|
|
-- if ( not AchievementFrame ) then
|
|
-- AchievementFrame_LoadUI();
|
|
-- AchievementAlertFrame_ShowAlert(...);
|
|
-- end
|
|
-- self:UnregisterEvent(event);
|
|
end
|
|
|
|
-- Events for Glyphs
|
|
if ( event == "USE_GLYPH" ) then
|
|
OpenGlyphFrame();
|
|
return;
|
|
end
|
|
|
|
-- Display instance reset info
|
|
if ( event == "RAID_INSTANCE_WELCOME" ) then
|
|
local dungeonName = arg1;
|
|
local lockExpireTime = arg2;
|
|
local locked = arg3;
|
|
local extended = arg4;
|
|
local message;
|
|
|
|
if ( locked == 0 ) then
|
|
message = format(RAID_INSTANCE_WELCOME, dungeonName, SecondsToTime(lockExpireTime, nil, 1))
|
|
else
|
|
if ( lockExpireTime == 0 ) then
|
|
message = format(RAID_INSTANCE_WELCOME_EXTENDED, dungeonName);
|
|
else
|
|
if ( extended == 0 ) then
|
|
message = format(RAID_INSTANCE_WELCOME_LOCKED, dungeonName, SecondsToTime(lockExpireTime, nil, 1));
|
|
else
|
|
message = format(RAID_INSTANCE_WELCOME_LOCKED_EXTENDED, dungeonName, SecondsToTime(lockExpireTime, nil, 1));
|
|
end
|
|
end
|
|
end
|
|
|
|
local info = ChatTypeInfo["SYSTEM"];
|
|
DEFAULT_CHAT_FRAME:AddMessage(message, info.r, info.g, info.b, info.id);
|
|
return;
|
|
end
|
|
|
|
-- Events for taxi benchmarking
|
|
if ( event == "ENABLE_TAXI_BENCHMARK" ) then
|
|
if ( not FramerateText:IsShown() ) then
|
|
ToggleFramerate(true);
|
|
end
|
|
local info = ChatTypeInfo["SYSTEM"];
|
|
DEFAULT_CHAT_FRAME:AddMessage(BENCHMARK_TAXI_MODE_ON, info.r, info.g, info.b, info.id);
|
|
return;
|
|
end
|
|
if ( event == "DISABLE_TAXI_BENCHMARK" ) then
|
|
if ( FramerateText.benchmark ) then
|
|
ToggleFramerate();
|
|
end
|
|
local info = ChatTypeInfo["SYSTEM"];
|
|
DEFAULT_CHAT_FRAME:AddMessage(BENCHMARK_TAXI_MODE_OFF, info.r, info.g, info.b, info.id);
|
|
return;
|
|
end
|
|
|
|
-- Push to talk
|
|
if ( event == "VOICE_PUSH_TO_TALK_START" and GetVoiceCurrentSessionID() ) then
|
|
if ( GetCVarBool("PushToTalkSound") ) then
|
|
PlaySound("VoiceChatOn");
|
|
end
|
|
-- Animate the player frame speaker even if not broadcasting
|
|
if ( GetCVar("VoiceChatMode") == "0" ) then
|
|
UIFrameFadeIn(PlayerSpeakerFrame, 0.2, PlayerSpeakerFrame:GetAlpha(), 1);
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "VOICE_PUSH_TO_TALK_STOP" ) then
|
|
if ( GetCVarBool("PushToTalkSound") and GetVoiceCurrentSessionID() ) then
|
|
PlaySound("VoiceChatOff");
|
|
end
|
|
-- Stop Animation
|
|
if ( GetCVar("VoiceChatMode") == "0" and PlayerSpeakerFrame:GetAlpha() > 0 ) then
|
|
UIFrameFadeOut(PlayerSpeakerFrame, 0.2, PlayerSpeakerFrame:GetAlpha(), 0);
|
|
end
|
|
return;
|
|
end
|
|
if ( event == "LEVEL_GRANT_PROPOSED" ) then
|
|
StaticPopup_Show("LEVEL_GRANT_PROPOSED", arg1);
|
|
return;
|
|
end
|
|
|
|
if ( event == "CHAT_MSG_WHISPER" and arg6 == "GM" ) then --GMChatUI
|
|
GMChatFrame_LoadUI(event, ...);
|
|
end
|
|
|
|
if ( event == "WOW_MOUSE_NOT_FOUND" ) then
|
|
StaticPopup_Show("WOW_MOUSE_NOT_FOUND");
|
|
end
|
|
|
|
if ( event == "TALENTS_INVOLUNTARILY_RESET" ) then
|
|
if ( arg1 ) then
|
|
StaticPopup_Show("TALENTS_INVOLUNTARILY_RESET_PET");
|
|
else
|
|
StaticPopup_Show("TALENTS_INVOLUNTARILY_RESET");
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Frame Management --
|
|
|
|
-- UIPARENT_MANAGED_FRAME_POSITIONS stores all the frames that have positioning dependencies based on other frames.
|
|
|
|
-- UIPARENT_MANAGED_FRAME_POSITIONS["FRAME"] = {
|
|
-- none = This value is used if no dependent frames are shown
|
|
-- reputation = This is the offset used if the reputation watch bar is shown
|
|
-- anchorTo = This is the object that the stored frame is anchored to
|
|
-- point = This is the point on the frame used as the anchor
|
|
-- rpoint = This is the point on the "anchorTo" frame that the stored frame is anchored to
|
|
-- bottomEither = This offset is used if either bottom multibar is shown
|
|
-- bottomLeft
|
|
-- var = If this is set use _G[varName] = value instead of setpoint
|
|
-- };
|
|
|
|
|
|
-- some standard offsets
|
|
local actionBarOffset = 45;
|
|
local menuBarTop = 55;
|
|
local vehicleMenuBarTop = 40;
|
|
|
|
function UpdateMenuBarTop ()
|
|
--Determines the optimal magic number based on resolution and action bar status.
|
|
menuBarTop = 55;
|
|
local width, height = string.match((({GetScreenResolutions()})[GetCurrentResolution()] or ""), "(%d+).-(%d+)");
|
|
if ( tonumber(width) / tonumber(height ) > 4/3 ) then
|
|
--Widescreen resolution
|
|
menuBarTop = 75;
|
|
end
|
|
end
|
|
|
|
UIPARENT_MANAGED_FRAME_POSITIONS = {
|
|
--Items with baseY set to "true" are positioned based on the value of menuBarTop and their offset needs to be repeatedly evaluated as menuBarTop can change.
|
|
--"yOffset" gets added to the value of "baseY", which is used for values based on menuBarTop.
|
|
["MultiBarBottomLeft"] = {baseY = 17, reputation = 1, maxLevel = 1, anchorTo = "ActionButton1", point = "BOTTOMLEFT", rpoint = "TOPLEFT"};
|
|
["MultiBarRight"] = {baseY = 98, reputation = 1, anchorTo = "UIParent", point = "BOTTOMRIGHT", rpoint = "BOTTOMRIGHT"};
|
|
["VoiceChatTalkers"] = {baseY = true, bottomEither = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, reputation = 1};
|
|
["GroupLootFrame1"] = {baseY = true, bottomEither = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, pet = 1, reputation = 1};
|
|
["TutorialFrameAlertButton"] = {baseY = true, yOffset = -10, bottomEither = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, reputation = 1};
|
|
["FramerateLabel"] = {baseY = true, bottomEither = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, pet = 1, reputation = 1};
|
|
["CastingBarFrame"] = {baseY = true, yOffset = 40, bottomEither = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, pet = 1, reputation = 1, tutorialAlert = 1};
|
|
["ChatFrame1"] = {baseY = true, yOffset = 40, bottomLeft = actionBarOffset-8, justBottomRightAndShapeshift = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, pet = 1, reputation = 1, maxLevel = 1, point = "BOTTOMLEFT", rpoint = "BOTTOMLEFT", xOffset = 32};
|
|
["ChatFrame2"] = {baseY = true, yOffset = 40, bottomRight = actionBarOffset-8, vehicleMenuBar = vehicleMenuBarTop, rightLeft = -2*actionBarOffset, rightRight = -actionBarOffset, reputation = 1, maxLevel = 1, point = "BOTTOMRIGHT", rpoint = "BOTTOMRIGHT", xOffset = -32};
|
|
["ShapeshiftBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
|
|
["PossessBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
|
|
["MultiCastActionBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
|
|
["AuctionProgressFrame"] = {baseY = true, yOffset = 18, bottomEither = actionBarOffset, vehicleMenuBar = vehicleMenuBarTop, pet = 1, reputation = 1, tutorialAlert = 1};
|
|
|
|
-- Vars
|
|
-- These indexes require global variables of the same name to be declared. For example, if I have an index ["FOO"] then I need to make sure the global variable
|
|
-- FOO exists before this table is constructed. The function UIParent_ManageFramePosition will use the "FOO" table index to change the value of the FOO global
|
|
-- variable so that other modules can use the most up-to-date value of FOO without having knowledge of the UIPARENT_MANAGED_FRAME_POSITIONS table.
|
|
["CONTAINER_OFFSET_X"] = {baseX = 0, rightLeft = 2*actionBarOffset+3, rightRight = actionBarOffset+3, isVar = "xAxis"};
|
|
["CONTAINER_OFFSET_Y"] = {baseY = true, yOffset = 10, bottomEither = actionBarOffset, reputation = 1, isVar = "yAxis"};
|
|
["BATTLEFIELD_TAB_OFFSET_Y"] = {baseY = 210, bottomRight = actionBarOffset, reputation = 1, isVar = "yAxis"};
|
|
["PETACTIONBAR_YPOS"] = {baseY = 97, bottomLeft = actionBarOffset, justBottomRightAndShapeshift = actionBarOffset, reputation = 1, maxLevel = 1, isVar = "yAxis"};
|
|
["MULTICASTACTIONBAR_YPOS"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, isVar = "yAxis"};
|
|
};
|
|
|
|
-- If any Var entries in UIPARENT_MANAGED_FRAME_POSITIONS are used exclusively by addons, they should be declared here and not in one of the addon's files.
|
|
-- The reason why is that it is possible for UIParent_ManageFramePosition to be run before the addon loads.
|
|
BATTLEFIELD_TAB_OFFSET_Y = 0;
|
|
|
|
|
|
-- constant offsets
|
|
for _, data in pairs(UIPARENT_MANAGED_FRAME_POSITIONS) do
|
|
for flag, value in pairs(data) do
|
|
if ( flag == "reputation" ) then
|
|
data[flag] = value * 9;
|
|
elseif ( flag == "maxLevel" ) then
|
|
data[flag] = value * -5;
|
|
elseif ( flag == "pet" ) then
|
|
data[flag] = value * 35;
|
|
elseif ( flag == "tutorialAlert" ) then
|
|
data[flag] = value * 35;
|
|
end
|
|
end
|
|
end
|
|
|
|
function UIParent_ManageFramePosition(index, value, yOffsetFrames, xOffsetFrames, hasBottomLeft, hasBottomRight, hasPetBar)
|
|
local frame, xOffset, yOffset, anchorTo, point, rpoint;
|
|
|
|
frame = _G[index];
|
|
if ( not frame or (type(frame)=="table" and frame.ignoreFramePositionManager)) then
|
|
return;
|
|
end
|
|
|
|
-- Always start with base as the base offset or default to zero if no "none" specified
|
|
xOffset = 0;
|
|
if ( value["baseX"] ) then
|
|
xOffset = value["baseX"];
|
|
elseif ( value["xOffset"] ) then
|
|
xOffset = value["xOffset"];
|
|
end
|
|
yOffset = 0;
|
|
if ( tonumber(value["baseY"]) ) then
|
|
--tonumber(nil) and tonumber(boolean) evaluate as nil, tonumber(number) evaluates as a number, which evaluates as true.
|
|
--This allows us to use the true value in baseY for flagging a frame's positioning as dependent upon the value of menuBarTop.
|
|
yOffset = value["baseY"];
|
|
elseif ( value["baseY"] ) then
|
|
--value["baseY"] is true, use menuBarTop.
|
|
yOffset = menuBarTop;
|
|
end
|
|
|
|
if ( value["yOffset"] ) then
|
|
--This is so things based on menuBarTop can still have an offset. Otherwise you'd just use put the offset value in baseY.
|
|
yOffset = yOffset + value["yOffset"];
|
|
end
|
|
|
|
-- Iterate through frames that affect y offsets
|
|
local hasBottomEitherFlag;
|
|
for _, flag in pairs(yOffsetFrames) do
|
|
if ( value[flag] ) then
|
|
if ( flag == "bottomEither" ) then
|
|
hasBottomEitherFlag = 1;
|
|
end
|
|
yOffset = yOffset + value[flag];
|
|
end
|
|
end
|
|
|
|
-- don't offset for the pet bar and bottomEither if the player has
|
|
-- the bottom right bar shown and not the bottom left
|
|
if ( hasBottomEitherFlag and hasBottomRight and hasPetBar and not hasBottomLeft ) then
|
|
yOffset = yOffset - (value["pet"] or 0);
|
|
end
|
|
|
|
-- Iterate through frames that affect x offsets
|
|
for _, flag in pairs(xOffsetFrames) do
|
|
if ( value[flag] ) then
|
|
xOffset = xOffset + value[flag];
|
|
end
|
|
end
|
|
|
|
-- Set up anchoring info
|
|
anchorTo = value["anchorTo"];
|
|
point = value["point"];
|
|
rpoint = value["rpoint"];
|
|
if ( not anchorTo ) then
|
|
anchorTo = "UIParent";
|
|
end
|
|
if ( not point ) then
|
|
point = "BOTTOM";
|
|
end
|
|
if ( not rpoint ) then
|
|
rpoint = "BOTTOM";
|
|
end
|
|
|
|
-- Anchor frame
|
|
if ( value["isVar"] ) then
|
|
if ( value["isVar"] == "xAxis" ) then
|
|
_G[index] = xOffset;
|
|
else
|
|
_G[index] = yOffset;
|
|
end
|
|
else
|
|
if ( frame ~= ChatFrame2 and not(frame:IsObjectType("frame") and frame:IsUserPlaced()) ) then
|
|
frame:SetPoint(point, anchorTo, rpoint, xOffset, yOffset);
|
|
end
|
|
end
|
|
end
|
|
|
|
local function FramePositionDelegate_OnAttributeChanged(self, attribute)
|
|
if ( attribute == "panel-show" ) then
|
|
local force = self:GetAttribute("panel-force");
|
|
local frame = self:GetAttribute("panel-frame");
|
|
self:ShowUIPanel(frame, force);
|
|
elseif ( attribute == "panel-hide" ) then
|
|
local frame = self:GetAttribute("panel-frame");
|
|
local skipSetPoint = self:GetAttribute("panel-skipSetPoint");
|
|
self:HideUIPanel(frame, skipSetPoint);
|
|
elseif ( attribute == "panel-update" ) then
|
|
local frame = self:GetAttribute("panel-frame");
|
|
self:UpdateUIPanelPositions(frame);
|
|
elseif ( attribute == "uiparent-manage" ) then
|
|
self:UIParentManageFramePositions();
|
|
end
|
|
end
|
|
|
|
local FramePositionDelegate = CreateFrame("FRAME");
|
|
FramePositionDelegate:SetScript("OnAttributeChanged", FramePositionDelegate_OnAttributeChanged);
|
|
|
|
function FramePositionDelegate:ShowUIPanel(frame, force)
|
|
local frameArea, framePushable;
|
|
frameArea = GetUIPanelWindowInfo(frame, "area");
|
|
if ( not CanOpenPanels() and frameArea ~= "center" and frameArea ~= "full" ) then
|
|
self:ShowUIPanelFailed(frame);
|
|
return;
|
|
end
|
|
framePushable = GetUIPanelWindowInfo(frame, "pushable") or 0;
|
|
|
|
if ( UnitIsDead("player") and not GetUIPanelWindowInfo(frame, "whileDead") ) then
|
|
NotWhileDeadError();
|
|
return;
|
|
end
|
|
|
|
-- If we have a full-screen frame open, ignore other non-fullscreen open requests
|
|
if ( self:GetUIPanel("fullscreen") and (frameArea ~= "full") ) then
|
|
if ( force ) then
|
|
self:SetUIPanel("fullscreen", nil, 1);
|
|
else
|
|
self:ShowUIPanelFailed(frame);
|
|
return;
|
|
end
|
|
end
|
|
|
|
-- If we have a "center" frame open, only listen to other "center" open requests
|
|
local centerFrame = self:GetUIPanel("center");
|
|
local centerArea, centerPushable;
|
|
if ( centerFrame ) then
|
|
if ( GetUIPanelWindowInfo(centerFrame, "allowOtherPanels") ) then
|
|
HideUIPanel(centerFrame);
|
|
centerFrame = nil;
|
|
else
|
|
centerArea = GetUIPanelWindowInfo(centerFrame, "area");
|
|
if ( centerArea and (centerArea == "center") and (frameArea ~= "center") and (frameArea ~= "full") ) then
|
|
if ( force ) then
|
|
self:SetUIPanel("center", nil, 1);
|
|
else
|
|
self:ShowUIPanelFailed(frame);
|
|
return;
|
|
end
|
|
end
|
|
centerPushable = GetUIPanelWindowInfo(centerFrame, "pushable") or 0;
|
|
end
|
|
end
|
|
|
|
-- Full-screen frames just replace each other
|
|
if ( frameArea == "full" ) then
|
|
securecall("CloseAllWindows");
|
|
self:SetUIPanel("fullscreen", frame);
|
|
return;
|
|
end
|
|
|
|
-- Native "center" frames just replace each other, and they take priority over pushed frames
|
|
if ( frameArea == "center" ) then
|
|
securecall("CloseWindows");
|
|
if ( not GetUIPanelWindowInfo(frame, "allowOtherPanels") ) then
|
|
securecall("CloseAllBags");
|
|
end
|
|
self:SetUIPanel("center", frame, 1);
|
|
return;
|
|
end
|
|
|
|
-- Doublewide frames take up the left and center spots
|
|
if ( frameArea == "doublewide" ) then
|
|
local leftFrame = self:GetUIPanel("left");
|
|
if ( leftFrame ) then
|
|
local leftPushable = GetUIPanelWindowInfo(leftFrame, "pushable") or 0;
|
|
if ( leftPushable > 0 and CanShowRightUIPanel(leftFrame) ) then
|
|
-- Push left to right
|
|
self:MoveUIPanel("left", "right", 1);
|
|
elseif ( centerFrame and CanShowRightUIPanel(centerFrame) ) then
|
|
self:MoveUIPanel("center", "right", 1);
|
|
end
|
|
end
|
|
self:SetUIPanel("doublewide", frame);
|
|
return;
|
|
end
|
|
|
|
-- If not pushable, close any doublewide frames
|
|
local doublewideFrame = self:GetUIPanel("doublewide");
|
|
if ( doublewideFrame ) then
|
|
if ( framePushable == 0 ) then
|
|
-- Set as left (closes doublewide) and slide over the right frame
|
|
self:SetUIPanel("left", frame, 1);
|
|
self:MoveUIPanel("right", "center");
|
|
elseif ( CanShowRightUIPanel(frame) ) then
|
|
-- Set as right
|
|
self:SetUIPanel("right", frame);
|
|
else
|
|
self:SetUIPanel("left", frame);
|
|
end
|
|
return;
|
|
end
|
|
|
|
-- Try to put it on the left
|
|
local leftFrame = self:GetUIPanel("left");
|
|
if ( not leftFrame ) then
|
|
self:SetUIPanel("left", frame);
|
|
return;
|
|
end
|
|
local leftPushable = GetUIPanelWindowInfo(leftFrame, "pushable") or 0;
|
|
|
|
-- Two open already
|
|
local rightFrame = self:GetUIPanel("right");
|
|
if ( centerFrame and not rightFrame ) then
|
|
-- If not pushable and left isn't pushable
|
|
if ( leftPushable == 0 and framePushable == 0 ) then
|
|
-- Replace left
|
|
self:SetUIPanel("left", frame);
|
|
elseif ( ( framePushable > centerPushable or centerArea == "center" ) and CanShowRightUIPanel(frame) ) then
|
|
-- This one is highest priority, show as right
|
|
self:SetUIPanel("right", frame);
|
|
elseif ( framePushable < leftPushable ) then
|
|
if ( centerArea == "center" ) then
|
|
if ( CanShowRightUIPanel(leftFrame) ) then
|
|
-- Skip center
|
|
self:MoveUIPanel("left", "right", 1);
|
|
self:SetUIPanel("left", frame);
|
|
else
|
|
-- Replace left
|
|
self:SetUIPanel("left", frame);
|
|
end
|
|
else
|
|
if ( CanShowUIPanels(frame, leftFrame, centerFrame) ) then
|
|
-- Shift both
|
|
self:MoveUIPanel("center", "right", 1);
|
|
self:MoveUIPanel("left", "center", 1);
|
|
self:SetUIPanel("left", frame);
|
|
else
|
|
-- Replace left
|
|
self:SetUIPanel("left", frame);
|
|
end
|
|
end
|
|
elseif ( framePushable <= centerPushable and centerArea ~= "center" and CanShowUIPanels(leftFrame, frame, centerFrame) ) then
|
|
-- Push center
|
|
self:MoveUIPanel("center", "right", 1);
|
|
self:SetUIPanel("center", frame);
|
|
elseif ( framePushable <= centerPushable and centerArea ~= "center" ) then
|
|
-- Replace left
|
|
self:SetUIPanel("left", frame);
|
|
else
|
|
-- Replace center
|
|
self:SetUIPanel("center", frame);
|
|
end
|
|
|
|
return;
|
|
end
|
|
|
|
-- If there's only one open...
|
|
if ( not centerFrame ) then
|
|
-- If neither is pushable, replace
|
|
if ( (leftPushable == 0) and (framePushable == 0) ) then
|
|
self:SetUIPanel("left", frame);
|
|
return;
|
|
end
|
|
|
|
-- Highest priority goes to center
|
|
if ( leftPushable > framePushable ) then
|
|
self:MoveUIPanel("left", "center", 1);
|
|
self:SetUIPanel("left", frame);
|
|
else
|
|
self:SetUIPanel("center", frame);
|
|
end
|
|
|
|
return;
|
|
end
|
|
|
|
-- Three are shown
|
|
local rightPushable = GetUIPanelWindowInfo(rightFrame, "pushable") or 0;
|
|
if ( framePushable > rightPushable ) then
|
|
-- This one is highest priority, slide the other two over
|
|
if ( CanShowUIPanels(centerFrame, rightFrame, frame) ) then
|
|
self:MoveUIPanel("center", "left", 1);
|
|
self:MoveUIPanel("right", "center", 1);
|
|
self:SetUIPanel("right", frame);
|
|
else
|
|
self:MoveUIPanel("right", "left", 1);
|
|
self:SetUIPanel("center", frame);
|
|
end
|
|
elseif ( framePushable > centerPushable ) then
|
|
-- This one is middle priority, so move the center frame to the left
|
|
self:MoveUIPanel("center", "left", 1);
|
|
self:SetUIPanel("center", frame);
|
|
else
|
|
self:SetUIPanel("left", frame);
|
|
end
|
|
end
|
|
|
|
function FramePositionDelegate:ShowUIPanelFailed(frame)
|
|
local showFailedFunc = _G[GetUIPanelWindowInfo(frame, "showFailedFunc")];
|
|
if ( showFailedFunc ) then
|
|
showFailedFunc(frame);
|
|
end
|
|
end
|
|
|
|
function FramePositionDelegate:SetUIPanel(key, frame, skipSetPoint)
|
|
if ( key == "fullscreen" ) then
|
|
local oldFrame = self.fullscreen;
|
|
self.fullscreen = frame;
|
|
|
|
if ( oldFrame ) then
|
|
oldFrame:Hide();
|
|
end
|
|
|
|
if ( frame ) then
|
|
UIParent:Hide();
|
|
frame:Show();
|
|
else
|
|
UIParent:Show();
|
|
SetUIVisibility(true);
|
|
end
|
|
return;
|
|
elseif ( key == "doublewide" ) then
|
|
local oldLeft = self.left;
|
|
local oldCenter = self.center;
|
|
local oldDoubleWide = self.doublewide;
|
|
self.doublewide = frame;
|
|
self.left = nil;
|
|
self.center = nil;
|
|
|
|
if ( oldDoubleWide ) then
|
|
oldDoubleWide:Hide();
|
|
end
|
|
|
|
if ( oldLeft ) then
|
|
oldLeft:Hide();
|
|
end
|
|
|
|
if ( oldCenter ) then
|
|
oldCenter:Hide();
|
|
end
|
|
elseif ( key ~= "left" and key ~= "center" and key ~= "right" ) then
|
|
return;
|
|
else
|
|
local oldFrame = self[key];
|
|
self[key] = frame;
|
|
if ( oldFrame ) then
|
|
oldFrame:Hide();
|
|
else
|
|
if ( self.doublewide ) then
|
|
if ( key == "left" or key == "center" ) then
|
|
self.doublewide:Hide();
|
|
self.doublewide = nil;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if ( not skipSetPoint ) then
|
|
securecall("UpdateUIPanelPositions");
|
|
end
|
|
|
|
if ( frame ) then
|
|
frame:Show();
|
|
-- Hide all child windows
|
|
securecall("CloseChildWindows");
|
|
end
|
|
end
|
|
|
|
function FramePositionDelegate:MoveUIPanel(current, new, skipSetPoint)
|
|
if ( current ~= "left" and current ~= "center" and current ~= "right" and new ~= "left" and new ~= "center" and new ~= "right" ) then
|
|
return;
|
|
end
|
|
|
|
self:SetUIPanel(new, nil, skipSetPoint);
|
|
if ( self[current] ) then
|
|
self[current]:Raise();
|
|
self[new] = self[current];
|
|
self[current] = nil;
|
|
if ( not skipSetPoint ) then
|
|
securecall("UpdateUIPanelPositions");
|
|
end
|
|
end
|
|
end
|
|
|
|
function FramePositionDelegate:HideUIPanel(frame, skipSetPoint)
|
|
-- If we're hiding the full-screen frame, just hide it
|
|
if ( frame == self:GetUIPanel("fullscreen") ) then
|
|
self:SetUIPanel("fullscreen", nil);
|
|
return;
|
|
end
|
|
|
|
-- If we're hiding the right frame, just hide it
|
|
if ( frame == self:GetUIPanel("right") ) then
|
|
self:SetUIPanel("right", nil, skipSetPoint);
|
|
return;
|
|
elseif ( frame == self:GetUIPanel("doublewide") ) then
|
|
-- Slide over any right frame (hides the doublewide)
|
|
self:MoveUIPanel("right", "left", skipSetPoint);
|
|
return;
|
|
end
|
|
|
|
-- If we're hiding the center frame, slide over any right frame
|
|
local centerFrame = self:GetUIPanel("center");
|
|
if ( frame == centerFrame ) then
|
|
self:MoveUIPanel("right", "center", skipSetPoint);
|
|
elseif ( frame == self:GetUIPanel("left") ) then
|
|
-- If we're hiding the left frame, move the other frames left, unless the center is a native center frame
|
|
if ( centerFrame ) then
|
|
local area = GetUIPanelWindowInfo(centerFrame, "area");
|
|
if ( area ) then
|
|
if ( area == "center" ) then
|
|
-- Slide left, skip the center
|
|
self:MoveUIPanel("right", "left", skipSetPoint);
|
|
return;
|
|
else
|
|
-- Slide everything left
|
|
self:MoveUIPanel("center", "left", 1);
|
|
self:MoveUIPanel("right", "center", skipSetPoint);
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
self:SetUIPanel("left", nil, skipSetPoint);
|
|
else
|
|
frame:Hide();
|
|
end
|
|
end
|
|
|
|
function FramePositionDelegate:GetUIPanel(key)
|
|
if ( key ~= "left" and key ~= "center" and key ~= "right" and key ~= "doublewide" and key ~= "fullscreen" ) then
|
|
return nil;
|
|
end
|
|
|
|
return self[key];
|
|
end
|
|
|
|
function FramePositionDelegate:UpdateUIPanelPositions(currentFrame)
|
|
if ( self.updatingPanels ) then
|
|
return;
|
|
end
|
|
self.updatingPanels = true;
|
|
|
|
local topOffset = UIParent:GetAttribute("TOP_OFFSET");
|
|
local leftOffset = UIParent:GetAttribute("LEFT_OFFSET");
|
|
local centerOffset = UIParent:GetAttribute("CENTER_OFFSET");
|
|
local rightOffset = UIParent:GetAttribute("RIGHT_OFFSET");
|
|
|
|
local info;
|
|
local frame = self:GetUIPanel("left");
|
|
if ( frame ) then
|
|
local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
|
|
local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
|
|
frame:ClearAllPoints();
|
|
frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", leftOffset + xOff, topOffset + yOff);
|
|
centerOffset = leftOffset + GetUIPanelWidth(frame) + xOff;
|
|
UIParent:SetAttribute("CENTER_OFFSET", centerOffset);
|
|
frame:Raise();
|
|
else
|
|
frame = self:GetUIPanel("doublewide");
|
|
if ( frame ) then
|
|
local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
|
|
local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
|
|
frame:ClearAllPoints();
|
|
frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", leftOffset + xOff, topOffset + yOff);
|
|
rightOffset = leftOffset + GetUIPanelWidth(frame) + xOff;
|
|
UIParent:SetAttribute("RIGHT_OFFSET", rightOffset);
|
|
frame:Raise();
|
|
end
|
|
end
|
|
|
|
frame = self:GetUIPanel("center");
|
|
if ( frame ) then
|
|
if ( CanShowCenterUIPanel(frame) ) then
|
|
local area = GetUIPanelWindowInfo(frame, "area");
|
|
local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
|
|
local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
|
|
if ( area ~= "center" ) then
|
|
frame:ClearAllPoints();
|
|
frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", centerOffset + xOff, topOffset + yOff);
|
|
end
|
|
rightOffset = centerOffset + GetUIPanelWidth(frame) + xOff;
|
|
else
|
|
if ( frame == currentFrame ) then
|
|
frame = self:GetUIPanel("left") or self:GetUIPanel("doublewide");
|
|
if ( frame ) then
|
|
self:HideUIPanel(frame);
|
|
self.updatingPanels = nil;
|
|
self:UpdateUIPanelPositions(currentFrame);
|
|
return;
|
|
end
|
|
end
|
|
self:SetUIPanel("center", nil, 1);
|
|
rightOffset = centerOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
|
|
end
|
|
frame:Raise();
|
|
elseif ( not self:GetUIPanel("doublewide") ) then
|
|
if ( self:GetUIPanel("left") ) then
|
|
rightOffset = centerOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
|
|
else
|
|
rightOffset = leftOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH") * 2
|
|
end
|
|
end
|
|
UIParent:SetAttribute("RIGHT_OFFSET", rightOffset);
|
|
|
|
frame = self:GetUIPanel("right");
|
|
if ( frame ) then
|
|
if ( CanShowRightUIPanel(frame) ) then
|
|
local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
|
|
local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
|
|
frame:ClearAllPoints();
|
|
frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", rightOffset + xOff, topOffset + yOff);
|
|
else
|
|
if ( frame == currentFrame ) then
|
|
frame = GetUIPanel("center") or GetUIPanel("left") or GetUIPanel("doublewide");
|
|
if ( frame ) then
|
|
self:HideUIPanel(frame);
|
|
self.updatingPanels = nil;
|
|
self:UpdateUIPanelPositions(currentFrame);
|
|
return;
|
|
end
|
|
end
|
|
self:SetUIPanel("right", nil, 1);
|
|
end
|
|
frame:Raise();
|
|
end
|
|
|
|
self.updatingPanels = nil;
|
|
end
|
|
|
|
function FramePositionDelegate:UIParentManageFramePositions()
|
|
-- Update the variable with the happy magic number.
|
|
UpdateMenuBarTop();
|
|
|
|
-- Frames that affect offsets in y axis
|
|
local yOffsetFrames = {};
|
|
-- Frames that affect offsets in x axis
|
|
local xOffsetFrames = {};
|
|
|
|
-- Set up flags
|
|
local hasBottomLeft, hasBottomRight, hasPetBar;
|
|
|
|
if ( VehicleMenuBar and VehicleMenuBar:IsShown() ) then
|
|
tinsert(yOffsetFrames, "vehicleMenuBar");
|
|
else
|
|
if ( MultiBarBottomLeft:IsShown() or MultiBarBottomRight:IsShown() ) then
|
|
tinsert(yOffsetFrames, "bottomEither");
|
|
end
|
|
if ( MultiBarBottomRight:IsShown() ) then
|
|
tinsert(yOffsetFrames, "bottomRight");
|
|
hasBottomRight = 1;
|
|
end
|
|
if ( MultiBarBottomLeft:IsShown() ) then
|
|
tinsert(yOffsetFrames, "bottomLeft");
|
|
hasBottomLeft = 1;
|
|
end
|
|
if ( MultiBarLeft:IsShown() ) then
|
|
tinsert(xOffsetFrames, "rightLeft");
|
|
elseif ( MultiBarRight:IsShown() ) then
|
|
tinsert(xOffsetFrames, "rightRight");
|
|
end
|
|
if (PetActionBarFrame_IsAboveShapeshift and PetActionBarFrame_IsAboveShapeshift()) then
|
|
tinsert(yOffsetFrames, "justBottomRightAndShapeshift");
|
|
end
|
|
if ( ( PetActionBarFrame and PetActionBarFrame:IsShown() ) or ( ShapeshiftBarFrame and ShapeshiftBarFrame:IsShown() ) or
|
|
( MultiCastActionBarFrame and MultiCastActionBarFrame:IsShown() ) or ( PossessBarFrame and PossessBarFrame:IsShown() ) or
|
|
( MainMenuBarVehicleLeaveButton and MainMenuBarVehicleLeaveButton:IsShown() ) ) then
|
|
tinsert(yOffsetFrames, "pet");
|
|
hasPetBar = 1;
|
|
end
|
|
if ( ReputationWatchBar:IsShown() and MainMenuExpBar:IsShown() ) then
|
|
tinsert(yOffsetFrames, "reputation");
|
|
end
|
|
if ( MainMenuBarMaxLevelBar:IsShown() ) then
|
|
tinsert(yOffsetFrames, "maxLevel");
|
|
end
|
|
if ( TutorialFrameAlertButton:IsShown() ) then
|
|
tinsert(yOffsetFrames, "tutorialAlert");
|
|
end
|
|
end
|
|
|
|
if ( menuBarTop == 55 ) then
|
|
UIPARENT_MANAGED_FRAME_POSITIONS["TutorialFrameAlertButton"].yOffset = -10;
|
|
else
|
|
UIPARENT_MANAGED_FRAME_POSITIONS["TutorialFrameAlertButton"].yOffset = -30;
|
|
end
|
|
|
|
|
|
-- Iterate through frames and set anchors according to the flags set
|
|
for index, value in pairs(UIPARENT_MANAGED_FRAME_POSITIONS) do
|
|
securecall("UIParent_ManageFramePosition", index, value, yOffsetFrames, xOffsetFrames, hasBottomLeft, hasBottomRight, hasPetBar);
|
|
end
|
|
|
|
-- Custom positioning not handled by the loop
|
|
|
|
-- Update shapeshift bar appearance
|
|
if ( MultiBarBottomLeft:IsShown() ) then
|
|
SlidingActionBarTexture0:Hide();
|
|
SlidingActionBarTexture1:Hide();
|
|
if ( ShapeshiftBarFrame ) then
|
|
ShapeshiftBarLeft:Hide();
|
|
ShapeshiftBarRight:Hide();
|
|
ShapeshiftBarMiddle:Hide();
|
|
for i=1, GetNumShapeshiftForms() do
|
|
_G["ShapeshiftButton"..i.."NormalTexture"]:SetWidth(50);
|
|
_G["ShapeshiftButton"..i.."NormalTexture"]:SetHeight(50);
|
|
end
|
|
end
|
|
else
|
|
if (PetActionBarFrame_IsAboveShapeshift and PetActionBarFrame_IsAboveShapeshift()) then
|
|
SlidingActionBarTexture0:Hide();
|
|
SlidingActionBarTexture1:Hide();
|
|
else
|
|
SlidingActionBarTexture0:Show();
|
|
SlidingActionBarTexture1:Show();
|
|
end
|
|
if ( ShapeshiftBarFrame ) then
|
|
if ( GetNumShapeshiftForms() > 2 ) then
|
|
ShapeshiftBarMiddle:Show();
|
|
end
|
|
ShapeshiftBarLeft:Show();
|
|
ShapeshiftBarRight:Show();
|
|
for i=1, GetNumShapeshiftForms() do
|
|
_G["ShapeshiftButton"..i.."NormalTexture"]:SetWidth(64);
|
|
_G["ShapeshiftButton"..i.."NormalTexture"]:SetHeight(64);
|
|
end
|
|
end
|
|
end
|
|
|
|
-- HACK: we have too many bars in this game now...
|
|
-- if the shapeshift bar is shown then hide the multi-cast bar
|
|
-- we'll have to figure out what we should do in this case if it ever really becomes a problem
|
|
-- HACK 2: if the possession bar is shown then hide the multi-cast bar
|
|
-- yeah, way too many bars...
|
|
if ( ( ShapeshiftBarFrame and ShapeshiftBarFrame:IsShown() ) or
|
|
( PossessBarFrame and PossessBarFrame:IsShown() ) ) then
|
|
HideMultiCastActionBar();
|
|
elseif ( HasMultiCastActionBar and HasMultiCastActionBar() ) then
|
|
ShowMultiCastActionBar();
|
|
end
|
|
|
|
-- If petactionbar is already shown, set its point in addition to changing its y target
|
|
if ( PetActionBarFrame:IsShown() ) then
|
|
PetActionBar_UpdatePositionValues();
|
|
PetActionBarFrame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT", PETACTIONBAR_XPOS, PETACTIONBAR_YPOS);
|
|
end
|
|
|
|
-- Set battlefield minimap position
|
|
if ( BattlefieldMinimapTab and not BattlefieldMinimapTab:IsUserPlaced() ) then
|
|
BattlefieldMinimapTab:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMRIGHT", -225-CONTAINER_OFFSET_X, BATTLEFIELD_TAB_OFFSET_Y);
|
|
end
|
|
|
|
-- Setup y anchors
|
|
local anchorY = 0;
|
|
-- Capture bars
|
|
if ( NUM_EXTENDED_UI_FRAMES ) then
|
|
local captureBar;
|
|
local numCaptureBars = 0;
|
|
for i=1, NUM_EXTENDED_UI_FRAMES do
|
|
captureBar = _G["WorldStateCaptureBar"..i];
|
|
if ( captureBar and captureBar:IsShown() ) then
|
|
captureBar:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
|
|
anchorY = anchorY - captureBar:GetHeight();
|
|
end
|
|
end
|
|
end
|
|
|
|
--Setup Vehicle seat indicator offset
|
|
if ( VehicleSeatIndicator ) then
|
|
if ( VehicleSeatIndicator and VehicleSeatIndicator:IsShown() ) then
|
|
anchorY = anchorY - VehicleSeatIndicator:GetHeight() - 18; --The -18 is there to give a small buffer for things like the QuestTimeFrame below the Seat Indicator
|
|
end
|
|
|
|
end
|
|
|
|
-- Boss frames
|
|
local numBossFrames = 0;
|
|
local durabilityXOffset = CONTAINER_OFFSET_X;
|
|
local durabilityYOffset = anchorY;
|
|
if ( Boss1TargetFrame ) then
|
|
for i = 1, MAX_BOSS_FRAMES do
|
|
if ( _G["Boss"..i.."TargetFrame"]:IsShown() ) then
|
|
numBossFrames = numBossFrames + 1;
|
|
else
|
|
break;
|
|
end
|
|
end
|
|
if ( numBossFrames > 0 ) then
|
|
Boss1TargetFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -(CONTAINER_OFFSET_X * 1.3) + 60, anchorY + 20);
|
|
anchorY = anchorY - 6 - numBossFrames * 66;
|
|
durabilityXOffset = durabilityXOffset + 135;
|
|
end
|
|
end
|
|
|
|
-- Setup durability offset
|
|
if ( DurabilityFrame ) then
|
|
if ( DurabilityShield:IsShown() or DurabilityOffWeapon:IsShown() or DurabilityRanged:IsShown() ) then
|
|
durabilityXOffset = durabilityXOffset + 20;
|
|
end
|
|
DurabilityFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -durabilityXOffset, durabilityYOffset);
|
|
if ( DurabilityFrame:IsShown() and numBossFrames == 0 ) then
|
|
anchorY = anchorY - DurabilityFrame:GetHeight() - 10;
|
|
end
|
|
end
|
|
|
|
if ( ArenaEnemyFrames ) then
|
|
ArenaEnemyFrames:ClearAllPoints();
|
|
ArenaEnemyFrames:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
|
|
end
|
|
|
|
local numArenaOpponents = GetNumArenaOpponents();
|
|
if ( not WatchFrame:IsUserPlaced() and ArenaEnemyFrames and ArenaEnemyFrames:IsShown() and (numArenaOpponents > 0) ) then
|
|
WatchFrame:ClearAllPoints();
|
|
WatchFrame:SetPoint("TOPRIGHT", "ArenaEnemyFrame"..numArenaOpponents, "BOTTOMRIGHT", 2, -35);
|
|
elseif ( not WatchFrame:IsUserPlaced() ) then -- We're using Simple Quest Tracking, automagically size and position!
|
|
WatchFrame:ClearAllPoints();
|
|
-- move up if only the minimap cluster is above, move down a little otherwise
|
|
if ( anchorY == 0 ) then
|
|
anchorY = 20;
|
|
end
|
|
WatchFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
|
|
-- OnSizeChanged for WatchFrame handles its redraw
|
|
end
|
|
|
|
WatchFrame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, CONTAINER_OFFSET_Y);
|
|
|
|
-- Update chat dock since the dock could have moved
|
|
FCF_DockUpdate();
|
|
updateContainerFrameAnchors();
|
|
end
|
|
|
|
-- Call this function to update the positions of all frames that can appear on the right side of the screen
|
|
function UIParent_ManageFramePositions()
|
|
--Dispatch to secure code
|
|
FramePositionDelegate:SetAttribute("uiparent-manage", true);
|
|
end
|
|
|
|
function ToggleFrame(frame)
|
|
if ( frame:IsShown() ) then
|
|
HideUIPanel(frame);
|
|
else
|
|
ShowUIPanel(frame);
|
|
end
|
|
end
|
|
|
|
function ShowUIPanel(frame, force)
|
|
if ( not frame or frame:IsShown() ) then
|
|
return;
|
|
end
|
|
if ( not GetUIPanelWindowInfo(frame, "area") ) then
|
|
frame:Show();
|
|
return;
|
|
end
|
|
|
|
-- Dispatch to secure code
|
|
FramePositionDelegate:SetAttribute("panel-force", force);
|
|
FramePositionDelegate:SetAttribute("panel-frame", frame);
|
|
FramePositionDelegate:SetAttribute("panel-show", true);
|
|
end
|
|
|
|
function HideUIPanel(frame, skipSetPoint)
|
|
if ( not frame or not frame:IsShown() ) then
|
|
return;
|
|
end
|
|
|
|
if ( not GetUIPanelWindowInfo(frame, "area") ) then
|
|
frame:Hide();
|
|
return;
|
|
end
|
|
|
|
--Dispatch to secure code
|
|
FramePositionDelegate:SetAttribute("panel-frame", frame);
|
|
FramePositionDelegate:SetAttribute("panel-skipSetPoint", skipSetPoint);
|
|
FramePositionDelegate:SetAttribute("panel-hide", true);
|
|
end
|
|
|
|
function HideParentPanel(self)
|
|
HideUIPanel(self:GetParent());
|
|
end
|
|
|
|
function GetUIPanel(key)
|
|
return FramePositionDelegate:GetUIPanel(key);
|
|
end
|
|
|
|
function GetUIPanelWidth(frame)
|
|
return GetUIPanelWindowInfo(frame, "width") or frame:GetWidth();
|
|
end
|
|
|
|
function GetMaxUIPanelsWidth()
|
|
local bufferBoundry = UIParent:GetRight() - UIParent:GetAttribute("RIGHT_OFFSET_BUFFER");
|
|
if ( Minimap:IsShown() and not MinimapCluster:IsUserPlaced() ) then
|
|
-- If the Minimap is in the default place, make sure you wont overlap it either
|
|
return min(MinimapCluster:GetLeft(), bufferBoundry);
|
|
else
|
|
-- If the minimap has been moved, make sure not to overlap the right side bars
|
|
return bufferBoundry;
|
|
end
|
|
end
|
|
|
|
function CanShowRightUIPanel(frame)
|
|
local width;
|
|
if ( frame ) then
|
|
width = GetUIPanelWidth(frame);
|
|
else
|
|
width = UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
|
|
end
|
|
|
|
local rightSide = UIParent:GetAttribute("RIGHT_OFFSET") + width;
|
|
if ( rightSide < GetMaxUIPanelsWidth() ) then
|
|
return 1;
|
|
end
|
|
end
|
|
|
|
function CanShowCenterUIPanel(frame)
|
|
local width;
|
|
if ( frame ) then
|
|
width = GetUIPanelWidth(frame);
|
|
else
|
|
width = UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
|
|
end
|
|
|
|
local rightSide = UIParent:GetAttribute("CENTER_OFFSET") + width;
|
|
if ( rightSide < GetMaxUIPanelsWidth() ) then
|
|
return 1;
|
|
end
|
|
end
|
|
|
|
function CanShowUIPanels(leftFrame, centerFrame, rightFrame)
|
|
local offset = UIParent:GetAttribute("LEFT_OFFSET");
|
|
|
|
if ( leftFrame ) then
|
|
offset = offset + GetUIPanelWidth(leftFrame);
|
|
if ( centerFrame ) then
|
|
local area = GetUIPanelWindowInfo(centerFrame, "area");
|
|
if ( area ~= "center" ) then
|
|
offset = offset + ( GetUIPanelWindowInfo(centerFrame, "width") or UIParent:GetAttribute("DEFAULT_FRAME_WIDTH") );
|
|
else
|
|
offset = offset + GetUIPanelWidth(centerFrame);
|
|
end
|
|
if ( rightFrame ) then
|
|
offset = offset + GetUIPanelWidth(rightFrame);
|
|
end
|
|
end
|
|
elseif ( centerFrame ) then
|
|
offset = GetUIPanelWidth(centerFrame);
|
|
end
|
|
|
|
if ( offset < GetMaxUIPanelsWidth() ) then
|
|
return 1;
|
|
end
|
|
end
|
|
|
|
function CanOpenPanels()
|
|
--[[
|
|
if ( UnitIsDead("player") ) then
|
|
return nil;
|
|
end
|
|
|
|
Previously couldn't open frames if player was out of control i.e. feared
|
|
if ( UnitIsDead("player") or UIParent.isOutOfControl ) then
|
|
return nil;
|
|
end
|
|
]]
|
|
|
|
local centerFrame = GetUIPanel("center");
|
|
if ( not centerFrame ) then
|
|
return 1;
|
|
end
|
|
|
|
local area = GetUIPanelWindowInfo(centerFrame, "area");
|
|
local allowOtherPanels = GetUIPanelWindowInfo(centerFrame, "allowOtherPanels");
|
|
if ( area and (area == "center") and not allowOtherPanels ) then
|
|
return nil;
|
|
end
|
|
|
|
return 1;
|
|
end
|
|
|
|
-- this function handles possibly tainted values and so
|
|
-- should always be called from secure code using securecall()
|
|
function CloseChildWindows()
|
|
local childWindow;
|
|
for index, value in pairs(UIChildWindows) do
|
|
childWindow = _G[value];
|
|
if ( childWindow ) then
|
|
childWindow:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
-- this function handles possibly tainted values and so
|
|
-- should always be called from secure code using securecall()
|
|
function CloseSpecialWindows()
|
|
local found;
|
|
for index, value in pairs(UISpecialFrames) do
|
|
local frame = _G[value];
|
|
if ( frame and frame:IsShown() ) then
|
|
frame:Hide();
|
|
found = 1;
|
|
end
|
|
end
|
|
return found;
|
|
end
|
|
|
|
function CloseWindows(ignoreCenter, frameToIgnore)
|
|
-- This function will close all frames that are not the current frame
|
|
local leftFrame = GetUIPanel("left");
|
|
local centerFrame = GetUIPanel("center");
|
|
local rightFrame = GetUIPanel("right");
|
|
local doublewideFrame = GetUIPanel("doublewide");
|
|
local fullScreenFrame = GetUIPanel("fullscreen");
|
|
local found = leftFrame or centerFrame or rightFrame or doublewideFrame or fullScreenFrame;
|
|
|
|
if ( not frameToIgnore or frameToIgnore ~= leftFrame ) then
|
|
HideUIPanel(leftFrame, 1);
|
|
end
|
|
|
|
HideUIPanel(fullScreenFrame, 1);
|
|
HideUIPanel(doublewideFrame, 1);
|
|
|
|
if ( not frameToIgnore or frameToIgnore ~= centerFrame ) then
|
|
if ( centerFrame ) then
|
|
local area = GetUIPanelWindowInfo(centerFrame, "area");
|
|
if ( area ~= "center" or not ignoreCenter ) then
|
|
HideUIPanel(centerFrame, 1);
|
|
end
|
|
end
|
|
end
|
|
|
|
if ( not frameToIgnore or frameToIgnore ~= rightFrame ) then
|
|
if ( rightFrame ) then
|
|
HideUIPanel(rightFrame, 1);
|
|
end
|
|
end
|
|
|
|
found = securecall("CloseSpecialWindows") or found;
|
|
|
|
UpdateUIPanelPositions();
|
|
|
|
return found;
|
|
end
|
|
|
|
function CloseAllWindows_WithExceptions()
|
|
-- Insert exceptions here, right now we just don't close the scoreFrame when the player loses control i.e. the game over spell effect
|
|
if ( GetUIPanel("center") == WorldStateScoreFrame ) then
|
|
CloseAllWindows(1);
|
|
elseif ( IsOptionFrameOpen() ) then
|
|
CloseAllWindows(1);
|
|
else
|
|
CloseAllWindows();
|
|
end
|
|
end
|
|
|
|
function CloseAllWindows(ignoreCenter)
|
|
local bagsVisible = nil;
|
|
local windowsVisible = nil;
|
|
for i=1, NUM_CONTAINER_FRAMES, 1 do
|
|
local containerFrame = _G["ContainerFrame"..i];
|
|
if ( containerFrame:IsShown() ) then
|
|
containerFrame:Hide();
|
|
bagsVisible = 1;
|
|
end
|
|
end
|
|
windowsVisible = CloseWindows(ignoreCenter);
|
|
return (bagsVisible or windowsVisible);
|
|
end
|
|
|
|
-- this function handles possibly tainted values and so
|
|
-- should always be called from secure code using securecall()
|
|
function CloseMenus()
|
|
local menusVisible = nil;
|
|
local menu
|
|
for index, value in pairs(UIMenus) do
|
|
menu = _G[value];
|
|
if ( menu and menu:IsShown() ) then
|
|
menu:Hide();
|
|
menusVisible = 1;
|
|
end
|
|
end
|
|
return menusVisible;
|
|
end
|
|
|
|
function UpdateUIPanelPositions(currentFrame)
|
|
FramePositionDelegate:SetAttribute("panel-frame", currentFrame)
|
|
FramePositionDelegate:SetAttribute("panel-update", true);
|
|
end
|
|
|
|
function IsOptionFrameOpen()
|
|
if ( GameMenuFrame:IsShown() or InterfaceOptionsFrame:IsShown() or (KeyBindingFrame and KeyBindingFrame:IsShown()) ) then
|
|
return 1;
|
|
else
|
|
return nil;
|
|
end
|
|
end
|
|
|
|
function LowerFrameLevel(frame)
|
|
frame:SetFrameLevel(frame:GetFrameLevel()-1);
|
|
end
|
|
|
|
function RaiseFrameLevel(frame)
|
|
frame:SetFrameLevel(frame:GetFrameLevel()+1);
|
|
end
|
|
|
|
-- Function to reposition frames if they get dragged off screen
|
|
function ValidateFramePosition(frame, offscreenPadding, returnOffscreen)
|
|
if ( not frame ) then
|
|
return;
|
|
end
|
|
local left = frame:GetLeft();
|
|
local right = frame:GetRight();
|
|
local top = frame:GetTop();
|
|
local bottom = frame:GetBottom();
|
|
local newAnchorX, newAnchorY;
|
|
if ( not offscreenPadding ) then
|
|
offscreenPadding = 15;
|
|
end
|
|
if ( bottom < (0 + MainMenuBar:GetHeight() + offscreenPadding)) then
|
|
-- Off the bottom of the screen
|
|
newAnchorY = MainMenuBar:GetHeight() + frame:GetHeight() - GetScreenHeight();
|
|
elseif ( top > GetScreenHeight() ) then
|
|
-- Off the top of the screen
|
|
newAnchorY = 0;
|
|
end
|
|
if ( left < 0 ) then
|
|
-- Off the left of the screen
|
|
newAnchorX = 0;
|
|
elseif ( right > GetScreenWidth() ) then
|
|
-- Off the right of the screen
|
|
newAnchorX = GetScreenWidth() - frame:GetWidth();
|
|
end
|
|
if ( newAnchorX or newAnchorY ) then
|
|
if ( returnOffscreen ) then
|
|
return 1;
|
|
else
|
|
if ( not newAnchorX ) then
|
|
newAnchorX = left;
|
|
elseif ( not newAnchorY ) then
|
|
newAnchorY = top - GetScreenHeight();
|
|
end
|
|
frame:ClearAllPoints();
|
|
frame:SetPoint("TOPLEFT", nil, "TOPLEFT", newAnchorX, newAnchorY);
|
|
end
|
|
|
|
|
|
else
|
|
if ( returnOffscreen ) then
|
|
return nil;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
-- Time --
|
|
|
|
function SecondsToTime(seconds, noSeconds, notAbbreviated, maxCount)
|
|
local time = "";
|
|
local count = 0;
|
|
local tempTime;
|
|
seconds = floor(seconds);
|
|
maxCount = maxCount or 2;
|
|
if ( seconds >= 86400 ) then
|
|
tempTime = floor(seconds / 86400);
|
|
if ( notAbbreviated ) then
|
|
time = format(D_DAYS,tempTime);
|
|
else
|
|
time = format(DAYS_ABBR,tempTime);
|
|
end
|
|
seconds = mod(seconds, 86400);
|
|
count = count + 1;
|
|
end
|
|
if ( seconds >= 3600 ) then
|
|
if ( time ~= "" ) then
|
|
time = time..TIME_UNIT_DELIMITER;
|
|
end
|
|
tempTime = floor(seconds / 3600);
|
|
if ( notAbbreviated ) then
|
|
time = time..format(D_HOURS, tempTime);
|
|
else
|
|
time = time..format(HOURS_ABBR, tempTime);
|
|
end
|
|
seconds = mod(seconds, 3600);
|
|
count = count + 1;
|
|
end
|
|
if ( count < maxCount and seconds >= 60 ) then
|
|
if ( time ~= "" ) then
|
|
time = time..TIME_UNIT_DELIMITER;
|
|
end
|
|
tempTime = floor(seconds / 60);
|
|
if ( notAbbreviated ) then
|
|
time = time..format(D_MINUTES, tempTime);
|
|
else
|
|
time = time..format(MINUTES_ABBR, tempTime);
|
|
end
|
|
seconds = mod(seconds, 60);
|
|
count = count + 1;
|
|
end
|
|
if ( count < maxCount and seconds > 0 and not noSeconds ) then
|
|
if ( time ~= "" ) then
|
|
time = time..TIME_UNIT_DELIMITER;
|
|
end
|
|
seconds = format("%d", seconds);
|
|
if ( notAbbreviated ) then
|
|
time = time..format(D_SECONDS, seconds);
|
|
else
|
|
time = time..format(SECONDS_ABBR, seconds);
|
|
end
|
|
end
|
|
return time;
|
|
end
|
|
|
|
function SecondsToTimeAbbrev(seconds)
|
|
local tempTime;
|
|
if ( seconds >= 86400 ) then
|
|
tempTime = ceil(seconds / 86400);
|
|
return DAY_ONELETTER_ABBR, tempTime;
|
|
end
|
|
if ( seconds >= 3600 ) then
|
|
tempTime = ceil(seconds / 3600);
|
|
return HOUR_ONELETTER_ABBR, tempTime;
|
|
end
|
|
if ( seconds >= 60 ) then
|
|
tempTime = ceil(seconds / 60);
|
|
return MINUTE_ONELETTER_ABBR, tempTime;
|
|
end
|
|
return SECOND_ONELETTER_ABBR, seconds;
|
|
end
|
|
|
|
function RecentTimeDate(year, month, day, hour)
|
|
local lastOnline;
|
|
if ( (year == 0) or (year == nil) ) then
|
|
if ( (month == 0) or (month == nil) ) then
|
|
if ( (day == 0) or (day == nil) ) then
|
|
if ( (hour == 0) or (hour == nil) ) then
|
|
lastOnline = LASTONLINE_MINS;
|
|
else
|
|
lastOnline = format(LASTONLINE_HOURS, hour);
|
|
end
|
|
else
|
|
lastOnline = format(LASTONLINE_DAYS, day);
|
|
end
|
|
else
|
|
lastOnline = format(LASTONLINE_MONTHS, month);
|
|
end
|
|
else
|
|
lastOnline = format(LASTONLINE_YEARS, year);
|
|
end
|
|
return lastOnline;
|
|
end
|
|
|
|
|
|
-- Frame fading and flashing --
|
|
|
|
local frameFadeManager = CreateFrame("FRAME");
|
|
|
|
-- Generic fade function
|
|
function UIFrameFade(frame, fadeInfo)
|
|
if (not frame) then
|
|
return;
|
|
end
|
|
if ( not fadeInfo.mode ) then
|
|
fadeInfo.mode = "IN";
|
|
end
|
|
local alpha;
|
|
if ( fadeInfo.mode == "IN" ) then
|
|
if ( not fadeInfo.startAlpha ) then
|
|
fadeInfo.startAlpha = 0;
|
|
end
|
|
if ( not fadeInfo.endAlpha ) then
|
|
fadeInfo.endAlpha = 1.0;
|
|
end
|
|
alpha = 0;
|
|
elseif ( fadeInfo.mode == "OUT" ) then
|
|
if ( not fadeInfo.startAlpha ) then
|
|
fadeInfo.startAlpha = 1.0;
|
|
end
|
|
if ( not fadeInfo.endAlpha ) then
|
|
fadeInfo.endAlpha = 0;
|
|
end
|
|
alpha = 1.0;
|
|
end
|
|
frame:SetAlpha(fadeInfo.startAlpha);
|
|
|
|
frame.fadeInfo = fadeInfo;
|
|
frame:Show();
|
|
|
|
local index = 1;
|
|
while FADEFRAMES[index] do
|
|
-- If frame is already set to fade then return
|
|
if ( FADEFRAMES[index] == frame ) then
|
|
return;
|
|
end
|
|
index = index + 1;
|
|
end
|
|
tinsert(FADEFRAMES, frame);
|
|
frameFadeManager:SetScript("OnUpdate", UIFrameFade_OnUpdate);
|
|
end
|
|
|
|
-- Convenience function to do a simple fade in
|
|
function UIFrameFadeIn(frame, timeToFade, startAlpha, endAlpha)
|
|
local fadeInfo = {};
|
|
fadeInfo.mode = "IN";
|
|
fadeInfo.timeToFade = timeToFade;
|
|
fadeInfo.startAlpha = startAlpha;
|
|
fadeInfo.endAlpha = endAlpha;
|
|
UIFrameFade(frame, fadeInfo);
|
|
end
|
|
|
|
-- Convenience function to do a simple fade out
|
|
function UIFrameFadeOut(frame, timeToFade, startAlpha, endAlpha)
|
|
local fadeInfo = {};
|
|
fadeInfo.mode = "OUT";
|
|
fadeInfo.timeToFade = timeToFade;
|
|
fadeInfo.startAlpha = startAlpha;
|
|
fadeInfo.endAlpha = endAlpha;
|
|
UIFrameFade(frame, fadeInfo);
|
|
end
|
|
|
|
function UIFrameFadeRemoveFrame(frame)
|
|
tDeleteItem(FADEFRAMES, frame);
|
|
end
|
|
|
|
function UIFrameFlashRemoveFrame(frame)
|
|
tDeleteItem(FLASHFRAMES, frame);
|
|
end
|
|
|
|
-- Function that actually performs the alpha change
|
|
--[[
|
|
Fading frame attribute listing
|
|
============================================================
|
|
frame.timeToFade [Num] Time it takes to fade the frame in or out
|
|
frame.mode ["IN", "OUT"] Fade mode
|
|
frame.finishedFunc [func()] Function that is called when fading is finished
|
|
frame.finishedArg1 [ANYTHING] Argument to the finishedFunc
|
|
frame.finishedArg2 [ANYTHING] Argument to the finishedFunc
|
|
frame.finishedArg3 [ANYTHING] Argument to the finishedFunc
|
|
frame.finishedArg4 [ANYTHING] Argument to the finishedFunc
|
|
frame.fadeHoldTime [Num] Time to hold the faded state
|
|
]]
|
|
|
|
function UIFrameFade_OnUpdate(self, elapsed)
|
|
local index = 1;
|
|
local frame, fadeInfo;
|
|
while FADEFRAMES[index] do
|
|
frame = FADEFRAMES[index];
|
|
fadeInfo = FADEFRAMES[index].fadeInfo;
|
|
-- Reset the timer if there isn't one, this is just an internal counter
|
|
if ( not fadeInfo.fadeTimer ) then
|
|
fadeInfo.fadeTimer = 0;
|
|
end
|
|
fadeInfo.fadeTimer = fadeInfo.fadeTimer + elapsed;
|
|
|
|
-- If the fadeTimer is less then the desired fade time then set the alpha otherwise hold the fade state, call the finished function, or just finish the fade
|
|
if ( fadeInfo.fadeTimer < fadeInfo.timeToFade ) then
|
|
if ( fadeInfo.mode == "IN" ) then
|
|
frame:SetAlpha((fadeInfo.fadeTimer / fadeInfo.timeToFade) * (fadeInfo.endAlpha - fadeInfo.startAlpha) + fadeInfo.startAlpha);
|
|
elseif ( fadeInfo.mode == "OUT" ) then
|
|
frame:SetAlpha(((fadeInfo.timeToFade - fadeInfo.fadeTimer) / fadeInfo.timeToFade) * (fadeInfo.startAlpha - fadeInfo.endAlpha) + fadeInfo.endAlpha);
|
|
end
|
|
else
|
|
frame:SetAlpha(fadeInfo.endAlpha);
|
|
-- If there is a fadeHoldTime then wait until its passed to continue on
|
|
if ( fadeInfo.fadeHoldTime and fadeInfo.fadeHoldTime > 0 ) then
|
|
fadeInfo.fadeHoldTime = fadeInfo.fadeHoldTime - elapsed;
|
|
else
|
|
-- Complete the fade and call the finished function if there is one
|
|
UIFrameFadeRemoveFrame(frame);
|
|
if ( fadeInfo.finishedFunc ) then
|
|
fadeInfo.finishedFunc(fadeInfo.finishedArg1, fadeInfo.finishedArg2, fadeInfo.finishedArg3, fadeInfo.finishedArg4);
|
|
fadeInfo.finishedFunc = nil;
|
|
end
|
|
end
|
|
end
|
|
|
|
index = index + 1;
|
|
end
|
|
|
|
if ( #FADEFRAMES == 0 ) then
|
|
self:SetScript("OnUpdate", nil);
|
|
end
|
|
end
|
|
|
|
function UIFrameIsFading(frame)
|
|
for index, value in pairs(FADEFRAMES) do
|
|
if ( value == frame ) then
|
|
return 1;
|
|
end
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
local frameFlashManager = CreateFrame("FRAME");
|
|
|
|
local UIFrameFlashTimers = {};
|
|
|
|
-- Function to start a frame flashing
|
|
function UIFrameFlash(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
|
|
if ( frame ) then
|
|
local index = 1;
|
|
-- If frame is already set to flash then return
|
|
while FLASHFRAMES[index] do
|
|
if ( FLASHFRAMES[index] == frame ) then
|
|
return;
|
|
end
|
|
index = index + 1;
|
|
end
|
|
|
|
if (syncId) then
|
|
frame.syncId = syncId;
|
|
if (UIFrameFlashTimers[syncId] == nil) then
|
|
UIFrameFlashTimers[syncId] = 0;
|
|
end
|
|
else
|
|
frame.syncId = nil;
|
|
end
|
|
|
|
-- Time it takes to fade in a flashing frame
|
|
frame.fadeInTime = fadeInTime;
|
|
-- Time it takes to fade out a flashing frame
|
|
frame.fadeOutTime = fadeOutTime;
|
|
-- How long to keep the frame flashing
|
|
frame.flashDuration = flashDuration;
|
|
-- Show the flashing frame when the fadeOutTime has passed
|
|
frame.showWhenDone = showWhenDone;
|
|
-- Internal timer
|
|
frame.flashTimer = 0;
|
|
-- How long to hold the faded in state
|
|
frame.flashInHoldTime = flashInHoldTime;
|
|
-- How long to hold the faded out state
|
|
frame.flashOutHoldTime = flashOutHoldTime;
|
|
|
|
tinsert(FLASHFRAMES, frame);
|
|
|
|
frameFlashManager:SetScript("OnUpdate", UIFrameFlash_OnUpdate);
|
|
end
|
|
end
|
|
|
|
-- Called every frame to update flashing frames
|
|
function UIFrameFlash_OnUpdate(self, elapsed)
|
|
local frame;
|
|
local index = #FLASHFRAMES;
|
|
|
|
-- Update timers for all synced frames
|
|
for syncId, timer in pairs(UIFrameFlashTimers) do
|
|
UIFrameFlashTimers[syncId] = timer + elapsed;
|
|
end
|
|
|
|
while FLASHFRAMES[index] do
|
|
frame = FLASHFRAMES[index];
|
|
frame.flashTimer = frame.flashTimer + elapsed;
|
|
|
|
if ( (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
|
|
UIFrameFlashStop(frame);
|
|
else
|
|
local flashTime = frame.flashTimer;
|
|
local alpha;
|
|
|
|
if (frame.syncId) then
|
|
flashTime = UIFrameFlashTimers[frame.syncId];
|
|
end
|
|
|
|
flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0));
|
|
if (flashTime < frame.fadeInTime) then
|
|
alpha = flashTime/frame.fadeInTime;
|
|
elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)) then
|
|
alpha = 1;
|
|
elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime) then
|
|
alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime);
|
|
else
|
|
alpha = 0;
|
|
end
|
|
|
|
frame:SetAlpha(alpha);
|
|
frame:Show();
|
|
end
|
|
|
|
-- Loop in reverse so that removing frames is safe
|
|
index = index - 1;
|
|
end
|
|
|
|
if ( #FLASHFRAMES == 0 ) then
|
|
self:SetScript("OnUpdate", nil);
|
|
end
|
|
end
|
|
|
|
-- Function to see if a frame is already flashing
|
|
function UIFrameIsFlashing(frame)
|
|
for index, value in pairs(FLASHFRAMES) do
|
|
if ( value == frame ) then
|
|
return 1;
|
|
end
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
-- Function to stop flashing
|
|
function UIFrameFlashStop(frame)
|
|
UIFrameFlashRemoveFrame(frame);
|
|
frame:SetAlpha(1.0);
|
|
frame.flashTimer = nil;
|
|
if ( frame.showWhenDone ) then
|
|
frame:Show();
|
|
else
|
|
frame:Hide();
|
|
end
|
|
end
|
|
|
|
-- Functions to handle button pulsing (Highlight, Unhighlight)
|
|
function SetButtonPulse(button, duration, pulseRate)
|
|
button.pulseDuration = pulseRate;
|
|
button.pulseTimeLeft = duration
|
|
-- pulseRate is actually seconds per pulse state
|
|
button.pulseRate = pulseRate;
|
|
button.pulseOn = 0;
|
|
tinsert(PULSEBUTTONS, button);
|
|
end
|
|
|
|
-- Update the button pulsing
|
|
function ButtonPulse_OnUpdate(elapsed)
|
|
for index, button in pairs(PULSEBUTTONS) do
|
|
if ( button.pulseTimeLeft > 0 ) then
|
|
if ( button.pulseDuration < 0 ) then
|
|
if ( button.pulseOn == 1 ) then
|
|
button:UnlockHighlight();
|
|
button.pulseOn = 0;
|
|
else
|
|
button:LockHighlight();
|
|
button.pulseOn = 1;
|
|
end
|
|
button.pulseDuration = button.pulseRate;
|
|
end
|
|
button.pulseDuration = button.pulseDuration - elapsed;
|
|
button.pulseTimeLeft = button.pulseTimeLeft - elapsed;
|
|
else
|
|
button:UnlockHighlight();
|
|
button.pulseOn = 0;
|
|
tDeleteItem(PULSEBUTTONS, button);
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
function ButtonPulse_StopPulse(button)
|
|
for index, pulseButton in pairs(PULSEBUTTONS) do
|
|
if ( pulseButton == button ) then
|
|
tDeleteItem(PULSEBUTTONS, button);
|
|
end
|
|
end
|
|
end
|
|
|
|
function UIDoFramesIntersect(frame1, frame2)
|
|
if ( ( frame1:GetLeft() < frame2:GetRight() ) and ( frame1:GetRight() > frame2:GetLeft() ) and
|
|
( frame1:GetBottom() < frame2:GetTop() ) and ( frame1:GetTop() > frame2:GetBottom() ) ) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end
|
|
end
|
|
|
|
-- Lua Helper functions --
|
|
|
|
function BuildListString(...)
|
|
local text = ...;
|
|
if ( not text ) then
|
|
return nil;
|
|
end
|
|
local string = text;
|
|
for i=2, select("#", ...) do
|
|
text = select(i, ...);
|
|
if ( text ) then
|
|
string = string..", "..text;
|
|
end
|
|
end
|
|
return string;
|
|
end
|
|
|
|
function BuildColoredListString(...)
|
|
if ( select("#", ...) == 0 ) then
|
|
return nil;
|
|
end
|
|
|
|
-- Takes input where odd items are the text and even items determine whether the arg should be colored or not
|
|
local text, normal = ...;
|
|
local string;
|
|
if ( normal ) then
|
|
string = text;
|
|
else
|
|
string = RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
|
|
end
|
|
for i=3, select("#", ...), 2 do
|
|
text, normal = select(i, ...);
|
|
if ( normal ) then
|
|
-- If meets the condition
|
|
string = string..", "..text;
|
|
else
|
|
-- If doesn't meet the condition
|
|
string = string..", "..RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
|
|
end
|
|
end
|
|
|
|
return string;
|
|
end
|
|
|
|
function BuildNewLineListString(...)
|
|
local text;
|
|
local index = 1;
|
|
for i=1, select("#", ...) do
|
|
text = select(i, ...);
|
|
index = index + 1;
|
|
if ( text ) then
|
|
break;
|
|
end
|
|
end
|
|
if ( not text ) then
|
|
return nil;
|
|
end
|
|
local string = text;
|
|
for i=index, select("#", ...) do
|
|
text = select(i, ...);
|
|
if ( text ) then
|
|
string = string.."\n"..text;
|
|
end
|
|
end
|
|
return string;
|
|
end
|
|
|
|
function BuildMultilineTooltip(globalStringName, tooltip, r, g, b)
|
|
if ( not tooltip ) then
|
|
tooltip = GameTooltip;
|
|
end
|
|
if ( not r ) then
|
|
r = 1.0;
|
|
g = 1.0;
|
|
b = 1.0;
|
|
end
|
|
local i = 1;
|
|
local string = _G[globalStringName..i];
|
|
while (string) do
|
|
tooltip:AddLine(string, "", r, g, b);
|
|
i = i + 1;
|
|
string = _G[globalStringName..i];
|
|
end
|
|
end
|
|
|
|
function tDeleteItem(table, item)
|
|
local index = 1;
|
|
while table[index] do
|
|
if ( item == table[index] ) then
|
|
tremove(table, index);
|
|
else
|
|
index = index + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
function tContains(table, item)
|
|
local index = 1;
|
|
while table[index] do
|
|
if ( item == table[index] ) then
|
|
return 1;
|
|
end
|
|
index = index + 1;
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
function CopyTable(settings)
|
|
local copy = {};
|
|
for k, v in pairs(settings) do
|
|
if ( type(v) == "table" ) then
|
|
copy[k] = CopyTable(v);
|
|
else
|
|
copy[k] = v;
|
|
end
|
|
end
|
|
return copy;
|
|
end
|
|
|
|
function MouseIsOver(region, topOffset, bottomOffset, leftOffset, rightOffset)
|
|
return region:IsMouseOver(topOffset, bottomOffset, leftOffset, rightOffset);
|
|
end
|
|
|
|
-- Wrapper for the desaturation function
|
|
function SetDesaturation(texture, desaturation)
|
|
local shaderSupported = texture:SetDesaturated(desaturation);
|
|
if ( not shaderSupported ) then
|
|
if ( desaturation ) then
|
|
texture:SetVertexColor(0.5, 0.5, 0.5);
|
|
else
|
|
texture:SetVertexColor(1.0, 1.0, 1.0);
|
|
end
|
|
end
|
|
end
|
|
|
|
function GetMaterialTextColors(material)
|
|
local textColor = MATERIAL_TEXT_COLOR_TABLE[material];
|
|
local titleColor = MATERIAL_TITLETEXT_COLOR_TABLE[material];
|
|
if ( not(textColor and titleColor) ) then
|
|
textColor = MATERIAL_TEXT_COLOR_TABLE["Default"];
|
|
titleColor = MATERIAL_TITLETEXT_COLOR_TABLE["Default"];
|
|
end
|
|
return textColor, titleColor;
|
|
end
|
|
|
|
|
|
-- Model --
|
|
|
|
-- Generic model rotation functions
|
|
function Model_OnLoad (self)
|
|
self.rotation = 0.61;
|
|
self:SetRotation(self.rotation);
|
|
end
|
|
|
|
function Model_RotateLeft(model, rotationIncrement)
|
|
if ( not rotationIncrement ) then
|
|
rotationIncrement = 0.03;
|
|
end
|
|
model.rotation = model.rotation - rotationIncrement;
|
|
model:SetRotation(model.rotation);
|
|
PlaySound("igInventoryRotateCharacter");
|
|
end
|
|
|
|
function Model_RotateRight(model, rotationIncrement)
|
|
if ( not rotationIncrement ) then
|
|
rotationIncrement = 0.03;
|
|
end
|
|
model.rotation = model.rotation + rotationIncrement;
|
|
model:SetRotation(model.rotation);
|
|
PlaySound("igInventoryRotateCharacter");
|
|
end
|
|
|
|
function Model_OnUpdate(self, elapsedTime, rotationsPerSecond)
|
|
if ( not rotationsPerSecond ) then
|
|
rotationsPerSecond = ROTATIONS_PER_SECOND;
|
|
end
|
|
if ( _G[self:GetName().."RotateLeftButton"]:GetButtonState() == "PUSHED" ) then
|
|
self.rotation = self.rotation + (elapsedTime * 2 * PI * rotationsPerSecond);
|
|
if ( self.rotation < 0 ) then
|
|
self.rotation = self.rotation + (2 * PI);
|
|
end
|
|
self:SetRotation(self.rotation);
|
|
end
|
|
if ( _G[self:GetName().."RotateRightButton"]:GetButtonState() == "PUSHED" ) then
|
|
self.rotation = self.rotation - (elapsedTime * 2 * PI * rotationsPerSecond);
|
|
if ( self.rotation > (2 * PI) ) then
|
|
self.rotation = self.rotation - (2 * PI);
|
|
end
|
|
self:SetRotation(self.rotation);
|
|
end
|
|
end
|
|
|
|
-- Function that handles the escape key functions
|
|
function ToggleGameMenu()
|
|
if ( not UIParent:IsShown() ) then
|
|
UIParent:Show();
|
|
SetUIVisibility(true);
|
|
elseif ( securecall("StaticPopup_EscapePressed") ) then
|
|
elseif ( GameMenuFrame:IsShown() ) then
|
|
PlaySound("igMainMenuQuit");
|
|
HideUIPanel(GameMenuFrame);
|
|
elseif ( HelpFrame:IsShown() ) then
|
|
if ( HelpFrame.back and HelpFrame.back.Click ) then
|
|
HelpFrame.back:Click();
|
|
end
|
|
elseif ( VideoOptionsFrame:IsShown() ) then
|
|
VideoOptionsFrameCancel:Click();
|
|
elseif ( AudioOptionsFrame:IsShown() ) then
|
|
AudioOptionsFrameCancel:Click();
|
|
elseif ( InterfaceOptionsFrame:IsShown() ) then
|
|
InterfaceOptionsFrameCancel:Click();
|
|
elseif ( TimeManagerFrame and TimeManagerFrame:IsShown() ) then
|
|
TimeManagerCloseButton:Click();
|
|
elseif ( MultiCastFlyoutFrame:IsShown() ) then
|
|
MultiCastFlyoutFrame_Hide(MultiCastFlyoutFrame, true);
|
|
elseif ( securecall("FCFDockOverflow_CloseLists") ) then
|
|
elseif ( securecall("CloseMenus") ) then
|
|
elseif ( CloseCalendarMenus and securecall("CloseCalendarMenus") ) then
|
|
elseif ( SpellStopCasting() ) then
|
|
elseif ( SpellStopTargeting() ) then
|
|
elseif ( securecall("CloseAllWindows") ) then
|
|
elseif ( ClearTarget() and (not UnitIsCharmed("player")) ) then
|
|
elseif ( OpacityFrame:IsShown() ) then
|
|
OpacityFrame:Hide();
|
|
else
|
|
PlaySound("igMainMenuOpen");
|
|
ShowUIPanel(GameMenuFrame);
|
|
end
|
|
end
|
|
|
|
-- Visual Misc --
|
|
|
|
function GetScreenHeightScale()
|
|
local screenHeight = 768;
|
|
return GetScreenHeight()/screenHeight;
|
|
end
|
|
|
|
function GetScreenWidthScale()
|
|
local screenWidth = 1024;
|
|
return GetScreenWidth()/screenWidth;
|
|
end
|
|
|
|
function ShowInspectCursor()
|
|
SetCursor("INSPECT_CURSOR");
|
|
end
|
|
|
|
-- Helper function to show the inspect cursor if the ctrl key is down
|
|
function CursorUpdate(self)
|
|
if ( IsModifiedClick("DRESSUP") and self.hasItem ) then
|
|
ShowInspectCursor();
|
|
else
|
|
ResetCursor();
|
|
end
|
|
end
|
|
|
|
function CursorOnUpdate(self)
|
|
if ( GameTooltip:IsOwned(self) ) then
|
|
CursorUpdate(self);
|
|
end
|
|
end
|
|
|
|
function AnimateTexCoords(texture, textureWidth, textureHeight, frameWidth, frameHeight, numFrames, elapsed)
|
|
if ( not texture.frame ) then
|
|
-- initialize everything
|
|
texture.frame = 1;
|
|
texture.numColumns = textureWidth/frameWidth;
|
|
texture.numRows = textureHeight/frameHeight;
|
|
texture.columnWidth = frameWidth/textureWidth;
|
|
texture.rowHeight = frameHeight/textureHeight;
|
|
end
|
|
local frame = texture.frame;
|
|
if ( not texture.throttle or texture.throttle > 0.1 ) then
|
|
texture.throttle = 0;
|
|
if ( frame > numFrames ) then
|
|
frame = 1;
|
|
end
|
|
local left = mod(frame-1, texture.numColumns)*texture.columnWidth;
|
|
local right = left + texture.columnWidth;
|
|
local bottom = ceil(frame/texture.numColumns)*texture.rowHeight;
|
|
local top = bottom - texture.rowHeight;
|
|
texture:SetTexCoord(left, right, top, bottom);
|
|
|
|
texture.frame = frame + 1;
|
|
else
|
|
texture.throttle = texture.throttle + elapsed;
|
|
end
|
|
end
|
|
|
|
|
|
-- Bindings --
|
|
|
|
function GetBindingText(name, prefix, returnAbbr)
|
|
if ( not name ) then
|
|
return "";
|
|
end
|
|
local tempName = name;
|
|
local i = strfind(name, "-");
|
|
local dashIndex = nil;
|
|
local count = 0;
|
|
while ( i ) do
|
|
if ( not dashIndex ) then
|
|
dashIndex = i;
|
|
else
|
|
dashIndex = dashIndex + i;
|
|
end
|
|
count = count + 1;
|
|
tempName = strsub(tempName, i + 1);
|
|
i = strfind(tempName, "-");
|
|
end
|
|
|
|
local modKeys = '';
|
|
if ( not dashIndex ) then
|
|
dashIndex = 0;
|
|
else
|
|
modKeys = strsub(name, 1, dashIndex);
|
|
|
|
if ( tempName == "CAPSLOCK" ) then
|
|
gsub(tempName, "CAPSLOCK", "Caps");
|
|
end
|
|
|
|
-- replace for all languages
|
|
-- for the "push-to-talk" binding
|
|
modKeys = gsub(modKeys, "LSHIFT", LSHIFT_KEY_TEXT);
|
|
modKeys = gsub(modKeys, "RSHIFT", RSHIFT_KEY_TEXT);
|
|
modKeys = gsub(modKeys, "LCTRL", LCTRL_KEY_TEXT);
|
|
modKeys = gsub(modKeys, "RCTRL", RCTRL_KEY_TEXT);
|
|
modKeys = gsub(modKeys, "LALT", LALT_KEY_TEXT);
|
|
modKeys = gsub(modKeys, "RALT", RALT_KEY_TEXT);
|
|
|
|
-- use the SHIFT code if they decide to localize the CTRL further. The token is CTRL_KEY_TEXT
|
|
if ( GetLocale() == "deDE") then
|
|
modKeys = gsub(modKeys, "CTRL", "STRG");
|
|
end
|
|
-- Only doing French for now since all the other languages use SHIFT, remove the "if" if other languages localize it
|
|
if ( GetLocale() == "frFR" ) then
|
|
modKeys = gsub(modKeys, "SHIFT", SHIFT_KEY_TEXT);
|
|
end
|
|
end
|
|
|
|
if ( returnAbbr ) then
|
|
if ( count > 1 ) then
|
|
return "·";
|
|
else
|
|
modKeys = gsub(modKeys, "CTRL", "c");
|
|
modKeys = gsub(modKeys, "SHIFT", "s");
|
|
modKeys = gsub(modKeys, "ALT", "a");
|
|
modKeys = gsub(modKeys, "STRG", "st");
|
|
end
|
|
end
|
|
|
|
if ( not prefix ) then
|
|
prefix = "";
|
|
end
|
|
|
|
-- fix for bug 103620: mouse buttons are not being translated properly
|
|
if ( tempName == "LeftButton" ) then
|
|
tempName = "BUTTON1";
|
|
elseif ( tempName == "RightButton" ) then
|
|
tempName = "BUTTON2";
|
|
elseif ( tempName == "MiddleButton" ) then
|
|
tempName = "BUTTON3";
|
|
elseif ( tempName == "Button4" ) then
|
|
tempName = "BUTTON4";
|
|
elseif ( tempName == "Button5" ) then
|
|
tempName = "BUTTON5";
|
|
elseif ( tempName == "Button6" ) then
|
|
tempName = "BUTTON6";
|
|
elseif ( tempName == "Button7" ) then
|
|
tempName = "BUTTON7";
|
|
elseif ( tempName == "Button8" ) then
|
|
tempName = "BUTTON8";
|
|
elseif ( tempName == "Button9" ) then
|
|
tempName = "BUTTON9";
|
|
elseif ( tempName == "Button10" ) then
|
|
tempName = "BUTTON10";
|
|
elseif ( tempName == "Button11" ) then
|
|
tempName = "BUTTON11";
|
|
elseif ( tempName == "Button12" ) then
|
|
tempName = "BUTTON12";
|
|
elseif ( tempName == "Button13" ) then
|
|
tempName = "BUTTON13";
|
|
elseif ( tempName == "Button14" ) then
|
|
tempName = "BUTTON14";
|
|
elseif ( tempName == "Button15" ) then
|
|
tempName = "BUTTON15";
|
|
elseif ( tempName == "Button16" ) then
|
|
tempName = "BUTTON16";
|
|
elseif ( tempName == "Button17" ) then
|
|
tempName = "BUTTON17";
|
|
elseif ( tempName == "Button18" ) then
|
|
tempName = "BUTTON18";
|
|
elseif ( tempName == "Button19" ) then
|
|
tempName = "BUTTON19";
|
|
elseif ( tempName == "Button20" ) then
|
|
tempName = "BUTTON20";
|
|
elseif ( tempName == "Button21" ) then
|
|
tempName = "BUTTON21";
|
|
elseif ( tempName == "Button22" ) then
|
|
tempName = "BUTTON22";
|
|
elseif ( tempName == "Button23" ) then
|
|
tempName = "BUTTON23";
|
|
elseif ( tempName == "Button24" ) then
|
|
tempName = "BUTTON24";
|
|
elseif ( tempName == "Button25" ) then
|
|
tempName = "BUTTON25";
|
|
elseif ( tempName == "Button26" ) then
|
|
tempName = "BUTTON26";
|
|
elseif ( tempName == "Button27" ) then
|
|
tempName = "BUTTON27";
|
|
elseif ( tempName == "Button28" ) then
|
|
tempName = "BUTTON28";
|
|
elseif ( tempName == "Button29" ) then
|
|
tempName = "BUTTON29";
|
|
elseif ( tempName == "Button30" ) then
|
|
tempName = "BUTTON30";
|
|
elseif ( tempName == "Button31" ) then
|
|
tempName = "BUTTON31";
|
|
end
|
|
|
|
local localizedName = nil;
|
|
if ( IsMacClient() ) then
|
|
-- see if there is a mac specific name for the key
|
|
localizedName = _G[prefix..tempName.."_MAC"];
|
|
end
|
|
if ( not localizedName ) then
|
|
localizedName = _G[prefix..tempName];
|
|
end
|
|
-- for the "push-to-talk" binding it can be just a modifier key
|
|
if ( not localizedName ) then
|
|
localizedName = _G[tempName.."_KEY_TEXT"];
|
|
end
|
|
if ( not localizedName ) then
|
|
localizedName = tempName;
|
|
end
|
|
return modKeys..localizedName;
|
|
end
|
|
|
|
|
|
function GetBindingFromClick(input)
|
|
local fullInput = "";
|
|
|
|
-- MUST BE IN THIS ORDER (ALT, CTRL, SHIFT)
|
|
if ( IsAltKeyDown() ) then
|
|
fullInput = fullInput.."ALT-";
|
|
end
|
|
|
|
if ( IsControlKeyDown() ) then
|
|
fullInput = fullInput.."CTRL-"
|
|
end
|
|
|
|
if ( IsShiftKeyDown() ) then
|
|
fullInput = fullInput.."SHIFT-"
|
|
end
|
|
|
|
if ( input == "LeftButton" ) then
|
|
fullInput = fullInput.."BUTTON1";
|
|
elseif ( input == "RightButton" ) then
|
|
fullInput = fullInput.."BUTTON2";
|
|
elseif ( input == "MiddleButton" ) then
|
|
fullInput = fullInput.."BUTTON3";
|
|
elseif ( input == "Button4" ) then
|
|
fullInput = fullInput.."BUTTON4";
|
|
elseif ( input == "Button5" ) then
|
|
fullInput = fullInput.."BUTTON5";
|
|
elseif ( input == "Button6" ) then
|
|
fullInput = fullInput.."BUTTON6";
|
|
elseif ( input == "Button7" ) then
|
|
fullInput = fullInput.."BUTTON7";
|
|
elseif ( input == "Button8" ) then
|
|
fullInput = fullInput.."BUTTON8";
|
|
elseif ( input == "Button9" ) then
|
|
fullInput = fullInput.."BUTTON9";
|
|
elseif ( input == "Button10" ) then
|
|
fullInput = fullInput.."BUTTON10";
|
|
elseif ( input == "Button11" ) then
|
|
fullInput = fullInput.."BUTTON11";
|
|
elseif ( input == "Button12" ) then
|
|
fullInput = fullInput.."BUTTON12";
|
|
elseif ( input == "Button13" ) then
|
|
fullInput = fullInput.."BUTTON13";
|
|
elseif ( input == "Button14" ) then
|
|
fullInput = fullInput.."BUTTON14";
|
|
elseif ( input == "Button15" ) then
|
|
fullInput = fullInput.."BUTTON15";
|
|
elseif ( input == "Button16" ) then
|
|
fullInput = fullInput.."BUTTON16";
|
|
elseif ( input == "Button17" ) then
|
|
fullInput = fullInput.."BUTTON17";
|
|
elseif ( input == "Button18" ) then
|
|
fullInput = fullInput.."BUTTON18";
|
|
elseif ( input == "Button19" ) then
|
|
fullInput = fullInput.."BUTTON19";
|
|
elseif ( input == "Button20" ) then
|
|
fullInput = fullInput.."BUTTON20";
|
|
elseif ( input == "Button21" ) then
|
|
fullInput = fullInput.."BUTTON21";
|
|
elseif ( input == "Button22" ) then
|
|
fullInput = fullInput.."BUTTON22";
|
|
elseif ( input == "Button23" ) then
|
|
fullInput = fullInput.."BUTTON23";
|
|
elseif ( input == "Button24" ) then
|
|
fullInput = fullInput.."BUTTON24";
|
|
elseif ( input == "Button25" ) then
|
|
fullInput = fullInput.."BUTTON25";
|
|
elseif ( input == "Button26" ) then
|
|
fullInput = fullInput.."BUTTON26";
|
|
elseif ( input == "Button27" ) then
|
|
fullInput = fullInput.."BUTTON27";
|
|
elseif ( input == "Button28" ) then
|
|
fullInput = fullInput.."BUTTON28";
|
|
elseif ( input == "Button29" ) then
|
|
fullInput = fullInput.."BUTTON29";
|
|
elseif ( input == "Button30" ) then
|
|
fullInput = fullInput.."BUTTON30";
|
|
elseif ( input == "Button31" ) then
|
|
fullInput = fullInput.."BUTTON31";
|
|
else
|
|
fullInput = fullInput..input;
|
|
end
|
|
|
|
return GetBindingByKey(fullInput);
|
|
end
|
|
|
|
|
|
-- Game Logic --
|
|
|
|
function RealPartyIsFull()
|
|
if ( (GetRealNumPartyMembers() < MAX_PARTY_MEMBERS) or (GetRealNumRaidMembers() > 0 and (GetRealNumRaidMembers() < MAX_RAID_MEMBERS)) ) then
|
|
return false;
|
|
else
|
|
return true;
|
|
end
|
|
end
|
|
|
|
function CanGroupInvite()
|
|
if ( (GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0) ) then
|
|
if ( IsPartyLeader() or IsRaidOfficer() ) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end
|
|
else
|
|
return true;
|
|
end
|
|
end
|
|
|
|
function UnitHasMana(unit)
|
|
local powerType, powerToken = UnitPowerType(unit);
|
|
if ( powerToken == "MANA" and UnitPowerMax(unit, powerType) > 0 ) then
|
|
return 1;
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
function RaiseFrameLevelByTwo(frame)
|
|
-- We do this enough that it saves closures.
|
|
frame:SetFrameLevel(frame:GetFrameLevel()+2);
|
|
end
|
|
|
|
function ShowResurrectRequest(offerer)
|
|
if ( ResurrectHasSickness() ) then
|
|
StaticPopup_Show("RESURRECT", offerer);
|
|
elseif ( ResurrectHasTimer() ) then
|
|
StaticPopup_Show("RESURRECT_NO_SICKNESS", offerer);
|
|
else
|
|
StaticPopup_Show("RESURRECT_NO_TIMER", offerer);
|
|
end
|
|
end
|
|
|
|
function RefreshAuras(frame, unit, numAuras, suffix, checkCVar, showBuffs)
|
|
if ( showBuffs ) then
|
|
RefreshBuffs(frame, unit, numAuras, suffix, checkCVar);
|
|
else
|
|
RefreshDebuffs(frame, unit, numAuras, suffix, checkCVar);
|
|
end
|
|
end
|
|
|
|
function RefreshBuffs(frame, unit, numBuffs, suffix, checkCVar)
|
|
local frameName = frame:GetName();
|
|
|
|
frame.hasDispellable = nil;
|
|
|
|
numBuffs = numBuffs or MAX_PARTY_BUFFS;
|
|
suffix = suffix or "Buff";
|
|
|
|
local unitStatus, statusColor;
|
|
local debuffTotal = 0;
|
|
local name, rank, icon, count, debuffType, duration, expirationTime;
|
|
for i=1, numBuffs do
|
|
local filter;
|
|
if ( checkCVar and GetCVarBool("showCastableBuffs") ) then
|
|
filter = "RAID";
|
|
end
|
|
name, rank, icon, count, debuffType, duration, expirationTime = UnitBuff(unit, i, filter);
|
|
|
|
local buffName = frameName..suffix..i;
|
|
if ( icon ) then
|
|
-- if we have an icon to show then proceed with setting up the aura
|
|
|
|
-- set the icon
|
|
local buffIcon = _G[buffName.."Icon"];
|
|
buffIcon:SetTexture(icon);
|
|
|
|
-- setup the cooldown
|
|
local coolDown = _G[buffName.."Cooldown"];
|
|
if ( coolDown ) then
|
|
CooldownFrame_SetTimer(coolDown, expirationTime - duration, duration, 1);
|
|
end
|
|
|
|
-- show the aura
|
|
_G[buffName]:Show();
|
|
else
|
|
-- no icon, hide the aura
|
|
_G[buffName]:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
function RefreshDebuffs(frame, unit, numDebuffs, suffix, checkCVar)
|
|
local frameName = frame:GetName();
|
|
|
|
frame.hasDispellable = nil;
|
|
|
|
numDebuffs = numDebuffs or MAX_PARTY_DEBUFFS;
|
|
suffix = suffix or "Debuff";
|
|
|
|
local unitStatus, statusColor;
|
|
local debuffTotal = 0;
|
|
local name, rank, icon, count, debuffType, duration, expirationTime, caster;
|
|
local isEnemy = UnitCanAttack("player", unit);
|
|
for i=1, numDebuffs do
|
|
if ( unit == "party"..i ) then
|
|
unitStatus = _G[frameName.."Status"];
|
|
end
|
|
|
|
local filter;
|
|
if ( checkCVar and GetCVarBool("showDispelDebuffs") ) then
|
|
filter = "RAID";
|
|
end
|
|
name, rank, icon, count, debuffType, duration, expirationTime, caster = UnitDebuff(unit, i, filter);
|
|
|
|
local debuffName = frameName..suffix..i;
|
|
if ( icon and ( SHOW_CASTABLE_DEBUFFS == "0" or not isEnemy or caster == "player" ) ) then
|
|
-- if we have an icon to show then proceed with setting up the aura
|
|
|
|
-- set the icon
|
|
local debuffIcon = _G[debuffName.."Icon"];
|
|
debuffIcon:SetTexture(icon);
|
|
|
|
-- setup the border
|
|
local debuffBorder = _G[debuffName.."Border"];
|
|
local debuffColor = DebuffTypeColor[debuffType] or DebuffTypeColor["none"];
|
|
debuffBorder:SetVertexColor(debuffColor.r, debuffColor.g, debuffColor.b);
|
|
|
|
-- record interesting data for the aura button
|
|
statusColor = debuffColor;
|
|
frame.hasDispellable = 1;
|
|
debuffTotal = debuffTotal + 1;
|
|
|
|
-- setup the cooldown
|
|
local coolDown = _G[debuffName.."Cooldown"];
|
|
if ( coolDown ) then
|
|
CooldownFrame_SetTimer(coolDown, expirationTime - duration, duration, 1);
|
|
end
|
|
|
|
-- show the aura
|
|
_G[debuffName]:Show();
|
|
else
|
|
-- no icon, hide the aura
|
|
_G[debuffName]:Hide();
|
|
end
|
|
end
|
|
|
|
frame.debuffTotal = debuffTotal;
|
|
-- Reset unitStatus overlay graphic timer
|
|
if ( frame.numDebuffs and debuffTotal >= frame.numDebuffs ) then
|
|
frame.debuffCountdown = 30;
|
|
end
|
|
if ( unitStatus and statusColor ) then
|
|
unitStatus:SetVertexColor(statusColor.r, statusColor.g, statusColor.b);
|
|
end
|
|
end
|
|
|
|
function GetQuestDifficultyColor(level)
|
|
local levelDiff = level - UnitLevel("player");
|
|
local color;
|
|
if ( levelDiff >= 5 ) then
|
|
return QuestDifficultyColors["impossible"];
|
|
elseif ( levelDiff >= 3 ) then
|
|
return QuestDifficultyColors["verydifficult"];
|
|
elseif ( levelDiff >= -2 ) then
|
|
return QuestDifficultyColors["difficult"];
|
|
elseif ( -levelDiff <= GetQuestGreenRange() ) then
|
|
return QuestDifficultyColors["standard"];
|
|
else
|
|
return QuestDifficultyColors["trivial"];
|
|
end
|
|
end
|
|
|
|
function GetDungeonNameWithDifficulty(name, difficultyName)
|
|
name = name or "";
|
|
if ( difficultyName == "" ) then
|
|
name = NORMAL_FONT_COLOR_CODE..name..FONT_COLOR_CODE_CLOSE;
|
|
else
|
|
name = NORMAL_FONT_COLOR_CODE..format(DUNGEON_NAME_WITH_DIFFICULTY, name, difficultyName)..FONT_COLOR_CODE_CLOSE;
|
|
end
|
|
return name;
|
|
end
|
|
|
|
|
|
-- Animated shine stuff --
|
|
|
|
function AnimatedShine_Start(shine, r, g, b)
|
|
if ( not tContains(SHINES_TO_ANIMATE, shine) ) then
|
|
shine.timer = 0;
|
|
tinsert(SHINES_TO_ANIMATE, shine);
|
|
end
|
|
local shineName = shine:GetName();
|
|
_G[shineName.."Shine1"]:Show();
|
|
_G[shineName.."Shine2"]:Show();
|
|
_G[shineName.."Shine3"]:Show();
|
|
_G[shineName.."Shine4"]:Show();
|
|
if ( r ) then
|
|
_G[shineName.."Shine1"]:SetVertexColor(r, g, b);
|
|
_G[shineName.."Shine2"]:SetVertexColor(r, g, b);
|
|
_G[shineName.."Shine3"]:SetVertexColor(r, g, b);
|
|
_G[shineName.."Shine4"]:SetVertexColor(r, g, b);
|
|
end
|
|
|
|
end
|
|
|
|
function AnimatedShine_Stop(shine)
|
|
tDeleteItem(SHINES_TO_ANIMATE, shine);
|
|
local shineName = shine:GetName();
|
|
_G[shineName.."Shine1"]:Hide();
|
|
_G[shineName.."Shine2"]:Hide();
|
|
_G[shineName.."Shine3"]:Hide();
|
|
_G[shineName.."Shine4"]:Hide();
|
|
end
|
|
|
|
function AnimatedShine_OnUpdate(elapsed)
|
|
local shine1, shine2, shine3, shine4;
|
|
local speed = 2.5;
|
|
local parent, distance;
|
|
for index, value in pairs(SHINES_TO_ANIMATE) do
|
|
shine1 = _G[value:GetName().."Shine1"];
|
|
shine2 = _G[value:GetName().."Shine2"];
|
|
shine3 = _G[value:GetName().."Shine3"];
|
|
shine4 = _G[value:GetName().."Shine4"];
|
|
value.timer = value.timer+elapsed;
|
|
if ( value.timer > speed*4 ) then
|
|
value.timer = 0;
|
|
end
|
|
parent = _G[value:GetName().."Shine"];
|
|
distance = parent:GetWidth();
|
|
if ( value.timer <= speed ) then
|
|
shine1:SetPoint("CENTER", parent, "TOPLEFT", value.timer/speed*distance, 0);
|
|
shine2:SetPoint("CENTER", parent, "BOTTOMRIGHT", -value.timer/speed*distance, 0);
|
|
shine3:SetPoint("CENTER", parent, "TOPRIGHT", 0, -value.timer/speed*distance);
|
|
shine4:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, value.timer/speed*distance);
|
|
elseif ( value.timer <= speed*2 ) then
|
|
shine1:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed)/speed*distance);
|
|
shine2:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed)/speed*distance);
|
|
shine3:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed)/speed*distance, 0);
|
|
shine4:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed)/speed*distance, 0);
|
|
elseif ( value.timer <= speed*3 ) then
|
|
shine1:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed*2)/speed*distance, 0);
|
|
shine2:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed*2)/speed*distance, 0);
|
|
shine3:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed*2)/speed*distance);
|
|
shine4:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed*2)/speed*distance);
|
|
else
|
|
shine1:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed*3)/speed*distance);
|
|
shine2:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed*3)/speed*distance);
|
|
shine3:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed*3)/speed*distance, 0);
|
|
shine4:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed*3)/speed*distance, 0);
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
-- Autocast shine stuff --
|
|
|
|
AUTOCAST_SHINE_R = .95;
|
|
AUTOCAST_SHINE_G = .95;
|
|
AUTOCAST_SHINE_B = .32;
|
|
|
|
AUTOCAST_SHINE_SPEEDS = { 2, 4, 6, 8 };
|
|
AUTOCAST_SHINE_TIMERS = { 0, 0, 0, 0 };
|
|
|
|
local AUTOCAST_SHINES = {};
|
|
|
|
|
|
function AutoCastShine_OnLoad(self)
|
|
self.sparkles = {};
|
|
|
|
local name = self:GetName();
|
|
|
|
for i = 1, 16 do
|
|
tinsert(self.sparkles, _G[name .. i]);
|
|
end
|
|
end
|
|
|
|
function AutoCastShine_AutoCastStart(button, r, g, b)
|
|
if ( AUTOCAST_SHINES[button] ) then
|
|
return;
|
|
end
|
|
|
|
AUTOCAST_SHINES[button] = true;
|
|
|
|
if ( not r ) then
|
|
r, g, b = AUTOCAST_SHINE_R, AUTOCAST_SHINE_G, AUTOCAST_SHINE_B;
|
|
end
|
|
|
|
for _, sparkle in next, button.sparkles do
|
|
sparkle:Show();
|
|
sparkle:SetVertexColor(r, g, b);
|
|
end
|
|
end
|
|
|
|
function AutoCastShine_AutoCastStop(button)
|
|
AUTOCAST_SHINES[button] = nil;
|
|
|
|
for _, sparkle in next, button.sparkles do
|
|
sparkle:Hide();
|
|
end
|
|
end
|
|
|
|
function AutoCastShine_OnUpdate(self, elapsed)
|
|
for i in next, AUTOCAST_SHINE_TIMERS do
|
|
AUTOCAST_SHINE_TIMERS[i] = AUTOCAST_SHINE_TIMERS[i] + elapsed;
|
|
if ( AUTOCAST_SHINE_TIMERS[i] > AUTOCAST_SHINE_SPEEDS[i]*4 ) then
|
|
AUTOCAST_SHINE_TIMERS[i] = 0;
|
|
end
|
|
end
|
|
|
|
for button in next, AUTOCAST_SHINES do
|
|
self = button;
|
|
local parent, distance = self, self:GetWidth();
|
|
|
|
-- This is local to this function to save a lookup. If you need to use it elsewhere, might wanna make it global and use a local reference.
|
|
local AUTOCAST_SHINE_SPACING = 6;
|
|
|
|
for i = 1, 4 do
|
|
local timer = AUTOCAST_SHINE_TIMERS[i];
|
|
local speed = AUTOCAST_SHINE_SPEEDS[i];
|
|
|
|
if ( timer <= speed ) then
|
|
local basePosition = timer/speed*distance;
|
|
self.sparkles[0+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
|
|
self.sparkles[4+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
|
|
self.sparkles[8+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
|
|
self.sparkles[12+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
|
|
elseif ( timer <= speed*2 ) then
|
|
local basePosition = (timer-speed)/speed*distance;
|
|
self.sparkles[0+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
|
|
self.sparkles[4+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
|
|
self.sparkles[8+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
|
|
self.sparkles[12+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
|
|
elseif ( timer <= speed*3 ) then
|
|
local basePosition = (timer-speed*2)/speed*distance;
|
|
self.sparkles[0+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
|
|
self.sparkles[4+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
|
|
self.sparkles[8+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
|
|
self.sparkles[12+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
|
|
else
|
|
local basePosition = (timer-speed*3)/speed*distance;
|
|
self.sparkles[0+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
|
|
self.sparkles[4+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
|
|
self.sparkles[8+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
|
|
self.sparkles[12+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ConsolePrint(...)
|
|
ConsoleAddMessage(strjoin(" ", tostringall(...)));
|
|
end
|
|
|
|
function GetTexCoordsByGrid(xOffset, yOffset, textureWidth, textureHeight, gridWidth, gridHeight)
|
|
local widthPerGrid = gridWidth/textureWidth;
|
|
local heightPerGrid = gridHeight/textureHeight;
|
|
return (xOffset-1)*widthPerGrid, (xOffset)*widthPerGrid, (yOffset-1)*heightPerGrid, (yOffset)*heightPerGrid;
|
|
end
|
|
|
|
function LFD_IsEmpowered()
|
|
return not ( ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0)) and
|
|
not (IsPartyLeader() or IsRaidLeader()) ) or HasLFGRestrictions();
|
|
end
|
|
|
|
function LFR_IsEmpowered()
|
|
return not ( ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0)) and
|
|
not (IsPartyLeader() or IsRaidLeader()) );
|
|
end
|
|
|
|
function GetLFGMode()
|
|
local proposalExists, typeID, id, name, texture, role, hasResponded, totalEncounters, completedEncounters, numMembers = GetLFGProposal();
|
|
local inParty, joined, queued, noPartialClear, achievements, lfgComment, slotCount = GetLFGInfoServer();
|
|
local roleCheckInProgress, slots, members = GetLFGRoleUpdate();
|
|
|
|
if ( proposalExists and not hasResponded ) then
|
|
return "proposal", "unaccepted";
|
|
elseif ( proposalExists ) then
|
|
return "proposal", "accepted";
|
|
elseif ( queued ) then
|
|
return "queued", (LFD_IsEmpowered() and "empowered" or "unempowered");
|
|
elseif ( roleCheckInProgress ) then
|
|
return "rolecheck";
|
|
elseif ( IsListedInLFR() ) then
|
|
return "listed", (LFR_IsEmpowered() and "empowered" or "unempowered");
|
|
elseif ( IsPartyLFG() and ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0)) ) then
|
|
return "lfgparty";
|
|
elseif ( IsPartyLFG() and IsInLFGDungeon() ) then
|
|
return "abandonedInDungeon";
|
|
end
|
|
end
|
|
|
|
--Like date(), but localizes AM/PM. In the future, could also localize other stuff.
|
|
function BetterDate(formatString, timeVal)
|
|
local dateTable = date("*t", timeVal);
|
|
local amString = (dateTable.hour >= 12) and TIMEMANAGER_PM or TIMEMANAGER_AM;
|
|
|
|
--First, we'll replace %p with the appropriate AM or PM.
|
|
formatString = gsub(formatString, "^%%p", amString) --Replaces %p at the beginning of the string with the am/pm token
|
|
formatString = gsub(formatString, "([^%%])%%p", "%1"..amString); -- Replaces %p anywhere else in the string, but doesn't replace %%p (since the first % escapes the second)
|
|
|
|
return date(formatString, timeVal);
|
|
end
|