Advanced customization using Lua code in WeakAuras
WeakAuras supports custom Lua code for advanced functionality beyond standard triggers and conditions. This guide covers the Lua environment, common patterns, and best practices.
The aura_env table is unique to each aura and persists while the aura is loaded:
-- Store variables specific to this auraaura_env.myCounter = 0aura_env.lastCastTime = 0aura_env.playerName = UnitName("player")-- Access in other custom code sectionsif aura_env.myCounter > 5 then -- Do somethingend
Use aura_env to share data between different custom code sections (Init, Trigger, Actions).
function() -- Return true to show, false to hide local name, _, _, count, _, duration, expirationTime = WA_GetUnitBuff("player", "Battle Shout") if name then -- Provide state data to the display return true, { show = true, changed = true, name = name, duration = duration, expirationTime = expirationTime, stacks = count or 1 } end return falseend
Provides duration information for progress bars and cooldown displays:
function() local name, _, _, _, _, duration, expirationTime = WA_GetUnitBuff("player", "Battle Shout") if name and duration and duration > 0 then return duration, expirationTime end return 0, 0 -- No durationend
-- On Showif aura_env.config.playSound then PlaySoundFile("Sound\\Interface\\AlarmClockWarning3.ogg")endprint("Buff active! Duration:", aura_env.state.duration)-- On Hide aura_env.hasWarned = falseprint("Buff faded")
-- Get aura data (returns a copy)local data = WeakAuras.GetData("AuraName")-- Get regionlocal region = WeakAuras.GetRegion("AuraName")-- Scan for events (trigger refresh)WeakAuras.ScanEvents("AURA_UPDATE")-- Show/hide overlaysWeakAuras.ShowOverlayGlow(frame)WeakAuras.HideOverlayGlow(frame)
Calling WeakAuras.GetData() frequently can impact performance. Cache results when possible.
function() local buffs = {"Battle Shout", "Commanding Shout", "Fortitude"} local activeBuffs = {} for _, buffName in ipairs(buffs) do if WA_GetUnitBuff("player", buffName) then table.insert(activeBuffs, buffName) end end if #activeBuffs > 0 then return true, { show = true, changed = true, activeCount = #activeBuffs, buffList = table.concat(activeBuffs, ", ") } end return falseend
function() local healthPct = (UnitHealth("player") / UnitHealthMax("player")) * 100 local threshold = 35 -- 35% health if healthPct < threshold then return true, { show = true, changed = true, health = healthPct, progressType = "static", value = healthPct, total = 100 } end return falseend
function() local debuffSpellIDs = {12345, 23456, 34567} -- Raid debuffs to track for unit in WA_IterateGroupMembers() do for _, spellID in ipairs(debuffSpellIDs) do local name, _, count, _, _, duration, expirationTime = WA_GetUnitDebuff(unit, spellID) if name then return true, { show = true, changed = true, unit = unit, unitName = WA_ClassColorName(unit), debuffName = name, stacks = count or 1, duration = duration, expirationTime = expirationTime } end end end return falseend
-- On Init: Setup event listeneraura_env.frame = aura_env.frame or CreateFrame("Frame")aura_env.shouldShow = falseaura_env.frame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")aura_env.frame:SetScript("OnEvent", function(self, event, unit, _, spellID) if unit == "player" and spellID == 47440 then -- Battle Shout cast aura_env.shouldShow = true aura_env.castTime = GetTime() WeakAuras.ScanEvents("CUSTOM_TRIGGER_CHECK") endend)-- Custom Triggerfunction() if aura_env.shouldShow then local elapsed = GetTime() - aura_env.castTime if elapsed < 5 then -- Show for 5 seconds return true, { show = true, changed = true, elapsed = elapsed } else aura_env.shouldShow = false end end return falseend
-- BAD: Calls API every framefunction() local name = GetSpellInfo(47440) local health = UnitHealth("player") -- ... more API calls every trigger checkend-- GOOD: Cache static data in aura_env-- On Init:aura_env.spellName = GetSpellInfo(47440) -- Cache spell name-- Custom Trigger:function() local health = UnitHealth("player") -- Only call what changes -- Use aura_env.spellName instead of calling GetSpellInfo againend
-- Wrap risky code in pcalllocal success, result = pcall(function() -- Code that might error return someFunction()end)if not success then print("Error occurred:", result)end
-- On Initaura_env.counter = 0aura_env.threshold = 50aura_env.spellID = 47440
Comment Your Code
Document complex logic:
-- Check if player has Battle Shout and is in combat-- Returns true when buff duration < 30 seconds remainingfunction() local name, _, _, _, _, duration, expirationTime = WA_GetUnitBuff("player", 47440) -- ... implementationend
Validate Input
Check for nil values:
local name, _, count = WA_GetUnitBuff("player", spellID)if name then -- Make sure buff exists local stacks = count or 1 -- Default to 1 if count is nil -- ... use stacksend
Clean Up Resources
Unregister events and clean up frames when appropriate:
-- When no longer neededif aura_env.frame then aura_env.frame:UnregisterAllEvents()end