Skip to content

Commit

Permalink
Fix #85: Lua Error - Reputation (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mctalian authored Sep 3, 2024
1 parent 4d64bc1 commit 2ebae04
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 176 deletions.
2 changes: 1 addition & 1 deletion Features/Currency.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
251 changes: 98 additions & 153 deletions Features/Reputation.lua
Original file line number Diff line number Diff line change
@@ -1,195 +1,140 @@
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
self:Disable()
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
21 changes: 4 additions & 17 deletions LootDisplay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down
10 changes: 5 additions & 5 deletions config/Positioning.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions locale/enUS.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2ebae04

Please sign in to comment.