vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | -- SoulStamp |
2 | SOULSTAMP_VERSION="0.1"; |
||
3 | -- This addon tracks the source of soul shards (the mob or player they were created from) |
||
4 | -- and adds this information under a tooltip you can see when mousing over the shard. |
||
5 | -- This information is at the moment only visible to you. |
||
6 | -- |
||
7 | -- Much of the infrastructure code for detecting spell casts |
||
8 | -- was shamelessly stolen from CountDoom. |
||
9 | -- |
||
10 | -- Copyright (c) 2006 Colin Walters <cgwalters@gmail.com> |
||
11 | -- All rights reserved. |
||
12 | -- |
||
13 | -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
||
14 | -- |
||
15 | -- * Redistributions of source code must retain the above copyright notice, this list |
||
16 | -- of conditions and the following disclaimer. |
||
17 | -- * Redistributions in binary form must reproduce the above copyright notice, this list |
||
18 | -- of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
||
19 | -- * The names of its contributors may not be used to endorse |
||
20 | -- or promote products derived from this software without specific prior written permission. |
||
21 | -- |
||
22 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||
23 | -- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
||
24 | -- IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
||
25 | -- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
26 | -- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||
27 | -- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
||
28 | -- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
29 | -- |
||
30 | |||
31 | SoulStamp = {}; |
||
32 | SoulStamp.debug = false; |
||
33 | SoulStamp.initialized = false; |
||
34 | |||
35 | -- Utility functions stolen from CountDoom |
||
36 | SoulStamp.Chat = function(msg, r, g, b) |
||
37 | local msgOutput = DEFAULT_CHAT_FRAME; |
||
38 | if(msgOutput) then |
||
39 | msgOutput:AddMessage(msg, r, g, b); |
||
40 | end |
||
41 | end; |
||
42 | |||
43 | SoulStamp.Debug = function(msg, r, g, b) |
||
44 | if (SoulStamp.debug) then |
||
45 | SoulStamp.Chat("<SSDebug>: " .. msg, r, g, b); |
||
46 | end |
||
47 | end; |
||
48 | |||
49 | SoulStamp.ToString = function(arg1) |
||
50 | local argType = type(arg1); |
||
51 | |||
52 | if argType == "nil" then |
||
53 | return "nil"; |
||
54 | elseif argType == "boolean" then |
||
55 | if arg1 then |
||
56 | return "true"; |
||
57 | else |
||
58 | return "false"; |
||
59 | end |
||
60 | else |
||
61 | return "" .. arg1; |
||
62 | end |
||
63 | end; |
||
64 | |||
65 | -- Stolen from auctioneer |
||
66 | SoulStamp.BreakLink = function(link) |
||
67 | local i,j, itemID, enchant, randomProp, uniqID, name = string.find(link, "|Hitem:(%d+):(%d+):(%d+):(%d+)|h[[]([^]]+)[]]|h"); |
||
68 | return tonumber(itemID or 0), tonumber(randomProp or 0), tonumber(enchant or 0), tonumber(uniqID or 0), name; |
||
69 | end |
||
70 | SoulStamp.BreakItemKey = function(itemKey) |
||
71 | local i,j, itemID, randomProp, enchant = string.find(itemKey, "(%d+):(%d+):(%d+)"); |
||
72 | return tonumber(itemID or 0), tonumber(randomProp or 0), tonumber(enchant or 0); |
||
73 | end |
||
74 | |||
75 | SoulStamp.lastSpellTarget = nil; |
||
76 | SoulStamp.drainSoulActive = false; |
||
77 | SoulStampShardSourceMap = {}; |
||
78 | SoulStamp.shardSourceMap = SoulStampShardSourceMap; |
||
79 | local initSoulStampShardSourceMap = SoulStampShardSourceMap; |
||
80 | |||
81 | function SSFrame_OnLoad() |
||
82 | this:RegisterEvent("ADDON_LOADED"); |
||
83 | this:RegisterEvent("VARIABLES_LOADED"); |
||
84 | this:RegisterEvent("SPELLCAST_STOP"); |
||
85 | this:RegisterEvent("SPELLCAST_FAILED"); |
||
86 | this:RegisterEvent("SPELLCAST_INTERRUPTED"); |
||
87 | this:RegisterEvent("ITEM_PUSH"); |
||
88 | this:RegisterEvent("CHAT_MSG_LOOT"); |
||
89 | this:RegisterEvent("BAG_UPDATE"); |
||
90 | end; |
||
91 | |||
92 | function SSFrame_OnEvent(event) |
||
93 | if (event == "VARIABLES_LOADED") then |
||
94 | SoulStamp.Initialize(); |
||
95 | elseif event == "SPELLCAST_INTERRUPTED" or event == "SPELLCAST_FAILED" then |
||
96 | SoulStamp.SpellCastFailedCallback() |
||
97 | -- User stopped casting a spell |
||
98 | elseif event == "SPELLCAST_STOP" then |
||
99 | SoulStamp.SpellCastStoppedCallback() |
||
100 | elseif event == "ITEM_PUSH" then |
||
101 | SoulStamp.ItemPushCallback(arg1, arg2) |
||
102 | elseif event == "CHAT_MSG_LOOT" then |
||
103 | SoulStamp.LootCallback(arg1) |
||
104 | elseif event == "BAG_UPDATE" then |
||
105 | SoulStamp.BagUpdateCallback(arg1) |
||
106 | elseif event == "ADDON_LOADED" and arg1 == "SoulStamp" then |
||
107 | SoulStamp.shardSourceMap = SoulStampShardSourceMap; |
||
108 | end; |
||
109 | end; |
||
110 | |||
111 | SoulStamp.IsItemSoulShard = function(name) |
||
112 | return string.find(name, "Soul Shard"); |
||
113 | end; |
||
114 | |||
115 | SoulStamp.ForeachSoulShardInBag = function(func, bag) |
||
116 | for slot=1,GetContainerNumSlots(bag) do |
||
117 | local link = GetContainerItemLink(bag,slot); |
||
118 | if (link) then |
||
119 | local itemID, randomProp, enchant, uniqID, lame = SoulStamp.BreakLink(link); |
||
120 | if (SoulStamp.IsItemSoulShard(lame)) then |
||
121 | SoulStamp.Debug("Soul shard at slot=" .. SoulStamp.ToString(slot) .. " uniqId=" .. SoulStamp.ToString(uniqId)); |
||
122 | func(uniqID, lame); |
||
123 | end |
||
124 | end |
||
125 | end |
||
126 | end; |
||
127 | |||
128 | SoulStamp.ForeachSoulShard = function(func, bag) |
||
129 | local bag; |
||
130 | for bag=0,4 do |
||
131 | SoulStamp.ForeachSoulShardInBag(func, bag); |
||
132 | end; |
||
133 | end; |
||
134 | |||
135 | SoulStamp.Initialize = function() |
||
136 | SLASH_SOULSTAMP1 = "/soulstamp"; |
||
137 | SlashCmdList["SOULSTAMP"] = function(msg) |
||
138 | SoulStamp.SlashCommand(msg); |
||
139 | end |
||
140 | SoulStamp.Debug("SoulStamp " .. SOULSTAMP_VERSION .. " by Xalan of Crushridge initalized"); |
||
141 | |||
142 | -- Hook into the tooltip popup functions |
||
143 | SoulStamp.OrigContainerFrameItemButton_OnEnter = ContainerFrameItemButton_OnEnter; |
||
144 | ContainerFrameItemButton_OnEnter = SoulStamp.ContainerFrameItemButton_OnEnter; |
||
145 | |||
146 | SoulStamp.DumpShards(); |
||
147 | end; |
||
148 | |||
149 | SoulStamp.SlashCommand = function(msg) |
||
150 | msg = string.lower(msg); |
||
151 | local a, b, c, n = string.find (msg, "(%w+) ([_%w]+)"); |
||
152 | |||
153 | if( c == nil and n == nil ) then |
||
154 | a, b, c = string.find (msg, "(%w+)"); |
||
155 | end |
||
156 | |||
157 | if (c ~= nil) then |
||
158 | SoulStamp.Debug("c:"..c); |
||
159 | else |
||
160 | SoulStamp.Debug("c: nil"); |
||
161 | end |
||
162 | |||
163 | if (n ~= nil) then |
||
164 | SoulStamp.Debug("n:"..n); |
||
165 | else |
||
166 | SoulStamp.Debug("n: nil"); |
||
167 | end |
||
168 | |||
169 | if(c == "debug") then |
||
170 | SoulStamp.debug = not SoulStamp.debug; |
||
171 | if (SoulStamp.debug) then |
||
172 | SoulStamp.Chat("SoulStamp debug is now on"); |
||
173 | else |
||
174 | SoulStamp.Chat("SoulStamp debug is now off"); |
||
175 | end |
||
176 | elseif (c == "dumpshards") then |
||
177 | SoulStamp.DumpShards(); |
||
178 | elseif (c == "dumpmap") then |
||
179 | SoulStamp.DumpShardMap(); |
||
180 | end |
||
181 | end |
||
182 | |||
183 | SoulStamp.DumpShards = function() |
||
184 | local function ssCallback(uniqID, lame) |
||
185 | SoulStamp.Chat("shard=" .. uniqID); |
||
186 | end; |
||
187 | SoulStamp.ForeachSoulShard(ssCallback); |
||
188 | end; |
||
189 | |||
190 | SoulStamp.DumpShardMap = function() |
||
191 | for k,v in pairs(SoulStamp.shardSourceMap) do |
||
192 | SoulStamp.Chat("shard=" .. SoulStamp.ToString(k) .. " maps to " .. SoulStamp.ToString(v)); |
||
193 | end; |
||
194 | end; |
||
195 | |||
196 | SoulStamp.SpellCastStartCallback = function (spellName, spellRank) |
||
197 | SoulStamp.Debug("Cast of: " .. SoulStamp.ToString(spellName) .. " Rank: " .. SoulStamp.ToString(spellRank)); |
||
198 | SoulStamp.lastSpellTarget = UnitName("target"); |
||
199 | end; |
||
200 | |||
201 | SoulStamp.SpellCastFailedCallback = function () |
||
202 | SoulStamp.Debug("Last spell cast failed"); |
||
203 | end; |
||
204 | |||
205 | SoulStamp.SpellCastStoppedCallback = function () |
||
206 | SoulStamp.Debug("Last spell cast stopped"); |
||
207 | end; |
||
208 | |||
209 | SoulStamp.ItemPushCallback = function (stackSize, iconPath) |
||
210 | SoulStamp.Debug("Item push: " .. SoulStamp.ToString(stackSize) .. " " .. SoulStamp.ToString(iconPath)); |
||
211 | end; |
||
212 | |||
213 | SoulStamp.OnSoulShardCreated = function() |
||
214 | SoulStamp.Debug("Soul shard created from " .. SoulStamp.ToString(SoulStamp.lastSpellTarget)); |
||
215 | if (not SoulStamp.lastSpellTarget) then |
||
216 | SoulStamp.Debug("ERROR: no previous spell target after creating soul shard") |
||
217 | return; |
||
218 | end; |
||
219 | local foundUnknownShard = false; |
||
220 | local function ssCallback(uniqID, lame) |
||
221 | if (foundUnknownShard) then |
||
222 | return; |
||
223 | end; |
||
224 | if (not SoulStamp.shardSourceMap[uniqID]) then |
||
225 | SoulStamp.Debug("assigning shard " .. uniqID .. " to " .. SoulStamp.lastSpellTarget); |
||
226 | SoulStamp.shardSourceMap[uniqID] = SoulStamp.lastSpellTarget; |
||
227 | foundUnknownShard = true; |
||
228 | end; |
||
229 | end; |
||
230 | SoulStamp.ForeachSoulShard(ssCallback); |
||
231 | end; |
||
232 | |||
233 | SoulStamp.LootCallback = function(msg) |
||
234 | SoulStamp.Debug("Loot: " .. SoulStamp.ToString(msg)); |
||
235 | if (string.find(msg, "You create.+Soul Shard")) then |
||
236 | SoulStamp.OnSoulShardCreated(); |
||
237 | end |
||
238 | end; |
||
239 | |||
240 | SoulStamp.BagUpdateCallback = function(bag) |
||
241 | SoulStamp.Debug("Bag update: " .. SoulStamp.ToString(bag)); |
||
242 | end; |
||
243 | |||
244 | SoulStamp.ContainerFrameItemButton_OnEnter = function () |
||
245 | SoulStamp.OrigContainerFrameItemButton_OnEnter(); |
||
246 | local frameID = this:GetParent():GetID(); |
||
247 | local frame = GameTooltip; |
||
248 | local buttonID = this:GetID(); |
||
249 | local link = GetContainerItemLink(frameID, buttonID); |
||
250 | |||
251 | -- SoulStamp.Debug("ContainerFrameItemButton_OnEnter frameId=" .. SoulStamp.ToString(frameID) .. " buttonID=" .. SoulStamp.ToString(buttonID) .. " link=" .. SoulStamp.ToString(link)); |
||
252 | |||
253 | if (not link) then |
||
254 | return; |
||
255 | end; |
||
256 | |||
257 | local itemID, randomProp, enchant, uniqID, lame = SoulStamp.BreakLink(link); |
||
258 | local itemKey = itemID..":"..randomProp..":"..enchant; |
||
259 | |||
260 | -- SoulStamp.Debug("ContainerFrameItemButton_OnEnter lame=" .. SoulStamp.ToString(lame) .. "uniqID=" .. SoulStamp.ToString(uniqID)); |
||
261 | |||
262 | if (not string.find(lame, "Soul Shard")) then |
||
263 | return; |
||
264 | end; |
||
265 | |||
266 | local source = SoulStamp.shardSourceMap[uniqID]; |
||
267 | if (not source) then |
||
268 | frame:AddLine("Source unknown", 0.6, 0.6, 0.6); |
||
269 | else |
||
270 | frame:AddLine("Drained from " .. source .. "", 0.7, 0, 0); |
||
271 | end; |
||
272 | frame:Show(); |
||
273 | end |
||
274 | |||
275 | -- Hook into CastSpell |
||
276 | SoulStamp.oldCastSpell = CastSpell; |
||
277 | SoulStamp.OnCastSpell = function (spellId,spellbookTabNum) |
||
278 | local spellName, spellRank = GetSpellName(spellId, spellbookTabNum); |
||
279 | if spellRank ~= nil then |
||
280 | local _, _, spellRankString = string.find(spellRank, "(%d+)"); |
||
281 | rank = tonumber(spellRankString); |
||
282 | end; |
||
283 | |||
284 | SoulStamp.SpellCastStartCallback(spellName, rank); |
||
285 | |||
286 | SoulStamp.oldCastSpell(spellId, spellbookTabNum); |
||
287 | end; |
||
288 | CastSpell = SoulStamp.OnCastSpell; |
||
289 | |||
290 | SoulStamp.oldCastSpellByName = CastSpellByName; |
||
291 | SoulStamp.OnCastSpellByName = function(spellString) |
||
292 | local startIndex, endIndex, spellName = string.find(spellString, "(.+)%("); |
||
293 | local _, _, spellRankStr = string.find(spellString, "([%d]+)"); |
||
294 | local rank = nil; |
||
295 | rank = tonumber(spellRankStr); |
||
296 | |||
297 | SoulStamp.SpellCastStartCallback(spellName, rank); |
||
298 | |||
299 | SoulStamp.oldCastSpellByName(spellString); |
||
300 | end; |
||
301 | CastSpellByName = SoulStamp.OnCastSpellByName; |
||
302 | |||
303 | SoulStamp.oldUseAction = UseAction; |
||
304 | SoulStamp.OnUseAction = function (a1, a2, a3) |
||
305 | |||
306 | SoulStamp.Debug("Got OnUseAction: " .. SoulStamp.ToString(a1)); |
||
307 | |||
308 | -- Only process if it isn't a macro |
||
309 | if GetActionText(a1) == nil then |
||
310 | -- This screwy code is stolen from CountDoom |
||
311 | SS_SpellDetector:Hide(); |
||
312 | SS_SpellDetector:SetOwner(SoulStampFrame,"ANCHOR_NONE"); |
||
313 | SS_SpellDetector:SetAction(a1); |
||
314 | |||
315 | local spellName = nil; |
||
316 | |||
317 | if SS_SpellDetectorTextLeft1 ~= nil then |
||
318 | spellName = SS_SpellDetectorTextLeft1:GetText(); |
||
319 | end; |
||
320 | |||
321 | local spellRank = nil; |
||
322 | if SS_SpellDetectorTextRight1 ~= nil then |
||
323 | spellRank = SS_SpellDetectorTextRight1:GetText(); |
||
324 | end; |
||
325 | local rank = nil; |
||
326 | |||
327 | if spellRank ~= nil then |
||
328 | local _, _, spellRankString = string.find( spellRank, "[^%d]*(%d+)"); |
||
329 | rank = tonumber(spellRankString); |
||
330 | end; |
||
331 | |||
332 | SoulStamp.SpellCastStartCallback(spellName, rank); |
||
333 | end |
||
334 | |||
335 | SoulStamp.oldUseAction(a1, a2, a3); |
||
336 | end; |
||
337 | UseAction = SoulStamp.OnUseAction; |