I came across a bug that has annoyed me for a few days and I can't quite pin-point the problem.
When trying to access the Forge of Bonds in Ardenweald, I get the following error below.
When I disable my addon "GarrisonJukeBox", the error goes away.
Any hint to help me look in the right direction would be greatly appreciated.
Oh, and my addon works without issues.
Question : I was wondering if there was a buttongroup type of frame and if all buttons must have such a parent?
Thank you.
From Bugsack :
1x SharedXML\ButtonGroup.lua:55: attempt to call a table value
[string "@SharedXML\ButtonGroup.lua"]:55: in function `RemoveAllButtons'
[string "@SharedXML\ButtonGroup.lua"]:65: in function `Reset'
[string "@Blizzard_Soulbinds\Blizzard_SoulbindsSelectGroup.lua"]:52: in function `Init'
[string "@Blizzard_Soulbinds\Blizzard_SoulbindsViewer.lua"]:217: in function `Init'
[string "@Blizzard_Soulbinds\Blizzard_SoulbindsViewer.lua"]:200: in function `OpenSoulbind'
[string "@Blizzard_Soulbinds\Blizzard_SoulbindsViewer.lua"]:194: in function `Open'
[string "@Blizzard_Soulbinds\Blizzard_Soulbinds.lua"]:3: in function `?'
[string "@FrameXML\UIParent.lua"]:2235: in function <FrameXML\UIParent.lua:1269>
Locals:
self = <table> {
GetButtons = <function> defined @SharedXML\ButtonGroup.lua:60
GetSelectedButtons = <function> defined @SharedXML\ButtonGroup.lua:119
RemoveAllButtons = <function> defined @SharedXML\ButtonGroup.lua:54
AddInternal = <function> defined @SharedXML\ButtonGroup.lua:169
GenerateCallbackEvents = <function> defined @SharedXML\CallbackRegistry.lua:92
TriggerEvent = <function> defined @SharedXML\CallbackRegistry.lua:36
Select = <function> defined @SharedXML\ButtonGroup.lua:93
RegisterCallback = <function> defined @SharedXML\CallbackRegistry.lua:19
SetUndefinedEventsAllowed = <function> defined @SharedXML\CallbackRegistry.lua:15
UnregisterCallback = <function> defined @SharedXML\CallbackRegistry.lua:60
UnregisterAllCallbacksByEvent = <function> defined @SharedXML\CallbackRegistry.lua:76
Unselect = <function> defined @SharedXML\ButtonGroup.lua:89
UnregisterEvents = <function> defined @SharedXML\CallbackRegistry.lua:81
SelectAtIndex = <function> defined @SharedXML\ButtonGroup.lua:105
buttons = <table> {
}
CanChangeSelection = <function> defined @SharedXML\ButtonGroup.lua:152
funcRegistry = <table> {
}
closureRegistry = <table> {
}
GetAtIndex = <function> defined @SharedXML\ButtonGroup.lua:131
RemoveInternal = <function> defined @SharedXML\ButtonGroup.lua:174
RemoveButtons = <function> defined @SharedXML\ButtonGroup.lua:34
Init = <function> defined @SharedXML\ButtonGroup.lua:10
Event = <table> {
}
RemoveButton = <function> defined @SharedXML\ButtonGroup.lua:30
AddButtons = <function> defined @SharedXML\ButtonGroup.lua:19
GetButtonsByPredicate = <function> defined @SharedXML\ButtonGroup.lua:79
FindButtonByPredicate = <function> defined @SharedXML\ButtonGroup.lua:70
UnselectAtIndex = <function> defined @SharedXML\ButtonGroup.lua:112
SetButtons = <function> defined @SharedXML\ButtonGroup.lua:49
AddButton = <function> defined @SharedXML\ButtonGroup.lua:15
OnLoad = <function> defined @SharedXML\CallbackRegistry.lua:3
OnSelectionChange = <function> defined @SharedXML\ButtonGroup.lua:156
GetButtonIndex = <function> defined @SharedXML\ButtonGroup.lua:127
Reset = <function> defined @SharedXML\ButtonGroup.lua:64
}
(for generator) = <table> {
}
(for state) = nil
(for control) = nil
(*temporary) = <table> {
}
(*temporary) = nil
(*temporary) = nil
(*temporary) = "attempt to call a table value"
From ButtonGroup.lua
function ButtonGroupBaseMixin:RemoveAllButtons()
for index, button in ripairs(self.buttons) do <--- line 55
self:RemoveInternal(button);
end
end
I would like to know if frame creation below is ok with mixin (from my addon)?
GJB.mplayer.fbg = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate")
Found this :
ButtonGroupBaseMixin = CreateFromMixins(CallbackRegistryMixin);
ButtonGroupBaseMixin:GenerateCallbackEvents(
{
"Selected",
"Unselected",
}
);
function ButtonGroupBaseMixin:Init()
CallbackRegistryMixin.OnLoad(self);
self.buttons = {};
end
function ButtonGroupBaseMixin:AddButton(button)
self:AddInternal(button);
end
function ButtonGroupBaseMixin:AddButtons(buttons)
for buttonIndex, button in ipairs(buttons) do
self:AddInternal(button);
end
end
function ButtonGroupBaseMixin:AddInternal(button, func, owner)
table.insert(self.buttons, button);
button:RegisterSelectionChangedCallback(func, owner);
end
function ButtonGroupBaseMixin:RemoveButton(button)
self:RemoveInternal(button);
end
function ButtonGroupBaseMixin:RemoveButtons(buttons)
if buttons == self.buttons then
self:RemoveAllButtons();
else
for buttonIndex, button in ipairs(buttons) do
self:RemoveInternal(button);
end
end
end
function ButtonGroupBaseMixin:RemoveInternal(button)
tDeleteItem(self.buttons, button);
button:UnregisterSelectionChangedCallback(self);
end
function ButtonGroupBaseMixin:SetButtons(buttons)
self:RemoveAllButtons();
self:AddButtons(buttons);
end
function ButtonGroupBaseMixin:RemoveAllButtons()
for index, button in ripairs(self.buttons) do
self:RemoveInternal(button);
end
end
function ButtonGroupBaseMixin:GetButtons()
return self.buttons;
end
function ButtonGroupBaseMixin:Reset()
self:RemoveAllButtons();
self:UnregisterEvents();
self.callbacks = {};
end
function ButtonGroupBaseMixin:FindButtonByPredicate(pred)
for buttonIndex, button in ipairs(self.buttons) do
if pred(button) then
return button;
end
end
return nil;
end
function ButtonGroupBaseMixin:GetButtonsByPredicate(pred)
local buttons = {};
for buttonIndex, button in ipairs(self.buttons) do
if pred(button) then
table.insert(buttons, button);
end
end
return buttons;
end
function ButtonGroupBaseMixin:Unselect(button)
self:UnselectAtIndex(self:GetButtonIndex(button));
end
function ButtonGroupBaseMixin:Select(button, isInitializing)
self:SelectAtIndex(self:GetButtonIndex(button), isInitializing);
end
function ButtonGroupBaseMixin:UnselectAtIndex(index)
local button = self:GetAtIndex(index);
if button then
local isInitializing = false;
button:SetSelected(false, isInitializing);
end
end
function ButtonGroupBaseMixin:SelectAtIndex(index, isInitializing)
local button = self:GetAtIndex(index);
if button then
button:SetSelected(true, isInitializing);
end
end
function ButtonGroupBaseMixin:UnselectAtIndex(index)
local button = self:GetAtIndex(index);
if button then
button:SetSelected(false);
end
end
function ButtonGroupBaseMixin:GetSelectedButtons()
return self:GetButtonsByPredicate(
function(button)
return button:IsSelected();
end
);
end
function ButtonGroupBaseMixin:GetButtonIndex(button)
return tIndexOf(self.buttons, button);
end
function ButtonGroupBaseMixin:GetAtIndex(index)
return self.buttons[index];
end
ButtonGroupMixin = CreateFromMixins(ButtonGroupBaseMixin);
function ButtonGroupMixin:OnSelectionChange(button, newSelected)
local event = newSelected and ButtonGroupBaseMixin.Event.Selected or ButtonGroupBaseMixin.Event.Unselected;
self:TriggerEvent(event, button, self:GetButtonIndex(button));
end
function ButtonGroupMixin:AddInternal(button)
ButtonGroupBaseMixin.AddInternal(self, button, self.OnSelectionChange, self);
end
function CreateButtonGroup()
return CreateAndInitFromMixin(ButtonGroupMixin);
end
RadioButtonGroupMixin = CreateFromMixins(ButtonGroupBaseMixin);
function RadioButtonGroupMixin:CanChangeSelection(button, newSelected)
return not (not newSelected and #self:GetSelectedButtons() == 1);
end
function RadioButtonGroupMixin:OnSelectionChange(button, newSelected)
if newSelected then
for selectedButtonIndex, selectedButton in ipairs(self:GetSelectedButtons()) do
if selectedButton ~= button then
selectedButton:SetSelected(false);
self:TriggerEvent(ButtonGroupBaseMixin.Event.Unselected, selectedButton, self:GetButtonIndex(selectedButton));
end
end
self:TriggerEvent(ButtonGroupBaseMixin.Event.Selected, button, self:GetButtonIndex(button));
end
end
function RadioButtonGroupMixin:AddInternal(button)
button:SetSelectionChangeInterrupt(GenerateClosure(self.CanChangeSelection, self));
ButtonGroupBaseMixin.AddInternal(self, button, self.OnSelectionChange, self);
end
function RadioButtonGroupMixin:RemoveInternal(button)
button:SetSelectionChangeInterrupt(nil);
ButtonGroupBaseMixin.RemoveInternal(self, button);
end
function CreateRadioButtonGroup()
return CreateAndInitFromMixin(RadioButtonGroupMixin);
end
The following frame creation child is the culprit:
Now I can drag but no more history items appear in the list...
-------------------------------------
-- History Scroll
-------------------------------------
-- Create the parent frame that will contain the inner scroll child,
-- song history items, and the scroll bar slider.
--GJB.mplayer.fp = FPreviewFrame or CreateFrame("ScrollFrame", "FPreviewFrame", fbg)
GJB.mplayer.fp = CreateFrame("ScrollFrame", "FPreviewFrame", fbg)
local fp = GJB.mplayer.fp
fp:SetPoint("TOPLEFT", fbg, "BOTTOMLEFT", 0, 0)
fp:SetBackdrop(
{
-- bgFile = "Interface/Tooltips/UI-Tooltip-Background",
bgFile = "Interface/FrameGeneral/UI-Background-Rock",
edgeFile = "",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 0, right = 0, top = 0, bottom = 0 }
})
fp:SetBackdropColor(0, 0, 0, 1)
fp:SetWidth(400)
fp:SetHeight(150)
-- This is a bare-bones frame is used to encapsulate the contents of
-- the scroll frame. Each scrollframe can have one scroll child.
--GJB.mplayer.fpsc = FPreviewSC or CreateFrame("Frame", "FPreviewSC")
GJB.mplayer.fpsc = CreateFrame("Frame", "FPreviewSC")
local fpsc = GJB.mplayer.fpsc
-- Create the slider that will be used to scroll through the results
--GJB.mplayer.fpsb = FPreviewScrollBar or CreateFrame("Slider", "FPreviewScrollBar", fp)
GJB.mplayer.fpsb = CreateFrame("Slider", "FPreviewScrollBar", fp)
local fpsb = GJB.mplayer.fpsb
-- Set up internal textures for the scrollbar, background and thumb texture
fpsb.bg = fpsb:CreateTexture(nil, "BACKGROUND")
fpsb.bg:SetAllPoints(true)
fpsb.bg:SetTexture("Interface\\FrameGeneral\\UI-Background-Rock")
fpsb.thumb = fpsb:CreateTexture(nil, "OVERLAY")
fpsb.thumb:SetTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
fpsb.thumb:SetSize(25, 25)
fpsb:SetThumbTexture(fpsb.thumb)
...
...
...
function GJB:CreateHistoryButtonFrames()
local pool = GJB.historypool
local fp = GJB.mplayer.fp
local fpsb = GJB.mplayer.fpsb
local fpsc = GJB.mplayer.fpsc
local height = 150
local width = 400
local Padding = 0
for i = 1, 10 do
local btn = CreateFrame("Button", "HistoryButton" .. i, fpsc)
btn:SetPoint("LEFT", GJB.mplayer.fpsc, "LEFT", 0, 0)
btn:SetBackdrop(
{
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
edgeFile = "",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 1, right = 1, top = 1, bottom = 1 }
})
btn:SetBackdropColor(10, 10, 10, 0.15)
btn:SetWidth(388)
btn:SetHeight(28)
btn:SetText("...")
btn:SetNormalFontObject("GameFontDarkGraySmall")
btn:SetHighlightFontObject("GameFontNormalSmall")
local bfs = btn:GetFontString()
bfs:SetJustifyH("left")
bfs:SetAllPoints(true)
btn:SetFontString(bfs)
local fheight = 0
if i == 1 then
btn:SetPoint("TOPLEFT", 7, -7)
height = height + fheight
else
btn:SetPoint("TOPLEFT", "HistoryButton" .. (i - 1), "BOTTOMLEFT", 0, - Padding)
height = height + fheight + Padding
end
btn:Hide()
tinsert(pool, btn)
-- Update the 'max' width of the frame
--width = (fwidth > width) and fwidth or width
end
-- Set the size of the scroll child
fpsc:SetSize(width, 280)
-- Size and place the parent frame, and set the scrollchild to be the
-- frame of font strings we've created
fp:SetSize(width, height)
fp:SetPoint("CENTER", 0, 0)
fp:SetScrollChild(fpsc)
fp:Show()
fpsc:SetSize(width, height)
-- Set up the scrollbar to work properly
local scrollMax = 280 - 140
fpsb:SetOrientation("VERTICAL");
fpsb:SetSize(16, height)
fpsb:SetPoint("TOPLEFT", fp, "TOPRIGHT", 0, 0)
fpsb:SetMinMaxValues(0, scrollMax)
fpsb:SetValue(0)
fpsb:SetScript("OnValueChanged", function(self) fp:SetVerticalScroll(self:GetValue()) end)
-- Enable mousewheel scrolling
fp:EnableMouseWheel(true)
fp:SetScript("OnMouseWheel", function(self, delta)
local current = fpsb:GetValue()
if IsShiftKeyDown() and (delta > 0) then
fpsb:SetValue(0)
elseif IsShiftKeyDown() and (delta < 0) then
fpsb:SetValue(scrollMax)
elseif (delta < 0) and (current < scrollMax) then
fpsb:SetValue(current + 25)
elseif (delta > 0) and (current > 1) then
fpsb:SetValue(current - 25)
end
end)
end
::Needed to simply correct some references to parent frame in the scroll list.
Hello all,
I was made aware of a bug in my addon from a user and I can't seem to figure it out on my own.
The code has not changed for more than a year and it suddenly stopped working as intended; thinking maybe a change in the api is the cause or worse, of my doing.
Simply put, I'm trying to drag a frame anchored to the UIParent and the second I start the "drag", the child frame's FontStrings disappear and it's like if the frame and it's children no longer acknowledge events; not even button clicks.
Any help or insight would be greatly appreciated.
function GJB:CreateMusicPlayer()
local MUSICPLAYER_WIDTH = 200 --width of the music player
local MUSICPLAYER_HEIGHT = 70 --height of the music player
local MUSICPLAYER_BUTTONMARGIN = 15 -- Left margin for the buttons' positions
local MUSICPLAYER_BUTTON_Y = -40 -- Y position of the buttons
-------------------------------------
-- Background Frame
-------------------------------------
GJB.mplayer.fbg = CreateFrame("Frame", "GJBP_BG", UIParent)
local fbg = GJB.mplayer.fbg
assert(fbg, "Failed to create frame " .. "GJBP_BG") -- failed to create the frame
fbg:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
fbg:SetMovable(true)
fbg:EnableMouse(true)
fbg:RegisterForDrag("RightButton")
fbg:SetScript("OnDragStart",
function( self )
if IsAltKeyDown() then
self:StartMoving()
end
end
)
fbg:SetScript("OnDragStop",
function( self )
self:StopMovingOrSizing()
pos = GJB.db.profile.musicplayer.pos
pos.a, pos.r, pos.rp, pos.x, pos.y = self:GetPoint(1)
end
)
fbg:SetBackdrop(
{
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 }
})
fbg:SetBackdropColor(0, 0, 0, 0.5)
fbg:SetBackdropBorderColor(1, 1, 0.5, 1)
fbg:SetWidth(MUSICPLAYER_WIDTH)
fbg:SetHeight(MUSICPLAYER_HEIGHT)
fbg:SetScale(1)
fbg:Show()
-------------------------------------
-- Header Frame
-------------------------------------
GJB.mplayer.fhdr = CreateFrame("Frame", "GJBP_Header", fbg)
local fhdr = GJB.mplayer.fhdr
assert(fhdr, "Failed to create frame " .. "GJBP_Header") -- failed to create the frame
fhdr.root = false
fhdr:SetPoint("TOPLEFT", "GJBP_BG", "TOPLEFT", 5, -1)
do
local text = {}
text = fhdr:CreateFontString(nil, "ARTWORK", "NumberFont_Shadow_Small")
assert(text, "Error creating font string.")
text:SetAllPoints(true)
text:SetJustifyH("CENTER")
text:SetJustifyV("CENTER")
text:SetTextColor(1, 1, 0.5, 1)
text:SetText(L["GJBP_TITLE"])
end
fhdr:SetBackdropColor(123, 123, 123, 0)
fhdr:SetBackdropBorderColor(0, 0, 0, 0)
fhdr:SetWidth(190)
fhdr:SetHeight(20)
fhdr:SetScale(1)
fhdr:Show()
Ok, now I understand. I thought GJB: Disable() would put the addon in a "non functioning" state; no event triggers whatsoever except OnEnable
So I'm better off managing an enabled state of GJB myself. Only thing is, it seems redundant to check all the time for every action such as a button click or event trigger.
something like this:
if GJB.enabled then
-- Do what was called for
end
Are there facilities in place to deal with this or is this example the way to go other than managing all events in every callback?
Thank you very much for helping me understand this.
1. This will be added considering my project is split in several different files.
local GJB = LibStub("AceAddon-3.0"):GetAddon("GarrisonJukeBox")
2. I'm used to initializing variables.
3. 4. I omitted the default table but this was already in my code.
GJB.defaults = {
profile = {
AddonEnabled = true,
... other saved variables here
},
}
5. 6. Will modifying self.db.profile.AddonEnabled further on in the code automatically set the AceAddon's internal enabled variable or do I still need to call GJB : Disable()?
In the OnInitialize, I check if the saved variables for the profile are from an old version and if so, will offer a choice to the user. No matter what choice is given to the user, The addon must cease loading and unregister any events previously registered.
Maybe I misunderstand the use of the AceAddon:Disable() function. I presumed that this function disabled the addon entirely like when you select what addon you want enabled in the addon options on the game login screen.
After loading the profile, I check if it's from a version prior to x.x.x.x. If it is, I must inform the user and stop the addon from loading any further.
As for myrroddin's suggestion on using tokens, I guess it would make sense in the long run considering I already have over 500 strings. The only problem I find with using this method is if I decide to change the way the message is presented to the user, the token might not express the correct message. I'm used to C++ #define in caps, figured I'd use the same here. Thank you.
GJB = LibStub("AceAddon-3.0"):NewAddon("GarrisonJukeBox", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceComm-3.0", "AceSerializer-3.0")
local L = LibStub("AceLocale-3.0"):GetLocale("GarrisonJukeBox")
_G["GJB"] = GJB -- Isn't GJB already in the global scope?
function GJB:OnInitialize()
self.db = {}
self.db = LibStub("AceDB-3.0"):New("GarrisonJukeBoxDB", self.defaults, true)
if self:VersionCheckResetData() then
self.OnInitialize = nil -- ewww, twice
GJB:Disabled()
return -- sloppy maybe but it works !!!
end
self.db.RegisterCallback(self, "OnProfileChanged", "OnProfileChanged")
self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged")
self.db.RegisterCallback(self, "OnProfileReset", "OnProfileChanged")
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("GarrisonJukeBoxDB", self.GenerateOptions)
LibStub("AceConfig-3.0"):RegisterOptionsTable("GarrisonJukeBox", self.slashcmd, "gjb")
local ACD3 = LibStub("AceConfigDialog-3.0")
self.optionsFrames = {}
self.optionsFrames.JukeBox = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["ADDON_NAME"], nil, "JukeBox")
self.optionsFrames.Zones = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["OPT_ZONES"], L["ADDON_NAME"], "Zones")
self.optionsFrames.Advanced = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["OPT_ADVANCED"], L["ADDON_NAME"], "Advanced")
self.optionsFrames.STMode = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["OPT_STMODE"], L["ADDON_NAME"], "STMode")
self.optionsFrames.Settings = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["OPT_SETTINGS"], L["ADDON_NAME"], "Settings")
self.optionsFrames.Audio = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["OPT_AUDIO"], L["ADDON_NAME"], "Audio")
self:RegisterModuleOptions("GJBSlashCmd", self.slashcmd, L["ADDON_SLASHCMD"])
self:RegisterModuleOptions("Profiles", function() return LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) end, L["Profiles"])
self.optionsFrames.About = ACD3:AddToBlizOptions("GarrisonJukeBoxDB", L["OPT_ABOUT"], L["ADDON_NAME"], "About")
self.OnInitialize = nil
end
function GJB:OnEnable()
self:RegisterEvent("PLAYER_ENTERING_WORLD", "OnPEWEvent")
self:RegisterEvent("PET_BATTLE_OPENING_START", "OnPetBattleStart")
self:RegisterEvent("PET_BATTLE_OVER", "OnPetBattleEnd")
self:RegisterEvent("ZONE_CHANGED_NEW_AREA", "OnZoneChangedNewArea")
self:RegisterEvent("ZONE_CHANGED_INDOORS", "OnZoneChangedIndoors")
self:RegisterEvent("ZONE_CHANGED", "OnZoneChanged")
self:RegisterEvent("GROUP_ROSTER_UPDATE", "OnJoinParty")
-- Register callbacks for inter-addon comms
self:RegisterComm(COMM_PREFIX .. "ReqVersion", "OnBuddyReqVersion") -- Sends requesters version and name-realm to all party members
self:RegisterComm(COMM_PREFIX .. "SentVersion", "OnBuddySentVersion") -- Sends version back to requester
self:RegisterComm(COMM_PREFIX .. "GetMusic", "OnBuddyListenMusic") -- Get music sent by leader
end
-- -------------------------------------------
-- OnDisable
-- -------------------------------------------
function GJB:OnDisable()
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
self:UnregisterEvent("PET_BATTLE_OPENING_START")
self:UnregisterEvent("PET_BATTLE_OVER")
self:UnregisterEvent("ZONE_CHANGED_NEW_AREA")
self:UnregisterEvent("ZONE_CHANGED_INDOORS")
self:UnregisterEvent("ZONE_CHANGED")
self:UnregisterEvent("GROUP_ROSTER_UPDATE")
-- add comm events unregisters
end
I'm trying to disable my addon without success. Am I missing something?
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceComm-3.0", "AceSerializer-3.0")
local f = AceGUI:Create("Frame")
f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end)
f:SetWidth(620)
f:SetHeight(250)
f:SetTitle(L["ADDON_BETA_WARNING_TITLE"])
f:SetLayout("Flow")
-- Create a button
local btn = AceGUI:Create("Button")
btn:SetWidth(100)
btn:SetText("...")
btn:SetCallback("OnClick",
function()
if MyAddon:Disable() then
f:Hide()
end
end)
-- Add the button to the container
f:AddChild(btn)
I already have the most up-to-date version of the listfile but it does not contain 6.2 Tanaan Jungle music entries. I actually went through every DBC/DB2 file that seemed pertinent to music with DBC Viewer, but could only find ID references and descriptive names (not actual filenames). I even wrote a parser for the unclassified DB2 files not in the filelist; there were 9 of them if memory serves.
Then I had an idea. I went on WoWHead and took a look at the stored mp3 files located on ZAM and voila! The actual mp3s (numerically named) contained enough information for me to guess the missing ones.
Here is a list of the ones I found so far:
Sound\Music\Draenor\MUS_62_tanaander_A.mp3
Sound\Music\Draenor\MUS_62_tanaander_B.mp3
Sound\Music\Draenor\MUS_62_tanaander_C.mp3
Sound\Music\Draenor\MUS_62_tanaander_H.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_A.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_B.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_C.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_H.mp3
Sound\Music\Draenor\MUS_62_thewanderer_A.mp3
Sound\Music\Draenor\MUS_62_thewanderer_B.mp3
Sound\Music\Draenor\MUS_62_thewanderer_H.mp3
Sound\Music\Draenor\MUS_62_undaunted_a.mp3
Sound\Music\Draenor\MUS_62_undaunted_b.mp3
Sound\Music\Draenor\MUS_62_undaunted_h.mp3
Sound\Music\Draenor\MUS_62_mortalnight_a.mp3
Sound\Music\Draenor\MUS_62_mortalnight_b.mp3
Sound\Music\Draenor\MUS_62_mortalnight_c.mp3
Sound\Music\Draenor\MUS_62_mortalnight_h.mp3
Sound\Music\Draenor\MUS_62_feudelenfer_a.mp3
Sound\Music\Draenor\MUS_62_feudelenfer_h.mp3
Sound\Music\Draenor\MUS_62_felessence_a.mp3
Sound\Music\Draenor\MUS_62_felessence_b.mp3
Sound\Music\Draenor\MUS_62_felessence_c.mp3
Sound\Music\Draenor\MUS_62_felessence_d.mp3
Sound\Music\Draenor\MUS_62_felessence_h.mp3
Sound\Music\Draenor\MUS_62_falling_1a.mp3
Sound\Music\Draenor\MUS_62_falling_1b.mp3
Sound\Music\Draenor\MUS_62_falling_2h.mp3
Sound\Music\Draenor\MUS_Invincible.mp3
I would like to add more ingame music to my addon Garrison Jukebox, like Tanaan Jungle and Timeless Isle. However, I've hit a snag. My current way of playing WoW music is by using the PlayMusic function. I'm having a hard time finding the paths and filenames of some of the missing tunes, thus, unable to add them.
There is a way of playing music with PlaySoundKitID but there's a catch. If there are multiple songs that can be played within a kit, I cannot track when to trigger my next timer. Consider the following:
Path + Filenames within the kit are unknown.
The currently playing file within the kit is unknown; thus the length (in seconds) of the file is also unknown.
GJB works with a timer (length of the music file in seconds) to trigger the next lookup.
I'm left with one obvious choice. Take the biggest length file within the kit as a reference and apply it to all elements within the said kit.
The drawback of this design is that a lot of music will play more than once and cut off in the middle of play.
If someone knows some other way to do this or can direct me to an updated music filelist, I would greatly appreciate it.
I tried to mess around with graphical options (game/driver) and it barely changed a thing for the Shaman's Lightning/Water Shields. Like you said, there are no "legal" in terms of respecting the ToU, to accomplish this as of this moment.
I hope the developers over at Blizzard find a viable solution to this issue by means of an option or Character API for addons.
I have a friend that has trouble (illness related) with specific character animations such as the shaman's rotating Lightning Shield and I was wondering if I could help my friend either by changing a setting in the client or using the wow api (addon) to disable such animations from occurring without disabling it's in-game functionality.
I am aware that the Lightning Shield can be omitted but at the cost of some damage output. Is there another way of accomplishing this?
Thank you, I didn't realize that sounds could be stopped. I thought it was an "in queue" list number; I guess I could have realized it was a handle given the name :P DOH!
But doesn't that still require me to toggle the Music CVar to play music without the currently playing zone music?
I currently use PlayMusic / StopMusic in my addon and that takes care of stopping in-game zone music. Adding support for PlaySoundKitID is doable but adds some complexity that I didn't plan for. What sound channel do you suggest I use to replace zone music? I would think "Music" but it doesn't stop the original zone music currently playing before the call.
Note: I was able to find an ogg or mp3 file (CASC hashed of course) so I'm pretty sure that its callable via path+filename.
I'm used to the PlayMusic function and was wondering if anyone knows of a website or resource (I've check for some time now without results) that would list the paths and filenames of 6.1 music, including the new Garrison Jukebox rolls?
I know that PlaySoundKitID plays sound files by passing the ID but there is no way to stop the sound on demand except by messing with CVars; I don't like that.
The location of the declaration "local fx = {}" was far from practical as the function always returned nil. Thank you for pointing out the obvious. :shock:
0
Hello,
I came across a bug that has annoyed me for a few days and I can't quite pin-point the problem.
When trying to access the Forge of Bonds in Ardenweald, I get the following error below.
When I disable my addon "GarrisonJukeBox", the error goes away.
Any hint to help me look in the right direction would be greatly appreciated.
Oh, and my addon works without issues.
Question : I was wondering if there was a buttongroup type of frame and if all buttons must have such a parent?
Thank you.
From Bugsack :
From ButtonGroup.lua
I would like to know if frame creation below is ok with mixin (from my addon)?
Found this :
0
*Update 1
The following frame creation child is the culprit:
Now I can drag but no more history items appear in the list...
...
...
...
0
**FIXED**
::Needed to simply correct some references to parent frame in the scroll list.
Hello all,
I was made aware of a bug in my addon from a user and I can't seem to figure it out on my own.
The code has not changed for more than a year and it suddenly stopped working as intended; thinking maybe a change in the api is the cause or worse, of my doing.
Simply put, I'm trying to drag a frame anchored to the UIParent and the second I start the "drag", the child frame's FontStrings disappear and it's like if the frame and it's children no longer acknowledge events; not even button clicks.
Any help or insight would be greatly appreciated.
...
...
...
0
So I'm better off managing an enabled state of GJB myself. Only thing is, it seems redundant to check all the time for every action such as a button click or event trigger.
something like this:
Are there facilities in place to deal with this or is this example the way to go other than managing all events in every callback?
Thank you very much for helping me understand this.
0
1. This will be added considering my project is split in several different files.
2. I'm used to initializing variables.
3. 4. I omitted the default table but this was already in my code.
5. 6. Will modifying self.db.profile.AddonEnabled further on in the code automatically set the AceAddon's internal enabled variable or do I still need to call GJB : Disable()?
7. Got it.
Thanks
0
Maybe I misunderstand the use of the AceAddon:Disable() function. I presumed that this function disabled the addon entirely like when you select what addon you want enabled in the addon options on the game login screen.
After loading the profile, I check if it's from a version prior to x.x.x.x. If it is, I must inform the user and stop the addon from loading any further.
As for myrroddin's suggestion on using tokens, I guess it would make sense in the long run considering I already have over 500 strings. The only problem I find with using this method is if I decide to change the way the message is presented to the user, the token might not express the correct message. I'm used to C++ #define in caps, figured I'd use the same here. Thank you.
0
only hides the AceGUI frame 'f'. What I want to achieve is to disable the whole addon 'MyAddon' previously created with
The return value I obtain is true, saying the disable method worked, but the addon is still usable. Any clues?
0
I'm trying to disable my addon without success. Am I missing something?
0
I already have the most up-to-date version of the listfile but it does not contain 6.2 Tanaan Jungle music entries. I actually went through every DBC/DB2 file that seemed pertinent to music with DBC Viewer, but could only find ID references and descriptive names (not actual filenames). I even wrote a parser for the unclassified DB2 files not in the filelist; there were 9 of them if memory serves.
Then I had an idea. I went on WoWHead and took a look at the stored mp3 files located on ZAM and voila! The actual mp3s (numerically named) contained enough information for me to guess the missing ones.
Here is a list of the ones I found so far:
Sound\Music\Draenor\MUS_62_tanaander_A.mp3
Sound\Music\Draenor\MUS_62_tanaander_B.mp3
Sound\Music\Draenor\MUS_62_tanaander_C.mp3
Sound\Music\Draenor\MUS_62_tanaander_H.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_A.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_B.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_C.mp3
Sound\Music\Draenor\MUS_62_tanaangloom_H.mp3
Sound\Music\Draenor\MUS_62_thewanderer_A.mp3
Sound\Music\Draenor\MUS_62_thewanderer_B.mp3
Sound\Music\Draenor\MUS_62_thewanderer_H.mp3
Sound\Music\Draenor\MUS_62_undaunted_a.mp3
Sound\Music\Draenor\MUS_62_undaunted_b.mp3
Sound\Music\Draenor\MUS_62_undaunted_h.mp3
Sound\Music\Draenor\MUS_62_mortalnight_a.mp3
Sound\Music\Draenor\MUS_62_mortalnight_b.mp3
Sound\Music\Draenor\MUS_62_mortalnight_c.mp3
Sound\Music\Draenor\MUS_62_mortalnight_h.mp3
Sound\Music\Draenor\MUS_62_feudelenfer_a.mp3
Sound\Music\Draenor\MUS_62_feudelenfer_h.mp3
Sound\Music\Draenor\MUS_62_felessence_a.mp3
Sound\Music\Draenor\MUS_62_felessence_b.mp3
Sound\Music\Draenor\MUS_62_felessence_c.mp3
Sound\Music\Draenor\MUS_62_felessence_d.mp3
Sound\Music\Draenor\MUS_62_felessence_h.mp3
Sound\Music\Draenor\MUS_62_falling_1a.mp3
Sound\Music\Draenor\MUS_62_falling_1b.mp3
Sound\Music\Draenor\MUS_62_falling_2h.mp3
Sound\Music\Draenor\MUS_Invincible.mp3
0
I would like to add more ingame music to my addon Garrison Jukebox, like Tanaan Jungle and Timeless Isle. However, I've hit a snag. My current way of playing WoW music is by using the PlayMusic function. I'm having a hard time finding the paths and filenames of some of the missing tunes, thus, unable to add them.
There is a way of playing music with PlaySoundKitID but there's a catch. If there are multiple songs that can be played within a kit, I cannot track when to trigger my next timer. Consider the following:
I'm left with one obvious choice. Take the biggest length file within the kit as a reference and apply it to all elements within the said kit.
The drawback of this design is that a lot of music will play more than once and cut off in the middle of play.
If someone knows some other way to do this or can direct me to an updated music filelist, I would greatly appreciate it.
Thanks ~Az
0
I hope the developers over at Blizzard find a viable solution to this issue by means of an option or Character API for addons.
0
I have a friend that has trouble (illness related) with specific character animations such as the shaman's rotating Lightning Shield and I was wondering if I could help my friend either by changing a setting in the client or using the wow api (addon) to disable such animations from occurring without disabling it's in-game functionality.
I am aware that the Lightning Shield can be omitted but at the cost of some damage output. Is there another way of accomplishing this?
Thanks
0
But doesn't that still require me to toggle the Music CVar to play music without the currently playing zone music?
I currently use PlayMusic / StopMusic in my addon and that takes care of stopping in-game zone music. Adding support for PlaySoundKitID is doable but adds some complexity that I didn't plan for. What sound channel do you suggest I use to replace zone music? I would think "Music" but it doesn't stop the original zone music currently playing before the call.
Note: I was able to find an ogg or mp3 file (CASC hashed of course) so I'm pretty sure that its callable via path+filename.
0
I know that PlaySoundKitID plays sound files by passing the ID but there is no way to stop the sound on demand except by messing with CVars; I don't like that.
Thanks.
0