vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
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;