@@ -6,8 +6,8 @@ if MINOR_VERSION > _G.DogTag_Unit_MINOR_VERSION then
66end
77
88local _G , pairs , wipe , tonumber , GetTime = _G , pairs , wipe , tonumber , GetTime
9- local UnitName , UnitGUID , UnitCastingInfo , UnitChannelInfo , CastingInfo , ChannelInfo =
10- UnitName , UnitGUID , UnitCastingInfo , UnitChannelInfo , CastingInfo , ChannelInfo
9+ local UnitName , UnitGUID , UnitCastingInfo , UnitChannelInfo , CastingInfo , ChannelInfo , UnitCastingDuration , UnitChannelDuration , UnitSpellTargetName =
10+ UnitName , UnitGUID , UnitCastingInfo , UnitChannelInfo , CastingInfo , ChannelInfo , UnitCastingDuration , UnitChannelDuration , UnitSpellTargetName
1111
1212DogTag_Unit_funcs [# DogTag_Unit_funcs + 1 ] = function (DogTag_Unit , DogTag )
1313
@@ -19,110 +19,149 @@ local castData = {}
1919local UnitGUID = UnitGUID
2020local IsNormalUnit = DogTag_Unit .IsNormalUnit
2121local issecretvalue = DogTag .issecretvalue
22+ local hasSecrets = C_Secrets and C_Secrets .HasSecretRestrictions ()
2223
2324local wow_ver = select (4 , GetBuildInfo ())
2425local cast_api_has_ranks = wow_ver < 80000 and WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
2526
2627local playerGuid = nil
28+ local trackedUnits = {}
2729DogTag :AddEventHandler (" Unit" , " PLAYER_LOGIN" , function ()
2830 playerGuid = UnitGUID (" player" )
2931end )
3032
33+ local nextSpell , nextRank , nextTarget
34+ local function populateCastData (event , unit , data )
35+ local guid = UnitGUID (unit )
36+ if not guid then
37+ return false
38+ end
39+
40+ local spell , rank , displayName , icon , startTime , endTime , _ , spellID
41+ local channeling = false
42+ if UnitCastingInfo then
43+ if cast_api_has_ranks then
44+ spell , rank , displayName , icon , startTime , endTime = UnitCastingInfo (unit )
45+ if not spell then
46+ spell , rank , displayName , icon , startTime , endTime = UnitChannelInfo (unit )
47+ channeling = true
48+ end
49+ else
50+ spell , displayName , icon , startTime , endTime , _ , _ , _ , spellID = UnitCastingInfo (unit )
51+ rank = nil
52+ if not spell then
53+ spell , displayName , icon , startTime , endTime , _ , _ , spellID = UnitChannelInfo (unit )
54+ channeling = true
55+ end
56+ end
57+ elseif CastingInfo then
58+ -- Classic only has an API for player spellcasts. No API for arbitrary units.
59+ if unit == " player" then
60+ spell , displayName , icon , startTime , endTime , _ , _ , _ , spellID = CastingInfo ()
61+ rank = nil
62+ if not spell then
63+ spell , displayName , icon , startTime , endTime , _ , _ , spellID = ChannelInfo ()
64+ channeling = true
65+ end
66+ end
67+ end
68+
69+ local durationFunc = channeling and UnitChannelDuration or UnitCastingDuration
70+ if durationFunc then
71+ data .duration = durationFunc (unit )
72+ end
73+
74+ if spell then
75+ data .spell = spell
76+ rank = rank and tonumber (rank :match (" %d+" ))
77+ data .rank = rank
78+ local oldStart = data .startTime
79+ if not issecretvalue (startTime ) then
80+ startTime = startTime * 0.001
81+ end
82+ data .startTime = startTime
83+ data .endTime = issecretvalue (endTime ) and endTime or endTime * 0.001
84+ if not issecretvalue (startTime ) and (event == " UNIT_SPELLCAST_DELAYED" or event == " UNIT_SPELLCAST_CHANNEL_UPDATE" ) then
85+ data .delay = (data .delay or 0 ) + (startTime - (oldStart or startTime ))
86+ else
87+ data .delay = 0
88+ end
89+ if UnitSpellTargetName then
90+ data .target = UnitSpellTargetName (unit )
91+ elseif not issecretvalue (guid ) and guid == playerGuid
92+ and not issecretvalue (spellID ) and spellID == nextSpell
93+ and rank == nextRank then
94+ data .target = nextTarget
95+ end
96+ data .casting = not channeling
97+ data .channeling = channeling
98+ data .fadeOut = false
99+ data .stopTime = nil
100+ data .stopMessage = nil
101+ return true
102+ end
103+
104+ if not data .spell then
105+ return true
106+ end
107+
108+ if event == " UNIT_SPELLCAST_FAILED" then
109+ data .stopMessage = _G .FAILED
110+ elseif event == " UNIT_SPELLCAST_INTERRUPTED" then
111+ data .stopMessage = _G .INTERRUPTED
112+ end
113+
114+ data .casting = false
115+ data .channeling = false
116+ data .fadeOut = true
117+ if not data .stopTime then
118+ data .stopTime = GetTime ()
119+ end
120+
121+ return true
122+ end
123+
31124local castEventIsSetup = false
32125DogTag :AddEventHandler (" Unit" , " EventRequested" , function (_ , event )
33126 if event ~= " Cast" or castEventIsSetup then return end
34127 castEventIsSetup = true
35-
36- local nextSpell , nextRank , nextTarget
128+
37129 local function updateInfo (event , unit )
38130 local guid = UnitGUID (unit )
39- if not guid or issecretvalue (guid ) then
131+ if not guid then
132+ return
133+ end
134+ if hasSecrets then
135+ trackedUnits [unit ] = true
136+ DogTag :FireEvent (" Cast" , unit )
40137 return
41138 end
42139 local data = castData [guid ]
43140 if not data then
44141 data = newList ()
45142 castData [guid ] = data
46143 end
47-
48- local spell , rank , displayName , icon , startTime , endTime
49- local channeling = false
50- if UnitCastingInfo then
51- if cast_api_has_ranks then
52- spell , rank , displayName , icon , startTime , endTime = UnitCastingInfo (unit )
53- if not spell then
54- spell , rank , displayName , icon , startTime , endTime = UnitChannelInfo (unit )
55- channeling = true
56- end
57- else
58- spell , displayName , icon , startTime , endTime = UnitCastingInfo (unit )
59- rank = nil
60- if not spell then
61- spell , displayName , icon , startTime , endTime = UnitChannelInfo (unit )
62- channeling = true
63- end
64- end
65- elseif CastingInfo then
66- -- Classic only has an API for player spellcasts. No API for arbitrary units.
67- if unit == " player" then
68- spell , displayName , icon , startTime , endTime = CastingInfo ()
69- rank = nil
70- if not spell then
71- spell , displayName , icon , startTime , endTime = ChannelInfo ()
72- channeling = true
73- end
74- end
75- end
76144
77- if spell then
78- data .spell = spell
79- rank = rank and tonumber (rank :match (" %d+" ))
80- data .rank = rank
81- local oldStart = data .startTime
82- startTime = startTime * 0.001
83- data .startTime = startTime
84- data .endTime = endTime * 0.001
85- if event == " UNIT_SPELLCAST_DELAYED" or event == " UNIT_SPELLCAST_CHANNEL_UPDATE" then
86- data .delay = (data .delay or 0 ) + (startTime - (oldStart or startTime ))
87- else
88- data .delay = 0
89- end
90- if guid == playerGuid and spell == nextSpell and rank == nextRank then
91- data .target = nextTarget
92- end
93- data .casting = not channeling
94- data .channeling = channeling
95- data .fadeOut = false
96- data .stopTime = nil
97- data .stopMessage = nil
98- DogTag :FireEvent (" Cast" , unit )
145+ if not populateCastData (event , unit , data ) then
99146 return
100147 end
101-
148+
102149 if not data .spell then
103150 castData [guid ] = del (data )
104- DogTag :FireEvent (" Cast" , unit )
105- return
106- end
107-
108- if event == " UNIT_SPELLCAST_FAILED" then
109- data .stopMessage = _G .FAILED
110- elseif event == " UNIT_SPELLCAST_INTERRUPTED" then
111- data .stopMessage = _G .INTERRUPTED
112- end
113-
114- data .casting = false
115- data .channeling = false
116- data .fadeOut = true
117- if not data .stopTime then
118- data .stopTime = GetTime ()
119151 end
152+
120153 DogTag :FireEvent (" Cast" , unit )
121154 end
122155
123156 local guidsToFire , unitsToUpdate = {}, {}
124157 local function fixCastData ()
125- local frame
158+ if hasSecrets then
159+ for unit , _ in pairs (trackedUnits ) do
160+ DogTag :FireEvent (" Cast" , unit )
161+ end
162+ return
163+ end
164+
126165 local currentTime = GetTime ()
127166 for guid , data in pairs (castData ) do
128167 if data .casting then
@@ -143,7 +182,7 @@ DogTag:AddEventHandler("Unit", "EventRequested", function(_, event)
143182 if stopTime then
144183 alpha = stopTime - currentTime + 1
145184 end
146-
185+
147186 if alpha <= 0 then
148187 castData [guid ] = del (data )
149188 end
@@ -167,7 +206,7 @@ DogTag:AddEventHandler("Unit", "EventRequested", function(_, event)
167206 if not normal then
168207 unitsToUpdate [found ] = true
169208 end
170-
209+
171210 guidsToFire [guid ] = true
172211 end
173212 end
@@ -194,13 +233,11 @@ DogTag:AddEventHandler("Unit", "EventRequested", function(_, event)
194233 DogTag :AddEventHandler (" Unit" , " UNIT_SPELLCAST_CHANNEL_STOP" , updateInfo )
195234 DogTag :AddEventHandler (" Unit" , " UnitChanged" , updateInfo )
196235
197- DogTag :AddEventHandler (" Unit" , " UNIT_SPELLCAST_SENT" , function (event , unit , spell , rank , target )
198-
236+ DogTag :AddEventHandler (" Unit" , " UNIT_SPELLCAST_SENT" , function (event , unit , target , castGUID , spellID )
237+
199238 -- The purpose of this event is to predict the next spell target.
200- -- This seems to be removed in at least wow_800
201- if unit == " player" and cast_api_has_ranks then
202- nextSpell = spell
203- nextRank = rank and tonumber (rank :match (" %d+" ))
239+ if unit == " player" then
240+ nextSpell = spellID
204241 nextTarget = target ~= " " and target or nil
205242 end
206243 end )
@@ -209,7 +246,18 @@ end)
209246
210247local blank = {}
211248local function getCastData (unit )
212- return castData [UnitGUID (unit )] or blank
249+ local guid = UnitGUID (unit )
250+ if not guid then
251+ return blank
252+ end
253+
254+ if hasSecrets then
255+ local data = newList ()
256+ populateCastData (nil , unit , data )
257+ return data
258+ end
259+
260+ return castData [guid ] or blank
213261end
214262
215263DogTag :AddTag (" Unit" , " CastName" , {
@@ -256,7 +304,11 @@ DogTag:AddTag("Unit", "CastRank", {
256304
257305DogTag :AddTag (" Unit" , " CastStartDuration" , {
258306 code = function (unit )
259- local t = getCastData (unit ).startTime
307+ local data = getCastData (unit )
308+ if data .duration then
309+ return data .duration :GetElapsedDuration ()
310+ end
311+ local t = data .startTime
260312 if t then
261313 return GetTime () - t
262314 else
@@ -275,7 +327,11 @@ DogTag:AddTag("Unit", "CastStartDuration", {
275327
276328DogTag :AddTag (" Unit" , " CastEndDuration" , {
277329 code = function (unit )
278- local t = getCastData (unit ).endTime
330+ local data = getCastData (unit )
331+ if data .duration then
332+ return data .duration :GetRemainingDuration ()
333+ end
334+ local t = data .endTime
279335 if t then
280336 return t - GetTime ()
281337 else
0 commit comments