From de057d0b6ed86f8a8bcfb5588c793dadd35cc53d Mon Sep 17 00:00:00 2001 From: Lexie <6937574+Lexiebean@users.noreply.github.com> Date: Fri, 7 Apr 2023 12:07:19 +1000 Subject: [PATCH] Reupload + some bug fixes --- Bindings.xml | 47 ++ FishingBuddy.lua | 1687 +++++++++++++++++++++++++++++++++++++ FishingBuddy.toc | 34 + FishingBuddy.xml | 24 + FishingBuddyFrame.lua | 147 ++++ FishingBuddyFrame.xml | 316 +++++++ FishingBuddyInfoBar.lua | 48 ++ FishingBuddyInfoBar.xml | 43 + FishingBuddyMinimap.lua | 116 +++ FishingBuddyMinimap.xml | 86 ++ FishingBuddyTitan.lua | 58 ++ FishingBuddyTitan.xml | 27 + FishingDebugging.lua | 95 +++ FishingExtravaganza.lua | 511 +++++++++++ FishingExtravaganza.xml | 116 +++ FishingHoles.lua | 43 + FishingInit.lua | 733 ++++++++++++++++ FishingLocationsFrame.lua | 664 +++++++++++++++ FishingLocationsFrame.xml | 590 +++++++++++++ FishingOptionsFrame.lua | 214 +++++ FishingOptionsFrame.xml | 341 ++++++++ FishingOutfitFrame.lua | 259 ++++++ FishingOutfitFrame.xml | 120 +++ FishingOutfitManager.lua | 184 ++++ FishingOutfitManager.xml | 11 + FishingOutfitter.lua | 140 +++ FishingSchools.lua | 165 ++++ FishingSetup.lua | 127 +++ FishingTrackingFrame.lua | 387 +++++++++ FishingTrackingFrame.xml | 156 ++++ FishingWatcher.lua | 373 ++++++++ FishingWatcher.xml | 258 ++++++ GraphHandler.lua | 251 ++++++ GraphHandler.xml | 211 +++++ Icons/Fishing-Icon.tga | Bin 0 -> 12332 bytes Icons/MiniMapArrow.blp | Bin 0 -> 2553 bytes Icons/MiniMapArrow0.tga | Bin 0 -> 750 bytes Icons/MiniMapArrow10.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow100.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow110.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow120.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow130.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow140.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow150.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow160.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow170.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow180.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow190.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow20.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow200.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow210.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow220.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow230.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow240.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow250.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow260.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow270.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow280.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow290.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow30.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow300.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow310.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow320.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow330.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow340.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow350.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow40.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow50.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow60.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow70.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow80.tga | Bin 0 -> 1068 bytes Icons/MiniMapArrow90.tga | Bin 0 -> 1068 bytes README.md | 13 +- changes.txt | 263 ++++++ future.txt | 40 + localization.de.lua | 200 +++++ localization.es.lua | 142 ++++ localization.fr.lua | 150 ++++ localization.lua | 272 ++++++ localization.ru.lua | 258 ++++++ readme.txt | 64 ++ 81 files changed, 9972 insertions(+), 12 deletions(-) create mode 100644 Bindings.xml create mode 100644 FishingBuddy.lua create mode 100644 FishingBuddy.toc create mode 100644 FishingBuddy.xml create mode 100644 FishingBuddyFrame.lua create mode 100644 FishingBuddyFrame.xml create mode 100644 FishingBuddyInfoBar.lua create mode 100644 FishingBuddyInfoBar.xml create mode 100644 FishingBuddyMinimap.lua create mode 100644 FishingBuddyMinimap.xml create mode 100644 FishingBuddyTitan.lua create mode 100644 FishingBuddyTitan.xml create mode 100644 FishingDebugging.lua create mode 100644 FishingExtravaganza.lua create mode 100644 FishingExtravaganza.xml create mode 100644 FishingHoles.lua create mode 100644 FishingInit.lua create mode 100644 FishingLocationsFrame.lua create mode 100644 FishingLocationsFrame.xml create mode 100644 FishingOptionsFrame.lua create mode 100644 FishingOptionsFrame.xml create mode 100644 FishingOutfitFrame.lua create mode 100644 FishingOutfitFrame.xml create mode 100644 FishingOutfitManager.lua create mode 100644 FishingOutfitManager.xml create mode 100644 FishingOutfitter.lua create mode 100644 FishingSchools.lua create mode 100644 FishingSetup.lua create mode 100644 FishingTrackingFrame.lua create mode 100644 FishingTrackingFrame.xml create mode 100644 FishingWatcher.lua create mode 100644 FishingWatcher.xml create mode 100644 GraphHandler.lua create mode 100644 GraphHandler.xml create mode 100644 Icons/Fishing-Icon.tga create mode 100644 Icons/MiniMapArrow.blp create mode 100644 Icons/MiniMapArrow0.tga create mode 100644 Icons/MiniMapArrow10.tga create mode 100644 Icons/MiniMapArrow100.tga create mode 100644 Icons/MiniMapArrow110.tga create mode 100644 Icons/MiniMapArrow120.tga create mode 100644 Icons/MiniMapArrow130.tga create mode 100644 Icons/MiniMapArrow140.tga create mode 100644 Icons/MiniMapArrow150.tga create mode 100644 Icons/MiniMapArrow160.tga create mode 100644 Icons/MiniMapArrow170.tga create mode 100644 Icons/MiniMapArrow180.tga create mode 100644 Icons/MiniMapArrow190.tga create mode 100644 Icons/MiniMapArrow20.tga create mode 100644 Icons/MiniMapArrow200.tga create mode 100644 Icons/MiniMapArrow210.tga create mode 100644 Icons/MiniMapArrow220.tga create mode 100644 Icons/MiniMapArrow230.tga create mode 100644 Icons/MiniMapArrow240.tga create mode 100644 Icons/MiniMapArrow250.tga create mode 100644 Icons/MiniMapArrow260.tga create mode 100644 Icons/MiniMapArrow270.tga create mode 100644 Icons/MiniMapArrow280.tga create mode 100644 Icons/MiniMapArrow290.tga create mode 100644 Icons/MiniMapArrow30.tga create mode 100644 Icons/MiniMapArrow300.tga create mode 100644 Icons/MiniMapArrow310.tga create mode 100644 Icons/MiniMapArrow320.tga create mode 100644 Icons/MiniMapArrow330.tga create mode 100644 Icons/MiniMapArrow340.tga create mode 100644 Icons/MiniMapArrow350.tga create mode 100644 Icons/MiniMapArrow40.tga create mode 100644 Icons/MiniMapArrow50.tga create mode 100644 Icons/MiniMapArrow60.tga create mode 100644 Icons/MiniMapArrow70.tga create mode 100644 Icons/MiniMapArrow80.tga create mode 100644 Icons/MiniMapArrow90.tga create mode 100644 changes.txt create mode 100644 future.txt create mode 100644 localization.de.lua create mode 100644 localization.es.lua create mode 100644 localization.fr.lua create mode 100644 localization.lua create mode 100644 localization.ru.lua create mode 100644 readme.txt diff --git a/Bindings.xml b/Bindings.xml new file mode 100644 index 0000000..8bff328 --- /dev/null +++ b/Bindings.xml @@ -0,0 +1,47 @@ + + + + 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 + + + if ( keystate == "down" ) then + FishingBuddy.SuitUpAndGoFishing(); + end + + + + \ No newline at end of file diff --git a/FishingBuddy.lua b/FishingBuddy.lua new file mode 100644 index 0000000..d499f4d --- /dev/null +++ b/FishingBuddy.lua @@ -0,0 +1,1687 @@ +-- 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] = "Aquadynamic Fish Attractor", -- 100 for 5 mins + [7307] = "Flesh Eating Worm", -- 75 for 10 mins + [6532] = "Bright Baubles", -- 75 for 10 mins + [6811] = "Aquadynamic Fish Lens", -- 50 for 10 mins + [6530] = "Nightcrawlers", -- 50 for 10 mins + [6529] = "Shiny Bauble", -- 25 for 10 mins +} + +FishingBuddy.OPTIONS = { + ["ShowNewFishies"] = { + ["text"] = FishingBuddy.CONFIG_SHOWNEWFISHIES_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_SHOWNEWFISHIES_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1 }, + ["WatchFishies"] = { + ["text"] = FishingBuddy.CONFIG_FISHWATCH_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCH_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1 }, + ["WatchCurrentSkill"] = { + ["text"] = FishingBuddy.CONFIG_FISHWATCHSKILL_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHSKILL_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1, + ["deps"] = { ["WatchFishies"] = "d" } }, + ["WatchCurrentZone"] = { + ["text"] = FishingBuddy.CONFIG_FISHWATCHZONE_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHZONE_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 0, + ["deps"] = { ["WatchFishies"] = "d" } }, + ["WatchOnlyWhenFishing"] = { + ["text"] = FishingBuddy.CONFIG_FISHWATCHONLY_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHONLY_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1, + ["deps"] = { ["WatchFishies"] = "d" } }, + ["WatchFishPercent"] = { + ["text"] = FishingBuddy.CONFIG_FISHWATCHPERCENT_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_FISHWATCHPERCENT_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1, + ["deps"] = { ["WatchFishies"] = "d" } }, + ["SortByPercent"] = { + ["text"] = FishingBuddy.CONFIG_SORTBYPERCENT_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_SORTBYPERCENT_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1 }, + ["SuitUpFirst"] = { + ["text"] = FishingBuddy.CONFIG_SUITUPFIRST_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_SUITUPFIRST_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 0 }, + ["EasyCast"] = { + ["text"] = FishingBuddy.CONFIG_EASYCAST_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_EASYCAST_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 1 }, + ["EasyLures"] = { + ["text"] = FishingBuddy.CONFIG_EASYLURES_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_EASYLURES_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 0 }, + ["STVTimer"] = { + ["text"] = FishingBuddy.CONFIG_STVTIMER_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_STVTIMER_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 0 }, + ["STVPoolsOnly"] = { + ["text"] = FishingBuddy.CONFIG_STVPOOLSONLY_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_STVPOOLSONLY_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 0, + ["deps"] = { ["STVTimer"] = "d", ["EasyCast"] = "d" } }, + ["UseButtonHole"] = { + ["text"] = FishingBuddy.CONFIG_USEBUTTONHOLE_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_USEBUTTONHOLE_INFO, + ["v"] = 1, + ["default"] = 0, + ["check"] = function () return ButtonHole ~= nil; end, + ["checkfail"] = 0 }, + ["UseGatherer"] = { + ["text"] = FishingBuddy.CONFIG_USEGATHERER_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_USEGATHERER_INFO, + ["v"] = 1, + ["default"] = 0, + ["check"] = function () return Gatherer_OnLoad ~= nil; end, + ["checkfail"] = 0 }, + ["MinimapButtonVisible"] = { + ["tooltip"] = FishingBuddy.CONFIG_MINIMAPBUTTON_INFO, + ["v"] = 1, + ["default"] = 1, + ["check"] = function () return not FishingBuddy.UseButtonHole(); end, + ["checkfail"] = 0, + ["update"] = function(checked) + local b = FishingBuddyOption_MinimapButtonVisible; + if ( b:GetChecked() ) then + b.text = ""; + else + b.text = FishingBuddy.CONFIG_MINIMAPBUTTON_ONOFF; + end + FishingBuddyOption_MinimapButtonVisibleText:SetText(b.text); + end, + }, + ["EnhanceFishingSounds"] = { + ["text"] = FishingBuddy.CONFIG_ENHANCESOUNDS_ONOFF, + ["tooltip"] = FishingBuddy.CONFIG_ENHANCESOUNDS_INFO, + ["v"] = 1, + ["m"] = 1, + ["default"] = 0 }, + -- options not in a menu + ["ShowLocationZones"] = { + ["default"] = 1, + }, + ["GroupByLocation"] = { + ["default"] = 1, + }, + ["TitanClickToSwitch"] = { + ["default"] = 1, + }, + ["FubarClickToSwitch"] = { + ["default"] = 1, + }, + ["InfoBarClickToSwitch"] = { + ["default"] = 1, + }, + ["MinimapClickToSwitch"] = { + ["default"] = 0, + }, + ["EasyCastKeys"] = { + ["default"] = FishingBuddy.KEYS_NONE, + ["deps"] = { ["EasyCast"] = "h" }, + }, + ["SuitUpKeys"] = { + ["default"] = FishingBuddy.KEYS_NONE, + }, + ["EnhanceSoundSoundVolume"] = { + ["default"] = 1.0, + }, + ["EnhanceSoundMusicVolume"] = { + ["default"] = 0.0, + }, + ["EnhanceSoundAmbienceVolume"] = { + ["default"] = 0.0, + }, + ["MinimapButtonPosition"] = { + ["default"] = FishingBuddy.DEFAULT_MINIMAP_POSITION, + }, + ["MinimapPosSlider"] = { + ["deps"] = { ["MinimapButtonVisible"] = "h", }, + }, + ["ClockOffset"] = { + ["default"] = 0, + ["deps"] = { ["STVTimer"] = "h" }, + ["visible"] = function() + if ( FishingBuddy.ClockOffsets ) then + return 1; + else + return 0; + end; + end, + }, + ["OutfitManager"] = { + ["default"] = "OutfitDisplayFrame", + }, +} + +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; + +FishingBuddy.StartedFishing = nil; + +local TestingLures = false; +local CastingNow = false; +local AddingLure = false; +local IsLooting = false; + +local FishingSpellID = nil; +local FishingSkillName = nil; + +local gotSetupDone = false; +local playerName = nil; +local realmName = nil; +local schooltipText = nil; + +FishingBuddy.currentFishies = {}; + +local DEFAULT_MINIMAP_POSITION = 256; + +local function GetDefault(setting) + local opt = FishingBuddy.OPTIONS[setting]; + if ( opt ) then + if ( opt.check and opt.checkfail ) then + if ( not opt.check() ) then + return opt.checkfail; + end + end + return opt.default; + end +end +FishingBuddy.GetDefault = GetDefault; + +local function GetSetting(setting) + if ( not FishingBuddy_Player or + not FishingBuddy_Player["Settings"] ) then + return; + end + local val = FishingBuddy_Player["Settings"][setting]; + if ( val == nil ) then + val = GetDefault(setting); + end + return val; +end +FishingBuddy.GetSetting = GetSetting; + +local function SetSetting(setting, value) + if ( FishingBuddy_Player and setting ) then + local val = GetDefault(setting); + if ( val == value ) then + FishingBuddy_Player["Settings"][setting] = nil; + else + FishingBuddy_Player["Settings"][setting] = value; + end + end +end +FishingBuddy.SetSetting = SetSetting; + +local function SetClockOffset(offset) + if ( not FishingBuddy_Info["ClockOffsets"] ) then + FishingBuddy_Info["ClockOffsets"] = {}; + end + if ( offset == 0 ) then + FishingBuddy_Info["ClockOffsets"][realmName] = nil; + else + FishingBuddy_Info["ClockOffsets"][realmName] = offset; + end +end +FishingBuddy.SetClockOffset = SetClockOffset; + +local function GetClockOffset() + if ( not FishingBuddy_Info["ClockOffsets"] or + not FishingBuddy_Info["ClockOffsets"][realmName] ) then + return 0; + end + return FishingBuddy_Info["ClockOffsets"][realmName]; +end +FishingBuddy.GetClockOffset = GetClockOffset; + +-- We have to do this at PLAYER_ENTERING_WORLD or PLAYER_LOGIN +-- GetGameTime isn't correct at VARIABLES_LOADED +local function CheckClockOffset() + local hour,minute = GetGameTime(); + local lhour = date("%H"); + local lminute = date("%M"); + local houroff; + houroff = hour - lhour; + if ( houroff ~= 0 ) then + local houroff24; + if ( houroff < 0 ) then + houroff24 = 24 + houroff; + else + houroff24 = houroff - 24; + end + local offsets = { houroff, houroff24 }; + FishingBuddy.ClockOffsets = offsets; + local current = GetClockOffset(); + -- don't change it if we've already got a good value + if ( current ~= houroff and current ~= houroff24 ) then + SetClockOffset(houroff); + end + else + FishingBuddy.ClockOffsets = nil; + SetClockOffset(0); + end + -- Set up the menu and such + FishingBuddy.OptionsFrame.SetClockValues(GetClockOffset()); +end + +-- look at tooltips +local function GetTooltipText() + local text = ""; + if ( GameTooltip:IsVisible() ) then + text = getglobal("GameTooltipTextLeft1"); + if ( text ) then + return text:GetText(); + end + end + return nil; +end +FishingBuddy.GetTooltipText = GetTooltipText; + +local function OnFishingBobber() + local text = GetTooltipText(); + if ( text ) then + -- let a partial match work (for translations) + return ( text and string.find(text, FishingBuddy.BOBBER_NAME ) ); + end + return false; +end + +-- support finding the fishing skill +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 + +local function GetFishingSkillName() + GetFishingSpellID(); + if ( not FishingSkillName ) then + return FishingBuddy.FISHINGSKILL; + else + return FishingSkillName; + end +end +FishingBuddy.GetFishingSkillName = GetFishingSkillName; + +-- 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 ( setting and key_actions[setting] ) then + return key_actions[setting](); + else + return true; + end +end + +-- get our current fishing skill level +local lastSkillIndex = nil; +local function GetCurrentSkill() + if ( lastSkillIndex ) then + local name, _, _, rank, _, modifier = GetSkillLineInfo(lastSkillIndex); + if ( name == GetFishingSkillName() )then + return rank, modifier; + end + end + local n = GetNumSkillLines(); + for i=1,n do + local name, _, _, rank, _, modifier = GetSkillLineInfo(i); + if ( name == GetFishingSkillName() ) then + lastSkillIndex = i; + return rank, modifier; + end + end + return 0, 0; +end +FishingBuddy.GetCurrentSkill = GetCurrentSkill; + +-- handle dynamic event registration +local function EventRegistration(frame, events, reg) + for _,evt in events do + if ( reg ) then + frame:RegisterEvent(evt); + else + frame:UnregisterEvent(evt); + end + end +end + + +-- handle the vagaries of zones and subzones +local function GetZoneInfo() + 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.GetZoneInfo = GetZoneInfo; + +local zonemapping; +local subzonemapping; + +local function DumpMappings() + FishingBuddy.Debug("Zone mapping"); + FishingBuddy.Dump(zonemapping); + FishingBuddy.Debug("SubZone mapping"); + FishingBuddy.Dump(subzonemapping); +end +FishingBuddy.DumpMappings = DumpMappings; + +local function GetZoneIndex(zone, subzone) + if ( not zone ) then + zone, subzone = GetZoneInfo(); + end + if ( not zonemapping ) then + zonemapping = {}; + for idx,z in FishingBuddy_Info["ZoneIndex"] do + zonemapping[z] = idx; + end + end + local zidx = zonemapping[zone]; + if ( not subzonemapping ) then + subzonemapping = {}; + for idx,_ in FishingBuddy_Info["ZoneIndex"] do + subzonemapping[idx] = {}; + if ( FishingBuddy_Info["SubZones"][idx] ) then + for jdx,sz in FishingBuddy_Info["SubZones"][idx] do + subzonemapping[idx][sz] = jdx; + end + end + end + end + if ( not zidx ) then + return; + end + if ( not subzonemapping[zidx] ) then + subzonemapping[zidx] = {}; + end + if ( not subzone or not subzonemapping[zidx][subzone] ) then + return zidx; + end + return zidx, subzonemapping[zidx][subzone]; +end +FishingBuddy.GetZoneIndex = GetZoneIndex; + +local function AddZoneIndex(zone, subzone) + if ( not zone ) then + zone, subzone = GetZoneInfo(); + end + if ( type(zone) ~= "string" ) then + FishingBuddy.Debug("AddZoneIndex "..zone); + end + local zidx, sidx = GetZoneIndex(zone, subzone); + if ( not zidx ) then + tinsert(FishingBuddy_Info["ZoneIndex"], zone); + zidx = table.getn(FishingBuddy_Info["ZoneIndex"]); + zonemapping[zone] = zidx; + -- keep sort helpers up to date + if ( FishingBuddy.SortedZones ) then + tinsert(FishingBuddy.SortedZones, zone); + table.sort(FishingBuddy.SortedZones); + end + end + if ( not subzone ) then + return zidx; + end + if ( not subzonemapping[zidx] ) then + subzonemapping[zidx] = {}; + end + if ( not subzonemapping[zidx][subzone] ) then + if ( not FishingBuddy_Info["SubZones"][zidx] ) then + FishingBuddy_Info["SubZones"][zidx] = {}; + end + tinsert(FishingBuddy_Info["SubZones"][zidx], subzone); + subzonemapping[zidx][subzone] = table.getn(FishingBuddy_Info["SubZones"][zidx]); + -- keep sort helpers up to date + if ( FishingBuddy.SortedByZone ) then + FishingBuddy.SortedByZone[zone] = {}; + tinsert(FishingBuddy.SortedByZone[zone], subzone); + table.sort(FishingBuddy.SortedByZone[zone]); + tinsert(FishingBuddy.SortedSubZones, subzone); + table.sort(FishingBuddy.SortedSubZones); + end + end + return zidx, subzonemapping[zidx][subzone]; +end +FishingBuddy.AddZoneIndex = AddZoneIndex; + +local function SetZoneLevel(zone, subzone, fishid) + local skill, mods = GetCurrentSkill(); + local zidx, sidx = GetZoneIndex(zone, subzone); + local fs = FishingBuddy_Info["FishingSkill"]; + if ( not fs[zidx] ) then + fs[zidx] = {}; + end + local skillcheck = skill + mods; + if ( skillcheck > 0 ) then + if ( not fs[zidx][sidx] or skillcheck < fs[zidx][sidx] ) then + fs[zidx][sidx] = skillcheck; + end + if ( fishid ) 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 +FishingBuddy.SetZoneLevel = SetZoneLevel; + +local OldBindingKey; +local OldBindingKey2; +local function UpdateBindings(onoff) + if ( onoff ) then + if ( not OldKeyBinding ) then + OldKeyBinding, OldBindingKey2 = GetBindingKey("TURNORACTION"); + if ( OldKeyBinding ) then + SetBinding(OldKeyBinding, "FISHINGBUDDY_PERFORMCAST"); + if (OldBindingKey2) then + SetBinding(OldBindingKey2, "FISHINGBUDDY_PERFORMCAST"); + end + else + FishingBuddy.UIError(FishingBuddy.TOOMANYFISHERMEN); + end + end + else + if ( OldKeyBinding ) then + SetBinding(OldKeyBinding, "TURNORACTION"); + OldKeyBinding = nil; + if (OldBindingKey2) then + SetBinding(OldBindingKey2, "TURNORACTION"); + OldBindingKey2 = nil; + end + end + end +end +FishingBuddy.UpdateBindings = UpdateBindings; + +-- Something else that should be in a library +local function SplitLink(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.SplitLink = SplitLink; + +local function SplitFishLink(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 +FishingBuddy.SplitFishLink = SplitFishLink; + +local function IsLinkableItem(item) + local link = "item:"..item; + local n,l,_,_,_,_,_,_ = GetItemInfo(link); + return ( n and l ); +end +FishingBuddy.IsLinkableItem = IsLinkableItem; + +-- 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, _ = SplitLink(link); + -- Make sure it's not "Nat Pagle's Fish Terminator" + if ( not string.find(id, "^19944") ) then + return true; + end + end + return false; +end +FishingBuddy.API.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 NormalHijackCheck() + if ( GetSetting("EasyCast") == 1 and + CastingKeys() and IsFishingPole() ) then + return true; + end +end +FishingBuddy.NormalHijackCheck = NormalHijackCheck; + +local HijackCheck = NormalHijackCheck; +local function SetHijackCheck(func) + if ( not func ) then + func = NormalHijackCheck; + end + HijackCheck = func; +end +FishingBuddy.SetHijackCheck = SetHijackCheck; + +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 FindItemByID(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, check, n = SplitFishLink(link); + 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 + +local function AddFishie(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 ( name and not FishingBuddy_Info["Fishies"][id].name ) then + FishingBuddy_Info["Fishies"][id].name = name; + end + + if ( not zone ) then + zone = FishingBuddy.UNKNOWN; + end + if ( not subzone ) then + subzone = zone; + end + local zidx, sidx = AddZoneIndex(zone, subzone); + + if ( not FishingBuddy.currentFishies[sidx] ) then + FishingBuddy.currentFishies[sidx] = {}; + end + if ( not FishingBuddy.currentFishies[sidx][id] ) then + FishingBuddy.currentFishies[sidx][id] = quantity; + else + FishingBuddy.currentFishies[sidx][id] = FishingBuddy.currentFishies[sidx][id] + quantity; + end + + if( not FishingBuddy_Info["FishingHoles"][zidx] ) then + FishingBuddy_Info["FishingHoles"][zidx] = { }; + end + if( not FishingBuddy_Info["FishingHoles"][zidx][sidx] ) then + FishingBuddy_Info["FishingHoles"][zidx][sidx] = { }; + end + local fh = FishingBuddy_Info["FishingHoles"][zidx]; + if ( not fh[sidx][id] ) then + fh[sidx][id] = quantity; + if ( GetSetting("ShowNewFishies") == 1 ) then + FishingBuddy.Print(FishingBuddy.ADDFISHIEMSG, name, subzone); + end + else + fh[sidx][id] = fh[sidx][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][sidx] = quantity; + else + FishingBuddy.ByFishie[id][sidx] = FishingBuddy.ByFishie[id][sidx] + quantity; + end + end + FishingBuddy.Locations.DataChanged(zone, subzone, fishie); + FishingBuddy.WatchUpdate(); +end +FishingBuddy.AddFishie = AddFishie; + +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]; + 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; +-- 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"]; +-- 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 InvokeFishing() + GetFishingSpellID(); + if ( FishingSpellID ) then + CastSpell(FishingSpellID, BOOKTYPE_SPELL); + end +end + +local ModeEventTable = { + "LOOT_OPENED", + "LOOT_CLOSED", + "SPELLS_CHANGED", + "SPELLCAST_CHANNEL_START", + "SPELLCAST_CHANNEL_STOP", + "SPELLCAST_START", + "SPELLCAST_STOP", + "SPELLCAST_INTERRUPTED", + "SPELLCAST_FAILED", + "SKILL_LINES_CHANGED", +}; + +-- 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 FishingBuddy.StartedFishing ) then + FishingBuddy.StartedFishing = GetTime(); + FishingBuddy.EnhanceFishingSounds(true); + FishingBuddy.WatchUpdate(); + EventRegistration(FishingBuddyRoot, ModeEventTable, true); + end +end + +local function StopFishingMode() + if ( FishingBuddy.StartedFishing ) then + FishingBuddy.EnhanceFishingSounds(false); + FishingBuddy.WatchUpdate(); + FishingBuddy.StartedFishing = nil; + EventRegistration(FishingBuddyRoot, ModeEventTable, false); + end + if ( resetClickToMove ) then + -- Re-enable Click-to-Move if we changed it + SetCVar("autointeract", "1"); + resetClickToMove = nil; + end +end + +local function FishingMode() + if ( IsFishingPole() ) then + StartFishingMode(); + else + StopFishingMode(); + end +end +FishingBuddy.API.FishingMode = FishingMode; + +-- 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 = FindItemByID(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 + 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 ( 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); + + if ( not schooltipText or not OnFishingBobber() ) then + -- watch for fishing holes + schooltipText = GetTooltipText(); + end + + -- put on a lure if we need to + if ( not UpdateLure() ) then + InvokeFishing(); + end +end + +FishingBuddy.SuitUpAndGoFishing = function() + if ( IsFishingPole() ) then + -- put on a lure if we need to + if ( not UpdateLure() ) then + InvokeFishing(); + end + elseif ( GetSetting("SuitUpFirst") == 1 ) then + FishingBuddy.OutfitManager.Switch(); + 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 + +-- we should collect these, but then they would be in the cache +local QuestItems = {}; +QuestItems[6717] = 1; -- Gaffer Jack +QuestItems[6718] = 1; -- Electropeller +QuestItems[16970] = 1; -- Misty Reed Mahi Mahi +QuestItems[16968] = 1; -- Sar'theris Striker +QuestItems[16969] = 1; -- Savage Coast Blue +QuestItems[16967] = 1; -- Feralas Ahi + +-- User interface handling +local function IsRareFish(id, forced) + -- always skip extravaganza fish + if ( FishingBuddy.Extravaganza.Fish[id] ) then + return true; + end + return ( not forced and QuestItems[id] ); +end + +FishingBuddy.Commands[FishingBuddy.UPDATEDB] = {}; +FishingBuddy.Commands[FishingBuddy.UPDATEDB].help = FishingBuddy.UPDATEDB_HELP; +FishingBuddy.Commands[FishingBuddy.UPDATEDB].func = + function(what) + local ff = FishingBuddy_Info["Fishies"]; + local forced; + if ( what and what == FishingBuddy.FORCE ) then + forced = true; + end + FishingOutfitTooltip:SetOwner(FishingBuddyFrame, "ANCHOR_RIGHT"); + FishingOutfitTooltip:Show(); + local count = 0; + for id,info in ff do + local item = id..":0:0:0"; + if ( not IsLinkableItem(item) or not info.name ) then + if ( not IsRareFish(id, forced) ) then + local link = "item:"..item; + -- fetch the data (may disconnect) + FishingBuddy.Debug(link); + FishingOutfitTooltip:SetHyperlink(link); + -- now that we have it in our cache, get the name + local n,_,_,_,_,_,_,_ = GetItemInfo(link); + if ( n ) then + count = count + 1; + FishingBuddy_Info["Fishies"][id].name = n; + end + end + end + end + FishingBuddy.Print(FishingBuddy.UPDATEDB_MSG, count); + 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.TooltipBody = function(hintcheck) + local text = FishingBuddy.DESCRIPTION1.."\n"..FishingBuddy.DESCRIPTION2; + if ( hintcheck ) then + text = text.."\n".."|c"..FishingBuddy.Colors.GREEN; + text = text .. FishingBuddy.TOOLTIP_HINT.." "; + if (FishingBuddy.GetSetting(hintcheck) == 1) then + text = text..FishingBuddy.TOOLTIP_HINTSWITCH; + else + text = text..FishingBuddy.TOOLTIP_HINTTOGGLE; + end + text = text.."|r"; + end + return text; +end + +local IWEventTable = { + "ITEM_LOCK_CHANGED", +}; + +FishingBuddy.OnLoad = function() + this:RegisterEvent("PLAYER_ENTERING_WORLD"); + this:RegisterEvent("PLAYER_LEAVING_WORLD"); + + this:RegisterEvent("PLAYER_LOGIN"); + this:RegisterEvent("PLAYER_LOGOUT"); + this:RegisterEvent("VARIABLES_LOADED"); + + this:RegisterEvent("MINIMAP_ZONE_CHANGED"); + + -- Set up command + SlashCmdList["fishingbuddy"] = FishingBuddy.Command; + SLASH_fishingbuddy1 = "/fishingbuddy"; + SLASH_fishingbuddy2 = "/fb"; + + FishingBuddy.Output(FishingBuddy.WINDOW_TITLE.." loaded"); +end + +local IsZoning; +local ZoneEvents; +local function TrackZoneEvents(evt) + if ( IsZoning ) then + if ( not ZoneEvents ) then + ZoneEvents = {}; + end + if ( ZoneEvents[evt] ) then + ZoneEvents[evt] = ZoneEvents[evt] + 1; + else + ZoneEvents[evt] = 1; + end + end +end + +local function DumpZoneEvents() + FishingBuddy.Dump(ZoneEvents); + ZoneEvents = nil; +end + +FishingBuddy.OnEvent = function() + local needUpdate = false; +-- TrackZoneEvents(event); + if ( event == "LOOT_OPENED" ) then + IsLooting = true; + if ( IsFishingLoot()) then + local zone, subzone = GetZoneInfo(); + local check = FishingBuddy.Schools.CheckFishingHole; + 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 = SplitFishLink(link); + AddFishie(color, id, name, zone, subzone, texture, quantity, quality); + if ( FishingBuddy.AddTracking ) then + FishingBuddy.AddTracking(id, name); + end + check(schooltipText, id); + SetZoneLevel(zone, subzone, id); + end + end + if ( schooltipText ) then + schooltipText = nil; + end + end + elseif ( event == "LOOT_CLOSED" ) then + IsLooting = false; + elseif ( event == "MINIMAP_ZONE_CHANGED" ) then + if ( not FishingBuddy.IsLoaded() ) then + return; + end + FishingBuddy.currentFishies = {}; + needUpdate = true; + elseif ( event == "SPELLS_CHANGED" ) then + -- Fishing might have moved, go look again + FishingSpellID = nil; + elseif ( event == "ITEM_LOCK_CHANGED" ) then + FishingMode(); + elseif ( event == "SPELLCAST_CHANNEL_START" ) then + -- Mugendai is one sharp cookie (shamelessly stealing from TackleBox) + -- Keep up with whether or not we are casting + CastingNow = true; + elseif ( event == "SPELLCAST_CHANNEL_STOP" ) then + CastingNow = false; + elseif ( 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; + elseif ( event == "SKILL_LINES_CHANGED" ) then + if ( GetSetting("WatchCurrentSkill") == 1 ) then + needUpdate = true; + end + elseif ( event == "PLAYER_LOGIN" ) then + -- set up outfit stuff + playerName = UnitName("player"); + realmName = GetRealmName(); + CheckClockOffset(); + FishingBuddy.OutfitManager.Initialize(); + FishingMode(); + elseif ( event == "PLAYER_LOGOUT" ) then + -- reset the fishing sounds, if we need to + StopFishingMode(); + FishingBuddy.SavePlayerInfo(); + elseif ( event == "VARIABLES_LOADED" ) then + FishingBuddy.Initialize(); + this:UnregisterEvent("VARIABLES_LOADED"); + elseif ( event == "PLAYER_ENTERING_WORLD" ) then + IsZoning = nil; +-- DumpZoneEvents(); + EventRegistration(this, IWEventTable, true); + elseif ( event == "PLAYER_LEAVING_WORLD") then + IsZoning = 1; + EventRegistration(this, IWEventTable, false); + end + FishingBuddy.Extravaganza.IsTime(true); + if ( needUpdate ) then + FishingBuddy.WatchUpdate(); + end +end + +FishingBuddy.PrintHelp = function(tab) + if ( tab ) then + if ( type(tab) == "table" ) then + for _,line in tab do + FishingBuddy.PrintHelp(line); + end + else + -- check for a reference to another help item + local _,_,w = string.find(tab, "^@([A-Z0-9_]+)$"); + if ( w ) then + FishingBuddy.PrintHelp(FishingBuddy[w]); + else + FishingBuddy.Output(tab); + end + end + 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.MakeToggle = MakeToggle; + +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 name,option in FishingBuddy.OPTIONS do + if ( option.m ) then + local addthis = true; + if ( option.check ) then + addthis = option.check(); + end + if ( addthis ) then + info = {}; + info.text = option.text; + info.func = MakeToggle(name); + info.checked = (GetSetting(name) == 1); + info.keepShownOnClick = 1; + UIDropDownMenu_AddButton(info); + end + 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.index and b.index and a.index 1 ) then + fishie = string.sub(fishie, 1, s-1)..string.sub(fishie, e+1); + else + fishie = string.sub(fishie, e+1); + end + else + s,e = string.find(fishie, " "..FishingBuddy.RAW); + if ( s ) then + fishie = string.sub(fishie, 1, s-1)..string.sub(fishie, e+1); + end + end + return fishie; + end + -- this means an import failed somewhere + return FishingBuddy.UNKNOWN; +end + +FishingBuddy.ToggleDropDownMenu = function(level, value, menu, anchor, xOffset, yOffset) + ToggleDropDownMenu(level, value, menu, anchor, xOffset, yOffset); + if (not level) then + level = 1; + end + local anchorName; + if ( type(anchor) == "string" ) then + anchorName = anchor; + else + anchorName = anchor:GetName(); + end + local frame = getglobal("DropDownList"..level); + local uiScale = UIParent:GetScale() + if ( frame:GetRight() > ( GetScreenWidth()*uiScale ) ) then + if ( anchorName == "cursor" ) then + if ( not xOffset ) then + xOffset = 0; + end + if ( not yOffset ) then + yOffset = 0; + end + local cursorX, cursorY = GetCursorPosition(); + xOffset = -cursorX + xOffset; + yOffset = cursorY + yOffset; + else + if ( not xOffset or not yOffset ) then + xOffset = 8; + yOffset = 22; + end + end + frame:ClearAllPoints(); + frame:SetPoint("TOPRIGHT", anchorName, "BOTTOMLEFT", -xOffset, yOffset); + end + if ( frame:GetBottom() < 0 ) then + frame:ClearAllPoints(); + frame:SetPoint("BOTTOMRIGHT", anchorName, "BOTTOMLEFT", -xOffset, yOffset); + end +end + +FishingBuddy.EnglishList = function(list, conjunction) + if ( list ) then + local n = table.getn(list); + local str = ""; + for idx=1,n do + local name = list[idx]; + if ( idx == 1 ) then + str = name; + elseif ( idx == n ) then + str = str .. ", "; + if ( conjunction ) then + str = str .. conjunction; + else + str = str .. "and"; + end + str = str .. " " .. name; + else + str = str .. ", " .. name; + end + end + return str; + end +end + +FishingBuddy.Message = function(msg, r, g, b) + FishingBuddy.Output(FishingBuddy.NAME..": "..msg, r, g, b); +end + +FishingBuddy.Print = function(...) + local msg = string.format(unpack(arg)); + FishingBuddy.Message(msg); +end + +FishingBuddy.Error = function(msg) + FishingBuddy.Output(FishingBuddy.NAME..": "..msg, 1.0, 0, 0); +end + +FishingBuddy.UIError = function(msg) + -- Okay, this check is probably not necessary... + if ( UIErrorsFrame ) then + UIErrorsFrame:AddMessage(msg, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME); + else + FishingBuddy.Error(msg); + end +end + +FishingBuddy.Testing = function(line) + if ( not FishingBuddy_Info["Testing"] ) then + FishingBuddy_Info["Testing"] = {}; + end + tinsert(FishingBuddy_Info["Testing"], line); +end diff --git a/FishingBuddy.toc b/FishingBuddy.toc new file mode 100644 index 0000000..1f06b8e --- /dev/null +++ b/FishingBuddy.toc @@ -0,0 +1,34 @@ +## Interface: 11200 +## Title: Fishing Buddy +## Version: 0.8.8e +## Notes: Help with fishing related tasks -- clothing, fish information, etc. +## Notes-ruRU: Отслеживает какую рыбу и где вы поймали и помогает управлять вашим рыболовским снарежением. +## Notes-deDE: Erleichtert das Angeln - Ausr\195\188stung und Fish-Infos +## Notes-frFR: Vous facilite la vie de pecheur. Informations sur les poissons, changement d'habits, etc. +## Notes-esES: Ayude con las tareas relacionadas pesca -- ropa, informaci\195\179n de los pescados +## Author: Sutorix=AT=hotmail.com +## OptionalDeps: FBEnEspagnol, OutfitDisplayFrame, Outfitter, myAddOns, FuBar, Titan, InfoBar, Gatherer, FuBar, ButtonHole +## SavedVariables: FishingBuddy_Info +## SavedVariablesPerCharacter: FishingBuddy_Player +localization.lua +localization.ru.lua +localization.de.lua +localization.es.lua +localization.fr.lua +FishingDebugging.lua +FishingSetup.lua +FishingBuddy.xml +FishingBuddyFrame.xml +FishingOptionsFrame.xml +FishingLocationsFrame.xml +FishingOutfitManager.xml +FishingOutfitFrame.xml +FishingOutfitter.lua +FishingBuddyTitan.xml +FishingBuddyMinimap.xml +FishingBuddyInfoBar.xml +FishingExtravaganza.xml +FishingWatcher.xml +GraphHandler.xml +FishingTrackingFrame.xml +FishingSchools.lua diff --git a/FishingBuddy.xml b/FishingBuddy.xml new file mode 100644 index 0000000..82a8ad1 --- /dev/null +++ b/FishingBuddy.xml @@ -0,0 +1,24 @@ + +