Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Author: Alternator (Massiner of Nathrezim)
- Copyright 2010
- Notes:
- ]]
- local Util = BFUtil;
- local Const = BFConst;
- local UILib = BFUILib;
- local CustomAction = BFCustomAction;
- local Button = BFButton;
- local Bar = BFBar;
- local EventFull = BFEventFrames["Full"];
- local MiscFrame = BFEventFrames["Misc"];
- local Delay = BFEventFrames["Delay"];
- local ConfigureLayer = BFConfigureLayer;
- local DestroyBarOverlay = BFDestroyBarOverlay;
- --This will get the currently applicable locale, or allocate it if needed (note that locales other than enUS will need the metatable set)
- BFLocales[GetLocale()] = BFLocales[GetLocale()] or {};
- local Locale = BFLocales[GetLocale()];
- if (GetLocale() ~= "enUS") then
- setmetatable(Locale, BFLocales["enUS"]);
- end
- Util.ActiveButtons = {};
- Util.InactiveButtons = {};
- Util.ActiveMacros = {};
- Util.ActiveSpells = {};
- Util.ActiveItems = {};
- Util.ActiveBonusActions = {};
- Util.RangeTimerButtons = {};
- Util.FlashButtons = {};
- Util.ActiveBars = {};
- Util.InactiveBars = {};
- Util.ActiveTabs = {};
- Util.InactiveTabs = {};
- Util.SpellIndex = {};
- Util.SpellMana = {};
- Util.NewSpellIndex = {};
- Util.GlowSpells = {};
- Util.PetSpellIndex = {};
- Util.NewPetSpellIndex = {};
- Util.BagItemNameIndex = {};
- Util.BagItemIdIndex = {};
- Util.BagItemNameId = {};
- Util.InvItemNameIndex = {};
- Util.InvItemIdIndex = {};
- Util.InvItemNameId = {};
- Util.GridHidden = true;
- Util.LowStrata = true;
- Util.BlizBarWrappers = {};
- Util.BlizEnabledBars = {};
- Util.CallbackFunctions = {};
- Util.CallbackArgs = {};
- Util.ButtonWidgetMap = {};
- Util.UpdateMacroEventCount = 0;
- Util.MacroCheckDelayComplete = false;
- Util.ForceOffCastOnKeyDown = false;
- Util.MountUselessIndexToIndex = {};
- --One quick override function
- local G_PickupSpellBookItem = PickupSpellBookItem;
- local function PickupSpellBookItem(NameRank, Book)
- local Index, Alt_Book = Util.LookupSpellIndex(NameRank);
- if (Index) then
- return G_PickupSpellBookItem(Index, Alt_Book);
- elseif (Book) then
- return G_PickupSpellBookItem(NameRank, Book);
- end
- return G_PickupSpellBookItem(NameRank);
- end
- --[[
- Make sure that the saved data is kept inline with the version being run
- --]]
- function Util.UpdateSavedData()
- ---- FIX for MACS, if character data hasn't loaded but is otherwise available in the global save ----
- local CharRealm = UnitName("player");
- CharRealm = CharRealm.."-"..GetRealmName();
- if (ButtonForgeSave == nil
- and ButtonForgeGlobalBackup ~= nil
- and ButtonForgeGlobalBackup[CharRealm] ~= nil) then
- ButtonForgeSave = ButtonForgeGlobalBackup[CharRealm];
- end
- ------The following section updates the per character saved data------
- --Need to allocate save structure
- if (not ButtonForgeSave) then
- --Swap v0.9.0 / v0.9.1 / v0.9.2 users to the new save structure
- if (type(BFSave) == "table" and BFSave["Version"] and BFSave["VersionMinor"] and
- BFSave["Version"] == 0.9 and BFSave["VersionMinor"] <= 2) then
- --the above test checks if a legitimate ButtonForge BFSave exists before we adopt it to the new table name
- ButtonForgeSave = BFSave;
- BFSave = nil;
- else
- ButtonForgeSave = {};
- ButtonForgeSave["ConfigureMode"] = true;
- ButtonForgeSave["AdvancedMode"] = false;
- ButtonForgeSave["RightClickSelfCast"] = false;
- ButtonForgeSave["Version"] = Const.Version;
- ButtonForgeSave["VersionMinor"] = Const.VersionMinor;
- ButtonForgeSave.Bars = {};
- end
- ButtonForgeSave["AddonName"] = "Button Forge";
- end
- --v0.9.3 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 3) then
- for i = 1, #ButtonForgeSave.Bars do
- ButtonForgeSave.Bars[i]["HBonusBar"] = true;
- end
- ButtonForgeSave["VersionMinor"] = 3;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.3", .5, 1, 0, 1);
- end
- --v0.9.12 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 12) then
- for i = 1, #ButtonForgeSave.Bars do
- ButtonForgeSave.Bars[i]["MacroText"] = true;
- ButtonForgeSave.Bars[i]["KeyBindText"] = true;
- end
- ButtonForgeSave["VersionMinor"] = 12;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.12", .5, 1, 0, 1);
- end
- --v0.9.13 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 13) then
- for i = 1, #ButtonForgeSave.Bars do
- ButtonForgeSave.Bars[i]["Enabled"] = true;
- ButtonForgeSave.Bars[i]["ButtonGap"] = 6;
- end
- ButtonForgeSave["VersionMinor"] = 13;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.13", .5, 1, 0, 1);
- end
- --v0.9.17 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 17) then
- for i = 1, #ButtonForgeSave.Bars do
- ButtonForgeSave.Bars[i]["GUI"] = true;
- ButtonForgeSave.Bars[i]["Alpha"] = 1;
- end
- ButtonForgeSave["VersionMinor"] = 17;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.17", .5, 1, 0, 1);
- end
- --v0.9.22 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 22) then
- for i = 1, #ButtonForgeSave.Bars do
- if (ButtonForgeSave.Bars[i]["VDriver"] == "[bonusbar:5] show; hide") then
- ButtonForgeSave.Bars[i]["VDriver"] = "[overridebar][vehicleui] show; hide";
- end
- end
- ButtonForgeSave["VersionMinor"] = 22;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.22", .5, 1, 0, 1);
- end
- --v0.9.25 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 25) then
- for i = 1, #ButtonForgeSave.Bars do
- ButtonForgeSave.Bars[i]["HPetBattle"] = true;
- end
- ButtonForgeSave["VersionMinor"] = 25;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.25", .5, 1, 0, 1);
- end
- -- v0.9.34 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 34) then
- for i = 1, #ButtonForgeSave.Bars do
- Util.UpdateMounts602(ButtonForgeSave.Bars[i].Buttons);
- end
- ButtonForgeSave["VersionMinor"] = 34;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.34", .5, 1, 0, 1);
- end
- -- v0.9.36 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 36) then
- for i = 1, #ButtonForgeSave.Bars do
- Util.UpdateBattlePets602(ButtonForgeSave.Bars[i].Buttons);
- end
- if (ButtonForgeSave.UndoProfileBars ~= nil) then
- for i = 1, #ButtonForgeSave.UndoProfileBars do
- Util.UpdateMounts602(ButtonForgeSave.UndoProfileBars[i].Buttons);
- Util.UpdateBattlePets602(ButtonForgeSave.UndoProfileBars[i].Buttons);
- end
- end
- ButtonForgeSave["VersionMinor"] = 36;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.36", .5, 1, 0, 1);
- end
- -- v0.9.41 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 41) then
- for i = 1, #ButtonForgeSave.Bars do
- Util.UpdateMounts700(ButtonForgeSave.Bars[i].Buttons);
- end
- if (ButtonForgeSave.UndoProfileBars ~= nil) then
- for i = 1, #ButtonForgeSave.UndoProfileBars do
- Util.UpdateMounts700(ButtonForgeSave.UndoProfileBars[i].Buttons);
- end
- end
- ButtonForgeSave["VersionMinor"] = 41;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.41", .5, 1, 0, 1);
- end
- -- v0.9.42 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 42) then
- for i = 1, #ButtonForgeSave.Bars do
- ButtonForgeSave.Bars[i].HSpec3 = false;
- ButtonForgeSave.Bars[i].HSpec4 = false;
- end
- if (ButtonForgeSave.UndoProfileBars ~= nil) then
- for i = 1, #ButtonForgeSave.UndoProfileBars do
- ButtonForgeSave.UndoProfileBars[i].HSpec3 = false;
- ButtonForgeSave.UndoProfileBars[i].HSpec4 = false;
- end
- end
- ButtonForgeSave["VersionMinor"] = 42;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.42", .5, 1, 0, 1);
- end
- -- v0.9.44 update
- if (ButtonForgeSave["Version"] == 0.9 and ButtonForgeSave["VersionMinor"] < 44) then
- for i = 1, #ButtonForgeSave.Bars do
- Util.RemoveCancelPossession700(ButtonForgeSave.Bars[i].Buttons);
- end
- if (ButtonForgeSave.UndoProfileBars ~= nil) then
- for i = 1, #ButtonForgeSave.UndoProfileBars do
- Util.RemoveCancelPossession700(ButtonForgeSave.UndoProfileBars[i].Buttons);
- end
- end
- ButtonForgeSave["VersionMinor"] = 44;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v0.9.44", .5, 1, 0, 1);
- end
- --Bring v up to the latest version
- if (ButtonForgeSave["Version"] < Const.Version) then
- ButtonForgeSave["Version"] = Const.Version;
- ButtonForgeSave["VersionMinor"] = Const.VersionMinor;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v"..Const.Version.."."..Const.VersionMinor, .5, 1, 0, 1);
- elseif (ButtonForgeSave["Version"] == Const.Version and ButtonForgeSave["VersionMinor"] < Const.VersionMinor) then
- ButtonForgeSave["VersionMinor"] = Const.VersionMinor;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UpgradedChatMsg").."v"..Const.Version.."."..Const.VersionMinor, .5, 1, 0, 1);
- end
- -----This section updates the global button forge data (introduced at 0.9.16)
- if (not ButtonForgeGlobalSettings) then
- ButtonForgeGlobalSettings = {};
- ButtonForgeGlobalSettings["Version"] = 0.9;
- ButtonForgeGlobalSettings["VersionMinor"] = 16;
- ButtonForgeGlobalSettings["MacroCheckDelay"] = 3;
- ButtonForgeGlobalSettings["RemoveMissingMacros"] = true;
- end
- --v0.9.30 update (to global settings)
- if (ButtonForgeGlobalSettings["Version"] == 0.9 and ButtonForgeGlobalSettings["VersionMinor"] < 30) then
- ButtonForgeGlobalSettings["ForceOffCastOnKeyDown"] = false;
- ButtonForgeGlobalSettings["VersionMinor"] = 30;
- end
- --v0.9.31 update (to global profiles)
- if (ButtonForgeGlobalSettings["Version"] == 0.9 and ButtonForgeGlobalSettings["VersionMinor"] < 31) then
- ButtonForgeGlobalProfiles = {};
- ButtonForgeGlobalSettings["VersionMinor"] = 31;
- end
- --pre v0.9.36 Safety process
- if (not ButtonForgeGlobalProfiles) then
- ButtonForgeGlobalProfiles = {};
- end
- --v0.9.36 update
- if (ButtonForgeGlobalSettings["Version"] == 0.9 and ButtonForgeGlobalSettings["VersionMinor"] < 36) then
- for k,v in pairs(ButtonForgeGlobalProfiles) do
- for i = 1, #v.Bars do
- Util.UpdateMounts602(v.Bars[i].Buttons);
- Util.UpdateBattlePets602(v.Bars[i].Buttons);
- end
- end
- ButtonForgeGlobalSettings["VersionMinor"] = 36;
- end
- --v0.9.38 update
- if (ButtonForgeGlobalBackup == nil) then
- ButtonForgeGlobalBackup = {};
- end
- -- v0.9.41
- if (ButtonForgeGlobalSettings["Version"] == 0.9 and ButtonForgeGlobalSettings["VersionMinor"] < 41) then
- for k, v in pairs(ButtonForgeGlobalProfiles) do
- for i = 1, #v.Bars do
- Util.UpdateMounts700(v.Bars[i].Buttons);
- end
- end
- ButtonForgeGlobalSettings["VersionMinor"] = 41;
- end
- -- v0.9.42
- if (ButtonForgeGlobalSettings["Version"] == 0.9 and ButtonForgeGlobalSettings["VersionMinor"] < 42) then
- for k, v in pairs(ButtonForgeGlobalProfiles) do
- for i = 1, #v.Bars do
- v.Bars[i].HSpec3 = false;
- v.Bars[i].HSpec4 = false;
- end
- end
- ButtonForgeGlobalSettings["VersionMinor"] = 42;
- end
- -- v0.9.44
- if (ButtonForgeGlobalSettings["Version"] == 0.9 and ButtonForgeGlobalSettings["VersionMinor"] < 44) then
- ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"] = not AreDangerousScriptsAllowed();
- ButtonForgeGlobalSettings["VersionMinor"] = 44;
- for k, v in pairs(ButtonForgeGlobalProfiles) do
- for i = 1, #v.Bars do
- Util.RemoveCancelPossession700(v.Bars[i].Buttons);
- end
- end
- end
- --Bring the global settings up to the latest version
- if (ButtonForgeGlobalSettings["Version"] < Const.Version) then
- ButtonForgeGlobalSettings["Version"] = Const.Version;
- ButtonForgeGlobalSettings["VersionMinor"] = Const.VersionMinor;
- elseif (ButtonForgeGlobalSettings["Version"] == Const.Version and ButtonForgeGlobalSettings["VersionMinor"] < Const.VersionMinor) then
- ButtonForgeGlobalSettings["VersionMinor"] = Const.VersionMinor;
- end
- end
- function Util.UpdateMounts602(Buttons)
- Util.UpdateMounts700(Buttons)
- for j = 1, #Buttons do
- if (Buttons[j]["Mode"] == "companion") then
- -- Either fix the mapping, or clear the mount
- local MountID = Util.GetMountIDFromName(Buttons[j]["CompanionName"]);
- Buttons[j]["Mode"] = nil;
- Buttons[j]["CompanionId"] = nil;
- Buttons[j]["CompanionType"] = nil;
- Buttons[j]["CompanionIndex"] = nil;
- Buttons[j]["CompanionName"] = nil;
- Buttons[j]["CompanionSpellName"] = nil;
- if (Index) then
- Buttons[j]["Mode"] = "mount";
- Buttons[j]["MountID"] = MountID;
- end
- end
- end
- end
- function Util.UpdateBattlePets602(Buttons)
- for j = 1, #Buttons do
- if (Buttons[j]["Mode"] == "battlepet") then
- Buttons[j]["Mode"] = nil;
- Buttons[j]["BattlePetId"] = nil;
- end
- end
- end
- function Util.UpdateMounts700(Buttons)
- for j = 1, #Buttons do
- if (Buttons[j]["Mode"] == "mount") then
- local MountIndex = Buttons[j]["MountIndex"];
- local MountName = Buttons[j]["MountName"];
- Buttons[j]["MountID"] = nil;
- Buttons[j]["MountSpellID"] = nil;
- Buttons[j]["MountName"] = nil;
- Buttons[j]["MountIndex"] = nil;
- if (MountIndex == 0) then
- Buttons[j]["MountID"] = Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID;
- else
- local MountID = Util.GetMountIDFromName(MountName);
- if (MountID) then
- Buttons[j]["MountID"] = MountID;
- else
- Buttons[j]["Mode"] = nil;
- end
- end
- end
- end
- end
- function Util.RemoveCancelPossession700(Buttons)
- for j = 1, #Buttons do
- if (Buttons[j]["Mode"] == "customaction" and Buttons[j]["CustomActionName"] == "possesscancel") then
- Buttons[j]["Mode"] = nil;
- Buttons[j]["CustomActionName"] = nil;
- end
- end
- end
- --[[
- Load the bars and buttons from the saved addon values
- --]]
- function Util.Load()
- local CharRealm = UnitName("player");
- CharRealm = CharRealm.."-"..GetRealmName();
- ButtonForgeGlobalBackup[CharRealm] = ButtonForgeSave;
- Util.ForceOffCastOnKeyDown = ButtonForgeGlobalSettings["ForceOffCastOnKeyDown"];
- if (not Util.ForceOffCastOnKeyDown) then
- hooksecurefunc("SetCVar", MiscFrame.SetCVarCalled);
- end
- if (ButtonForgeSave.ConfigureMode) then
- ConfigureLayer:Show();
- end
- if (ButtonForgeSave.AdvancedMode) then
- UILib.ToggleAdvancedTools();
- end
- --if (Util.LBFMasterGroup and ButtonForgeSave["SkinID"]) then
- -- Util.LBFMasterGroup:Skin(ButtonForgeSave.SkinID, ButtonForgeSave.Gloss, ButtonForgeSave.Backdrop, ButtonForgeSave.Colors);
- --end
- for i = 1, #ButtonForgeSave.Bars do
- Util.NewBar(0, 0, ButtonForgeSave.Bars[i]);
- end
- UILib.ToggleRightClickSelfCast(ButtonForgeSave["RightClickSelfCast"] or false);
- Util.Loaded = true;
- Util.StartMacroCheckDelay();
- Util.RefreshOnUpdateFunction();
- SLASH_BUTTONFORGE1 = Util.GetLocaleString("SlashButtonForge1"); -- = "/buttonforge"; --these two identifiers probably shouldn't change, but if need be they can be?!
- SLASH_BUTTONFORGE2 = Util.GetLocaleString("SlashButtonForge2"); -- = "/bufo";
- collectgarbage("collect");
- Util.CallbackEvent("INITIALISED");
- end
- -- Grabbed from the Lua wiki
- function Util.deepcopy(orig)
- local orig_type = type(orig)
- local copy
- if orig_type == 'table' then
- copy = {}
- for orig_key, orig_value in next, orig, nil do
- copy[Util.deepcopy(orig_key)] = Util.deepcopy(orig_value)
- end
- -- setmetatable(copy, Util.deepcopy(getmetatable(orig))) -- I don't need this specifically for ButtonForge
- else -- number, string, boolean, etc
- copy = orig
- end
- return copy
- end
- --[[
- Load the bars and buttons from a profile
- --]]
- function Util.LoadProfile(ProfileName)
- if (InCombatLockdown()) then
- Util.SlashShowMessageByLine(Util.GetLocaleString("ActionFailedCombatLockdown"));
- return;
- end
- if (ButtonForgeGlobalProfiles[string.upper(ProfileName)] == nil) then
- Util.SlashShowMessageByLine(Util.GetLocaleString("ProfileNotFound"));
- return;
- end
- -- 1. Store the current configuration as the revert configuration for this character, in case the players wishes to go back
- ButtonForgeSave.UndoProfileBars = Util.deepcopy(ButtonForgeSave.Bars);
- -- 2. Deallocate the current UI
- for i = #Util.ActiveBars, 1, -1 do
- Util.DeallocateBar(Util.ActiveBars[i]);
- end
- -- 3. Apply the profile as the new bars/buttons for this character
- ButtonForgeSave.Bars = Util.deepcopy(ButtonForgeGlobalProfiles[string.upper(ProfileName)].Bars);
- -- 4. Attach the Bars back to the UI
- for i = 1, #ButtonForgeSave.Bars do
- Util.NewBar(0, 0, ButtonForgeSave.Bars[i]);
- end
- Util.RefreshCompanions();
- Util.RefreshMacros();
- Util.RefreshEquipmentSets();
- Util.RefreshSpells();
- Util.RefreshGridStatus(true);
- Util.RefreshBarStrata(true);
- Util.RefreshBarGUIStatus();
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("LoadedProfile"), .5, 1, 0, 1);
- end
- --[[
- Load the bars and buttons from a profile
- --]]
- function Util.LoadProfileTemplate(ProfileName)
- if (InCombatLockdown()) then
- Util.SlashShowMessageByLine(Util.GetLocaleString("ActionFailedCombatLockdown"));
- return;
- end
- if (ButtonForgeGlobalProfiles[string.upper(ProfileName)] == nil) then
- Util.SlashShowMessageByLine(Util.GetLocaleString("ProfileNotFound"));
- return;
- end
- -- 1. Store the current configuration as the revert configuration for this character, in case the players wishes to go back
- ButtonForgeSave.UndoProfileBars = Util.deepcopy(ButtonForgeSave.Bars);
- -- 2. Deallocate the current UI
- for i = #Util.ActiveBars, 1, -1 do
- Util.DeallocateBar(Util.ActiveBars[i]);
- end
- -- 3. Apply the profile as the new bars/buttons for this character
- ButtonForgeSave.Bars = Util.deepcopy(ButtonForgeGlobalProfiles[string.upper(ProfileName)].Bars);
- -- 4. Attach the Bars back to the UI
- for i = 1, #ButtonForgeSave.Bars do
- Util.NewBar(0, 0, ButtonForgeSave.Bars[i]);
- end
- -- 5. Blank all the buttons - this is programatically the easiest way to handle it
- for i = 1, #Util.ActiveButtons do
- if (Util.ActiveButtons[i].Mode ~= "bonusaction") then
- Util.ActiveButtons[i]:SetCommandFromTriplet();
- end
- end
- Util.RefreshGridStatus(true);
- Util.RefreshBarStrata(true);
- Util.RefreshBarGUIStatus();
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("LoadedProfileTemplate"), .5, 1, 0, 1);
- end
- --[[
- Save the bars and buttons to a profile, NB ProfileName is case insenstive for the purposes of saving loading deleting
- --]]
- function Util.SaveProfile(ProfileName)
- local NewProfile = {};
- NewProfile.Name = ProfileName; -- To capture the case sensitive version
- -- Record this extra info in case it is useful later, probably wont be but could help keep profiles organised with a future update??
- NewProfile.Icon = "INV_Misc_QuestionMark"; --"Interface/Icons/".. for when/if a gui gets setup it will be good to assign an icon
- NewProfile.Date = date("%c");
- NewProfile.Realm = GetRealmName();
- NewProfile.Char = UnitName("player");
- NewProfile.Class = UnitClass("player");
- NewProfile.Bars = Util.deepcopy(ButtonForgeSave.Bars)
- ButtonForgeGlobalProfiles[string.upper(ProfileName)] = NewProfile;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("SavedProfile"), .5, 1, 0, 1);
- end
- --[[
- -- Lazy, I should've factored this with the save profile function
- --]]
- function Util.UndoProfile()
- if (InCombatLockdown()) then
- Util.SlashShowMessageByLine(Util.GetLocaleString("ActionFailedCombatLockdown"));
- return;
- end
- if (ButtonForgeSave.UndoProfileBars == nil) then
- return;
- end
- for i = #Util.ActiveBars, 1, -1 do
- Util.DeallocateBar(Util.ActiveBars[i]);
- end
- ButtonForgeSave.Bars = Util.deepcopy(ButtonForgeSave.UndoProfileBars);
- for i = 1, #ButtonForgeSave.Bars do
- Util.NewBar(0, 0, ButtonForgeSave.Bars[i]);
- end
- Util.RefreshCompanions();
- Util.RefreshMacros();
- Util.RefreshEquipmentSets();
- Util.RefreshSpells();
- Util.RefreshGridStatus(true);
- Util.RefreshBarStrata(true);
- Util.RefreshBarGUIStatus();
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("UndoneProfile"), .5, 1, 0, 1);
- end
- function Util.DeleteProfile(ProfileName)
- ProfileName = string.upper(ProfileName);
- if (ButtonForgeGlobalProfiles[ProfileName]) then
- ButtonForgeGlobalProfiles[ProfileName] = nil;
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("DeletedProfile"), .5, 1, 0, 1);
- end
- -- Some day I may add comfirmations, at least perhaps for the /slash commands... perhaps also a session log?? But when?!
- end
- --[[
- Save Button Facade settings if present
- --]]
- function Util:ButtonFacadeCallback(SkinID, Gloss, Backdrop, Group, Button, Colors)
- -- If no group is specified, save the data as the root add-on skin.
- -- This will allow the ButtonFacade GUI to display it correctly.
- return; -- This may longer be necessary
- --[[if not Group then
- ButtonForgeSave["SkinID"] = SkinID;
- ButtonForgeSave["Gloss"] = Gloss;
- ButtonForgeSave["Backdrop"] = Backdrop;
- ButtonForgeSave["Colors"] = Colors;
- else
- --not presently implemented by Button Forge --
- ButtonForgeSave[Group]["SkinID"] = SkinID;
- ButtonForgeSave[Group]["Gloss"] = Gloss;
- ButtonForgeSave[Group]["Backdrop"] = Backdrop;
- ButtonForgeSave[Group]["Colors"] = Colors;
- end]]
- end
- --[[
- To allow auto-alignment to also consider the blizzard multibars, this function will create wrappers to go on these bars
- which will also be considered when dragging a Button Forge bar... Since this is possibly a compatibility point, it can be
- hard disabled by a const param, it will also disable in the presence of Bartender which I know it doesn't function properly with
- --]]
- function Util.CreateBlizzardBarWrappers()
- if (IsAddOnLoaded("Bartender4") or Const.DisableAutoAlignAgainstDefaultBars) then
- return;
- end
- Util.BlizBarWrappers[1] = CreateFrame("FRAME", nil, UIParent);
- Util.BlizBarWrappers[1]:SetPoint("TOPLEFT", MultiBarBottomLeftButton1, "TOPLEFT", -Const.I, Const.I + 1);
- Util.BlizBarWrappers[1]:SetPoint("BOTTOMRIGHT", MultiBarBottomLeftButton12, "BOTTOMRIGHT", Const.I, -Const.I + 1);
- Util.BlizBarWrappers[2] = CreateFrame("FRAME", nil, UIParent);
- Util.BlizBarWrappers[2]:SetPoint("TOPLEFT", MultiBarBottomRightButton1, "TOPLEFT", -Const.I, Const.I + 1);
- Util.BlizBarWrappers[2]:SetPoint("BOTTOMRIGHT", MultiBarBottomRightButton12, "BOTTOMRIGHT", Const.I, -Const.I + 1);
- Util.BlizBarWrappers[3] = CreateFrame("FRAME", nil, UIParent);
- Util.BlizBarWrappers[3]:SetPoint("TOPLEFT", MultiBarRightButton1, "TOPLEFT", -Const.I, Const.I + 1);
- Util.BlizBarWrappers[3]:SetPoint("BOTTOMRIGHT", MultiBarRightButton12, "BOTTOMRIGHT", Const.I, -Const.I + 1);
- Util.BlizBarWrappers[4] = CreateFrame("FRAME", nil, UIParent);
- Util.BlizBarWrappers[4]:SetPoint("TOPLEFT", MultiBarLeftButton1, "TOPLEFT", -Const.I, Const.I + 1);
- Util.BlizBarWrappers[4]:SetPoint("BOTTOMRIGHT", MultiBarLeftButton12, "BOTTOMRIGHT", Const.I, -Const.I + 1);
- end
- function Util.UpdateBlizzardEnabledBarsMap()
- Util.BlizEnabledBars = {GetActionBarToggles()};
- end
- --[[
- Button Allocation Functions
- --]]
- function Util.NewButton(Parent, ButtonSave, ButtonLocked, TooltipOn, MacroText, KeyBindText)
- if (InCombatLockdown()) then
- return;
- end
- local NewButton;
- if (#(Util.InactiveButtons) > 0) then
- NewButton = table.remove(Util.InactiveButtons);
- NewButton:Configure(Parent, ButtonSave, ButtonLocked, TooltipOn, MacroText, KeyBindText);
- else
- NewButton = Button.New(Parent, ButtonSave, ButtonLocked, TooltipOn, MacroText, KeyBindText);
- Util.ButtonWidgetMap[NewButton.Widget] = NewButton;
- end
- table.insert(Util.ActiveButtons, NewButton);
- Util.CallbackEvent("BUTTON_ALLOCATED", NewButton.Widget:GetName());
- return NewButton;
- end
- function Util.DeallocateButton(Value)
- if (InCombatLockdown()) then
- return;
- end
- Value:Deallocate();
- table.remove(Util.ActiveButtons, Util.FindInTable(Util.ActiveButtons, Value));
- table.insert(Util.InactiveButtons, Value);
- Util.CallbackEvent("BUTTON_DEALLOCATED", Value.Widget:GetName());
- end
- function Util.DetachButton(Value)
- if (InCombatLockdown()) then
- return;
- end
- Value:Detach();
- table.remove(Util.ActiveButtons, Util.FindInTable(Util.ActiveButtons, Value));
- table.insert(Util.InactiveButtons, Value);
- Util.CallbackEvent("BUTTON_DEALLOCATED", Value.Widget:GetName());
- end
- --[[
- Bar Allocation Functions
- --]]
- function Util.NewBarSave()
- local Save = {};
- Save["Left"] = 0;
- Save["Top"] = 0;
- Save["Scale"] = 1;
- Save["Order"] = #Util.ActiveBars;
- Save["Label"] = nil;
- Save["Rows"] = Const.DefaultRows;
- Save["Cols"] = Const.DefaultCols;
- Save["VDriver"] = nil;
- Save["HVehicle"] = true;
- Save["HSpec1"] = false;
- Save["HSpec2"] = false;
- Save["HSpec3"] = false;
- Save["HSpec4"] = false;
- Save["HBonusBar"] = true;
- Save["HPetBattle"] = true;
- Save["GridAlwaysOn"] = true;
- Save["ButtonsLocked"] = false;
- Save["TooltipsOn"] = true;
- Save["MacroText"] = true;
- Save["KeyBindText"] = true;
- Save["ButtonGap"] = 6;
- Save["Enabled"] = true;
- Save["BonusBar"] = false;
- Save["GUI"] = true;
- Save["Alpha"] = 1;
- Save["Buttons"] = {};
- return Save;
- end
- function Util.NewBar(Left, Top, BarSave)
- if (InCombatLockdown()) then
- return;
- end
- local NewBar;
- if (not BarSave) then
- BarSave = Util.NewBarSave();
- BarSave["Left"] = Left;
- BarSave["Top"] = Top;
- table.insert(ButtonForgeSave.Bars, BarSave);
- PlaySoundFile("Sound\\Interface\\Pickup\\Putdownsmallmetal.Wav");
- --PlaySoundFile("Sound\\Item\\Weapons\\Mace2h\\2hmacehitplate1a.Wav");
- end
- if (#(Util.InactiveBars) > 0) then
- NewBar = table.remove(Util.InactiveBars);
- NewBar:Configure(BarSave);
- else
- NewBar = Bar.New(BarSave);
- end
- table.insert(Util.ActiveBars, NewBar);
- if (NewBar.Cols * NewBar.Rows == 0) then
- --Failed to allocate buttons, get rid of the bar
- NewBar:Deallocate();
- return nil;
- else
- Util.RefreshTab(NewBar.ControlFrame:GetLeft(), NewBar.ControlFrame:GetTop());
- return NewBar;
- end
- end
- function Util.NewBonusBar(Left, Top)
- if (InCombatLockdown()) then
- return;
- end
- local BarSave = Util.NewBarSave();
- BarSave["BonusBar"] = true;
- BarSave["Left"] = Left;
- BarSave["Top"] = Top;
- BarSave["Rows"] = 1;
- BarSave["Cols"] = 13;
- BarSave["HBonusBar"] = false;
- BarSave["HVehicle"] = false;
- BarSave["VDriver"] = "[overridebar][vehicleui] show; hide";
- BarSave["ButtonsLocked"] = true;
- BarSave["GridAlwaysOn"] = false;
- table.insert(ButtonForgeSave.Bars, BarSave);
- PlaySoundFile("Sound\\Interface\\Pickup\\Putdownsmallmetal.Wav");
- return Util.NewBar(Left, Top, BarSave);
- end
- function Util.DeallocateBar(Value)
- if (InCombatLockdown()) then
- return;
- end
- Value:Deallocate(); --Note that deallocating a bar will call a function that changes the bars state (primarily it removes all buttons, and changes it's order... both of which change the save state data)
- table.remove(Util.ActiveBars, Util.FindInTable(Util.ActiveBars, Value));
- table.remove(ButtonForgeSave.Bars, Util.FindInTable(ButtonForgeSave.Bars, Value.BarSave));
- table.insert(Util.InactiveBars, Value);
- local Left, Top = Value.ControlFrame:GetLeft(), Value.ControlFrame:GetTop();
- Util.RefreshTab(Left, Top);
- end
- function Util.DetachBar(Value)
- if (InCombatLockdown()) then
- return;
- end
- Value:Detach();
- table.remove(Util.ActiveBars, Util.FindInTable(Util.ActiveBars, Value));
- table.insert(Util.InactiveBars, Value);
- local Left, Top = Value.ControlFrame:GetLeft(), Value.ControlFrame:GetTop();
- Util.RefreshTab(Left, Top);
- end
- function Util.GetButtonFrameName(Label)
- Label = Label or "";
- local Name = Const.BarNaming.."Bar_"..(Label or "");
- if (not _G[Name.."_ButtonFrame"] and Label ~= "") then
- return Name.."_ButtonFrame";
- end
- while true do
- if (not _G[Name..Const.BarSeq.."_ButtonFrame"]) then
- return Name..Const.BarSeq.."_ButtonFrame";
- end
- Const.BarSeq = Const.BarSeq + 1;
- end
- end
- --[[
- Bar Management Functions
- --]]
- function Util.ReorderBar(Bar, NewPosition)
- local CurrentPosition = Bar.BarSave["Order"];
- local Order;
- if (CurrentPosition > NewPosition) then
- for i = 1, #Util.ActiveBars do
- Order = Util.ActiveBars[i].BarSave["Order"];
- if (Order < CurrentPosition and Order >= NewPosition) then
- Util.ActiveBars[i]:SetOrder(Order + 1);
- end
- end
- elseif (CurrentPosition < NewPosition) then
- for i = 1, #Util.ActiveBars do
- Order = Util.ActiveBars[i].BarSave["Order"];
- if (Order > CurrentPosition and Order <= NewPosition) then
- Util.ActiveBars[i]:SetOrder(Order - 1);
- end
- end
- end
- Bar:SetOrder(NewPosition);
- end
- function Util.DockCoords(Left, Top, ExcludeBar)
- local CLeft, CTop, CDist, CBar = 0, 0, 100000000, nil; --This is an arbitrary number that will be big enough here
- local Dist, X, Y;
- local Bars = Util.ActiveBars;
- for i = 1, #Bars do
- X = Bars[i].ControlFrame:GetLeft();--BarSave["Left"];
- Y = Bars[i].ControlFrame:GetTop();--BarSave["Top"];
- Dist = ((Left - X) ^ 2)+ ((Top - Y) ^ 2);
- if (Dist < CDist and Bars[i] ~= ExcludeBar) then
- CLeft = X;
- CTop = Y;
- CDist = Dist;
- CBar = Bars[i];
- end
- end
- return CLeft, CTop, CDist, CBar;
- end
- function Util.FindClosestPoint(Coord, Points, Offsets, ExcludeBar)
- local MatchedBar, MatchedPoint, Shift, MatchedCoord = nil, 0, 0, 0;
- local Calc, CalcCoord, MinCalc = 0, 0, 10000000;
- local Bars = Util.ActiveBars;
- for i = 1, #Bars do
- if (Bars[i] ~= ExcludeBar) then
- for j = 1, #Points do
- CalcCoord = Bars[i].ControlFrame[Points[j]](Bars[i].ControlFrame) + Offsets[j]; --basically translates down to things like Bars[i]:GetLeft() + Offset[j]; if Points[j] is "GetLeft"
- Calc = CalcCoord - Coord;
- Calc = Calc * Calc;
- if (Calc < MinCalc - 0.1) then
- MinCalc = Calc;
- MatchedCoord = CalcCoord;
- Shift = CalcCoord - Coord;
- MatchedBar = Bars[i].ControlFrame;
- MatchedPoint = j;
- end
- end
- end
- end
- Bars = Util.BlizBarWrappers;
- local EnabledBars = Util.BlizEnabledBars;
- for i = 1, #Bars do
- if (EnabledBars[i]) then
- for j = 1, #Points do
- CalcCoord = Bars[i][Points[j]](Bars[i]);
- if (not CalcCoord) then
- Util.BlizEnabledBars[i] = false;
- break;
- else
- CalcCoord = CalcCoord + Offsets[j]; --basically translates down to things like Bars[i]:GetLeft() + Offset[j]; if Points[j] is "GetLeft"
- Calc = CalcCoord - Coord;
- Calc = Calc * Calc;
- if (Calc < MinCalc - 0.1) then
- MinCalc = Calc;
- MatchedCoord = CalcCoord;
- Shift = CalcCoord - Coord;
- MatchedBar = Bars[i];
- MatchedPoint = j;
- end
- end
- end
- end
- end
- return MatchedBar, MatchedPoint, MinCalc, Shift, MatchedCoord;
- end
- --[[ While the Configure overlay is shown make sure that all bars are visible (unless in combat), this function also cleansup when the overlay is hidden again --]]
- function Util.VDriverOverride()
- if (InCombatLockdown()) then
- return;
- end
- local Bars = Util.ActiveBars;
- if (ConfigureLayer:IsShown() or DestroyBarOverlay:IsShown()) then
- for i = 1, #Bars do
- Bars[i]:SetTempShowVD();
- end
- else
- for i = 1, #Bars do
- Bars[i]:ClearTempShowVD();
- end
- end
- end
- --[[ Since the Spellbook has an annoying tendancy to cover bars this function will raise (or relower) the buttons to so they can be clicked
- Note: It will do this for everything but items - since that could quickly get annoying when moving items around (there isn't really a perfect solution, so best to not go overboard)
- Also it doesn't do a combat lockdown check, it is expected that this has been done up the chain (the bars will auto drop to the low strata if combat begins!)
- --]]
- function Util.RefreshBarStrata(ForceUpdate)
- local LowStrata = Util.InCombat or DestroyBarOverlay:IsShown() or (GetCursorInfo() == "item" and not IsShiftKeyDown()) or not Util.CursorAction;
- if (LowStrata ~= Util.LowStrata or ForceUpdate) then
- Util.LowStrata = LowStrata;
- local Bars = Util.ActiveBars;
- if (LowStrata) then
- for i = 1, #Bars do
- Bars[i].ButtonFrame:SetFrameStrata("LOW");
- Bars[i]:SetOrder(); --without a param this will cause a refresh (just in case moving the strata causes the level to change)
- end
- else
- for i = 1, #Bars do
- Bars[i].ButtonFrame:SetFrameStrata("DIALOG");
- Bars[i]:SetOrder(); --without a param this will cause a refresh (just in case moving the strata causes the level to change)
- end
- end
- end
- end
- function Util.RefreshGridStatus(ForceUpdate)
- local Hide = Util.InCombat or not (Util.CursorAction or ConfigureLayer:IsShown() or DestroyBarOverlay:IsShown());
- if (Hide ~= Util.GridHidden or ForceUpdate) then
- Util.GridHidden = Hide;
- local Bars = Util.ActiveBars;
- if (Hide) then
- for i = 1, #Bars do
- if (not Bars[i].BarSave["GridAlwaysOn"]) then
- Bars[i]:GridHide();
- end
- end
- else
- for i = 1, #Bars do
- if (not Bars[i].BarSave["GridAlwaysOn"]) then
- Bars[i]:GridShow();
- end
- end
- end
- end
- end
- function Util.RefreshBarGUIStatus()
- local BarGUIForceOn = (not Util.InCombat) and (ConfigureLayer:IsShown() or DestroyBarOverlay:IsShown() or (IsShiftKeyDown() and Util.CursorAction));
- local Bars = Util.ActiveBars;
- if (BarGUIForceOn) then
- for i = 1, #Bars do
- Bars[i]:GUIOn();
- end
- else
- for i = 1, #Bars do
- if (not Bars[i].BarSave["GUI"]) then
- Bars[i]:GUIOff();
- end
- end
- end
- end
- function Util.SetControlFrameAlphas(Alpha)
- local Bars = Util.ActiveBars;
- for i = 1, #Bars do
- Bars[i].ControlFrame:SetAlpha(Alpha);
- end
- end
- function Util.RefreshTab(Left, Top)
- local Count = 0;
- local Bar;
- local StackedBar;
- local Label;
- for i = 1, #Util.ActiveBars do
- Bar = Util.ActiveBars[i];
- if (math.abs(Bar.ControlFrame:GetLeft() - Left) < 0.01 and math.abs(Bar.ControlFrame:GetTop() - Top) < 0.01) then
- Count = Count + 1;
- StackedBar = Bar;
- end
- end
- if (Count == 0) then
- return;
- end
- if (Count == 1) then
- --Set it's label back in and dealloc the tabframe
- StackedBar.Tabbed = false;
- Label = StackedBar.LabelFrame;
- Label:ClearAllPoints();
- Label:SetPoint("TOPLEFT", StackedBar.TopIconsFrame, "TOPLEFT", Const.BarInset, -Const.BarEdge); --Const.MiniIconSize + Const.MiniIconGap +Const.BarEdge, -Const.BarEdge);
- Label:SetBackdropColor(0, 0, 0, 1);
- Label:SetAlpha(1);
- Label:EnableMouse(false);
- Label:SetScript("OnMouseDown", nil);
- Label:SetScript("OnEnter", nil);
- Label:SetScript("OnLeave", nil);
- Util.DeallocateTab(Left, Top);
- StackedBar:ReflowUI();
- return;
- end
- local Offset = 0;
- local HighestBar;
- local TabFrame = Util.GetTabFrame(Left, Top);
- for i = 1, #Util.ActiveBars do
- Bar = Util.ActiveBars[i];
- if (math.abs(Bar.ControlFrame:GetLeft() - Left) < 0.01 and math.abs(Bar.ControlFrame:GetTop() - Top) < 0.01) then
- if (not HighestBar) then
- --anchor tabframe
- HighestBar = Bar;
- TabFrame:ClearAllPoints();
- TabFrame:SetPoint("TOPLEFT", Bar.ControlFrame, "TOPLEFT", 0, Const.MiniIconSize);
- elseif (HighestBar.BarSave["Order"] < Bar.BarSave["Order"]) then
- HighestBar = Bar;
- end
- Bar.Tabbed = true;
- Label = Bar.LabelFrame;
- Label:ClearAllPoints();
- Label:SetPoint("TOPLEFT", TabFrame, "TOPLEFT", Offset, 0);
- Label:SetBackdropColor(0, 0, 0, 1);
- Label:SetAlpha(.5);
- Label:EnableMouse(true);
- Label:SetScript("OnMouseDown", Bar.SendToFront);
- Label:SetScript("OnEnter", Bar.LabelOnEnter);
- Label:SetScript("OnLeave", Bar.LabelOnLeave);
- if (Label:GetWidth() > 4.5) then
- Offset = Offset + Label:GetWidth();
- end
- Bar:ReflowUI();
- end
- end
- TabFrame:SetSize(Offset, Const.MiniIconSize);
- Label = HighestBar.LabelFrame;
- Label:SetAlpha(1);
- --Label:SetScript("OnMouseDown", nil);
- Label:SetScript("OnEnter", nil);
- Label:SetScript("OnLeave", nil);
- end
- function Util.DeallocateTab(Left, Top)
- if (Util.ActiveTabs[Left.." "..Top]) then
- table.insert(Util.InactiveTabs, Util.ActiveTabs[Left.." "..Top]);
- Util.ActiveTabs[Left.." "..Top] = nil;
- end
- end
- function Util.GetTabFrame(Left, Top)
- if (not Util.ActiveTabs[Left.." "..Top]) then
- if (#Util.InactiveTabs > 0) then
- Util.ActiveTabs[Left.." "..Top] = table.remove(Util.InactiveTabs);
- else
- Util.ActiveTabs[Left.." "..Top] = CreateFrame("FRAME", nil, ConfigureLayer);
- Util.ActiveTabs[Left.." "..Top]:SetSize(1, 1);
- Util.ActiveTabs[Left.." "..Top]:SetClampedToScreen(true);
- end
- end
- return Util.ActiveTabs[Left.." "..Top];
- end
- function Util.BarHasButton(Bar, Command, Data, Subvalue)
- local BCommand, BData, BSubvalue
- for i = 1, #Bar.Buttons do
- BCommand, BData, BSubvalue = Bar.Buttons[i]:GetCursor();
- if (Command == BCommand and Data == BData and Subvalue == BSubvalue) then
- return true;
- end
- end
- return false;
- end
- --[[
- Helper functions
- --]]
- function Util.FindInTable(Table, Value, Start)
- for i = Start or 1, #Table do
- if (Table[i] == Value) then
- return i;
- end
- end
- return nil;
- end
- function Util.GetLocaleString(Value)
- return Locale[Value];
- end
- function Util.GetLocaleEnabledDisabled(Value)
- if (Value) then
- return Locale["Enabled"];
- else
- return Locale["Disabled"];
- end
- end
- function Util.CastBool(Value)
- return Locale.BoolTable[strlower(Value or '')];
- end
- function Util.ProcessSlashCommandParams(Command, Params)
- Params = Params or "";
- if (Const.SlashCommands[Command].params == "bool") then
- local Bool = Util.CastBool(Params, "^%s*(%w*)%s*$");
- if (Bool == nil) then
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("SlashParamsInvalid")..Command.." "..Params, .5, 1, 0, 1);
- return;
- end
- return {Bool};
- else
- local Values = {string.match(Params, Const.SlashCommands[Command].params)};
- if (Values[1] == nil) then
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("SlashParamsInvalid")..Command.." "..Params, .5, 1, 0, 1);
- return;
- end
- return Values;
- end
- end
- --[[Unused function for allowing a more... ]]--
- local SlashRemainingMessage = '';
- function Util.SlashShowRemainingMessage()
- local Display, Remainder = string.match(SlashRemainingMessage, "^("..strrep(".-\n", Const.SlashNumLines-1)..".-)\n(.-)$");
- if (Display) then
- SlashRemainingMessage = Remainder;
- else
- Display = SlashRemainingMessage;
- SlashRemainingMessage = '';
- end
- DEFAULT_CHAT_FRAME:AddMessage(' '..Display, .5, 1, 0, 1);
- end
- function Util.SlashShowMessageByLine(Message)
- for Line in string.gmatch(Message, '([^\n]*)') do
- DEFAULT_CHAT_FRAME:AddMessage(Line, .5, 1, 0, 1);
- end
- end
- function SlashCmdList.BUTTONFORGE(msg, editbox)
- local PreparedCommands = {};
- local Command, Params;
- local Count = 0;
- Params = '';
- for Token, Space in string.gmatch(msg, '([^%s]+)([%s]*)') do
- if (Const.SlashCommands[strlower(Token)]) then
- if (Command) then
- Count = Count + 1;
- --PreparedCommands["Count"] = Count;
- PreparedCommands[Command] = Util.ProcessSlashCommandParams(Command, Params);
- if (PreparedCommands[Command] == nil) then
- return;
- end
- end
- Command = strlower(Token);
- Params = '';
- elseif (string.match(Token, '^-') == '-') then
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("SlashCommandNotRecognised")..Token, .5, 1, 0, 1);
- return;
- else
- Params = Params..Token..Space;
- end
- end
- if (Command) then
- Count = Count + 1;
- --PreparedCommands["Count"] = Count;
- PreparedCommands[Command] = Util.ProcessSlashCommandParams(Command, Params);
- if (PreparedCommands[Command] == nil) then
- return;
- end
- local Bars = Util.ActiveBars;
- local Commands = PreparedCommands;
- -- Check the constraint rules
- -- 1. Only 1 group is allowed
- -- 2. A rules required's must be present
- -- 3. A rules exclusions must not be present
- local Group;
- local FirstCommand;
- for k, v in pairs(Commands) do
- FirstCommand = FirstCommand or k;
- if (Group ~= nil and Group ~= Const.SlashCommands[k].group) then
- -- must be the same group
- DEFAULT_CHAT_FRAME:AddMessage(string.gsub(string.gsub(Util.GetLocaleString("SlashCommandIncompatible"), "<COMMANDA>", FirstCommand), "<COMMANDB>", k), .5, 1, 0, 1);
- return;
- end
- Group = Const.SlashCommands[k].group;
- local Requires = Const.SlashCommands[k].requires;
- if (Requires) then
- for k1, v1 in pairs(Requires) do
- if (Commands[v1] == nil) then
- -- Missing a required command
- DEFAULT_CHAT_FRAME:AddMessage(string.gsub(string.gsub(Util.GetLocaleString("SlashCommandRequired"), "<COMMANDA>", k), "<COMMANDB>", v1), .5, 1, 0, 1);
- return;
- end
- end
- end
- local Incompat = Const.SlashCommands[k].incompat;
- if (Incompat) then
- for k1, v1 in pairs(Incompat) do
- if (Commands[v1]) then
- -- Incompatible command present
- DEFAULT_CHAT_FRAME:AddMessage(string.gsub(string.gsub(Util.GetLocaleString("SlashCommandIncompatible"), "<COMMANDA>", k), "<COMMANDB>", v1), .5, 1, 0, 1);
- return;
- end
- if (v1 == "ALL" and Count > 1) then
- -- Only 1 command would be allowed
- DEFAULT_CHAT_FRAME:AddMessage(string.gsub(Util.GetLocaleString("SlashCommandAlone"), "<COMMANDA>", k), .5, 1, 0, 1);
- return;
- end
- end
- end
- local Validate = Const.SlashCommands[k].validate;
- if (Validate) then
- if (not Validate(unpack(v))) then
- -- Validate function failed
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("SlashParamsInvalid")..k.." "..table.concat(v, " "), .5, 1, 0, 1);
- return;
- end
- end
- end
- if (Group == "bar") then
- if (Commands["-createbar"]) then
- Util.ApplySlashCommands(Commands);
- else
- local BarName;
- if (Commands["-bar"]) then
- BarName = Commands["-bar"][1];
- elseif (Commands["-destroybar"]) then
- BarName = Commands["-destroybar"][1];
- end
- for i = 1, #Bars do
- if ((not BarName) or strlower(BarName) == strlower(Bars[i].BarSave["Label"])) then
- Util.ApplySlashCommands(Commands, Bars[i]);
- end
- end
- end
- else
- Util.ApplySlashCommands(Commands);
- end
- else
- Util.SlashShowMessageByLine(Util.GetLocaleString("SlashHelpFormatted")); --]]
- end
- end
- function Util.ApplySlashCommands(Commands, Bar)
- if (Commands["-createbar"]) then
- Bar = Util.NewBar(0, 0);
- if (Bar == nil) then
- DEFAULT_CHAT_FRAME:AddMessage(Util.GetLocaleString("SlashCreateBarFailed"), .5, 1, 0, 1);
- return
- end
- Commands["-rename"] = Commands["-createbar"]; --this could arguably work by having an empty param to createbar but I think it will feel more natural to require a name with this command
- end
- if (Commands["-destroybar"]) then
- Util.DeallocateBar(Bar);
- end
- if (Commands["-macrotext"]) then
- Bar:SetMacroText(Commands["-macrotext"][1]);
- end
- if (Commands["-keybindtext"]) then
- Bar:SetKeyBindText(Commands["-keybindtext"][1]);
- end
- if (Commands["-tooltips"]) then
- Bar:SetTooltips(Commands["-tooltips"][1]);
- end
- if (Commands["-emptybuttons"]) then
- Bar:SetGridAlwaysOn(Commands["-emptybuttons"][1]);
- end
- if (Commands["-lockbuttons"]) then
- Bar:SetButtonsLocked(Commands["-lockbuttons"][1]);
- end
- if (Commands["-scale"]) then
- Bar:SetScale(tonumber(Commands["-scale"][1]));
- end
- if (Commands["-rows"]) then
- Bar:SetNumButtons(Bar.BarSave["Cols"], tonumber(Commands["-rows"][1]));
- end
- if (Commands["-cols"]) then
- Bar:SetNumButtons(tonumber(Commands["-cols"][1]), Bar.BarSave["Rows"]);
- end
- if (Commands["-coords"]) then
- Bar:SetPosition(tonumber(Commands["-coords"][1]), tonumber(Commands["-coords"][2]));
- end
- if (Commands["-rename"]) then
- Bar:SetLabel(Commands["-rename"][1]);
- end
- if (Commands["-hidespec1"]) then
- Bar:SetHSpec1(Commands["-hidespec1"][1]);
- end
- if (Commands["-hidespec2"]) then
- Bar:SetHSpec2(Commands["-hidespec2"][1]);
- end
- if (Commands["-hidespec3"]) then
- Bar:SetHSpec3(Commands["-hidespec3"][1]);
- end
- if (Commands["-hidespec4"]) then
- Bar:SetHSpec4(Commands["-hidespec4"][1]);
- end
- if (Commands["-hidevehicle"]) then
- Bar:SetHVehicle(Commands["-hidevehicle"][1]);
- end
- if (Commands["-hideoverridebar"]) then
- Bar:SetHBonusBar(Commands["-hideoverridebar"][1]);
- end
- if (Commands["-hidepetbattle"]) then
- Bar:SetHPetBattle(Commands["-hidepetbattle"][1]);
- end
- if (Commands["-vismacro"]) then
- Bar:SetVD(Commands["-vismacro"][1]);
- end
- if (Commands["-gui"]) then
- Bar:SetGUI(Commands["-gui"][1]);
- end
- if (Commands["-alpha"]) then
- Bar:SetAlpha(tonumber(Commands["-alpha"][1]));
- end
- if (Commands["-enabled"]) then
- Bar:SetEnabled(Commands["-enabled"][1]);
- end
- if (Commands["-gap"]) then
- Bar:SetButtonGap(tonumber(Commands["-gap"][1]));
- end
- if (Commands["-info"]) then
- --print out the bar info's
- local String = Util.GetLocaleString("InfoLabel")..": "..(Bar:GetLabel() or "").."\n"..
- Util.GetLocaleString("InfoRowsCols")..": "..select(3, Bar:GetNumButtons()).."\n"..
- Util.GetLocaleString("InfoScale")..": "..Bar:GetScale().."\n"..
- Util.GetLocaleString("InfoGap")..": "..Bar:GetButtonGap().."\n"..
- Util.GetLocaleString("InfoCoords")..": "..select(3, Bar:GetPosition()).."\n"..
- Util.GetLocaleString("InfoTooltips")..": "..select(2, Bar:GetTooltips()).."\n"..
- Util.GetLocaleString("InfoEmptyGrid")..": "..select(2, Bar:GetGridAlwaysOn()).."\n"..
- Util.GetLocaleString("InfoLock")..": "..select(2, Bar:GetButtonsLocked()).."\n"..
- Util.GetLocaleString("InfoMacroText")..": "..select(2, Bar:GetMacroText()).."\n"..
- Util.GetLocaleString("InfoKeybindText")..": "..select(2, Bar:GetKeyBindText()).."\n"..
- Util.GetLocaleString("InfoHSpec1")..": "..select(2, Bar:GetHSpec1()).."\n"..
- Util.GetLocaleString("InfoHSpec2")..": "..select(2, Bar:GetHSpec2()).."\n"..
- Util.GetLocaleString("InfoHSpec3")..": "..select(2, Bar:GetHSpec3()).."\n"..
- Util.GetLocaleString("InfoHSpec4")..": "..select(2, Bar:GetHSpec4()).."\n"..
- Util.GetLocaleString("InfoHVehicle")..": "..select(2, Bar:GetHVehicle()).."\n"..
- Util.GetLocaleString("InfoHBonusBar5")..": "..select(2, Bar:GetHBonusBar()).."\n"..
- Util.GetLocaleString("InfoHPetBattle")..": "..select(2, Bar:GetHPetBattle()).."\n"..
- Util.GetLocaleString("InfoVisibilityMacro")..": "..(Bar:GetVD() or "").."\n"..
- Util.GetLocaleString("InfoGUI")..": "..select(2, Bar:GetGUI()).."\n"..
- Util.GetLocaleString("InfoAlpha")..": "..Bar:GetAlpha().."\n"..
- Util.GetLocaleString("InfoEnabled")..": "..select(2, Bar:GetEnabled());
- Util.SlashShowMessageByLine(String);
- end
- if (Commands["-technicalinfo"]) then
- --print out technical info for the bar
- local String = Util.GetLocaleString("InfoButtonFrameName")..": "..Bar.ButtonFrame:GetName();
- Util.SlashShowMessageByLine(String);
- end
- if (Commands["-saveprofile"]) then
- Util.SaveProfile(Commands["-saveprofile"][1]);
- end
- if (Commands["-loadprofile"]) then
- Util.LoadProfile(Commands["-loadprofile"][1]);
- end
- if (Commands["-loadprofiletemplate"]) then
- Util.LoadProfileTemplate(Commands["-loadprofiletemplate"][1]);
- end
- if (Commands["-undoprofile"]) then
- Util.UndoProfile();
- end
- if (Commands["-listprofiles"]) then
- local String = Util.GetLocaleString("BFProfiles").."\n---------------------\n";
- for k,v in pairs(ButtonForgeGlobalProfiles) do
- String = String..v.Name.."\n";
- end
- String = String.."---------------------\n";
- Util.SlashShowMessageByLine(String);
- end
- if (Commands["-deleteprofile"]) then
- Util.DeleteProfile(Commands["-deleteprofile"][1]);
- end
- if (Commands["-macrocheckdelay"]) then
- ButtonForgeGlobalSettings["MacroCheckDelay"] = tonumber(Commands["-macrocheckdelay"][1]);
- end
- if (Commands["-removemissingmacros"]) then
- ButtonForgeGlobalSettings["RemoveMissingMacros"] = Commands["-removemissingmacros"][1];
- end
- if (Commands["-forceoffcastonkeydown"]) then
- ButtonForgeGlobalSettings["ForceOffCastOnKeyDown"] = Commands["-forceoffcastonkeydown"][1];
- end
- if (Commands["-usecollectionsfavoritemountbutton"]) then
- ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"] = Commands["-usecollectionsfavoritemountbutton"][1];
- end
- if (Commands["-globalsettings"]) then
- --print out what the global settings for Button Forge are
- local String = Util.GetLocaleString("InfoMacroCheckDelay")..": "..ButtonForgeGlobalSettings["MacroCheckDelay"].."\n"..
- Util.GetLocaleString("InfoRemoveMissingMacros")..": "..Util.GetLocaleEnabledDisabled(ButtonForgeGlobalSettings["RemoveMissingMacros"]).."\n"..
- Util.GetLocaleString("InfoForceOffCastOnKeyDown")..": "..Util.GetLocaleEnabledDisabled(ButtonForgeGlobalSettings["ForceOffCastOnKeyDown"]).."\n"..
- Util.GetLocaleString("InfoUseCollectionsFavoriteMountButton")..": "..Util.GetLocaleEnabledDisabled(ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"]);
- Util.SlashShowMessageByLine(String);
- end
- end
- --[[ Store cursor type info for later use --]]
- function Util.StoreCursor(Command, Data, Subvalue, Subsubvalue)
- Util.Command = Command;
- Util.Data = Data;
- Util.Subvalue = Subvalue;
- Util.Subsubvalue = Subsubvalue
- end
- function Util.GetStoredCursor()
- return Util.Command, Util.Data, Util.Subvalue, Util.Subsubvalue;
- end
- --[[ Set the cursor based on the triplet passed in --]]
- function Util.SetCursor(Command, Data, Subvalue, Subsubvalue)
- ClearCursor();
- UILib.StopDraggingIcon();
- SpellFlyout:Hide();
- if (Command == "spell") then
- --PickupSpellBookItem(Data, Subvalue);
- PickupSpell(Subsubvalue);
- elseif (Command == "item") then
- PickupItem(Data);
- elseif (Command == "macro") then
- PickupMacro(Data);
- elseif (Command == "mount") then
- --if (Subvalue == nil) then
- -- Data = Util.GetMountIndexFromUselessIndex(Data);
- --end
- C_MountJournal.Pickup(Util.GetMountIndexFromMountID(Data));
- elseif (Command == "equipmentset") then
- PickupEquipmentSetByName(Data);
- elseif (Command == "bonusaction") then
- local page = 12; --The page for vehicleactionbar
- if (HasOverrideActionBar()) then
- page = 14;
- end
- local Texture = GetActionTexture(Data + ((page - 1) * 12));
- if (Texture and (HasOverrideActionBar() or HasVehicleActionBar())) then
- UILib.StartDraggingIcon(Texture, 23, 23, "bonusaction", Data);
- else
- UILib.StartDraggingIcon(Const.ImagesDir.."Bonus"..Data, 23, 23, "bonusaction", Data);
- end
- elseif (Command == "flyout") then
- local ind, booktype = Util.LookupSpellIndex("FLYOUT"..Data);
- if (ind) then
- PickupSpellBookItem(ind, booktype);
- end
- elseif (Command == "customaction") then
- CustomAction.SetCursor(Data);
- elseif (Command == "battlepet") then
- C_PetJournal.PickupPet(Data);
- end
- end
- --[[ These two functions will take care of non secure gui updates when the player enters or exits combat ]]--
- function Util.PreCombatStateUpdate()
- Util.InCombat = true;
- Util.RefreshGridStatus();
- Util.RefreshBarStrata(); --Im surprised that these refreshes dont lead to taint, I must be forgetting something??!
- UILib.ToggleCreateBarMode(true);
- UILib.ToggleDestroyBarMode(true);
- Util.RefreshBarGUIStatus();
- end
- function Util.PostCombatStateUpdate()
- Util.InCombat = false;
- Util.VDriverOverride();
- Util.RefreshGridStatus();
- Util.RefreshBarStrata();
- Util.RefreshBarGUIStatus();
- if (Util.DelayedRefreshMacros) then
- Util.RefreshMacros();
- Util.DelayedRefreshMacros = nil;
- end
- if (Util.DelayedUpdateButtonClickHandling) then
- Util.UpdateButtonClickHandling();
- Util.DelayedUpdateButtonClickHandling = nil;
- end
- if (Util.DelayedPromoteSpells) then
- Util.PromoteSpells();
- Util.DelayedPromoteSpells = nil;
- end
- if (Util.DelayedRefreshCompanions) then
- Util.RefreshCompanions();
- Util.DelayedRefreshCompanions = nil;
- end
- if (Util.DelayedRefreshEquipmentSets) then
- Util.RefreshEquipmentSets();
- Util.DelayedRefreshEquipmentSets = nil;
- end
- end
- --[[ Add and remove buttons to a list that gets updated for the range timer --]]
- function Util.AddToRangeTimer(Value)
- if (#Util.RangeTimerButtons == 0) then
- --BF
- end
- Util.RangeTimerButtons[Value] = true;
- end
- function Util.RemoveFromRangeTimer(Value)
- Util.RangeTimerButtons[Value] = nil;
- end
- --[[ Add and remove buttons to a list that gets updated for flashing --]]
- function Util.AddToFlash(Value)
- if (#Util.FlashButtons == 0) then
- --BF
- end
- Util.FlashButtons[Value] = true;
- end
- function Util.RemoveFromFlash(Value)
- Util.FlashButtons[Value] = nil;
- end
- function Util.RightClickSelfCast(Value)
- if (InCombatLockdown()) then
- return;
- end
- if (Value) then
- for i = 1, #Util.ActiveButtons do
- Util.ActiveButtons[i].Widget:SetAttribute("unit2", "player");
- end
- else
- for i = 1, #Util.ActiveButtons do
- Util.ActiveButtons[i].Widget:SetAttribute("unit2", nil);
- end
- end
- ButtonForgeSave["RightClickSelfCast"] = Value;
- end
- --[[---------------------------------------
- Spell Functions
- -------------------------------------------]]
- function Util.GetFullSpellName(Name, Rank)
- if (Name) then
- return Name.."("..Rank..")";
- end
- end
- function Util.GetSpellId(NameRank)
- local Link = GetSpellLink(NameRank);
- return select(3, strfind(Link, "spell:(%d+)|"));
- end
- function Util.IsSpellIdTalent(SpellId)
- local TalentInfoFuncs = {GetTalentInfo, GetPvpTalentInfo};
- -- Scan both normal and PvP talents
- -- Note rather than assume number of talents, we just scan till the rows and columns till we hit a nil
- for _, TalentInfoFunc in ipairs(TalentInfoFuncs) do
- local r = 1;
- local c = 1;
- local TalentSpellID = select(6, TalentInfoFunc(r, c, 1));
- while (TalentSpellID) do
- while (TalentSpellID) do
- if (TalentSpellID == SpellId) then
- return true;
- end
- c = c + 1;
- TalentSpellID = select(6, TalentInfoFunc(r, c, 1));
- end
- r = r + 1;
- c = 1;
- TalentSpellID = select(6, TalentInfoFunc(r, c, 1));
- end
- end
- return false;
- end
- function Util.CacheSpellIndexes()
- local i = 1;
- local NewSI = {};
- local NewSM = {-10000000, 10000000};
- local ManaPoints = {};
- local ItemType, Id;
- Util.NewSpellIndex = {};
- local total = 0;
- for j = 1, GetNumSpellTabs() do
- total = total + select(4, GetSpellTabInfo(j));
- end
- for i = total, 1, -1 do
- ItemType, Id = GetSpellBookItemInfo(i, BOOKTYPE_SPELL);
- --local Name, Rank, Icon, PowerCost, IsFunnel, PowerType = GetSpellInfo(i, BOOKTYPE_SPELL);
- local Name, Rank, Icon, PowerCost, IsFunnel, PowerType = GetSpellInfo(Id);
- local NameRank = Util.GetFullSpellName(Name, Rank);
- if (ItemType == "SPELL") then
- NewSI[NameRank] = i;
- elseif (ItemType == "FLYOUT") then
- NewSI["FLYOUT"..Id] = i;
- elseif (ItemType == nil) then
- break;
- end
- -- if (not Util.SpellIndex[NameRank]) then
- -- Util.NewSpellIndex[NameRank] = i;
- --end
- if (PowerType == 0 and not ManaPoints[Power]) then
- ManaPoints[PowerCost] = true;
- table.insert(NewSM, PowerCost);
- end
- end
- -- local total = 0;
- --for j = 1, GetNumSpellTabs() do
- -- total = total + select(4, GetSpellTabInfo(j));
- --end
- --print("Calc total = "..total, "actual total = "..i);
- Util.SpellIndex = NewSI;
- table.sort(NewSM);
- Util.SpellMana = NewSM;
- end
- function Util.CachePetSpellIndexes()
- local i = 1;
- local NewPSI = {};
- --Util.NewPetSpellIndex = {};
- while true do
- local NameRank = Util.GetFullSpellName(GetSpellInfo(i, BOOKTYPE_PET));
- if (not NameRank) then
- break;
- end
- --if (not Util.PetSpellIndex[NameRank]) then
- -- Util.NewPetSpellIndex[NameRanl] = i;
- --end
- NewPSI[NameRank] = i;
- i = i + 1;
- end
- Util.PetSpellIndex = NewPSI;
- end
- function Util.LookupSpellIndex(NameRank)
- local Index = Util.SpellIndex[NameRank];
- if (Index) then
- return Index, BOOKTYPE_SPELL;
- end
- Index = Util.PetSpellIndex[NameRank];
- if (Index) then
- return Index, BOOKTYPE_PET;
- end
- end
- function Util.LookupNewSpellIndex(NameRank)
- local Index = Util.NewSpellIndex[NameRank];
- if (Index) then
- return Index, BOOKTYPE_SPELL;
- end
- Index = Util.NewPetSpellIndex[NameRank];
- if (Index) then
- return Index, BOOKTYPE_PET;
- end
- end
- --[[ Used when the players mana crosses a threshold to find the next thresholds to test against --]]
- function Util.FindNewThresholds(Mana, Index, SearchDown)
- local SpellMana = Util.SpellMana;
- if (SearchDown) then
- for i = Index-1, 1, -1 do
- if (SpellMana[i] <= Mana) then
- return SpellMana[i], SpellMana[i+1], i;
- end
- end
- else
- for i = Index+2, #SpellMana do
- if (SpellMana[i] > Mana) then
- return SpellMana[i-1], SpellMana[i], i-1;
- end
- end
- end
- end
- --[[ I will probably need to do the above for Rage/Energy and Runic Power, but for now will skip such tests --]]
- --[[ If a spell is learnt this will promote any usage of that spell to it's highest rank --]]
- function Util.PromoteSpells()
- if (InCombatLockdown()) then
- Util.DelayedPromoteSpells = true; --Since this relies on the NewSpell table this may not work too well? (ultimately this is minor and perhaps not worth the extra code paths to manage)
- return;
- end
- return;
- --for k, v in pairs(Util.ActiveButtons) do
- -- v:PromoteSpell();
- --end
- end
- function Util.RefreshSpells()
- --Unlike the others this can be done during combat (ironically)
- for k, v in pairs(Util.ActiveButtons) do
- v:RefreshSpell();
- end
- end
- function Util.RefreshBattlePets()
- for k, v in pairs(Util.ActiveButtons) do
- v:RefreshBattlePet();
- end
- end
- function Util.AddSpell(Value)
- if (not Util.FindInTable(Util.ActiveSpells, Value)) then
- table.insert(Util.ActiveSpells, Value);
- end
- end
- function Util.RemoveSpell(Value)
- local Index = Util.FindInTable(Util.ActiveSpells, Value);
- if (Index) then
- table.remove(Util.ActiveSpells, Index);
- end
- end
- --[[---------------------------------------
- Companion Functions
- -------------------------------------------]]
- function Util.CacheCompanions()
- --[[Util.Critters = {};
- for i = 1, GetNumCompanions("CRITTER") do
- local Id, Name = GetCompanionInfo("CRITTER", i);
- if (not Name) then
- return;
- end
- Util.Critters[Name] = i;
- end]]
- --[[Util.Mounts = {};
- for i = 1, C_MountJournal.GetNumMounts() do
- local Name, Id = C_MountJournal.GetDisplayedMountInfo(i);
- if (not Name) then
- return;
- end
- Util.Mounts[Name] = i;
- end]]
- Util.CompanionsCached = true;
- end
- function Util.LookupCompanion(Name)
- if (Util.Critters[Name]) then
- return "CRITTER", Util.Critters[Name];
- elseif (Util.Mounts[Name]) then
- return "MOUNT", Util.Mounts[Name];
- else
- return nil, nil;
- end
- end
- function Util.RefreshCompanions()
- if (InCombatLockdown()) then
- Util.DelayedRefreshCompanions = true;
- return;
- end
- for k, v in pairs(Util.ActiveButtons) do
- v:RefreshCompanion();
- end
- end
- --[[---------------------------------------
- Item Functions
- -------------------------------------------]]
- function Util.GetItemId(Name)
- --return select(3, strfind(Link, "item:(%d+)|"));
- return Util.InvItemNameId[Name] or Util.BagItemNameId[Name];
- end
- function Util.CacheBagItems()
- local BagItemNameIndexes = {};
- local BagItemIdIndexes = {};
- local BagItemNameId = {};
- local ItemId;
- local ItemName;
- for b = 4, 0, -1 do
- for s = GetContainerNumSlots(b), 1, -1 do
- ItemId = GetContainerItemID(b, s);
- ItemName = GetItemInfo(ItemId or "");
- if (ItemName ~= nil and ItemName ~= "") then
- BagItemNameIndexes[ItemName] = {b, s};
- BagItemIdIndexes[ItemId] = {b, s};
- BagItemNameId[ItemName] = ItemId;
- end
- end
- end
- Util.BagItemNameIndexes = BagItemNameIndexes;
- Util.BagItemIdIndexes = BagItemIdIndexes;
- Util.BagItemNameId = BagItemNameId;
- end
- function Util.CacheInvItems()
- local InvItemNameIndexes = {};
- local InvItemIdIndexes = {};
- local InvItemNameId = {};
- local ItemId;
- local ItemName;
- for s = 32, 0, -1 do
- ItemId = GetInventoryItemID("player", s);
- ItemName = GetItemInfo(ItemId or "");
- if (ItemName ~= nil and ItemName ~= "") then
- InvItemNameIndexes[ItemName] = s;
- InvItemIdIndexes[ItemId] = s;
- InvItemNameId[ItemName] = ItemId;
- end
- end
- Util.InvItemNameIndexes = InvItemNameIndexes;
- Util.InvItemIdIndexes = InvItemIdIndexes;
- Util.InvItemNameId = InvItemNameId;
- end
- --[[ Look for the item in players equipped slots --]]
- function Util.LookupItemNameEquippedSlot(ItemName)
- return Util.InvItemNameIndexes[ItemName];
- end
- function Util.LookupItemIdEquippedSlot(ItemId)
- return Util.InvItemIdIndexes[ItemId];
- end
- --[[ Look for the item in the players inventory --]]
- function Util.LookupItemNameBagSlot(ItemName)
- local Result = Util.BagItemNameIndexes[ItemName];
- if (Result) then
- return Result[1], Result[2];
- else
- return nil, nil;
- end
- end
- function Util.LookupItemIdBagSlot(ItemId)
- local Result = Util.BagItemIdIndexes[ItemId];
- if (Result) then
- return Result[1], Result[2];
- else
- return nil, nil;
- end
- end
- --[[ Look for the item in players equipped slots --]]
- function Util.LookupItemEquippedSlot(ItemId)
- for s = 0,23 do
- local Id = GetInventoryItemID("player", s);
- if (ItemId == Id) then
- return s;
- end
- end
- return nil;
- end
- --[[ Look for the item in the players inventory
- Notes: Don't use this function, the above functions are better
- Reason: In the simple case profiling shows that the performance hit is neglible from doing this scan...
- That is until GetItemInfo is used to get the name of the item
- all other things being equal that call increases my perf time from 0.04ms (approx 100 bag slots, with half used) to 0.44ms
- The above caching mechanism requires more work of the addon (not a good thing, complexity breeds issues) but it avoids the whole perf issue and doesn't even register (i.e. 0.00ms) --]]
- function Util.LookupItemInvSlot(ItemId)
- local Id;
- local Name = "";
- for b = 0, 4 do
- for s = 1, GetContainerNumSlots(b) do
- Id = GetContainerItemID(b, s);
- if (Id) then
- Name = GetItemInfo(Id);
- if (ItemId == Id) then
- return b, s;
- end
- end
- end
- end
- return nil, nil;
- end
- --[[ Look the item in the players bank (not sure if I need to make such a function so will leave this stub for now --]]
- function Util.LookupItemBankSlot(ItemName)
- return nil, nil;
- end
- function Util.AddItem(Value)
- if (not Util.FindInTable(Util.ActiveItems, Value)) then
- table.insert(Util.ActiveItems, Value);
- end
- end
- function Util.RemoveItem(Value)
- local Index = Util.FindInTable(Util.ActiveItems, Value);
- if (Index) then
- table.remove(Util.ActiveItems, Index);
- end
- end
- --[[---------------------------------------
- EquipmentSet Functions
- -------------------------------------------]]
- function Util.RefreshEquipmentSets()
- if (InCombatLockdown()) then
- Util.DelayedRefreshEquipmentSets = true;
- return;
- end
- for k, v in pairs(Util.ActiveButtons) do
- v:RefreshEquipmentSet();
- end
- end
- --[[---------------------------------------
- Bonus Action Functions
- -------------------------------------------]]
- function Util.AddBonusAction(Value)
- if (not Util.FindInTable(Util.ActiveBonusActions, Value)) then
- table.insert(Util.ActiveBonusActions, Value);
- end
- end
- function Util.RemoveBonusAction(Value)
- local Index = Util.FindInTable(Util.ActiveBonusActions, Value);
- if (Index) then
- table.remove(Util.ActiveBonusActions, Index);
- end
- end
- function Util.UpdateButtonClickHandling()
- if (InCombatLockdown() or not Util.Loaded) then
- Util.DelayedUpdateButtonClickHandling = true;
- return;
- end
- for i = 1, #Util.ActiveButtons do
- Util.ActiveButtons[i]:SetupActionButtonClick();
- end
- for i = 1, #Util.InactiveButtons do
- Util.InactiveButtons[i]:SetupActionButtonClick();
- end
- end
- --[[---------------------------------------
- Macro Functions
- -------------------------------------------]]
- function Util.Trim5(S)
- return strmatch(S or '', '^%s*(.*%S)') or '';
- end
- function Util.IncBetween(Val, Low, High)
- return Val >= Low and Val <= High;
- end
- function Util.RefreshMacros()
- if (InCombatLockdown() or not Util.Loaded) then
- Util.DelayedRefreshMacros = true;
- return;
- end
- if (Util.UpdateMacroEventCount < 2) then
- --Not all macros have been loaded yet so don't refresh
- return;
- end
- local AccMacros, CharMacros = GetNumMacros();
- if (not Util.MacroCount) then
- Util.MacroCount = AccMacros + CharMacros;
- elseif (Util.MacroCount > AccMacros + CharMacros) then
- Util.MacroDeleted = true;
- end
- for i = 1, #Util.ActiveButtons do
- Util.ActiveButtons[i]:RefreshMacro();
- end
- Util.MacroDeleted = false;
- Util.MacroCount = AccMacros + CharMacros;
- end
- function Util.AddMacro(Value)
- if (not Util.FindInTable(Util.ActiveMacros, Value)) then
- table.insert(Util.ActiveMacros, Value);
- end
- Util.RefreshOnUpdateFunction();
- end
- function Util.RemoveMacro(Value)
- local Index = Util.FindInTable(Util.ActiveMacros, Value);
- if (Index) then
- table.remove(Util.ActiveMacros, Index);
- Util.RefreshOnUpdateFunction();
- end
- end
- --[[ Monitor the macro check delay --]]
- function Util.StartMacroCheckDelay()
- Delay:SetScript("OnUpdate", Delay.OnUpdate);
- end
- function Util.StopMacroCheckDelay()
- Delay:SetScript("OnUpdate", nil);
- Util.MacroCheckDelayComplete = true;
- Util.RefreshMacros();
- end
- --[[
- The following creates an OnUpdate function designed to scan for macro conditionals that can't
- adequately be covered by events alone - it will only perform processing for conditionals that actually
- exist in allocated macros
- --]]
- function Util.RefreshOnUpdateFunction()
- if (not Util.Loaded) then
- return;
- end
- local ConcatMacros = "";
- local FunctionString =
- [[return function (self, Elapsed)
- ]];
- for i = 1, #(Util.ActiveMacros) do
- if (Util.ActiveMacros[i].Mode == "macro") then
- ConcatMacros = ConcatMacros..":"..(GetMacroBody(Util.ActiveMacros[i].MacroIndex) or "");
- end
- end
- ConcatMacros = strupper(ConcatMacros);
- --The following tests should be performed the buttons are updated
- if (strfind(ConcatMacros, "FLYING", 1, true)) then FunctionString = FunctionString..Util.SnippetIsFlying(); end
- if (strfind(ConcatMacros, "MOUNTED", 1, true)) then FunctionString = FunctionString..Util.SnippetIsMounted(); end
- FunctionString = FunctionString..Util.SnippetRefreshButtons();
- --The following tests need to be performed after the buttons are updated (so that the buttons can be updated at the next onupdate)
- if (strfind(ConcatMacros, "FLYABLE", 1, true)) then FunctionString = FunctionString..Util.SnippetIsFlyable(); end
- if (strfind(ConcatMacros, "MOUSEOVER", 1, true)) then FunctionString = FunctionString..Util.SnippetMouseOver(); end
- FunctionString = FunctionString.."end";
- local Func = assert(loadstring(FunctionString, "ButtonForgeOnUpdate"));
- Util.OnUpdate = Func();
- EventFull:SetScript("OnUpdate", Util.OnUpdate);
- end
- function Util.SnippetRefreshButtons()
- return
- [[if (self.RefreshButtons) then
- local ActiveButtons = self.Util.ActiveButtons;
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateTexture(); --make sure the texture is always upto date (most actions wont need to do anything here, really this is just for spellwisp)
- end
- if (self.RefChecked) then
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateChecked();
- end
- end
- if (self.RefEquipped) then
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateEquipped();
- end
- end
- if (self.RefUsable) then
- --print("Usable");
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateUsable();
- end
- end
- if (self.RefCooldown) then
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateCooldown();
- end
- end
- if (self.RefText) then
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateTextCount();
- end
- end
- if (self.RefFlyouts) then
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateFlyout();
- end
- end
- if (self.RefGlow) then
- for i = 1, #ActiveButtons do
- ActiveButtons[i]:UpdateGlow();
- end
- end
- if (self.RefConditional) then
- local ActiveMacros = self.Util.ActiveMacros;
- for i = 1, #ActiveMacros do
- ActiveMacros[i]:TranslateMacro();
- end
- end
- self.RefreshButtons = false;
- self.RefFull = false;
- self.RefChecked = false;
- self.RefEquipped = false;
- self.RefUsable = false;
- self.RefCooldown = false;
- self.RefText = false;
- self.RefFlyouts = false;
- self.RefGlow = false;
- self.RefConditional = false;
- end
- ]];
- end
- function Util.SnippetMouseOver()
- return
- [[if (UnitName("mouseover") ~= self.MOUnit or UnitIsDead("mouseover") ~= self.MOUnitDead) then
- self.MOUnit = UnitName("mouseover");
- self.MOUnitDead = UnitIsDead("mouseover");
- self.RefreshButtons = true;
- self.RefConditional = true;
- end
- ]];
- end
- function Util.SnippetIsFlying()
- return
- [[if (IsFlying() ~= self.IsFlying) then
- self.IsFlying = IsFlying();
- self.RefreshButtons = true;
- self.RefConditional = true;
- end
- ]];
- end
- function Util.SnippetIsMounted()
- return
- [[if (IsMounted() ~= self.IsMounted) then
- self.IsMounted = IsMounted();
- self.RefreshButtons = true;
- self.RefConditional = true;
- end
- ]];
- end
- function Util.SnippetIsFlyable()
- return
- [[if (IsFlyableArea() ~= self.IsFlyableArea) then
- self.IsFlyableArea = IsFlyableArea();
- self.RefreshButtons = true;
- self.RefConditional = true;
- end
- ]];
- end
- --[[
- API1 Support Functions
- --]]
- function Util.RegisterCallback(Callback, Arg)
- table.insert(Util.CallbackFunctions, Callback);
- table.insert(Util.CallbackArgs, Arg);
- end
- function Util.UnregisterCallback(Callback, Arg)
- for i = #Util.CallbackFunctions, 1, -1 do
- if (Util.CallbackFunctions[i] == Callback and Util.CallbackArgs[i] == Arg) then
- table.remove(Util.CallbackFunctions, i);
- table.remove(Util.CallbackArgs, i);
- end
- end
- end
- local CallbackFunc;
- local CallbackArg;
- local CallbackEvent;
- local CallbackEventArgs;
- function Util.CallbackWrapper()
- CallbackFunc(CallbackArg, CallbackEvent, unpack(CallbackEventArgs));
- end
- function Util.CallbackEvent(Event, ...)
- CallbackEvent = Event;
- CallbackEventArgs = {...};
- --local Args = {...};
- for i = 1, #Util.CallbackFunctions do
- CallbackFunc = Util.CallbackFunctions[i];
- CallbackArg = Util.CallbackArgs[i];
- xpcall(Util.CallbackWrapper, geterrorhandler());
- --xpcall(function () Util.CallbackFunctions[i](Util.CallbackArgs[i], Event, unpack(Args)); end, geterrorhandler()); --The other way provides a little more context if an error occurs
- end
- end
- --This one breaks with the philosophy of the Button implementation but for now should be sufficient to support the API function
- function Util.GetButtonActionInfo(ButtonName)
- local Button = Util.ButtonWidgetMap[_G[ButtonName]];
- if (not Button) then
- return;
- end
- if (Button.Mode == "spell") then
- return "spell", Button.SpellId, Button.SpellBook;
- elseif (Button.Mode == "item") then
- return "item", Button.ItemId;
- elseif (Button.Mode == "macro") then
- return "macro", Button.MacroIndex;
- elseif (Button.Mode == "companion") then
- local spellid = select(3, GetCompanionInfo(Button.CompanionType, Button.CompanionIndex));
- return "companion", spellid, Button.CompanionType;
- elseif (Button.Mode == "equipmentset") then
- return "equipmentset", Button.EquipmentSetName;
- elseif (Button.Mode == "flyout") then
- return "flyout", Button.FlyoutId;
- elseif (Button.Mode == "battlepet") then
- return "battlepet", Button.BattlePetId;
- end
- end
- --This one breaks with the philosophy of the Button implementation but for now should be sufficient to support the API function
- function Util.GetButtonActionInfo2(ButtonName)
- local Button = Util.ButtonWidgetMap[_G[ButtonName]];
- if (not Button) then
- return;
- end
- --[[
- "spell", SpellName, SpellSubName, SpellId, SpellIndex, SpellBook
- "item", ItemId, ItemName
- "macro", MacroIndex
- "companion", CompanionType, CompanionIndex
- "equipmentset", Name
- "flyout", FlyoutId
- "bonusaction", BonusActionSlot
- "customaction", CustomActionName
- --]]
- if (Button.Mode == "spell") then
- local Rank = select(2, GetSpellInfo(Button.SpellId));
- return "spell", Button.SpellName, Rank, Button.SpellId, Util.LookupSpellIndex(Button.SpellNameRank), Button.SpellBook;
- elseif (Button.Mode == "item") then
- return "item", Button.ItemId, Button.ItemName;
- elseif (Button.Mode == "macro") then
- return "macro", Button.MacroIndex;
- elseif (Button.Mode == "companion") then
- return "companion", Button.CompanionType, Button.CompanionIndex;
- elseif (Button.Mode == "equipmentset") then
- return "equipmentset", Button.EquipmentSetName;
- elseif (Button.Mode == "flyout") then
- return "flyout", Button.FlyoutId;
- elseif (Button.Mode == "bonusaction") then
- return "bonusaction", Button.BonusActionSlot;
- elseif (Button.Mode == "customaction") then
- return "customaction", Button.CustomActionName;
- elseif (Button.Mode == "battlepet") then
- return "battlepet", Button.BattlePetId;
- end
- end
- --[[------------------------------------------------
- Get Correct Mount Index
- The Hack:
- hooksecurefunc
- C_MountJournal.Pickup
- GameTooltip:SetAction
- Both these functions offer a moment when both
- the UselessIndex and the actual Index or SpellID
- for a mount is available... Also in theory
- one of these will have to fire before the player
- can actually put a mount on the cursor - so we
- simply patch work build a map of these
- Useless Index to useful index mappings.
- It does rely on the useless index not changing during
- a session - i suspect it wont, but it might when a new
- mount is learned, something that is hard to test on my
- account these days
- --------------------------------------------------]]
- --[[ should no longer be needed
- function Util.HookSecureFunc_C_MountJournal_Pickup(Index)
- local UselessIndex = select(2, GetCursorInfo());
- if (Index and UselessIndex) then
- Util.MountUselessIndexToIndex[select(2, GetCursorInfo())] = Index;
- end
- end
- hooksecurefunc(C_MountJournal, "Pickup", Util.HookSecureFunc_C_MountJournal_Pickup);
- function Util.HookSecureFunc_GameTooltip_SetAction(_, Slot)
- if (Slot == nil or Slot < 1 or Slot > 1000) then
- return;
- end
- local Command, UselessIndex = GetActionInfo(Slot);
- if (Command == "summonmount") then
- if (Util.MountUselessIndexToIndex[UselessIndex] == nil) then
- Util.MountUselessIndexToIndex[UselessIndex] = Util.GetMountIndexFromSpellID(select(3, GameTooltip:GetSpell()));
- end
- end
- end
- hooksecurefunc(GameTooltip, "SetAction", Util.HookSecureFunc_GameTooltip_SetAction);
- function Util.GetMountIndexFromUselessIndex(Index)
- return Util.MountUselessIndexToIndex[Index];
- end
- ]]
- --[[------------------------------------------------
- GetCorrectMountIndex
- --------------------------------------------------]]
- --[[
- function Util.GetMountIndexFromSpellID(SpellID)
- local Num = C_MountJournal.GetNumMounts();
- if (SpellID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL) then
- return 0; -- This is summon favorite
- end
- for i = 1, Num do
- if (select(2, C_MountJournal.GetDisplayedMountInfo(i)) == SpellID) then
- return i;
- end
- end
- return nil;
- end
- ]]
- --[[------------------------------------------------
- --------------------------------------------------]]
- function Util.GetMountIDFromName(Name)
- local Num = C_MountJournal.GetNumMounts();
- for i = 1, Num do
- if (C_MountJournal.GetDisplayedMountInfo(i) == Name) then
- return select(12, C_MountJournal.GetDisplayedMountInfo(i));
- end
- end
- return nil;
- end
- function Util.GetMountIndexFromMountID(MountID)
- local Num = C_MountJournal.GetNumMounts();
- if (MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID) then
- return 0;
- end
- for i = 1, Num do
- if (select(12, C_MountJournal.GetDisplayedMountInfo(i)) == MountID) then
- return i;
- end
- end
- end
- function Util.UpdateButtonsCooldownSwipeBling()
- local ActiveButtons = Util.ActiveButtons;
- for i = 1, #ActiveButtons do
- local Alpha = ActiveButtons[i].WCooldown:GetEffectiveAlpha();
- ActiveButtons[i].WCooldown:SetDrawBling(Alpha == 1);
- ActiveButtons[i].WCooldown:SetSwipeColor(0,0,0,Alpha);
- end
- end
- --[[
- Copied from Bliz implementation
- The difference is I use the effective alpha to override the bling and edge settings, and also adjust the swipe alpha
- I suspect this will need fine tuning for Masque and perhaps OmniCC, but that can be down the track
- ]]
- function Util.CooldownFrame_SetTimer(self, start, duration, enable, charges, maxCharges, forceShowDrawEdge)
- if(enable) then
- if (enable ~= 0) then
- local drawEdge = false;
- if ( duration > 2 and charges and maxCharges and charges ~= 0) then
- drawEdge = true;
- end
- local Alpha = self:GetEffectiveAlpha();
- self:SetSwipeColor(0, 0, 0, Alpha); -- eventually I may need to make this obey the current color!!!
- if (Alpha > 0.4) then
- self:SetDrawEdge(drawEdge or forceShowDrawEdge);
- self:SetDrawBling(true);
- else
- self:SetDrawEdge(false);
- self:SetDrawBling(false);
- end
- self:SetDrawSwipe(not drawEdge);
- self:SetCooldown(start, duration);
- else
- self:SetCooldown(0, 0);
- end
- end
- end
- function Util.LookupEquipmentSetIndex(EquipmentSetID)
- local Total = GetNumEquipmentSets();
- for i = 1, Total do
- if (select(3, GetEquipmentSetInfo(i)) == EquipmentSetID) then
- return i;
- end
- end
- return nil;
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement