diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 96ed63c..4d11dc3 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -55,20 +55,35 @@ jobs: test_package: runs-on: ubuntu-latest + env: + IS_FORK: ${{ github.event.pull_request.head.repo.fork }} steps: - name: Checkout code + if: env.IS_FORK == 'false' uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.ref }} fetch-depth: 0 + - name: Checkout code (fork) + if: env.IS_FORK == 'true' + uses: actions/checkout@v4 + - name: Package + if: env.IS_FORK == 'false' uses: BigWigsMods/packager@v2 with: args: -d pandoc: "false" + - name: Package (fork) + if: env.IS_FORK == 'true' + uses: BigWigsMods/packager@v2 + with: + args: -d -n {package-name}-pr${{github.event.number}}-{nolib}{classic} + pandoc: "false" + - name: Capture Filenames id: capture-filenames run: | diff --git a/Features/Currency.lua b/Features/Currency.lua index aeafb44..d400de5 100644 --- a/Features/Currency.lua +++ b/Features/Currency.lua @@ -24,7 +24,7 @@ function Currency:CURRENCY_DISPLAY_UPDATE(_, ...) end local info = C_CurrencyInfo.GetCurrencyInfo(currencyType) - if info == nil or info.description == "" then + if info == nil or info.description == "" or info.iconFileID == nil then return end diff --git a/Features/Reputation.lua b/Features/Reputation.lua index c4de2f0..3913054 100644 --- a/Features/Reputation.lua +++ b/Features/Reputation.lua @@ -1,13 +1,10 @@ -local Rep = G_RLF.RLF:NewModule("Reputation", "AceEvent-3.0") - -local repData = {} -local paragonRepData = {} -local majorRepData = {} -local cachedFactionCount -local showLegacyReps -local firstNilIndex = 1 +local Rep = G_RLF.RLF:NewModule("Reputation", "AceEvent-3.0", "AceTimer-3.0") +local locale function Rep:OnInitialize() + locale = GetLocale() + G_RLF.db.global.factionMaps = G_RLF.db.global.factionMaps or {} + G_RLF.db.global.factionMaps[locale] = G_RLF.db.global.factionMaps[locale] or {} if G_RLF.db.global.repFeed then self:Enable() else @@ -15,181 +12,129 @@ function Rep:OnInitialize() end end -local function snapshot() - showLegacyReps = C_Reputation.AreLegacyReputationsShown() +local function countMappedFactions() local count = 0 - local i = 1 - local factionData = C_Reputation.GetFactionDataByIndex(i) - while factionData ~= nil do - if not factionData.isHeader or factionData.isHeaderWithRep then - if C_Reputation.IsFactionParagon(factionData.factionID) then - -- Need to support Paragon factions - local value, max = C_Reputation.GetFactionParagonInfo(factionData.factionID) - paragonRepData[factionData.factionID] = value - elseif C_Reputation.IsMajorFaction(factionData.factionID) then - -- Need to support Major factions - local majorFactionData = C_MajorFactions.GetMajorFactionData(factionData.factionID) - local level = majorFactionData.renownLevel - local rep = majorFactionData.renownReputationEarned - local max = majorFactionData.renownLevelThreshold - majorRepData[factionData.factionID] = { level, rep, max } - else - repData[factionData.factionID] = factionData.currentStanding - end + for k, v in pairs(G_RLF.db.global.factionMaps[locale]) do + if v then count = count + 1 end - i = i + 1 - factionData = C_Reputation.GetFactionDataByIndex(i) end - firstNilIndex = i - cachedFactionCount = count -end - -function Rep:OnDisable() - self:UnregisterEvent("PLAYER_ENTERING_WORLD") - self:UnregisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") - self:UnregisterEvent("MAJOR_FACTION_RENOWN_LEVEL_CHANGED") + return count end -function Rep:OnEnable() - self:RegisterEvent("PLAYER_ENTERING_WORLD") - self:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") - self:RegisterEvent("MAJOR_FACTION_RENOWN_LEVEL_CHANGED") - if showLegacyReps == nil then - snapshot() - end -end - -local function initializeParagonFaction(fId) - if not paragonRepData[fId] then - paragonRepData[fId] = 0 +local function buildFactionLocaleMap(findName) + local numFactions = C_Reputation.GetNumFactions() + if countMappedFactions() == numFactions and not findName then + return end -end - -local function initializeMajorFaction(fId, mfd) - if not majorRepData[fId] then - local level = mfd.renownLevel - local max = mfd.renownLevelThreshold - majorRepData[fId] = { level, 0, max } + for i = 1, numFactions do + local factionData = C_Reputation.GetFactionDataByIndex(i) + if factionData then + if not G_RLF.db.global.factionMaps[locale][factionData.name] then + G_RLF.db.global.factionMaps[locale][factionData.name] = factionData.factionID + end + if findName and factionData.name == findName then + break + end + end end end -local function initializeNormalFaction(fId) - if not repData[fId] then - repData[fId] = 0 +-- Function to extract faction and reputation change using precomputed patterns +local function extractFactionAndRep(message, patterns) + for _, segments in ipairs(patterns) do + local prePattern, midPattern, postPattern = unpack(segments) + local preMatchStart, preMatchEnd = string.find(message, prePattern, 1, true) + if preMatchStart then + local msgLoop = message:sub(preMatchEnd + 1) + local midMatchStart, midMatchEnd = string.find(msgLoop, midPattern, 1, true) + if midMatchStart then + local postMatchStart, postMatchEnd = string.find(msgLoop, postPattern, midMatchEnd, true) + if postMatchStart then + local faction = msgLoop:sub(1, midMatchStart - 1) + local rep = msgLoop:sub(midMatchEnd + 1, postMatchStart - 1) + return faction, tonumber(rep) + end + end + end end + return nil, nil end -local function initializeRepFaction(fId) - if C_Reputation.IsFactionParagon(fId) then - initializeParagonFaction(fId) - elseif C_Reputation.IsMajorFaction(fId) then - local mfd = C_MajorFactions.GetMajorFactionData(fId) - initializeMajorFaction(fId, mfd) - else - initializeNormalFaction(fId) +-- Precompute pattern segments to optimize runtime message parsing +local function precomputePatternSegments(patterns) + local computedPatterns = {} + for _, pattern in ipairs(patterns) do + local preStart, preEnd = string.find(pattern, "%%s") + local prePattern = string.sub(pattern, 1, preStart - 1) + local midStart, midEnd = string.find(pattern, "%%d", preEnd + 1) + local midPattern = string.sub(pattern, preEnd + 1, midStart - 1) + local postPattern = string.sub(pattern, midEnd + 1) + table.insert(computedPatterns, { prePattern, midPattern, postPattern }) end + return computedPatterns end -local function handleMajorFactionRepChange(id, level) - local factionData = C_Reputation.GetFactionDataByID(id) - local majorFactionData = C_MajorFactions.GetMajorFactionData(id) - local level = level or C_MajorFactions.GetCurrentRenownLevel(id) - local rep = majorFactionData.renownReputationEarned - local max = majorFactionData.renownLevelThreshold - local oldLevel, oldRep, oldMax = unpack(majorRepData[id]) +local increasePatterns = precomputePatternSegments({ + FACTION_STANDING_INCREASED, + FACTION_STANDING_INCREASED_ACCOUNT_WIDE, + FACTION_STANDING_INCREASED_ACH_BONUS, + FACTION_STANDING_INCREASED_ACH_BONUS_ACCOUNT_WIDE, + FACTION_STANDING_INCREASED_BONUS, + FACTION_STANDING_INCREASED_DOUBLE_BONUS, +}) - if rep > oldRep then - G_RLF.LootDisplay:ShowRep(rep - oldRep, factionData) - elseif rep < oldRep then - G_RLF.LootDisplay:ShowRep(oldMax - oldRep + rep, factionData) - elseif rep == oldRep and level > oldLevel then - G_RLF.LootDisplay:ShowRep(oldMax - oldRep + rep, factionData) - end - majorRepData[id] = { level, rep, max } -end +local decreasePatterns = precomputePatternSegments({ + FACTION_STANDING_DECREASED, + FACTION_STANDING_DECREASED_ACCOUNT_WIDE, +}) -local function factionListHasNotChanged() - return C_Reputation.GetFactionDataByIndex(firstNilIndex) == nil -- if a new index hasn't been added - and firstNilIndex > 1 -- we had at least 1 faction before - and C_Reputation.GetFactionDataByIndex(firstNilIndex - 1) -- the previous faction is still not nil - and showLegacyReps == C_Reputation.AreLegacyReputationsShown() -- Showing Legacy Reputations hasn't changed -end - -local function addAnyNewFactions() - if factionListHasNotChanged() then - -- No new factions, skipping - return - end - - showLegacyReps = C_Reputation.AreLegacyReputationsShown() - - local i = 1 - local factionData = C_Reputation.GetFactionDataByIndex(i) - while factionData ~= nil do - if not factionData.isHeader or factionData.isHeaderWithRep then - local fId = factionData.factionID - initializeRepFaction(fId) - end - i = i + 1 - factionData = C_Reputation.GetFactionDataByIndex(i) - end - - firstNilIndex = i +function Rep:OnDisable() + self:UnregisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") end -function Rep:PLAYER_ENTERING_WORLD() - G_RLF:fn(snapshot) +function Rep:OnEnable() + self:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") end -local function findDelta() - addAnyNewFactions() - - if G_RLF.db.global.repFeed then - -- Normal rep factions - for k, v in pairs(repData) do - local factionData = C_Reputation.GetFactionDataByID(k) - if factionData.currentStanding ~= v then - G_RLF.LootDisplay:ShowRep(factionData.currentStanding - v, factionData) - repData[k] = factionData.currentStanding +function Rep:CHAT_MSG_COMBAT_FACTION_CHANGE(_, message) + G_RLF:fn(function() + local faction, repChange = extractFactionAndRep(message, increasePatterns) + if not faction then + faction, repChange = extractFactionAndRep(message, decreasePatterns) + if repChange then + repChange = -repChange end end - -- Paragon facions - for k, v in pairs(paragonRepData) do - local factionData = C_Reputation.GetFactionDataByID(k) - local value, max = C_Reputation.GetFactionParagonInfo(k) - if value ~= v then - -- Not thoroughly tested - if v == max then - -- We were at paragon cap, then the reward was obtained, so we started back at 0 - G_RLF.LootDisplay:ShowRep(value, factionData) - else - G_RLF.LootDisplay:ShowRep(value - v, factionData) + local r, g, b, color + if G_RLF.db.global.factionMaps[locale][faction] == nil then + -- attempt to find the missing faction's ID + buildFactionLocaleMap(faction) + end + + if G_RLF.db.global.factionMaps[locale][faction] then + local fId = G_RLF.db.global.factionMaps[locale][faction] + if C_Reputation.IsMajorFaction(fId) then + color = ACCOUNT_WIDE_FONT_COLOR + elseif C_Reputation.IsFactionParagon(fId) then + color = FACTION_GREEN_COLOR + else + local factionData = C_Reputation.GetFactionDataByID(fId) + if factionData.reaction then + color = FACTION_BAR_COLORS[factionData.reaction] end - paragonRepData[k] = value end end - -- Major factions - for k, v in pairs(majorRepData) do - -- Delay in case the rep change caused a level up, - -- the level up event should take precedent. - C_Timer.After(0.5, function() - handleMajorFactionRepChange(k) - end) - end - end -end - -function Rep:MAJOR_FACTION_RENOWN_LEVEL_CHANGED(_, mfID, newLevel, oldLevel) - G_RLF:fn(addAnyNewFactions) - G_RLF:fn(initializeMajorFaction, mfID) - G_RLF:fn(handleMajorFactionRepChange, mfID, newLevel) -end + if color then + r, g, b = color.r, color.g, color.b + end -function Rep:CHAT_MSG_COMBAT_FACTION_CHANGE() - G_RLF:fn(findDelta) + if faction and repChange then + G_RLF.LootDisplay:ShowRep(repChange, faction, r, g, b) + end + end) end return Rep diff --git a/LootDisplay.lua b/LootDisplay.lua index 5588bde..0cf0417 100644 --- a/LootDisplay.lua +++ b/LootDisplay.lua @@ -237,8 +237,8 @@ function LootDisplay:ShowXP(experience) row.fadeOutAnimation:Play() end -function LootDisplay:ShowRep(rep, factionData) - local key = "REP_" .. factionData.factionID -- Use ID as a unique key +function LootDisplay:ShowRep(rep, factionName, r, g, b) + local key = "REP_" .. factionName -- Use ID as a unique key local text -- Check if the item or currency is already displayed @@ -262,22 +262,9 @@ function LootDisplay:ShowRep(rep, factionData) if rep < 0 then sign = "-" end - text = sign .. math.abs(row.rep) .. " " .. factionData.name + text = sign .. math.abs(row.rep) .. " " .. factionName row.amountText:SetText(text) - local r, g, b - if - factionData.reaction - and not C_Reputation.IsFactionParagon(factionData.factionID) - and not C_Reputation.IsMajorFaction(factionData.factionID) - then - r = FACTION_BAR_COLORS[factionData.reaction].r - g = FACTION_BAR_COLORS[factionData.reaction].g - b = FACTION_BAR_COLORS[factionData.reaction].b - else - r = 0.26 - g = 1 - b = 1 - end + local r, g, b = r or 0.5, g or 0.5, b or 1 row.amountText:SetTextColor(r, g, b, 1) row.fadeOutAnimation:Stop() diff --git a/config/Positioning.lua b/config/Positioning.lua index dd8266e..2ad37b6 100644 --- a/config/Positioning.lua +++ b/config/Positioning.lua @@ -9,13 +9,13 @@ G_RLF.defaults.global.frameStrata = "MEDIUM" -- Default frame strata -- Enumerate available frames to anchor to local function EnumerateFrames() local frames = { - [-1] = "Screen", + [-1] = G_RLF.L["Screen"], } local framesToCheck = { - ["UIParent"] = "UIParent", - ["PlayerFrame"] = "PlayerFrame", - ["Minimap"] = "Minimap", - ["MainMenuBarBackpackButton"] = "BagBar", + ["UIParent"] = G_RLF.L["UIParent"], + ["PlayerFrame"] = G_RLF.L["PlayerFrame"], + ["Minimap"] = G_RLF.L["Minimap"], + ["MainMenuBarBackpackButton"] = G_RLF.L["BagBar"], } for f, s in pairs(framesToCheck) do if _G[f] then diff --git a/locale/enUS.lua b/locale/enUS.lua index f25f75e..286c0e2 100644 --- a/locale/enUS.lua +++ b/locale/enUS.lua @@ -65,6 +65,11 @@ L["Drag to Move"] = true L["PositioningDesc"] = "Position and anchor the loot feed." L["Anchor Relative To"] = true L["RelativeToDesc"] = "Select a frame to anchor the loot feed to" +L["Screen"] = true +L["UIParent"] = true +L["PlayerFrame"] = true +L["Minimap"] = true +L["BagBar"] = true L["Anchor Point"] = true L["AnchorPointDesc"] = "Where on the screen to base the loot feed positioning (also impacts sizing direction)" L["Top Left"] = true