commit 6b001ce4b48dc7bf619f8412cef52ef6aec8dec1 Author: anthonycoffey Date: Thu Oct 19 17:39:57 2017 -0500 initial commit diff --git a/Bindings.xml b/Bindings.xml new file mode 100755 index 0000000..05c46ab --- /dev/null +++ b/Bindings.xml @@ -0,0 +1,42 @@ + + + + if ( keystate == "down" ) then + FishingBuddy.Command(""); + end + + + if ( keystate == "down" ) then + ToggleFishingBuddyFrame("FishingLocationsFrame"); + end + + + if ( keystate == "down" ) then + ToggleFishingBuddyFrame("FishingOutfitFrame"); + end + + + if ( keystate == "down" ) then + ToggleFishingBuddyFrame("FishingTrackingFrame"); + end + + + if ( keystate == "down" ) then + ToggleFishingBuddyFrame("FishingOptionsFrame"); + end + + + + if ( keystate == "down" ) then + FishingBuddy.Command(FishingBuddy.SWITCH); + end + + + + \ No newline at end of file diff --git a/FishingBuddy.lua b/FishingBuddy.lua new file mode 100755 index 0000000..73ff028 --- /dev/null +++ b/FishingBuddy.lua @@ -0,0 +1,1202 @@ +-- FishingBuddy +-- +-- Everything you wanted support for in your fishing endeavors + +-- Information for the stylin' fisherman +local POLES = { + ["Fishing Pole"] = "6256:0:0:0", + ["Strong Fishing Pole"] = "6365:0:0:0", + ["Darkwood Fishing Pole"] = "6366:0:0:0", + ["Big Iron Fishing Pole"] = "6367:0:0:0", + ["Blump Family Fishing Pole"] = "12225:0:0:0", + ["Nat Pagle's Extreme Angler FC-5000"] = "19022:0:0:0", + ["Arcanite Fishing Pole"] = "19970:0:0:0", + -- yeah, so you can't really use these (for now :-) + ["Dwarven Fishing Pole"] = "3567:0:0:0", + ["Goblin Fishing Pole"] = "4598:0:0:0", +} + +local FISHINGLURES = { + ["6533:0:0:0"] = "Aquadynamic Fish Attractor", -- 100 for 5 mins + ["7307:0:0:0"] = "Flesh Eating Worm", -- 75 for 10 mins + ["6532:0:0:0"] = "Bright Baubles", -- 75 for 10 mins + ["6811:0:0:0"] = "Aquadynamic Fish Lens", -- 50 for 10 mins + ["6530:0:0:0"] = "Nightcrawlers", -- 50 for 10 mins + ["6529:0:0:0"] = "Shiny Bauble", -- 25 for 10 mins +} + +FishingBuddy.OPTIONS = { + { ["name"] = "ShowNewFishies", + ["text"] = FishingBuddy.CONFIG_SHOWNEWFISHIES_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_SHOWNEWFISHIES_INFO, + ["default"] = 1 }, + { ["name"] = "WatchFishies", + ["text"] = FishingBuddy.CONFIG_FISHWATCH_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCH_INFO, + ["default"] = 1 }, + { ["name"] = "WatchCurrentSkill", + ["text"] = FishingBuddy.CONFIG_FISHWATCHSKILL_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHSKILL_INFO, + ["default"] = 1 }, + { ["name"] = "WatchCurrentZone", + ["text"] = FishingBuddy.CONFIG_FISHWATCHZONE_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHZONE_INFO, + ["default"] = 0 }, + { ["name"] = "WatchOnlyWhenFishing", + ["text"] = FishingBuddy.CONFIG_FISHWATCHONLY_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHONLY_INFO, + ["default"] = 1 }, + { ["name"] = "WatchFishPercent", + ["text"] = FishingBuddy.CONFIG_FISHWATCHPERCENT_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHPERCENT_INFO, + ["default"] = 1 }, + { ["name"] = "SortByPercent", + ["text"] = FishingBuddy.CONFIG_SORTBYPERCENT_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_SORTBYPERCENT_INFO, + ["default"] = 1 }, + { ["name"] = "SuitUpFirst", + ["text"] = FishingBuddy.CONFIG_SUITUPFIRST_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_SUITUPFIRST_INFO, + ["default"] = 0 }, + { ["name"] = "EasyCast", + ["text"] = FishingBuddy.CONFIG_EASYCAST_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_EASYCAST_INFO, + ["default"] = 1 }, + { ["name"] = "FastCast", + ["text"] = FishingBuddy.CONFIG_FASTCAST_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FASTCAST_INFO, + ["default"] = 1 }, + { ["name"] = "EasyLures", + ["text"] = FishingBuddy.CONFIG_EASYLURES_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_EASYLURES_INFO, + ["default"] = 0 }, + { ["name"] = "STVTimer", + ["text"] = FishingBuddy.CONFIG_STVTIMER_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_STVTIMER_INFO, + ["default"] = 0 }, + { ["name"] = "UseButtonHole", + ["text"] = FishingBuddy.CONFIG_USEBUTTONHOLE_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_USEBUTTONHOLE_INFO, + ["default"] = 0, + ["check"] = function () return ButtonHole ~= nil; end, + ["checkfail"] = 0 }, + { ["name"] = "MinimapButtonVisible", + ["text"] = FishingBuddy.CONFIG_MINIMAPBUTTON_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_MINIMAPBUTTON_INFO, + ["default"] = 1, + ["check"] = function () return not FishingBuddy.UseButtonHole(); end, + ["checkfail"] = 1 }, + { ["name"] = "EnhanceFishingSounds", + ["text"] = FishingBuddy.CONFIG_ENHANCESOUNDS_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_ENHANCESOUNDS_INFO, + ["default"] = 1 }, +} + +FishingBuddy.ByFishie = nil; +FishingBuddy.SortedFishies = nil; + +local ActionStartTime = 0; +local ActionDoubleTime = 0; +local ACTIONDOWNWAIT = 0.2; +local ACTIONDOUBLEWAIT = 0.4; +local SavedAddMessage = nil; + +FishingBuddy.SavedToggleMinimap = nil; + +local StartedFishing = nil; +local TestingLures = false; +local CastingNow = false; +local AddingLure = false; + +local FishingSpellID = nil; +local FishingSkillName = nil; + +local gotSetupDone = false; +local playerName = nil; +local realmName = nil; + +FishingBuddy.currentFishies = {}; + +local DEFAULT_MINIMAP_POSITION = 256; + +-- Fill in the player name and realm +FishingBuddy.SetupNameInfo = function() + playerName = UnitName("player"); + realmName = GetRealmName(); + return playerName, realmName; +end + +FishingBuddy.GetWasWearing = function() + if FishingBuddy_Player["WasWearing"] then + return FishingBuddy_Player["WasWearing"]; + end +end + +FishingBuddy.SetWasWearing = function(outfit) + FishingBuddy_Player["WasWearing"] = outfit; +end + +FishingBuddy.GetOutfitItem = function(slotName) + if (FishingBuddy_Player["Outfit"]) then + return FishingBuddy_Player["Outfit"][slotName]; + end +end + +FishingBuddy.GetOutfit = function() + return FishingBuddy_Player["Outfit"]; +end + +FishingBuddy.SetOutfit = function(outfit) + FishingBuddy_Player["Outfit"] = outfit; +end + +local function GetSetting(setting) + if ( not FishingBuddy_Player or + not FishingBuddy_Player["Settings"] ) then + return; + end + return FishingBuddy_Player["Settings"][setting]; +end +FishingBuddy.GetSetting = GetSetting; + +local function SetSetting(setting, value) + FishingBuddy_Player["Settings"][setting] = value; +end +FishingBuddy.SetSetting = SetSetting; + +-- handle option keys for enabling casting +local key_actions = { + [FishingBuddy.KEYS_NONE] = function() return true; end, + [FishingBuddy.KEYS_SHIFT] = function() return IsShiftKeyDown(); end, + [FishingBuddy.KEYS_CTRL] = function() return IsControlKeyDown(); end, + [FishingBuddy.KEYS_ALT] = function() return IsAltKeyDown(); end, +} +local function CastingKeys() + local setting = GetSetting("EasyCastKeys"); + if ( key_actions[setting] ) then + return key_actions[setting](); + else + return true; + end +end + +-- get our current fishing skill level +local lastSkillIndex = nil; +FishingBuddy.GetCurrentSkill = function() + if ( lastSkillIndex ) then + local name, _, _, rank, _, modifier = GetSkillLineInfo(lastSkillIndex); + if ( name == FishingBuddy.GetFishingSkillName() )then + return rank, modifier; + end + end + local n = GetNumSkillLines(); + for i=1,n do + local name, _, _, rank, _, modifier = GetSkillLineInfo(i); + if ( name == FishingBuddy.GetFishingSkillName() ) then + lastSkillIndex = i; + return rank, modifier; + end + end + return 0, 0; +end + +FishingBuddy.SetZoneLevel = function(zone, subzone, fishid) + local skill, mods = FishingBuddy.GetCurrentSkill(); + local fs = FishingBuddy_Info["FishingSkill"]; + if ( not fs[zone] ) then + fs[zone] = {}; + end + local skillcheck = skill + mods; + if ( skillcheck > 0 ) then + if ( not fs[zone][subzone] or skillcheck < fs[zone][subzone] ) then + fs[zone][subzone] = skillcheck; + end + if ( fishie ) then + if ( not FishingBuddy_Info["Fishies"][fishid].level or + skillcheck < FishingBuddy_Info["Fishies"][fishid].level ) then + FishingBuddy_Info["Fishies"][fishid].level = skillcheck; + FishingBuddy_Info["Fishies"][fishid].skill = skill; + FishingBuddy_Info["Fishies"][fishid].mods = mods; + end + end + end +end + +local OldBindingKey; +local function UpdateBindings(onoff) + if ( onoff ) then + if ( not OldKeyBinding ) then + OldKeyBinding = GetBindingKey("TURNORACTION"); + if ( OldKeyBinding ) then + SetBinding(OldKeyBinding, "FISHINGBUDDY_PERFORMCAST"); + else + FishingBuddy.UIError(FishingBuddy.TOOMANYFISHERMEN); + end + end + else + if ( OldKeyBinding ) then + SetBinding(OldKeyBinding, "TURNORACTION"); + OldKeyBinding = nil; + end + end +end +FishingBuddy.UpdateBindings = UpdateBindings; + +-- Shamelessly stolen from TackleBox +local function IsFishingPole() + -- Get the main hand item texture + local slot = GetInventorySlotInfo("MainHandSlot"); + local itemTexture = GetInventoryItemTexture("player", slot); + -- If there is infact an item in the main hand, and it's texture + -- that matches the fishing pole texture, then we have a fishing pole + if ( itemTexture and string.find(itemTexture, "INV_Fishingpole") ) then + local link = GetInventoryItemLink("player", slot); + local _, id, _ = FishingBuddy.SplitLink(link); + -- Make sure it's not "Nat Pagle's Fish Terminator" + return (id ~= 19944); + end + return false; +end +FishingBuddy.IsFishingPole = IsFishingPole; + +-- override the error message method (need an object as the first arg) +local function UIError_AddMessage( o, msg, a, r, g, b, hold ) + -- If we should be hiding the can't use item error, then do so + if ( TestingLures and msg == ERR_CANT_USE_ITEM ) then + -- We have the can't use item error, so abort + return; + end + --Call the original + local obj = SavedAddMessage.obj; + local method = SavedAddMessage.method; + return method( obj, msg, a, r, g, b, hold ); +end +FishingBuddy.AddMessage = UIError_AddMessage; + +local function HijackCheck() + return ( GetSetting("EasyCast") == 1 and + CastingKeys() and IsFishingPole() ); +end + +local SavedWFOnMouseUp; +local SavedWFOnMouseDown; +-- handle mouse up and mouse down in the WorldFrame so that we can steal +-- the hardware events to implement 'Easy Cast' +-- Thanks to the Cosmos team for figuring this one out -- I didn't realize +-- that the mouse handler in the WorldFrame got everything first! +local function WF_OnMouseDown() + -- Only steal 'right clicks' + if ( arg1 == "RightButton" and HijackCheck() ) then + FishingBuddy.ActionStartCheck(); + end + if ( SavedWFOnMouseDown ) then + SavedWFOnMouseDown(); + end +end + +-- disable click to move if we're fishing +local resetClickToMove = false; +local function WF_OnMouseUp() + local retval; + if ( SavedWFOnMouseUp ) then + retval = SavedWFOnMouseUp(); + end + -- Only steal 'right clicks' + if ( arg1 == "RightButton" ) then + -- we fail if there are multiple modifier keys + if ( IsAltKeyDown() and ( IsShiftKeyDown() or IsControlKeyDown() ) ) then + return retval; + end + if ( IsShiftKeyDown() and IsControlKeyDown() ) then + return retval; + end + if ( HijackCheck() ) then + FishingBuddy.StopCastingCheck(); + elseif ( resetClickToMove ) then + -- Re-enable Click-to-Move if we changed it + SetCVar("autointeract", "1"); + resetClickToMove = nil; + end + end + return retval; +end + +-- Find things in our inventory +local function FindItem(id) + if ( id ) then + local numSlots = 0; + -- check each of the bags on the player + for bag=0, NUM_BAG_FRAMES do + -- get the number of slots in the bag (0 if no bag) + numSlots = GetContainerNumSlots(bag); + if (numSlots > 0) then + -- check each slot in the bag + for slot=1, numSlots do + local link = GetContainerItemLink (bag,slot); + if (link) then + local c, i, n = FishingBuddy.SplitLink(link); + local check = string.gsub(i, "^(%d+):(%d+):(%d+):(%d+)$", "%1:%2:0:0"); + if ( check == id ) then + return bag, slot; + end + end + end + end + end + end + return nil, nil; +end + +local function SafeHookMethod(object, method, newmethod) + local oldValue = object[method]; + if ( oldValue ~= getglobal(newmethod) ) then + object[method] = newmethod; + return true; + end + return false; +end + +local function SafeHookScript(frame, handlername, newscript) + local oldValue = frame:GetScript(handlername); + frame:SetScript(handlername, newscript); + return oldValue; +end + +-- Something else that should be in a library +FishingBuddy.SplitLink = function(link) + if ( link ) then + local _,_, color, item, name = string.find(link, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r"); + return color, item, name; + end +end + +FishingBuddy.SplitFishLink = function(link) + if ( link ) then + local _,_, color, id, name = string.find(link, "|c(%x+)|Hitem:(%d+):%d+:%d+:%d+|h%[(.-)%]|h|r"); + return color, tonumber(id), name; + end +end + +-- handle the vagaries of zones and subzones +FishingBuddy.GetZoneInfo = function() + local zone = GetRealZoneText(); + local subzone = GetSubZoneText(); + if ( not zone or zone == "" ) then + zone = FishingBuddy.UNKNOWN; + end + if ( not subzone or subzone == "" ) then + subzone = zone; + end + return zone, subzone; +end + +FishingBuddy.AddFishie = function(color, id, name, zone, subzone, texture, quantity, quality) + if ( not FishingBuddy_Info["Fishies"][id] ) then + FishingBuddy_Info["Fishies"][id] = { }; + FishingBuddy_Info["Fishies"][id].name = name; + FishingBuddy_Info["Fishies"][id].texture = texture; + FishingBuddy_Info["Fishies"][id].quality = quality; + if ( color ~= "ffffffff" ) then + FishingBuddy_Info["Fishies"][id].color = color; + end + if ( FishingBuddy.SortedFishies ) then + tinsert(FishingBuddy.SortedFishies, { text = name, id = id }); + FishingBuddy.FishSort(FishingBuddy.SortedFishies, true); + end + end + + if ( not zone ) then + zone = FishingBuddy.UNKNOWN; + end + if ( not subzone ) then + subzone = zone; + end + + if ( not FishingBuddy.currentFishies[subzone] ) then + FishingBuddy.currentFishies[subzone] = {}; + end + if ( not FishingBuddy.currentFishies[subzone][id] ) then + FishingBuddy.currentFishies[subzone][id] = quantity; + else + FishingBuddy.currentFishies[subzone][id] = FishingBuddy.currentFishies[subzone][id] + quantity; + end + + if( not FishingBuddy_Info["FishingHoles"][zone] ) then + FishingBuddy_Info["FishingHoles"][zone] = { }; + tinsert(FishingBuddy.SortedZones, zone); + table.sort(FishingBuddy.SortedZones); + end + if( not FishingBuddy_Info["FishingHoles"][zone][subzone] ) then + FishingBuddy_Info["FishingHoles"][zone][subzone] = { }; + FishingBuddy.SortedByZone[zone] = {}; + tinsert(FishingBuddy.SortedByZone[zone], subzone); + table.sort(FishingBuddy.SortedByZone[zone]); + tinsert(FishingBuddy.SortedSubZones, subzone); + table.sort(FishingBuddy.SortedSubZones); + end + local fh = FishingBuddy_Info["FishingHoles"][zone]; + if ( not fh[subzone][id] ) then + fh[subzone][id] = quantity; + if ( GetSetting("ShowNewFishies") == 1 ) then + FishingBuddy.Print(FishingBuddy.ADDFISHIEMSG, name, subzone); + end + else + fh[subzone][id] = fh[subzone][id] + quantity; + end + + if ( FishingBuddy.ByFishie ) then + if ( not FishingBuddy.ByFishie[id] ) then + FishingBuddy.ByFishie[id] = {}; + end + if ( not FishingBuddy.ByFishie[id][subzone] ) then + FishingBuddy.ByFishie[id][subzone] = quantity; + else + FishingBuddy.ByFishie[id][subzone] = FishingBuddy.ByFishie[id][subzone] + quantity; + end + end + FishingBuddy.Locations.DataChanged(zone, subzone, fishie); + FishingBuddy.WatchUpdate(); +end + +FishingBuddy.GetFishie = function(fishid) + if( FishingBuddy_Info["Fishies"][fishid] ) then + return string.format("%d:0:0:0", fishid), + FishingBuddy_Info["Fishies"][fishid].texture, + FishingBuddy_Info["Fishies"][fishid].color, + FishingBuddy_Info["Fishies"][fishid].quantity, + FishingBuddy_Info["Fishies"][fishid].quality, + FishingBuddy_Info["Fishies"][fishid].name; + end +end + +local function ImportFish() + local oldShowNewFishies = GetSetting("ShowNewFishies"); + SetSetting("ShowNewFishies"); + if ( FishInfo2DataSub and FishingBuddy_Info["FishInfo2"] == 0 ) then + for toon in FishInfo2DataSub do + if ( not string.find(toon, "|User$") ) then + for fishie in FishInfo2DataSub[toon] do + local texture = FishInfo2DataSub[toon][fishie]["texture"]; + local quality = FishInfo2DataSub[toon][fishie]["rarity"]; + local fz = FishInfo2DataSub[toon][fishie]["zones"]; + local link = FishInfo2DataSub[toon][fishie]["link"]; + if ( link ) then + local _,_,id = string.find(link, "^(%d+):"); + for zone in fz do + for subzone in fz[zone] do + local quantity = fz[zone][subzone]; + FishingBuddy.AddFishie("ffffffff", id, fishie, zone, subzone, texture, quantity, quality) + end + end + end + end + end + end + FishingBuddy_Info["FishInfo2"] = 1; + FishingBuddy.Print(FishingBuddy.IMPORTMSG, "FishInfo2"); +-- elseif ( imppfishinfoDB and FishingBuddy_Info["ImppDBLoaded"] == 0 ) then +-- for subzone in imppfishinfoDB do +-- for item in imppfishinfoDB[subzone]["itemnames"] do +-- local quantity = imppfishinfoDB[subzone]["itemnames"][item].number; +-- local texture = imppfishinfoDB[subzone]["itemnames"][item].texture; +-- local quality = imppfishinfoDB[subzone]["itemnames"][item].quality; +-- FishingBuddy.AddFishie(color, id, name, subzone, texture, item, quantity, quality) +-- end +-- end +-- FishingBuddy_Info["ImppDBLoaded"] = 1; +-- FishingBuddy.Print(FishingBuddy.IMPORTMSG, "Impp's fishinfo"); +-- elseif ( DataFishDB and FishingBuddy_Info["DataFish"] == 0 ) then +-- for fishie in DataFishDB["catches"] do +-- for zone in DataFishDB["catches"][fishie]["locnames"] do +-- for subzone in DataFishDB["catches"][fishie]["locnames"][zone] do +-- local dfl = DataFishDB["locations"][subzone]["itemnames"][fishie]; +-- local quantity = dfl["number"]; +-- local texture = dfl["texture"]; +-- local quality = dfl["quality"]; +-- FishingBuddy.AddFishie(color, id, name, zone, subzone, texture, quantity, quality) +-- end +-- end +-- end +-- FishingBuddy_Info["DataFish"] = 1; +-- FishingBuddy.Print(FishingBuddy.IMPORTMSG, "DataFish"); + else + FishingBuddy.Message(FishingBuddy.NOIMPORTMSG); + end + SetSetting("ShowNewFishies", oldShowNewFishies); +end + +local function FindSpellID(thisone) + local id = 1; + local spellTexture = GetSpellTexture(id, BOOKTYPE_SPELL); + while (spellTexture) do + if (spellTexture and spellTexture == thisone) then + return id; + end + id = id + 1; + spellTexture = GetSpellTexture(id, BOOKTYPE_SPELL); + end + return nil; +end + +local function GetFishingSpellID() + if ( not FishingSpellID or not FishingSkillName) then + FishingSpellID = FindSpellID(FishingBuddy.FISHINGTEXTURE); + end + if ( FishingSpellID and not FishingSkillName ) then + FishingSkillName = GetSpellName(FishingSpellID, BOOKTYPE_SPELL); + end +end + +FishingBuddy.GetFishingSkillName = function() + GetFishingSpellID(); + if ( not FishingSkillName ) then + return FishingBuddy.FISHINGSKILL; + else + return FishingSkillName; + end + +end + +local function InvokeFishing() + GetFishingSpellID(); + if ( FishingSpellID ) then + CastSpell(FishingSpellID, BOOKTYPE_SPELL); + end +end + +-- do everything we think is necessary when we start fishing +-- even if we didn't do the switch to a fishing pole +local function StartFishingMode() + if ( not StartedFishing ) then + StartedFishing = GetTime(); + FishingBuddy.EnhanceFishingSounds(true); + FishingBuddy.WatchUpdate(); + end +end +FishingBuddy.StartFishingMode = StartFishingMode; + +local function StopFishingMode() + if ( StartedFishing ) then + FishingBuddy.EnhanceFishingSounds(false); + FishingBuddy.WatchUpdate(); + StartedFishing = nil; + end + if ( resetClickToMove ) then + -- Re-enable Click-to-Move if we changed it + SetCVar("autointeract", "1"); + resetClickToMove = nil; + end +end +FishingBuddy.StopFishingMode = StopFishingMode; + +local function FishingMode() + if ( IsFishingPole() ) then + StartFishingMode(); + else + StopFishingMode(); + end +end +FishingBuddy.FishingMode = FishingMode; + +local function OnFishingBobber() + if ( GameTooltip:IsVisible() ) then + local text = getglobal("GameTooltipTextLeft1"); + if ( text ) then + text = text:GetText(); + -- let a partial match work (for translations) + return ( text and string.find(text, FishingBuddy.BOBBER_NAME ) ); + end + end + return false; +end + +-- Easy lures (borrowed from Mugendai's excellent code) +local function UpdateLure() + -- if the pole has an enchantment, we can assume it's got a lure on it (so far, anyway) + if ( ( GetSetting("EasyLures") == 1 ) and not GetWeaponEnchantInfo() ) then + -- trap message handler if we haven't already + if ( not SavedAddMessage ) then + FishingBuddy.TrapUIErrors(); + end + + --Check for a lure in the bags, starting with the highest power one + local bag, slot; + for lure in FISHINGLURES do + --If we find this lure in the bag, then use it + bag, slot = FindItem(lure); + if (bag and slot) then + --We need to temporarily disable the cant use item error, incase this item is too high of a level to use + TestingLures = true; + --Temporarily disable error message sounds, incase this item is too high of a level to use + local soundState = GetCVar("EnableErrorSpeech"); + if ( soundState == "1" ) then + SetCVar("EnableErrorSpeech", 0); + end + --Try to use the item + UseContainerItem(bag, slot); + -- re-enable the can't use item error message + TestingLures = false; + -- re-enable error message sounds + if ( soundState == "1" ) then + SetCVar("EnableErrorSpeech", 1); + end + -- if we have a targeting cursor, then we succesfully used the lure + if ( SpellIsTargeting() ) then + -- apply the lure to the fishing pole + local mainhandslot = GetInventorySlotInfo("MainHandSlot"); + PickupInventoryItem(mainhandslot); + AddingLure = true; + return true; + end + end + end + end + return false; +end + +FishingBuddy.ActionStartCheck = function() + -- Disable Click-to-Move if we're fishing + if ( GetCVar("autointeract") == "1" ) then + resetClickToMove = true; + SetCVar("autointeract", "0"); + end + -- Don't interrupt putting on a lure, or if we're not fastcasting + if ( AddingLure ) then + ActionStartTime = 0; + else + ActionStartTime = GetTime(); + end +end + +-- add the double click checking in based on the code is Cosmos +FishingBuddy.StopCastingCheck = function() + if ( not ActionStartTime ) then + ActionStartTime = 0; + end + if ( not ActionDoubleTime ) then + ActionDoubleTime = 0; + end + local time = GetTime(); + local pressTime = time - ActionStartTime; + local doubleTime = time - ActionDoubleTime; + -- if we're not putting on a lure and the casting modifiers are good + if ( not SpellIsTargeting() ) then + -- if the click was "short" enough that we're going to treat it + -- as a cast + if ( ActionStartTime > 0 and ACTIONDOWNWAIT >= pressTime) then + -- if we're already casting, enforce double click timing + if ( GetSetting("FastCast") ~= 1 and CastingNow and + ( ActionDoubleTime == 0 or ACTIONDOUBLEWAIT < doubleTime ) ) then + ActionDoubleTime = GetTime(); + else + ActionDoubleTime = 0; + -- rebind the mouse event + UpdateBindings(true); + end + end + end +end + +FishingBuddy.PerformCast = function() + -- We're stealing the mouse-up hardware event, make sure we exit MouseLook + if ( IsMouselooking() ) then + MouselookStop(); + end + -- reset the TURNORACTION binding so that everything else works 'right' + UpdateBindings(false); + -- put on a lure if we need to + if ( not UpdateLure() ) then + InvokeFishing(); + end +end + +FishingBuddy.TrapUIErrors = function() + local temp = {}; + temp.obj= UIErrorsFrame; + temp.method = UIErrorsFrame["AddMessage"]; + if ( SafeHookMethod(UIErrorsFrame, "AddMessage", FishingBuddy.AddMessage) ) then + SavedAddMessage = temp; + end +end + +FishingBuddy.TrapWorldMouse = function() + SavedWFOnMouseUp = SafeHookScript(WorldFrame, "OnMouseUp", WF_OnMouseUp); + SavedWFOnMouseDown = SafeHookScript(WorldFrame, "OnMouseDown", WF_OnMouseDown); +end + +-- User interface handling + +FishingBuddy.Commands = {}; +FishingBuddy.Commands[FishingBuddy.SWITCH] = {}; +FishingBuddy.Commands[FishingBuddy.SWITCH].func = function() + FishingBuddy.OutfitManager.Switch(); + return true; + end; +FishingBuddy.Commands[FishingBuddy.CURRENT] = {}; +FishingBuddy.Commands[FishingBuddy.CURRENT].help = FishingBuddy.CURRENT_HELP; +FishingBuddy.Commands[FishingBuddy.CURRENT].func = + function(what) + if ( what and what == FishingBuddy.RESET) then + FishingBuddy.currentFishies = {}; + FishingMode(); + return true; + end + end; +FishingBuddy.Commands[FishingBuddy.IMPORT] = {}; +FishingBuddy.Commands[FishingBuddy.IMPORT].help = FishingBuddy.IMPORT_HELP; +FishingBuddy.Commands[FishingBuddy.IMPORT].func = + function() + ImportFish(); + return true; + end; +FishingBuddy.Commands[FishingBuddy.CLEANUP] = {}; +FishingBuddy.Commands[FishingBuddy.CLEANUP].help = FishingBuddy.CLEANUP_HELP; +FishingBuddy.Commands[FishingBuddy.CLEANUP].func = + function(what) + local tabs = { "Settings", "Outfit", "WasWearing" }; + local rnames = {}; + local onames = {}; + if ( not what or what == FishingBuddy.CHECK ) then + if ( FishingBuddy_Info["Settings"] ) then + for name in FishingBuddy_Info["Settings"] do + tinsert(onames, name); + end + end + if ( FishingBuddy_Info[realmName] ) then + local fs = FishingBuddy_Info[realmName]["Settings"]; + if ( fs ) then + for name,info in fs do + tinsert(rnames, name); + end + end + end + if ( next(rnames) or next(onames) ) then + if ( next(rnames) ) then + FishingBuddy.Print(FishingBuddy.CLEANUP_WILLMSG, realmName, + FishingBuddy.EnglishList(rnames)); + end + if ( next(onames) ) then + FishingBuddy.Print(FishingBuddy.CLEANUP_WILLMSG, + FishingBuddy.NOREALM, + FishingBuddy.EnglishList(onames)); + end + else + FishingBuddy.Message(FishingBuddy.CLEANUP_NONEMSG); + end + return true; + else + if ( what == FishingBuddy.NOW ) then + if ( FishingBuddy_Info["Settings"] ) then + for name in FishingBuddy_Info["Settings"] do + tinsert(onames, name); + end + end + if ( FishingBuddy_Info[realmName] ) then + local fs = FishingBuddy_Info[realmName]["Settings"]; + if ( fs ) then + for name,info in fs do + tinsert(rnames, name); + end + end + end + else + if ( FishingBuddy_Info["Settings"] and FishingBuddy_Info["Settings"][what] ) then + tinsert(onames, what); + elseif ( FishingBuddy_Info[realmName] and + FishingBuddy_Info[realmName]["Settings"] and + FishingBuddy_Info[realmName]["Settings"][what] ) then + tinsert(rnames, what); + else + FishingBuddy.Print(FishingBuddy.CLEANUP_NOOLDMSG, what); + return true; + end + end + if ( next(rnames) or next(onames) ) then + if ( next(rnames) ) then + for _,name in rnames do + for _,tab in tabs do + if ( FishingBuddy_Info[realmName] and FishingBuddy_Info[realmName][tab] ) then + FishingBuddy_Info[realmName][tab][name] = nil; + if ( next(FishingBuddy_Info[realmName][tab]) == nil ) then + FishingBuddy_Info[realmName][tab] = nil; + end + end + end + end + if ( FishingBuddy_Info[realmName] and next(FishingBuddy_Info[realmName]) == nil ) then + FishingBuddy_Info[realmName] = nil; + end + FishingBuddy.Print(FishingBuddy.CLEANUP_DONEMSG, realmName, + FishingBuddy.EnglishList(rnames)); + end + if ( next(onames) ) then + for _,name in onames do + for _,tab in tabs do + if ( FishingBuddy_Info[tab] ) then + FishingBuddy_Info[tab][name] = nil; + if ( next(FishingBuddy_Info[tab]) ) then + FishingBuddy_Info[tab] = nil; + end + end + end + end + FishingBuddy.Print(FishingBuddy.CLEANUP_DONEMSG, + FishingBuddy.NOREALM, + FishingBuddy.EnglishList(onames)); + end + else + FishingBuddy.Message(FishingBuddy.CLEANUP_NONEMSG); + end + return true; + end + end; + +local function nextarg(msg, pattern) + if ( not msg or not pattern ) then + return nil, nil; + end + local s,e = string.find(msg, pattern); + if ( s ) then + local word = strsub(msg, s, e); + msg = strsub(msg, e+1); + return word, msg; + end + return nil, msg; +end + +FishingBuddy.Command = function(msg) + if ( not msg ) then + return; + end + if ( FishingBuddy.IsLoaded() ) then + -- collect arguments (whee, lua string manipulation) + local cmd; + cmd, msg = nextarg(msg, "[%w]+"); + + -- the empty string gives us no args at all + if ( not cmd ) then + -- toggle window + if ( FishingBuddyFrame:IsVisible() ) then + HideUIPanel(FishingBuddyFrame); + else + ShowUIPanel(FishingBuddyFrame); + end + elseif ( cmd == FishingBuddy.HELP or cmd == "help" ) then + FishingBuddy.Output(FishingBuddy.WINDOW_TITLE); + FishingBuddy.PrintHelp(FishingBuddy.HELPMSG); + else + local command = FishingBuddy.Commands[cmd]; + if ( command ) then + local args = {}; + local goodargs = true; + if ( command.args ) then + for _,pat in command.args do + local w, msg = nextarg(msg, pat); + if ( not w ) then + goodargs = false; + break; + end + tinsert(args, w); + end + else + local a; + while ( msg ) do + a, msg = nextarg(msg, "[%w]+"); + if ( not a ) then + break; + end + tinsert(args, a); + end + end + if ( not goodargs or not command.func(unpack(args)) ) then + if ( command.help ) then + FishingBuddy.PrintHelp(command.help); + else + FishingBuddy.Debug("command failed"); + end + end + else + FishingBuddy.Command("help"); + end + end + else + FishingBuddy.Error(FishingBuddy.FAILEDINIT); + end +end + +FishingBuddy.OnLoad = function() + this:RegisterEvent("PLAYER_LOGIN"); + this:RegisterEvent("PLAYER_LOGOUT"); + this:RegisterEvent("VARIABLES_LOADED"); + + this:RegisterEvent("ITEM_LOCK_CHANGED"); + this:RegisterEvent("LOOT_OPENED"); + this:RegisterEvent("ZONE_CHANGED"); + this:RegisterEvent("MINIMAP_ZONE_CHANGED"); + + this:RegisterEvent("SPELLS_CHANGED"); + this:RegisterEvent("SPELLCAST_CHANNEL_START"); + this:RegisterEvent("SPELLCAST_CHANNEL_STOP"); + this:RegisterEvent("SPELLCAST_START"); + this:RegisterEvent("SPELLCAST_STOP"); + this:RegisterEvent("SPELLCAST_INTERRUPTED"); + this:RegisterEvent("SPELLCAST_FAILED"); + + this:RegisterEvent("SKILL_LINES_CHANGED"); + + -- Set up command + SlashCmdList["fishingbuddy"] = FishingBuddy.Command; + SLASH_fishingbuddy1 = "/fishingbuddy"; + SLASH_fishingbuddy2 = "/fb"; + + FishingBuddy.Output(FishingBuddy.WINDOW_TITLE.." loaded"); +end + +FishingBuddy.OnEvent = function() + local needUpdate = false; + if ( event == "VARIABLES_LOADED" ) then + FishingBuddy.Initialize(); + elseif ( event == "PLAYER_LOGIN" ) then + -- set up outfit stuff + FishingBuddy.OutfitManager.Initialize(); + FishingMode(); + elseif ( event == "PLAYER_LOGOUT" ) then + -- reset the fishing sounds, if we need to + StopFishingMode(); + FishingBuddy.SavePlayerInfo(); + elseif ( event == "ITEM_LOCK_CHANGED" ) then + FishingMode(); + elseif ( event == "LOOT_OPENED" ) then + if ( IsFishingLoot()) then + local zone, subzone = FishingBuddy.GetZoneInfo(); + for index = 1, GetNumLootItems(), 1 do + if (LootSlotIsItem(index)) then + local texture, fishie, quantity, quality = GetLootSlotInfo(index); + local link = GetLootSlotLink(index); + local color, id, name = FishingBuddy.SplitFishLink(link); + FishingBuddy.AddFishie(color, id, name, zone, subzone, texture, quantity, quality); + if ( FishingBuddy.AddTracking ) then + FishingBuddy.AddTracking(id, name); + end + FishingBuddy.SetZoneLevel(zone, subzone, id); + end + end + end + elseif ( event == "ZONE_CHANGED" or event == "MINIMAP_ZONE_CHANGED" ) then + if ( not FishingBuddy.IsLoaded() ) then + return; + end + FishingBuddy.currentFishies = {}; + needUpdate = true; + elseif ( event == "SKILL_LINES_CHANGED" ) then + if ( GetSetting("WatchCurrentSkill") == 1 ) then + needUpdate = true; + end + elseif ( event == "SPELLS_CHANGED" ) then + -- Fishing might have moved, go look again + FishingSpellID = nil; + else + -- Mugendai is one sharp cookie (shamelessly stealing from TackleBox again) + -- Keep up with whether or not we are casting + if ( event == "SPELLCAST_CHANNEL_START" ) then + CastingNow = true; + elseif ( event == "SPELLCAST_CHANNEL_STOP" ) then + CastingNow = false; + else + -- Keep up with whether we are adding a lure (or casting a normal spell) or not + if ( event == "SPELLCAST_START" ) then + -- AddingLure = true; + elseif ( event == "SPELLCAST_STOP" ) then + if ( AddingLure ) then + AddingLure = false; + -- update the skill line if we have one + if ( GetSetting("WatchCurrentSkill") == 1 ) then + needUpdate = true; + end + end + elseif ( ( event == "SPELLCAST_INTERRUPTED" ) or ( event == "SPELLCAST_FAILED" ) ) then + AddingLure = false; + end + end + end + FishingBuddy.Extravaganza.IsTime(true); + if ( needUpdate ) then + FishingBuddy.WatchUpdate(); + end +end + +FishingBuddy.PrintHelp = function(tab) + if ( type(tab) == "table" ) then + for _,line in tab do + FishingBuddy.PrintHelp(line); + end + else + FishingBuddy.Output(tab); + end +end + +FishingBuddy["EFSV"] = {}; +FishingBuddy["EFSV"]["MusicVolume"] = tonumber(GetCVar("MusicVolume")); +FishingBuddy["EFSV"]["AmbienceVolume"] = tonumber(GetCVar("AmbienceVolume")); +FishingBuddy["EFSV"]["SoundVolume"] =tonumber(GetCVar("SoundVolume")); +local SoundWasEnhanced; +FishingBuddy.EnhanceFishingSounds = function(turniton) + if ( GetSetting("EnhanceFishingSounds") == 1 ) then + if ( turniton ) then + -- collect the current value + FishingBuddy["EFSV"]["MusicVolume"] = tonumber(GetCVar("MusicVolume")); + FishingBuddy["EFSV"]["AmbienceVolume"] = tonumber(GetCVar("AmbienceVolume")); + FishingBuddy["EFSV"]["SoundVolume"] =tonumber(GetCVar("SoundVolume")); + -- turn 'em off! + for setting in FishingBuddy["EFSV"] do + SetCVar(setting, + GetSetting("EnhanceSound"..setting)); + end + SoundWasEnhanced = true; + else + if ( SoundWasEnhanced ) then + for setting, value in FishingBuddy["EFSV"] do + SetCVar(setting, value); + end + SoundWasEnhanced = false; + end + end + end +end + +-- Drop-down menu support +FishingBuddy.ToggleSetting = function(setting) + local value = GetSetting(setting); + if ( not value ) then + value = 0; + end + SetSetting(setting, 1 - value); + FishingBuddy.WatchUpdate(); + FishingBuddy.UpdateMinimap(); +end + +-- save some memory by keeping one copy of each one +local ToggleFunctions = {}; +-- let's use closures +local function MakeToggle(name) + if ( not ToggleFunctions[name] ) then + local n = name; + ToggleFunctions[name] = function() FishingBuddy.ToggleSetting(n) end; + end + return ToggleFunctions[name]; +end + +FishingBuddy.MakeDropDown = function(switchItem, switchSetting) + local info; + -- If no outfit frame, we can't switch outfits... + if ( FishingBuddy.OutfitManager.HasManager() ) then + info = {}; + info.text = switchItem; + info.func = MakeToggle(switchSetting); + info.checked = (GetSetting(switchSetting) == 1); + info.keepShownOnClick = 1; + UIDropDownMenu_AddButton(info); + info = {}; + info.disabled = 1; + UIDropDownMenu_AddButton(info); + end + + for _, option in FishingBuddy.OPTIONS do + local addthis = true; + if ( option.check ) then + addthis = option.check(); + end + if ( addthis ) then + info = {}; + info.text = option.text; + info.func = MakeToggle(option.name); + info.checked = (GetSetting(option.name) == 1); + info.keepShownOnClick = 1; + UIDropDownMenu_AddButton(info); + end + end +end + +-- utility functions +FishingBuddy.AddTooltip = function(text, r, g, b) + if ( text ) then + if ( type(text) == "table" ) then + for _,l in text do + FishingBuddy.AddTooltip(l.text, l.r, l.g, l.b); + end + else + GameTooltip:AddLine(text, r, g, b); + end + end +end + +FishingBuddy.ChatLink = function(item, name, color) + if( item and name and ChatFrameEditBox:IsVisible() ) then + if not color then + color = FishingBuddy.Colors.WHITE; + end + local link = "|c"..color.."|Hitem:"..item.."|h["..name.."]|h|r"; + ChatFrameEditBox:Insert(link); + end +end + +FishingBuddy.FishSort = function(tab, forcename) + if ( forcename or GetSetting("SortByPercent") == 0 ) then + table.sort(tab, function(a,b) return a.text and b.text and a.text +