Since you are still learning here are a few more suggestions. You don't really need to create a separate set of functions for each individual toggle option. If you aren't calling BuildTokensDisplay() often, which you shouldn't be, then any reference to count is not really guaranteed to be accurate in the future. Here is a slightly cleaned up version to show what I'm talking about (I kept the name colored by count just to show how it would fit):
local playerName, realmName = UnitName("player"), GetRealmName()
local function GetDesc(info)
local _, _, _, _, _, count = GetCurrencyListInfo(info.option.order)
return ("\nYou have %s.\n"):format(ColorUtils("GetCText", "sgray", count))
end
local function GetToken(info)
return Tokens[playerName][info[#info]]
end
local function SetToken(info, value)
Tokens[playerName][info[#info]] = value
end
function BuildTokensDisplay()
local allowedTokens = Opts.args.cat6.args.AllowedTokens
allowedTokens.name = ColorUtils("GetCClass", Characters[realmName][playerName].Class, ("%s's Tokens"):format(playerName))
allowedTokens = allowedTokens.args
if type(Tokens) ~= "table" then
Tokens = { [playerName] = { } }
elseif type(Tokens[playerName]) ~= "table" then
Tokens[playerName] = { }
end
for index = 1, GetCurrencyListSize() do
local tokenName, isHeader, _, _, _, count, icon = GetCurrencyListInfo(index)
if not isHeader then
allowedTokens[tokenName] = {
name = ColorUtils("GetCText", count ~= 0 and "white" or "sgray", tokenName),
type = "toggle",
order = index,
width = "double",
desc = GetDesc,
image = icon,
get = GetToken,
set = SetToken
}
end
end
end
Note that desc is now dynamic so that it will update any time the options are refreshed. Also, if you ever move your options table around you only have to update it in one place now instead of three. If you only call BuildTokensDisplay() once then you can move the locals from outside the function to inside as well.
local tremove = _G.tremove
local ipairs = _G.ipairs
local type = _G.type
local UnitMaxPower = _G.UnitMaxPower
local UnitPower = _G.UnitPower
local wipe = _G.table.wipe
local GetAddOnMetadata = _G.GetAddOnMetadata
local tonumber = _G.tonumber
local tostring = _G.tostring
local ceil = _G.ceil
local floor = _G.floor
Instead of just:
local tremove = tremove
local ipairs = ipairs
local type = type
local UnitMaxPower = UnitMaxPower
local UnitPower = UnitPower
local wipe = wipe
local GetAddOnMetadata = GetAddOnMetadata
local tonumber = tonumber
local tostring = tostring
local ceil = ceil
local floor = floor
That code gets run once so it does not need optimized.
This bit had me scratching my head:
function ACM:UpdateMedia(callback, type, handle)
local fontStyle
if self.db.profile.messageFontEffects or self.db.profile.manaFontEffects == monochrome then
fontStyle = "MONOCHROME"
elseif self.db.profile.messageFontEffects or self.db.profile.manaFontEffects == outline then
fontStyle = "OUTLINE"
else
fontStyle = "THICKOUTLINE"
end
if type == "border" then
ManaDisplay:SetBackdrop({
edgeFile = Media:Fetch("border", self.db.profile.barBorder),
tile = false,
edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 },
})
elseif type == "font" then
self.ManaDisplay.message:SetFont(self.db.profile.messageFont, self.db.profile.messageFontSize, fontStyle)
self.ManaDisplay.leftSide:SetFont(self.db.profile.manaFont, self.db.profile.manaFontSize, fontStyle)
self.ManaDisplay.rightSide:SetFont(self.db.profile.manaFont, self.db.profile.manaFontSize, fontStyle)
end
end
Why are you determining which font style is used when you haven't even checked if the font needs updated yet? I am assuming that was meant to be more like:
function ACM:UpdateMedia(callback, type, handle)
if type == "border" then
self.ManaDisplay:SetBackdrop({
edgeFile = Media:Fetch("border", self.db.profile.barBorder),
tile = false,
edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 },
})
elseif type == "font" then
local ManaDisplay, profile, fontStyle = self.ManaDisplay, self.db.profile
if profile.messageFontEffects == "monochrome" or profile.manaFontEffects == "monochrome" then
fontStyle = "MONOCHROME"
elseif profile.messageFontEffects == "outline" or profile.manaFontEffects == "outline" then
fontStyle = "OUTLINE"
else
fontStyle = "THICKOUTLINE"
end
ManaDisplay.message:SetFont(profile.messageFont, profile.messageFontSize, fontStyle)
ManaDisplay.leftSide:SetFont(profile.manaFont, profile.manaFontSize, fontStyle)
ManaDisplay.rightSide:SetFont(profile.manaFont, profile.manaFontSize, fontStyle)
end
end
And this bit from the function ACM.Combat does nothing:
I can only assume that was somehow supposed to tie-in to the local OnUpdate function declared at the end?
Basically everything after the function ACM.CreateSegments makes no sense to me. Was it copy pasted from somewhere else? The variable self means nothing at that point in the program so self.ManaDisplay is just an error waiting to be thrown.
As far as the original intent of this thread, you are using the array allManaValues to store all of your combat data but also duplicate a subset of that data into the array manaValues. Why not instead just always process the last 5 values in allManaValues?
local counter = 0
local function OnUpdate(self, elapsed)
counter = counter + elapsed
if counter < 2 then return end
counter = 0
local currentMana = UnitPower("player")
local deltaMana = currentMana - firstManaValue
firstManaValue = currentMana
local numManaValues = #allManaValues + 1
allManaValues[numManaValues] = deltaMana
local count = numManaValues >= 5 and 5 or numManaValues
for index = numManaValues - count + 1, numManaValues - 1 do
deltaMana = deltaMana + allManaValues[index]
end
averageMana = floor(deltaMana / count)
end
Update counter and check for the 2 seconds before initializing variables that may not even be needed
Since you are always placing values at the end of the arrays I would do table[#table + 1] = value instead of using tinsert
Is that really your OnUpdate handler or a function called by it? It is hard to tell because the function is named OnUpdate and takes the proper args yet it is returning averageMana like it is called elsewhere.
Is averageMana meant to be accessed outside of that OnUpdate function?
How can I refresh a menu on the fly?
I have a menu button which is a checkbox and has an arrow. In the submenu, I can chose something. When you do, the check has to be checked in the 'parent' button...
Here is a modified version of a function I wrote for a similar purpose (should work for any menu level):
local function RefreshMenu(menu)
if UIDROPDOWNMENU_OPEN_MENU == menu and DropDownList1:IsShown() then
local menuLevel, frame = UIDROPDOWNMENU_MENU_LEVEL
for level = 2, menuLevel do
frame = _G['DropDownList' .. level]
if not (frame and frame:IsShown()) then
menuLevel = level - 1
break
end
end
CloseDropDownMenus()
if menu.point ~= 'cursor' then
ToggleDropDownMenu(1, nil, menu, menu.relativeTo or 'UIParent')
else
ToggleDropDownMenu(1, nil, menu, 'cursor', menu.xOffset, menu.yOffset)
end
if DropDownList1:IsShown() then
local button, _
for level = 2, menuLevel do
frame = _G['DropDownList' .. level]
_, button = frame:GetPoint()
if button and button.hasArrow then
ToggleDropDownMenu(level, button.value, nil, nil, nil, nil, nil, button)
if frame.numButtons == 0 then
break
end
end
end
return true
end
end
end
If you look at the Minimap code for 4.0 you will see that the frame MinimapPing doesn't exist any more and the stuff it did is now handled directly by Minimap. Since MinimapPing will evaluate as nil I'd bet that is messing with your anchoring.
In all my testings, isNotRadial is not working. That what is used in blizz code and what is documented in UIDropDownMenu.lua. I haven't tried isNotRadio. I guess I should. Where did you get that?
When a button is clicked and keepShownOnClick is set, notCheckable now prevents a check from showing up (currently you must manually remove the check).
When checked is a function the button being evaluated is now passed as the first (and only) argument (currently no arguments are passed, which sucked).
Check marks now default to a radio style unless isNotRadio is set to keep the old check mark look.
The state driver code only runs during an OnUpdate script which will be after the events are processed for any action bar change. The result is your action bar works correctly but the icons/tooltips are for the wrong bar. You need to trigger the button's OnAttributeChanged script so they will update properly. I hope I explained that right.
That error is specific to Ace3 r948-r952, r953 fixes the error but doesn't correct the issue if r948-r952 had been previously run, and r954 fixes the issue completely. If they are getting that error then the highest version of Ace3 on their system falls in that range.
my working idea was to have a client/server setup running and when a new client logs in, they'd send an announcement and the master would identify. the new client would upload their data to the master, then the master would update the new client with what it was missing, then broadcast guild-wide what new info it got from the client.
there'd need to be some kind of heartbeat broadcast from the master just to ensure that it didn't crash out or get disabled and hang everybody up. if the master is detected to have gone offline, then you pick a new master by some simple system like alphabetical order (so everybody agrees).
I did something like this for one of my addons awhile back. The best method for determining the master I found was to pick the character with the shortest name, breaking ties with alphabetical order. The reason being the master will be using the addon channel the most and their name is sent each time. It may be a small difference but it does adds up.
0
Note that desc is now dynamic so that it will update any time the options are refreshed. Also, if you ever move your options table around you only have to update it in one place now instead of three. If you only call BuildTokensDisplay() once then you can move the locals from outside the function to inside as well.
0
0
Instead of just:
That code gets run once so it does not need optimized.
This bit had me scratching my head:
Why are you determining which font style is used when you haven't even checked if the font needs updated yet? I am assuming that was meant to be more like:
And this bit from the function ACM.Combat does nothing:
I can only assume that was somehow supposed to tie-in to the local OnUpdate function declared at the end?
Basically everything after the function ACM.CreateSegments makes no sense to me. Was it copy pasted from somewhere else? The variable self means nothing at that point in the program so self.ManaDisplay is just an error waiting to be thrown.
As far as the original intent of this thread, you are using the array allManaValues to store all of your combat data but also duplicate a subset of that data into the array manaValues. Why not instead just always process the last 5 values in allManaValues?
0
Is that really your OnUpdate handler or a function called by it? It is hard to tell because the function is named OnUpdate and takes the proper args yet it is returning averageMana like it is called elsewhere.
Is averageMana meant to be accessed outside of that OnUpdate function?
0
Shouldn't that be something more like:
0
Here is a modified version of a function I wrote for a similar purpose (should work for any menu level):
0
0
From UIDropDownMenu.lua:
0
When a button is clicked and keepShownOnClick is set, notCheckable now prevents a check from showing up (currently you must manually remove the check).
When checked is a function the button being evaluated is now passed as the first (and only) argument (currently no arguments are passed, which sucked).
Check marks now default to a radio style unless isNotRadio is set to keep the old check mark look.
0
0
0
0
0
0