from retail

This commit is contained in:
Bunny67
2020-07-11 00:19:17 +03:00
parent bbb4ac1c37
commit 6a7003b535
27 changed files with 2317 additions and 647 deletions
+43
View File
@@ -63,12 +63,55 @@ local WA_ClassColorName = function(unit)
end end
end end
WeakAuras.WA_ClassColorName = WA_ClassColorName
-- UTF-8 Sub is pretty commonly needed
local WA_Utf8Sub = function(input, size)
local output = ""
local i = 1
while (size > 0) do
local byte = input:byte(i)
if not byte then
return output
end
if byte < 128 then
-- ASCII byte
output = output .. input:sub(i, i)
size = size - 1
elseif byte < 192 then
-- Continuation bytes
output = output .. input:sub(i, i)
elseif byte < 244 then
-- Start bytes
output = output .. input:sub(i, i)
size = size - 1
end
i = i + 1
end
-- Add any bytes that are part of the sequence
while (true) do
local byte = input:byte(i)
if byte >= 128 and byte < 192 then
output = output .. input:sub(i, i)
else
break
end
i = i + 1
end
return output
end
WeakAuras.WA_Utf8Sub = WA_Utf8Sub
local helperFunctions = { local helperFunctions = {
WA_GetUnitAura = WA_GetUnitAura, WA_GetUnitAura = WA_GetUnitAura,
WA_GetUnitBuff = WA_GetUnitBuff, WA_GetUnitBuff = WA_GetUnitBuff,
WA_GetUnitDebuff = WA_GetUnitDebuff, WA_GetUnitDebuff = WA_GetUnitDebuff,
WA_IterateGroupMembers = WA_IterateGroupMembers, WA_IterateGroupMembers = WA_IterateGroupMembers,
WA_ClassColorName = WA_ClassColorName, WA_ClassColorName = WA_ClassColorName,
WA_Utf8Sub = WA_Utf8Sub,
} }
local LCG = LibStub("LibCustomGlow-1.0") local LCG = LibStub("LibCustomGlow-1.0")
+33 -16
View File
@@ -82,7 +82,7 @@ local scanFuncNameGroup = {}
local scanFuncSpellIdGroup = {} local scanFuncSpellIdGroup = {}
local scanFuncGeneralGroup = {} local scanFuncGeneralGroup = {}
-- Contains all scanFuncs that should be check if the exitance of a unit changed -- Contains all scanFuncs that should be check if the existence of a unit changed
local unitExistScanFunc = {} local unitExistScanFunc = {}
-- Which units exist -- Which units exist
local existingUnits = {} local existingUnits = {}
@@ -870,6 +870,10 @@ local function TriggerInfoApplies(triggerInfo, unit)
return false return false
end end
if triggerInfo.ignoreInvisible and not UnitIsVisible(unit) then
return false
end
if triggerInfo.unit == "group" and triggerInfo.groupSubType == "party" then if triggerInfo.unit == "group" and triggerInfo.groupSubType == "party" then
if IsInRaid() then if IsInRaid() then
-- Filter our player/party# while in raid and keep only raid units that are correct -- Filter our player/party# while in raid and keep only raid units that are correct
@@ -895,6 +899,11 @@ local function TriggerInfoApplies(triggerInfo, unit)
if triggerInfo.class and not triggerInfo.class[select(2, UnitClass(unit))] then if triggerInfo.class and not triggerInfo.class[select(2, UnitClass(unit))] then
return false return false
end end
if triggerInfo.nameChecker and not triggerInfo.nameChecker:Check(WeakAuras.UnitNameWithRealm(unit)) then
return false
end
return true return true
end end
@@ -1012,8 +1021,8 @@ local function UpdateTriggerState(time, id, triggernum)
useMatches = SatisfiesGroupMatchCount(triggerInfo, unitCount, maxUnitCount, matchCount) useMatches = SatisfiesGroupMatchCount(triggerInfo, unitCount, maxUnitCount, matchCount)
end end
local cloneIds = {}
if useMatches then if useMatches then
table.sort(auraDatas, SortMatchDataByUnitIndex) table.sort(auraDatas, SortMatchDataByUnitIndex)
local affected, unaffected local affected, unaffected
@@ -1022,7 +1031,6 @@ local function UpdateTriggerState(time, id, triggernum)
end end
local usedCloneIds = {}; local usedCloneIds = {};
for index, auraData in ipairs(auraDatas) do for index, auraData in ipairs(auraDatas) do
local cloneId = (auraData.GUID or auraData.unit or "unknown") .. " " .. auraData.spellId local cloneId = (auraData.GUID or auraData.unit or "unknown") .. " " .. auraData.spellId
if usedCloneIds[cloneId] then if usedCloneIds[cloneId] then
@@ -1033,15 +1041,17 @@ local function UpdateTriggerState(time, id, triggernum)
end end
updated = UpdateStateWithMatch(time, auraData, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, matchCountPerUnit[auraData.unit], totalStacks, affected, unaffected) or updated updated = UpdateStateWithMatch(time, auraData, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, matchCountPerUnit[auraData.unit], totalStacks, affected, unaffected) or updated
cloneIds[cloneId] = true
end end
if matchCount == 0 then if matchCount == 0 then
updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, "", nil, 0, 0, maxUnitCount, 0, totalStacks, affected, unaffected) or updated updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, "", nil, 0, 0, maxUnitCount, 0, totalStacks, affected, unaffected) or updated
cloneIds[""] = true
end end
end end
for cloneId, state in pairs(triggerStates) do for cloneId, state in pairs(triggerStates) do
if state.show and state.time < time then if not cloneIds[cloneId] then
updated = RemoveState(triggerStates, cloneId) or updated updated = RemoveState(triggerStates, cloneId) or updated
end end
end end
@@ -1069,6 +1079,7 @@ local function UpdateTriggerState(time, id, triggernum)
local useMatches = SatisfiesGroupMatchCount(triggerInfo, unitCount, maxUnitCount, matchCount) local useMatches = SatisfiesGroupMatchCount(triggerInfo, unitCount, maxUnitCount, matchCount)
local cloneIds = {}
if useMatches then if useMatches then
local affected, unaffected local affected, unaffected
if triggerInfo.useAffected then if triggerInfo.useAffected then
@@ -1079,6 +1090,7 @@ local function UpdateTriggerState(time, id, triggernum)
for unit, bestMatch in pairs(matches) do for unit, bestMatch in pairs(matches) do
if bestMatch then if bestMatch then
updated = UpdateStateWithMatch(time, bestMatch, triggerStates, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, affected, unaffected) or updated updated = UpdateStateWithMatch(time, bestMatch, triggerStates, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, affected, unaffected) or updated
cloneIds[unit] = true
end end
end end
else else
@@ -1089,9 +1101,11 @@ local function UpdateTriggerState(time, id, triggernum)
if bestMatch then if bestMatch then
if triggerInfo.perUnitMode == "all" then if triggerInfo.perUnitMode == "all" then
updated = UpdateStateWithMatch(time, bestMatch, triggerStates, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, affected, unaffected) or updated updated = UpdateStateWithMatch(time, bestMatch, triggerStates, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, affected, unaffected) or updated
cloneIds[unit] = true
end end
else else
updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, unit, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, affected, unaffected) or updated updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, unit, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, affected, unaffected) or updated
cloneIds[unit] = true
end end
end end
end end
@@ -1099,7 +1113,7 @@ local function UpdateTriggerState(time, id, triggernum)
end end
for cloneId, state in pairs(triggerStates) do for cloneId, state in pairs(triggerStates) do
if state.show and state.time < time then if not cloneIds[cloneId] then
updated = RemoveState(triggerStates, cloneId) or updated updated = RemoveState(triggerStates, cloneId) or updated
end end
end end
@@ -1156,11 +1170,12 @@ local function PrepareMatchData(unit, filter)
end end
end end
local function CleanUpOutdatedMatchData(time, unit, filter) local function CleanUpOutdatedMatchData(removeIndex, unit, filter)
-- Figure out if any matchData is outdated -- Figure out if any matchData is outdated
if matchData[unit] and matchData[unit][filter] then if matchData[unit] and matchData[unit][filter] then
for index, data in pairs(matchData[unit][filter]) do for index = removeIndex, #matchData[unit][filter] do
if data.time < time or not UnitExists(unit) then local data = matchData[unit][filter][index]
if data.index >= removeIndex or not UnitExists(unit) then
matchData[unit][filter][index] = nil matchData[unit][filter][index] = nil
for id, triggerData in pairs(data.auras) do for id, triggerData in pairs(data.auras) do
for triggernum in pairs(triggerData) do for triggernum in pairs(triggerData) do
@@ -1233,7 +1248,7 @@ local function ScanUnitWithFilter(matchDataChanged, time, unit, filter,
if matchDataUpToDate[unit] then if matchDataUpToDate[unit] then
matchDataUpToDate[unit][filter] = nil matchDataUpToDate[unit][filter] = nil
end end
CleanUpOutdatedMatchData(time, unit, filter) CleanUpOutdatedMatchData(1, unit, filter)
return return
end end
@@ -1268,7 +1283,7 @@ local function ScanUnitWithFilter(matchDataChanged, time, unit, filter,
end end
end end
CleanUpOutdatedMatchData(time, unit, filter) CleanUpOutdatedMatchData(index, unit, filter)
matchDataUpToDate[unit] = matchDataUpToDate[unit] or {} matchDataUpToDate[unit] = matchDataUpToDate[unit] or {}
matchDataUpToDate[unit][filter] = true matchDataUpToDate[unit][filter] = true
@@ -1514,11 +1529,7 @@ local function EventHandler(frame, event, arg1, arg2, ...)
tinsert(unitsToRemove, unit) tinsert(unitsToRemove, unit)
end end
end end
elseif event == "UNIT_FLAGS" then elseif event == "UNIT_FLAGS" or event == "UNIT_NAME_UPDATE" or event == "PLAYER_FLAGS_CHANGED" then
if WeakAuras.multiUnitUnits.group[arg1] then
RecheckActiveForUnitType("group", arg1, deactivatedTriggerInfos)
end
elseif event == "PLAYER_FLAGS_CHANGED" then
if WeakAuras.multiUnitUnits.group[arg1] then if WeakAuras.multiUnitUnits.group[arg1] then
RecheckActiveForUnitType("group", arg1, deactivatedTriggerInfos) RecheckActiveForUnitType("group", arg1, deactivatedTriggerInfos)
end end
@@ -1549,6 +1560,7 @@ local function EventHandler(frame, event, arg1, arg2, ...)
end end
frame:RegisterEvent("UNIT_AURA") frame:RegisterEvent("UNIT_AURA")
frame:RegisterEvent("UNIT_NAME_UPDATE")
frame:RegisterEvent("UNIT_FLAGS") frame:RegisterEvent("UNIT_FLAGS")
frame:RegisterEvent("PLAYER_FLAGS_CHANGED") frame:RegisterEvent("PLAYER_FLAGS_CHANGED")
frame:RegisterEvent("UNIT_PET") frame:RegisterEvent("UNIT_PET")
@@ -2128,6 +2140,8 @@ function BuffTrigger.Add(data)
local effectiveClass = groupTrigger and trigger.useClass and trigger.class local effectiveClass = groupTrigger and trigger.useClass and trigger.class
local effectiveIgnoreDead = groupTrigger and trigger.ignoreDead local effectiveIgnoreDead = groupTrigger and trigger.ignoreDead
local effectiveIgnoreDisconnected = groupTrigger and trigger.ignoreDisconnected local effectiveIgnoreDisconnected = groupTrigger and trigger.ignoreDisconnected
local effectiveIgnoreInvisible = groupTrigger and trigger.ignoreInvisible
local effectiveNameCheck = groupTrigger and trigger.useUnitName and trigger.unitName
if trigger.unit == "multi" then if trigger.unit == "multi" then
BuffTrigger.InitMultiAura() BuffTrigger.InitMultiAura()
@@ -2180,12 +2194,14 @@ function BuffTrigger.Add(data)
ignoreSelf = effectiveIgnoreSelf, ignoreSelf = effectiveIgnoreSelf,
ignoreDead = effectiveIgnoreDead, ignoreDead = effectiveIgnoreDead,
ignoreDisconnected = effectiveIgnoreDisconnected, ignoreDisconnected = effectiveIgnoreDisconnected,
ignoreInvisible = effectiveIgnoreInvisible,
groupSubType = groupSubType, groupSubType = groupSubType,
groupCountFunc = groupCountFunc, groupCountFunc = groupCountFunc,
class = effectiveClass, class = effectiveClass,
matchCountFunc = matchCountFunc, matchCountFunc = matchCountFunc,
useAffected = unit == "group" and trigger.useAffected, useAffected = unit == "group" and trigger.useAffected,
isMulti = trigger.unit == "multi", isMulti = trigger.unit == "multi",
nameChecker = effectiveNameCheck and WeakAuras.ParseNameCheck(trigger.unitName)
} }
triggerInfos[id] = triggerInfos[id] or {} triggerInfos[id] = triggerInfos[id] or {}
triggerInfos[id][triggernum] = triggerInformation triggerInfos[id][triggernum] = triggerInformation
@@ -2322,6 +2338,7 @@ function BuffTrigger.GetAdditionalProperties(data, triggernum)
ret = ret .. "|cFFFF0000%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n"
ret = ret .. "|cFFFF0000%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n"
ret = ret .. "|cFFFF0000%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n"
ret = ret .. "|cFFFF0000%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n"
ret = ret .. "|cFFFF0000%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n"
ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n"
ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n"
@@ -2385,7 +2402,7 @@ function BuffTrigger.GetTriggerConditions(data, triggernum)
result["spellId"] = { result["spellId"] = {
display = L["Spell Id"], display = L["Spell Id"],
type = "number", type = "number",
operator_types_only_equal = true operator_types = "only_equal"
} }
result["matchCount"] = { result["matchCount"] = {
+65 -11
View File
@@ -190,7 +190,8 @@ function TestForMultiSelect(trigger, arg)
end end
function ConstructTest(trigger, arg) function ConstructTest(trigger, arg)
local test; local test
local preamble
local name = arg.name; local name = arg.name;
if(arg.hidden or arg.type == "tristate" or arg.type == "toggle" or (arg.type == "multiselect" and trigger["use_"..name] ~= nil) or ((trigger["use_"..name] or arg.required) and trigger[name])) then if(arg.hidden or arg.type == "tristate" or arg.type == "toggle" or (arg.type == "multiselect" and trigger["use_"..name] ~= nil) or ((trigger["use_"..name] or arg.required) and trigger[name])) then
local number = tonumber(trigger[name]); local number = tonumber(trigger[name]);
@@ -215,11 +216,15 @@ function ConstructTest(trigger, arg)
end end
end end
if (test == "(true)") then if arg.preamble then
return nil; preamble = arg.preamble:format(trigger[name] or "")
end end
return test; if (test == "(true)") then
return nil, preamble
end
return test, preamble
end end
function ConstructFunction(prototype, trigger, inverse) function ConstructFunction(prototype, trigger, inverse)
@@ -243,6 +248,7 @@ function ConstructFunction(prototype, trigger, inverse)
local debug = {}; local debug = {};
local store = {}; local store = {};
local init; local init;
local preambles = ""
if(prototype.init) then if(prototype.init) then
init = prototype.init(trigger); init = prototype.init(trigger);
else else
@@ -268,7 +274,7 @@ function ConstructFunction(prototype, trigger, inverse)
if (arg.store) then if (arg.store) then
tinsert(store, name); tinsert(store, name);
end end
local test = ConstructTest(trigger, arg); local test, preamble = ConstructTest(trigger, arg);
if (test) then if (test) then
if(arg.required) then if(arg.required) then
tinsert(required, test); tinsert(required, test);
@@ -279,10 +285,13 @@ function ConstructFunction(prototype, trigger, inverse)
tinsert(debug, arg.debug:format(trigger[name])); tinsert(debug, arg.debug:format(trigger[name]));
end end
end end
if (preamble) then
preambles = preambles .. "\n" .. preamble
end
end end
end end
end end
local ret = "return function("..tconcat(input, ", ")..")\n"; local ret = preambles .. "return function("..tconcat(input, ", ")..")\n";
ret = ret..(init or ""); ret = ret..(init or "");
ret = ret..(#debug > 0 and tconcat(debug, "\n") or ""); ret = ret..(#debug > 0 and tconcat(debug, "\n") or "");
@@ -558,6 +567,13 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2
untriggerCheck = true; untriggerCheck = true;
end end
elseif (data.statesParameter == "unit") then elseif (data.statesParameter == "unit") then
if optionsEvent then
if WeakAuras.multiUnitUnits[data.trigger.unit] then
arg1 = next(WeakAuras.multiUnitUnits[data.trigger.unit])
else
arg1 = data.trigger.unit
end
end
if arg1 then if arg1 then
local unit, cloneId local unit, cloneId
if WeakAuras.multiUnitUnits[data.trigger.unit] then if WeakAuras.multiUnitUnits[data.trigger.unit] then
@@ -2501,7 +2517,7 @@ end
local watchUnitChange local watchUnitChange
-- Nameplates only distinguish between friends and everyone else -- Nameplates only distinguish between friends and everyone else
function WeakAuras.GetPlayerReaciton(unit) function WeakAuras.GetPlayerReaction(unit)
return UnitIsEnemy('player', unit) and 'hostile' or 'friendly' return UnitIsEnemy('player', unit) and 'hostile' or 'friendly'
end end
@@ -3644,16 +3660,17 @@ function GenericTrigger.GetTriggerConditions(data, triggernum)
end end
end end
end end
if (v.conditionPreamble) then
result[v.name].preamble = v.conditionPreamble;
end
if (v.conditionTest) then if (v.conditionTest) then
result[v.name].test = v.conditionTest; result[v.name].test = v.conditionTest;
end end
if (v.conditionEvents) then if (v.conditionEvents) then
result[v.name].events = v.conditionEvents; result[v.name].events = v.conditionEvents;
end end
if (v.operator_types_without_equal) then if (v.operator_types) then
result[v.name].operator_types_without_equal = true; result[v.name].operator_types = v.operator_types;
elseif (v.operator_types_only_equal) then
result[v.name].operator_types_only_equal = true;
end end
end end
end end
@@ -3861,6 +3878,43 @@ function GenericTrigger.GetTriggerDescription(data, triggernum, namestable)
end end
end end
do
-- Based on Code by DejaCharacterStats. Ugly code to figure out the GCD
local GetCombatRatingBonus = GetCombatRatingBonus
local CR_HASTE_MELEE = CR_HASTE_MELEE
local CR_HASTE_RANGED = CR_HASTE_RANGED
local CR_HASTE_SPELL = CR_HASTE_SPELL
local class = select(2, UnitClass("player"))
if class == "DRUID" then
function WeakAuras.CalculatedGcdDuration()
local id = GetShapeshiftFormID()
local haste = GetHaste()
return id == 1 and 1 or max(0.75, 1.5 * 100 / (100 + GetCombatRatingBonus(CR_HASTE_SPELL)))
end
elseif class == "ROGUE" then
function WeakAuras.CalculatedGcdDuration()
return 1
end
else
local GetHaste
if class == "HUNTER" then
function GetHaste()
return GetCombatRatingBonus(CR_HASTE_RANGED)
end
elseif class == "DEATHKNIGHT" or class == "PALADIN" or class == "WARRIOR" then
function GetHaste()
return GetCombatRatingBonus(CR_HASTE_MELEE)
end
else
function GetHaste()
return GetCombatRatingBonus(CR_HASTE_SPELL)
end
end
function WeakAuras.CalculatedGcdDuration()
return max(0.75, 1.5 * 100 / (100 + GetHaste()))
end
end
end
WeakAuras.RegisterTriggerSystem({"event", "status", "custom"}, GenericTrigger); WeakAuras.RegisterTriggerSystem({"event", "status", "custom"}, GenericTrigger);
+1 -1
View File
@@ -7,7 +7,7 @@ WeakAuras.halfWidth = WeakAuras.normalWidth / 2
WeakAuras.doubleWidth = WeakAuras.normalWidth * 2 WeakAuras.doubleWidth = WeakAuras.normalWidth * 2
local versionStringFromToc = GetAddOnMetadata("WeakAuras", "Version") local versionStringFromToc = GetAddOnMetadata("WeakAuras", "Version")
local versionString = "2.17.8" local versionString = "2.17.11"
local buildTime = "20200511190745" local buildTime = "20200511190745"
WeakAuras.versionString = versionStringFromToc WeakAuras.versionString = versionStringFromToc
+422 -97
View File
@@ -12,6 +12,7 @@ local UnitClass, UnitHealth, UnitHealthMax, UnitName, UnitPower, UnitPowerMax =
local GetSpellInfo, GetItemInfo, GetItemCount, GetItemIcon = GetSpellInfo, GetItemInfo, GetItemCount, GetItemIcon local GetSpellInfo, GetItemInfo, GetItemCount, GetItemIcon = GetSpellInfo, GetItemInfo, GetItemCount, GetItemIcon
local GetShapeshiftFormInfo, GetShapeshiftForm = GetShapeshiftFormInfo, GetShapeshiftForm local GetShapeshiftFormInfo, GetShapeshiftForm = GetShapeshiftFormInfo, GetShapeshiftForm
local GetRuneCooldown, UnitCastingInfo, UnitChannelInfo = GetRuneCooldown, UnitCastingInfo, UnitChannelInfo local GetRuneCooldown, UnitCastingInfo, UnitChannelInfo = GetRuneCooldown, UnitCastingInfo, UnitChannelInfo
local UnitDetailedThreatSituation, UnitThreatSituation = UnitDetailedThreatSituation, UnitThreatSituation
local WeakAuras = WeakAuras local WeakAuras = WeakAuras
local L = WeakAuras.L local L = WeakAuras.L
@@ -74,6 +75,17 @@ end
LibRangeCheck:RegisterCallback(LibRangeCheck.CHECKERS_CHANGED, RangeCacheUpdate) LibRangeCheck:RegisterCallback(LibRangeCheck.CHECKERS_CHANGED, RangeCacheUpdate)
function WeakAuras.UnitDetailedThreatSituation(unit1, unit2)
local ok, aggro, status, threatpct, rawthreatpct, threatvalue = pcall(UnitDetailedThreatSituation, unit1, unit2)
if ok then
return aggro, status, threatpct, rawthreatpct, threatvalue
end
end
local constants = {
nameRealmFilterDesc = L[" Filter formats: 'Name', 'Name-Realm', '-Realm'. \n\nSupports multiple entries, separated by commas\n"],
}
WeakAuras.function_strings = { WeakAuras.function_strings = {
count = [[ count = [[
return function(count) return function(count)
@@ -718,15 +730,31 @@ WeakAuras.load_prototype = {
}, },
{ {
name = "name", name = "name",
display = L["Player Name"], hidden = true,
type = "tristatestring", init = "arg",
init = "arg" test = "true"
}, },
{ {
name = "realm", name = "realm",
display = L["Realm"], hidden = true,
type = "tristatestring", init = "arg",
init = "arg" test = "true"
},
{
name = "namerealm",
display = L["Player Name/Realm"],
type = "string",
test = "nameRealmChecker:Check(player, realm)",
preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)",
desc = constants.nameRealmFilterDesc,
},
{
name = "namerealmblack",
display = L["Blacklisted Player Name/Realm"],
type = "string",
test = "not nameRealmBlacklistChecker:Check(player, realm)",
preamble = "local nameRealmBlacklistChecker = WeakAuras.ParseNameCheck(%q)",
desc = constants.nameRealmFilterDesc,
}, },
{ {
name = "class", name = "class",
@@ -927,6 +955,10 @@ WeakAuras.event_prototypes = {
local result = {} local result = {}
AddUnitEventForEvents(result, unit, "UNIT_LEVEL") AddUnitEventForEvents(result, unit, "UNIT_LEVEL")
AddUnitEventForEvents(result, unit, "UNIT_FACTION") AddUnitEventForEvents(result, unit, "UNIT_FACTION")
AddUnitEventForEvents(result, unit, "UNIT_NAME_UPDATE")
if trigger.use_ignoreDead or trigger.use_ignoreDisconnected then
AddUnitEventForEvents(result, unit, "UNIT_FLAGS")
end
return result; return result;
end, end,
internal_events = function(trigger) internal_events = function(trigger)
@@ -946,6 +978,7 @@ WeakAuras.event_prototypes = {
unit = string.lower(unit) unit = string.lower(unit)
local smart = %s local smart = %s
local extraUnit = %q; local extraUnit = %q;
local name, realm = WeakAuras.UnitNameWithRealm(unit)
]=]; ]=];
ret = ret .. unitHelperFunctions.SpecificUnitCheck(trigger) ret = ret .. unitHelperFunctions.SpecificUnitCheck(trigger)
@@ -980,9 +1013,32 @@ WeakAuras.event_prototypes = {
name = "name", name = "name",
display = L["Name"], display = L["Name"],
type = "string", type = "string",
init = "UnitName(unit)",
store = true, store = true,
conditionType = "string" hidden = true,
test = "true"
},
{
name = "realm",
display = L["Realm"],
type = "string",
store = true,
hidden = true,
test = "true"
},
{
name = "namerealm",
display = L["Unit Name/Realm"],
type = "string",
preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)",
test = "nameRealmChecker:Check(name, realm)",
conditionType = "string",
conditionPreamble = function(input)
return WeakAuras.ParseNameCheck(input)
end,
conditionTest = function(state, needle, op, preamble)
return preamble:Check(state.name, state.realm)
end,
operator_types = "none",
}, },
{ {
name = "class", name = "class",
@@ -1002,11 +1058,31 @@ WeakAuras.event_prototypes = {
store = true, store = true,
conditionType = "select" conditionType = "select"
}, },
{
name = "ignoreDead",
display = WeakAuras.newFeatureString .. L["Ignore Dead"],
type = "toggle",
width = WeakAuras.doubleWidth,
enable = function(trigger)
return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"
end,
init = "not UnitIsDeadOrGhost(unit)"
},
{
name = "ignoreDisconnected",
display = WeakAuras.newFeatureString .. L["Ignore Disconnected"],
type = "toggle",
width = WeakAuras.doubleWidth,
enable = function(trigger)
return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"
end,
init = "UnitIsConnected(unit)"
},
{ {
name = "hostility", name = "hostility",
display = L["Hostility"], display = L["Hostility"],
type = "select", type = "select",
init = "WeakAuras.GetPlayerReaciton(unit)", init = "WeakAuras.GetPlayerReaction(unit)",
values = "hostility_types", values = "hostility_types",
store = true, store = true,
conditionType = "select", conditionType = "select",
@@ -1058,6 +1134,10 @@ WeakAuras.event_prototypes = {
local unit = trigger.unit local unit = trigger.unit
local result = {} local result = {}
AddUnitEventForEvents(result, unit, "UNIT_HEALTH") AddUnitEventForEvents(result, unit, "UNIT_HEALTH")
AddUnitEventForEvents(result, unit, "UNIT_NAME_UPDATE")
if trigger.use_ignoreDead or trigger.use_ignoreDisconnected then
AddUnitEventForEvents(result, unit, "UNIT_FLAGS")
end
return result return result
end, end,
internal_events = function(trigger) internal_events = function(trigger)
@@ -1072,6 +1152,7 @@ WeakAuras.event_prototypes = {
trigger.unit = trigger.unit or "player"; trigger.unit = trigger.unit or "player";
local ret = [=[ local ret = [=[
unit = string.lower(unit) unit = string.lower(unit)
local name, realm = WeakAuras.UnitNameWithRealm(unit)
local smart = %s local smart = %s
]=]; ]=];
@@ -1132,9 +1213,33 @@ WeakAuras.event_prototypes = {
name = "name", name = "name",
display = L["Unit Name"], display = L["Unit Name"],
type = "string", type = "string",
init = "UnitName(unit)",
store = true, store = true,
conditionType = "string" hidden = true,
test = "true"
},
{
name = "realm",
display = L["Realm"],
type = "string",
store = true,
hidden = true,
test = "true"
},
{
name = "namerealm",
display = L["Unit Name/Realm"],
type = "string",
preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)",
test = "nameRealmChecker:Check(name, realm)",
conditionType = "string",
conditionPreamble = function(input)
return WeakAuras.ParseNameCheck(input)
end,
conditionTest = function(state, needle, op, preamble)
return preamble:Check(state.name, state.realm)
end,
operator_types = "none",
desc = constants.nameRealmFilterDesc,
}, },
{ {
name = "npcId", name = "npcId",
@@ -1153,6 +1258,26 @@ WeakAuras.event_prototypes = {
store = true, store = true,
conditionType = "select" conditionType = "select"
}, },
{
name = "ignoreDead",
display = WeakAuras.newFeatureString .. L["Ignore Dead"],
type = "toggle",
width = WeakAuras.doubleWidth,
enable = function(trigger)
return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"
end,
init = "not UnitIsDeadOrGhost(unit)"
},
{
name = "ignoreDisconnected",
display = WeakAuras.newFeatureString .. L["Ignore Disconnected"],
type = "toggle",
width = WeakAuras.doubleWidth,
enable = function(trigger)
return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"
end,
init = "UnitIsConnected(unit)"
},
{ {
name = "name", name = "name",
hidden = true, hidden = true,
@@ -1184,6 +1309,11 @@ WeakAuras.event_prototypes = {
AddUnitEventForEvents(result, unit, "UNIT_MAXRUNIC_POWER") AddUnitEventForEvents(result, unit, "UNIT_MAXRUNIC_POWER")
AddUnitEventForEvents(result, unit, "UNIT_DISPLAYPOWER") AddUnitEventForEvents(result, unit, "UNIT_DISPLAYPOWER")
AddUnitEventForEvents(result, unit, "UNIT_HAPPINESS") AddUnitEventForEvents(result, unit, "UNIT_HAPPINESS")
AddUnitEventForEvents(result, unit, "UNIT_NAME_UPDATE")
if trigger.use_ignoreDead or trigger.use_ignoreDisconnected then
AddUnitEventForEvents(result, unit, "UNIT_FLAGS")
end
return result; return result;
end, end,
@@ -1200,6 +1330,7 @@ WeakAuras.event_prototypes = {
trigger.unit = trigger.unit or "player"; trigger.unit = trigger.unit or "player";
local ret = [=[ local ret = [=[
unit = string.lower(unit) unit = string.lower(unit)
local name, realm = WeakAuras.UnitNameWithRealm(unit)
local smart = %s local smart = %s
local powerType = %s; local powerType = %s;
local unitPowerType = UnitPowerType(unit); local unitPowerType = UnitPowerType(unit);
@@ -1290,9 +1421,33 @@ WeakAuras.event_prototypes = {
name = "name", name = "name",
display = L["Unit Name"], display = L["Unit Name"],
type = "string", type = "string",
init = "UnitName(unit)",
store = true, store = true,
conditionType = "string" hidden = true,
test = "true"
},
{
name = "realm",
display = L["Realm"],
type = "string",
store = true,
hidden = true,
test = "true"
},
{
name = "namerealm",
display = L["Unit Name/Realm"],
type = "string",
preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)",
test = "nameRealmChecker:Check(name, realm)",
conditionType = "string",
conditionPreamble = function(input)
return WeakAuras.ParseNameCheck(input)
end,
conditionTest = function(state, needle, op, preamble)
return preamble:Check(state.name, state.realm)
end,
operator_types = "none",
desc = constants.nameRealmFilterDesc,
}, },
{ {
name = "npcId", name = "npcId",
@@ -1311,6 +1466,26 @@ WeakAuras.event_prototypes = {
store = true, store = true,
conditionType = "select" conditionType = "select"
}, },
{
name = "ignoreDead",
display = WeakAuras.newFeatureString .. L["Ignore Dead"],
type = "toggle",
width = WeakAuras.doubleWidth,
enable = function(trigger)
return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"
end,
init = "not UnitIsDeadOrGhost(unit)"
},
{
name = "ignoreDisconnected",
display = WeakAuras.newFeatureString .. L["Ignore Disconnected"],
type = "toggle",
width = WeakAuras.doubleWidth,
enable = function(trigger)
return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"
end,
init = "UnitIsConnected(unit)"
},
{ {
hidden = true, hidden = true,
test = "WeakAuras.UnitExistsFixed(unit, smart) and specificUnitCheck" test = "WeakAuras.UnitExistsFixed(unit, smart) and specificUnitCheck"
@@ -1341,7 +1516,8 @@ WeakAuras.event_prototypes = {
init = "arg", init = "arg",
hidden = "true", hidden = "true",
test = "true", test = "true",
store = true store = true,
display = L["Source GUID"]
}, },
{ {
name = "sourceUnit", name = "sourceUnit",
@@ -1415,7 +1591,8 @@ WeakAuras.event_prototypes = {
init = "arg", init = "arg",
hidden = "true", hidden = "true",
test = "true", test = "true",
store = true store = true,
display = L["Destination GUID"]
}, },
{ {
name = "destUnit", name = "destUnit",
@@ -4401,26 +4578,42 @@ WeakAuras.event_prototypes = {
}, },
["Threat Situation"] = { ["Threat Situation"] = {
type = "status", type = "status",
events = { events = function(trigger)
["unit_events"] = {
["player"] = {"UNIT_THREAT_SITUATION_UPDATE"}
}
},
internal_events = function(trigger)
local result = {} local result = {}
AddUnitChangeInternalEvents(trigger.unit, result) if trigger.threatUnit and trigger.threatUnit ~= "none" then
AddUnitEventForEvents(result, trigger.threatUnit, "UNIT_THREAT_LIST_UPDATE")
else
AddUnitEventForEvents(result, "player", "UNIT_THREAT_SITUATION_UPDATE")
end
return result return result
end, end,
force_events = "UNIT_THREAT_SITUATION_UPDATE", internal_events = function(trigger)
local result = {}
if trigger.threatUnit and trigger.threatUnit ~= "none" then
AddUnitChangeInternalEvents(trigger.threatUnit, result)
end
return result
end,
force_events = "UNIT_THREAT_LIST_UPDATE",
name = L["Threat Situation"], name = L["Threat Situation"],
init = function(trigger) init = function(trigger)
local ret = [[ local ret = [[
local status = UnitThreatSituation('player', %s) or -1; local unit = %s
local aggro = status == 2 or status == 3; local ok = true
local aggro, status, threatpct, rawthreatpct, threatvalue, threattotal
if unit then
aggro, status, threatpct, rawthreatpct, threatvalue = WeakAuras.UnitDetailedThreatSituation('player', unit)
threattotal = (threatvalue or 0) * 100 / (threatpct or 1)
else
status = UnitThreatSituation('player')
aggro = status == 2 or status == 3
threatpct, rawthreatpct, threatvalue, threattotal = 100, 100, 0, 100
end
]]; ]];
return ret:format(trigger.threatUnit and trigger.threatUnit ~= "none" and "[["..trigger.threatUnit.."]]" or "nil"); return ret:format(trigger.threatUnit and trigger.threatUnit ~= "none" and "[["..trigger.threatUnit.."]]" or "nil");
end, end,
canHaveDuration = true,
statesParameter = "one",
args = { args = {
{ {
name = "threatUnit", name = "threatUnit",
@@ -4435,17 +4628,68 @@ WeakAuras.event_prototypes = {
name = "status", name = "status",
display = L["Status"], display = L["Status"],
type = "select", type = "select",
values = "unit_threat_situation_types" values = "unit_threat_situation_types",
store = true,
conditionType = "select"
}, },
{ {
name = "aggro", name = "aggro",
display = L["Aggro"], display = L["Aggro"],
type = "tristate" store = true,
conditionType = "bool",
},
{
name = "threatpct",
display = L["Threat Percent"],
desc = L["Your threat on the mob as a percentage of the amount required to pull aggro. Will pull aggro at 100."],
type = "number",
store = true,
conditionType = "number",
enable = function(trigger) return trigger.threatUnit ~= "none" end,
},
{
name = "rawthreatpct",
display = L["Raw Threat Percent"],
desc = L["Your threat as a percentage of the tank's current threat."],
type = "number",
store = true,
conditionType = "number",
enable = function(trigger) return trigger.threatUnit ~= "none" end,
},
{
name = "threatvalue",
display = L["Threat Value"],
desc = L["Your total threat on the mob."],
type = "number",
store = true,
conditionType = "number",
enable = function(trigger) return trigger.threatUnit ~= "none" end,
},
{
name = "value",
hidden = true,
init = "threatvalue",
store = true,
test = "true"
},
{
name = "total",
hidden = true,
init = "threattotal",
store = true,
test = "true"
},
{
name = "progressType",
hidden = true,
init = "'static'",
store = true,
test = "true"
}, },
{ {
hidden = true, hidden = true,
test = "status ~= -1" test = "status ~= nil and ok"
}, }
}, },
automaticrequired = true automaticrequired = true
}, },
@@ -4483,6 +4727,7 @@ WeakAuras.event_prototypes = {
AddUnitEventForEvents(result, unit, "UNIT_SPELLCAST_NOT_INTERRUPTIBLE") AddUnitEventForEvents(result, unit, "UNIT_SPELLCAST_NOT_INTERRUPTIBLE")
AddUnitEventForEvents(result, unit, "UNIT_SPELLCAST_INTERRUPTED") AddUnitEventForEvents(result, unit, "UNIT_SPELLCAST_INTERRUPTED")
AddUnitEventForEvents(result, unit, "UNIT_TARGET") AddUnitEventForEvents(result, unit, "UNIT_TARGET")
AddUnitEventForEvents(result, unit, "UNIT_NAME_UPDATE")
return result return result
end, end,
internal_events = function(trigger) internal_events = function(trigger)
@@ -4499,6 +4744,11 @@ WeakAuras.event_prototypes = {
trigger.unit = trigger.unit or "player"; trigger.unit = trigger.unit or "player";
local ret = [=[ local ret = [=[
unit = string.lower(unit) unit = string.lower(unit)
local destUnit = unit .. '-target'
local sourceName, sourceRealm = WeakAuras.UnitNameWithRealm(unit)
local destName, destRealm = WeakAuras.UnitNameWithRealm(destUnit)
destName = destName or ""
destRealm = destRealm or ""
local smart = %s local smart = %s
local remainingCheck = %s local remainingCheck = %s
local inverseTrigger = %s local inverseTrigger = %s
@@ -4678,18 +4928,43 @@ WeakAuras.event_prototypes = {
{ {
name = "sourceName", name = "sourceName",
display = L["Caster Name"], display = L["Caster Name"],
type = "string",
store = true, store = true,
hidden = true, hidden = true,
test = "true", test = "true",
init = "UnitName(unit)",
enable = function(trigger) return not trigger.use_inverse end, enable = function(trigger) return not trigger.use_inverse end,
}, },
{
name = "sourceRealm",
display = L["Caster Realm"],
type = "string",
store = true,
hidden = true,
test = "true",
enable = function(trigger) return not trigger.use_inverse end,
},
{
name = "sourceNameRealm",
display = L["Source Unit Name/Realm"],
type = "string",
preamble = "local sourceNameRealmChecker = WeakAuras.ParseNameCheck(%q)",
test = "sourceNameRealmChecker:Check(sourceName, sourceRealm)",
conditionType = "string",
conditionPreamble = function(input)
return WeakAuras.ParseNameCheck(input)
end,
conditionTest = function(state, needle, op, preamble)
return preamble:Check(state.sourceName, state.sourceRealm)
end,
operator_types = "none",
enable = function(trigger) return not trigger.use_inverse end,
desc = constants.nameRealmFilterDesc,
},
{ {
name = "destUnit", name = "destUnit",
display = L["Caster's Target "], display = L["Caster's Target "],
type = "unit", type = "unit",
values = "actual_unit_types_with_specific", values = "actual_unit_types_with_specific",
init = "unit .. '-target'",
conditionType = "unit", conditionType = "unit",
conditionTest = function(state, unit, op) conditionTest = function(state, unit, op)
return state and state.show and state.destUnit and ((UnitIsUnit(state.destUnit, unit) == 1 and true or false) == (op == "==")) return state and state.show and state.destUnit and ((UnitIsUnit(state.destUnit, unit) == 1 and true or false) == (op == "=="))
@@ -4701,12 +4976,38 @@ WeakAuras.event_prototypes = {
{ {
name = "destName", name = "destName",
display = L["Name of Caster's Target"], display = L["Name of Caster's Target"],
type = "string",
store = true, store = true,
hidden = true, hidden = true,
test = "true", test = "true",
init = "UnitName(destUnit)",
enable = function(trigger) return not trigger.use_inverse end, enable = function(trigger) return not trigger.use_inverse end,
}, },
{
name = "destRealm",
display = L["Realm of Caster's Target"],
type = "string",
store = true,
hidden = true,
test = "true",
enable = function(trigger) return not trigger.use_inverse end,
},
{
name = "destNameRealm",
display = L["Name/Realm of Caster's Target"],
type = "string",
preamble = "local destNameRealmChecker = WeakAuras.ParseNameCheck(%q)",
test = "destNameRealmChecker:Check(destName, destRealm)",
conditionType = "string",
conditionPreamble = function(input)
return WeakAuras.ParseNameCheck(input)
end,
conditionTest = function(state, needle, op, preamble)
return preamble:Check(state.destName, state.destRealm)
end,
operator_types = "none",
enable = function(trigger) return not trigger.use_inverse end,
desc = constants.nameRealmFilterDesc,
},
{ {
name = "inverse", name = "inverse",
display = L["Inverse"], display = L["Inverse"],
@@ -5336,7 +5637,7 @@ WeakAuras.event_prototypes = {
name = "range", name = "range",
display = L["Distance"], display = L["Distance"],
type = "number", type = "number",
operator_types_without_equal = true, operator_types = "without_equal",
test = "triggerResult", test = "triggerResult",
conditionType = "number", conditionType = "number",
conditionTest = function(state, needle, needle2) conditionTest = function(state, needle, needle2)
@@ -5360,97 +5661,121 @@ WeakAuras.event_prototypes["BigWigs Timer"] = nil
WeakAuras.dynamic_texts = { WeakAuras.dynamic_texts = {
["p"] = { ["p"] = {
func = function(state, region) get = function(state)
if not state then return "" end if not state then return nil end
if state.progressType == "static" then if state.progressType == "static" then
return state.value or "" return state.value or nil
end end
if state.progressType == "timed" then if state.progressType == "timed" then
if not state.expirationTime or not state.duration then if not state.expirationTime or not state.duration then
return "" return nil
end end
local remaining = state.expirationTime - GetTime(); local remaining = state.expirationTime - GetTime();
local duration = state.duration; return remaining >= 0 and remaining or nil
local remainingStr = "";
if remaining == math.huge then
remainingStr = " ";
elseif remaining > 60 then
remainingStr = string.format("%i:", math.floor(remaining / 60));
remaining = remaining % 60;
remainingStr = remainingStr..string.format("%02i", remaining);
elseif remaining > 0 then
local progressPrecision = region.progressPrecision and math.abs(region.progressPrecision) or 1
-- remainingStr = remainingStr..string.format("%."..(data.progressPrecision or 1).."f", remaining);
if progressPrecision == 4 and remaining <= 3 then
remainingStr = remainingStr..string.format("%.1f", remaining);
elseif progressPrecision == 5 and remaining <= 3 then
remainingStr = remainingStr..string.format("%.2f", remaining);
elseif (progressPrecision == 4 or progressPrecision == 5) and remaining > 3 then
remainingStr = remainingStr..string.format("%d", remaining);
else
remainingStr = remainingStr..string.format("%.".. progressPrecision .."f", remaining);
end
else
remainingStr = " ";
end
return remainingStr
end end
end,
func = function(remaining, state, progressPrecision)
progressPrecision = progressPrecision or 1
if not state or state.progressType ~= "timed" then
return remaining
end
if type(remaining) ~= "number" then
return ""
end
local remainingStr = "";
if remaining == math.huge then
remainingStr = " ";
elseif remaining > 60 then
remainingStr = string.format("%i:", math.floor(remaining / 60));
remaining = remaining % 60;
remainingStr = remainingStr..string.format("%02i", remaining);
elseif remaining > 0 then
if progressPrecision == 4 and remaining <= 3 then
remainingStr = remainingStr..string.format("%.1f", remaining);
elseif progressPrecision == 5 and remaining <= 3 then
remainingStr = remainingStr..string.format("%.2f", remaining);
elseif progressPrecision == 6 and remaining <= 3 then
remainingStr = remainingStr..string.format("%.3f", remaining);
elseif (progressPrecision == 4 or progressPrecision == 5 or progressPrecision == 6) and remaining > 3 then
remainingStr = remainingStr..string.format("%d", remaining);
else
remainingStr = remainingStr..string.format("%.".. progressPrecision .."f", remaining);
end
else
remainingStr = " ";
end
return remainingStr
end end
}, },
["t"] = { ["t"] = {
func = function(state, region) get = function(state)
if not state then return "" end if not state then return "" end
if state.progressType == "static" then if state.progressType == "static" then
return state.total or "" return state.total, false
end end
if state.progressType == "timed" then if state.progressType == "timed" then
if not state.duration then if not state.duration then
return "" return nil
end end
-- Format a duration time string return state.duration, true
local durationStr = "";
local duration = state.duration
if math.abs(duration) == math.huge or tostring(duration) == "nan" then
durationStr = " ";
elseif duration > 60 then
durationStr = string.format("%i:", math.floor(duration / 60));
duration = duration % 60;
durationStr = durationStr..string.format("%02i", duration);
elseif duration > 0 then
local totalPrecision = region.totalPrecision and math.abs(region.totalPrecision) or 1
if totalPrecision == 4 and duration <= 3 then
durationStr = durationStr..string.format("%.1f", duration);
elseif totalPrecision == 5 and duration <= 3 then
durationStr = durationStr..string.format("%.2f", duration);
elseif (totalPrecision == 4 or totalPrecision == 5) and duration > 3 then
durationStr = durationStr..string.format("%d", duration);
else
durationStr = durationStr..string.format("%."..totalPrecision.."f", duration);
end
else
durationStr = " ";
end
return durationStr
end end
end,
func = function(duration, state, totalPrecision)
if state.progressType ~= "timed" then
return duration
end
if type(duration) ~= "number" then
return ""
end
local durationStr = "";
if math.abs(duration) == math.huge or tostring(duration) == "nan" then
durationStr = " ";
elseif duration > 60 then
durationStr = string.format("%i:", math.floor(duration / 60));
duration = duration % 60;
durationStr = durationStr..string.format("%02i", duration);
elseif duration > 0 then
if totalPrecision == 4 and duration <= 3 then
durationStr = durationStr..string.format("%.1f", duration);
elseif totalPrecision == 5 and duration <= 3 then
durationStr = durationStr..string.format("%.2f", duration);
elseif totalPrecision == 6 and duration <= 3 then
durationStr = durationStr..string.format("%.3f", duration);
elseif (totalPrecision == 4 or totalPrecision == 5 or totalPrecision == 6) and duration > 3 then
durationStr = durationStr..string.format("%d", duration);
else
durationStr = durationStr..string.format("%."..totalPrecision.."f", duration);
end
else
durationStr = " ";
end
return durationStr
end end
}, },
["n"] = { ["n"] = {
func = function(state) get = function(state)
if not state then return "" end return state.name or state.id or "", true
return state.name or state.id end,
func = function(v)
return v
end end
}, },
["i"] = { ["i"] = {
func = function(state) get = function(state)
if not state or not state.icon then return "|TInterface\\Icons\\INV_Misc_QuestionMark:12:12:0:0:64:64:4:60:4:60|t" end return state.icon or "Interface\\Icons\\INV_Misc_QuestionMark"
return "|T".. state.icon ..":12:12:0:0:64:64:4:60:4:60|t" end,
func = function(v)
return "|T".. v ..":12:12:0:0:64:64:4:60:4:60|t"
end end
}, },
["s"] = { ["s"] = {
func = function(state) get = function(state)
if not state or state.stacks == 0 then return "" end if not state or state.stacks == 0 then return "" end
return state.stacks return state.stacks
end,
func = function(v)
return v
end end
} }
}; };
+227 -181
View File
@@ -53,6 +53,11 @@ local properties = {
setter = "Color", setter = "Color",
type = "color", type = "color",
}, },
icon_visible = {
display = L["Icon Visible"],
setter = "SetIconVisible",
type = "bool"
},
icon_color = { icon_color = {
display = L["Icon Color"], display = L["Icon Color"],
setter = "SetIconColor", setter = "SetIconColor",
@@ -552,6 +557,151 @@ local barPrototype = {
["orientation"] = "HORIZONTAL", ["orientation"] = "HORIZONTAL",
} }
local GetRealSize = {
["HORIZONTAL"] = {
[true] = function(self)
return self.totalWidth - self.iconWidth, self.totalHeight
end,
[false] = function(self)
return self.totalWidth, self.totalHeight
end
},
["VERTICAL"] = {
[true] = function(self)
return self.totalWidth, self.totalHeight - self.iconHeight
end,
[false] = function(self)
return self.totalWidth, self.totalHeight
end
},
}
-- Orientation helper methods
local function orientHorizontalInverse(region)
-- Localize
local bar, icon = region.bar, region.icon;
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
bar.GetRealSize = GetRealSize["HORIZONTAL"][region.iconVisible or false]
-- Align icon and bar
if region.iconVisible then
if region.icon_side == "LEFT" then
icon:SetPoint("LEFT", region, "LEFT");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "TOPRIGHT");
else
icon:SetPoint("RIGHT", region, "RIGHT");
bar:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT");
bar:SetPoint("TOPRIGHT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation(region.effectiveOrientation);
end
local function orientHorizontal(region)
-- Localize
local bar, icon = region.bar, region.icon;
bar.GetRealSize = GetRealSize["HORIZONTAL"][region.iconVisible or false]
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
-- Align icon and bar
if region.iconVisible then
if region.icon_side == "LEFT" then
icon:SetPoint("LEFT", region, "LEFT");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "TOPRIGHT");
else
icon:SetPoint("RIGHT", region, "RIGHT");
bar:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT");
bar:SetPoint("TOPRIGHT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation(region.effectiveOrientation);
end
local function orientVerticalInverse(region)
-- Localize
local bar, icon = region.bar, region.icon;
bar.GetRealSize = GetRealSize["VERTICAL"][region.iconVisible or false]
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
-- Align icon and bar
if region.iconVisible then
if region.icon_side == "LEFT" then
icon:SetPoint("TOP", region, "TOP");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "BOTTOMLEFT");
else
icon:SetPoint("BOTTOM", region, "BOTTOM");
bar:SetPoint("TOPRIGHT", region, "TOPRIGHT");
bar:SetPoint("BOTTOMLEFT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation("VERTICAL_INVERSE");
end
local function orientVertical(region)
-- Localize
local bar, icon = region.bar, region.icon;
bar.GetRealSize = GetRealSize["VERTICAL"][region.iconVisible or false]
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
-- Align icon and bar
if region.iconVisible then
if region.icon_side == "LEFT" then
icon:SetPoint("TOP", region, "TOP");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "BOTTOMLEFT");
else
icon:SetPoint("BOTTOM", region, "BOTTOM");
bar:SetPoint("TOPRIGHT", region, "TOPRIGHT");
bar:SetPoint("BOTTOMLEFT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation("VERTICAL");
end
local function GetTexCoordZoom(texWidth)
local texCoord = {texWidth, texWidth, texWidth, 1 - texWidth, 1 - texWidth, texWidth, 1 - texWidth, 1 - texWidth}
return unpack(texCoord)
end
local funcs = { local funcs = {
AnchorSubRegion = function(self, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset) AnchorSubRegion = function(self, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset)
if anchorType == "area" then if anchorType == "area" then
@@ -616,9 +766,11 @@ local funcs = {
end end
end, end,
SetIconColor = function(self, r, g, b, a) SetIconColor = function(self, r, g, b, a)
self.icon_color = {r, g, b, a}
self.icon:SetVertexColor(r, g, b, a); self.icon:SetVertexColor(r, g, b, a);
end, end,
SetIconDesaturated = function(self, b) SetIconDesaturated = function(self, b)
self.desaturateIcon = b
self.icon:SetDesaturated(b); self.icon:SetDesaturated(b);
end, end,
SetBackgroundColor = function (self, r, g, b, a) SetBackgroundColor = function (self, r, g, b, a)
@@ -679,6 +831,38 @@ local funcs = {
self:UpdateEffectiveOrientation() self:UpdateEffectiveOrientation()
self.bar:SetValue(self.bar:GetValue()); self.bar:SetValue(self.bar:GetValue());
end, end,
SetIconVisible = function(self, iconVisible)
if (self.iconVisible == iconVisible) then
return
end
self.iconVisible = iconVisible
local icon = self.icon
if self.iconVisible then
-- Update icon
local iconsize = math.min(self.height, self.width);
icon:SetWidth(iconsize);
icon:SetHeight(iconsize);
self.bar.iconWidth = iconsize
self.bar.iconHeight = iconsize
local texWidth = 0.25 * self.zoom;
icon:SetTexCoord(GetTexCoordZoom(texWidth))
icon:SetDesaturated(self.desaturateIcon);
icon:SetVertexColor(self.icon_color[1], self.icon_color[2], self.icon_color[3], self.icon_color[4]);
-- Update icon visibility
icon:Show();
else
self.bar.iconWidth = 0
self.bar.iconHeight = 0
icon:Hide();
end
self:ReOrient()
self.subRegionEvents:Notify("OrientationChanged")
end,
SetOverlayColor = function(self, id, r, g, b, a) SetOverlayColor = function(self, id, r, g, b, a)
self.bar:SetAdditionalBarColor(id, { r, g, b, a}); self.bar:SetAdditionalBarColor(id, { r, g, b, a});
end, end,
@@ -687,6 +871,42 @@ local funcs = {
end, end,
GetInverse = function(self) GetInverse = function(self)
return self.inverseDirection return self.inverseDirection
end,
ReOrient = function(self)
if self.effectiveOrientation == "HORIZONTAL_INVERSE" then
orientHorizontalInverse(self);
elseif self.effectiveOrientation == "HORIZONTAL" then
orientHorizontal(self);
elseif self.effectiveOrientation == "VERTICAL_INVERSE" then
orientVerticalInverse(self);
elseif self.effectiveOrientation == "VERTICAL" then
orientVertical(self);
end
end,
UpdateEffectiveOrientation = function(self)
local orientation = self.orientation
if self.flipX then
if self.orientation == "HORIZONTAL" then
orientation = "HORIZONTAL_INVERSE"
elseif self.orientation == "HORIZONTAL_INVERSE" then
orientation = "HORIZONTAL"
end
end
if self.flipY then
if self.orientation == "VERTICAL" then
orientation = "VERTICAL_INVERSE"
elseif self.orientation == "VERTICAL_INVERSE" then
orientation = "VERTICAL"
end
end
if orientation ~= self.effectiveOrientation then
self.effectiveOrientation = orientation
self:ReOrient()
end
self.subRegionEvents:Notify("OrientationChanged")
end end
} }
@@ -746,151 +966,6 @@ local function create(parent)
return region; return region;
end end
local GetRealSize = {
["HORIZONTAL"] = {
[true] = function(self)
return self.totalWidth - self.iconWidth, self.totalHeight
end,
[false] = function(self)
return self.totalWidth, self.totalHeight
end
},
["VERTICAL"] = {
[true] = function(self)
return self.totalWidth, self.totalHeight - self.iconHeight
end,
[false] = function(self)
return self.totalWidth, self.totalHeight
end
},
}
-- Orientation helper methods
local function orientHorizontalInverse(region, data)
-- Localize
local bar, icon = region.bar, region.icon;
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
bar.GetRealSize = GetRealSize["HORIZONTAL"][data.icon or false]
-- Align icon and bar
if data.icon then
if data.icon_side == "LEFT" then
icon:SetPoint("LEFT", region, "LEFT");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "TOPRIGHT");
else
icon:SetPoint("RIGHT", region, "RIGHT");
bar:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT");
bar:SetPoint("TOPRIGHT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation(region.effectiveOrientation);
end
local function orientHorizontal(region, data)
-- Localize
local bar, icon = region.bar, region.icon;
bar.GetRealSize = GetRealSize["HORIZONTAL"][data.icon or false]
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
-- Align icon and bar
if data.icon then
if data.icon_side == "LEFT" then
icon:SetPoint("LEFT", region, "LEFT");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "TOPRIGHT");
else
icon:SetPoint("RIGHT", region, "RIGHT");
bar:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT");
bar:SetPoint("TOPRIGHT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation(region.effectiveOrientation);
end
local function orientVerticalInverse(region, data)
-- Localize
local bar, icon = region.bar, region.icon;
bar.GetRealSize = GetRealSize["VERTICAL"][data.icon or false]
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
-- Align icon and bar
if data.icon then
if data.icon_side == "LEFT" then
icon:SetPoint("TOP", region, "TOP");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "BOTTOMLEFT");
else
icon:SetPoint("BOTTOM", region, "BOTTOM");
bar:SetPoint("TOPRIGHT", region, "TOPRIGHT");
bar:SetPoint("BOTTOMLEFT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation("VERTICAL_INVERSE");
end
local function orientVertical(region, data)
-- Localize
local bar, icon = region.bar, region.icon;
bar.GetRealSize = GetRealSize["VERTICAL"][data.icon or false]
-- Reset
icon:ClearAllPoints();
bar:ClearAllPoints();
-- Align icon and bar
if data.icon then
if data.icon_side == "LEFT" then
icon:SetPoint("TOP", region, "TOP");
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", icon, "BOTTOMLEFT");
else
icon:SetPoint("BOTTOM", region, "BOTTOM");
bar:SetPoint("TOPRIGHT", region, "TOPRIGHT");
bar:SetPoint("BOTTOMLEFT", icon, "TOPLEFT");
end
else
bar:SetPoint("BOTTOMRIGHT", region, "BOTTOMRIGHT");
bar:SetPoint("TOPLEFT", region, "TOPLEFT");
end
-- Save orientation
bar:SetOrientation("VERTICAL");
end
local function GetTexCoordZoom(texWidth)
local texCoord = {texWidth, texWidth, texWidth, 1 - texWidth, 1 - texWidth, texWidth, 1 - texWidth, 1 - texWidth}
return unpack(texCoord)
end
local function TimerTick(self) local function TimerTick(self)
local state = self.state local state = self.state
local duration = state.duration or 0 local duration = state.duration or 0
@@ -927,6 +1002,11 @@ local function modify(parent, region, data)
region.effectiveOrientation = nil region.effectiveOrientation = nil
region.overlayclip = data.overlayclip; region.overlayclip = data.overlayclip;
region.iconVisible = data.icon
region.icon_side = data.icon_side
region.icon_color = CopyTable(data.icon_color)
region.desaturateIcon = data.desaturate
region.zoom = data.zoom
region.overlays = {}; region.overlays = {};
if (data.overlays) then if (data.overlays) then
@@ -938,7 +1018,7 @@ local function modify(parent, region, data)
bar:SetStatusBarTexture(texturePath); bar:SetStatusBarTexture(texturePath);
bar:SetBackgroundColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); bar:SetBackgroundColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]);
-- Update spark settings -- Update spark settings
WeakAuras.SetTexture(bar.spark, data.sparkTexture); bar.spark:SetTexture(data.sparkTexture);
bar.spark:SetVertexColor(data.sparkColor[1], data.sparkColor[2], data.sparkColor[3], data.sparkColor[4]); bar.spark:SetVertexColor(data.sparkColor[1], data.sparkColor[2], data.sparkColor[3], data.sparkColor[4]);
bar.spark:SetWidth(data.sparkWidth); bar.spark:SetWidth(data.sparkWidth);
bar.spark:SetHeight(data.sparkHeight); bar.spark:SetHeight(data.sparkHeight);
@@ -977,7 +1057,7 @@ local function modify(parent, region, data)
local textDegrees = data.rotateText == "LEFT" and 90 or data.rotateText == "RIGHT" and -90 or 0; local textDegrees = data.rotateText == "LEFT" and 90 or data.rotateText == "RIGHT" and -90 or 0;
-- Update icon visibility -- Update icon visibility
if data.icon then if region.iconVisible then
-- Update icon -- Update icon
local iconsize = math.min(region.height, region.width); local iconsize = math.min(region.height, region.width);
icon:SetWidth(iconsize); icon:SetWidth(iconsize);
@@ -999,40 +1079,6 @@ local function modify(parent, region, data)
region.inverseDirection = data.inverse; region.inverseDirection = data.inverse;
region.UpdateEffectiveOrientation = function()
local orientation = region.orientation
if region.flipX then
if region.orientation == "HORIZONTAL" then
orientation = "HORIZONTAL_INVERSE"
elseif region.orientation == "HORIZONTAL_INVERSE" then
orientation = "HORIZONTAL"
end
end
if region.flipY then
if region.orientation == "VERTICAL" then
orientation = "VERTICAL_INVERSE"
elseif region.orientation == "VERTICAL_INVERSE" then
orientation = "VERTICAL"
end
end
if orientation ~= region.effectiveOrientation then
region.effectiveOrientation = orientation
if region.effectiveOrientation == "HORIZONTAL_INVERSE" then
orientHorizontalInverse(region, data);
elseif region.effectiveOrientation == "HORIZONTAL" then
orientHorizontal(region, data);
elseif region.effectiveOrientation == "VERTICAL_INVERSE" then
orientVerticalInverse(region, data);
elseif region.effectiveOrientation == "VERTICAL" then
orientVertical(region, data);
end
end
region.subRegionEvents:Notify("OrientationChanged")
end
-- Apply orientation alignment -- Apply orientation alignment
region:UpdateEffectiveOrientation() region:UpdateEffectiveOrientation()
+18 -6
View File
@@ -117,7 +117,7 @@ local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ce
function WeakAuras.GetAnchorsForData(parentData, type) function WeakAuras.GetAnchorsForData(parentData, type)
local result local result
if not parentData.controlledChildren then if not parentData.controlledChildren then
if not WeakAuras.regionOptions[parentData.regionType].getAnchors then if not WeakAuras.regionOptions[parentData.regionType] or not WeakAuras.regionOptions[parentData.regionType].getAnchors then
return return
end end
@@ -258,7 +258,7 @@ local function SendChat(self, options)
if (not options or WeakAuras.IsOptionsOpen()) then if (not options or WeakAuras.IsOptionsOpen()) then
return return
end end
WeakAuras.HandleChatAction(options.message_type, options.message, options.message_dest, options.message_channel, options.r, options.g, options.b, self, options.message_custom); WeakAuras.HandleChatAction(options.message_type, options.message, options.message_dest, options.message_channel, options.r, options.g, options.b, self, options.message_custom, nil, options.message_formaters);
end end
local function RunCode(self, func) local function RunCode(self, func)
@@ -532,6 +532,22 @@ function WeakAuras.regionPrototype.modify(parent, region, data)
WeakAuras.AnchorFrame(data, region, parent); WeakAuras.AnchorFrame(data, region, parent);
end end
end end
region.startFormatters = WeakAuras.CreateFormatters(data.actions.start.message, function(key, default)
local fullKey = "message_format_" .. key
if data.actions.start[fullKey] == nil then
data.actions.start[fullKey] = default
end
return data.actions.start[fullKey]
end)
region.finishFormatters = WeakAuras.CreateFormatters(data.actions.finish.message, function(key, default)
local fullKey = "message_format_" .. key
if data.actions.finish[fullKey] == nil then
data.actions.finish[fullKey] = default
end
return data.actions.finish[fullKey]
end)
end end
function WeakAuras.regionPrototype.modifyFinish(parent, region, data) function WeakAuras.regionPrototype.modifyFinish(parent, region, data)
@@ -849,7 +865,3 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare
function region:Expand() end function region:Expand() end
end end
end end
function WeakAuras.SetTexture(texture, path, wrapModeH, wrapModeV)
texture:SetTexture(path, wrapModeH, wrapModeV);
end
+9 -4
View File
@@ -6,7 +6,6 @@ local L = WeakAuras.L;
local defaultFont = WeakAuras.defaultFont local defaultFont = WeakAuras.defaultFont
local defaultFontSize = WeakAuras.defaultFontSize local defaultFontSize = WeakAuras.defaultFontSize
local default = { local default = {
displayText = "%p", displayText = "%p",
outline = "OUTLINE", outline = "OUTLINE",
@@ -76,8 +75,6 @@ local function modify(parent, region, data)
local text = region.text; local text = region.text;
region.useAuto = WeakAuras.CanHaveAuto(data); region.useAuto = WeakAuras.CanHaveAuto(data);
region.progressPrecision = data.progressPrecision;
region.totalPrecision = data.totalPrecision;
local fontPath = SharedMedia:Fetch("font", data.font); local fontPath = SharedMedia:Fetch("font", data.font);
text:SetFont(fontPath, data.fontSize, data.outline); text:SetFont(fontPath, data.fontSize, data.outline);
@@ -161,9 +158,17 @@ local function modify(parent, region, data)
local UpdateText local UpdateText
if WeakAuras.ContainsAnyPlaceHolders(data.displayText) then if WeakAuras.ContainsAnyPlaceHolders(data.displayText) then
local getter = function(key, default)
local fullKey = "displayText_format_" .. key
if (data[fullKey] == nil) then
data[fullKey] = default
end
return data[fullKey]
end
local formatters = WeakAuras.CreateFormatters(data.displayText, getter)
UpdateText = function() UpdateText = function()
local textStr = data.displayText; local textStr = data.displayText;
textStr = WeakAuras.ReplacePlaceHolders(textStr, region, nil); textStr = WeakAuras.ReplacePlaceHolders(textStr, region, nil, false, formatters);
if (textStr == nil or textStr == "") then if (textStr == nil or textStr == "") then
textStr = " "; textStr = " ";
end end
+2 -2
View File
@@ -86,7 +86,7 @@ end
local function modify(parent, region, data) local function modify(parent, region, data)
WeakAuras.regionPrototype.modify(parent, region, data); WeakAuras.regionPrototype.modify(parent, region, data);
WeakAuras.SetTexture(region.texture, data.texture); region.texture:SetTexture(data.texture);
region.texture:SetDesaturated(data.desaturate) region.texture:SetDesaturated(data.desaturate)
region:SetWidth(data.width); region:SetWidth(data.width);
region:SetHeight(data.height); region:SetHeight(data.height);
@@ -182,7 +182,7 @@ local function modify(parent, region, data)
function region:Update() function region:Update()
if region.state.texture then if region.state.texture then
WeakAuras.SetTexture(region.texture, region.state.texture); region.texture:SetTexture(region.state.texture);
end end
end end
+9 -7
View File
@@ -225,12 +225,6 @@ local function modify(parent, region, parentData, data, first)
end end
if first then if first then
-- Certain data is stored directly on the parent, because it's shared between multiple texts
-- And shared by other code paths e.g. SendChatMessage
-- That is partly for legacy reasons
parent.progressPrecision = parentData.progressPrecision
parent.totalPrecision = parentData.totalPrecision
local containsCustomText = false local containsCustomText = false
for index, subRegion in ipairs(parentData.subRegions) do for index, subRegion in ipairs(parentData.subRegions) do
if subRegion.type == "subtext" and WeakAuras.ContainsCustomPlaceHolder(subRegion.text_text) then if subRegion.type == "subtext" and WeakAuras.ContainsCustomPlaceHolder(subRegion.text_text) then
@@ -249,9 +243,17 @@ local function modify(parent, region, parentData, data, first)
local UpdateText local UpdateText
if data.text_text and WeakAuras.ContainsAnyPlaceHolders(data.text_text) then if data.text_text and WeakAuras.ContainsAnyPlaceHolders(data.text_text) then
local getter = function(key, default)
local fullKey = "text_text_format_" .. key
if data[fullKey] == nil then
data[fullKey] = default
end
return data[fullKey]
end
local formatters = WeakAuras.CreateFormatters(data.text_text, getter)
UpdateText = function() UpdateText = function()
local textStr = data.text_text or "" local textStr = data.text_text or ""
textStr = WeakAuras.ReplacePlaceHolders(textStr, parent, nil) textStr = WeakAuras.ReplacePlaceHolders(textStr, parent, nil, false, formatters)
if text:GetFont() then if text:GetFont() then
text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr)) text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr))
+3
View File
@@ -1175,6 +1175,9 @@ local function findMatch(data, children)
if old.uid ~= new.uid then if old.uid ~= new.uid then
return return
else else
if (children == nil) ~= (old.controlledChildren == nil) then
return
end
return true return true
end end
else else
+488 -25
View File
@@ -68,10 +68,492 @@ WeakAuras.precision_types = {
[1] = "12.3", [1] = "12.3",
[2] = "12.34", [2] = "12.34",
[3] = "12.345", [3] = "12.345",
[4] = "Dynamic 12.3", -- will show 1 digit precision when time is lower than 3 seconds, hardcoded
[5] = "Dynamic 12.34" -- will show 2 digits precision when time is lower than 3 seconds, hardcoded
} }
WeakAuras.big_number_types = {
["AbbreviateNumbers"] = L["AbbreviateNumbers (Blizzard)"],
["AbbreviateLargeNumbers"] = L["AbbreviateLargeNumbers (Blizzard)"]
}
WeakAuras.round_types = {
floor = L["Floor"],
ceil = L["Ceil"],
round = L["Round"]
}
WeakAuras.unit_color_types = {
none = L["None"],
class = L["Class"]
}
WeakAuras.unit_realm_name_types = {
never = L["Never"],
star = L["* Suffix"],
differentServer = L["Only if on a different realm"],
always = L["Always include realm"]
}
local simpleFormatters = {
--[[
AbbreviateNumbers = function(value, state)
return (type(value) == "number") and AbbreviateNumbers(value) or value
end,
AbbreviateLargeNumbers = function(value, state)
return (type(value) == "number") and AbbreviateLargeNumbers(Round(value)) or value
end,
]]
floor = function(value)
return (type(value) == "number") and floor(value) or value
end,
ceil = function(value)
return (type(value) == "number") and ceil(value) or value
end,
round = function(value)
return (type(value) == "number") and Round(value) or value
end
}
WeakAuras.format_types = {
none = {
display = L["None"],
AddOptions = function() end,
CreateFormatter = function() end
},
timed = {
display = L["Time Format"],
AddOptions = function(symbol, hidden, addOption, get)
addOption(symbol .. "_time_precision", {
type = "select",
name = L["Precision"],
width = WeakAuras.normalWidth,
values = WeakAuras.precision_types,
hidden = hidden
})
addOption(symbol .. "_time_dynamic", {
type = "toggle",
name = L["Dynamic"],
desc = L["Increased Precision below 3s"],
width = WeakAuras.normalWidth,
hidden = hidden,
disabled = function() return get(symbol .. "_time_precision") == 0 end
})
end,
CreateFormatter = function(symbol, get)
local precision = get(symbol .. "_time_precision", 1)
local dynamic = get(symbol .. "_time_dynamic", false)
if dynamic then
if precision == 1 or precision == 2 or precision == 3 then
precision = precision + 3
end
end
return function(value, state)
return WeakAuras.dynamic_texts.p.func(value, state, precision)
end
end
},
--[[
BigNumber = {
display = L["Big Number"],
AddOptions = function(symbol, hidden, addOption)
addOption(symbol .. "_big_number_format", {
type = "select",
name = L["Format"],
width = WeakAuras.normalWidth,
values = WeakAuras.big_number_types,
hidden = hidden
})
end,
CreateFormatter = function(symbol, get)
local format = get(symbol .. "_big_number_format", "AbbreviateNumbers")
if (format == "AbbreviateNumbers") then
return simpleFormatters.AbbreviateNumbers
end
return simpleFormatters.AbbreviateLargeNumbers
end
},
]]
Number = {
display = L["Number"],
AddOptions = function(symbol, hidden, addOption, get)
addOption(symbol .. "_decimal_precision", {
type = "select",
name = L["Precision"],
width = WeakAuras.normalWidth,
values = WeakAuras.precision_types,
hidden = hidden
})
addOption(symbol .. "_round_type", {
type = "select",
name = L["Round Mode"],
width = WeakAuras.normalWidth,
values = WeakAuras.round_types,
hidden = hidden,
disabled = function()
return get(symbol .. "_decimal_precision") ~= 0
end
})
end,
CreateFormatter = function(symbol, get)
local precision = get(symbol .. "_decimal_precision", 1)
if precision == 0 then
local type = get(symbol .. "_round_type", "floor")
return simpleFormatters[type]
else
local format = "%." .. precision .. "f"
return function(value)
return (type(value) == "number") and string.format(format, value) or value
end
end
end
},
Unit = {
display = L["Formats |cFFFF0000%unit|r"],
AddOptions = function(symbol, hidden, addOption, get)
addOption(symbol .. "_color", {
type = "select",
name = L["Color"],
width = WeakAuras.normalWidth,
values = WeakAuras.unit_color_types,
hidden = hidden,
})
addOption(symbol .. "_realm_name", {
type = "select",
name = L["Realm Name"],
width = WeakAuras.normalWidth,
values = WeakAuras.unit_realm_name_types,
hidden = hidden,
})
addOption(symbol .. "_abbreviate", {
type = "toggle",
name = L["Abbreviate"],
width = WeakAuras.normalWidth,
hidden = hidden,
})
addOption(symbol .. "_abbreviate_max", {
type = "range",
name = L["Max Char "],
width = WeakAuras.normalWidth,
hidden = hidden,
min = 1,
max = 20,
hidden = hidden,
disabled = function()
return not get(symbol .. "_abbreviate")
end
})
end,
CreateFormatter = function(symbol, get)
local color = get(symbol .. "_color", true)
local realm = get(symbol .. "_realm_name", "never")
local abbreviate = get(symbol .. "_abbreviate", false)
local abbreviateMax = get(symbol .. "_abbreviate_max", 8)
local nameFunc
local colorFunc
local abbreviateFunc
if color == "class" then
colorFunc = function(unit, text)
if UnitPlayerControlled(unit) then
return GetClassColoredTextForUnit(unit, text)
end
return text
end
end
if realm == "never" then
nameFunc = UnitName
elseif realm == "star" then
nameFunc = function(unit)
local name, realm = UnitName(unit)
if realm then
return name .. "*"
end
return name
end
elseif realm == "differentServer" then
nameFunc = function(unit)
local name, realm = UnitName(unit)
if realm then
return name .. "-" .. realm
end
return name
end
elseif realm == "always" then
nameFunc = function(unit)
local name, realm = WeakAuras.UnitNameWithRealm(unit)
return name .. "-" .. realm
end
end
if abbreviate then
abbreviateFunc = function(input)
return WeakAuras.WA_Utf8Sub(input, abbreviateMax)
end
end
-- Do the checks on what is necessary here instead of inside the returned
-- formatter
if colorFunc then
if abbreviateFunc then
return function(unit)
local name = abbreviateFunc(nameFunc(unit))
return colorFunc(unit, name)
end
else
return function(unit)
local name = nameFunc(unit)
return colorFunc(unit, name)
end
end
else
if abbreviateFunc then
return function(unit)
local name = nameFunc(unit)
return abbreviateFunc(name)
end
else
return nameFunc
end
end
end
},
guid = {
display = L["Formats Player's |cFFFF0000%guid|r"],
AddOptions = function(symbol, hidden, addOption, get)
addOption(symbol .. "_color", {
type = "select",
name = L["Color"],
width = WeakAuras.normalWidth,
values = WeakAuras.unit_color_types,
hidden = hidden,
})
addOption(symbol .. "_realm_name", {
type = "select",
name = L["Realm Name"],
width = WeakAuras.normalWidth,
values = WeakAuras.unit_realm_name_types,
hidden = hidden,
})
addOption(symbol .. "_abbreviate", {
type = "toggle",
name = L["Abbreviate"],
width = WeakAuras.normalWidth,
hidden = hidden,
})
addOption(symbol .. "_abbreviate_max", {
type = "range",
name = L["Max Char "],
width = WeakAuras.normalWidth,
hidden = hidden,
min = 1,
max = 20,
hidden = hidden,
disabled = function()
return not get(symbol .. "_abbreviate")
end
})
end,
CreateFormatter = function(symbol, get)
local color = get(symbol .. "_color", true)
local realm = get(symbol .. "_realm_name", "never")
local abbreviate = get(symbol .. "_abbreviate", false)
local abbreviateMax = get(symbol .. "_abbreviate_max", 8)
local nameFunc
local colorFunc
local abbreviateFunc
if color == "class" then
colorFunc = function(class, text)
local color = RAID_CLASS_COLORS[class]
if color then
return string.format("|c%s%s|r", string.format("ff%.2x%.2x%.2x", color.r * 255, color.g * 255, color.b * 255), text)
else
return text
end
end
end
if realm == "never" then
nameFunc = function(name, realm)
return name
end
elseif realm == "star" then
nameFunc = function(name, realm)
if realm ~= "" then
return name .. "*"
end
return name
end
elseif realm == "differentServer" then
nameFunc = function(name, realm)
if realm ~= "" then
return name .. "-" .. realm
end
return name
end
elseif realm == "always" then
nameFunc = function(name, realm)
if realm == "" then
realm = select(2, WeakAuras.UnitNameWithRealm("player"))
end
return name .. "-" .. realm
end
end
if abbreviate then
abbreviateFunc = function(input)
return WeakAuras.WA_Utf8Sub(input, abbreviateMax)
end
end
-- Do the checks on what is necessary here instead of inside the returned
-- formatter
if colorFunc then
if abbreviateFunc then
return function(guid)
local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid)
if ok then
local name = abbreviateFunc(nameFunc(name, realm))
return colorFunc(class, name)
end
end
else
return function(guid)
local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid)
if ok then
return colorFunc(class, nameFunc(name, realm))
end
end
end
else
if abbreviateFunc then
return function(guid)
local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid)
if ok then
return abbreviateFunc(nameFunc(name, realm))
end
end
else
return function(guid)
local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid)
if ok then
return nameFunc(name, realm)
end
end
end
end
end
},
GCDTime = {
display = L["Time in GCDs"],
AddOptions = function(symbol, hidden, addOption, get)
addOption(symbol .. "_gcd_gcd", {
type = "toggle",
name = L["Subtract GCD"],
width = WeakAuras.normalWidth,
hidden = hidden
})
addOption(symbol .. "_gcd_cast", {
type = "toggle",
name = L["Subtract Cast"],
width = WeakAuras.normalWidth,
hidden = hidden
})
addOption(symbol .. "_gcd_channel", {
type = "toggle",
name = L["Subtract Channel"],
width = WeakAuras.normalWidth,
hidden = hidden
})
addOption(symbol .. "_gcd_hide_zero", {
type = "toggle",
name = L["Hide 0 cooldowns"],
width = WeakAuras.normalWidth,
hidden = hidden
})
addOption(symbol .. "_decimal_precision", {
type = "select",
name = L["Precision"],
width = WeakAuras.normalWidth,
values = WeakAuras.precision_types,
hidden = hidden
})
addOption(symbol .. "_round_type", {
type = "select",
name = L["Round Mode"],
width = WeakAuras.normalWidth,
values = WeakAuras.round_types,
hidden = hidden,
disabled = function()
return get(symbol .. "_decimal_precision") ~= 0
end
})
end,
CreateFormatter = function(symbol, get)
local gcd = get(symbol .. "_gcd_gcd", true)
local cast = get(symbol .. "_gcd_cast", false)
local channel = get(symbol .. "_gcd_channel", false)
local hideZero = get(symbol .. "_gcd_hide_zero", false)
local precision = get(symbol .. "_decimal_precision", 1)
local numberToStringFunc
if precision ~= 0 then
local format = "%." .. precision .. "f"
numberToStringFunc = function(number)
return string.format(format, number)
end
else
local type = get(symbol .. "_round_type", "ceil")
numberToStringFunc = simpleFormatters[type]
end
return function(value, state)
if state.progressType ~= "timed" or type(value) ~= "number" then
return value
end
WeakAuras.WatchGCD()
local result = value
local now = GetTime()
if gcd then
local gcdDuration, gcdExpirationTime = WeakAuras.GetGCDInfo()
if gcdDuration ~= 0 then
result = now + value - gcdExpirationTime
end
end
if cast then
local _, _, _, _, endTime = UnitCastingInfo("player")
local castExpirationTIme = endTime and endTime > 0 and (endTime / 1000) or 0
if castExpirationTIme > 0 then
result = min(result, now + value - castExpirationTIme)
end
end
if channel then
local _, _, _, _, endTime = UnitChannelInfo("player")
local castExpirationTIme = endTime and endTime > 0 and (endTime / 1000) or 0
if castExpirationTIme > 0 then
result = min(result, now + value - castExpirationTIme)
end
end
if result <= 0 then
return hideZero and "" or "0"
end
return numberToStringFunc(result / WeakAuras.CalculatedGcdDuration())
end
end
}
}
WeakAuras.format_types_display = {}
for k, v in pairs(WeakAuras.format_types) do WeakAuras.format_types_display[k] = v.display end
WeakAuras.sound_channel_types = { WeakAuras.sound_channel_types = {
Master = L["Master"], Master = L["Master"],
SFX = ENABLE_SOUNDFX, SFX = ENABLE_SOUNDFX,
@@ -510,28 +992,6 @@ WeakAuras.orientation_with_circle_types = {
ANTICLOCKWISE = L["Anticlockwise"] ANTICLOCKWISE = L["Anticlockwise"]
} }
-- TODO
WeakAuras.spec_types = {
[1] = "SPECIALIZATION".." 1",
[2] = "SPECIALIZATION".." 2",
[3] = "SPECIALIZATION".." 3",
[4] = "SPECIALIZATION".." 4"
}
WeakAuras.spec_types_3 = {
[1] = "SPECIALIZATION".." 1",
[2] = "SPECIALIZATION".." 2",
[3] = "SPECIALIZATION".." 3"
}
WeakAuras.spec_types_2 = {
[1] = "SPECIALIZATION".." 1",
[2] = "SPECIALIZATION".." 2"
}
WeakAuras.spec_types_specific = {}
WeakAuras.spec_types_all = {}
WeakAuras.talent_types = {} WeakAuras.talent_types = {}
for tab = 1, 5 do for tab = 1, 5 do
for num_talent = 1, MAX_NUM_TALENTS do for num_talent = 1, MAX_NUM_TALENTS do
@@ -1961,9 +2421,12 @@ WeakAuras.multiUnitUnits.party["player"] = true
for i = 1, 4 do for i = 1, 4 do
WeakAuras.baseUnitId["party"..i] = true WeakAuras.baseUnitId["party"..i] = true
WeakAuras.baseUnitId["partypet"..i] = true WeakAuras.baseUnitId["partypet"..i] = true
WeakAuras.baseUnitId["boss"..i] = true
WeakAuras.multiUnitUnits.group["party"..i] = true WeakAuras.multiUnitUnits.group["party"..i] = true
WeakAuras.multiUnitUnits.party["party"..i] = true WeakAuras.multiUnitUnits.party["party"..i] = true
end
for i = 1, MAX_BOSS_FRAMES do
WeakAuras.baseUnitId["boss"..i] = true
WeakAuras.multiUnitUnits.boss["boss"..i] = true WeakAuras.multiUnitUnits.boss["boss"..i] = true
end end
+424 -45
View File
@@ -1,4 +1,4 @@
local internalVersion = 29; local internalVersion = 32;
-- Lua APIs -- Lua APIs
local insert = table.insert local insert = table.insert
@@ -320,6 +320,12 @@ WeakAuras.customActionsFunctions = {};
-- Custom Functions used in conditions, keyed on id, condition number, "changes", property number -- Custom Functions used in conditions, keyed on id, condition number, "changes", property number
WeakAuras.customConditionsFunctions = {}; WeakAuras.customConditionsFunctions = {};
-- Text format functions for chat messages, keyed on id, condition number, changes, property number
WeakAuras.conditionTextFormatters = {}
-- Helpers for conditions, that is custom run functions and preamble objects for built in checks
-- keyed on UID not on id!
WeakAuras.conditionHelpers = {}
local anim_function_strings = WeakAuras.anim_function_strings; local anim_function_strings = WeakAuras.anim_function_strings;
local anim_presets = WeakAuras.anim_presets; local anim_presets = WeakAuras.anim_presets;
@@ -580,6 +586,7 @@ function WeakAuras.ConstructFunction(prototype, trigger, skipOptional)
local debug = {}; local debug = {};
local events = {} local events = {}
local init; local init;
local preambles = ""
if(prototype.init) then if(prototype.init) then
init = prototype.init(trigger); init = prototype.init(trigger);
else else
@@ -682,10 +689,16 @@ function WeakAuras.ConstructFunction(prototype, trigger, skipOptional)
end end
test = "("..name..(trigger[name.."_operator"] or "==")..(number or "[["..(trigger[name] or "").."]]")..")"; test = "("..name..(trigger[name.."_operator"] or "==")..(number or "[["..(trigger[name] or "").."]]")..")";
end end
if(arg.required) then if (arg.preamble) then
tinsert(required, test); preambles = preambles .. arg.preamble:format(trigger[name]) .. "\n"
else end
tinsert(tests, test);
if test ~= "(test)" then
if(arg.required) then
tinsert(required, test);
else
tinsert(tests, test);
end
end end
if test and arg.events then if test and arg.events then
@@ -702,7 +715,7 @@ function WeakAuras.ConstructFunction(prototype, trigger, skipOptional)
end end
end end
local ret = "return function("..table.concat(input, ", ")..")\n"; local ret = preambles .. "return function("..table.concat(input, ", ")..")\n";
ret = ret..(init or ""); ret = ret..(init or "");
ret = ret..(#debug > 0 and table.concat(debug, "\n") or ""); ret = ret..(#debug > 0 and table.concat(debug, "\n") or "");
ret = ret.."if("; ret = ret.."if(";
@@ -722,7 +735,7 @@ function WeakAuras.GetActiveConditions(id, cloneId)
return triggerState[id].activatedConditions[cloneId]; return triggerState[id].activatedConditions[cloneId];
end end
local function formatValueForAssignment(vType, value, pathToCustomFunction) local function formatValueForAssignment(vType, value, pathToCustomFunction, pathToFormatters)
if (value == nil) then if (value == nil) then
value = false; value = false;
end end
@@ -739,10 +752,12 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction)
return "{1, 1, 1, 1}"; return "{1, 1, 1, 1}";
elseif(vType == "chat") then elseif(vType == "chat") then
if (value and type(value) == "table") then if (value and type(value) == "table") then
return string.format("{message_type = %q, message = %q, message_dest = %q, message_channel = %q, message_custom = %s}", local serialized = string.format("{message_type = %q, message = %q, message_dest = %q, message_channel = %q, message_custom = %s, message_formaters = %s}",
tostring(value.message_type), tostring(value.message or ""), tostring(value.message_type), tostring(value.message or ""),
tostring(value.message_dest), tostring(value.message_channel), tostring(value.message_dest), tostring(value.message_channel),
pathToCustomFunction); pathToCustomFunction,
pathToFormatters)
return serialized
end end
elseif(vType == "sound") then elseif(vType == "sound") then
if (value and type(value) == "table") then if (value and type(value) == "table") then
@@ -822,10 +837,8 @@ function WeakAuras.scheduleConditionCheck(time, id, cloneId)
end end
end end
local customConditionTestFunctions = {}; function WeakAuras.CallCustomConditionTest(uid, testFunctionNumber, ...)
local ok, result = pcall(WeakAuras.conditionHelpers[uid].customTestFunctions[testFunctionNumber], ...)
function WeakAuras.CallCustomConditionTest(testFunctionNumber, ...)
local ok, result = pcall(customConditionTestFunctions[testFunctionNumber], ...)
if not ok then if not ok then
geterrorhandler()(result) geterrorhandler()(result)
elseif (ok) then elseif (ok) then
@@ -833,7 +846,7 @@ function WeakAuras.CallCustomConditionTest(testFunctionNumber, ...)
end end
end end
local function CreateTestForCondition(input, allConditionsTemplate, usedStates) local function CreateTestForCondition(uid, input, allConditionsTemplate, usedStates)
local trigger = input and input.trigger; local trigger = input and input.trigger;
local variable = input and input.variable; local variable = input and input.variable;
local op = input and input.op; local op = input and input.op;
@@ -846,7 +859,7 @@ local function CreateTestForCondition(input, allConditionsTemplate, usedStates)
local test = {}; local test = {};
if (input.checks) then if (input.checks) then
for i, subcheck in ipairs(input.checks) do for i, subcheck in ipairs(input.checks) do
local subtest, subrecheckCode = CreateTestForCondition(subcheck, allConditionsTemplate, usedStates); local subtest, subrecheckCode = CreateTestForCondition(uid, subcheck, allConditionsTemplate, usedStates);
if (subtest) then if (subtest) then
tinsert(test, "(" .. subtest .. ")"); tinsert(test, "(" .. subtest .. ")");
end end
@@ -871,16 +884,31 @@ local function CreateTestForCondition(input, allConditionsTemplate, usedStates)
local conditionTemplate = allConditionsTemplate[trigger] and allConditionsTemplate[trigger][variable]; local conditionTemplate = allConditionsTemplate[trigger] and allConditionsTemplate[trigger][variable];
local cType = conditionTemplate and conditionTemplate.type; local cType = conditionTemplate and conditionTemplate.type;
local test = conditionTemplate and conditionTemplate.test; local test = conditionTemplate and conditionTemplate.test;
local preamble = conditionTemplate and conditionTemplate.preamble;
local stateCheck = "state[" .. trigger .. "] and state[" .. trigger .. "].show and "; local stateCheck = "state[" .. trigger .. "] and state[" .. trigger .. "].show and ";
local stateVariableCheck = "state[" .. trigger .. "]." .. variable .. "~= nil and "; local stateVariableCheck = "state[" .. trigger .. "]." .. variable .. "~= nil and ";
local preambleString
if preamble then
WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {}
WeakAuras.conditionHelpers[uid].preambles = WeakAuras.conditionHelpers[uid].preambles or {}
tinsert(WeakAuras.conditionHelpers[uid].preambles, preamble(value));
local preambleNumber = #WeakAuras.conditionHelpers[uid].preambles
preambleString = string.format("WeakAuras.conditionHelpers[%q].preambles[%s]", uid, preambleNumber)
end
if (test) then if (test) then
if (value) then if (value) then
tinsert(customConditionTestFunctions, test); WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {}
local testFunctionNumber = #(customConditionTestFunctions); WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {}
local valueString = type(value) == "string" and "[[" .. value .. "]]" or value; tinsert(WeakAuras.conditionHelpers[uid].customTestFunctions, test);
local opString = type(op) == "string" and "[[" .. op .. "]]" or op; local testFunctionNumber = #(WeakAuras.conditionHelpers[uid].customTestFunctions);
check = "state and WeakAuras.CallCustomConditionTest(" .. testFunctionNumber .. ", state[" .. trigger .. "], " .. valueString .. ", " .. (opString or "nil") .. ")"; local valueString = type(value) == "string" and string.format("%q", value) or value;
local opString = type(op) == "string" and string.format("%q", op) or op;
check = string.format("state and WeakAuras.CallCustomConditionTest(%q, %s, state[%s], %s, %s, %s)",
uid, testFunctionNumber, trigger, valueString, (opString or "nil"), preambleString or "nil");
end end
elseif (cType == "number" and op) then elseif (cType == "number" and op) then
local v = tonumber(value) local v = tonumber(value)
@@ -923,9 +951,9 @@ local function CreateTestForCondition(input, allConditionsTemplate, usedStates)
return check, recheckCode; return check, recheckCode;
end end
local function CreateCheckCondition(ret, condition, conditionNumber, allConditionsTemplate, debug) local function CreateCheckCondition(uid, ret, condition, conditionNumber, allConditionsTemplate, debug)
local usedStates = {}; local usedStates = {};
local check, recheckCode = CreateTestForCondition(condition.check, allConditionsTemplate, usedStates); local check, recheckCode = CreateTestForCondition(uid, condition.check, allConditionsTemplate, usedStates);
if (check) then if (check) then
ret = ret .. " state = region.states\n" ret = ret .. " state = region.states\n"
ret = ret .. " if (" .. check .. ") then\n"; ret = ret .. " if (" .. check .. ") then\n";
@@ -1005,14 +1033,21 @@ local function CreateActivateCondition(ret, id, condition, conditionNumber, prop
if (debug) then ret = ret .. " print('- " .. change.property .. " " .. formatValueForAssignment(propertyData.type, change.value) .. "')\n"; end if (debug) then ret = ret .. " print('- " .. change.property .. " " .. formatValueForAssignment(propertyData.type, change.value) .. "')\n"; end
elseif (propertyData.action) then elseif (propertyData.action) then
local pathToCustomFunction = "nil"; local pathToCustomFunction = "nil";
local pathToFormatter = "nil"
if (WeakAuras.customConditionsFunctions[id] if (WeakAuras.customConditionsFunctions[id]
and WeakAuras.customConditionsFunctions[id][conditionNumber] and WeakAuras.customConditionsFunctions[id][conditionNumber]
and WeakAuras.customConditionsFunctions[id][conditionNumber].changes and WeakAuras.customConditionsFunctions[id][conditionNumber].changes
and WeakAuras.customConditionsFunctions[id][conditionNumber].changes[changeNum]) then and WeakAuras.customConditionsFunctions[id][conditionNumber].changes[changeNum]) then
pathToCustomFunction = string.format("WeakAuras.customConditionsFunctions[%q][%s].changes[%s]", id, conditionNumber, changeNum); pathToCustomFunction = string.format("WeakAuras.customConditionsFunctions[%q][%s].changes[%s]", id, conditionNumber, changeNum);
end end
ret = ret .. " region:" .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction) .. ")" .. "\n"; if WeakAuras.conditionTextFormatters[id]
if (debug) then ret = ret .. " print('# " .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction) .. "')\n"; end and WeakAuras.conditionTextFormatters[id][conditionNumber]
and WeakAuras.conditionTextFormatters[id][conditionNumber].changes
and WeakAuras.conditionTextFormatters[id][conditionNumber].changes[changeNum] then
pathToFormatter = string.format("WeakAuras.conditionTextFormatters[%q][%s].changes[%s]", id, conditionNumber, changeNum);
end
ret = ret .. " region:" .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter) .. ")" .. "\n";
if (debug) then ret = ret .. " print('# " .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter) .. "')\n"; end
end end
end end
end end
@@ -1133,6 +1168,20 @@ function WeakAuras.LoadConditionPropertyFunctions(data)
WeakAuras.customConditionsFunctions[id][conditionNumber].changes[changeIndex] = customFunc; WeakAuras.customConditionsFunctions[id][conditionNumber].changes[changeIndex] = customFunc;
end end
end end
if change.property == "chat" then
local getter = function(key, default)
local fullKey = "message_format_" .. key
if change.value[fullKey] == nil then
change.value[fullKey] = default
end
return change.value[fullKey]
end
local formatters = change.value and WeakAuras.CreateFormatters(change.value.message, getter)
WeakAuras.conditionTextFormatters[id] = WeakAuras.conditionTextFormatters[id] or {}
WeakAuras.conditionTextFormatters[id][conditionNumber] = WeakAuras.conditionTextFormatters[id][conditionNumber] or {};
WeakAuras.conditionTextFormatters[id][conditionNumber].changes = WeakAuras.conditionTextFormatters[id][conditionNumber].changes or {};
WeakAuras.conditionTextFormatters[id][conditionNumber].changes[changeIndex] = formatters;
end
end end
end end
end end
@@ -1199,8 +1248,9 @@ function WeakAuras.ConstructConditionFunction(data)
-- First Loop gather which conditions are active -- First Loop gather which conditions are active
ret = ret .. " if (not hideRegion) then\n" ret = ret .. " if (not hideRegion) then\n"
if (data.conditions) then if (data.conditions) then
WeakAuras.conditionHelpers[data.uid] = nil
for conditionNumber, condition in ipairs(data.conditions) do for conditionNumber, condition in ipairs(data.conditions) do
ret = CreateCheckCondition(ret, condition, conditionNumber, allConditionsTemplate, debug) ret = CreateCheckCondition(data.uid, ret, condition, conditionNumber, allConditionsTemplate, debug)
end end
end end
ret = ret .. " end\n"; ret = ret .. " end\n";
@@ -2255,6 +2305,7 @@ function WeakAuras.Delete(data)
WeakAuras.customActionsFunctions[id] = nil; WeakAuras.customActionsFunctions[id] = nil;
WeakAuras.customConditionsFunctions[id] = nil; WeakAuras.customConditionsFunctions[id] = nil;
WeakAuras.conditionTextFormatters[id] = nil
for event, funcs in pairs(dynamicConditions) do for event, funcs in pairs(dynamicConditions) do
funcs[id] = nil; funcs[id] = nil;
@@ -2262,6 +2313,8 @@ function WeakAuras.Delete(data)
WeakAuras.frameLevels[id] = nil; WeakAuras.frameLevels[id] = nil;
WeakAuras.conditionHelpers[data.uid] = nil
WeakAuras.DeleteCollapsedData(id) WeakAuras.DeleteCollapsedData(id)
end end
@@ -2366,6 +2419,9 @@ function WeakAuras.Rename(data, newid)
WeakAuras.customConditionsFunctions[newid] = WeakAuras.customConditionsFunctions[oldid]; WeakAuras.customConditionsFunctions[newid] = WeakAuras.customConditionsFunctions[oldid];
WeakAuras.customConditionsFunctions[oldid] = nil; WeakAuras.customConditionsFunctions[oldid] = nil;
WeakAuras.conditionTextFormatters[newid] = WeakAuras.conditionTextFormatters[oldid]
WeakAuras.conditionTextFormatters[oldid] = nil
for event, funcs in pairs(dynamicConditions) do for event, funcs in pairs(dynamicConditions) do
funcs[newid] = funcs[oldid] funcs[newid] = funcs[oldid]
funcs[oldid] = nil; funcs[oldid] = nil;
@@ -3570,6 +3626,189 @@ function WeakAuras.Modernize(data)
end end
end end
if data.internalVersion < 30 then
local convertLegacyPrecision = function(precision)
if not precision then
return 1
end
if precision < 4 then
return precision, false
else
return precision - 3, true
end
end
local progressPrecision = data.progressPrecision
local totalPrecision = data.totalPrecision
if data.regionType == "text" then
local seenSymbols = {}
WeakAuras.ParseTextStr(data.displayText, function(symbol)
if not seenSymbols[symbol] then
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
sym = sym or symbol
if sym == "p" or sym == "t" then
data["displayText_format_" .. symbol .. "_format"] = "timed"
data["displayText_format_" .. symbol .. "_time_precision"], data["displayText_format_" .. symbol .. "_time_dynamic"]
= convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision)
end
end
seenSymbols[symbol] = symbol
end)
end
if data.subRegions then
for index, subRegionData in ipairs(data.subRegions) do
if subRegionData.type == "subtext" then
local seenSymbols = {}
WeakAuras.ParseTextStr(subRegionData.text_text, function(symbol)
if not seenSymbols[symbol] then
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
sym = sym or symbol
if sym == "p" or sym == "t" then
subRegionData["text_text_format_" .. symbol .. "_format"] = "timed"
subRegionData["text_text_format_" .. symbol .. "_time_precision"], subRegionData["text_text_format_" .. symbol .. "_time_dynamic"]
= convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision)
end
end
seenSymbols[symbol] = symbol
end)
end
end
end
if data.actions then
for _, when in ipairs{ "start", "finish" } do
if data.actions[when] then
local seenSymbols = {}
WeakAuras.ParseTextStr(data.actions[when].message, function(symbol)
if not seenSymbols[symbol] then
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
sym = sym or symbol
if sym == "p" or sym == "t" then
data.actions[when]["message_format_" .. symbol .. "_format"] = "timed"
data.actions[when]["message_format_" .. symbol .. "_time_precision"], data.actions[when]["message_format_" .. symbol .. "_time_dynamic"]
= convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision)
end
end
seenSymbols[symbol] = symbol
end)
end
end
end
if data.conditions then
for conditionIndex, condition in ipairs(data.conditions) do
for changeIndex, change in ipairs(condition.changes) do
if change.property == "chat" and change.value then
local seenSymbols = {}
WeakAuras.ParseTextStr(change.value.message, function(symbol)
if not seenSymbols[symbol] then
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
sym = sym or symbol
if sym == "p" or sym == "t" then
change.value["message_format_" .. symbol .. "_format"] = "timed"
change.value["message_format_" .. symbol .. "_time_precision"], change.value["message_format_" .. symbol .. "_time_dynamic"]
= convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision)
end
end
seenSymbols[symbol] = symbol
end)
end
end
end
end
-- To convert:
-- * actions
-- * conditions
data.progressPrecision = nil
data.totalPrecision = nil
end
-- Introduced in June 2020 in Bfa
if data.internalVersion < 31 then
local whitelist
local blacklist
if data.load.use_name == true and data.load.name then
whitelist = data.load.name
elseif data.load.use_name == false and data.load.name then
blacklist = data.load.name
end
if data.load.use_realm == true and data.load.realm then
whitelist = (whitelist or "") .. "-" .. data.load.realm
elseif data.load.use_realm == false and data.load.realm then
blacklist = (blacklist or "") .. "-" .. data.load.realm
end
if whitelist then
data.load.use_namerealm = true
data.load.namerealm = whitelist
end
if blacklist then
data.load.use_namerealmblack = true
data.load.namerealmblack = blacklist
end
data.load.use_name = nil
data.load.name = nil
data.load.use_realm = nil
data.load.realm = nil
end
-- Introduced in June 2020 in Bfa
if data.internalVersion < 32 then
local replacements = {}
local function repairCheck(replacements, check)
if check and check.trigger then
if replacements[check.trigger] then
if replacements[check.trigger][check.variable] then
check.variable = replacements[check.trigger][check.variable]
end
end
end
end
if data.triggers then
for triggerId, triggerData in ipairs(data.triggers) do
if triggerData.trigger.type == "status" then
local event = triggerData.trigger.event
if event == "Unit Characteristics" or event == "Health" or event == "Power" then
replacements[triggerId] = {}
replacements[triggerId]["use_name"] = "use_namerealm"
replacements[triggerId]["name"] = "namerealm"
elseif event == "Cast" then
replacements[triggerId] = {}
replacements[triggerId]["use_sourceName"] = "use_sourceNameRealm"
replacements[triggerId]["sourceName"] = "sourceNameRealm"
replacements[triggerId]["use_destName"] = "use_destNameRealm"
replacements[triggerId]["destName"] = "destNameRealm"
end
if replacements[triggerId] then
for old, new in pairs(replacements[triggerId]) do
triggerData.trigger[new] = triggerData.trigger[old]
triggerData.trigger[old] = nil
end
local function recurseRepairChecks(replacements, checks)
if not checks then return end
for _, check in pairs(checks) do
repairCheck(replacements, check);
recurseRepairChecks(replacements, check.checks);
end
end
for _, condition in pairs(data.conditions) do
repairCheck(replacements, condition.check);
recurseRepairChecks(replacements, condition.check.checks);
end
end
end
end
end
end
for _, triggerSystem in pairs(triggerSystems) do for _, triggerSystem in pairs(triggerSystems) do
triggerSystem.Modernize(data); triggerSystem.Modernize(data);
end end
@@ -4345,10 +4584,10 @@ function WeakAuras.ReleaseClone(id, cloneId, regionType)
clonePool[regionType][#clonePool[regionType] + 1] = region; clonePool[regionType][#clonePool[regionType] + 1] = region;
end end
function WeakAuras.HandleChatAction(message_type, message, message_dest, message_channel, r, g, b, region, customFunc, when) function WeakAuras.HandleChatAction(message_type, message, message_dest, message_channel, r, g, b, region, customFunc, when, formatters)
local useHiddenStates = when == "finish" local useHiddenStates = when == "finish"
if (message:find('%%')) then if (message:find('%%')) then
message = WeakAuras.ReplacePlaceHolders(message, region, customFunc, useHiddenStates); message = WeakAuras.ReplacePlaceHolders(message, region, customFunc, useHiddenStates, formatters);
end end
if(message_type == "PRINT") then if(message_type == "PRINT") then
DEFAULT_CHAT_FRAME:AddMessage(message, r or 1, g or 1, b or 1); DEFAULT_CHAT_FRAME:AddMessage(message, r or 1, g or 1, b or 1);
@@ -4567,17 +4806,20 @@ function WeakAuras.PerformActions(data, when, region)
return; return;
end; end;
local actions; local actions;
local formatters
if(when == "start") then if(when == "start") then
actions = data.actions.start; actions = data.actions.start;
formatters = region.startFormatters
elseif(when == "finish") then elseif(when == "finish") then
actions = data.actions.finish; actions = data.actions.finish;
formatters = region.finishFormatters
else else
return; return;
end end
if(actions.do_message and actions.message_type and actions.message) then if(actions.do_message and actions.message_type and actions.message) then
local customFunc = WeakAuras.customActionsFunctions[data.id][when .. "_message"]; local customFunc = WeakAuras.customActionsFunctions[data.id][when .. "_message"];
WeakAuras.HandleChatAction(actions.message_type, actions.message, actions.message_dest, actions.message_channel, actions.r, actions.g, actions.b, region, customFunc, when); WeakAuras.HandleChatAction(actions.message_type, actions.message, actions.message_dest, actions.message_channel, actions.r, actions.g, actions.b, region, customFunc, when, formatters);
end end
if(actions.do_sound and actions.sound) then if(actions.do_sound and actions.sound) then
@@ -5943,11 +6185,12 @@ function WeakAuras.RunCustomTextFunc(region, customFunc)
end end
local state = region.state local state = region.state
WeakAuras.ActivateAuraEnvironment(region.id, region.cloneId, region.state, region.states); WeakAuras.ActivateAuraEnvironment(region.id, region.cloneId, region.state, region.states);
local progress = WeakAuras.dynamic_texts.p.func(state, region)
local dur = WeakAuras.dynamic_texts.t.func(state, region) local progress = WeakAuras.dynamic_texts.p.func(WeakAuras.dynamic_texts.p.get(state), state, 1)
local name = WeakAuras.dynamic_texts.n.func(state, region) local dur = WeakAuras.dynamic_texts.t.func( WeakAuras.dynamic_texts.t.get(state), state, 1)
local icon = WeakAuras.dynamic_texts.i.func(state, region) local name = WeakAuras.dynamic_texts.n.func(WeakAuras.dynamic_texts.n.get(state))
local stacks = WeakAuras.dynamic_texts.s.func(state, region) local icon = WeakAuras.dynamic_texts.i.func(WeakAuras.dynamic_texts.i.get(state))
local stacks = WeakAuras.dynamic_texts.s.func(WeakAuras.dynamic_texts.s.get(state))
local expirationTime local expirationTime
local duration local duration
@@ -5972,7 +6215,7 @@ function WeakAuras.RunCustomTextFunc(region, customFunc)
return custom return custom
end end
local function ReplaceValuePlaceHolders(textStr, region, customFunc, state) local function ReplaceValuePlaceHolders(textStr, region, customFunc, state, formatter)
local regionValues = region.values; local regionValues = region.values;
local value; local value;
if string.sub(textStr, 1, 1) == "c" then if string.sub(textStr, 1, 1) == "c" then
@@ -5992,7 +6235,12 @@ local function ReplaceValuePlaceHolders(textStr, region, customFunc, state)
if (not variable) then if (not variable) then
return nil; return nil;
end end
value = variable.func(state, region) value = variable.get(state)
if formatter then
value = formatter(value, state)
elseif variable.func then
value = variable.func(value)
end
end end
return value or ""; return value or "";
end end
@@ -6110,30 +6358,42 @@ function WeakAuras.ContainsAnyPlaceHolders(textStr)
return ContainsPlaceHolders(textStr, function(symbol) return true end) return ContainsPlaceHolders(textStr, function(symbol) return true end)
end end
local function ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates) local function ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates, formatters)
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)") local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
triggerNum = triggerNum and tonumber(triggerNum) triggerNum = triggerNum and tonumber(triggerNum)
if triggerNum and sym then if triggerNum and sym then
if regionStates[triggerNum] then if regionStates[triggerNum] then
if (useHiddenStates or regionStates[triggerNum].show) then if (useHiddenStates or regionStates[triggerNum].show) then
if regionStates[triggerNum][sym] then if regionStates[triggerNum][sym] then
return tostring(regionStates[triggerNum][sym]) or "" local value = regionStates[triggerNum][sym]
if formatters[symbol] then
return tostring(formatters[symbol](value, regionStates[triggerNum])) or ""
else
return tostring(value) or ""
end
else else
local value = ReplaceValuePlaceHolders(sym, region, customFunc, regionStates[triggerNum]); local value = ReplaceValuePlaceHolders(sym, region, customFunc, regionStates[triggerNum], formatters[symbol]);
return value or "" return value or ""
end end
end end
end end
return "" return ""
elseif regionState[symbol] then elseif regionState[symbol] then
return (useHiddenStates or regionState.show) and tostring(regionState[symbol]) or "" if(useHiddenStates or regionState.show) then
local value = regionState[symbol]
if formatters[symbol] then
return tostring(formatters[symbol](value, regionState) or "") or ""
else
return tostring(value) or ""
end
end
else else
local value = (useHiddenStates or regionState.show) and ReplaceValuePlaceHolders(symbol, region, customFunc, regionState); local value = (useHiddenStates or regionState.show) and ReplaceValuePlaceHolders(symbol, region, customFunc, regionState, formatters[symbol]);
return value or "" return value or ""
end end
end end
function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenStates) function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenStates, formatters)
local regionValues = region.values; local regionValues = region.values;
local regionState = region.state or {}; local regionState = region.state or {};
local regionStates = region.states or {}; local regionStates = region.states or {};
@@ -6148,7 +6408,8 @@ function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenSta
if (endPos == 2) then if (endPos == 2) then
if string.byte(textStr, 1) == 37 then if string.byte(textStr, 1) == 37 then
local value = (regionState.show or useHiddenStates) and ReplaceValuePlaceHolders(string.sub(textStr, 2), region, customFunc, regionState); local symbol = string.sub(textStr, 2)
local value = (regionState.show or useHiddenStates) and ReplaceValuePlaceHolders(symbol, region, customFunc, regionState, formatters[symbol]);
if (value) then if (value) then
textStr = tostring(value); textStr = tostring(value);
end end
@@ -6186,7 +6447,7 @@ function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenSta
-- 0-9a-zA-Z or dot character -- 0-9a-zA-Z or dot character
else -- End of variable else -- End of variable
local symbol = string.sub(textStr, start, currentPos - 1) local symbol = string.sub(textStr, start, currentPos - 1)
result = result .. ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates) result = result .. ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates, formatters)
if char == 37 then if char == 37 then
else else
@@ -6196,7 +6457,7 @@ function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenSta
elseif state == 3 then elseif state == 3 then
if char == 125 then -- } closing brace if char == 125 then -- } closing brace
local symbol = string.sub(textStr, start, currentPos - 1) local symbol = string.sub(textStr, start, currentPos - 1)
result = result .. ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates) result = result .. ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates, formatters)
start = currentPos + 1 start = currentPos + 1
end end
end end
@@ -6208,7 +6469,7 @@ function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenSta
result = result .. string.sub(textStr, start, currentPos - 1) result = result .. string.sub(textStr, start, currentPos - 1)
elseif state == 2 and currentPos > start then elseif state == 2 and currentPos > start then
local symbol = string.sub(textStr, start, currentPos - 1) local symbol = string.sub(textStr, start, currentPos - 1)
result = result .. ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates) result = result .. ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates, formatters)
elseif state == 1 then elseif state == 1 then
result = result .. "%" result = result .. "%"
end end
@@ -6217,6 +6478,79 @@ function WeakAuras.ReplacePlaceHolders(textStr, region, customFunc, useHiddenSta
return textStr; return textStr;
end end
function WeakAuras.ParseTextStr(textStr, symbolCallback)
if not textStr then
return
end
local endPos = textStr:len();
local currentPos = 1 -- Position of the "cursor"
local state = 0
local start = 1 -- Start of whatever "word" we are currently considering, doesn't include % or {} symbols
while currentPos <= endPos do
local char = string.byte(textStr, currentPos);
if state == 0 then -- Normal State
elseif state == 1 then -- Percent Start State
if char == 37 then
start = currentPos
elseif char == 123 then
start = currentPos + 1
elseif (char >= 48 and char <= 57) or (char >= 65 and char <= 90) or (char >= 97 and char <= 122) or char == 46 then
-- 0-9a-zA-Z or dot character
start = currentPos
else
start = currentPos
end
elseif state == 2 then -- Percent Rest State
if (char >= 48 and char <= 57) or (char >= 65 and char <= 90) or (char >= 97 and char <= 122) or char == 46 then
-- 0-9a-zA-Z or dot character
else -- End of variable
local symbol = string.sub(textStr, start, currentPos - 1)
symbolCallback(symbol)
if char == 37 then
else
start = currentPos
end
end
elseif state == 3 then
if char == 125 then -- } closing brace
local symbol = string.sub(textStr, start, currentPos - 1)
symbolCallback(symbol)
start = currentPos + 1
end
end
state = nextState(char, state)
currentPos = currentPos + 1
end
if state == 2 and currentPos > start then
local symbol = string.sub(textStr, start, currentPos - 1)
symbolCallback(symbol)
end
end
function WeakAuras.CreateFormatters(input, getter)
local seenSymbols = {}
local formatters = {}
WeakAuras.ParseTextStr(input, function(symbol)
if not seenSymbols[symbol] then
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
sym = sym or symbol
if sym == "c" or sym == "i" then
-- Do nothing
else
local default = (sym == "p" or sym == "t") and "timed" or "none"
local selectedFormat = getter(symbol .. "_format", default)
if (WeakAuras.format_types[selectedFormat]) then
formatters[symbol] = WeakAuras.format_types[selectedFormat].CreateFormatter(symbol, getter)
end
end
end
seenSymbols[symbol] = true
end)
return formatters
end
function WeakAuras.IsTriggerActive(id) function WeakAuras.IsTriggerActive(id)
local active = triggerState[id]; local active = triggerState[id];
return active and active.show; return active and active.show;
@@ -6685,3 +7019,48 @@ end
function WeakAuras.UntrackableUnit(unit) function WeakAuras.UntrackableUnit(unit)
return not trackableUnits[unit] return not trackableUnits[unit]
end end
local ownRealm = GetRealmName()
function WeakAuras.UnitNameWithRealm(unit)
local name, realm = UnitName(unit)
return name or "", realm or ownRealm or ""
end
function WeakAuras.ParseNameCheck(name)
local matches = {
name = {},
realm = {},
full = {},
AddMatch = function(self, name, start, last)
local match = strtrim(name:sub(start, last))
if (match:sub(1, 1) == "-") then
self.realm[match:sub(2)] = true
elseif match:find("-", 1, true) then
self.full[match] = true
else
self.name[match] = true
end
end,
Check = function(self, name, realm)
if not name or not realm then
return false
end
return self.name[name] or self.realm[realm] or self.full[name .. "-" .. realm]
end
}
local start = 1
local last = name:find(',', start, true)
while (last) do
matches:AddMatch(name, start, last - 1)
start = last + 1
last = name:find(',', start, true)
end
last = #name
matches:AddMatch(name, start, last)
return matches
end
+1 -1
View File
@@ -1,7 +1,7 @@
## Interface: 30300 ## Interface: 30300
## Title: WeakAuras 2 ## Title: WeakAuras 2
## Author: Mirrored and the WeakAuras Team ## Author: Mirrored and the WeakAuras Team
## Version: 2.17.8 ## Version: 2.17.11
## Notes: A powerful, comprehensive utility for displaying graphics and information based on buffs, debuffs, and other triggers. ## Notes: A powerful, comprehensive utility for displaying graphics and information based on buffs, debuffs, and other triggers.
## Notes-esES: Potente y completa aplicación que te permitirá mostrar por pantalla múltiples diseños, basados en beneficios, perjuicios y otros activadores. ## Notes-esES: Potente y completa aplicación que te permitirá mostrar por pantalla múltiples diseños, basados en beneficios, perjuicios y otros activadores.
## Notes-deDE: Ein leistungsfähiges, umfassendes Addon zur grafischen Darstellung von Informationen von Auren, Cooldowns, Timern und vielem mehr. ## Notes-deDE: Ein leistungsfähiges, umfassendes Addon zur grafischen Darstellung von Informationen von Auren, Cooldowns, Timern und vielem mehr.
+12
View File
@@ -2,10 +2,22 @@ local ipairs = ipairs
local pairs = pairs local pairs = pairs
local select = select local select = select
local ceil, floor = math.ceil, math.floor local ceil, floor = math.ceil, math.floor
local format = string.format
local GetInstanceInfo = GetInstanceInfo local GetInstanceInfo = GetInstanceInfo
local GetNumPartyMembers = GetNumPartyMembers local GetNumPartyMembers = GetNumPartyMembers
local GetNumRaidMembers = GetNumRaidMembers local GetNumRaidMembers = GetNumRaidMembers
local UnitClass = UnitClass
function GetClassColoredTextForUnit(unit, text)
local _, classFilename = UnitClass(unit)
local color = RAID_CLASS_COLORS[classFilename]
if color then
return format("|c%s%s|r", format("ff%.2x%.2x%.2x", color.r * 255, color.g * 255, color.b * 255), text)
else
return text
end
end
function tInvert(tbl) function tInvert(tbl)
local inverted = {}; local inverted = {};
+124 -13
View File
@@ -51,6 +51,9 @@ function WeakAuras.AddActionOption(id, data)
pcall(PlaySound, v, "Master"); pcall(PlaySound, v, "Master");
end end
WeakAuras.Add(data); WeakAuras.Add(data);
if(value == "message") then
WeakAuras.ReloadOptions(data.id)
end
end, end,
args = { args = {
init_header = { init_header = {
@@ -112,7 +115,7 @@ function WeakAuras.AddActionOption(id, data)
type = "input", type = "input",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Send To"], name = L["Send To"],
order = 4, order = 3.1,
disabled = function() return not data.actions.start.do_message end, disabled = function() return not data.actions.start.do_message end,
hidden = function() return data.actions.start.message_type ~= "WHISPER" end hidden = function() return data.actions.start.message_type ~= "WHISPER" end
}, },
@@ -120,7 +123,7 @@ function WeakAuras.AddActionOption(id, data)
type = "input", type = "input",
width = WeakAuras.doubleWidth, width = WeakAuras.doubleWidth,
name = L["Message"], name = L["Message"],
order = 5, order = 4,
disabled = function() return not data.actions.start.do_message end, disabled = function() return not data.actions.start.do_message end,
desc = function() desc = function()
return L["Dynamic text tooltip"] .. WeakAuras.GetAdditionalProperties(data) return L["Dynamic text tooltip"] .. WeakAuras.GetAdditionalProperties(data)
@@ -131,27 +134,27 @@ function WeakAuras.AddActionOption(id, data)
type = "toggle", type = "toggle",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Play Sound"], name = L["Play Sound"],
order = 7 order = 8
}, },
start_do_loop = { start_do_loop = {
type = "toggle", type = "toggle",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Loop"], name = L["Loop"],
order = 7.1, order = 8.1,
disabled = function() return not data.actions.start.do_sound end, disabled = function() return not data.actions.start.do_sound end,
}, },
start_sound_repeat = { start_sound_repeat = {
type = "range", type = "range",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Repeat After"], name = L["Repeat After"],
order = 7.2, order = 8.2,
hidden = function() return not data.actions.start.do_loop end, hidden = function() return not data.actions.start.do_loop end,
disabled = function() return not data.actions.start.do_sound end, disabled = function() return not data.actions.start.do_sound end,
}, },
start_sound_repeat_space = { start_sound_repeat_space = {
type = "description", type = "description",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
order = 7.3, order = 8.3,
name = "", name = "",
hidden = function() return not data.actions.start.do_loop end, hidden = function() return not data.actions.start.do_loop end,
}, },
@@ -159,7 +162,7 @@ function WeakAuras.AddActionOption(id, data)
type = "select", type = "select",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Sound"], name = L["Sound"],
order = 8, order = 8.4,
values = sound_types, values = sound_types,
disabled = function() return not data.actions.start.do_sound end, disabled = function() return not data.actions.start.do_sound end,
control = "WeakAurasSortedDropdown" control = "WeakAurasSortedDropdown"
@@ -484,7 +487,7 @@ function WeakAuras.AddActionOption(id, data)
type = "input", type = "input",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Send To"], name = L["Send To"],
order = 24, order = 23.1,
disabled = function() return not data.actions.finish.do_message end, disabled = function() return not data.actions.finish.do_message end,
hidden = function() return data.actions.finish.message_type ~= "WHISPER" end hidden = function() return data.actions.finish.message_type ~= "WHISPER" end
}, },
@@ -492,7 +495,7 @@ function WeakAuras.AddActionOption(id, data)
type = "input", type = "input",
width = WeakAuras.doubleWidth, width = WeakAuras.doubleWidth,
name = L["Message"], name = L["Message"],
order = 25, order = 24,
disabled = function() return not data.actions.finish.do_message end, disabled = function() return not data.actions.finish.do_message end,
desc = function() desc = function()
return L["Dynamic text tooltip"] .. WeakAuras.GetAdditionalProperties(data) return L["Dynamic text tooltip"] .. WeakAuras.GetAdditionalProperties(data)
@@ -503,13 +506,13 @@ function WeakAuras.AddActionOption(id, data)
type = "toggle", type = "toggle",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Play Sound"], name = L["Play Sound"],
order = 27 order = 28
}, },
finish_sound = { finish_sound = {
type = "select", type = "select",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Sound"], name = L["Sound"],
order = 28, order = 28.1,
values = sound_types, values = sound_types,
disabled = function() return not data.actions.finish.do_sound end, disabled = function() return not data.actions.finish.do_sound end,
control = "WeakAurasSortedDropdown" control = "WeakAurasSortedDropdown"
@@ -796,17 +799,125 @@ function WeakAuras.AddActionOption(id, data)
}, },
} }
-- Text format option helpers
WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "init", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#on-init", WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "init", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#on-init",
0.011, function() return not data.actions.init.do_custom end, {"actions", "init", "custom"}, true); 0.011, function() return not data.actions.init.do_custom end, {"actions", "init", "custom"}, true);
WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "start_message", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#chat-message---custom-code", WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "start_message", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#chat-message---custom-code",
5.1, function() return not (data.actions.start.do_message and WeakAuras.ContainsCustomPlaceHolder(data.actions.start.message)) end, {"actions", "start", "message_custom"}, false); 5, function() return not (data.actions.start.do_message and WeakAuras.ContainsCustomPlaceHolder(data.actions.start.message)) end, {"actions", "start", "message_custom"}, false);
local startHidden = function()
return WeakAuras.IsCollapsed("format_option", "actions", "start_message", true)
end
local startSetHidden = function(hidden)
WeakAuras.SetCollapsed("format_option", "actions", "start_message", hidden)
end
local startGet = function(key)
return data.actions.start["message_format_" .. key]
end
local order = 6
local usedKeys = {}
local function startAddOption(key, option)
if usedKeys[key] then
return
end
usedKeys[key] = true
option.order = order
order = order + 0.01
local reload = option.reloadOptions
option.reloadOptions = nil
option.set = function(info, v)
data.actions.start["message_format_" .. key] = v
WeakAuras.Add(data)
if reload then
WeakAuras.ReloadOptions2(data.id, data)
end
end
if option.hidden then
local hidden = option.hidden
option.hidden = function() return not data.actions.start.do_message or hidden() end
else
option.hidden = function() return not data.actions.start.do_message end
end
action.args["start_message_format_" .. key] = option
end
if data.controlledChildren then
for _, childId in pairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId)
local startGet = function(key)
return childData.actions.start["message_format_" .. key]
end
WeakAuras.AddTextFormatOption(childData.actions and childData.actions.start.message, true, startGet, startAddOption, startHidden, startSetHidden)
end
else
WeakAuras.AddTextFormatOption(data.actions and data.actions.start.message, true, startGet, startAddOption, startHidden, startSetHidden)
end
WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "start", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#on-show", WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "start", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#on-show",
13, function() return not data.actions.start.do_custom end, {"actions", "start", "custom"}, true); 13, function() return not data.actions.start.do_custom end, {"actions", "start", "custom"}, true);
WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "finish_message", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#chat-message---custom-code", WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "finish_message", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#chat-message---custom-code",
26, function() return not (data.actions.finish.do_message and WeakAuras.ContainsCustomPlaceHolder(data.actions.finish.message)) end, {"actions", "finish", "message_custom"}, false); 25, function() return not (data.actions.finish.do_message and WeakAuras.ContainsCustomPlaceHolder(data.actions.finish.message)) end, {"actions", "finish", "message_custom"}, false);
local finishHidden = function()
return WeakAuras.IsCollapsed("format_option", "actions", "finish_message", true)
end
local finishSetHidden = function(hidden)
WeakAuras.SetCollapsed("format_option", "actions", "finish_message", hidden)
end
local finishGet = function(key)
return data.actions.finish["message_format_" .. key]
end
order = 25
usedKeys = {}
local function finishAddOption(key, option)
if usedKeys[key] then
return
end
option.order = order
order = order + 0.01
local reload = option.reloadOptions
option.reloadOptions = nil
option.set = function(info, v)
data.actions.finish["message_format_" .. key] = v
WeakAuras.Add(data)
if reload then
WeakAuras.ReloadOptions2(data.id, data)
end
end
if option.hidden then
local hidden = option.hidden
option.hidden = function() return not data.actions.finish.do_message or hidden() end
else
option.hidden = function() return not data.actions.finish.do_message end
end
action.args["finish_message_format_" .. key] = option
end
if data.controlledChildren then
for _, childId in pairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId)
local finishGet = function(key)
return childData.actions.finish["message_format_" .. key]
end
WeakAuras.AddTextFormatOption(childData.actions and childData.actions.finish.message, true, finishGet, finishAddOption, finishHidden, finishSetHidden)
end
else
WeakAuras.AddTextFormatOption(data.actions and data.actions.finish.message, true, finishGet, finishAddOption, finishHidden, finishSetHidden)
end
WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "finish", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#on-hide", WeakAuras.AddCodeOption(action.args, data, L["Custom Code"], "finish", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#on-hide",
32, function() return not data.actions.finish.do_custom end, {"actions", "finish", "custom"}, true); 32, function() return not data.actions.finish.do_custom end, {"actions", "finish", "custom"}, true);
+2 -4
View File
@@ -11,8 +11,7 @@ local group_aura_name_info_types = WeakAuras.group_aura_name_info_types;
local group_aura_stack_info_types = WeakAuras.group_aura_stack_info_types; local group_aura_stack_info_types = WeakAuras.group_aura_stack_info_types;
local function getAuraMatchesLabel(name) local function getAuraMatchesLabel(name)
local iconCache = WeakAuras.spellCache.Get(); local ids = WeakAuras.spellCache.GetSpellsMatching(name)
local ids = iconCache[name]
if(ids) then if(ids) then
local descText = ""; local descText = "";
local numMatches = 0; local numMatches = 0;
@@ -37,8 +36,7 @@ local function spellId_tremove(tbl, pos)
end end
local function getAuraMatchesList(name) local function getAuraMatchesList(name)
local iconCache = WeakAuras.spellCache.Get(); local ids = WeakAuras.spellCache.GetSpellsMatching(name)
local ids = iconCache[name]
if(ids) then if(ids) then
local descText = ""; local descText = "";
for id, _ in pairs(ids) do for id, _ in pairs(ids) do
+45 -8
View File
@@ -6,8 +6,7 @@ local operator_types = WeakAuras.operator_types
local debuff_types = WeakAuras.debuff_types local debuff_types = WeakAuras.debuff_types
local function getAuraMatchesLabel(name) local function getAuraMatchesLabel(name)
local iconCache = WeakAuras.spellCache.Get() local ids = WeakAuras.spellCache.GetSpellsMatching(name)
local ids = iconCache[name]
if ids then if ids then
local descText = "" local descText = ""
local numMatches = 0 local numMatches = 0
@@ -21,8 +20,7 @@ local function getAuraMatchesLabel(name)
end end
local function getAuraMatchesList(name) local function getAuraMatchesList(name)
local iconCache = WeakAuras.spellCache.Get() local ids = WeakAuras.spellCache.GetSpellsMatching(name)
local ids = iconCache[name]
if ids then if ids then
local descText = "" local descText = ""
for id, _ in pairs(ids) do for id, _ in pairs(ids) do
@@ -695,18 +693,57 @@ local function GetBuffTriggerOptions(data, optionTriggerChoices)
width = WeakAuras.doubleWidth, width = WeakAuras.doubleWidth,
hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party")) end hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party")) end
}, },
ignoreInvisible = {
type = "toggle",
name = WeakAuras.newFeatureString .. L["Ignore out of checking range."],
desc = L["Uses UnitIsVisible() to check if in range. This is polled every second."],
order = 68.9,
width = WeakAuras.doubleWidth,
hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party")) end
},
useUnitName = {
type = "toggle",
width = "WeakAuras.normalWidth",
name = L["UnitName Filter"],
order = 69.1,
hidden = function() return
not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party"))
end
},
unitName = {
type = "input",
width = WeakAuras.normalWidth,
name = L["Unit Name Filter"],
desc = L["Filter formats: 'Name', 'Name-Realm', '-Realm'.\n\nSupports multiple entries, separated by commas\n"],
order = 69.2,
hidden = function()
return not (trigger.type == "aura2"
and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party") and trigger.useUnitName)
end
},
unitNameSpace = {
type = "description",
name = "",
order = 69.3,
width = WeakAuras.normalWidth,
hidden = function()
return not (trigger.type == "aura2"
and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party") and not trigger.useUnitName)
end
},
useGroup_count = { useGroup_count = {
type = "toggle", type = "toggle",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Unit Count"], name = L["Unit Count"],
hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger)) end, hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger)) end,
order = 69 order = 70
}, },
useGroup_countSpace = { useGroup_countSpace = {
type = "description", type = "description",
name = "", name = "",
order = 69.1, order = 70.1,
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger) and not trigger.useGroup_count) end hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger) and not trigger.useGroup_count) end
}, },
@@ -721,7 +758,7 @@ local function GetBuffTriggerOptions(data, optionTriggerChoices)
return L["Group aura count description"]:format(groupType, groupType, groupType, groupType, groupType, groupType, groupType) return L["Group aura count description"]:format(groupType, groupType, groupType, groupType, groupType, groupType, groupType)
end end
end, end,
order = 69.2, order = 70.2,
width = WeakAuras.halfWidth, width = WeakAuras.halfWidth,
values = operator_types, values = operator_types,
hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger) and trigger.useGroup_count) end, hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger) and trigger.useGroup_count) end,
@@ -738,7 +775,7 @@ local function GetBuffTriggerOptions(data, optionTriggerChoices)
return L["Group aura count description"]:format(groupType, groupType, groupType, groupType, groupType, groupType, groupType) return L["Group aura count description"]:format(groupType, groupType, groupType, groupType, groupType, groupType, groupType)
end end
end, end,
order = 69.3, order = 70.3,
width = WeakAuras.halfWidth, width = WeakAuras.halfWidth,
hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger) and trigger.useGroup_count) end, hidden = function() return not (trigger.type == "aura2" and IsGroupTrigger(trigger) and trigger.useGroup_count) end,
}, },
+91 -36
View File
@@ -12,42 +12,70 @@ local spellCache = {}
WeakAuras.spellCache = spellCache WeakAuras.spellCache = spellCache
local cache local cache
local metaData
local bestIcon = {} local bestIcon = {}
local dynFrame = WeakAuras.dynFrame local dynFrame = WeakAuras.dynFrame
-- Builds a cache of name/icon pairs from existing spell data -- Builds a cache of name/icon pairs from existing spell data
-- This is a rather slow operation, so it's only done once, and the result is subsequently saved -- This is a rather slow operation, so it's only done once, and the result is subsequently saved
function spellCache.Build(callback) function spellCache.Build()
if cache then if not cache then
local co = coroutine.create(function()
local id = 0
local misses = 0
while misses < 400 do
id = id + 1
local name, _, icon = GetSpellInfo(id)
if(icon == 136243) then -- 136243 is the a gear icon, we can ignore those spells
misses = 0;
elseif name and name ~= "" then
cache[name] = cache[name] or {}
cache[name][id] = icon
misses = 0
else
misses = misses + 1
end
coroutine.yield()
end
if callback then
callback()
end
end)
dynFrame:AddAction(callback, co)
else
error("spellCache has not been loaded. Call WeakAuras.spellCache.Load(...) first.") error("spellCache has not been loaded. Call WeakAuras.spellCache.Load(...) first.")
end end
if not metaData.needsRebuild then
return
end
wipe(cache)
local co = coroutine.create(function()
local id = 0
local misses = 0
while misses < 400 do
id = id + 1
local name, _, icon = GetSpellInfo(id)
if(icon == 136243) then -- 136243 is the a gear icon, we can ignore those spells
misses = 0;
elseif name and name ~= "" then
cache[name] = cache[name] or {}
cache[name].spells = cache[name].spells or {}
cache[name].spells[id] = icon
misses = 0
else
misses = misses + 1
end
coroutine.yield()
end
for _, category in pairs(GetCategoryList()) do
local total = GetCategoryNumAchievements(category, true)
for i = 1, total do
local id,name,_,_,_,_,_,_,_,iconID = GetAchievementInfo(category, i)
if name and iconID then
cache[name] = cache[name] or {}
cache[name].achievements = cache[name].achievements or {}
cache[name].achievements[id] = iconID
end
end
coroutine.yield()
end
-- Updates the icon cache with whatever icons WeakAuras core has actually used.
-- This helps keep name<->icon matches relevant.
for name, icons in pairs(WeakAurasSaved.dynamicIconCache) do
if WeakAurasSaved.dynamicIconCache[name] then
for spellId, icon in pairs(WeakAurasSaved.dynamicIconCache[name]) do
spellCache.AddIcon(name, spellId, icon)
end
end
end
metaData.needsRebuild = false
end)
dynFrame:AddAction("spellCache", co)
end end
function spellCache.GetIcon(name) function spellCache.GetIcon(name)
@@ -62,22 +90,30 @@ function spellCache.GetIcon(name)
local icons = cache[name] local icons = cache[name]
local bestMatch = nil local bestMatch = nil
if (icons) then if (icons) then
for spellId, icon in pairs(icons) do if (icons.spells) then
if (not bestMatch) then for spellId, icon in pairs(icons.spells) do
bestMatch = spellId if (not bestMatch) then
elseif(type(spellId) == "number" and IsSpellKnown(spellId)) then bestMatch = spellId
bestMatch = spellId elseif(type(spellId) == "number" and IsSpellKnown(spellId)) then
bestMatch = spellId
end
end end
end end
end end
bestIcon[name] = bestMatch and icons[bestMatch]; bestIcon[name] = bestMatch and icons.spells[bestMatch];
return bestIcon[name]; return bestIcon[name];
else else
error("spellCache has not been loaded. Call WeakAuras.spellCache.Load(...) first.") error("spellCache has not been loaded. Call WeakAuras.spellCache.Load(...) first.")
end end
end end
function spellCache.GetSpellsMatching(name)
if cache[name] then
return cache[name].spells
end
end
function spellCache.AddIcon(name, id, icon) function spellCache.AddIcon(name, id, icon)
if cache then if cache then
if name then if name then
@@ -100,7 +136,26 @@ function spellCache.Get()
end end
function spellCache.Load(data) function spellCache.Load(data)
cache = cache or data metaData = data
cache = metaData.spellCache
local _, build = GetBuildInfo();
local locale = GetLocale();
local version = WeakAuras.versionString
local num = 0;
for i,v in pairs(cache) do
num = num + 1;
end
if(num < 39000 or metaData.locale ~= locale or metaData.build ~= build or metaData.version ~= version or not metaData.spellCacheAchivements) then
metaData.build = build;
metaData.locale = locale;
metaData.version = version;
metaData.spellCacheAchivements = true
metaData.needsRebuild = true
wipe(cache)
end
end end
-- This function computes the Levenshtein distance between two strings -- This function computes the Levenshtein distance between two strings
+106 -37
View File
@@ -331,7 +331,7 @@ local function addControlsForChange(args, order, data, conditionVariable, condit
WeakAuras.ReloadTriggerOptions(data); WeakAuras.ReloadTriggerOptions(data);
end end
setValueComplex = function(property) setValueComplex = function(property, reloadOptions)
return function(info, v) return function(info, v)
for id, reference in pairs(conditions[i].changes[j].references) do for id, reference in pairs(conditions[i].changes[j].references) do
local auraData = WeakAuras.GetData(id); local auraData = WeakAuras.GetData(id);
@@ -346,7 +346,11 @@ local function addControlsForChange(args, order, data, conditionVariable, condit
conditions[i].changes[j].value = {}; conditions[i].changes[j].value = {};
end end
conditions[i].changes[j].value[property] = v; conditions[i].changes[j].value[property] = v;
WeakAuras.ReloadTriggerOptions(data); if reloadOptions then
WeakAuras.ReloadOptions2(data.id, data)
else
WeakAuras.ReloadTriggerOptions(data);
end
end end
end end
@@ -394,13 +398,16 @@ local function addControlsForChange(args, order, data, conditionVariable, condit
WeakAuras.Add(data); WeakAuras.Add(data);
end end
setValueComplex = function(property) setValueComplex = function(property, reloadOptions)
return function(info, v) return function(info, v)
if (type (conditions[i].changes[j].value) ~= "table") then if (type (conditions[i].changes[j].value) ~= "table") then
conditions[i].changes[j].value = {}; conditions[i].changes[j].value = {};
end end
conditions[i].changes[j].value[property] = v; conditions[i].changes[j].value[property] = v;
WeakAuras.Add(data); WeakAuras.Add(data);
if reloadOptions then
WeakAuras.ReloadOptions2(data.id, data)
end
end end
end end
@@ -671,6 +678,10 @@ local function addControlsForChange(args, order, data, conditionVariable, condit
descMessage = L["Dynamic text tooltip"] .. WeakAuras.GetAdditionalProperties(data) descMessage = L["Dynamic text tooltip"] .. WeakAuras.GetAdditionalProperties(data)
end end
local message_getter = function()
return type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value.message;
end
args["condition" .. i .. "value" .. j .. "message"] = { args["condition" .. i .. "value" .. j .. "message"] = {
type = "input", type = "input",
width = WeakAuras.doubleWidth, width = WeakAuras.doubleWidth,
@@ -680,10 +691,47 @@ local function addControlsForChange(args, order, data, conditionVariable, condit
get = function() get = function()
return type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value.message; return type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value.message;
end, end,
set = setValueComplex("message") get = message_getter,
set = setValueComplex("message", true)
} }
order = order + 1; order = order + 1;
local formatGet = function(key)
return type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value["message_format_" .. key]
end
local usedKeys = {}
local function addOption(key, option)
if usedKeys[key] then
return
end
usedKeys[key] = true
option.order = order
order = order + 0.01
local fullKey = "condition" .. i .. "value" .. j .. "message_format_" .. key
option.get = function()
return type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value["message_format_" .. key];
end
local originalName = option.name
option.name = blueIfNoValue2(data, conditions[i].changes[j], "value", "message_format_" .. key, originalName, originalName)
option.desc = descIfNoValue2(data, conditions[i].changes[j], "value", "message_format_" .. key, nil, option.values)
option.set = setValueComplex("message_format_" .. key, option.reloadOptions)
option.reloadOptions = nil
args[fullKey] = option
end
if data.controlledChildren then
for id, reference in pairs(conditions[i].changes[j].references) do
local input = reference.value and reference.value.message
WeakAuras.AddTextFormatOption(input, false, formatGet, addOption)
end
else
local input = type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value["message"]
WeakAuras.AddTextFormatOption(input, false, formatGet, addOption)
end
local function customHidden() local function customHidden()
local message = type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value.message; local message = type(conditions[i].changes[j].value) == "table" and conditions[i].changes[j].value.message;
if (not message) then return true; end if (not message) then return true; end
@@ -1434,9 +1482,9 @@ local function addControlsForIfLine(args, order, data, conditionVariable, condit
if (currentConditionTemplate.type == "number" or currentConditionTemplate.type == "timer") then if (currentConditionTemplate.type == "number" or currentConditionTemplate.type == "timer") then
local opTypes = WeakAuras.operator_types local opTypes = WeakAuras.operator_types
if currentConditionTemplate.operator_types_without_equal then if currentConditionTemplate.operator_types == "without_equal" then
opTypes = WeakAuras.operator_types_without_equal opTypes = WeakAuras.operator_types_without_equal
elseif currentConditionTemplate.operator_types_only_equal then elseif currentConditionTemplate.operator_types == "only_equal" then
opTypes = WeakAuras.equality_operator_types opTypes = WeakAuras.equality_operator_types
end end
@@ -1546,21 +1594,22 @@ local function addControlsForIfLine(args, order, data, conditionVariable, condit
} }
order = order + 1; order = order + 1;
elseif (currentConditionTemplate.type == "string") then elseif (currentConditionTemplate.type == "string") then
args["condition" .. i .. tostring(path) .. "_op"] = { if currentConditionTemplate.operator_types ~= "none" then
name = blueIfNoValue(data, conditions[i].check, "op", L["Differences"]), args["condition" .. i .. tostring(path) .. "_op"] = {
desc = descIfNoValue(data, conditions[i].check, "op", currentConditionTemplate.type), name = blueIfNoValue(data, conditions[i].check, "op", L["Differences"]),
type = "select", desc = descIfNoValue(data, conditions[i].check, "op", currentConditionTemplate.type),
width = WeakAuras.normalWidth, type = "select",
order = order, width = WeakAuras.normalWidth,
values = WeakAuras.string_operator_types, order = order,
get = function() values = WeakAuras.string_operator_types,
return check and check.op; get = function()
end, return check and check.op;
set = setOp end,
} set = setOp
order = order + 1; }
order = order + 1;
order = addSpace(args, order); order = addSpace(args, order);
end
args["condition" .. i .. tostring(path) .. "_value"] = { args["condition" .. i .. tostring(path) .. "_value"] = {
type = "input", type = "input",
@@ -2085,18 +2134,34 @@ local function findMatchingProperty(all, change, id)
return nil; return nil;
end end
local propertyTypeToSubProperty = { local noop = function() end
chat = { "message_type", "message_dest", "message_channel", "message", "custom" }, local function SubPropertiesForChange(change)
sound = { "sound", "sound_channel", "sound_path", "sound_kit_id", "sound_repeat", "sound_type"}, if change.property == "sound" then
customcode = { "custom" }, return { "sound", "sound_channel", "sound_path", "sound_kit_id", "sound_repeat", "sound_type"}
glowexternal = { elseif change.property == "customcode" then
"glow_action", "glow_frame_type", "glow_type", return { "custom" }
"glow_frame", "choose_glow_frame", elseif change.property == "glowexternal" then
"use_glow_color", "glow_color", return {
"glow_lines", "glow_frequency", "glow_length", "glow_thickness", "glow_XOffset", "glow_YOffset", "glow_action", "glow_frame_type", "glow_type",
"glow_scale", "glow_border" "glow_frame", "choose_glow_frame",
} "use_glow_color", "glow_color",
}; "glow_lines", "glow_frequency", "glow_length", "glow_thickness", "glow_XOffset", "glow_YOffset",
"glow_scale", "glow_border"
}
elseif change.property == "chat" then
local result = { "message_type", "message_dest", "message_channel", "message", "custom" }
local input = change.value and change.value.message
if input then
local getter = function(key)
return change.value["message_format_" .. key]
end
WeakAuras.AddTextFormatOption(input, false, getter, function(key)
tinsert(result, "message_format_" .. key)
end)
end
return result
end
end
local subPropertyToType = { local subPropertyToType = {
glow_color = "color" glow_color = "color"
@@ -2115,8 +2180,12 @@ local function mergeConditionChange(all, change, id, changeIndex, allProperties)
all.samevalue = false; all.samevalue = false;
end end
else else
for _, propertyName in ipairs(propertyTypeToSubProperty[propertyType]) do for _, propertyName in ipairs(SubPropertiesForChange(change)) do
if not compareValues(all.value[propertyName], change.value[propertyName], subPropertyToType[propertyName]) then if all.samevalue[propertyName] == nil then
-- NEW not yet seen property
all.value[propertyName] = change.value[propertyName]
all.samevalue[propertyName] = true
elseif not compareValues(all.value[propertyName], change.value[propertyName], subPropertyToType[propertyName]) then
all.value[propertyName] = nil; all.value[propertyName] = nil;
if all.samevalue then if all.samevalue then
all.samevalue[propertyName] = false; all.samevalue[propertyName] = false;
@@ -2172,7 +2241,7 @@ local function mergeCondition(all, aura, id, conditionIndex, allProperties)
local propertyType = change.property and allProperties.propertyMap[change.property] and allProperties.propertyMap[change.property].type; local propertyType = change.property and allProperties.propertyMap[change.property] and allProperties.propertyMap[change.property].type;
if (propertyType == "chat" or propertyType == "sound" or propertyType == "customcode" or propertyType == "glowexternal") then if (propertyType == "chat" or propertyType == "sound" or propertyType == "customcode" or propertyType == "glowexternal") then
copy.samevalue = {}; copy.samevalue = {};
for _, propertyName in ipairs(propertyTypeToSubProperty[propertyType]) do for _, propertyName in ipairs(SubPropertiesForChange(change)) do
copy.samevalue[propertyName] = true; copy.samevalue[propertyName] = true;
end end
else else
@@ -2220,7 +2289,7 @@ local function mergeConditions(all, aura, id, allConditionTemplates, propertyTyp
local propertyType = change.property and propertyTypes.propertyMap[change.property] and propertyTypes.propertyMap[change.property].type; local propertyType = change.property and propertyTypes.propertyMap[change.property] and propertyTypes.propertyMap[change.property].type;
if (propertyType == "chat" or propertyType == "sound" or propertyType == "customcode" or propertyType == "glowexternal") then if (propertyType == "chat" or propertyType == "sound" or propertyType == "customcode" or propertyType == "glowexternal") then
change.samevalue = {}; change.samevalue = {};
for _, propertyName in ipairs(propertyTypeToSubProperty[propertyType]) do for _, propertyName in ipairs(SubPropertiesForChange(change)) do
change.samevalue[propertyName] = true; change.samevalue[propertyName] = true;
end end
else else
+31 -20
View File
@@ -22,7 +22,7 @@ local function ConstructIconPicker(frame)
group.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 30); -- 12 group.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 30); -- 12
group.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -50); group.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -50);
group.frame:Hide(); group.frame:Hide();
group:SetLayout("flow"); group:SetLayout("fill");
local scroll = AceGUI:Create("ScrollFrame"); local scroll = AceGUI:Create("ScrollFrame");
scroll:SetLayout("flow"); scroll:SetLayout("flow");
@@ -48,27 +48,40 @@ local function ConstructIconPicker(frame)
end end
local usedIcons = {}; local usedIcons = {};
local AddButton = function(name, icon)
local button = AceGUI:Create("WeakAurasIconButton");
button:SetName(name);
button:SetTexture(icon);
button:SetClick(function()
group:Pick(icon);
end);
scroll:AddChild(button);
usedIcons[icon] = true;
end
local num = 0; local num = 0;
if(subname and subname ~= "") then if(subname and subname ~= "") then
for name, icons in pairs(spellCache.Get()) do for name, icons in pairs(spellCache.Get()) do
local bestDistance = math.huge;
local bestName;
if(name:lower():find(subname, 1, true)) then if(name:lower():find(subname, 1, true)) then
if icons.spells then
for spellId, icon in pairs(icons) do for spellId, icon in pairs(icons.spells) do
if (not usedIcons[icon]) then if (not usedIcons[icon]) then
local button = AceGUI:Create("WeakAurasIconButton"); AddButton(name, icon)
button:SetName(name); num = num + 1;
button:SetTexture(icon); if(num >= 500) then
button:SetClick(function() break;
group:Pick(icon); end
end); end
scroll:AddChild(button); end
elseif icons.achievements then
usedIcons[icon] = true; for _, icon in pairs(icons.achievements) do
num = num + 1; if (not usedIcons[icon]) then
if(num >= 500) then AddButton(name, icon)
break; num = num + 1;
if(num >= 500) then
break;
end
end end
end end
end end
@@ -88,7 +101,6 @@ local function ConstructIconPicker(frame)
input:SetWidth(170); input:SetWidth(170);
input:SetHeight(15); input:SetHeight(15);
input:SetPoint("BOTTOMRIGHT", group.frame, "TOPRIGHT", -12, -5); input:SetPoint("BOTTOMRIGHT", group.frame, "TOPRIGHT", -12, -5);
WeakAuras.input = input;
local inputLabel = input:CreateFontString(nil, "OVERLAY", "GameFontNormal"); local inputLabel = input:CreateFontString(nil, "OVERLAY", "GameFontNormal");
inputLabel:SetText(L["Search"]); inputLabel:SetText(L["Search"]);
@@ -189,7 +201,6 @@ local function ConstructIconPicker(frame)
close:SetWidth(100); close:SetWidth(100);
close:SetText(L["Okay"]); close:SetText(L["Okay"]);
scroll.frame:SetPoint("BOTTOM", close, "TOP", 0, 10);
return group return group
end end
@@ -748,7 +748,7 @@ function WeakAuras.CreateFrame()
tremove(tempGroup.controlledChildren, index) tremove(tempGroup.controlledChildren, index)
displayButtons[id]:ClearPick() displayButtons[id]:ClearPick()
WeakAuras.ReloadTriggerOptions(tempGroup) WeakAuras.AddOption(tempGroup.id, tempGroup)
self:FillOptions(displayOptions[tempGroup.id]) self:FillOptions(displayOptions[tempGroup.id])
end end
@@ -962,7 +962,7 @@ function WeakAuras.CreateFrame()
end end
end end
WeakAuras.ReloadTriggerOptions(data) WeakAuras.AddOption(data.id, data)
self:FillOptions(displayOptions[id], tab) -- TODO: remove tab parametter once legacy aura trigger is removed self:FillOptions(displayOptions[id], tab) -- TODO: remove tab parametter once legacy aura trigger is removed
WeakAuras.SetMoverSizer(id) WeakAuras.SetMoverSizer(id)
@@ -1041,7 +1041,7 @@ function WeakAuras.CreateFrame()
WeakAuras.EnsureOptions(id) WeakAuras.EnsureOptions(id)
displayButtons[id]:Pick() displayButtons[id]:Pick()
tinsert(tempGroup.controlledChildren, id) tinsert(tempGroup.controlledChildren, id)
WeakAuras.ReloadTriggerOptions(tempGroup) WeakAuras.AddOption(tempGroup.id, tempGroup)
self:FillOptions(displayOptions[tempGroup.id]) self:FillOptions(displayOptions[tempGroup.id])
end end
end end
@@ -1062,7 +1062,7 @@ function WeakAuras.CreateFrame()
tinsert(tempGroup.controlledChildren, id) tinsert(tempGroup.controlledChildren, id)
end end
end end
WeakAuras.ReloadTriggerOptions(tempGroup) WeakAuras.AddOption(tempGroup.id, tempGroup)
self:FillOptions(displayOptions[tempGroup.id]) self:FillOptions(displayOptions[tempGroup.id])
self.pickedDisplay = tempGroup self.pickedDisplay = tempGroup
end end
@@ -146,39 +146,6 @@ function(allstates, event, ...)
index = , index = ,
} }
return true return true
end]=]
},
{
name = "Text: Decimals (percentage)",
snippet = [=[
function()
-- Change percentpower as needed
-- Change [1] to other your trigger number
-- The 0 in `"%.0f"` controls how many decimal places it will round to
if aura_env.states[1] and aura_env.states[1].percentpower then
return string.format("%.0f", aura_env.states[1].percentpower)
end
end]=]
},
{
name = "Text: Abbreviate numbers",
snippet = [=[
function()
-- Change tooltip1 to your value
-- Change [1] to other your trigger number
-- If using a tooltip value, be sure to tick Use Tooltip Values in the trigger
if aura_env.states[1] and aura_env.states[1].tooltip1 then
return AbbreviateNumbers(aura_env.states[1].tooltip1)
end
end]=]
},
{
name = "Text: Colored Name",
snippet = [=[
function()
if aura_env.states[1] and aura_env.states[1].unit then
return WA_ClassColorName(aura_env.states[1].unit)
end
end]=] end]=]
}, },
} }
+39 -29
View File
@@ -29,10 +29,11 @@ local function createOptions(id, data)
set = function(info, v) set = function(info, v)
data.displayText = WeakAuras.ReplaceLocalizedRaidMarkers(v); data.displayText = WeakAuras.ReplaceLocalizedRaidMarkers(v);
WeakAuras.Add(data); WeakAuras.Add(data);
WeakAuras.ReloadOptions2(data.id, data)
WeakAuras.UpdateThumbnail(data); WeakAuras.UpdateThumbnail(data);
WeakAuras.SetIconNames(data); WeakAuras.SetIconNames(data);
WeakAuras.ResetMoverSizer(); WeakAuras.ResetMoverSizer();
end end,
}, },
customTextUpdate = { customTextUpdate = {
type = "select", type = "select",
@@ -43,33 +44,6 @@ local function createOptions(id, data)
order = 36 order = 36
}, },
-- code editor added below -- code editor added below
progressPrecision = {
type = "select",
width = WeakAuras.normalWidth,
order = 39,
name = L["Remaining Time Precision"],
values = WeakAuras.precision_types,
get = function() return data.progressPrecision or 1 end,
hidden = function() return not (WeakAuras.ContainsPlaceHolders(data.displayText, "pt"));
end,
disabled = function()
return not WeakAuras.ContainsPlaceHolders(data.displayText, "p");
end
},
totalPrecision = {
type = "select",
width = WeakAuras.normalWidth,
order = 39.5,
name = L["Total Time Precision"],
values = WeakAuras.precision_types,
get = function() return data.totalPrecision or 1 end,
hidden = function()
return not (WeakAuras.ContainsPlaceHolders(data.displayText, "pt"));
end,
disabled = function()
return not WeakAuras.ContainsPlaceHolders(data.displayText, "t");
end
},
font = { font = {
type = "select", type = "select",
@@ -269,6 +243,43 @@ local function createOptions(id, data)
WeakAuras.AddCodeOption(options, data, L["Custom Function"], "customText", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-text", WeakAuras.AddCodeOption(options, data, L["Custom Function"], "customText", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-text",
37, function() return not WeakAuras.ContainsCustomPlaceHolder(data.displayText) end, {"customText"}, false); 37, function() return not WeakAuras.ContainsCustomPlaceHolder(data.displayText) end, {"customText"}, false);
-- Add Text Format Options
local input = data.displayText
local hidden = function()
return WeakAuras.IsCollapsed("format_option", "text", "displayText", true)
end
local setHidden = function(hidden)
WeakAuras.SetCollapsed("format_option", "text", "displayText", hidden)
end
local get = function(key)
return data["displayText_format_" .. key]
end
local order = 12
local function addOption(key, option)
option.order = order
order = order + 0.01
if option.reloadOptions then
option.reloadOptions = nil
option.set = function(info, v)
data["displayText_format_" .. key] = v
WeakAuras.Add(data)
WeakAuras.ReloadOptions2(data.id, data)
end
end
options["displayText_format_" .. key] = option
end
WeakAuras.AddTextFormatOption(input, true, get, addOption, hidden, setHidden)
addOption("footer", {
type = "description",
name = "",
width = WeakAuras.doubleWidth,
hidden = hidden
})
return { return {
text = options; text = options;
position = WeakAuras.PositionOptions(id, data, nil, true); position = WeakAuras.PositionOptions(id, data, nil, true);
@@ -341,7 +352,6 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size)
local function UpdateText() local function UpdateText()
local textStr = data.displayText; local textStr = data.displayText;
textStr = WeakAuras.ReplacePlaceHolders(textStr, borderframe);
text:SetText(textStr); text:SetText(textStr);
rescroll(); rescroll();
end end
+1 -1
View File
@@ -134,7 +134,7 @@ local function modifyThumbnail(parent, region, data, fullModify, size)
region.texture:SetHeight(scale * data.height); region.texture:SetHeight(scale * data.height);
end end
WeakAuras.SetTexture(region.texture, data.texture); region.texture:SetTexture(data.texture);
region.texture:SetVertexColor(data.color[1], data.color[2], data.color[3], data.color[4]); region.texture:SetVertexColor(data.color[1], data.color[2], data.color[3], data.color[4]);
region.texture:SetBlendMode(data.blendMode); region.texture:SetBlendMode(data.blendMode);
+40 -36
View File
@@ -82,14 +82,14 @@ local function createOptions(parentData, data, index, subIndex)
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
dialogControl = "LSM30_Font", dialogControl = "LSM30_Font",
name = L["Font"], name = L["Font"],
order = 12, order = 13,
values = AceGUIWidgetLSMlists.font, values = AceGUIWidgetLSMlists.font,
}, },
text_fontSize = { text_fontSize = {
type = "range", type = "range",
width = WeakAuras.normalWidth, width = WeakAuras.normalWidth,
name = L["Size"], name = L["Size"],
order = 13, order = 14,
min = 6, min = 6,
softMax = 72, softMax = 72,
step = 1, step = 1,
@@ -423,11 +423,9 @@ local function createOptions(parentData, data, index, subIndex)
end end
end end
local CheckForTimePlaceHolders = CheckTextOptions("pt")
local commonTextOptions = { local commonTextOptions = {
__title = L["Common Text"], __title = L["Common Text"],
__hidden = function() return hideCustomTextOption() and CheckForTimePlaceHolders() end, __hidden = function() return hideCustomTextOption() end,
text_customTextUpdate = { text_customTextUpdate = {
type = "select", type = "select",
width = WeakAuras.doubleWidth, width = WeakAuras.doubleWidth,
@@ -442,42 +440,48 @@ local function createOptions(parentData, data, index, subIndex)
WeakAuras.ReloadOptions2(parentData.id, parentData) WeakAuras.ReloadOptions2(parentData.id, parentData)
end end
}, },
-- Code Editor added below
text_progressPrecision = {
type = "select",
width = WeakAuras.normalWidth,
hidden = CheckForTimePlaceHolders,
disabled = CheckTextOptions("p"),
order = 5,
name = L["Remaining Time Precision"],
values = WeakAuras.precision_types,
get = function() return parentData.progressPrecision or 1 end,
set = function(info, v)
parentData.progressPrecision = v
WeakAuras.Add(parentData)
WeakAuras.ReloadOptions2(parentData.id, parentData)
end,
},
text_totalPrecision = {
type = "select",
width = WeakAuras.normalWidth,
hidden = CheckForTimePlaceHolders,
disabled = CheckTextOptions("t"),
order = 6,
name = L["Total Time Precision"],
values = WeakAuras.precision_types,
get = function() return parentData.totalPrecision or 1 end,
set = function(info, v)
parentData.totalPrecision = v
WeakAuras.Add(parentData)
WeakAuras.ReloadOptions2(parentData.id, parentData)
end,
},
} }
WeakAuras.AddCodeOption(commonTextOptions, parentData, L["Custom Function"], "customText", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-text", WeakAuras.AddCodeOption(commonTextOptions, parentData, L["Custom Function"], "customText", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-text",
4, hideCustomTextOption, {"customText"}, false) 4, hideCustomTextOption, {"customText"}, false)
-- Add Text Format Options
local input = data["text_text"]
local hidden = function()
return WeakAuras.IsCollapsed("format_option", "text", "text_text", true)
end
local setHidden = function(hidden)
WeakAuras.SetCollapsed("format_option", "text", "text_text", hidden)
end
local get = function(key)
return data["text_text_format_" .. key]
end
local order = 12
local function addOption(key, option)
option.order = order
order = order + 0.01
if option.reloadOptions then
option.reloadOptions = nil
option.set = function(info, v)
data["text_text_format_" .. key] = v
WeakAuras.Add(parentData)
WeakAuras.ReloadOptions2(parentData.id, parentData)
end
end
options["text_text_format_" .. key] = option
end
WeakAuras.AddTextFormatOption(input, true, get, addOption, hidden, setHidden)
addOption("footer", {
type = "description",
name = "",
width = WeakAuras.doubleWidth,
hidden = hidden
})
return options, commonTextOptions return options, commonTextOptions
end end
+77 -30
View File
@@ -1064,35 +1064,7 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon)
odb.idCache = nil; odb.idCache = nil;
end end
odb.spellCache = odb.spellCache or {}; odb.spellCache = odb.spellCache or {};
spellCache.Load(odb.spellCache); spellCache.Load(odb);
local _, build = GetBuildInfo();
local locale = GetLocale();
local version = WeakAuras.versionString
local num = 0;
for i,v in pairs(odb.spellCache) do
num = num + 1;
end
if(num < 39000 or odb.locale ~= locale or odb.build ~= build or odb.version ~= version) then
spellCache.Build();
odb.build = build;
odb.locale = locale;
odb.version = version;
end
-- Updates the icon cache with whatever icons WeakAuras core has actually used.
-- This helps keep name<->icon matches relevant.
for name, icons in pairs(db.dynamicIconCache) do
if db.dynamicIconCache[name] then
for spellId, icon in pairs(db.dynamicIconCache[name]) do
spellCache.AddIcon(name, spellId, icon)
end
end
end
if odb.magnetAlign == nil then if odb.magnetAlign == nil then
odb.magnetAlign = true odb.magnetAlign = true
@@ -1392,6 +1364,8 @@ function WeakAuras.ShowOptions(msg)
WeakAuras.Pause(); WeakAuras.Pause();
WeakAuras.SetFakeStates() WeakAuras.SetFakeStates()
WeakAuras.spellCache.Build()
if (firstLoad) then if (firstLoad) then
frame = WeakAuras.CreateFrame(); frame = WeakAuras.CreateFrame();
frame.buttonsScroll.frame:Show(); frame.buttonsScroll.frame:Show();
@@ -2551,7 +2525,7 @@ local function flattenRegionOptions(allOptions, isGroupTab)
end end
local function parsePrefix(input, data, create) local function parsePrefix(input, data, create)
local subRegionIndex, property = string.match(input, "^sub%.(%d+)%..+%.(.+)") local subRegionIndex, property = string.match(input, "^sub%.(%d+)%..-%.(.+)")
subRegionIndex = tonumber(subRegionIndex) subRegionIndex = tonumber(subRegionIndex)
if subRegionIndex then if subRegionIndex then
if create then if create then
@@ -4837,3 +4811,76 @@ end
function WeakAuras.DeleteCollapsedData(id) function WeakAuras.DeleteCollapsedData(id)
collapsedOptions[id] = nil collapsedOptions[id] = nil
end end
function WeakAuras.AddTextFormatOption(input, withHeader, get, addOption, hidden, setHidden)
local headerOption
if withHeader then
headerOption = {
type = "execute",
control = "WeakAurasExpandSmall",
name = function()
return L["|cFFffcc00Format Options|r"]
end,
width = WeakAuras.doubleWidth,
func = function()
setHidden(not hidden())
end,
image = function()
return hidden() and "Interface\\AddOns\\WeakAuras\\Media\\Textures\\edit" or "Interface\\AddOns\\WeakAuras\\Media\\Textures\\editdown"
end,
imageWidth = 24,
imageHeight = 24
}
addOption("header", headerOption)
else
hidden = false
end
local seenSymbols = {}
WeakAuras.ParseTextStr(input, function(symbol)
if not seenSymbols[symbol] then
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
sym = sym or symbol
addOption(symbol .. "desc", {
type = "description",
name = L["Format for %s"]:format("%" .. symbol),
width = WeakAuras.normalWidth,
hidden = hidden
})
if sym == "c" or sym == "i" then
-- No special options for these
else
addOption(symbol .. "_format", {
type = "select",
name = L["Format"],
width = WeakAuras.normalWidth,
values = WeakAuras.format_types_display,
hidden = hidden,
reloadOptions = true
})
local selectedFormat = get(symbol .. "_format")
if (WeakAuras.format_types[selectedFormat]) then
WeakAuras.format_types[selectedFormat].AddOptions(symbol, hidden, addOption, get)
end
end
end
seenSymbols[symbol] = true
end)
if next(seenSymbols) then
local footerOption = {
type = "header",
name = "",
}
addOption("footer", footerOption)
end
if not next(seenSymbols) and withHeader then
headerOption.hidden = true
end
end