local _ , addon = ...
if not addon.IsGame_11_0_2 then return end ;
local L = addon.L ;
local API = addon.API ;
local UIFrameFade = API.UIFrameFade ;
local TimeLeftTextToSeconds = API.TimeLeftTextToSeconds ;
local IsInDelves = API.IsInDelves ;
local GetDelvesForMap = C_AreaPoiInfo.GetDelvesForMap ; --Fail to obtain Bountiful Delves (Bountiful Delves use AreaPOIPinTemplate, Other Delves use DelveEntrancePinTemplate)
local GetAreaPOIInfo = C_AreaPoiInfo.GetAreaPOIInfo ;
local C_UIWidgetManager = C_UIWidgetManager ;
local GetMajorFactionRenownInfo = C_MajorFactions.GetMajorFactionRenownInfo ;
local GetStepInfo = C_Scenario.GetStepInfo ;
local UIParent = UIParent ;
local DELVES_SEASON_FACTION ; --2644
local DelvePOI = {
--{mapID, normalPoi, bountifulPoi}
--Isle of Dorn
{ 2248 , 7863 , 7787 } , --Earthcrawl Mines
{ 2248 , 7864 , 7779 } , --Fungal Folly
{ 2248 , 7865 , 7781 } , --Kriegval's Rest
--Ringing Deeps
{ 2214 , 7867 , 7788 } , --The Dread Pit
{ 2214 , 7866 , 7782 } , --The Waterworks
--Hallowfall
{ 2215 , 7869 , 7780 } , --Mycomancer Cavern
{ 2215 , 7868 , 7785 } , --Nightfall Sanctum
{ 2215 , 7871 , 7789 } , --Skittering Breach
{ 2215 , 7870 , 7783 } , --The Sinkhole
--Azj-Kahet
{ 2255 , 7873 , 7784 } , --Tak-Rethan Abyss
{ 2255 , 7874 , 7790 } , --The Spiral Weave
{ 2255 , 7872 , 7786 } , --The Underkeep
--{0, 7875, nil}, --Zekvir's Lair (Mystery 13th Delve)
} ;
local DelveMaps = {
2248 , 2214 , 2215 , 2255 ,
} ;
local POIxDelveIndex = { } ;
do --Format Data
local poiID ;
for delveIndex , data in ipairs ( DelvePOI ) do
poiID = data [ 2 ] ;
if poiID then
POIxDelveIndex [ poiID ] = delveIndex ;
end
poiID = data [ 3 ] ;
if poiID then
POIxDelveIndex [ poiID ] = delveIndex ;
end
end
end
local EL = CreateFrame ( " Frame " ) ;
EL.handlers = { } ;
EL : SetScript ( " OnEvent " , function ( self , event , ... )
if self.handlers [ event ] then
self.handlers [ event ] ( ... )
end
end ) ;
function EL : AddHandler ( event , func )
self.handlers [ event ] = func ;
end
function EL : OnUpdate ( elapsed )
self.t = self.t + elapsed ;
if self.t > 0 then
self.t = nil ;
self : SetScript ( " OnUpdate " , nil ) ;
for _ , queuedFunc in ipairs ( self.queuedFuncs ) do
queuedFunc ( ) ;
end
self.queuedFuncs = nil ;
end
end
function EL : ProcessOnNextCycle ( func )
if not self.queuedFuncs then
self.queuedFuncs = { } ;
end
self.t = - 0.2 ;
self : SetScript ( " OnUpdate " , self.OnUpdate ) ;
for _ , queuedFunc in ipairs ( self.queuedFuncs ) do
if queuedFunc == func then
return
end
end
table.insert ( self.queuedFuncs , func ) ;
end
local function Dev_GetDelveMapInfo ( )
--Bountfiul Delves have different poiID different from their regular modes
--C_AreaPoiInfo.GetAreaPOISecondsLeft returns nil
--/dump C_AreaPoiInfo.GetAreaPOIInfo(2215, 7783)
for delveIndex , data in ipairs ( DelvePOI ) do
data.isBountiful = true ;
end
local areaPoiIDs , poiInfo ;
local n = 0 ;
local poiData = { } ;
local delveIndex ;
for _ , mapID in ipairs ( DelveMaps ) do
areaPoiIDs = GetDelvesForMap ( mapID ) ;
for _ , poiID in ipairs ( areaPoiIDs ) do
delveIndex = POIxDelveIndex [ poiID ] ;
if delveIndex then
DelvePOI [ delveIndex ] . isBountiful = nil ;
end
end
end
local tooltipWidgetSet ;
local mapID , poiID ;
for delveIndex , data in ipairs ( DelvePOI ) do
mapID = data [ 1 ] ;
if data.isBountiful then
poiID = data [ 3 ] ;
else
poiID = data [ 2 ] ;
end
poiInfo = GetAreaPOIInfo ( mapID , poiID )
if poiInfo then
if not data.name then
data.name = poiInfo.name ;
end
if data.isBountiful then
print ( delveIndex , " |cnGREEN_FONT_COLOR: " .. data.name .. " |r " ) ;
if not tooltipWidgetSet then
tooltipWidgetSet = poiInfo.tooltipWidgetSet ;
end
local x , y = poiInfo.position : GetXY ( ) ;
API.ConvertMapPositionToContinentPosition ( mapID , x , y , poiID ) ;
else
print ( delveIndex , data.name ) ;
end
end
end
if tooltipWidgetSet then
local widgets = C_UIWidgetManager.GetAllWidgetsBySetID ( tooltipWidgetSet ) ;
local widgetID = widgets and widgets [ 1 ] and widgets [ 1 ] . widgetID ;
if widgetID then
local widgetInfo = C_UIWidgetManager.GetTextWithStateWidgetVisualizationInfo ( widgetID ) ;
if widgetInfo then
local seconds = TimeLeftTextToSeconds ( widgetInfo.text ) ;
print ( seconds ) ;
print ( API.SecondsToTime ( seconds ) )
end
end
end
end
local function GetEnemyGroupCount ( )
local widgetSetID = select ( 12 , GetStepInfo ( ) ) ;
if not widgetSetID then return end ;
local widgets = C_UIWidgetManager.GetAllWidgetsBySetID ( widgetSetID ) ;
if not widgets then return end ;
local TYPE_ID = Enum.UIWidgetVisualizationType . ScenarioHeaderDelves or 29 ;
local widgetID ;
for _ , widgetInfo in ipairs ( widgets ) do
if widgetInfo.widgetType == TYPE_ID then
widgetID = widgetInfo.widgetID ;
end
end
if not widgetID then return end ;
local SPELL_ID = 456037 ; --Zekvir's Influence
local isSpellFound ;
local widgetInfo = C_UIWidgetManager.GetScenarioHeaderDelvesWidgetVisualizationInfo ( widgetID ) ;
if widgetInfo and widgetInfo.shownState == 1 and widgetInfo.spells then
for _ , spellInfo in ipairs ( widgetInfo.spells ) do
if spellInfo.spellID == SPELL_ID then
if spellInfo.shownState == 1 then
isSpellFound = true ;
end
break
end
end
end
if isSpellFound then
local isPet = false ;
local showSubtext = true ;
local tooltipData = C_TooltipInfo.GetSpellByID ( SPELL_ID , isPet , showSubtext ) ;
if tooltipData and tooltipData.lines then
local numLines = # tooltipData.lines ;
local lineText = tooltipData.lines [ numLines ] . leftText ;
print ( lineText ) ; --Zekvir, the Hand of the Harbinger...Enemy groups remaining: 3/3
local current , total = string.match ( lineText , " (%d+)%s*/%s*(%d+) " ) ;
print ( current , total )
end
end
end
local BonusObjectiveTrackerMixin = { } ;
do --Show Enemy Group Count bellow affix spell on the ScenarioHeaderDelves
local GetCurrencyInfo = C_CurrencyInfo.GetCurrencyInfo ;
local CURRENCY_AFFIX_ACTIVE = 3103 ;
local CURRENCY_AFFIX_MAXIMUM = 3104 ;
function BonusObjectiveTrackerMixin : OnEvent ( event , ... )
--Fire CURRENCY_DISPLAY_UPDATE 1/2 times After killing one group, 3103 changed to 0 then the actual number
if event == " CURRENCY_DISPLAY_UPDATE " then
local currencyID = ...
if currencyID and ( currencyID == CURRENCY_AFFIX_ACTIVE or currencyID == CURRENCY_AFFIX_MAXIMUM ) then
self : RequestUpdate ( ) ;
end
end
end
function BonusObjectiveTrackerMixin : Remove ( )
if self.isActive then
self.isActive = false ;
self : Hide ( ) ;
self : ClearAllPoints ( ) ;
self : UnregisterEvent ( " CURRENCY_DISPLAY_UPDATE " ) ;
self : SetScript ( " OnUpdate " , nil ) ;
self : SetParent ( UIParent ) ;
self : SetPoint ( " TOP " , UIParent , " BOTTOM " , 0 , - 8 ) ;
end
end
function BonusObjectiveTrackerMixin : OnUpdate ( elapsed )
self.t = self.t + elapsed ;
if self.t >= 0.5 then
self.t = nil ;
self : SetScript ( " OnUpdate " , nil ) ;
self : Update ( ) ;
end
end
function BonusObjectiveTrackerMixin : RequestUpdate ( newDelve )
self.t = 0 ;
self : SetScript ( " OnUpdate " , self.OnUpdate ) ;
self : Show ( ) ;
if newDelve then
self.newDelve = true ;
end
end
function BonusObjectiveTrackerMixin : Reposition ( )
local widgetSetID = select ( 12 , GetStepInfo ( ) ) ;
if ( not widgetSetID ) or widgetSetID == 0 then return end ;
local widgets = C_UIWidgetManager.GetAllWidgetsBySetID ( widgetSetID ) ;
if not widgets then return end ;
local TYPE_ID = Enum.UIWidgetVisualizationType . ScenarioHeaderDelves or 29 ;
local widgetID ;
for _ , widgetInfo in ipairs ( widgets ) do
if widgetInfo.widgetType == TYPE_ID then
widgetID = widgetInfo.widgetID ;
end
end
if not widgetID then return end ;
local SPELL_ID = 456037 ; --Zekvir's Influence
local spellIndex ;
local widgetInfo = C_UIWidgetManager.GetScenarioHeaderDelvesWidgetVisualizationInfo ( widgetID ) ;
if widgetInfo and widgetInfo.shownState == 1 and widgetInfo.spells then
for i , spellInfo in ipairs ( widgetInfo.spells ) do
if spellInfo.spellID == SPELL_ID then
if spellInfo.shownState == 1 then
spellIndex = i ;
end
break
end
end
end
self : ClearAllPoints ( ) ;
self : SetParent ( UIParent ) ;
self : SetPoint ( " TOP " , UIParent , " BOTTOM " , 0 , - 8 ) ;
local parentObject ;
if spellIndex then
for widgetContainer in pairs ( UIWidgetManager.registeredWidgetContainers ) do
if widgetContainer.widgetSetID == widgetSetID then
if widgetContainer and widgetContainer.widgetFrames and widgetContainer.widgetFrames [ widgetID ] then
local p = widgetContainer.widgetFrames [ widgetID ] ;
if p.SpellContainer and p.SpellContainer . GetLayoutChildren then
local frames = p.SpellContainer : GetLayoutChildren ( ) ;
parentObject = frames [ spellIndex ] ;
end
end
break
end
end
end
if parentObject then
self : SetParent ( parentObject ) ;
self : SetPoint ( " TOP " , parentObject , " BOTTOM " , 0 , 0 ) ;
end
end
function BonusObjectiveTrackerMixin : Update ( )
local info ;
local current , max ;
info = GetCurrencyInfo ( CURRENCY_AFFIX_ACTIVE ) ;
if info then
current = info.quantity ;
end
info = GetCurrencyInfo ( CURRENCY_AFFIX_MAXIMUM ) ;
if info then
max = info.quantity ;
end
if current and max and max > 0 then
if current <= 0 then
self.Text : SetText ( " |TInterface \\ AddOns \\ Plumber \\ Art \\ Button \\ Checkmark-Green:16|t " ) ;
else
self.Text : SetText ( current ) ;
end
self.isActive = true ;
self : RegisterEvent ( " CURRENCY_DISPLAY_UPDATE " ) ;
if self.newDelve then
self.newDelve = nil ;
self : Reposition ( ) ;
end
else
self : Remove ( ) ;
end
end
end
local SeasonTracker = { } ;
do --Seasonal Journey Progress
--Currently can't track it on the ReputationBar by C_Reputation.SetWatchedFactionByID (C_Reputation.IsMajorFaction returns true but no C_MajorFactions.GetMajorFactionData)
local FADEOUT_DELAY = 4 ;
local MAPID_DORNOGAL = 2339 ; --Only listen UPDATE_FACTION in Delves and Dornogal (Weekly Quest Turn-in)
local ProgressBar ;
local BonusObjectiveTracker ;
local ZoneTriggerModule ;
local function ProgressBar_Init ( )
if ProgressBar then return end ;
ProgressBar = addon.CreateLevelProgressBar ( UIParent ) ;
ProgressBar : SetPoint ( " CENTER " , UIParent , " TOP " , 0 , - 128 ) ;
ProgressBar : SetLabel ( " Seasonal Journey " ) ;
ProgressBar : SetLevel ( 5 ) ;
ProgressBar : SetFrameStrata ( " HIGH " ) ;
ProgressBar : SetFrameLevel ( 990 ) ;
ProgressBar : Hide ( ) ;
ProgressBar : SetAlpha ( 0 ) ;
ProgressBar : SetUseAnimation ( true ) ;
ProgressBar : SetAutoFadeOut ( true ) ;
ProgressBar.FadeUpdateFrame = CreateFrame ( " Frame " ) ;
ProgressBar.FadeUpdateFrame : Hide ( ) ;
ProgressBar.FadeUpdateFrame : SetScript ( " OnUpdate " , function ( f , elapsed )
f.t = f.t + elapsed ;
if f.t >= FADEOUT_DELAY then
f.t = 0 ;
f : Hide ( ) ;
UIFrameFade ( ProgressBar , 0.25 , 0 ) ;
end
end ) ;
ProgressBar.onEnterFunc = function ( )
ProgressBar : FadeIn ( ) ;
end
ProgressBar.onLeaveFunc = function ( )
ProgressBar : StartFadeOutCountdown ( 2 ) ;
end
function ProgressBar : FadeIn ( )
ProgressBar.FadeUpdateFrame : Hide ( ) ;
UIFrameFade ( self , 0.25 , 1 ) ;
end
function ProgressBar : StartFadeOutCountdown ( delay )
if self : IsAnimating ( ) then
return
end
ProgressBar.FadeUpdateFrame : Show ( ) ;
ProgressBar.FadeUpdateFrame . t = delay or 0 ;
end
function ProgressBar : ShowProgress ( )
self : FadeIn ( ) ;
local level , earned , threshold = SeasonTracker : GetProgress ( ) ;
self : SetLevel ( level ) ;
self : SetMaxValue ( threshold ) ;
self : SetValue ( earned ) ;
end
local level , earned , threshold = SeasonTracker : GetProgress ( ) ;
ProgressBar : SetLevel ( level , threshold <= 0 ) ;
ProgressBar : SetMaxValue ( threshold ) ;
ProgressBar : SetValue ( earned ) ;
PB = ProgressBar ; --Debug
function ProgressBar : Test ( )
local level , earned , threshold = 2 , 3300 , 4200 ;
local deltaEarned , levelUp , reachMaxLevel = 290 , true , false ;
self : FadeIn ( ) ;
self : SetMaxValue ( threshold ) ;
self : SetValue ( earned , levelUp ) ;
self : AnimateDeltaValue ( deltaEarned ) ;
self : SetLevel ( level , reachMaxLevel ) ;
end
end
local function BonusObjectiveTracker_Init ( )
if BonusObjectiveTracker then return end ;
local f = CreateFrame ( " Frame " ) ;
BonusObjectiveTracker = f ;
f : SetSize ( 30 , 24 ) ;
local Text = f : CreateFontString ( nil , " OVERLAY " , " GameFontHighlight " ) ;
f.Text = Text ;
Text : SetJustifyH ( " CENTER " ) ;
Text : SetPoint ( " CENTER " , f , " CENTER " , 0 , 0 ) ;
local Bg = f : CreateTexture ( nil , " BORDER " ) ;
Bg : SetAllPoints ( true ) ;
Bg : SetTexture ( " Interface/AddOns/Plumber/Art/Delves/Delves-Scenario " ) ;
Bg : SetTexCoord ( 0 , 60 / 256 , 0 , 48 / 256 ) ;
API.Mixin ( f , BonusObjectiveTrackerMixin ) ;
f : SetScript ( " OnEvent " , f.OnEvent ) ;
end
local function BonusObjectiveTracker_Hide ( )
if BonusObjectiveTracker then
BonusObjectiveTracker : Remove ( ) ;
end
end
function SeasonTracker : GetProgress ( )
if not DELVES_SEASON_FACTION then
DELVES_SEASON_FACTION = C_DelvesUI and C_DelvesUI.GetDelvesFactionForSeason and C_DelvesUI.GetDelvesFactionForSeason ( ) or 0 ;
end
local renownInfo = GetMajorFactionRenownInfo ( DELVES_SEASON_FACTION ) ;
if not renownInfo then return 0 , 0 , 1 end ;
local level = renownInfo.renownLevel or 1 ;
local earned = renownInfo.renownReputationEarned or 0 ;
local threshold = renownInfo.renownLevelThreshold or 1 ;
return level , earned , threshold
end
function SeasonTracker : SnapShotSeasonalProgress ( )
--Assume the amount of renown required to gain 1 level is a constant (4200)
local level , earned , threshold = self : GetProgress ( ) ;
local deltaLevel , deltaEarned ;
if self.renownLevel then
deltaLevel = level - self.renownLevel ;
else
deltaLevel = 0 ;
end
local levelUp = deltaLevel > 0 ;
if self.renownReputationEarned and self.renownLevelThreshold then
if levelUp then
deltaEarned = earned + self.renownLevelThreshold - self.renownReputationEarned ;
else
deltaEarned = earned - self.renownReputationEarned ;
end
end
self.renownLevel = level ;
self.renownReputationEarned = earned ;
self.renownLevelThreshold = threshold ;
--print(level, earned, threshold);
local reachMaxLevel = ( not threshold ) or threshold <= 0 ;
if deltaEarned and deltaEarned > 0 then
return true , level , earned , threshold , deltaEarned , levelUp , reachMaxLevel
end
end
local function UpdateInDelveStatus ( )
--Seasonal Progress changes after looting a chest in the end
--To reduce usage, we start listening UPDATE_FACTION after the scenario is completed (the event fires after killing the final boss) (Companion level is also a faction)
--If player resets UI after scenario completion, we won't show the progress bar
--C_DelvesUI.HasActiveDelve doesn't change immediately after PLAYER_MAP_CHANGED
if IsInDelves ( ) then
EL : RegisterEvent ( " SCENARIO_COMPLETED " ) ;
EL : RegisterEvent ( " PLAYER_MAP_CHANGED " ) ;
BonusObjectiveTracker_Init ( ) ;
BonusObjectiveTracker : RequestUpdate ( true ) ;
--print("IN Delve");
return true
else
EL : UnregisterEvent ( " SCENARIO_COMPLETED " ) ;
EL : UnregisterEvent ( " PLAYER_MAP_CHANGED " ) ;
EL : UnregisterEvent ( " UPDATE_FACTION " ) ;
BonusObjectiveTracker_Hide ( ) ;
--print("NOT in Delve");
return false
end
end
EL : AddHandler ( " PLAYER_MAP_CHANGED " , function ( )
EL : ProcessOnNextCycle ( UpdateInDelveStatus ) ;
end ) ;
local function OnDelveEntered ( )
if UpdateInDelveStatus ( ) then
ProgressBar_Init ( ) ;
end
end
EL : AddHandler ( " WALK_IN_DATA_UPDATE " , function ( )
EL : ProcessOnNextCycle ( OnDelveEntered ) ;
end ) ;
local function OnScenarioCompleted ( )
EL : RegisterEvent ( " UPDATE_FACTION " ) ;
end
EL : AddHandler ( " SCENARIO_COMPLETED " , OnScenarioCompleted ) ;
local function OnFactionUpdated ( )
EL : RegisterEvent ( " UPDATE_FACTION " ) ;
local anyChange , level , earned , threshold , deltaEarned , levelUp , reachMaxLevel = SeasonTracker : SnapShotSeasonalProgress ( ) ;
if anyChange then
ProgressBar : FadeIn ( ) ;
ProgressBar : SetValue ( earned , levelUp ) ;
ProgressBar : AnimateDeltaValue ( deltaEarned ) ;
ProgressBar : SetLevel ( level , reachMaxLevel ) ;
ProgressBar : SetMaxValue ( threshold ) ;
ProgressBar : StartFadeOutCountdown ( 0 ) ;
end
end
EL : AddHandler ( " UPDATE_FACTION " , function ( )
EL : ProcessOnNextCycle ( OnFactionUpdated ) ;
end ) ;
local function ZoneTriggerModule_Enable ( state )
if state then
if not ZoneTriggerModule then
local module = API.CreateZoneTriggeredModule ( " dornogal " ) ;
ZoneTriggerModule = module ;
module : SetValidZones ( MAPID_DORNOGAL ) ;
local function OnEnterZoneCallback ( )
SeasonTracker : SnapShotSeasonalProgress ( ) ;
ProgressBar_Init ( ) ;
EL : RegisterEvent ( " UPDATE_FACTION " ) ;
end
local function OnLeaveZoneCallback ( )
UpdateInDelveStatus ( ) ;
end
module : SetEnterZoneCallback ( OnEnterZoneCallback ) ;
module : SetLeaveZoneCallback ( OnLeaveZoneCallback ) ;
end
ZoneTriggerModule : SetEnabled ( true ) ;
ZoneTriggerModule : Update ( ) ;
else
if ZoneTriggerModule then
ZoneTriggerModule : SetEnabled ( false ) ;
end
end
end
function SeasonTracker : SetEnabled ( state )
if state then
EL : RegisterEvent ( " WALK_IN_DATA_UPDATE " ) ; --Always registered
self : SnapShotSeasonalProgress ( ) ;
OnDelveEntered ( ) ;
else
EL : UnregisterEvent ( " WALK_IN_DATA_UPDATE " ) ;
EL : UnregisterEvent ( " PLAYER_MAP_CHANGED " ) ;
EL : UnregisterEvent ( " SCENARIO_COMPLETED " ) ;
EL : UnregisterEvent ( " UPDATE_FACTION " ) ;
end
ZoneTriggerModule_Enable ( state ) ;
end
C_Timer.After ( 2 , function ( ) --debug
SeasonTracker : SetEnabled ( true ) ;
end ) ;
end