vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 -- FishingBuddy
2 --
3 -- Everything you wanted support for in your fishing endeavors
4  
5 -- Information for the stylin' fisherman
6 local POLES = {
7 ["Fishing Pole"] = "6256:0:0:0",
8 ["Strong Fishing Pole"] = "6365:0:0:0",
9 ["Darkwood Fishing Pole"] = "6366:0:0:0",
10 ["Big Iron Fishing Pole"] = "6367:0:0:0",
11 ["Blump Family Fishing Pole"] = "12225:0:0:0",
12 ["Nat Pagle's Extreme Angler FC-5000"] = "19022:0:0:0",
13 ["Arcanite Fishing Pole"] = "19970:0:0:0",
14 -- yeah, so you can't really use these (for now :-)
15 ["Dwarven Fishing Pole"] = "3567:0:0:0",
16 ["Goblin Fishing Pole"] = "4598:0:0:0",
17 }
18  
19 local FISHINGLURES = {
20 ["6533:0:0:0"] = "Aquadynamic Fish Attractor", -- 100 for 5 mins
21 ["7307:0:0:0"] = "Flesh Eating Worm", -- 75 for 10 mins
22 ["6532:0:0:0"] = "Bright Baubles", -- 75 for 10 mins
23 ["6811:0:0:0"] = "Aquadynamic Fish Lens", -- 50 for 10 mins
24 ["6530:0:0:0"] = "Nightcrawlers", -- 50 for 10 mins
25 ["6529:0:0:0"] = "Shiny Bauble", -- 25 for 10 mins
26 }
27  
28 FishingBuddy.OPTIONS = {
29 { ["name"] = "ShowNewFishies",
30 ["text"] = FishingBuddy.CONFIG_SHOWNEWFISHIES_ONOFF,
31 ["tooltip"] = FishingBuddy.CONFIG_SHOWNEWFISHIES_INFO,
32 ["default"] = 1 },
33 { ["name"] = "WatchFishies",
34 ["text"] = FishingBuddy.CONFIG_FISHWATCH_ONOFF,
35 ["tooltip"] = FishingBuddy.CONFIG_FISHWATCH_INFO,
36 ["default"] = 1 },
37 { ["name"] = "WatchCurrentSkill",
38 ["text"] = FishingBuddy.CONFIG_FISHWATCHSKILL_ONOFF,
39 ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHSKILL_INFO,
40 ["default"] = 1 },
41 { ["name"] = "WatchCurrentZone",
42 ["text"] = FishingBuddy.CONFIG_FISHWATCHZONE_ONOFF,
43 ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHZONE_INFO,
44 ["default"] = 0 },
45 { ["name"] = "WatchOnlyWhenFishing",
46 ["text"] = FishingBuddy.CONFIG_FISHWATCHONLY_ONOFF,
47 ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHONLY_INFO,
48 ["default"] = 1 },
49 { ["name"] = "WatchFishPercent",
50 ["text"] = FishingBuddy.CONFIG_FISHWATCHPERCENT_ONOFF,
51 ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHPERCENT_INFO,
52 ["default"] = 1 },
53 { ["name"] = "SortByPercent",
54 ["text"] = FishingBuddy.CONFIG_SORTBYPERCENT_ONOFF,
55 ["tooltip"] = FishingBuddy.CONFIG_SORTBYPERCENT_INFO,
56 ["default"] = 1 },
57 { ["name"] = "SuitUpFirst",
58 ["text"] = FishingBuddy.CONFIG_SUITUPFIRST_ONOFF,
59 ["tooltip"] = FishingBuddy.CONFIG_SUITUPFIRST_INFO,
60 ["default"] = 0 },
61 { ["name"] = "EasyCast",
62 ["text"] = FishingBuddy.CONFIG_EASYCAST_ONOFF,
63 ["tooltip"] = FishingBuddy.CONFIG_EASYCAST_INFO,
64 ["default"] = 1 },
65 { ["name"] = "FastCast",
66 ["text"] = FishingBuddy.CONFIG_FASTCAST_ONOFF,
67 ["tooltip"] = FishingBuddy.CONFIG_FASTCAST_INFO,
68 ["default"] = 1 },
69 { ["name"] = "EasyLures",
70 ["text"] = FishingBuddy.CONFIG_EASYLURES_ONOFF,
71 ["tooltip"] = FishingBuddy.CONFIG_EASYLURES_INFO,
72 ["default"] = 0 },
73 { ["name"] = "STVTimer",
74 ["text"] = FishingBuddy.CONFIG_STVTIMER_ONOFF,
75 ["tooltip"] = FishingBuddy.CONFIG_STVTIMER_INFO,
76 ["default"] = 0 },
77 { ["name"] = "UseButtonHole",
78 ["text"] = FishingBuddy.CONFIG_USEBUTTONHOLE_ONOFF,
79 ["tooltip"] = FishingBuddy.CONFIG_USEBUTTONHOLE_INFO,
80 ["default"] = 0,
81 ["check"] = function () return ButtonHole ~= nil; end,
82 ["checkfail"] = 0 },
83 { ["name"] = "MinimapButtonVisible",
84 ["text"] = FishingBuddy.CONFIG_MINIMAPBUTTON_ONOFF,
85 ["tooltip"] = FishingBuddy.CONFIG_MINIMAPBUTTON_INFO,
86 ["default"] = 1,
87 ["check"] = function () return not FishingBuddy.UseButtonHole(); end,
88 ["checkfail"] = 1 },
89 { ["name"] = "EnhanceFishingSounds",
90 ["text"] = FishingBuddy.CONFIG_ENHANCESOUNDS_ONOFF,
91 ["tooltip"] = FishingBuddy.CONFIG_ENHANCESOUNDS_INFO,
92 ["default"] = 1 },
93 }
94  
95 FishingBuddy.ByFishie = nil;
96 FishingBuddy.SortedFishies = nil;
97  
98 local ActionStartTime = 0;
99 local ActionDoubleTime = 0;
100 local ACTIONDOWNWAIT = 0.2;
101 local ACTIONDOUBLEWAIT = 0.4;
102 local SavedAddMessage = nil;
103  
104 FishingBuddy.SavedToggleMinimap = nil;
105  
106 local StartedFishing = nil;
107 local TestingLures = false;
108 local CastingNow = false;
109 local AddingLure = false;
110  
111 local FishingSpellID = nil;
112 local FishingSkillName = nil;
113  
114 local gotSetupDone = false;
115 local playerName = nil;
116 local realmName = nil;
117  
118 FishingBuddy.currentFishies = {};
119  
120 local DEFAULT_MINIMAP_POSITION = 256;
121  
122 -- Fill in the player name and realm
123 FishingBuddy.SetupNameInfo = function()
124 playerName = UnitName("player");
125 realmName = GetRealmName();
126 return playerName, realmName;
127 end
128  
129 FishingBuddy.GetWasWearing = function()
130 if FishingBuddy_Player["WasWearing"] then
131 return FishingBuddy_Player["WasWearing"];
132 end
133 end
134  
135 FishingBuddy.SetWasWearing = function(outfit)
136 FishingBuddy_Player["WasWearing"] = outfit;
137 end
138  
139 FishingBuddy.GetOutfitItem = function(slotName)
140 if (FishingBuddy_Player["Outfit"]) then
141 return FishingBuddy_Player["Outfit"][slotName];
142 end
143 end
144  
145 FishingBuddy.GetOutfit = function()
146 return FishingBuddy_Player["Outfit"];
147 end
148  
149 FishingBuddy.SetOutfit = function(outfit)
150 FishingBuddy_Player["Outfit"] = outfit;
151 end
152  
153 local function GetSetting(setting)
154 if ( not FishingBuddy_Player or
155 not FishingBuddy_Player["Settings"] ) then
156 return;
157 end
158 return FishingBuddy_Player["Settings"][setting];
159 end
160 FishingBuddy.GetSetting = GetSetting;
161  
162 local function SetSetting(setting, value)
163 FishingBuddy_Player["Settings"][setting] = value;
164 end
165 FishingBuddy.SetSetting = SetSetting;
166  
167 -- handle option keys for enabling casting
168 local key_actions = {
169 [FishingBuddy.KEYS_NONE] = function() return true; end,
170 [FishingBuddy.KEYS_SHIFT] = function() return IsShiftKeyDown(); end,
171 [FishingBuddy.KEYS_CTRL] = function() return IsControlKeyDown(); end,
172 [FishingBuddy.KEYS_ALT] = function() return IsAltKeyDown(); end,
173 }
174 local function CastingKeys()
175 local setting = GetSetting("EasyCastKeys");
176 if ( key_actions[setting] ) then
177 return key_actions[setting]();
178 else
179 return true;
180 end
181 end
182  
183 -- get our current fishing skill level
184 local lastSkillIndex = nil;
185 FishingBuddy.GetCurrentSkill = function()
186 if ( lastSkillIndex ) then
187 local name, _, _, rank, _, modifier = GetSkillLineInfo(lastSkillIndex);
188 if ( name == FishingBuddy.GetFishingSkillName() )then
189 return rank, modifier;
190 end
191 end
192 local n = GetNumSkillLines();
193 for i=1,n do
194 local name, _, _, rank, _, modifier = GetSkillLineInfo(i);
195 if ( name == FishingBuddy.GetFishingSkillName() ) then
196 lastSkillIndex = i;
197 return rank, modifier;
198 end
199 end
200 return 0, 0;
201 end
202  
203 FishingBuddy.SetZoneLevel = function(zone, subzone, fishid)
204 local skill, mods = FishingBuddy.GetCurrentSkill();
205 local fs = FishingBuddy_Info["FishingSkill"];
206 if ( not fs[zone] ) then
207 fs[zone] = {};
208 end
209 local skillcheck = skill + mods;
210 if ( skillcheck > 0 ) then
211 if ( not fs[zone][subzone] or skillcheck < fs[zone][subzone] ) then
212 fs[zone][subzone] = skillcheck;
213 end
214 if ( fishie ) then
215 if ( not FishingBuddy_Info["Fishies"][fishid].level or
216 skillcheck < FishingBuddy_Info["Fishies"][fishid].level ) then
217 FishingBuddy_Info["Fishies"][fishid].level = skillcheck;
218 FishingBuddy_Info["Fishies"][fishid].skill = skill;
219 FishingBuddy_Info["Fishies"][fishid].mods = mods;
220 end
221 end
222 end
223 end
224  
225 local OldBindingKey;
226 local function UpdateBindings(onoff)
227 if ( onoff ) then
228 if ( not OldKeyBinding ) then
229 OldKeyBinding = GetBindingKey("TURNORACTION");
230 if ( OldKeyBinding ) then
231 SetBinding(OldKeyBinding, "FISHINGBUDDY_PERFORMCAST");
232 else
233 FishingBuddy.UIError(FishingBuddy.TOOMANYFISHERMEN);
234 end
235 end
236 else
237 if ( OldKeyBinding ) then
238 SetBinding(OldKeyBinding, "TURNORACTION");
239 OldKeyBinding = nil;
240 end
241 end
242 end
243 FishingBuddy.UpdateBindings = UpdateBindings;
244  
245 -- Shamelessly stolen from TackleBox
246 local function IsFishingPole()
247 -- Get the main hand item texture
248 local slot = GetInventorySlotInfo("MainHandSlot");
249 local itemTexture = GetInventoryItemTexture("player", slot);
250 -- If there is infact an item in the main hand, and it's texture
251 -- that matches the fishing pole texture, then we have a fishing pole
252 if ( itemTexture and string.find(itemTexture, "INV_Fishingpole") ) then
253 local link = GetInventoryItemLink("player", slot);
254 local _, id, _ = FishingBuddy.SplitLink(link);
255 -- Make sure it's not "Nat Pagle's Fish Terminator"
256 return (id ~= 19944);
257 end
258 return false;
259 end
260 FishingBuddy.IsFishingPole = IsFishingPole;
261  
262 -- override the error message method (need an object as the first arg)
263 local function UIError_AddMessage( o, msg, a, r, g, b, hold )
264 -- If we should be hiding the can't use item error, then do so
265 if ( TestingLures and msg == ERR_CANT_USE_ITEM ) then
266 -- We have the can't use item error, so abort
267 return;
268 end
269 --Call the original
270 local obj = SavedAddMessage.obj;
271 local method = SavedAddMessage.method;
272 return method( obj, msg, a, r, g, b, hold );
273 end
274 FishingBuddy.AddMessage = UIError_AddMessage;
275  
276 local function HijackCheck()
277 return ( GetSetting("EasyCast") == 1 and
278 CastingKeys() and IsFishingPole() );
279 end
280  
281 local SavedWFOnMouseUp;
282 local SavedWFOnMouseDown;
283 -- handle mouse up and mouse down in the WorldFrame so that we can steal
284 -- the hardware events to implement 'Easy Cast'
285 -- Thanks to the Cosmos team for figuring this one out -- I didn't realize
286 -- that the mouse handler in the WorldFrame got everything first!
287 local function WF_OnMouseDown()
288 -- Only steal 'right clicks'
289 if ( arg1 == "RightButton" and HijackCheck() ) then
290 FishingBuddy.ActionStartCheck();
291 end
292 if ( SavedWFOnMouseDown ) then
293 SavedWFOnMouseDown();
294 end
295 end
296  
297 -- disable click to move if we're fishing
298 local resetClickToMove = false;
299 local function WF_OnMouseUp()
300 local retval;
301 if ( SavedWFOnMouseUp ) then
302 retval = SavedWFOnMouseUp();
303 end
304 -- Only steal 'right clicks'
305 if ( arg1 == "RightButton" ) then
306 -- we fail if there are multiple modifier keys
307 if ( IsAltKeyDown() and ( IsShiftKeyDown() or IsControlKeyDown() ) ) then
308 return retval;
309 end
310 if ( IsShiftKeyDown() and IsControlKeyDown() ) then
311 return retval;
312 end
313 if ( HijackCheck() ) then
314 FishingBuddy.StopCastingCheck();
315 elseif ( resetClickToMove ) then
316 -- Re-enable Click-to-Move if we changed it
317 SetCVar("autointeract", "1");
318 resetClickToMove = nil;
319 end
320 end
321 return retval;
322 end
323  
324 -- Find things in our inventory
325 local function FindItem(id)
326 if ( id ) then
327 local numSlots = 0;
328 -- check each of the bags on the player
329 for bag=0, NUM_BAG_FRAMES do
330 -- get the number of slots in the bag (0 if no bag)
331 numSlots = GetContainerNumSlots(bag);
332 if (numSlots > 0) then
333 -- check each slot in the bag
334 for slot=1, numSlots do
335 local link = GetContainerItemLink (bag,slot);
336 if (link) then
337 local c, i, n = FishingBuddy.SplitLink(link);
338 local check = string.gsub(i, "^(%d+):(%d+):(%d+):(%d+)$", "%1:%2:0:0");
339 if ( check == id ) then
340 return bag, slot;
341 end
342 end
343 end
344 end
345 end
346 end
347 return nil, nil;
348 end
349  
350 local function SafeHookMethod(object, method, newmethod)
351 local oldValue = object[method];
352 if ( oldValue ~= getglobal(newmethod) ) then
353 object[method] = newmethod;
354 return true;
355 end
356 return false;
357 end
358  
359 local function SafeHookScript(frame, handlername, newscript)
360 local oldValue = frame:GetScript(handlername);
361 frame:SetScript(handlername, newscript);
362 return oldValue;
363 end
364  
365 -- Something else that should be in a library
366 FishingBuddy.SplitLink = function(link)
367 if ( link ) then
368 local _,_, color, item, name = string.find(link, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r");
369 return color, item, name;
370 end
371 end
372  
373 FishingBuddy.SplitFishLink = function(link)
374 if ( link ) then
375 local _,_, color, id, name = string.find(link, "|c(%x+)|Hitem:(%d+):%d+:%d+:%d+|h%[(.-)%]|h|r");
376 return color, tonumber(id), name;
377 end
378 end
379  
380 -- handle the vagaries of zones and subzones
381 FishingBuddy.GetZoneInfo = function()
382 local zone = GetRealZoneText();
383 local subzone = GetSubZoneText();
384 if ( not zone or zone == "" ) then
385 zone = FishingBuddy.UNKNOWN;
386 end
387 if ( not subzone or subzone == "" ) then
388 subzone = zone;
389 end
390 return zone, subzone;
391 end
392  
393 FishingBuddy.AddFishie = function(color, id, name, zone, subzone, texture, quantity, quality)
394 if ( not FishingBuddy_Info["Fishies"][id] ) then
395 FishingBuddy_Info["Fishies"][id] = { };
396 FishingBuddy_Info["Fishies"][id].name = name;
397 FishingBuddy_Info["Fishies"][id].texture = texture;
398 FishingBuddy_Info["Fishies"][id].quality = quality;
399 if ( color ~= "ffffffff" ) then
400 FishingBuddy_Info["Fishies"][id].color = color;
401 end
402 if ( FishingBuddy.SortedFishies ) then
403 tinsert(FishingBuddy.SortedFishies, { text = name, id = id });
404 FishingBuddy.FishSort(FishingBuddy.SortedFishies, true);
405 end
406 end
407  
408 if ( not zone ) then
409 zone = FishingBuddy.UNKNOWN;
410 end
411 if ( not subzone ) then
412 subzone = zone;
413 end
414  
415 if ( not FishingBuddy.currentFishies[subzone] ) then
416 FishingBuddy.currentFishies[subzone] = {};
417 end
418 if ( not FishingBuddy.currentFishies[subzone][id] ) then
419 FishingBuddy.currentFishies[subzone][id] = quantity;
420 else
421 FishingBuddy.currentFishies[subzone][id] = FishingBuddy.currentFishies[subzone][id] + quantity;
422 end
423  
424 if( not FishingBuddy_Info["FishingHoles"][zone] ) then
425 FishingBuddy_Info["FishingHoles"][zone] = { };
426 tinsert(FishingBuddy.SortedZones, zone);
427 table.sort(FishingBuddy.SortedZones);
428 end
429 if( not FishingBuddy_Info["FishingHoles"][zone][subzone] ) then
430 FishingBuddy_Info["FishingHoles"][zone][subzone] = { };
431 FishingBuddy.SortedByZone[zone] = {};
432 tinsert(FishingBuddy.SortedByZone[zone], subzone);
433 table.sort(FishingBuddy.SortedByZone[zone]);
434 tinsert(FishingBuddy.SortedSubZones, subzone);
435 table.sort(FishingBuddy.SortedSubZones);
436 end
437 local fh = FishingBuddy_Info["FishingHoles"][zone];
438 if ( not fh[subzone][id] ) then
439 fh[subzone][id] = quantity;
440 if ( GetSetting("ShowNewFishies") == 1 ) then
441 FishingBuddy.Print(FishingBuddy.ADDFISHIEMSG, name, subzone);
442 end
443 else
444 fh[subzone][id] = fh[subzone][id] + quantity;
445 end
446  
447 if ( FishingBuddy.ByFishie ) then
448 if ( not FishingBuddy.ByFishie[id] ) then
449 FishingBuddy.ByFishie[id] = {};
450 end
451 if ( not FishingBuddy.ByFishie[id][subzone] ) then
452 FishingBuddy.ByFishie[id][subzone] = quantity;
453 else
454 FishingBuddy.ByFishie[id][subzone] = FishingBuddy.ByFishie[id][subzone] + quantity;
455 end
456 end
457 FishingBuddy.Locations.DataChanged(zone, subzone, fishie);
458 FishingBuddy.WatchUpdate();
459 end
460  
461 FishingBuddy.GetFishie = function(fishid)
462 if( FishingBuddy_Info["Fishies"][fishid] ) then
463 return string.format("%d:0:0:0", fishid),
464 FishingBuddy_Info["Fishies"][fishid].texture,
465 FishingBuddy_Info["Fishies"][fishid].color,
466 FishingBuddy_Info["Fishies"][fishid].quantity,
467 FishingBuddy_Info["Fishies"][fishid].quality,
468 FishingBuddy_Info["Fishies"][fishid].name;
469 end
470 end
471  
472 local function ImportFish()
473 local oldShowNewFishies = GetSetting("ShowNewFishies");
474 SetSetting("ShowNewFishies");
475 if ( FishInfo2DataSub and FishingBuddy_Info["FishInfo2"] == 0 ) then
476 for toon in FishInfo2DataSub do
477 if ( not string.find(toon, "|User$") ) then
478 for fishie in FishInfo2DataSub[toon] do
479 local texture = FishInfo2DataSub[toon][fishie]["texture"];
480 local quality = FishInfo2DataSub[toon][fishie]["rarity"];
481 local fz = FishInfo2DataSub[toon][fishie]["zones"];
482 local link = FishInfo2DataSub[toon][fishie]["link"];
483 if ( link ) then
484 local _,_,id = string.find(link, "^(%d+):");
485 for zone in fz do
486 for subzone in fz[zone] do
487 local quantity = fz[zone][subzone];
488 FishingBuddy.AddFishie("ffffffff", id, fishie, zone, subzone, texture, quantity, quality)
489 end
490 end
491 end
492 end
493 end
494 end
495 FishingBuddy_Info["FishInfo2"] = 1;
496 FishingBuddy.Print(FishingBuddy.IMPORTMSG, "FishInfo2");
497 -- elseif ( imppfishinfoDB and FishingBuddy_Info["ImppDBLoaded"] == 0 ) then
498 -- for subzone in imppfishinfoDB do
499 -- for item in imppfishinfoDB[subzone]["itemnames"] do
500 -- local quantity = imppfishinfoDB[subzone]["itemnames"][item].number;
501 -- local texture = imppfishinfoDB[subzone]["itemnames"][item].texture;
502 -- local quality = imppfishinfoDB[subzone]["itemnames"][item].quality;
503 -- FishingBuddy.AddFishie(color, id, name, subzone, texture, item, quantity, quality)
504 -- end
505 -- end
506 -- FishingBuddy_Info["ImppDBLoaded"] = 1;
507 -- FishingBuddy.Print(FishingBuddy.IMPORTMSG, "Impp's fishinfo");
508 -- elseif ( DataFishDB and FishingBuddy_Info["DataFish"] == 0 ) then
509 -- for fishie in DataFishDB["catches"] do
510 -- for zone in DataFishDB["catches"][fishie]["locnames"] do
511 -- for subzone in DataFishDB["catches"][fishie]["locnames"][zone] do
512 -- local dfl = DataFishDB["locations"][subzone]["itemnames"][fishie];
513 -- local quantity = dfl["number"];
514 -- local texture = dfl["texture"];
515 -- local quality = dfl["quality"];
516 -- FishingBuddy.AddFishie(color, id, name, zone, subzone, texture, quantity, quality)
517 -- end
518 -- end
519 -- end
520 -- FishingBuddy_Info["DataFish"] = 1;
521 -- FishingBuddy.Print(FishingBuddy.IMPORTMSG, "DataFish");
522 else
523 FishingBuddy.Message(FishingBuddy.NOIMPORTMSG);
524 end
525 SetSetting("ShowNewFishies", oldShowNewFishies);
526 end
527  
528 local function FindSpellID(thisone)
529 local id = 1;
530 local spellTexture = GetSpellTexture(id, BOOKTYPE_SPELL);
531 while (spellTexture) do
532 if (spellTexture and spellTexture == thisone) then
533 return id;
534 end
535 id = id + 1;
536 spellTexture = GetSpellTexture(id, BOOKTYPE_SPELL);
537 end
538 return nil;
539 end
540  
541 local function GetFishingSpellID()
542 if ( not FishingSpellID or not FishingSkillName) then
543 FishingSpellID = FindSpellID(FishingBuddy.FISHINGTEXTURE);
544 end
545 if ( FishingSpellID and not FishingSkillName ) then
546 FishingSkillName = GetSpellName(FishingSpellID, BOOKTYPE_SPELL);
547 end
548 end
549  
550 FishingBuddy.GetFishingSkillName = function()
551 GetFishingSpellID();
552 if ( not FishingSkillName ) then
553 return FishingBuddy.FISHINGSKILL;
554 else
555 return FishingSkillName;
556 end
557  
558 end
559  
560 local function InvokeFishing()
561 GetFishingSpellID();
562 if ( FishingSpellID ) then
563 CastSpell(FishingSpellID, BOOKTYPE_SPELL);
564 end
565 end
566  
567 -- do everything we think is necessary when we start fishing
568 -- even if we didn't do the switch to a fishing pole
569 local function StartFishingMode()
570 if ( not StartedFishing ) then
571 StartedFishing = GetTime();
572 FishingBuddy.EnhanceFishingSounds(true);
573 FishingBuddy.WatchUpdate();
574 end
575 end
576 FishingBuddy.StartFishingMode = StartFishingMode;
577  
578 local function StopFishingMode()
579 if ( StartedFishing ) then
580 FishingBuddy.EnhanceFishingSounds(false);
581 FishingBuddy.WatchUpdate();
582 StartedFishing = nil;
583 end
584 if ( resetClickToMove ) then
585 -- Re-enable Click-to-Move if we changed it
586 SetCVar("autointeract", "1");
587 resetClickToMove = nil;
588 end
589 end
590 FishingBuddy.StopFishingMode = StopFishingMode;
591  
592 local function FishingMode()
593 if ( IsFishingPole() ) then
594 StartFishingMode();
595 else
596 StopFishingMode();
597 end
598 end
599 FishingBuddy.FishingMode = FishingMode;
600  
601 local function OnFishingBobber()
602 if ( GameTooltip:IsVisible() ) then
603 local text = getglobal("GameTooltipTextLeft1");
604 if ( text ) then
605 text = text:GetText();
606 -- let a partial match work (for translations)
607 return ( text and string.find(text, FishingBuddy.BOBBER_NAME ) );
608 end
609 end
610 return false;
611 end
612  
613 -- Easy lures (borrowed from Mugendai's excellent code)
614 local function UpdateLure()
615 -- if the pole has an enchantment, we can assume it's got a lure on it (so far, anyway)
616 if ( ( GetSetting("EasyLures") == 1 ) and not GetWeaponEnchantInfo() ) then
617 -- trap message handler if we haven't already
618 if ( not SavedAddMessage ) then
619 FishingBuddy.TrapUIErrors();
620 end
621  
622 --Check for a lure in the bags, starting with the highest power one
623 local bag, slot;
624 for lure in FISHINGLURES do
625 --If we find this lure in the bag, then use it
626 bag, slot = FindItem(lure);
627 if (bag and slot) then
628 --We need to temporarily disable the cant use item error, incase this item is too high of a level to use
629 TestingLures = true;
630 --Temporarily disable error message sounds, incase this item is too high of a level to use
631 local soundState = GetCVar("EnableErrorSpeech");
632 if ( soundState == "1" ) then
633 SetCVar("EnableErrorSpeech", 0);
634 end
635 --Try to use the item
636 UseContainerItem(bag, slot);
637 -- re-enable the can't use item error message
638 TestingLures = false;
639 -- re-enable error message sounds
640 if ( soundState == "1" ) then
641 SetCVar("EnableErrorSpeech", 1);
642 end
643 -- if we have a targeting cursor, then we succesfully used the lure
644 if ( SpellIsTargeting() ) then
645 -- apply the lure to the fishing pole
646 local mainhandslot = GetInventorySlotInfo("MainHandSlot");
647 PickupInventoryItem(mainhandslot);
648 AddingLure = true;
649 return true;
650 end
651 end
652 end
653 end
654 return false;
655 end
656  
657 FishingBuddy.ActionStartCheck = function()
658 -- Disable Click-to-Move if we're fishing
659 if ( GetCVar("autointeract") == "1" ) then
660 resetClickToMove = true;
661 SetCVar("autointeract", "0");
662 end
663 -- Don't interrupt putting on a lure, or if we're not fastcasting
664 if ( AddingLure ) then
665 ActionStartTime = 0;
666 else
667 ActionStartTime = GetTime();
668 end
669 end
670  
671 -- add the double click checking in based on the code is Cosmos
672 FishingBuddy.StopCastingCheck = function()
673 if ( not ActionStartTime ) then
674 ActionStartTime = 0;
675 end
676 if ( not ActionDoubleTime ) then
677 ActionDoubleTime = 0;
678 end
679 local time = GetTime();
680 local pressTime = time - ActionStartTime;
681 local doubleTime = time - ActionDoubleTime;
682 -- if we're not putting on a lure and the casting modifiers are good
683 if ( not SpellIsTargeting() ) then
684 -- if the click was "short" enough that we're going to treat it
685 -- as a cast
686 if ( ActionStartTime > 0 and ACTIONDOWNWAIT >= pressTime) then
687 -- if we're already casting, enforce double click timing
688 if ( GetSetting("FastCast") ~= 1 and CastingNow and
689 ( ActionDoubleTime == 0 or ACTIONDOUBLEWAIT < doubleTime ) ) then
690 ActionDoubleTime = GetTime();
691 else
692 ActionDoubleTime = 0;
693 -- rebind the mouse event
694 UpdateBindings(true);
695 end
696 end
697 end
698 end
699  
700 FishingBuddy.PerformCast = function()
701 -- We're stealing the mouse-up hardware event, make sure we exit MouseLook
702 if ( IsMouselooking() ) then
703 MouselookStop();
704 end
705 -- reset the TURNORACTION binding so that everything else works 'right'
706 UpdateBindings(false);
707 -- put on a lure if we need to
708 if ( not UpdateLure() ) then
709 InvokeFishing();
710 end
711 end
712  
713 FishingBuddy.TrapUIErrors = function()
714 local temp = {};
715 temp.obj= UIErrorsFrame;
716 temp.method = UIErrorsFrame["AddMessage"];
717 if ( SafeHookMethod(UIErrorsFrame, "AddMessage", FishingBuddy.AddMessage) ) then
718 SavedAddMessage = temp;
719 end
720 end
721  
722 FishingBuddy.TrapWorldMouse = function()
723 SavedWFOnMouseUp = SafeHookScript(WorldFrame, "OnMouseUp", WF_OnMouseUp);
724 SavedWFOnMouseDown = SafeHookScript(WorldFrame, "OnMouseDown", WF_OnMouseDown);
725 end
726  
727 -- User interface handling
728  
729 FishingBuddy.Commands = {};
730 FishingBuddy.Commands[FishingBuddy.SWITCH] = {};
731 FishingBuddy.Commands[FishingBuddy.SWITCH].func = function()
732 FishingBuddy.OutfitManager.Switch();
733 return true;
734 end;
735 FishingBuddy.Commands[FishingBuddy.CURRENT] = {};
736 FishingBuddy.Commands[FishingBuddy.CURRENT].help = FishingBuddy.CURRENT_HELP;
737 FishingBuddy.Commands[FishingBuddy.CURRENT].func =
738 function(what)
739 if ( what and what == FishingBuddy.RESET) then
740 FishingBuddy.currentFishies = {};
741 FishingMode();
742 return true;
743 end
744 end;
745 FishingBuddy.Commands[FishingBuddy.IMPORT] = {};
746 FishingBuddy.Commands[FishingBuddy.IMPORT].help = FishingBuddy.IMPORT_HELP;
747 FishingBuddy.Commands[FishingBuddy.IMPORT].func =
748 function()
749 ImportFish();
750 return true;
751 end;
752 FishingBuddy.Commands[FishingBuddy.CLEANUP] = {};
753 FishingBuddy.Commands[FishingBuddy.CLEANUP].help = FishingBuddy.CLEANUP_HELP;
754 FishingBuddy.Commands[FishingBuddy.CLEANUP].func =
755 function(what)
756 local tabs = { "Settings", "Outfit", "WasWearing" };
757 local rnames = {};
758 local onames = {};
759 if ( not what or what == FishingBuddy.CHECK ) then
760 if ( FishingBuddy_Info["Settings"] ) then
761 for name in FishingBuddy_Info["Settings"] do
762 tinsert(onames, name);
763 end
764 end
765 if ( FishingBuddy_Info[realmName] ) then
766 local fs = FishingBuddy_Info[realmName]["Settings"];
767 if ( fs ) then
768 for name,info in fs do
769 tinsert(rnames, name);
770 end
771 end
772 end
773 if ( next(rnames) or next(onames) ) then
774 if ( next(rnames) ) then
775 FishingBuddy.Print(FishingBuddy.CLEANUP_WILLMSG, realmName,
776 FishingBuddy.EnglishList(rnames));
777 end
778 if ( next(onames) ) then
779 FishingBuddy.Print(FishingBuddy.CLEANUP_WILLMSG,
780 FishingBuddy.NOREALM,
781 FishingBuddy.EnglishList(onames));
782 end
783 else
784 FishingBuddy.Message(FishingBuddy.CLEANUP_NONEMSG);
785 end
786 return true;
787 else
788 if ( what == FishingBuddy.NOW ) then
789 if ( FishingBuddy_Info["Settings"] ) then
790 for name in FishingBuddy_Info["Settings"] do
791 tinsert(onames, name);
792 end
793 end
794 if ( FishingBuddy_Info[realmName] ) then
795 local fs = FishingBuddy_Info[realmName]["Settings"];
796 if ( fs ) then
797 for name,info in fs do
798 tinsert(rnames, name);
799 end
800 end
801 end
802 else
803 if ( FishingBuddy_Info["Settings"] and FishingBuddy_Info["Settings"][what] ) then
804 tinsert(onames, what);
805 elseif ( FishingBuddy_Info[realmName] and
806 FishingBuddy_Info[realmName]["Settings"] and
807 FishingBuddy_Info[realmName]["Settings"][what] ) then
808 tinsert(rnames, what);
809 else
810 FishingBuddy.Print(FishingBuddy.CLEANUP_NOOLDMSG, what);
811 return true;
812 end
813 end
814 if ( next(rnames) or next(onames) ) then
815 if ( next(rnames) ) then
816 for _,name in rnames do
817 for _,tab in tabs do
818 if ( FishingBuddy_Info[realmName] and FishingBuddy_Info[realmName][tab] ) then
819 FishingBuddy_Info[realmName][tab][name] = nil;
820 if ( next(FishingBuddy_Info[realmName][tab]) == nil ) then
821 FishingBuddy_Info[realmName][tab] = nil;
822 end
823 end
824 end
825 end
826 if ( FishingBuddy_Info[realmName] and next(FishingBuddy_Info[realmName]) == nil ) then
827 FishingBuddy_Info[realmName] = nil;
828 end
829 FishingBuddy.Print(FishingBuddy.CLEANUP_DONEMSG, realmName,
830 FishingBuddy.EnglishList(rnames));
831 end
832 if ( next(onames) ) then
833 for _,name in onames do
834 for _,tab in tabs do
835 if ( FishingBuddy_Info[tab] ) then
836 FishingBuddy_Info[tab][name] = nil;
837 if ( next(FishingBuddy_Info[tab]) ) then
838 FishingBuddy_Info[tab] = nil;
839 end
840 end
841 end
842 end
843 FishingBuddy.Print(FishingBuddy.CLEANUP_DONEMSG,
844 FishingBuddy.NOREALM,
845 FishingBuddy.EnglishList(onames));
846 end
847 else
848 FishingBuddy.Message(FishingBuddy.CLEANUP_NONEMSG);
849 end
850 return true;
851 end
852 end;
853  
854 local function nextarg(msg, pattern)
855 if ( not msg or not pattern ) then
856 return nil, nil;
857 end
858 local s,e = string.find(msg, pattern);
859 if ( s ) then
860 local word = strsub(msg, s, e);
861 msg = strsub(msg, e+1);
862 return word, msg;
863 end
864 return nil, msg;
865 end
866  
867 FishingBuddy.Command = function(msg)
868 if ( not msg ) then
869 return;
870 end
871 if ( FishingBuddy.IsLoaded() ) then
872 -- collect arguments (whee, lua string manipulation)
873 local cmd;
874 cmd, msg = nextarg(msg, "[%w]+");
875  
876 -- the empty string gives us no args at all
877 if ( not cmd ) then
878 -- toggle window
879 if ( FishingBuddyFrame:IsVisible() ) then
880 HideUIPanel(FishingBuddyFrame);
881 else
882 ShowUIPanel(FishingBuddyFrame);
883 end
884 elseif ( cmd == FishingBuddy.HELP or cmd == "help" ) then
885 FishingBuddy.Output(FishingBuddy.WINDOW_TITLE);
886 FishingBuddy.PrintHelp(FishingBuddy.HELPMSG);
887 else
888 local command = FishingBuddy.Commands[cmd];
889 if ( command ) then
890 local args = {};
891 local goodargs = true;
892 if ( command.args ) then
893 for _,pat in command.args do
894 local w, msg = nextarg(msg, pat);
895 if ( not w ) then
896 goodargs = false;
897 break;
898 end
899 tinsert(args, w);
900 end
901 else
902 local a;
903 while ( msg ) do
904 a, msg = nextarg(msg, "[%w]+");
905 if ( not a ) then
906 break;
907 end
908 tinsert(args, a);
909 end
910 end
911 if ( not goodargs or not command.func(unpack(args)) ) then
912 if ( command.help ) then
913 FishingBuddy.PrintHelp(command.help);
914 else
915 FishingBuddy.Debug("command failed");
916 end
917 end
918 else
919 FishingBuddy.Command("help");
920 end
921 end
922 else
923 FishingBuddy.Error(FishingBuddy.FAILEDINIT);
924 end
925 end
926  
927 FishingBuddy.OnLoad = function()
928 this:RegisterEvent("PLAYER_LOGIN");
929 this:RegisterEvent("PLAYER_LOGOUT");
930 this:RegisterEvent("VARIABLES_LOADED");
931  
932 this:RegisterEvent("ITEM_LOCK_CHANGED");
933 this:RegisterEvent("LOOT_OPENED");
934 this:RegisterEvent("ZONE_CHANGED");
935 this:RegisterEvent("MINIMAP_ZONE_CHANGED");
936  
937 this:RegisterEvent("SPELLS_CHANGED");
938 this:RegisterEvent("SPELLCAST_CHANNEL_START");
939 this:RegisterEvent("SPELLCAST_CHANNEL_STOP");
940 this:RegisterEvent("SPELLCAST_START");
941 this:RegisterEvent("SPELLCAST_STOP");
942 this:RegisterEvent("SPELLCAST_INTERRUPTED");
943 this:RegisterEvent("SPELLCAST_FAILED");
944  
945 this:RegisterEvent("SKILL_LINES_CHANGED");
946  
947 -- Set up command
948 SlashCmdList["fishingbuddy"] = FishingBuddy.Command;
949 SLASH_fishingbuddy1 = "/fishingbuddy";
950 SLASH_fishingbuddy2 = "/fb";
951  
952 FishingBuddy.Output(FishingBuddy.WINDOW_TITLE.." loaded");
953 end
954  
955 FishingBuddy.OnEvent = function()
956 local needUpdate = false;
957 if ( event == "VARIABLES_LOADED" ) then
958 FishingBuddy.Initialize();
959 elseif ( event == "PLAYER_LOGIN" ) then
960 -- set up outfit stuff
961 FishingBuddy.OutfitManager.Initialize();
962 FishingMode();
963 elseif ( event == "PLAYER_LOGOUT" ) then
964 -- reset the fishing sounds, if we need to
965 StopFishingMode();
966 FishingBuddy.SavePlayerInfo();
967 elseif ( event == "ITEM_LOCK_CHANGED" ) then
968 FishingMode();
969 elseif ( event == "LOOT_OPENED" ) then
970 if ( IsFishingLoot()) then
971 local zone, subzone = FishingBuddy.GetZoneInfo();
972 for index = 1, GetNumLootItems(), 1 do
973 if (LootSlotIsItem(index)) then
974 local texture, fishie, quantity, quality = GetLootSlotInfo(index);
975 local link = GetLootSlotLink(index);
976 local color, id, name = FishingBuddy.SplitFishLink(link);
977 FishingBuddy.AddFishie(color, id, name, zone, subzone, texture, quantity, quality);
978 if ( FishingBuddy.AddTracking ) then
979 FishingBuddy.AddTracking(id, name);
980 end
981 FishingBuddy.SetZoneLevel(zone, subzone, id);
982 end
983 end
984 end
985 elseif ( event == "ZONE_CHANGED" or event == "MINIMAP_ZONE_CHANGED" ) then
986 if ( not FishingBuddy.IsLoaded() ) then
987 return;
988 end
989 FishingBuddy.currentFishies = {};
990 needUpdate = true;
991 elseif ( event == "SKILL_LINES_CHANGED" ) then
992 if ( GetSetting("WatchCurrentSkill") == 1 ) then
993 needUpdate = true;
994 end
995 elseif ( event == "SPELLS_CHANGED" ) then
996 -- Fishing might have moved, go look again
997 FishingSpellID = nil;
998 else
999 -- Mugendai is one sharp cookie (shamelessly stealing from TackleBox again)
1000 -- Keep up with whether or not we are casting
1001 if ( event == "SPELLCAST_CHANNEL_START" ) then
1002 CastingNow = true;
1003 elseif ( event == "SPELLCAST_CHANNEL_STOP" ) then
1004 CastingNow = false;
1005 else
1006 -- Keep up with whether we are adding a lure (or casting a normal spell) or not
1007 if ( event == "SPELLCAST_START" ) then
1008 -- AddingLure = true;
1009 elseif ( event == "SPELLCAST_STOP" ) then
1010 if ( AddingLure ) then
1011 AddingLure = false;
1012 -- update the skill line if we have one
1013 if ( GetSetting("WatchCurrentSkill") == 1 ) then
1014 needUpdate = true;
1015 end
1016 end
1017 elseif ( ( event == "SPELLCAST_INTERRUPTED" ) or ( event == "SPELLCAST_FAILED" ) ) then
1018 AddingLure = false;
1019 end
1020 end
1021 end
1022 FishingBuddy.Extravaganza.IsTime(true);
1023 if ( needUpdate ) then
1024 FishingBuddy.WatchUpdate();
1025 end
1026 end
1027  
1028 FishingBuddy.PrintHelp = function(tab)
1029 if ( type(tab) == "table" ) then
1030 for _,line in tab do
1031 FishingBuddy.PrintHelp(line);
1032 end
1033 else
1034 FishingBuddy.Output(tab);
1035 end
1036 end
1037  
1038 FishingBuddy["EFSV"] = {};
1039 FishingBuddy["EFSV"]["MusicVolume"] = tonumber(GetCVar("MusicVolume"));
1040 FishingBuddy["EFSV"]["AmbienceVolume"] = tonumber(GetCVar("AmbienceVolume"));
1041 FishingBuddy["EFSV"]["SoundVolume"] =tonumber(GetCVar("SoundVolume"));
1042 local SoundWasEnhanced;
1043 FishingBuddy.EnhanceFishingSounds = function(turniton)
1044 if ( GetSetting("EnhanceFishingSounds") == 1 ) then
1045 if ( turniton ) then
1046 -- collect the current value
1047 FishingBuddy["EFSV"]["MusicVolume"] = tonumber(GetCVar("MusicVolume"));
1048 FishingBuddy["EFSV"]["AmbienceVolume"] = tonumber(GetCVar("AmbienceVolume"));
1049 FishingBuddy["EFSV"]["SoundVolume"] =tonumber(GetCVar("SoundVolume"));
1050 -- turn 'em off!
1051 for setting in FishingBuddy["EFSV"] do
1052 SetCVar(setting,
1053 GetSetting("EnhanceSound"..setting));
1054 end
1055 SoundWasEnhanced = true;
1056 else
1057 if ( SoundWasEnhanced ) then
1058 for setting, value in FishingBuddy["EFSV"] do
1059 SetCVar(setting, value);
1060 end
1061 SoundWasEnhanced = false;
1062 end
1063 end
1064 end
1065 end
1066  
1067 -- Drop-down menu support
1068 FishingBuddy.ToggleSetting = function(setting)
1069 local value = GetSetting(setting);
1070 if ( not value ) then
1071 value = 0;
1072 end
1073 SetSetting(setting, 1 - value);
1074 FishingBuddy.WatchUpdate();
1075 FishingBuddy.UpdateMinimap();
1076 end
1077  
1078 -- save some memory by keeping one copy of each one
1079 local ToggleFunctions = {};
1080 -- let's use closures
1081 local function MakeToggle(name)
1082 if ( not ToggleFunctions[name] ) then
1083 local n = name;
1084 ToggleFunctions[name] = function() FishingBuddy.ToggleSetting(n) end;
1085 end
1086 return ToggleFunctions[name];
1087 end
1088  
1089 FishingBuddy.MakeDropDown = function(switchItem, switchSetting)
1090 local info;
1091 -- If no outfit frame, we can't switch outfits...
1092 if ( FishingBuddy.OutfitManager.HasManager() ) then
1093 info = {};
1094 info.text = switchItem;
1095 info.func = MakeToggle(switchSetting);
1096 info.checked = (GetSetting(switchSetting) == 1);
1097 info.keepShownOnClick = 1;
1098 UIDropDownMenu_AddButton(info);
1099 info = {};
1100 info.disabled = 1;
1101 UIDropDownMenu_AddButton(info);
1102 end
1103  
1104 for _, option in FishingBuddy.OPTIONS do
1105 local addthis = true;
1106 if ( option.check ) then
1107 addthis = option.check();
1108 end
1109 if ( addthis ) then
1110 info = {};
1111 info.text = option.text;
1112 info.func = MakeToggle(option.name);
1113 info.checked = (GetSetting(option.name) == 1);
1114 info.keepShownOnClick = 1;
1115 UIDropDownMenu_AddButton(info);
1116 end
1117 end
1118 end
1119  
1120 -- utility functions
1121 FishingBuddy.AddTooltip = function(text, r, g, b)
1122 if ( text ) then
1123 if ( type(text) == "table" ) then
1124 for _,l in text do
1125 FishingBuddy.AddTooltip(l.text, l.r, l.g, l.b);
1126 end
1127 else
1128 GameTooltip:AddLine(text, r, g, b);
1129 end
1130 end
1131 end
1132  
1133 FishingBuddy.ChatLink = function(item, name, color)
1134 if( item and name and ChatFrameEditBox:IsVisible() ) then
1135 if not color then
1136 color = FishingBuddy.Colors.WHITE;
1137 end
1138 local link = "|c"..color.."|Hitem:"..item.."|h["..name.."]|h|r";
1139 ChatFrameEditBox:Insert(link);
1140 end
1141 end
1142  
1143 FishingBuddy.FishSort = function(tab, forcename)
1144 if ( forcename or GetSetting("SortByPercent") == 0 ) then
1145 table.sort(tab, function(a,b) return a.text and b.text and a.text<b.text; end);
1146 else
1147 table.sort(tab, function(a,b) return a.count and b.count and b.count<a.count; end);
1148 end
1149 end
1150  
1151 FishingBuddy.EnglishList = function(list, conjunction)
1152 if ( list ) then
1153 local n = table.getn(list);
1154 local str = "";
1155 for idx=1,n do
1156 local name = list[idx];
1157 if ( idx == 1 ) then
1158 str = name;
1159 elseif ( idx == n ) then
1160 str = str .. ", ";
1161 if ( conjunction ) then
1162 str = str .. conjunction;
1163 else
1164 str = str .. "and";
1165 end
1166 str = str .. " " .. name;
1167 else
1168 str = str .. ", " .. name;
1169 end
1170 end
1171 return str;
1172 end
1173 end
1174  
1175 FishingBuddy.Message = function(msg, r, g, b)
1176 FishingBuddy.Output(FishingBuddy.NAME..": "..msg, r, g, b);
1177 end
1178  
1179 FishingBuddy.Print = function(...)
1180 local msg = string.format(unpack(arg));
1181 FishingBuddy.Message(msg);
1182 end
1183  
1184 FishingBuddy.Error = function(msg)
1185 FishingBuddy.Output(FishingBuddy.NAME..": "..msg, 1.0, 0, 0);
1186 end
1187  
1188 FishingBuddy.UIError = function(msg)
1189 -- Okay, this check is probably not necessary...
1190 if ( UIErrorsFrame ) then
1191 UIErrorsFrame:AddMessage(msg, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
1192 else
1193 FishingBuddy.Error(msg);
1194 end
1195 end
1196  
1197 FishingBuddy.Testing = function(line)
1198 if ( not FishingBuddy_Info["Testing"] ) then
1199 FishingBuddy_Info["Testing"] = {};
1200 end
1201 tinsert(FishingBuddy_Info["Testing"], line);
1202 end