You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
12 KiB

local ADDON, Addon = ...
local Mod = Addon:NewModule('ProgressTracker')
Mod.playerDeaths = {}
local lastQuantity
local lastDied
local lastDiedName
local lastDiedTime
local lastAmount
local lastAmountTime
local lastQuantity
local PRIDEFUL_AFFIX_ID = 121
local progressPresets = {}
local function ProcessLasts()
if lastDied and lastDiedTime and lastAmount and lastAmountTime then
if abs(lastAmountTime - lastDiedTime) < 0.1 then
if not AngryKeystones_Data.progress[lastDied] then AngryKeystones_Data.progress[lastDied] = {} end
if AngryKeystones_Data.progress[lastDied][lastAmount] then
AngryKeystones_Data.progress[lastDied][lastAmount] = AngryKeystones_Data.progress[lastDied][lastAmount] + 1
else
AngryKeystones_Data.progress[lastDied][lastAmount] = 1
end
lastDied, lastDiedTime, lastAmount, lastAmountTime, lastDiedName = nil, nil, nil, nil, nil
end
end
end
function Mod:COMBAT_LOG_EVENT_UNFILTERED()
local timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 = CombatLogGetCurrentEventInfo()
if event == "UNIT_DIED" then
if bit.band(destFlags, COMBATLOG_OBJECT_TYPE_NPC) > 0
and bit.band(destFlags, COMBATLOG_OBJECT_CONTROL_NPC) > 0
and (bit.band(destFlags, COMBATLOG_OBJECT_REACTION_HOSTILE) > 0 or bit.band(destFlags, COMBATLOG_OBJECT_REACTION_NEUTRAL) > 0) then
local type, zero, server_id, instance_id, zone_uid, npc_id, spawn_uid = strsplit("-", destGUID)
lastDied = tonumber(npc_id)
lastDiedTime = GetTime()
lastDiedName = destName
ProcessLasts()
end
if bit.band(destFlags, COMBATLOG_OBJECT_TYPE_PLAYER) > 0 then
if UnitIsFeignDeath(destName) then
-- Feign Death
elseif Mod.playerDeaths[destName] then
Mod.playerDeaths[destName] = Mod.playerDeaths[destName] + 1
else
Mod.playerDeaths[destName] = 1
end
--Addon.ObjectiveTracker:UpdatePlayerDeaths()
end
end
end
function Mod:SCENARIO_CRITERIA_UPDATE()
local scenarioType = select(10, C_Scenario.GetInfo())
if scenarioType == LE_SCENARIO_TYPE_CHALLENGE_MODE then
local numCriteria = select(3, C_Scenario.GetStepInfo())
for criteriaIndex = 1, numCriteria do
-- local criteriaString, criteriaType, _, quantity, totalQuantity, _, _, quantityString, _, _, _, _, isWeightedProgress = C_Scenario.GetCriteriaInfo(criteriaIndex)
local criteriaInfo = C_ScenarioInfo.GetCriteriaInfo(criteriaIndex)
if criteriaInfo and criteriaInfo.isWeightedProgress then
local quantityString = criteriaInfo.quantityString
local currentQuantity = quantityString and tonumber( quantityString:match("%d+") )
if lastQuantity and currentQuantity < criteriaInfo.totalQuantity and currentQuantity > lastQuantity then
lastAmount = currentQuantity - lastQuantity
lastAmountTime = GetTime()
ProcessLasts()
end
lastQuantity = currentQuantity
break
end
end
end
end
local function StartTime()
Mod:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
local numCriteria = select(3, C_Scenario.GetStepInfo())
for criteriaIndex = 1, numCriteria do
-- local criteriaString, criteriaType, _, quantity, totalQuantity, _, _, quantityString, _, _, _, _, isWeightedProgress = C_Scenario.GetCriteriaInfo(criteriaIndex)
local criteriaInfo = C_ScenarioInfo.GetCriteriaInfo(criteriaIndex)
if criteriaInfo and criteriaInfo.isWeightedProgress then
local quantityString = criteriaInfo.quantityString
lastQuantity = quantityString and tonumber( quantityString:match("%d+") )
break
end
end
end
local function StopTime()
Mod:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
local function CheckTime(...)
for i = 1, select("#", ...) do
local timerID = select(i, ...)
local _, elapsedTime, type = GetWorldElapsedTime(timerID)
if type == LE_WORLD_ELAPSED_TIMER_TYPE_CHALLENGE_MODE then
local mapID = C_ChallengeMode.GetActiveChallengeMapID()
if mapID then
StartTime()
return
end
end
end
StopTime()
end
local function OnTooltipSetUnit(tooltip)
local scenarioType = select(10, C_Scenario.GetInfo())
if scenarioType == LE_SCENARIO_TYPE_CHALLENGE_MODE and Addon.Config.progressTooltip then
local name, unit = tooltip:GetUnit()
local guid = unit and UnitGUID(unit)
if guid then
local type, zero, server_id, instance_id, zone_uid, npc_id, spawn_uid = strsplit("-", guid)
npc_id = tonumber(npc_id)
local info = AngryKeystones_Data.progress[npc_id]
local preset = progressPresets[npc_id]
if info or preset then
local numCriteria = select(3, C_Scenario.GetStepInfo())
local total
local progressName
for criteriaIndex = 1, numCriteria do
-- local criteriaString, _, _, quantity, totalQuantity, _, _, quantityString, _, _, _, _, isWeightedProgress = C_Scenario.GetCriteriaInfo(criteriaIndex)
local criteriaInfo = C_ScenarioInfo.GetCriteriaInfo(criteriaIndex)
if criteriaInfo and criteriaInfo.isWeightedProgress then
progressName = criteriaInfo.description
total = criteriaInfo.totalQuantity
break
end
end
local value, valueCount
if info then
for amount, count in pairs(info) do
if not valueCount or count > valueCount or (count == valueCount and amount < value) then
value = amount
valueCount = count
end
end
end
if preset and (not value or valueCount == 1) then
value = preset
end
if value and total then
local forcesFormat = format(" - %s: %%s", progressName)
local text
if Addon.Config.progressFormat == 1 or Addon.Config.progressFormat == 4 then
text = format( format(forcesFormat, "+%.2f%%"), value/total*100)
elseif Addon.Config.progressFormat == 2 or Addon.Config.progressFormat == 5 then
text = format( format(forcesFormat, "+%d"), value)
elseif Addon.Config.progressFormat == 3 or Addon.Config.progressFormat == 6 then
text = format( format(forcesFormat, "+%.2f%% - +%d"), value/total*100, value)
end
if text then
local matcher = format(forcesFormat, "%d+%%")
for i=2, tooltip:NumLines() do
local tiptext = _G["GameTooltipTextLeft"..i]
local linetext = tiptext and tiptext:GetText()
if linetext and linetext:match(matcher) then
tiptext:SetText(text)
tooltip:Show()
end
end
end
end
end
end
end
end
function Mod:GeneratePreset()
local ret = {}
for npcID, info in pairs(AngryKeystones_Data.progress) do
local value, valueCount
for amount, count in pairs(info) do
if not valueCount or count > valueCount or (count == valueCount and amount < value) then
value = amount
valueCount = count
end
end
ret[npcID] = value
end
AngryKeystones_Data.preset = ret
return ret
end
function Mod:PLAYER_ENTERING_WORLD(...) CheckTime(GetWorldElapsedTimers()) end
function Mod:WORLD_STATE_TIMER_START(...) local timerID = ...; CheckTime(timerID) end
function Mod:WORLD_STATE_TIMER_STOP(...) local timerID = ...; StopTime(timerID) end
function Mod:CHALLENGE_MODE_START(...) CheckTime(GetWorldElapsedTimers()) end
function Mod:CHALLENGE_MODE_RESET(...) wipe(Mod.playerDeaths) end
local function ProgressBar_SetValue(self, percent)
-- local _, _, _, _, totalQuantity, _, _, quantityString, _, _, _, _, _ = C_Scenario.GetCriteriaInfo(self.criteriaIndex)
local scenarioType = select(10, C_Scenario.GetInfo())
if scenarioType ~= LE_SCENARIO_TYPE_CHALLENGE_MODE then return end
local numCriteria = select(3, C_Scenario.GetStepInfo())
local criteriaInfo
local cInfo
for criteriaIndex = 1, numCriteria do
cInfo = C_ScenarioInfo.GetCriteriaInfo(criteriaIndex)
if cInfo and cInfo.isWeightedProgress then
criteriaInfo = cInfo
break
end
end
if not criteriaInfo then return end
local totalQuantity = criteriaInfo.totalQuantity
local quantityString = criteriaInfo.quantityString
local currentQuantity = quantityString and tonumber( quantityString:match("%d+") )
if currentQuantity and totalQuantity then
if Addon.Config.progressFormat == 1 then
self.Bar.Label:SetFormattedText("%.2f%%", currentQuantity/totalQuantity*100)
elseif Addon.Config.progressFormat == 2 then
self.Bar.Label:SetFormattedText("%d/%d", currentQuantity, totalQuantity)
elseif Addon.Config.progressFormat == 3 then
self.Bar.Label:SetFormattedText("%.2f%% - %d/%d", currentQuantity/totalQuantity*100, currentQuantity, totalQuantity)
elseif Addon.Config.progressFormat == 4 then
self.Bar.Label:SetFormattedText("%.2f%% (%.2f%%)", currentQuantity/totalQuantity*100, (totalQuantity-currentQuantity)/totalQuantity*100)
elseif Addon.Config.progressFormat == 5 then
self.Bar.Label:SetFormattedText("%d/%d (%d)", currentQuantity, totalQuantity, totalQuantity - currentQuantity)
elseif Addon.Config.progressFormat == 6 then
self.Bar.Label:SetFormattedText("%.2f%% (%.2f%%) - %d/%d (%d)", currentQuantity/totalQuantity*100, (totalQuantity-currentQuantity)/totalQuantity*100, currentQuantity, totalQuantity, totalQuantity - currentQuantity)
end
end
end
local progressBarFound = false
local function findProgressBar()
if progressBarFound then return end
local usedBars = ScenarioObjectiveTracker.usedProgressBars or {}
for _, bar in pairs(usedBars) do
if bar.used then
hooksecurefunc(bar, "SetValue", ProgressBar_SetValue)
progressBarFound = true
break
end
end
end
hooksecurefunc(ScenarioObjectiveTracker.ObjectivesBlock, "AddProgressBar", findProgressBar )
local function DeathCount_OnEnter(self)
local parent = self:GetParent()
GameTooltip:SetOwner(self, "ANCHOR_LEFT")
GameTooltip:SetText(CHALLENGE_MODE_DEATH_COUNT_TITLE:format(parent.deathCount), 1, 1, 1)
GameTooltip:AddLine(CHALLENGE_MODE_DEATH_COUNT_DESCRIPTION:format(SecondsToClock(parent.timeLost, false)))
GameTooltip:AddLine(" ")
local list = {}
local deathsCount = 0
for unit,count in pairs(Mod.playerDeaths) do
local _, class = UnitClass(unit)
deathsCount = deathsCount + count
table.insert(list, { count = count, unit = unit, class = class })
end
table.sort(list, function(a, b)
if a.count ~= b.count then
return a.count > b.count
else
return a.unit < b.unit
end
end)
for _,item in ipairs(list) do
local color = RAID_CLASS_COLORS[item.class] or HIGHLIGHT_FONT_COLOR
GameTooltip:AddDoubleLine(item.unit, item.count, color.r, color.g, color.b, HIGHLIGHT_FONT_COLOR:GetRGB())
end
GameTooltip:Show()
end
function Mod:Blizzard_ObjectiveTracker()
ScenarioObjectiveTracker.ChallengeModeBlock.DeathCount:SetScript("OnEnter", DeathCount_OnEnter)
end
function Mod:Startup()
if not AngryKeystones_Data then
AngryKeystones_Data = {}
end
if not AngryKeystones_Data.progress then
AngryKeystones_Data = { progress = AngryKeystones_Data }
end
if not AngryKeystones_Data.state then AngryKeystones_Data.state = {} end
local mapID = C_ChallengeMode.GetActiveChallengeMapID()
if select(10, C_Scenario.GetInfo()) == LE_SCENARIO_TYPE_CHALLENGE_MODE and mapID and mapID == AngryKeystones_Data.state.mapID and AngryKeystones_Data.state.playerDeaths then
Mod.playerDeaths = AngryKeystones_Data.state.playerDeaths
else
AngryKeystones_Data.state.mapID = nil
AngryKeystones_Data.state.playerDeaths = Mod.playerDeaths
end
self:RegisterEvent("SCENARIO_CRITERIA_UPDATE")
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("WORLD_STATE_TIMER_START")
self:RegisterEvent("WORLD_STATE_TIMER_STOP")
self:RegisterEvent("CHALLENGE_MODE_START")
self:RegisterEvent("CHALLENGE_MODE_RESET")
self:RegisterAddOnLoaded("Blizzard_ObjectiveTracker")
CheckTime(GetWorldElapsedTimers())
TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Unit, OnTooltipSetUnit)
Addon.Config:RegisterCallback('progressFormat', function()
local usedBars = ScenarioObjectiveTracker.usedProgressBars or {}
for _, bar in pairs(usedBars) do
if bar.used then
ProgressBar_SetValue(bar)
break
end
end
end)
end
-- hooksecurefunc("ScenarioTrackerProgressBar_SetValue", ProgressBar_SetValue)