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
+
+
+
+ if ( keystate == "up" ) then
+ FishingBuddy.PerformCast();
+ else
+ FishingBuddy.UpdateBindings(false);
+ 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 @@
+
+
+
+
+
+
+
+ FishingBuddy.OnLoad();
+
+
+ FishingBuddy.OnEvent();
+
+
+
+
+
+
+
+ -- FishingBuddy_RecastOnUpdate(arg1);
+
+
+
+
diff --git a/FishingBuddyFrame.lua b/FishingBuddyFrame.lua
new file mode 100644
index 0000000..537cd1b
--- /dev/null
+++ b/FishingBuddyFrame.lua
@@ -0,0 +1,147 @@
+local SUBFRAMES = {
+ ["FishingLocationsFrame"] = {
+ ["name"] = FishingBuddy.LOCATIONS_TAB,
+ ["tooltip"] = FishingBuddy.LOCATIONS_INFO,
+ ["toggle"] = "_LOC",
+ ["id"] = "1",
+ },
+ ["FishingOutfitFrame"] = {
+ ["name"] = FishingBuddy.OUTFITS_TAB,
+ ["tooltip"] = FishingBuddy.OUTFITS_INFO,
+ ["toggle"] = "_OUT",
+ ["id"] = "2",
+ },
+ ["FishingTrackingFrame"] = {
+ ["name"] = FishingBuddy.TRACKING_TAB,
+ ["tooltip"] = FishingBuddy.TRACKING_INFO,
+ ["toggle"] = "_TRK",
+ ["id"] = "3",
+ },
+ ["FishingOptionsFrame"] = {
+ ["name"] = FishingBuddy.OPTIONS_TAB,
+ ["tooltip"] = FishingBuddy.OPTIONS_INFO,
+ ["toggle"] = "_OPT",
+ ["id"] = "4",
+ }
+};
+
+local function DisableSubFrame(frameName)
+ for value,info in SUBFRAMES do
+ if ( value == frameName ) then
+ local id = info.id;
+ local hideframe = string.format("FishingBuddyFrameTab%d", id);
+ local f = getglobal(hideframe);
+ if ( f ) then
+ f:Hide();
+ f = getglobal(string.format("FishingBuddyFrameTab%d", id+1));
+ if ( f ) then
+ f:SetPoint("LEFT", hideframe, "LEFT", 0, 0)
+ end
+ end
+ end
+ end
+end
+FishingBuddy.DisableSubFrame = DisableSubFrame;
+
+local function EnableSubFrame(frameName)
+ for value,info in SUBFRAMES do
+ if ( value == frameName ) then
+ local id = info.id;
+ local hideframe = string.format("FishingBuddyFrameTab%d", id);
+ local f = getglobal(hideframe);
+ if ( f ) then
+ f:Show();
+ f = getglobal(string.format("FishingBuddyFrameTab%d", id+1));
+ if ( f ) then
+ f:SetPoint("LEFT", hideframe, "RIGHT", -18, 0)
+ end
+ end
+ end
+ end
+end
+FishingBuddy.EnableSubFrame = EnableSubFrame;
+
+local function ShowSubFrame(frameName)
+ for value,_ in SUBFRAMES do
+ local frame = getglobal(value);
+ if ( frame ) then
+ if ( value == frameName ) then
+ frame:Show()
+ else
+ frame:Hide();
+ end
+ end
+ end
+end
+
+function ToggleFishingBuddyFrame(tab)
+ if ( tab == "FishingOutfitFrame" and not OutfitDisplayFrame_OnLoad and not FishingOutfitFrame:IsVisible() ) then
+ return;
+ end
+ local subFrame = getglobal(tab);
+ if ( subFrame ) then
+ local id = subFrame:GetID();
+ PanelTemplates_SetTab(FishingBuddyFrame, id);
+ if ( FishingBuddyFrame:IsVisible() ) then
+ if ( subFrame:IsVisible() ) then
+ HideUIPanel(FishingBuddyFrame);
+ else
+ ShowSubFrame(tab);
+ end
+ else
+ ShowUIPanel(FishingBuddyFrame);
+ ShowSubFrame(tab);
+ end
+ end
+end
+
+local TABFRAMES = {};
+function FishingBuddyFrameTab_OnClick()
+ ToggleFishingBuddyFrame(TABFRAMES[this:GetName()]);
+ PlaySound("igCharacterInfoTab");
+end
+
+function FishingBuddyFrame_OnLoad()
+ -- Act like Blizzard windows
+ UIPanelWindows["FishingBuddyFrame"] = { area = "left", pushable = 999 };
+ -- Close with escape key
+ tinsert(UISpecialFrames, "FishingBuddyFrame");
+
+ -- Tab Handling code
+ PanelTemplates_SetNumTabs(this, 4);
+ PanelTemplates_SetTab(this, 1);
+
+ this:RegisterEvent("VARIABLES_LOADED");
+end
+
+function FishingBuddyFrame_OnEvent(event)
+ if ( event == "VARIABLES_LOADED" ) then
+ -- set up mappings
+ for frame,info in SUBFRAMES do
+ local f = getglobal(frame);
+ if ( f ) then
+ f:SetID(info.id);
+
+ local tabname = "FishingBuddyFrameTab"..info.id;
+ TABFRAMES[tabname] = frame;
+ local tab = getglobal(tabname);
+ tab:SetText(info.name);
+ tab.tooltip = info.tooltip;
+ tab.toggle = "TOGGLEFISHINGBUDDY"..info.toggle;
+ else
+ DisableSubFrame(frame);
+ end
+ end
+ ShowSubFrame("FishingLocationsFrame");
+ end
+end
+
+function FishingBuddyFrame_OnShow()
+ FishingBuddyFramePortrait:SetTexture("Interface\\LootFrame\\FishingLoot-Icon");
+ FishingBuddyNameText:SetText(FishingBuddy.WINDOW_TITLE);
+ UpdateMicroButtons();
+end
+
+function FishingBuddyFrame_OnHide()
+ UpdateMicroButtons();
+end
diff --git a/FishingBuddyFrame.xml b/FishingBuddyFrame.xml
new file mode 100644
index 0000000..c749712
--- /dev/null
+++ b/FishingBuddyFrame.xml
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(this:GetFrameLevel() + 1);
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddyFrame_OnLoad();
+
+
+ FishingBuddyFrame_OnEvent(event);
+
+
+ FishingBuddyFrame_OnShow();
+
+
+ FishingBuddyFrame_OnHide();
+
+
+
+
diff --git a/FishingBuddyInfoBar.lua b/FishingBuddyInfoBar.lua
new file mode 100644
index 0000000..bcde667
--- /dev/null
+++ b/FishingBuddyInfoBar.lua
@@ -0,0 +1,48 @@
+-- InfoBar support
+
+FishingBuddy.InfoBar = {};
+
+FishingBuddy.InfoBar.OnLoad = function()
+ if ( not InfoBarFrame ) then
+ return;
+ end
+
+ this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
+
+ this.info = {
+ name = FishingBuddy.NAME,
+ version = FishingBuddy.CURRENTVERSION/100,
+ tooltip = FishingBuddy.InfoBar.Tooltip,
+ };
+end
+
+FishingBuddy.InfoBar.OnClick = function(button)
+ if (button == "LeftButton") then
+ if (FishingBuddy.GetSetting("InfoBarClickToSwitch") == 1) then
+ FishingBuddy.Command(FishingBuddy.SWITCH);
+ else
+ FishingBuddy.Command("");
+ end
+ elseif ( IsShiftKeyDown() ) then
+ ToggleFishingBuddyFrame("FishingOptionsFrame");
+ else
+ -- Toggle menu
+ local menu = getglobal("FishingBuddyInfoBarMenu");
+ menu.point = "TOPRIGHT";
+ menu.relativePoint = "CENTER";
+ local level = 1;
+ ToggleDropDownMenu(level, nil, menu, "IB_FishingBuddy", 0, 0);
+ end
+end
+
+FishingBuddy.InfoBar.OnEvent = function()
+end
+
+FishingBuddy.InfoBar.Tooltip = function()
+ return FishingBuddy.TooltipBody("InfoBarClickToSwitch");
+end
+
+FishingBuddy.InfoBar.Menu_Initialize = function()
+ FishingBuddy.MakeDropDown(FishingBuddy.CLICKTOSWITCH_ONOFF,
+ "InfoBarClickToSwitch");
+end
diff --git a/FishingBuddyInfoBar.xml b/FishingBuddyInfoBar.xml
new file mode 100644
index 0000000..52e14c5
--- /dev/null
+++ b/FishingBuddyInfoBar.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
diff --git a/FishingBuddyMinimap.lua b/FishingBuddyMinimap.lua
new file mode 100644
index 0000000..b911c4e
--- /dev/null
+++ b/FishingBuddyMinimap.lua
@@ -0,0 +1,116 @@
+-- Minimap Button Handling
+
+FishingBuddy.UseButtonHole = function()
+ if ( ButtonHole and FishingBuddy.GetSetting("UseButtonHole") == 1 ) then
+ return true;
+ else
+ return false;
+ end
+end
+
+FishingBuddy.Minimap = {};
+
+FishingBuddy.Minimap.OnLoad = function()
+ this:RegisterEvent("VARIABLES_LOADED");
+end
+
+FishingBuddy.Minimap.OnEvent = function()
+ if ( FishingBuddy.UseButtonHole() ) then
+ local info = {};
+ info.id=FishingBuddy.ID;
+ info.name=FishingBuddy.NAME;
+ info.tooltip=FishingBuddy.DESCRIPTION;
+ info.buttonFrame="FishingBuddyMinimapFrame";
+ info.updateFunction="FishingBuddyMinimapButton_MoveButton";
+ ButtonHole.application.RegisterMod(info);
+ elseif ( ButtonHole ) then
+ -- hack, hack, hack
+ local playerName = UnitName("player");
+ if ( ButtonHoleConfig[playerName] and
+ ButtonHoleConfig[playerName].visibleMod == FishingBuddy.ID ) then
+ ButtonHoleConfig[playerName].visibleMod = nil;
+ end
+ end
+end
+
+FishingBuddy.Minimap.Button_OnLoad = function()
+ this:SetFrameLevel(this:GetFrameLevel()+1)
+ this:RegisterForClicks("LeftButtonDown", "RightButtonDown");
+ this:RegisterEvent("VARIABLES_LOADED");
+end
+
+FishingBuddy.Minimap.Button_OnClick = function(button)
+ if ( button == "RightButton" ) then
+ if ( IsShiftKeyDown() ) then
+ ToggleFishingBuddyFrame("FishingOptionsFrame");
+ else
+ -- Toggle menu
+ local menu = getglobal("FishingBuddyMinimapMenu");
+ menu.point = "TOPRIGHT";
+ menu.relativePoint = "CENTER";
+ ToggleDropDownMenu(1, nil, menu, "FishingBuddyMinimapButton", 0, 0);
+ end
+ elseif ( FishingBuddy.GetSetting("MinimapClickToSwitch") == 1 ) then
+ FishingBuddy.Command(FishingBuddy.SWITCH);
+ else
+ FishingBuddy.Command("");
+ end
+end
+
+FishingBuddyMinimapButton_MoveButton = function()
+ if ( FishingBuddy.IsLoaded() ) then
+ local where = FishingBuddy.GetSetting("MinimapButtonPosition");
+ FishingBuddyMinimapFrame:ClearAllPoints();
+ FishingBuddyMinimapFrame:SetPoint("TOPLEFT", "Minimap", "TOPLEFT",
+ 52 - (80 * cos(where)),
+ (80 * sin(where)) - 52);
+ end
+end
+
+FishingBuddy.UpdateMinimap = function()
+ FishingBuddyMinimapButton_MoveButton();
+ if ( FishingBuddy.GetSetting("MinimapButtonVisible") == 1 and
+ Minimap:IsVisible() ) then
+ FishingBuddyMinimapButton:EnableMouse(true);
+ FishingBuddyMinimapButton:Show();
+ FishingBuddyMinimapFrame:Show();
+ else
+ FishingBuddyMinimapButton:EnableMouse(false);
+ FishingBuddyMinimapButton:Hide();
+ FishingBuddyMinimapFrame:Hide();
+ end
+end
+
+FishingBuddy.Minimap.Button_OnEvent = function()
+ FishingBuddy.UpdateMinimap();
+end
+
+FishingBuddy.Minimap.Button_OnEnter = function()
+ if ( GameTooltip.fbmmbfinished ) then
+ return;
+ end
+ if ( FishingBuddy.GetSetting("UseButtonHole") == 0 ) then
+ GameTooltip.fbmmbfinished = 1;
+ GameTooltip:SetOwner(FishingBuddyMinimapFrame, "ANCHOR_LEFT");
+ GameTooltip:AddLine(FishingBuddy.NAME);
+ local text = FishingBuddy.TooltipBody("MinimapClickToSwitch");
+ GameTooltip:AddLine(text,.8,.8,.8,1);
+ GameTooltip:Show();
+ end
+end
+
+FishingBuddy.Minimap.Button_OnLeave = function()
+ GameTooltip:Hide();
+ GameTooltip.fbmmbfinished = nil;
+end
+
+function FishingBuddy_ToggleMinimap()
+ FishingBuddy.SavedToggleMinimap();
+ FishingBuddy.UpdateMinimap();
+end
+
+FishingBuddy.Minimap.Menu_Initialize = function()
+ FishingBuddy.MakeDropDown(FishingBuddy.CLICKTOSWITCH_ONOFF,
+ "MinimapClickToSwitch");
+end
+
diff --git a/FishingBuddyMinimap.xml b/FishingBuddyMinimap.xml
new file mode 100644
index 0000000..259c5e7
--- /dev/null
+++ b/FishingBuddyMinimap.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(0);
+ UIDropDownMenu_SetWidth(180);
+
+
+ UIDropDownMenu_Initialize(this, FishingBuddy.Minimap.Menu_Initialize, "MENU");
+
+
+
+
+
+
+
+ FishingBuddy.Minimap.OnLoad();
+
+
+ FishingBuddy.Minimap.OnEvent();
+
+
+
+
+
diff --git a/FishingBuddyTitan.lua b/FishingBuddyTitan.lua
new file mode 100644
index 0000000..4da5b5c
--- /dev/null
+++ b/FishingBuddyTitan.lua
@@ -0,0 +1,58 @@
+-- Titan Panel support
+
+FishingBuddy.Titan = {};
+
+FishingBuddy.Titan.OnLoad = function()
+ if not TitanPanelButton_UpdateButton then
+ return;
+ end
+
+ this.registry = {
+ id = FishingBuddy.ID,
+ menuText = FishingBuddy.NAME,
+ version = FishingBuddy.VERSION,
+ category = "Profession",
+ icon = "Interface\\AddOns\\FishingBuddy\\Icons\\Fishing-Icon",
+ iconWidth = 16,
+ tooltipTitle = FishingBuddy.NAME,
+ tooltipTextFunction = "TitanPanelFishingBuddyButton_GetTooltipText",
+ savedVariables = {
+ ShowIcon = 1,
+ }
+ };
+
+ this:RegisterEvent("PLAYER_ENTERING_WORLD");
+end
+
+FishingBuddy.Titan.OnClick = function(button)
+ if (button == "LeftButton") then
+ if (FishingBuddy.GetSetting("TitanClickToSwitch") == 1) then
+ FishingBuddy.Command(FishingBuddy.SWITCH);
+ else
+ FishingBuddy.Command("");
+ end
+ end
+end
+
+FishingBuddy.Titan.OnEvent = function()
+ if TitanPanelButton_UpdateButton then
+ TitanPanelButton_UpdateButton(FishingBuddy.ID);
+ TitanPanelButton_UpdateTooltip();
+ end
+end
+
+function TitanPanelFishingBuddyButton_GetTooltipText()
+ return FishingBuddy.TooltipBody("TitanClickToSwitch");
+end
+
+function TitanPanelRightClickMenu_PrepareFishingBuddyMenu()
+ TitanPanelRightClickMenu_AddTitle(TitanPlugins[FishingBuddy.ID].menuText);
+
+ FishingBuddy.MakeDropDown(FishingBuddy.CLICKTOSWITCH_ONOFF, "TitanClickToSwitch");
+
+ TitanPanelRightClickMenu_AddSpacer();
+ TitanPanelRightClickMenu_AddCommand(TITAN_PANEL_MENU_HIDE,
+ FishingBuddy.ID,
+ TITAN_PANEL_MENU_FUNC_HIDE);
+end
+
diff --git a/FishingBuddyTitan.xml b/FishingBuddyTitan.xml
new file mode 100644
index 0000000..21c2300
--- /dev/null
+++ b/FishingBuddyTitan.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/FishingDebugging.lua b/FishingDebugging.lua
new file mode 100644
index 0000000..739cba9
--- /dev/null
+++ b/FishingDebugging.lua
@@ -0,0 +1,95 @@
+-- debugging
+
+FishingBuddy = {};
+FishingBuddy.API = {};
+FishingBuddy.Commands = {};
+
+FishingBuddy.Debugging = true;
+
+local function printable(foo)
+ if ( foo ) then
+ if ( type(foo) == "table" ) then
+ return "table";
+ elseif ( type(foo) == "boolean" ) then
+ if ( foo ) then
+ return "true";
+ else
+ return "false";
+ end
+ else
+ return foo;
+ end
+ else
+ return "nil";
+ end
+end
+FishingBuddy.printable = printable;
+
+FishingBuddy.Output = function(msg, r, g, b)
+ if ( DEFAULT_CHAT_FRAME ) then
+ if ( not r ) then
+ DEFAULT_CHAT_FRAME:AddMessage(msg);
+ else
+ DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b);
+ end
+ end
+end
+
+FishingBuddy.Debug = function(msg, fixlinks)
+ if ( FishingBuddy.Debugging ) then
+ if ( fixlinks ) then
+ msg = string.gsub(msg, "|", ";");
+ end
+ local name = FishingBuddy.Name or "Fishing Buddy";
+ FishingBuddy.Output("|c"..FishingBuddy.Colors.RED..name.."|r "..msg);
+ end
+end
+
+FishingBuddy.DebugVars = function()
+ FishingBuddy.Debugging = true;
+end
+
+FishingBuddy.Dump = function(thing)
+ if ( FishingBuddy.Debugging ) then
+ if ( DevTools_Dump ) then
+ DevTools_Dump(thing);
+ else
+ FishingBuddy.Debug("Tried to dump a '"..FishingBuddy.printable(thing).."'.");
+ end
+ end
+end
+
+-- random debugging code, likely out of date
+FishingBuddy.Commands["debug"] = {};
+FishingBuddy.Commands["debug"].func =
+ function(what)
+ if ( what ) then
+ if ( what == "on" ) then
+ FishingBuddy.Debugging = true;
+ FishingBuddy.SetSetting("FishDebug", true);
+ FishingBuddy.Debug("Debugging turned on");
+ elseif ( what == "off" ) then
+ FishingBuddy.Debug("Debugging turned off");
+ FishingBuddy.Debugging = nil;
+ FishingBuddy.SetSetting("FishDebug", nil);
+ elseif ( what == "reset" ) then
+ FishingBuddy_Info["Testing"] = nil;
+ elseif ( what == "test" ) then
+ local STVInfo = { scale = 0.18128603034401, xoffset = 0.39145470225916, yoffset = 0.79412224886668 };
+ local xscale = 10448.3;
+ local yscale = 7072.7;
+ local playerX, playerY = GetPlayerMapPosition("player");
+ local x = playerX * STVInfo.scale + STVInfo.xoffset;
+ local y = playerY * STVInfo.scale + STVInfo.yoffset;
+ FishingBuddy.Print("PlayerMap: %f, %f", x, y);
+ for idx=1,10 do
+ playerY = playerY + 0.01;
+ local dx = playerX * STVInfo.scale + STVInfo.xoffset;
+ local dy = playerY * STVInfo.scale + STVInfo.yoffset;
+ local dist = math.sqrt((dx*xscale*dx*xscale)+(dy*yscale*dy*yscale));
+ FishingBuddy.Print("PlayerMap: %f, %f - %f", dx, dy, dist);
+ end
+ end
+ end
+ return true;
+ end;
diff --git a/FishingExtravaganza.lua b/FishingExtravaganza.lua
new file mode 100644
index 0000000..c9c43a7
--- /dev/null
+++ b/FishingExtravaganza.lua
@@ -0,0 +1,511 @@
+-- Support for the Extravaganza
+--
+-- Map support liberally borrowed from GuildMap, by Bru on Blackhand
+
+FishingBuddy.Extravaganza = {};
+
+local NUMMINIPOIS = 10;
+local ICONPATH = "Interface\\AddOns\\FishingBuddy\\Icons\\";
+
+-- the actual names don't matter, except to help make sure I've got 'em all
+local ExtravaganzaFish = {};
+ExtravaganzaFish[19807] = "Speckled Tastyfish";
+ExtravaganzaFish[19806] = "Dezian Queenfish";
+ExtravaganzaFish[19805] = "Keefer's Angelfish";
+-- makes you wonder what item 19804 is, doesn't it...
+ExtravaganzaFish[19803] = "Brownell's Blue Striped Racer";
+
+FishingBuddy.Extravaganza.Fish = ExtravaganzaFish;
+
+local UPDATETIME_POI = 0.2;
+local UPDATETIME_SCHOOLS = 0.1;
+local UPDATETIME_COUNTER = 60.0;
+local STVUpdateTimer = 0;
+local numCaught = 0;
+local tastyfish_id = 19807;
+local tastyfish;
+local ExtravaganzaIsOver;
+
+-- convert zone coords into minimap coords
+local STVInfo = { scale = 0.18128603034401,
+ xoffset = 0.39145470225916, yoffset = 0.79412224886668 };
+
+local ZoomScale = {};
+ZoomScale[0] = { xscale = 10448.3, yscale = 7072.7 };
+ZoomScale[1] = { xscale = 12160.5, yscale = 8197.8 };
+ZoomScale[2] = { xscale = 14703.1, yscale = 9825.0 };
+ZoomScale[3] = { xscale = 18568.7, yscale = 12472.2 };
+ZoomScale[4] = { xscale = 24390.3, yscale = 15628.5 };
+ZoomScale[5] = { xscale = 37012.2, yscale = 25130.6 };
+
+local function GetSTVPosition(x, y)
+ if ( not x or not y ) then
+ x, y = GetPlayerMapPosition("player");
+ end
+ x = (x * STVInfo.scale) + STVInfo.xoffset;
+ y = (y * STVInfo.scale) + STVInfo.yoffset;
+ return x, y;
+end
+
+local function SetTextureCoords(texture, A, B, C, D, E, F)
+ local det = A*E - B*D;
+ local ULx, ULy, LLx, LLy, URx, URy, LRx, LRy;
+
+ ULx, ULy = ( B*F - C*E ) / det, ( -(A*F) + C*D ) / det;
+ LLx, LLy = ( -B + B*F - C*E ) / det, ( A - A*F + C*D ) / det;
+ URx, URy = ( E + B*F - C*E ) / det, ( -D - A*F + C*D ) / det;
+ LRx, LRy = ( E - B + B*F - C*E ) / det, ( -D + A -(A*F) + C*D ) / det;
+
+ texture:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy);
+end
+
+local function SetTextureAngle(texture, angrads)
+ local c = math.cos(angrads);
+ local s = math.sin(angrads);
+ SetTextureCoords(texture, c, s, 0, -s, c, 0);
+end
+
+local function GetAngleIcon(x, y)
+ local angle = asin(x / 57);
+ if (x <= 0 and y <= 0) then
+ angle = 180 - angle;
+ elseif (x <= 0 and y > 0) then
+ angle = 360 + angle;
+ elseif (x > 0 and y >= 0) then
+ angle = angle;
+ else
+ angle = 180 - angle;
+ end
+ local fileNumber = math.floor((angle / 10) + 0.5) * 10;
+ if (fileNumber == 360) then
+ fileNumber = 0;
+ end
+ return ICONPATH.."MiniMapArrow"..fileNumber;
+end
+
+local function PlotPOI(index, x, y, rot, scale)
+ local poi = getglobal("FishingExtravaganzaMini"..index);
+ if ( poi ) then
+ if ( x and y ) then
+ local tex = getglobal("FishingExtravaganzaMini"..index.."Texture");
+ local zoom = ZoomScale[Minimap:GetZoom()];
+ x = x * zoom.xscale;
+ y = y * zoom.yscale;
+ local dist = math.sqrt(x*x + y*y);
+ if ( dist > 56.5 ) then
+ x = x * 57 / dist;
+ y = y * 57 / dist;
+ if ( rot) then
+ tex:SetTexture(ICONPATH.."MiniMapArrow");
+ SetTextureAngle(tex, math.asin(x / 57));
+ else
+ tex:SetTexture(GetAngleIcon(x, y));
+ tex:SetTexCoord(0.0, 1.0, 0.0, 1.0);
+ end
+ else
+ tex:SetTexture("Interface\\Minimap\\ObjectIcons");
+ tex:SetTexCoord(0.0, 0.25, 0.25, 0.5);
+ end
+ poi:SetPoint("CENTER", "MinimapCluster", "TOPLEFT", 107 + x, y - 92);
+ if ( scale ) then
+ poi:SetWidth(scale);
+ poi:SetHeight(scale);
+ end
+ poi:Show();
+ return true;
+ else
+ poi:Hide();
+ end
+ end
+ return false;
+end
+
+local function CloseEnough(x1, y1, x2, y2)
+ local zoom = Minimap:GetZoom();
+ local x = (x1 - x2) * ZoomScale[zoom].xscale;
+ local y = (y1 - y2) * ZoomScale[zoom].yscale;
+ if (sqrt( (x * x) + (y * y) ) > 56.5) then
+ return; -- false
+ end
+ return true;
+end
+
+local function GetDistance(x1, y1, x2, y2)
+ local dx = (x1 - x2);
+ local dy = (y1 - y2);
+ return math.sqrt(dx*dx + dy*dy);
+end
+
+local function GetMinimapDistance(x1, y1, x2, y2)
+ local zoom = ZoomScale[Minimap:GetZoom()];
+ local dx = (x1 - x2) * zoom.xscale;
+ local dy = (y1 - y2) * zoom.yscale;
+ return math.sqrt(dx*dx+dy*dy);
+end
+
+local lx, ly;
+local lastten;
+local function GetNearestTen(x, y)
+ local schools = FishingBuddy.Schools.GetSchools(FishingBuddy.STVZONENAME);
+ if ( not x or not y ) then
+ x, y = GetSTVPosition();
+ end
+ -- if we've moved less than half the distance to the closest hole
+ -- don't recalculate
+ if ( lastten ) then
+ if ( lx == x and ly == y ) then
+ return lastten;
+ end
+ if ( table.getn(lastten) > 0 ) then
+ local d = GetDistance(x, y, lx, ly);
+ if ( d < (lastten[1].dist/2) ) then
+ return lastten;
+ end
+ end
+ end
+
+ local bydist = {};
+ for idx=1,table.getn(schools) do
+ local t = schools[idx];
+ if ( t.kind == FishingBuddy.SCHOOL_TASTY ) then
+ local sx, sy = GetSTVPosition(t.x, t.y);
+ local d = GetDistance(sx, sy, x, y);
+ local info = {};
+ info.x = sx;
+ info.y = sy;
+ info.dist = d;
+ tinsert(bydist, info);
+ end
+ end
+ table.sort(bydist, function(a, b) return a.dist < b.dist; end);
+ local idx = 1;
+ lastten = {};
+ for _,info in bydist do
+ if ( idx < 10 ) then
+ tinsert(lastten, { dist = info.dist, x = info.x, y = info.y });
+ idx = idx + 1;
+ end
+ end
+ lx = x;
+ ly = y;
+ return lastten;
+end
+
+local function UpdatePOI()
+ local x, y = GetSTVPosition();
+ local loc1 = GetNearestTen(x, y);
+ for idx=1,NUMMINIPOIS do
+ local t = loc1[idx];
+ if ( t ) then
+ PlotPOI(idx, t.x - x, y - t.y);
+ else
+ PlotPOI(idx);
+ end
+ end
+end
+
+local function HidePOI()
+ local poi = getglobal("FishingExtravaganzaMini1");
+ if ( poi:IsVisible() ) then
+ for idx=1,NUMMINIPOIS do
+ PlotPOI(idx);
+ end
+ end
+end
+
+local POIUpdateTimer = UPDATETIME_POI;
+FishingBuddy.Extravaganza.POI_OnUpdate = function(elapsed)
+ POIUpdateTimer = POIUpdateTimer - elapsed;
+ if ( POIUpdateTimer < 0 ) then
+ FishingExtravaganzaPOIUpdate:Hide();
+ UpdatePOI();
+ POIUpdateTimer = UPDATETIME_POI;
+ end
+end
+
+local function DoUpdatePOI()
+ POIUpdateTimer = UPDATETIME_POI;
+ FishingExtravaganzaPOIUpdate:Show();
+end
+
+-- let an external entity forcibly mark a school
+FishingBuddy.Extravaganza.MarkSchool = function()
+ local zone, subzone = FishingBuddy.GetZoneInfo();
+ if ( zone == FishingBuddy.STVZONENAME ) then
+ FishingBuddy.Schools.AddFishingSchool(FishingBuddy.SCHOOL_TASTY, tastyfish_id, zone);
+ end
+end
+
+local function ExtravaganzaHijackCheck()
+ if ( FishingBuddy.NormalHijackCheck() ) then
+ -- also check to make sure we're over a pool
+ return FishingBuddy.Schools.IsFishingHole(FishingBuddy.GetTooltipText());
+ end
+end
+
+-- Sunday, 2pm
+local STVDay = "0";
+local STVStartHour = 14;
+
+-- Should we display the extravaganza message?
+local function IsTime(activate)
+ local showit = false;
+ if ( FishingBuddy.IsLoaded() ) then
+ if ( FishingBuddy.GetSetting("STVTimer") == 1 ) then
+ local mhour = date("%H");
+ local hour,minute = GetGameTime();
+ local day = date("%w");
+ local off = FishingBuddy.GetClockOffset();
+ if ( off ~= 0 ) then
+ local lhour = date("%H");
+ lhour = lhour + off;
+ if ( lhour >= 24 ) then
+ day = day + 1;
+ elseif( lhour < 0 ) then
+ day = day - 1;
+ end
+ end
+ -- Is it Sunday?
+ if ( day == STVDay and
+ (hour >= (STVStartHour-2) and hour <(STVStartHour+2))) then
+ showit = true;
+ end
+ end
+ end
+ if ( showit ) then
+ if ( activate ) then
+ FishingExtravaganzaFrame:Show();
+ end
+ if ( FishingBuddy.GetSetting("STVPoolsOnly") == 1 ) then
+ local zone,_ = FishingBuddy.GetZoneInfo();
+ if ( zone == FishingBuddy.STVZONENAME ) then
+ FishingBuddy.SetHijackCheck(ExtravaganzaHijackCheck);
+ else
+ FishingBuddy.SetHijackCheck();
+ end
+ end
+ else
+ if ( FishingExtravaganzaFrame:IsVisible() or
+ FishingExtravaganzaMini1:IsVisible() ) then
+ FishingExtravaganzaFrame:Hide();
+ HidePOI();
+ end
+ FishingBuddy.SetHijackCheck();
+ end
+ return showit;
+end
+FishingBuddy.Extravaganza.IsTime = IsTime;
+
+-- Check for mouse down event for dragging frame.
+FishingBuddy.Extravaganza.OnDragStart = function(arg1)
+ if (arg1 == "LeftButton") then
+ FishingExtravaganzaFrame:StartMoving();
+ FishingExtravaganzaFrame.isMoving = true;
+ end
+end
+
+-- Check for drag stop event to stop dragging.
+FishingBuddy.Extravaganza.OnDragStop = function(arg1)
+ if (arg1 == "LeftButton") then
+ FishingExtravaganzaFrame:StopMovingOrSizing();
+ FishingExtravaganzaFrame.isMoving = false;
+ end
+end
+
+-- Handle watching the loot
+FishingBuddy.Extravaganza.OnLoad = function()
+ this:RegisterEvent("PLAYER_LOGIN");
+ this:RegisterEvent("ZONE_CHANGED_NEW_AREA");
+ this:RegisterEvent("VARIABLES_LOADED");
+
+ this:RegisterForDrag("LeftButton");
+ this:Hide();
+end
+
+FishingBuddy.Extravaganza.OnShow = function()
+ -- check each of the bags on the player
+ numCaught = 0;
+ 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 _,id,_ = FishingBuddy.SplitFishLink(link);
+ if ( id and id == tastyfish_id ) then
+ local _,c,_,_,_ = GetContainerItemInfo(bag, slot);
+ numCaught = numCaught + c;
+ end
+ end
+ end
+ end
+ end
+end
+
+FishingBuddy.Extravaganza.OnEvent = function()
+ local zone, subzone = FishingBuddy.GetZoneInfo();
+ if ( event == "LOOT_OPENED" ) then
+ if ( IsFishingLoot()) then
+ for index = 1, GetNumLootItems(), 1 do
+ if (LootSlotIsItem(index)) then
+ local fishlink = GetLootSlotLink(index);
+ local _, id, name = FishingBuddy.SplitFishLink(fishlink);
+ if ( ExtravaganzaFish[id] ) then
+ FishingBuddy.Schools.AddFishingSchool(FishingBuddy.SCHOOL_TASTY, id, zone);
+ STVUpdateTimer = 0;
+ if ( id == tastyfish_id ) then
+ numCaught = numCaught + 1;
+ -- make sure we've got the name of the fish for display
+ tastyfish = name;
+ end
+ end
+ end
+ end
+ end
+ elseif ( event == "CHAT_MSG_YELL" ) then
+ -- Riggle Bassbait yells: We have a winner! (.*) is the Master Angler!
+ local e,s,n = string.find(arg1, FishingBuddy.RIGGLE_BASSBAIT);
+ if ( e ) then
+ ExtravaganzaIsOver = true;
+ end
+ elseif ( event == "MINIMAP_UPDATE_ZOOM" ) then
+ if ( zone == FishingBuddy.STVZONENAME ) then
+ if ( FishingBuddy.GetSetting("STVTimer") == 1 ) then
+ DoUpdatePOI();
+ end
+ end
+ elseif ( event == "ZONE_CHANGED_NEW_AREA" or event == "PLAYER_LOGIN" ) then
+ if ( zone == FishingBuddy.STVZONENAME and IsTime() ) then
+ this:RegisterEvent("CHAT_MSG_YELL");
+ this:RegisterEvent("LOOT_OPENED");
+ this:RegisterEvent("MINIMAP_UPDATE_ZOOM");
+ else
+ this:UnregisterEvent("CHAT_MSG_YELL");
+ this:UnregisterEvent("LOOT_OPENED");
+ this:UnregisterEvent("MINIMAP_UPDATE_ZOOM");
+ end
+ elseif ( event == "VARIABLES_LOADED" ) then
+ local _,_,_,_,_,n = FishingBuddy.GetFishie(tastyfish_id);
+ if ( n ) then
+ tastyfish = n;
+ else
+ tastyfish = FishingBuddy.FISH;
+ end
+ IsTime(true);
+ this:UnregisterEvent("VARIABLES_LOADED");
+ end
+end
+
+FishingBuddy.Extravaganza.OnUpdate = function(elapsed)
+ if ( IsTime() ) then
+ if ( not FishingExtravaganzaFrame:IsVisible() ) then
+ FishingExtravaganzaFrame:Show();
+ end
+ STVUpdateTimer = STVUpdateTimer - elapsed;
+ if ( STVUpdateTimer < 0 ) then
+ local hour,minute = GetGameTime();
+ local minleft;
+ local checkhour = STVStartHour;
+ local line;
+ local contestNow = false;
+ if ( hour >= STVStartHour ) then
+ if ( ExtravaganzaIsOver ) then
+ line = FishingBuddy.FATLADYSINGS;
+ else
+ line = FishingBuddy.TIMELEFT;
+ end
+ line = line..FishingBuddy.DASH.." |c";
+ if ( numCaught < 20 ) then
+ line = line..FishingBuddy.Colors.RED;
+ elseif ( numCaught < 39 ) then
+ line = line..FishingBuddy.Colors.YELLOW;
+ else
+ line = line..FishingBuddy.Colors.GREEN;
+ end
+ line = line..FishingBuddy.FISHCAUGHT.."|r";
+ checkhour = checkhour + 2;
+ contestNow = true;
+ else
+ line = FishingBuddy.TIMETOGO;
+ end
+ minleft = (checkhour - hour)*60 - minute;
+ if ( minleft > 0 ) then
+ FishingExtravaganzaFrameButtonText:SetTextColor(0.1, 1.0, 0.1);
+ if ( minleft < 10 ) then
+ FishingExtravaganzaFrameButtonText:SetTextColor(1.0, 0.1, 0.1);
+ end
+ line = string.format(line, minleft/60, math.mod(minleft, 60),
+ numCaught, tastyfish);
+ FishingExtravaganzaFrameButtonText:SetText(line);
+ local width = FishingExtravaganzaFrameButtonText:GetWidth();
+ FishingExtravaganzaFrame:SetWidth(width + 16);
+ local zone,_ = FishingBuddy.GetZoneInfo();
+ if ( zone == FishingBuddy.STVZONENAME ) then
+ DoUpdatePOI();
+ STVUpdateTimer = UPDATETIME_SCHOOLS;
+ else
+ STVUpdateTimer = UPDATETIME_COUNTER;
+ end
+ end
+ end
+ else
+ FishingExtravaganzaFrame:Hide();
+ HidePOI();
+ end
+end
+
+local function GetObjectCoords(poi, index, numcolumns, texturewidth)
+ local width = poi:GetWidth();
+ local xCoord1, xCoord2, yCoord1, yCoord2;
+ local coordIncrement = width / texturewidth;
+ xCoord1 = mod(index , numcolumns) * coordIncrement;
+ xCoord2 = xCoord1 + coordIncrement;
+ yCoord1 = floor(index / numcolumns) * coordIncrement;
+ yCoord2 = yCoord1 + coordIncrement;
+ return xCoord1, xCoord2, yCoord1, yCoord2;
+end
+
+local start = 0;
+-- debugging routines
+FishingBuddy.Extravaganza.Debug = function(day, hour, zone)
+ STVDay = day;
+ STVStartHour = hour;
+ if ( zone ) then
+ FishingBuddy.STVZONENAME = zone;
+ end
+ IsTime(true);
+end
+
+-- eventually, display what fish you caught here
+FishingBuddy.Extravaganza.MiniMap_OnEnter = function()
+end
+
+-- test the extravaganze school marking functions
+-- need to expand this for 1.9 if we can tell automatically
+FishingBuddy.Commands["mark"] = {};
+FishingBuddy.Commands["mark"].func =
+ function(what)
+ if ( what == "reset" ) then
+ FishingBuddy_Info["FishSchools"] = nil;
+ elseif ( what == "debug" ) then
+ local hour,_ = GetGameTime();
+ local day = date("%w");
+ FishingBuddy.Extravaganza.Debug(day, hour);
+ elseif ( what == "test" ) then
+ FishingBuddy.Debug("mark test");
+ local coord = 0.005;
+ local rot = 1;
+ PlotPOI(1, 0, coord, rot, 16);
+ PlotPOI(2, coord, coord, rot, 16);
+ PlotPOI(3, coord, 0, rot, 16);
+ PlotPOI(4, -coord, 0, rot, 16);
+ PlotPOI(5, -coord, -coord, rot, 16);
+ PlotPOI(6, 0, -coord, rot, 16);
+ else
+ FishingBuddy.Extravaganza.MarkSchool();
+ end
+ return true;
+ end;
+
diff --git a/FishingExtravaganza.xml b/FishingExtravaganza.xml
new file mode 100644
index 0000000..d30e4ae
--- /dev/null
+++ b/FishingExtravaganza.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.Extravaganza.OnLoad();
+
+
+ FishingBuddy.Extravaganza.OnShow();
+
+
+ FishingBuddy.Extravaganza.OnEvent();
+
+
+ FishingBuddy.Extravaganza.OnUpdate(arg1);
+
+
+
+
+
+
+
+ FishingBuddy.Extravaganza.POI_OnUpdate(arg1);
+
+
+
+
diff --git a/FishingHoles.lua b/FishingHoles.lua
new file mode 100644
index 0000000..f1e9736
--- /dev/null
+++ b/FishingHoles.lua
@@ -0,0 +1,43 @@
+-- Support for Fishing Holes
+
+FishingBuddy.FishingHoles = {};
+
+-- Let's store fishing holes like this
+-- FishingBuddy_Info["FishingHoles"][ZONE]
+-- Store everything to two digits?
+
+local function IsFishingHole()
+ if ( GameTooltip:IsVisible() ) then
+ local text = getglobal("GameTooltipTextLeft1");
+ if ( text ) then
+ text = text:GetText();
+ -- let a partial match work (for translations)
+ if ( string.find(text, FishingBuddy.SCHOOL_OF) ) then
+ local s,e = string.find(text, FishingBuddy.SCHOOL_OF.." ");
+ if ( s ) then
+ if ( s > 1 ) then
+ text = string.sub(text, 1, s-1)..string.sub(fishie, e+1);
+ else
+ text = string.sub(text, e+1);
+ end
+ else
+ s,e = string.find(text, " "..FishingBuddy.SCHOOL_OF);
+ if ( s ) then
+ text = string.sub(text, 1, s-1)..string.sub(text, e+1);
+ end
+ end
+ return text;
+ end
+ end
+ end
+ return nil;
+end
+
+FishingBuddy.FishingHoles.CheckFishingHole = function()
+ local holename = IsFishingHole();
+ if ( holename ) then
+ -- find the name of the fish in our database if we can
+ -- if not, we can find it later, when we catch one
+ -- need translations for the other kinds of fishing holes
+ end
+end
diff --git a/FishingInit.lua b/FishingInit.lua
new file mode 100644
index 0000000..d9be2bb
--- /dev/null
+++ b/FishingInit.lua
@@ -0,0 +1,733 @@
+-- FishingBuddy
+--
+-- Everything you wanted support for in your fishing endeavors
+
+local gotSetupDone = false;
+local lastVersion;
+local playerName;
+local realmName;
+
+local DEFAULT_MINIMAP_POSITION = 256;
+
+local function tablecount(tab)
+ local n = 0;
+ for k,v in tab do
+ n = n + 1;
+ end
+ return n;
+end
+FishingBuddy.tablecount = tablecount;
+
+FishingBuddy.IsLoaded = function()
+ return gotSetupDone;
+end
+
+-- if the old information is still there, then we might not have per
+-- character saved info, so let's save it away just in case. It'll go
+-- away the second time we load the add-on
+FishingBuddy.SavePlayerInfo = function()
+ if ( FishingBuddy_Info[realmName] and
+ FishingBuddy_Info[realmName]["Settings"] and
+ FishingBuddy_Info[realmName]["Settings"][playerName] ) then
+ local tabs = { "Settings", "Outfit", "WasWearing" };
+ for _,tab in tabs do
+ for k,v in FishingBuddy_Player[tab] do
+ FishingBuddy_Info[realmName][tab][playerName][k] = v;
+ end
+ end
+ end
+end
+
+local FishingInit = {};
+
+-- Fill in the player name and realm
+FishingInit.SetupNameInfo = function()
+ playerName = UnitName("player");
+ realmName = GetRealmName();
+ return playerName, realmName;
+end
+
+FishingInit.CheckPlayerInfo = function()
+ local tabs = { "Settings", "Outfit", "WasWearing" };
+ if ( not FishingBuddy_Player ) then
+ FishingBuddy_Player = {};
+ for _,tab in tabs do
+ FishingBuddy_Player[tab] = { };
+ end
+ if ( FishingBuddy_Info[realmName] and
+ FishingBuddy_Info[realmName]["Settings"] and
+ FishingBuddy_Info[realmName]["Settings"][playerName] ) then
+ for _,tab in tabs do
+ if ( FishingBuddy_Info[realmName][tab] and
+ FishingBuddy_Info[realmName][tab][playerName] ) then
+ for k,v in FishingBuddy_Info[realmName][tab][playerName] do
+ FishingBuddy_Player[tab][k] = v;
+ end
+ end
+ end
+ end
+ elseif ( FishingBuddy_Info[realmName] and
+ FishingBuddy_Info[realmName]["Settings"] ) then
+ -- the saved information is there, kill the old stuff
+ for _,tab in tabs do
+ if ( FishingBuddy_Info[realmName][tab] ) then
+ FishingBuddy_Info[realmName][tab][playerName] = nil;
+ -- Duh, table.getn doesn't work because there
+ -- aren't any integer keys in this table
+ if ( next(FishingBuddy_Info[realmName][tab]) == nil ) then
+ FishingBuddy_Info[realmName][tab] = nil;
+ end
+ end
+ end
+ if ( next(FishingBuddy_Info[realmName]) == nil ) then
+ FishingBuddy_Info[realmName] = nil;
+ end
+ end
+end
+
+FishingInit.CheckPlayerSetting = function(setting, defaultvalue)
+ if ( not FishingBuddy_Player["Settings"] ) then
+ FishingBuddy_Player["Settings"] = { };
+ end
+ if ( not FishingBuddy_Player["Settings"][setting] ) then
+ FishingBuddy_Player["Settings"][setting] = defaultvalue;
+ end
+end
+
+FishingInit.CheckGlobalSetting = function(setting, defaultvalue)
+ if ( not FishingBuddy_Info[setting] ) then
+ if ( not defaultvalue ) then
+ FishingBuddy_Info[setting] = {};
+ else
+ FishingBuddy_Info[setting] = defaultvalue;
+ end
+ end
+end
+
+FishingInit.CheckRealm = function()
+ local tabs = { "Settings", "Outfit", "WasWearing" };
+ for _,tab in tabs do
+ if ( FishingBuddy_Info[tab] ) then
+ local old = FishingBuddy_Info[tab][playerName];
+ if ( old ) then
+ if ( not FishingBuddy_Info[realmName] ) then
+ FishingBuddy_Info[realmName] = { };
+ for _,tab in tabs do
+ FishingBuddy_Info[realmName][tab] = { };
+ end
+ end
+
+ FishingBuddy_Info[realmName][tab][playerName] = { };
+ for k, v in old do
+ FishingBuddy_Info[realmName][tab][playerName][k] = v;
+ end
+ FishingBuddy_Info[tab][playerName] = nil;
+ end
+
+ -- clean out cruft, if we have some
+ FishingBuddy_Info[tab][UNKNOWNOBJECT] = nil;
+ FishingBuddy_Info[tab][UKNOWNBEING] = nil;
+
+ -- Duh, table.getn doesn't work because there
+ -- aren't any integer keys in this table
+ if ( next(FishingBuddy_Info[tab]) == nil ) then
+ FishingBuddy_Info[tab] = nil;
+ end
+ end
+ end
+end
+
+FishingInit.SetupZoneMapping = function()
+ local continentNames = { GetMapContinents() };
+ if ( not FishingBuddy_Info["ZoneIndex"] ) then
+ FishingBuddy_Info["ZoneIndex"] = {};
+ for idx,name in continentNames do
+ local zones = { GetMapZones(idx) };
+ for jdx,zone in zones do
+ tinsert(FishingBuddy_Info["ZoneIndex"], zone);
+ end
+ end
+ end
+ if ( not FishingBuddy_Info["SubZones"] ) then
+ FishingBuddy_Info["SubZones"] = {};
+ end
+end
+
+FishingInit.UpdateFishingDB1 = function()
+ local version = FishingBuddy_Info["Version"];
+ if ( not version ) then
+ version = 7700; -- be really old
+ end
+
+ if ( FishingBuddy_Info["FishingHoles"] ) then
+ if ( version < 8300 ) then
+ -- handle a beta bug where we missed that GetSubZoneText() returns "" and not nil
+ for zone in FishingBuddy_Info["FishingHoles"] do
+ if ( FishingBuddy_Info["FishingHoles"][zone][""] ) then
+ if ( not FishingBuddy_Info["FishingHoles"][zone][zone] ) then
+ FishingBuddy_Info["FishingHoles"][zone][zone] = { };
+ end
+ for k,v in FishingBuddy_Info["FishingHoles"][zone][""] do
+ FishingBuddy_Info["FishingHoles"][zone][zone][k] = v;
+ end
+ FishingBuddy_Info["FishingHoles"][zone][""] = nil;
+ end
+ end
+ end
+
+ if ( version < 8503 ) then
+ local fh = FishingBuddy_Info["FishingHoles"];
+ local ff = FishingBuddy_Info["Fishies"];
+ for zone in fh do
+ for subzone in fh[zone] do
+ local crap = {};
+ for fishie in fh[zone][subzone] do
+ if ( type(fishie) == "string" ) then
+ tinsert(crap, fishie);
+ end
+ end
+ for _,fishie in crap do
+ if ( ff[fishie] ) then
+ local item = ff[fishie].item;
+ if ( item ) then
+ local _,_,id = string.find(item, "^(%d+):");
+ id = id + 0;
+ fh[zone][subzone][id] = fh[zone][subzone][fishie];
+ fh[zone][subzone][fishie] = nil;
+ end
+ end
+ end
+ end
+ end
+ local fishes = {};
+ for fishie in ff do
+ if ( type(fishie) == "string" ) then
+ tinsert(fishes, fishie);
+ end
+ end
+ for _,fishie in fishes do
+ local item = ff[fishie].item;
+ if ( item ) then
+ local _,_,id = string.find(item, "^(%d+):");
+ id = id + 0;
+ ff[id] = {};
+ ff[id].name = fishie;
+ for k,v in ff[fishie] do
+ if ( k ~= "item" ) then
+ ff[id][k] = v;
+ end
+ end
+ ff[fishie] = nil;
+ end
+ end
+ -- tracking information
+ local ft = FishingBuddy_Info["FishTracking"];
+ for how in ft do
+ local fishes = {};
+ for item in ft[how] do
+ if ( type(item) == "string" ) then
+ tinsert(fishes, item);
+ end
+ end
+ for _,item in fishes do
+ local _,_,id = string.find(item, "^(%d+):");
+ id = tonumber(id);
+ ft[how][id] = {};
+ for k,v in ft[how][item] do
+ ft[how][id][k] = v;
+ end
+ if ( ft[how][id].count ) then
+ ft[how][id].data = {};
+ for k,v in ft[how][id].count do
+ ft[how][id].data[k] = v;
+ end
+ ft[how][id].count = nil;
+ end
+ end
+ for _,item in fishes do
+ ft[how][item] = nil;
+ end
+ end
+ end
+ end
+
+ if ( version < 8504 ) then
+ -- Let's not store default colors for things
+ local ff = FishingBuddy_Info["Fishies"];
+ if ( ff ) then
+ for id in ff do
+ if ( ff[id].color and ff[id].color == "ffffffff" ) then
+ ff[id].color = nil;
+ end
+ end
+ end
+ end
+
+ if ( version < 8509 and FishingBuddy_Info["FishTracking"] ) then
+ local ft = FishingBuddy_Info["FishTracking"]["WEEKLY"];
+ for id,what in ft do
+ if ( not ft[id].data[52] ) then
+ ft[id].data[52] = 0;
+ table.setn(ft[id].data, 53);
+ end
+ end
+ end
+
+ if ( not FishingBuddy_Info["Locations"] ) then
+ return;
+ end
+
+ -- Duh, table.getn doesn't work because there aren't any integer
+ -- keys in this table
+ if ( next(FishingBuddy_Info["Locations"]) == nil ) then
+ FishingBuddy_Info["Locations"] = nil;
+ return;
+ end
+
+ FishingBuddy_Info["FishingHoles"] = { };
+ FishingBuddy_Info["FishingHoles"][FishingBuddy.UNKNOWN] = { };
+ for zone in FishingBuddy_Info["Locations"] do
+ FishingBuddy_Info["FishingHoles"][FishingBuddy.UNKNOWN][zone] = { };
+ local tab = FishingBuddy_Info["FishingHoles"][FishingBuddy.UNKNOWN][zone];
+ for k,v in FishingBuddy_Info["Locations"][zone] do
+ tab[k] = v;
+ end
+ end
+ FishingBuddy_Info["Locations"] = nil;
+end
+
+FishingInit.FixupNumericZones = function()
+ -- fix bad zones from FishSchools update bug
+ local badones;
+ local biggest = 0;
+ local hardfix = false;
+ for zidx,zone in FishingBuddy_Info["ZoneIndex"] do
+ if ( type(zone) ~= "string" ) then
+ if ( not badones ) then
+ badones = {};
+ end
+ badones[zidx] = zone;
+ if ( biggest < zidx ) then
+ biggest = zidx;
+ end
+ elseif ( biggest > 0 ) then
+ -- found a string after we started seeing numbers
+ hardfix = true;
+ end
+ end
+ if ( badones ) then
+ local fs = FishingBuddy_Info["FishingSkill"];
+ local fh = FishingBuddy_Info["FishingHoles"];
+ for bidx,gidx in badones do
+ if ( fs[bidx] ) then
+ for sidx,skill in fs[bidx] do
+ local z = FishingBuddy_Info["ZoneIndex"][gidx];
+ local sz = FishingBuddy_Info["SubZones"][gidx][sidx];
+ FishingBuddy.SetZoneLevel(z, sz, fs[bidx][gidx]);
+ end
+ end
+ if ( fh[bidx] ) then
+ if ( not fh[gidx] ) then
+ fh[gidx] = {};
+ end
+ for sidx,fishies in fh[bidx] do
+ for id,cnt in fishies do
+ if ( fh[gidx] and
+ fh[gidx][sidx] and
+ fh[gidx][sidx][id] ) then
+ fh[gidx][sidx][id] = fh[gidx][sidx][id] + cnt;
+ else
+ if ( not fh[gidx] ) then
+ fh[gidx] = {};
+ end
+ if ( not fh[gidx][sidx] ) then
+ fh[gidx][sidx] = {};
+ end
+ fh[gidx][sidx][id] = cnt;
+ end
+ end
+ end
+ end
+ end
+ if ( not hardfix ) then
+ -- these are already in numerical order
+ local count = table.getn(FishingBuddy_Info["ZoneIndex"]);
+ for idx=count,1,-1 do
+ if ( badones[idx] ) then
+ table.remove(FishingBuddy_Info["ZoneIndex"], idx);
+ FishingBuddy_Info["FishingSkill"][idx] = nil;
+ FishingBuddy_Info["FishingHoles"][idx] = nil;
+ FishingBuddy_Info["SubZones"][idx] = nil;
+ end
+ end
+ else
+ local fixers = { "FishingSkill", "FishingHoles", "SubZones" };
+ -- okay, this gonna be tough
+ -- strip out the numbers after the string
+ while ( badones ) do
+ local count = table.getn(FishingBuddy_Info["ZoneIndex"]);
+ local gotstring = false;
+ local sidx;
+ for idx=count,1,-1 do
+ if ( not gotstring ) then
+ if (type(fh[idx]) ~= "string" ) then
+ table.remove(FishingBuddy_Info["ZoneIndex"], idx);
+ for _,k in fixers do
+ FishingBuddy_Info[k][idx] = nil;
+ end
+ badones[idx] = nil;
+ else
+ gotstring = true;
+ sidx = idx;
+ end
+ end
+ end
+ if ( next(badones) == nil) then
+ badones = nil;
+ end
+ if ( sidx and sidx ~= count ) then
+ count = table.getn(FishingBuddy_Info["ZoneIndex"]);
+ local fidx = 1;
+ while ( fidx < count and type(FishingBuddy_Info["ZoneIndex"][fidx] == "string" ) ) do
+ fidx = fidx + 1;
+ end
+ for k,v in FishingBuddy_Info["ZoneIndex"][sidx] do
+ FishingBuddy_Info["ZoneIndex"][fidx][k] = v;
+ end
+ FishingBuddy_Info["ZoneIndex"][sidx] = nil;
+ for _,f in fixers do
+ for k,v in FishingBuddy_Info[f][sidx] do
+ FishingBuddy_Info[f][fidx][k] = v;
+ end
+ FishingBuddy_Info[f][sidx] = nil;
+ end
+ else
+ -- if it's not already nil, we're in trouble
+ badones = nil;
+ end
+ end
+ end
+ end
+end
+
+FishingInit.UpdateFishingDB2 = function()
+ local version = FishingBuddy_Info["Version"];
+ if ( not version ) then
+ version = 7700; -- be really old
+ end
+
+ -- track the weekly fish that got missed at the end of the year
+ if ( version < 8509 and FishingBuddy.ByFishie ) then
+ local ft = FishingBuddy_Info["FishTracking"]["WEEKLY"];
+ for id,what in ft do
+ if ( FishingBuddy.ByFishie[id] ) then
+ local total = 0;
+ for _,count in FishingBuddy.ByFishie[id] do
+ total = total + count;
+ end
+ local tracked = 0;
+ local limit = table.getn(what.data)-1;
+ for i=0,limit do
+ tracked = tracked + what.data[i];
+ end
+ local diff = total - tracked;
+ if ( diff > 0 ) then
+ ft[id].data[52] = ft[id].data[52] + diff;
+ end
+ end
+ end
+ end
+
+ -- version < 8700
+ local needCollapse = true;
+ if ( FishingBuddy_Info["Schools"] ) then
+ -- convert zone coords into minimap coords
+ local STVInfo = { scale = 0.18128603034401,
+ xoffset = 0.39145470225916, yoffset = 0.79412224886668 };
+ local tastyfish_id = 19807;
+
+ local addschool = FishingBuddy.Schools.AddFishingSchool;
+ local zone = FishingBuddy.STVZONENAME;
+ for _,pools in FishingBuddy_Info["Schools"] do
+ for idx,entry in pools do
+ local t;
+ local x = (entry.x - STVInfo.xoffset) / STVInfo.scale;
+ local y = (entry.y - STVInfo.yoffset) / STVInfo.scale;
+ addschool(FishingBuddy.SCHOOL_TASTY, 19807, zone, x, y);
+ end
+ end
+ FishingBuddy_Info["Schools"] = nil;
+ needCollapse = nil;
+ end
+
+ if ( version < 8701 ) then
+ FishingBuddy.SetSetting("FastCast", nil);
+ end
+
+ if ( version < 8703 ) then
+ local azi = FishingBuddy.AddZoneIndex;
+ if ( FishingBuddy_Info["FishingSkill"] ) then
+ didsomething = false;
+ local fixit = false;
+ for zone,info in FishingBuddy_Info["FishingSkill"] do
+ if ( type(zone) == "string" ) then
+ fixit = true;
+ break;
+ end
+ end
+ if ( fixit ) then
+ local newskills = {};
+ for zone,info in FishingBuddy_Info["FishingSkill"] do
+ local zidx = azi(zone);
+ newskills[zidx] = {};
+ for subzone,count in info do
+ local _,sidx = azi(zone,subzone);
+ newskills[zidx][sidx] = count;
+ end
+ FishingBuddy_Info["FishingSkill"][zone] = nil;
+ end
+ FishingBuddy_Info["FishingSkill"] = newskills;
+ end
+ end
+
+ if ( FishingBuddy_Info["FishingHoles"] ) then
+ local fixit = false;
+ for zone,info in FishingBuddy_Info["FishingHoles"] do
+ if ( type(zone) == "string" ) then
+ fixit = true;
+ break;
+ end
+ end
+ if ( fixit ) then
+ local newholes = {};
+ for zone,info in FishingBuddy_Info["FishingHoles"] do
+ local zidx = azi(zone);
+ newholes[zidx] = {};
+ for subzone,stuff in info do
+ local _,sidx = azi(zone,subzone);
+ newholes[zidx][sidx] = stuff;
+ end
+ FishingBuddy_Info["FishingHoles"][zone] = nil;
+ end
+ FishingBuddy_Info["FishingHoles"] = newholes;
+ end
+ end
+ end
+
+ if ( version < 8704 and needCollapse ) then
+ if ( FishingBuddy_Info["FishSchools"] ) then
+ local azi = FishingBuddy.AddZoneIndex;
+ local fixit = false;
+ for zone,info in FishingBuddy_Info["FishSchools"] do
+ if ( type(zone) == "string" ) then
+ fixit = true;
+ break;
+ end
+ end
+ if ( fixit ) then
+ local newschools = {};
+ for zone,info in FishingBuddy_Info["FishSchools"] do
+ local zidx = azi(zone);
+ newschools[zidx] = {};
+ for idx,entry in info do
+ tinsert(newschools[zidx], entry);
+ end
+ FishingBuddy_Info["FishSchools"][zone] = nil;
+ end
+ FishingBuddy_Info["FishSchools"] = newschools;
+ end
+ end
+ FishingBuddy.Schools.CollapseHoles();
+ end
+
+ if ( version < 8707 ) then
+ FishingInit.FixupNumericZones();
+ end
+
+ if ( version < 8712 ) then
+ local ft = FishingBuddy_Info["FishTracking"];
+ for how,info in ft do
+ for id,what in ft[how] do
+ what.plot = 1;
+ end
+ end
+ end
+
+ -- save this for other pieces that might need to update
+ lastVersion = version;
+
+ FishingBuddy_Info["Version"] = FishingBuddy.CURRENTVERSION;
+end
+
+FishingBuddy.GetLastVersion = function()
+ return lastVersion;
+end
+
+-- Based on code in QuickMountEquip
+FishingInit.HookFunction = function(func, newfunc)
+ local oldValue = getglobal(func);
+ if ( oldValue ~= getglobal(newfunc) ) then
+ setglobal(func, getglobal(newfunc));
+ return true;
+ end
+ return false;
+end
+
+-- set up alternate view of fish data. do this as startup to
+-- lower overall dynamic hit when loading the window
+FishingInit.SetupByFishie = function()
+ if ( not FishingBuddy.ByFishie ) then
+ local fh = FishingBuddy_Info["FishingHoles"];
+ local ff = FishingBuddy_Info["Fishies"];
+ FishingBuddy.ByFishie = { };
+ FishingBuddy.SortedFishies = { };
+ for zidx in fh do
+ local zone = FishingBuddy_Info["ZoneIndex"][zidx];
+ for sidx in fh[zidx] do
+ local subzone = FishingBuddy_Info["SubZones"][zidx][sidx];
+ local indexer = zidx.."."..sidx;
+ for id in fh[zidx][sidx] do
+ local quantity = fh[zidx][sidx][id];
+ if ( not FishingBuddy.ByFishie[id] ) then
+ FishingBuddy.ByFishie[id] = { };
+ tinsert(FishingBuddy.SortedFishies,
+ { text = ff[id].name, id = id });
+ end
+
+ if ( not FishingBuddy.ByFishie[id][indexer] ) then
+ FishingBuddy.ByFishie[id][indexer] = quantity;
+ else
+ FishingBuddy.ByFishie[id][indexer] = FishingBuddy.ByFishie[id][indexer] + quantity;
+ end
+ end
+ end
+ end
+ FishingBuddy.FishSort(FishingBuddy.SortedFishies, true);
+ end
+end
+
+FishingInit.InitSortHelpers = function()
+ local fh = FishingBuddy_Info["FishingHoles"];
+ FishingBuddy.SortedZones = {};
+ FishingBuddy.SortedByZone = {};
+ FishingBuddy.SortedSubZones = {};
+ for zidx,zone in FishingBuddy_Info["ZoneIndex"] do
+ tinsert(FishingBuddy.SortedZones, zone);
+ FishingBuddy.SortedByZone[zone] = {};
+ if ( fh[zidx] ) then
+ for sidx in fh[zidx] do
+ local subzone = FishingBuddy_Info["SubZones"][zidx][sidx];
+ tinsert(FishingBuddy.SortedByZone[zone], subzone);
+ tinsert(FishingBuddy.SortedSubZones, subzone);
+ end
+ table.sort(FishingBuddy.SortedByZone[zone]);
+ end
+ end
+ table.sort(FishingBuddy.SortedZones);
+ table.sort(FishingBuddy.SortedSubZones);
+end
+
+FishingInit.InitSettings = function()
+ if( not FishingBuddy_Info ) then
+ FishingBuddy_Info = { };
+ end
+ -- global stuff
+ FishingInit.SetupZoneMapping();
+ FishingInit.UpdateFishingDB1();
+ FishingInit.CheckRealm();
+
+ FishingInit.CheckGlobalSetting("ImppDBLoaded", 0);
+ FishingInit.CheckGlobalSetting("FishInfo2", 0);
+ FishingInit.CheckGlobalSetting("DataFish", 0);
+ FishingInit.CheckGlobalSetting("FishingHoles");
+ FishingInit.CheckGlobalSetting("FishingSkill");
+ FishingInit.CheckGlobalSetting("Fishies");
+ FishingInit.CheckGlobalSetting("HiddenFishies");
+
+ FishingInit.CheckPlayerInfo();
+
+ -- per user stuff
+ if ( not FishingBuddy_Player["Settings"] ) then
+ FishingBuddy_Player["Settings"] = { };
+ end
+ if ( FishingBuddy.InitTracking ) then
+ FishingBuddy.InitTracking();
+ end
+ FishingInit.UpdateFishingDB2();
+ FishingInit.SetupByFishie();
+ FishingInit.InitSortHelpers();
+end
+
+FishingInit.RegisterMyAddOn = function()
+ -- Register the addon in myAddOns
+ if (myAddOnsFrame_Register) then
+ local details = {
+ name = FishingBuddy.ID,
+ description = FishingBuddy.DESCRIPTION,
+ version = FishingBuddy.VERSION,
+ releaseDate = 'July 21, 2005',
+ author = 'Sutorix',
+ email = 'Windrunner',
+ category = MYADDONS_CATEGORY_PROFESSIONS,
+ frame = "FishingBuddy",
+ optionsframe = "FishingBuddyFrame",
+ };
+ local help = "";
+ for _,line in FishingBuddy.HELPMSG do
+ if ( type(line) == "table" ) then
+ for _,l in line do
+ help = help.."\n"..l;
+ end
+ else
+ help = help.."\n"..line;
+ end
+ end
+ myAddOnsFrame_Register(details, { help });
+ end
+end
+
+FishingInit.RegisterHandlers = function()
+ temp = ToggleMinimap;
+ if ( FishingInit.HookFunction("ToggleMinimap", "FishingBuddy_ToggleMinimap") ) then
+ FishingBuddy.SavedToggleMinimap = temp;
+ end
+ FishingBuddy.TrapWorldMouse()
+end
+
+local WOW = {};
+FishingBuddy.WOWVersion = function()
+ return WOW.major, WOW.minor, WOW.dot;
+end
+
+FishingBuddy.Initialize = function()
+ -- Set everything up, then dump the code we don't need anymore
+ playerName, realmName = FishingInit.SetupNameInfo();
+ if ( FishingInit ) then
+ if ( GetBuildInfo ) then
+ local v, b, d = GetBuildInfo();
+ WOW.build = b;
+ WOW.date = d;
+ local s,e,maj,min,dot = string.find("(%d+).(%d+).(%d+)", v);
+ WOW.major = tonumber(maj);
+ WOW.minor = tonumber(min);
+ WOW.dot = tonumber(dot);
+ else
+ FishingBuddy.Is10900 = true;
+ end
+ FishingInit.RegisterHandlers();
+ FishingInit.InitSettings();
+ -- register with myAddOn
+ FishingInit.RegisterMyAddOn();
+ -- clean out some beta trash
+ FishingBuddy.SetSetting("ClockOffset", nil);
+
+ FishingBuddy.Schools.Init();
+
+ gotSetupDone = true;
+ FishingBuddy.WatchUpdate();
+ -- debugging state
+ FishingBuddy.Debugging = FishingBuddy.GetSetting("FishDebug");
+ -- we don't need these functions anymore, gc 'em
+ FishingInit = nil;
+ end
+end
diff --git a/FishingLocationsFrame.lua b/FishingLocationsFrame.lua
new file mode 100644
index 0000000..4f4aa0d
--- /dev/null
+++ b/FishingLocationsFrame.lua
@@ -0,0 +1,664 @@
+-- Handle displaying all the fish in their habitats
+
+FishingBuddy.Locations = {};
+
+local NUM_THINGIES_DISPLAYED = 20;
+FishingBuddy.Locations.FRAME_THINGIEHEIGHT = 16;
+
+local Collapsed = false;
+local LocationLineSelected = 0;
+local LocationLines = {};
+local LocationLastLine = 1;
+
+local function MakeInfo(line, level, collapsible, expanded, hasicon, text, tipinfo, index, id)
+ if ( not LocationLines[line] ) then
+ LocationLines[line] = {};
+ end
+ LocationLines[line].level = level;
+ LocationLines[line].collapsible = collapsible;
+ LocationLines[line].expanded = expanded;
+ LocationLines[line].hasicon = hasicon;
+ LocationLines[line].text = text;
+ LocationLines[line].tipinfo = tipinfo;
+ if ( index ) then
+ LocationLines[line].index = index;
+ else
+ LocationLines[line].index = text;
+ end
+ LocationLines[line].id = id;
+ LocationLines[line].valid = true;
+end
+
+local function CountLocationLines()
+ local linecount = 0;
+ local j = 1;
+ local limit = LocationLastLine;
+ while ( j <= limit ) do
+ local info = LocationLines[j];
+ j = j + 1;
+ if ( info and info.valid ) then
+ linecount = linecount + 1;
+ if ( info.collapsible and not info.expanded ) then
+ local i2 = LocationLines[j];
+ while ( i2 and i2.valid and (i2.level > info.level) ) do
+ j = j + 1;
+ i2 = LocationLines[j];
+ end
+ end
+ end
+ end
+ if ( linecount > 0 ) then
+ -- I have no idea why this works this way at all
+ if ( linecount > NUM_THINGIES_DISPLAYED and linecount < limit ) then
+ return linecount+1;
+ else
+ return linecount;
+ end
+ else
+ return 0;
+ end
+end
+
+local function FishCount(zone, subzone)
+ local zidx, sidx = FishingBuddy.GetZoneIndex(zone, subzone);
+ local count = 0;
+ local total = 0;
+ local fh = FishingBuddy_Info["FishingHoles"];
+ if( fh[zidx] and fh[zidx][sidx] ) then
+ for fishie in fh[zidx][sidx] do
+ count = count + 1;
+ total = total + fh[zidx][sidx][fishie];
+ end
+ end
+ return count, total;
+end
+FishingBuddy.FishCount = FishCount;
+
+local function FishiesChanged()
+ local fh = FishingBuddy_Info["FishingHoles"];
+ local ff = FishingBuddy_Info["Fishies"];
+ local line = 1
+ local fishcount = table.getn(FishingBuddy.SortedFishies);
+ local zonetotals = {};
+
+ for i=1,fishcount,1 do
+ local fishid = FishingBuddy.SortedFishies[i].id;
+ local fishname = FishingBuddy.StripRaw(ff[fishid].name);
+ local locsort = {};
+ local total = 0;
+ for indexer,count in FishingBuddy.ByFishie[fishid] do
+ local _,_,zidx,sidx = string.find(indexer, "(%d+).(%d+)");
+ zidx = tonumber(zidx);
+ sidx = tonumber(sidx);
+ if ( not zonetotals[zidx] ) then
+ if ( fh[zidx] and fh[zidx][sidx] ) then
+ local tot = 0;
+ local fi = fh[zidx][sidx];
+ for f in fi do
+ tot = tot + fi[f];
+ end
+ zonetotals[zidx] = tot;
+ end
+ end
+ local info = {};
+ if ( FishingBuddy_Info["SubZones"][zidx] ) then
+ if ( not FishingBuddy_Info["SubZones"][zidx][sidx] ) then
+ info.text = FishingBuddy_Info["ZoneIndex"][zidx];
+ else
+ info.text = FishingBuddy_Info["SubZones"][zidx][sidx];
+ end
+ else
+ info.text = FishingBuddy.UNKNOWN;
+ end
+ info.count = count;
+ info.total = zonetotals[zidx];
+ if ( not info.total or info.total == 0) then
+ info.total = 1;
+ end
+ tinsert(locsort, info);
+ total = total + count;
+ end
+ local tipinfo = {};
+ tipinfo.total = total;
+ if ( ff[fishid].level ) then
+ tipinfo.level = ff[fishid].level;
+ end
+ MakeInfo(line, 0, true, true, true, fishname, extra, nil, fishid);
+ line = line + 1;
+ FishingBuddy.FishSort(locsort);
+ for j=1,table.getn(locsort),1 do
+ local zone = locsort[j].text;
+ local amount = locsort[j].count;
+ local total = locsort[j].total;
+ local percent = format(" (%.1f%%)", ( amount / total ) * 100);
+ MakeInfo(line, 1, false, false, false, zone..percent, { amount = amount, total = total, title = zone });
+ line = line + 1;
+ end
+ end
+ LocationLastLine = line;
+end
+
+local function BothLocationsChanged()
+ local fh = FishingBuddy_Info["FishingHoles"];
+ local ff = FishingBuddy_Info["Fishies"];
+ local sorted = FishingBuddy.SortedZones;
+ local line = 1;
+ local zonecount = table.getn(sorted);
+ for i=1,zonecount,1 do
+ local zone = sorted[i];
+ local zidx = FishingBuddy.GetZoneIndex(zone);
+ if ( fh[zidx] ) then
+ local where = zone;
+ MakeInfo(line, 0, true, true, false, zone, nil, where);
+ line = line + 1;
+ local subsorted = FishingBuddy.SortedByZone[zone];
+ local subcount = table.getn(subsorted);
+ for s=1,subcount,1 do
+ local subzone = subsorted[s];
+ local count, total = FishCount(zone, subzone);
+ if ( total > 0 ) then
+ local zidx, sidx = FishingBuddy.GetZoneIndex(zone, subzone);
+ where = zone.."."..subzone;
+ local tipinfo = {};
+ tipinfo.types = count;
+ tipinfo.total = total;
+ if ( FishingBuddy_Info["FishingSkill"][zidx] and FishingBuddy_Info["FishingSkill"][zidx][sidx] ) then
+ tipinfo.skill = FishingBuddy_Info["FishingSkill"][zidx][sidx];
+ end
+ if ( fh[zidx][sidx] ) then
+ MakeInfo(line, 1, true, true, false, subzone, tipinfo, where);
+ line = line + 1;
+ local fishsort = {};
+ for fishid in fh[zidx][sidx] do
+ local info = {};
+ info.id = fishid;
+ info.text = FishingBuddy.StripRaw(ff[fishid].name);
+ info.count = fh[zidx][sidx][fishid];
+ tinsert(fishsort, info);
+ end
+ FishingBuddy.FishSort(fishsort);
+ for j=1,table.getn(fishsort),1 do
+ local fishie = fishsort[j].text;
+ local id = fishsort[j].id;
+ local amount = fishsort[j].count;
+ local percent = format(" (%.1f%%)", ( amount / total ) * 100);
+ MakeInfo(line, 2, false, false, true, fishie..percent, { amount = amount, total = total, title = fishie }, nil, id);
+ line = line + 1;
+ end
+ end
+ end
+ end
+ end
+ end
+ LocationLastLine = line;
+end
+
+local function SubZonesChanged()
+ local fh = FishingBuddy_Info["FishingHoles"];
+ local ff = FishingBuddy_Info["Fishies"];
+ local mapping = {};
+ for zone in fh do
+ for subzone in fh[zone] do
+ mapping[subzone] = zone;
+ end
+ end
+ local line = 1;
+ local zonecount = table.getn(FishingBuddy.SortedSubZones);
+ for i=1,zonecount,1 do
+ local subzone = FishingBuddy.SortedSubZones[i];
+ local zone = mapping[subzone];
+ local count, total = FishCount(zone, subzone);
+ if ( total > 0 ) then
+ local zidx, sidx = FishingBuddy.GetZoneIndex(zone, subzone);
+ local tipinfo = nil;
+ if ( FishingBuddy_Info["FishingSkill"][zidx] and FishingBuddy_Info["FishingSkill"][zidx][sidx] ) then
+ tipinfo = { skill = FishingBuddy_Info["FishingSkill"][zidx][sidx] };
+ end
+ MakeInfo(line, 0, true, true, false, subzone, tipinfo);
+ line = line + 1;
+ local fishsort = {};
+ for fishid in fh[zidx][sidx] do
+ local info = {};
+ info.id = fishid;
+ info.text = FishingBuddy.StripRaw(ff[fishid].name);
+ info.count = fh[zidx][sidx][fishid];
+ tinsert(fishsort, info);
+ end
+ FishingBuddy.FishSort(fishsort);
+ for j=1,table.getn(fishsort),1 do
+ local id = fishsort[j].id;
+ local fishie = fishsort[j].text;
+ local amount = fishsort[j].count;
+ local percent = format(" (%.1f%%)", ( amount / total ) * 100);
+ MakeInfo(line, 1, false, false, true, fishie..percent, { amount = amount, total = total, title = fishie} , nil, id);
+ line = line + 1;
+ end
+ end
+ end
+ LocationLastLine = line;
+end
+
+local function LinesChanged()
+ if ( FishingBuddy.GetSetting("GroupByLocation") == 1 ) then
+ if ( FishingBuddy.GetSetting("ShowLocationZones") == 1 ) then
+ BothLocationsChanged();
+ else
+ SubZonesChanged();
+ end
+ else
+ FishiesChanged();
+ end
+ for i=LocationLastLine,table.getn(LocationLines) do
+ local info = LocationLines[i];
+ if ( info ) then
+ info.valid = false;
+ end
+ end
+ FishingLocationsFrame.valid = true;
+end
+
+-- local MOUSEWHEEL_DELAY = 0.1;
+-- local lastScrollTime = nil;
+-- function FishingLocationsFrame_OnMouseWheel(value)
+-- local now = GetTime();
+-- if ( not lastScrollTime ) then
+-- lastScrollTime = now - 0.2;
+-- end
+-- if ( (now - lastScrollTime) > MOUSEWHEEL_DELAY ) then
+-- -- call the old mouse wheel function somehow?
+-- end
+-- end
+
+function FishingLocationsFrame_SetSelection(id, line)
+ local info = LocationLines[line];
+ FishingLocationHighlightFrame:Hide();
+ if info then
+ if ( info.collapsible ) then
+ info.expanded = not info.expanded;
+ else
+ LocationLineSelected = line;
+ FishingLocationHighlightFrame:SetPoint ( "TOPLEFT" , getglobal("FishingLocations"..id):GetName() , "TOPLEFT" , 5 , 0 )
+ FishingLocationHighlightFrame:Show()
+ end
+ end
+end
+
+function FishingLocationsFrame_MoveButtonText(i, what)
+ local relativeTo = "FishingLocations"..i..what;
+ local textfield = getglobal("FishingLocations"..i.."Text");
+ textfield:SetPoint("LEFT", relativeTo, "RIGHT", 2, 0);
+end
+
+FishingBuddy.Locations.Update = function(forced)
+ if ( not FishingLocationsFrame:IsVisible() ) then
+ return;
+ end
+
+ if ( forced or not FishingLocationsFrame.valid ) then
+ LinesChanged();
+ end
+
+ local offset = FauxScrollFrame_GetOffset(FishingLocsScrollFrame);
+ FauxScrollFrame_Update( FishingLocsScrollFrame, CountLocationLines(),
+ NUM_THINGIES_DISPLAYED,
+ FishingBuddy.Locations.FRAME_THINGIEHEIGHT,
+ nil, nil, nil,
+ FishingLocationHighlightFrame,
+ 230, 230
+ );
+
+ local lastlevel = 0;
+ FishingLocationHighlightFrame:Hide();
+ local j = 1;
+ local o = 1;
+ while ( o < offset ) do
+ local info = LocationLines[j];
+ if ( info ) then
+ j = j + 1;
+ o = o + 1;
+ if ( info.collapsible and not info.expanded ) then
+ local i2 = LocationLines[j];
+ while ( i2 and i2.level > info.level ) do
+ j = j + 1;
+ i2 = LocationLines[j];
+ end
+ end
+ end
+ end
+ for i = 1,NUM_THINGIES_DISPLAYED,1 do
+ local locButton = getglobal ( "FishingLocations"..i );
+ local info = LocationLines[j];
+ if ( info and info.valid ) then
+ local icon = getglobal("FishingLocations"..i.."Icon");
+ local icontex = getglobal("FishingLocations"..i.."IconTexture");
+ locButton.id = i;
+ locButton.line = j;
+
+ local leveloffset = (info.level - lastlevel)*16;
+ if ( i == 1 ) then
+ locButton:SetPoint("TOPLEFT", leveloffset+25, -100);
+ else
+ local t = i - 1;
+ locButton:SetPoint("TOPLEFT", "FishingLocations"..t, "BOTTOMLEFT", leveloffset, 0);
+ end
+ lastlevel = info.level;
+
+ local text = info.text;
+ if text and info.extra then
+ text = text .. info.extra;
+ end
+ locButton.tipinfo = info.tipinfo;
+
+ icon:ClearAllPoints();
+ if ( info.collapsible ) then
+ icon:SetPoint("LEFT", "FishingLocations"..i, "LEFT", 21, 0);
+ locButton:SetTextColor( 1, 0.82, 0 );
+ if ( info.expanded ) then
+ locButton:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up");
+ else
+ locButton:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
+ end
+ getglobal("FishingLocations"..i.."Highlight"):SetTexture("Interface\\Buttons\\UI-PlusButton-Hilight");
+ getglobal("FishingLocations"..i):UnlockHighlight();
+ else
+ icon:SetPoint("LEFT", "FishingLocations"..i, "LEFT", 3, 0);
+ locButton:SetTextColor( .5, .5, .5 );
+ locButton:SetNormalTexture("");
+ getglobal("FishingLocations"..i.."Highlight"):SetTexture("");
+ -- Place the highlight and lock the highlight state
+ if ( LocationLineSelected == j ) then
+ FishingLocationHighlightFrame:SetPoint("TOPLEFT", "FishingLocations"..i, "TOPLEFT", 21, 0);
+ FishingLocationHighlightFrame:Show();
+ locButton:LockHighlight();
+ else
+ locButton:UnlockHighlight();
+ end
+ end
+
+ locButton.tooltip = nil;
+ if ( info.hasicon ) then
+ local item, texture, _, _, _ = FishingBuddy.GetFishie(info.id);
+ locButton.item = item;
+ locButton.fishid = info.id;
+ locButton.name = info.text;
+ if( texture ) then
+ icontex:SetTexture(texture);
+ icon:Show();
+ icontex:Show();
+ end
+ FishingLocationsFrame_MoveButtonText(i, "Icon");
+ else
+ locButton.item = nil;
+ locButton.fishid = nil;
+ locButton.name = nil;
+ icontex:SetTexture("");
+ icontex:Hide();
+ icon:Hide();
+ FishingLocationsFrame_MoveButtonText(i, "Highlight");
+ end
+
+ if ( info.tipinfo ) then
+ local color = FishingBuddy.Colors.GREEN;
+ if ( locButton.item and
+ not FishingBuddy.IsLinkableItem(locButton.item) ) then
+ color = FishingBuddy.Colors.RED;
+ end
+ text = text.."|c"..color.."*|r";
+ end
+ locButton:SetText( text );
+ locButton:Show();
+ j = j + 1;
+ if ( info.collapsible and not info.expanded ) then
+ local i2 = LocationLines[j];
+ while ( i2 and (i2.level > info.level) ) do
+ j = j + 1;
+ i2 = LocationLines[j];
+ end
+ end
+ else
+ locButton:Hide();
+ locButton.id = nil;
+ locButton.line = nil;
+ end
+ end
+
+ if ( LocationLines ) then
+ -- Set the expand/collapse all button texture
+ local numHeaders = 0;
+ local notExpanded = 0;
+ for i=1,table.getn(LocationLines),1 do
+ local j = i + offset;
+ local info = LocationLines[j];
+ if ( info and info.collapsible ) then
+ numHeaders = numHeaders + 1;
+ if ( not info.expanded ) then
+ notExpanded = notExpanded + 1;
+ end
+ end
+ end
+ FishingLocationsCollapseAllButton:Show();
+ -- If all headers are not expanded then show collapse button, otherwise show the expand button
+ if ( notExpanded ~= numHeaders ) then
+ Collapsed = false;
+ FishingLocationsCollapseAllButton:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up");
+ else
+ Collapsed = true;
+ FishingLocationsCollapseAllButton:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
+ end
+ else
+ FishingLocationsCollapseAllButton:Hide();
+ end
+end
+
+local function TrackFishToggle(fishid, how)
+ local tab = FishingBuddy_Info["FishTracking"][how];
+ if ( not tab[fishid] ) then
+ local ff = FishingBuddy_Info["Fishies"];
+ FishingBuddy.TrackThis(how, fishid, ff[fishid].color, ff[fishid].name);
+ else
+ if ( not tab[fishid].nevermore ) then
+ tab[fishid].nevermore = true;
+ else
+ tab[fishid].nevermore = nil;
+ end
+ end
+end
+
+local function MakeTrackFishToggle(fishid, how)
+ local id = fishid;
+ local h = how;
+ return function() TrackFishToggle(id, h); end;
+end
+
+local function TrackFishEntry(fishid, how)
+ local fi = FishingBuddy_Info["FishTracking"];
+ local info = {};
+ info.text = FishingBuddy["TRACKFISH"..how];
+ info.func = MakeTrackFishToggle(fishid, how);
+ info.checked = ( fi[how][fishid] and not fi[how][fishid].nevermore );
+ return info;
+end
+
+local function FishOptionsInitialize()
+ local menu = getglobal("FishingBuddyLocationsMenu");
+ if ( menu.fishid ) then
+ local fishid = menu.fishid;
+ local ff = FishingBuddy_Info["Fishies"];
+ UIDropDownMenu_AddButton(TrackFishEntry(fishid, "HOURLY"));
+ UIDropDownMenu_AddButton(TrackFishEntry(fishid, "WEEKLY"));
+
+ local info = {};
+ info.text = FishingBuddy.HIDEINWATCHER;
+ info.func = FishingBuddy.WatchFrame.MakeToggle(fishid);
+ info.checked = ( not FishingBuddy_Info["HiddenFishies"][fishid] );
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+FishingBuddy.Locations.Button_OnClick = function(button)
+ if ( button == "LeftButton" ) then
+ if( IsShiftKeyDown() and this.item ) then
+ FishingBuddy.ChatLink(this.item, this.name, this.color);
+ elseif ( this.id and this.line ) then
+ FishingLocationsFrame_SetSelection(this.id, this.line);
+ FishingBuddy.Locations.Update();
+ end
+ elseif ( this.fishid and button == "RightButton" ) then
+ local menu = getglobal("FishingBuddyLocationsMenu");
+
+ menu.fishid = this.fishid;
+ UIDropDownMenu_Initialize(menu, FishOptionsInitialize, "MENU");
+ FishingBuddy.ToggleDropDownMenu(1, nil, menu, this, 0, 0);
+ end
+end
+
+function FishingLocationsCollapseAllButton_OnClick()
+ if not Collapsed then
+ FishingLocsScrollFrameScrollBar:SetValue(0);
+ LocationLineSelected = 1;
+ end
+ for _,info in LocationLines do
+ info.expanded = Collapsed;
+ end
+ Collapsed = not Collapsed;
+ FishingBuddy.Locations.Update();
+end
+
+FishingBuddy.Locations.Button_OnEnter = function()
+ if( GameTooltip.locbutfini ) then
+ return;
+ end
+ if ( this.item or this.tooltip or this.tipinfo ) then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ end
+
+ local gottitle;
+ if( this.item or this.tooltip ) then
+ gottitle = true;
+ if ( this.item and this.item ~= "" ) then
+ if ( FishingBuddy.IsLinkableItem(this.item) ) then
+ GameTooltip:SetHyperlink("item:"..this.item);
+ else
+ this.tooltip = {}
+ this.tooltip[1] = { ["text"] = this.name };
+ this.tooltip[2] = { ["text"] = FishingBuddy.NOTLINKABLE, ["r"] = 1.0, ["g"] = 0, ["b"] = 0 };
+ FishingBuddy.AddTooltip(this.tooltip);
+ this.item = nil;
+ end
+ elseif ( this.tooltip ) then
+ FishingBuddy.AddTooltip(this.tooltip, 1, 1, 1);
+ end
+ end
+ if ( this.tipinfo ) then
+ local ti = this.tipinfo;
+ local line;
+ if ( ti.title ) then
+ GameTooltip:AddLine(ti.title);
+ elseif ( not gottitle ) then
+ GameTooltip:AddLine(this:GetText());
+ end
+ if ( ti.types ) then
+ GameTooltip:AddLine(string.format(FishingBuddy.FISHTYPES, ti.types));
+ end
+ if ( ti.amount ) then
+ line = string.format(FishingBuddy.CAUGHTTHISMANY, ti.amount);
+ end
+ if ( ti.total ) then
+ if ( not line ) then
+ line = "";
+ else
+ line = line.."/";
+ end
+ line = line..string.format(FishingBuddy.CAUGHTTHISTOTAL, ti.total);
+ end
+ if ( ti.percent ) then
+ if ( not line ) then
+ line = "";
+ else
+ line = line.." ";
+ end
+ line = line.."("..ti.percent.."%)";
+ end
+ if ( line ) then
+ GameTooltip:AddLine(line, 1, 1, 1);
+ end
+ if ( ti.skill ) then
+ line = string.format(FishingBuddy.MINIMUMSKILL, ti.skill);
+ GameTooltip:AddLine(line, 0, 1, 0);
+ end
+ end
+ GameTooltip.locbutfini = 1;
+ GameTooltip:Show();
+end
+
+FishingBuddy.Locations.Button_OnLeave = function()
+ if( this.item or this.tooltip or this.tipinfo ) then
+ GameTooltip:Hide();
+ end
+ GameTooltip.locbutfini = nil;
+end
+
+FishingBuddy.Locations.DisplayChanged = function()
+ FishingLocsScrollFrameScrollBar:SetValue(0);
+ LocationLineSelected = 1;
+ FishingBuddy.Locations.Update(true);
+end
+
+local function UpdateButtonDisplay()
+ if ( FishingBuddy.GetSetting("GroupByLocation") == 1 ) then
+ FishingLocationsSwitchButton:SetText(FishingBuddy.SHOWFISHIES);
+ FishingBuddyOptionSLZ:Show();
+ else
+ FishingLocationsSwitchButton:SetText(FishingBuddy.SHOWLOCATIONS);
+ FishingBuddyOptionSLZ:Hide();
+ end
+end
+
+FishingBuddy.Locations.SwitchDisplay = function()
+ -- backwards logic check, we're about to change...
+ local setting = FishingBuddy.GetSetting("GroupByLocation");
+ setting = 1 - setting;
+ FishingBuddy.SetSetting("GroupByLocation", setting);
+ UpdateButtonDisplay();
+ FishingBuddy.Locations.DisplayChanged();
+end
+
+FishingBuddy.Locations.SwitchButton_OnEnter = function()
+ if ( FishingBuddy.GetSetting("GroupByLocation") == 1 ) then
+ GameTooltip:SetText(FishingBuddy.SHOWFISHIES_INFO);
+ else
+ GameTooltip:SetText(FishingBuddy.SHOWLOCATIONS_INFO);
+ end
+ GameTooltip:Show();
+end
+
+FishingBuddy.Locations.OnLoad = function()
+ this:RegisterEvent("VARIABLES_LOADED");
+ FishingLocationsSwitchButton:SetText(FishingBuddy.SHOWFISHIES);
+ -- Set up checkbox
+ FishingBuddyOptionSLZ.name = "ShowLocationZones";
+ FishingBuddyOptionSLZ.text = FishingBuddy.CONFIG_SHOWLOCATIONZONES_ONOFF;
+ FishingBuddyOptionSLZ.tooltip = FishingBuddy.CONFIG_SHOWLOCATIONZONES_INFO;
+
+
+end
+
+FishingBuddy.Locations.OnShow = function()
+ if ( FishingBuddy.IsLoaded() ) then
+ UpdateButtonDisplay();
+ FishingBuddy.Locations.Update();
+ end
+end
+
+FishingBuddy.Locations.OnEvent = function()
+ -- this crashes the client when enabled
+ -- this:EnableMouseWheel(0);
+end
+
+FishingBuddy.Locations.DataChanged = function(zone, subzone, fishie)
+ FishingLocationsFrame.valid = false;
+end
+
+FishingBuddy.ShowLocLine = function(j)
+ FishingBuddy.Dump(LocationLines[j]);
+end
diff --git a/FishingLocationsFrame.xml b/FishingLocationsFrame.xml
new file mode 100644
index 0000000..a1f442b
--- /dev/null
+++ b/FishingLocationsFrame.xml
@@ -0,0 +1,590 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(0);
+ UIDropDownMenu_SetWidth(180);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.Locations.SwitchDisplay();
+
+
+ FishingBuddy.Locations.SwitchButton_OnEnter();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.CheckButton_OnClick();
+ FishingBuddy.Locations.DisplayChanged();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(this:GetFrameLevel() + 1);
+ getglobal(this:GetName()):SetText(ALL);
+
+
+ FishingLocationsCollapseAllButton_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GameTooltip:Hide();
+ FauxScrollFrame_OnVerticalScroll(FishingBuddy.Locations.FRAME_THINGIEHEIGHT, FishingBuddy.Locations.Update);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.Locations.OnLoad();
+
+
+ FishingBuddy.Locations.OnEvent();
+
+
+ FishingBuddy.Locations.OnShow();
+
+
+ -- FishingLocationsFrame_OnMouseWheel(arg1);
+ return;
+
+
+
+
diff --git a/FishingOptionsFrame.lua b/FishingOptionsFrame.lua
new file mode 100644
index 0000000..fca5ac7
--- /dev/null
+++ b/FishingOptionsFrame.lua
@@ -0,0 +1,214 @@
+-- Handle all the option settings
+
+FishingBuddy.OptionsFrame = {};
+
+FishingBuddy.CheckButton_OnShow = function()
+ this:SetChecked(FishingBuddy.GetSetting(this.name));
+ getglobal(this:GetName().."Text"):SetText(this.text);
+end
+
+local function CheckBox_Able(value, button)
+ local color;
+ if ( value == 1 ) then
+ button:Enable();
+ color = NORMAL_FONT_COLOR;
+ else
+ button:Disable();
+ color = GRAY_FONT_COLOR;
+ end
+ getglobal(button:GetName().."Text"):SetTextColor(color.r, color.g, color.b);
+end
+
+local function CheckButton_OnClick(checkbox, quiet)
+ local value = 0;
+ if ( not checkbox ) then
+ checkbox = this;
+ end
+ if ( checkbox:GetChecked() ) then
+ if ( not quiet ) then
+ PlaySound("igMainMenuOptionCheckBoxOn");
+ end
+ value = 1;
+ else
+ if ( not quiet ) then
+ PlaySound("igMainMenuOptionCheckBoxOff");
+ end
+ end
+ FishingBuddy.SetSetting(checkbox.name, value);
+ if ( checkbox.update ) then
+ checkbox.update();
+ end
+ if ( checkbox.deps ) then
+ for button,what in checkbox.deps do
+ if ( what == "d" ) then
+ CheckBox_Able(value, button);
+ elseif ( what == "h" ) then
+ button:Hide();
+ if ( value == 1 ) then
+ if ( not button.visible or button.visible() == 1 ) then
+ button:Show();
+ end
+ end
+ end
+ end
+ end
+end
+FishingBuddy.CheckButton_OnClick = CheckButton_OnClick;
+
+FishingBuddy.CheckButton_OnEnter = function()
+ local tooltip = this.tooltip;
+ if ( tooltip ) then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1);
+ GameTooltip:Show();
+ end
+end
+
+FishingBuddy.CheckButton_OnLeave = function()
+ GameTooltip:Hide();
+end
+
+FishingBuddy.OptionsFrame.Setup = function()
+ for name,option in FishingBuddy.OPTIONS do
+ local button = getglobal("FishingBuddyOption_"..name);
+ if ( button ) then
+ if ( option.v ) then
+ local enable = true;
+ if ( option.check ) then
+ enable = option.check();
+ end
+ button.name = name;
+ button.update = option.update;
+ if ( option.text ) then
+ button.text = option.text;
+ else
+ button.text = "";
+ end
+ button.tooltip = option.tooltip;
+ if ( enable ) then
+ button:SetChecked(FishingBuddy.GetSetting(name));
+ CheckBox_Able(1, button);
+ else
+ CheckBox_Able(0, button);
+ end
+ end
+ local showit = 1;
+ if ( option.visible ) then
+ button.visible = option.visible;
+ showit = button.visible();
+ end
+ if ( showit ) then
+ button:Show();
+ else
+ button:Hide();
+ end
+ if ( option.deps ) then
+ for n,what in option.deps do
+ local b = getglobal("FishingBuddyOption_"..n);
+ if ( b ) then
+ if ( not b.deps ) then
+ b.deps = {};
+ end
+ b.deps[button] = what;
+ end
+ end
+ end
+ end
+ end
+
+ -- now that we've collected all of the dependencies, handle them
+ for name,option in FishingBuddy.OPTIONS do
+ if ( option.v ) then
+ local button = getglobal("FishingBuddyOption_"..name);
+ if ( button ) then
+ CheckButton_OnClick(button, true);
+ end
+ end
+ end
+
+ if ( FishingBuddy.UseButtonHole() ) then
+ FishingBuddyOption_MinimapPosSlider:Hide();
+ end
+ local gs = FishingBuddy.GetSetting;
+ FishingBuddy.OptionsFrame.SetKeyValue("EasyCastKeys", gs("EasyCastKeys"));
+end
+
+FishingBuddy.OptionsFrame.SetClockValues = function(value)
+ FishingBuddy.SetClockOffset(value);
+ if ( FishingBuddy.ClockOffsets ) then
+ local menu = getglobal("FishingBuddyOption_ClockOffset");
+ local label = getglobal("FishingBuddyOption_ClockOffsetLabel");
+ UIDropDownMenu_SetWidth(60, menu);
+ local sel = 1;
+ if ( value == FishingBuddy.ClockOffsets[2] ) then
+ sel = 2;
+ end
+ UIDropDownMenu_SetSelectedValue(menu, sel);
+ UIDropDownMenu_SetText(value, menu);
+ label:SetText(FishingBuddy.OFFSET_LABEL_TEXT);
+ end
+ if ( FishingBuddy.ClockOffsets and
+ FishingBuddy.GetSetting("STVTimer") == 1 ) then
+ FishingBuddyOption_ClockOffset:Show();
+ else
+ FishingBuddyOption_ClockOffset:Hide();
+ end
+end
+
+local function ClockOffsetMenuSetup()
+ if ( FishingBuddy.ClockOffsets ) then
+ local clockoff = FishingBuddy.GetClockOffset();
+ for _,offset in FishingBuddy.ClockOffsets do
+ local off = offset;
+ local info = {};
+ info.text = string.format("%4d", offset);
+ info.func = function()
+ FishingBuddy.OptionsFrame.SetClockValues(off);
+ end;
+ info.checked = ( offset == clockoff )
+ UIDropDownMenu_AddButton(info);
+ end
+ end
+end
+
+FishingBuddy.OptionsFrame.OffsetMenuSetup = function()
+ UIDropDownMenu_Initialize(this, ClockOffsetMenuSetup);
+end
+
+FishingBuddy.OptionsFrame.SetKeyValue = function(what, value)
+ local show = FishingBuddy.Keys[value];
+ FishingBuddy.SetSetting(what, value);
+ local menu = getglobal("FishingBuddyOption_"..what);
+ if ( menu ) then
+ local label = getglobal("FishingBuddyOption_"..what.."Label");
+ UIDropDownMenu_SetWidth(90, menu);
+ UIDropDownMenu_SetSelectedValue(menu, show);
+ UIDropDownMenu_SetText(show, menu);
+ label:SetText(FishingBuddy.KEYS_LABEL_TEXT);
+ end
+end
+
+FishingBuddy.OptionsFrame.LoadKeyMenu = function(what)
+ local info = {};
+ local setting = FishingBuddy.GetSetting(what);
+ for value,label in FishingBuddy.Keys do
+ local v = value;
+ local w = what;
+ info.text = label;
+ info.func = function() FishingBuddy.OptionsFrame.SetKeyValue(w, v); end;
+ if ( setting == value ) then
+ info.checked = true;
+ else
+ info.checked = false;
+ end
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+FishingBuddy.OptionsFrame.KeyMenuSetup = function(what)
+ UIDropDownMenu_Initialize(this,
+ function()
+ local w = what;
+ FishingBuddy.OptionsFrame.LoadKeyMenu(what);
+ end);
+end
diff --git a/FishingOptionsFrame.xml b/FishingOptionsFrame.xml
new file mode 100644
index 0000000..e6c5612
--- /dev/null
+++ b/FishingOptionsFrame.xml
@@ -0,0 +1,341 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.CheckButton_OnShow();
+
+
+ FishingBuddy.CheckButton_OnClick();
+
+
+ FishingBuddy.CheckButton_OnEnter();
+
+
+ FishingBuddy.CheckButton_OnLeave();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.OptionsFrame.KeyMenuSetup("EasyCastKeys");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.OptionsFrame.OffsetMenuSetup();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(this:GetName().."Text"):SetText(FishingBuddy.MINIMAPBUTTONPLACEMENT);
+ getglobal(this:GetName().."High"):SetText();
+ getglobal(this:GetName().."Low"):SetText();
+ this:SetMinMaxValues(0, 360);
+ this:SetValueStep(1);
+ this.tooltipText = FishingBuddy.MINIMAPBUTTONPLACEMENTTOOLTIP;
+
+
+ local where = FishingBuddy.GetSetting("MinimapButtonPosition");
+ if (where) then
+ this:SetValue(where);
+ end
+
+
+ where = this:GetValue();
+ getglobal(this:GetName().."Text"):SetText(FishingBuddy.MINIMAPBUTTONPLACEMENT .. " - "..this:GetValue().."\194\176");
+ FishingBuddy.SetSetting("MinimapButtonPosition", where);
+ FishingBuddyMinimapButton_MoveButton();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterEvent("VARIABLES_LOADED");
+
+
+ FishingBuddy.OptionsFrame.Setup();
+
+
+ FishingBuddy.WatchUpdate();
+ FishingBuddy.UpdateMinimap();
+
+
+ return;
+
+
+
+
diff --git a/FishingOutfitFrame.lua b/FishingOutfitFrame.lua
new file mode 100644
index 0000000..e810387
--- /dev/null
+++ b/FishingOutfitFrame.lua
@@ -0,0 +1,259 @@
+-- Wrap OutfitDisplayFrame with our "improvements"
+FishingBuddy.OutfitFrame = {};
+
+local DEFAULTUPDATE_WAIT = 0.1;
+
+local function StylePoints(outfit)
+ local isp = FishingBuddy.OutfitManager.ItemStylePoints;
+ local points = 0;
+ if ( outfit )then
+ for slot in outfit do
+ if ( outfit[slot].item ) then
+ local _,_,check, enchant = string.find(outfit[slot].item,
+ "^(%d+):(%d+)");
+ points = points + isp(check, enchant);
+ end
+ end
+ end
+ return points;
+end
+
+local match;
+local function ItemBonusPoints(item)
+ local points = 0;
+ if ( item and item ~= "" ) then
+ if ( not match ) then
+ match = FishingBuddy.GetFishingSkillName().." %+(%d+)";
+ end
+ FishingOutfitTooltip:SetHyperlink("item:"..item);
+ local bodyslot = FishingOutfitTooltipTextLeft2:GetText();
+ local textline = 2;
+ while (bodyslot) do
+ local _,_,bonus = string.find(bodyslot, match);
+ if bonus then
+ points = points + bonus;
+ end
+ textline = textline + 1;
+ bodyslot = getglobal("FishingOutfitTooltipTextLeft"..textline):GetText();
+ end
+ -- See if the Eternium Fishing Line has been applied
+ local _,_,check, enchant = string.find(item, "^(%d+):(%d+)");
+ if ( enchant == "2603" ) then
+ points = points + 5;
+ end
+ end
+ return points;
+end
+
+local function BonusPoints(outfit)
+ local points = 0;
+ if ( outfit )then
+ for slot in outfit do
+ points = points + ItemBonusPoints(outfit[slot].item);
+ end
+ end
+ return points;
+end
+
+local function UpdateSwitchButton(outfit)
+ local msg = OutfitDisplayFrame_SwitchWillFail(FishingOutfitFrame, outfit);
+ if ( outfit and not msg ) then
+ FishingOutfitSwitchButton:Enable();
+ else
+ FishingOutfitSwitchButton:Disable();
+ end
+end
+
+-- outfit support functions
+local function GetWasWearing()
+ if FishingBuddy_Player["WasWearing"] then
+ return FishingBuddy_Player["WasWearing"];
+ end
+end
+
+local function SetWasWearing(outfit)
+ FishingBuddy_Player["WasWearing"] = outfit;
+end
+
+local function GetOutfit()
+ return FishingBuddy_Player["Outfit"];
+end
+
+local saved_outfit;
+local function SetOutfit(outfit)
+ saved_outfit = outfit;
+ FishingBuddy_Player["Outfit"] = outfit;
+end
+
+local updateWait = DEFAULTUPDATE_WAIT;
+FishingBuddy.OutfitFrame.Update = function(elapsed)
+ updateWait = updateWait - elapsed;
+ if ( updateWait <= 0 ) then
+ UpdateSwitchButton(saved_outfit);
+ FishingOutfitUpdate:Hide();
+ end
+end
+
+local function UpdateStyleInfo()
+ local points = BonusPoints(outfit);
+ if ( points >= 0 ) then
+ points = "+"..points;
+ else
+ points = 0 - points;
+ points = "-"..points;
+ end
+ FishingOutfitSkill:SetText(FishingBuddy.CONFIG_SKILL_TEXT..points);
+ points = StylePoints(outfit);
+ local pstring;
+ if ( points == 1 ) then
+ pstring = FishingBuddy.POINT;
+ else
+ pstring = FishingBuddy.POINTS;
+ end
+ FishingOutfitStyle:SetText(FishingBuddy.CONFIG_STYLISH_TEXT..points.." "..pstring);
+end
+
+local function OutfitChanged(button)
+ local outfit = OutfitDisplayFrame_GetOutfit(FishingOutfitFrame);
+ if ( outfit ) then
+ SetOutfit(outfit);
+ end
+ UpdateStyleInfo();
+ FishingOutfitFrame.valid = true;
+ updateWait = DEFAULTUPDATE_WAIT;
+ FishingOutfitUpdate:Show();
+end
+
+FishingBuddy.OutfitFrame.OnShow = function()
+ if ( not this.valid ) then
+ saved_outfit = GetOutfit();
+ end
+ OutfitDisplayFrame_SetOutfit(FishingOutfitFrame, saved_outfit);
+ UpdateSwitchButton(saved_outfit);
+ if ( not this.valid ) then
+ OutfitChanged();
+ end
+end
+
+FishingBuddy.OutfitFrame.OnLoad = function()
+ -- Handle the override
+ if ( OutfitDisplayFrame_OnLoad ) then
+ OutfitDisplayFrame_OnLoad();
+ FishingOutfitSkill.tooltip = FishingBuddy.CONFIG_SKILL_INFO;
+ FishingOutfitStyle.tooltip = FishingBuddy.CONFIG_STYLISH_INFO;
+ FishingOutfitSwitchButton:SetText(FishingBuddy.SWITCHOUTFIT);
+ FishingOutfitFrame.OutfitChanged = OutfitChanged;
+ else
+ FishingBuddy.DisableSubFrame("FishingOutfitFrame");
+ end
+end
+
+FishingBuddy.OutfitFrame.OnHide = function()
+ -- OutfitChanged();
+end
+
+local function ODF_Initialize()
+ OutfitDisplayFrame_SetOutfit(FishingOutfitFrame, saved_outfit);
+end
+
+-- the user has chosen us, make sure everything is set up the way we need
+local function ODF_Choose(useme)
+ if ( FishingOutfitFrame ) then
+ if ( useme ) then
+ FishingBuddy.EnableSubFrame("FishingOutfitFrame");
+ else
+ FishingBuddy.DisableSubFrame("FishingOutfitFrame");
+ end
+ end
+end
+FishingBuddy.OutfitFrame.Choose = ODF_Choose;
+
+-- only have one outfit at the moment
+-- don't switch if
+-- we can't find everything in the outfit
+-- we have saved stuff but we're not wearing everything in the outfit
+-- We don't have the outfit display frame!
+local function ODF_Switch()
+ if (CursorHasItem()) then
+ FishingBuddy.UIError(FishingBuddy.CURSORBUSYMSG);
+ return false;
+ end
+ if ( OutfitDisplayFrame_IsSwapping() ) then
+ FishingBuddy.UIError(OUTFITDISPLAYFRAME_TOOFASTMSG);
+ return false;
+ end
+
+ local isfishing = FishingBuddy.API.IsFishingPole();
+ local outfit = GetOutfit();
+ local waswearing = GetWasWearing();
+ if ( waswearing ) then
+ local msg;
+
+ if ( isfishing ) then
+ msg = OutfitDisplayFrame_SwitchWillFail(FishingOutfitFrame, waswearing);
+ else
+ msg = FishingBuddy.CANTSWITCHBACK;
+ SetWasWearing(nil);
+ StartedFishing = nil;
+ end
+
+ if ( msg ) then
+ FishingBuddy.UIError(msg);
+ return false;
+ end
+ local check = OutfitDisplayFrame_SwitchOutfit(waswearing);
+ if ( check ) then
+ SetWasWearing(nil);
+ FishingBuddy.OutfitManager.CheckSwitch(false);
+ end
+ elseif ( outfit ) then
+ local msg;
+ if ( not isfishing ) then
+ msg = OutfitDisplayFrame_SwitchWillFail(FishingOutfitFrame, outfit);
+ else
+ msg = FishingBuddy.POLEALREADYEQUIPPED;
+ end
+ if ( msg ) then
+ FishingBuddy.UIError(msg);
+ return false;
+ end
+ local waswearing = OutfitDisplayFrame_SwitchOutfit(outfit);
+ if ( waswearing ) then
+ SetWasWearing(waswearing);
+ FishingBuddy.OutfitManager.CheckSwitch(true);
+ end
+ else
+ FishingBuddy.UIError(FishingBuddy.NOOUTFITDEFINED);
+ end
+ return true;
+end
+
+FishingBuddy.OutfitFrame.Button_OnClick = function()
+ -- make sure we have the current state
+ SetOutfit(OutfitDisplayFrame_GetOutfit(FishingOutfitFrame));
+ ODF_Switch();
+end
+
+-- outfit debugging functions
+FishingBuddy.Commands["outfit"] = {};
+FishingBuddy.Commands["outfit"].func =
+ function(what)
+ if ( what and OutfitDisplayFrame_OnLoad ) then
+ if ( what == FishingBuddy.RESET ) then
+ SetWasWearing(nil);
+ elseif ( what == "dump" ) then
+ FishingBuddy.Debug("Outfit");
+ FishingBuddy.Dump(GetOutfit());
+ FishingBuddy.Debug("Was Wearing");
+ FishingBuddy.Dump(GetWasWearing());
+ end
+ end
+ return true;
+ end;
+
+if ( OutfitDisplayFrame_OnLoad ) then
+ FishingBuddy.OutfitManager.RegisterManager("OutfitDisplayFrame",
+ ODF_Initialize,
+ ODF_Choose,
+ ODF_Switch);
+end
diff --git a/FishingOutfitFrame.xml b/FishingOutfitFrame.xml
new file mode 100644
index 0000000..74b6358
--- /dev/null
+++ b/FishingOutfitFrame.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+ this:SetOwner(WorldFrame, "ANCHOR_NONE");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if ( this.tooltip ) then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ GameTooltip:SetText(this.tooltip, nil, nil, nil, nil, 1);
+ GameTooltip:Show();
+ end
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.OutfitFrame.Button_OnClick();
+
+
+ GameTooltip:SetText(FishingBuddy.SWITCHOUTFIT_INFO);
+ GameTooltip:Show();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+ FishingBuddy.OutfitFrame.Update(arg1);
+
+
+
+
+
+
+ FishingBuddy.OutfitFrame.OnLoad();
+
+
+ FishingBuddy.OutfitFrame.OnShow();
+
+
+ FishingBuddy.OutfitFrame.OnHide();
+
+
+ return;
+
+
+
+
diff --git a/FishingOutfitManager.lua b/FishingOutfitManager.lua
new file mode 100644
index 0000000..97d9e36
--- /dev/null
+++ b/FishingOutfitManager.lua
@@ -0,0 +1,184 @@
+-- Manage outfits, whether they're from OutfitDisplayFrame or something else
+FishingBuddy.OutfitManager = {};
+
+-- Inferred from Draznar's Fishing FAQ
+local Accessories = {
+ [19979] = { ["n"] = "Hook of the Master Angler", ["score"] = 5, },
+ [19947] = { ["n"] = "Nat Pagle's Broken Reel", ["score"] = 4, },
+ [19972] = { ["n"] = "Lucky Fishing Hat", ["score"] = 5, },
+ [7996] = { ["n"] = "Lucky Fishing Hat", ["score"] = 5, },
+ [8749] = { ["n"] = "Crochet Hat", ["score"] = 3, },
+ [19039] = { ["n"] = "Zorbin's Water Resistant Hat", ["score"] = 3, },
+ [3889] = { ["n"] = "Russet Hat", ["score"] = 3, },
+ [14584] = { ["n"] = "Dokebi Hat", ["score"] = 2, },
+ [4048] = { ["n"] = "Emblazoned Hat", ["score"] = 1, },
+ [10250] = { ["n"] = "Masters Hat of the Whale", ["score"] = 1, },
+ [9508] = { ["n"] = "Mechbuilder's Overalls", ["score"] = 3, },
+ [6263] = { ["n"] = "Blue Overalls", ["score"] = 4, },
+ [3342] = { ["n"] = "Captain Sander's Shirt", ["score"] = 4, },
+ [5107] = { ["n"] = "Deckhand's Shirt", ["score"] = 2, },
+ [6795] = { ["n"] = "White Swashbuckler's Shirt", ["score"] = 1, },
+ [2576] = { ["n"] = "White Linen Shirt", ["score"] = 1, },
+ [6202] = { ["n"] = "Fingerless Gloves", ["score"] = 3, },
+ [792] = { ["n"] = "Knitted Sandals", ["score"] = 4, },
+ [1560] = { ["n"] = "Bluegill Sandals", ["score"] = 4, },
+ [13402] = { ["n"] = "Timmy's Galoshes", ["score"] = 2, },
+ [10658] = { ["n"] = "Quagmire Galoshes", ["score"] = 2, },
+ [1678] = { ["n"] = "Black Ogre Kickers", ["score"] = 1, },
+ [19969] = { ["n"] = "Nat Pagle's Extreme Anglin' Boots", ["score"] = 5, },
+ [15405] = { ["n"] = "Shucking Gloves", ["score"] = 5, },
+ [15406] = { ["n"] = "Crustacean Boots", ["score"] = 3, },
+ [3287] = { ["n"] = "Tribal Pants", ["score"] = 2, },
+ [5310] = { ["n"] = "Sea Dog Britches", ["score"] = 4, },
+}
+
+FishingBuddy.Commands[FishingBuddy.SWITCH] = {};
+FishingBuddy.Commands[FishingBuddy.SWITCH].func = function()
+ FishingBuddy.OutfitManager.Switch();
+ return true;
+ end;
+
+local OutfitManagers = {};
+local OutfitManagerCount = 0;
+FishingBuddy.OutfitManager.RegisterManager = function(name, init, choose, switch)
+ if ( not OutfitManagers[name] ) then
+ OutfitManagers[name] = {};
+ OutfitManagerCount = OutfitManagerCount + 1;
+ end
+ OutfitManagers[name].Initialize = init;
+ OutfitManagers[name].Choose = choose;
+ OutfitManagers[name].Switch = switch;
+end
+
+FishingBuddy.OutfitManager.ItemStylePoints = function(itemno, enchant)
+ local points = 0;
+ if ( itemno ) then
+ itemono = tonumber(itemno);
+ enchant = tonumber(enchant);
+ if (Accessories[itemno]) then
+ points = points + Accessories[itemno].score;
+ end
+ if ( enchant == 846 ) then
+ -- bonus for being enchanted with Fishing +2
+ points = points + 2;
+ end
+ end
+ return points;
+end
+
+local PoleCheck = nil;
+
+-- update the watcher when we're done switching outfits
+FishingBuddy.OutfitManager.WaitForUpdate =
+ function(arg1)
+ local hasPole = FishingBuddy.API.IsFishingPole();
+ if ( hasPole == PoleCheck ) then
+ FishingOutfitUpdateFrame:Hide();
+ FishingBuddy.API.FishingMode();
+ end
+ end
+
+local function CheckSwitch(topole)
+ PoleCheck = topole;
+ FishingOutfitUpdateFrame:Show();
+end
+FishingBuddy.OutfitManager.CheckSwitch = CheckSwitch;
+
+local function HasManager()
+ return (OutfitManagerCount > 0);
+end
+FishingBuddy.OutfitManager.HasManager = HasManager;
+
+FishingBuddy.OutfitManager.Switch = function(outfitname)
+ if ( HasManager() ) then
+ local outfitter = FishingBuddy.GetSetting("OutfitManager");
+ if ( outfitter and OutfitManagers[outfitter] ) then
+ local wasPole = OutfitManagers[outfitter].Switch(outfitname);
+ CheckSwitch(not wasPole);
+ end
+ else
+ FishingBuddy.UIError(FishingBuddy.COMPATIBLE_SWITCHER);
+ end
+ -- if we're now sporting a fishing pole, let's go fishing
+ FishingBuddy.API.FishingMode();
+end
+
+local current_manager;
+
+local function OutfitManagerMenuSetup()
+ for manager,_ in OutfitManagers do
+ local mgr = manager;
+ local info = {};
+ info.text = manager;
+ info.func = function() FishingBuddy.OutfitManager.ChooseManager(mgr); end;
+ info.checked = ( current_manager == manager )
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+local function SetOutfitManagerDisplay()
+ if ( OutfitManagerCount == 0 ) then
+ FishingBuddyOption_OutfitMenu:Hide();
+ FishingBuddyOption_OutfitText:SetText(FishingBuddy.OUTFITS_TAB..": |c"..FishingBuddy.Colors.RED..FishingBuddy.NONEAVAILABLE_MSG.."|r");
+ elseif ( OutfitManagerCount == 1 ) then
+ FishingBuddyOption_OutfitMenu:Hide();
+ FishingBuddyOption_OutfitText:SetText(FishingBuddy.OUTFITS_TAB..": |c"..FishingBuddy.Colors.GREEN..current_manager.."|r");
+ else
+ FishingBuddyOption_OutfitText:Hide();
+ UIDropDownMenu_Initialize(FishingBuddyOption_OutfitMenu,
+ OutfitManagerMenuSetup);
+ local show = 1;
+ for name,_ in OutfitManagers do
+ if ( name == current_manager ) then
+ break;
+ end
+ show = show + 1;
+ end
+ local label = getglobal("FishingBuddyOption_OutfitMenuLabel");
+ label:SetText(FishingBuddy.OUTFITS_TAB..": ");
+ local menu = FishingBuddyOption_OutfitMenu;
+ UIDropDownMenu_SetWidth(210, menu);
+ UIDropDownMenu_SetSelectedValue(menu, show);
+ UIDropDownMenu_SetText(current_manager, menu);
+ end
+end
+
+local function ChooseManager(manager)
+ if ( manager and OutfitManagers[manager] ) then
+ current_manager = manager;
+ if ( not OutfitManagers[manager].initialized ) then
+ OutfitManagers[manager].Initialize();
+ OutfitManagers[manager].initialized = 1;
+ end
+ for om,info in OutfitManagers do
+ info.Choose(om == manager);
+ end
+ SetOutfitManagerDisplay();
+ return true;
+ end
+end
+FishingBuddy.OutfitManager.ChooseManager = ChooseManager;
+
+FishingBuddy.OutfitManager.Initialize = function()
+ -- no outfit managers, no outfit switching
+ if ( not HasManager() ) then
+ FishingBuddy.SetSetting("InfoBarClickToSwitch", 0);
+ FishingBuddy.SetSetting("TitanClickToSwitch", 0);
+ FishingBuddy.SetSetting("MinimapClickToSwitch", 0);
+ else
+ if ( OutfitManagerCount == 1 ) then
+ -- we pretty much have to use this one
+ current_manager = next(OutfitManagers);
+ else
+ current_manager = FishingBuddy.GetSetting("OutfitManager");
+ if ( not manager or not OutfitManagers[manager] ) then
+ -- no valid ones, use the first one
+ current_manager = next(OutfitManagers);
+ end
+ end
+ ChooseManager(current_manager);
+ -- in case we changed things (do we want/need to do this?)
+ -- FishingBuddy.SetSetting("OutfitManager", current_manager);
+ end
+ SetOutfitManagerDisplay();
+end
diff --git a/FishingOutfitManager.xml b/FishingOutfitManager.xml
new file mode 100644
index 0000000..2cd18f8
--- /dev/null
+++ b/FishingOutfitManager.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+ FishingBuddy.OutfitManager.WaitForUpdate(arg1);
+
+
+
+
diff --git a/FishingOutfitter.lua b/FishingOutfitter.lua
new file mode 100644
index 0000000..c1927a4
--- /dev/null
+++ b/FishingOutfitter.lua
@@ -0,0 +1,140 @@
+-- Interface with the Outfitter addon by mundocani
+
+local function OutfitterSwitch(outfitName)
+ -- this uses a static string of "Fishing" *not* the translation
+ local vOut, vCat, vInd = Outfitter_FindOutfitByStatID("Fishing");
+ if ( vOut ) then
+ local wasPole = FishingBuddy.API.IsFishingPole();
+ if ( wasPole ) then
+ Outfitter_RemoveOutfit(vOut);
+ else
+ vOut.Disabled = nil;
+ Outfitter_WearOutfit(vOut, vCat);
+ end
+ Outfitter_Update(true);
+ return wasPole;
+ end
+end
+
+local function CleanOutDuplicates(vName)
+ local count = 0;
+ for vCategoryID, vOutfits in gOutfitter_Settings.Outfits do
+ for vOutfitIndex, vOutfit in vOutfits do
+ if ( vOutfit.Name == vName ) then
+ count = count + 1;
+ end
+ end
+ end
+ if ( count > 0 ) then
+ -- nuke all of the outfits named 'Fishing Buddy' since they're
+ -- likely wrong, so that we can create a new 'good' one
+ local vOut,_,_ = Outfitter_FindOutfitByName(vName);
+ while ( vOut ) do
+ Outfitter_DeleteOutfit(vOut);
+ vOut,_,_ = Outfitter_FindOutfitByName(vName);
+ end
+ end
+end
+
+local function OutfitterInitialize()
+ if ( gOutfitter_Settings ) then
+ local vName = "Fishing Buddy";
+ CleanOutDuplicates(vName);
+ -- create the default fishing outfit, if it doesn't exist
+ local vOut,_,_ = Outfitter_FindOutfitByStatID("Fishing");
+ if ( not vOut ) then
+ vOut = Outfitter_GenerateSmartOutfit(vName, "Fishing", OutfitterItemList_GetEquippableItems(true));
+ if ( vOut ) then
+ local vCategoryID = Outfitter_AddOutfit(vOut);
+ -- we're done
+ end
+ end
+ end
+end
+
+-- calculate scores based on Outfitter
+local function StylePoints(outfit)
+ local isp = FishingBuddy.OutfitManager.ItemStylePoints;
+ local points = 0;
+ if ( outfit )then
+ for slot in outfit.Items do
+ points = points + isp(outfit.Items[slot].Code,
+ outfit.Items[slot].EnchantCode);
+ end
+ end
+ return points;
+end
+
+local function BonusPoints(outfit, vStatID)
+ local points = 0;
+ if ( outfit )then
+ for slot in outfit.Items do
+ if ( outfit.Items[slot][vStatID] ) then
+ points = points + outfit.Items[slot][vStatID];
+ end
+ -- Enternium Fishing Line
+ if ( outfit.Items[slot].EnchantCode == 2603 ) then
+ points = points + 5;
+ end
+ end
+ end
+ return points;
+end
+
+-- Outfitter patches ( not needed in 1.2)
+if ( not Outfitter_FindOutfitByStatID ) then
+ Outfitter_FindOutfitByStatID = function(pStatID)
+ if not pStatID or pStatID == "" then
+ return nil;
+ end
+
+ for vCategoryID, vOutfits in gOutfitter_Settings.Outfits do
+ for vOutfitIndex, vOutfit in vOutfits do
+ if vOutfit.StatID and vOutfit.StatID == pStatID then
+ return vOutfit, vCategoryID, vOutfitIndex;
+ end
+ end
+ end
+
+ -- return nil, nil, nil;
+ end
+end
+
+local Saved_OutfitterItem_OnEnter = OutfitterItem_OnEnter;
+local function Patch_OutfitterItem_OnEnter(pItem)
+ Saved_OutfitterItem_OnEnter(pItem);
+ if ( not pItem.isCategoryItem ) then
+ local vOutfit = Outfitter_GetOutfitFromListItem(pItem);
+ if ( vOutfit and vOutfit.StatID == "Fishing" ) then
+ local vDescription;
+ local bp = BonusPoints(vOutfit, "Fishing");
+ if ( bp >= 0 ) then
+ bp = "+"..bp;
+ else
+ bp = 0 - bp;
+ bp = "-"..bp;
+ end
+ bp = Outfitter_cFishingStatName.." "..bp;
+ local sp = StylePoints(vOutfit);
+ local pstring;
+ if ( points == 1 ) then
+ pstring = FishingBuddy.POINT;
+ else
+ pstring = FishingBuddy.POINTS;
+ end
+ vDescription = string.format(FishingBuddy.CONFIG_OUTFITTER_TEXT,
+ bp, sp)..pstring;
+ GameTooltip_AddNewbieTip(vOutfit.Name, 1.0, 1.0, 1.0, vDescription, 1);
+ end
+ end
+end
+-- point to our new function so we get our own tooltip
+OutfitterItem_OnEnter = Patch_OutfitterItem_OnEnter;
+
+if ( Outfitter_OnLoad ) then
+ FishingBuddy.OutfitManager.RegisterManager("Outfitter",
+ OutfitterInitialize,
+ function(useme) end,
+ OutfitterSwitch);
+end
+
diff --git a/FishingSchools.lua b/FishingSchools.lua
new file mode 100644
index 0000000..cce78b9
--- /dev/null
+++ b/FishingSchools.lua
@@ -0,0 +1,165 @@
+-- Support for schools
+
+FishingBuddy.Schools = {};
+
+local SCHOOLS = {};
+local CLOSEENOUGH = 0.000001;
+
+local function distance(x1, y1, x2, y2)
+ local x = (x1 - x2);
+ local y = (y1 - y2);
+ return sqrt( (x * x) + (y * y) );
+end
+
+-- Let's store fishing holes like this
+-- FishingBuddy_Info["Schools"][ZONE]
+-- Store everything to two digits?
+
+local function AddFishingSchool(kind, fishid, zidx, x, y)
+ local entry = {};
+ if ( not zidx ) then
+ zidx, _ = FishingBuddy.GetZoneIndex();
+ elseif ( type(zidx) == "string" ) then
+ zidx = FishingBuddy.GetZoneIndex(zidx);
+ end
+ if ( not x or not y ) then
+ x, y = GetPlayerMapPosition("player");
+ end
+ if ( not FishingBuddy_Info["FishSchools"] ) then
+ FishingBuddy_Info["FishSchools"] = {};
+ end
+ if ( not FishingBuddy_Info["FishSchools"][zidx] ) then
+ FishingBuddy_Info["FishSchools"][zidx] = {};
+ else
+ -- how do we find the same pool?
+ for _,hole in FishingBuddy_Info["FishSchools"][zidx] do
+ local d = distance(hole.x, hole.y, x, y);
+ if ( d < CLOSEENOUGH ) then
+ if ( fishid ) then
+ if ( hole.fish ) then
+ for f,count in hole.fish do
+ if ( f == fishid ) then
+ hole.fish[f] = count + 1;
+ return;
+ end
+ end
+ else
+ hole.fish = {};
+ end
+ hole.fish[fishid] = 1;
+ end
+ if ( hole.count ) then
+ hole.count = hole.count + 1;
+ else
+ hole.count = 1;
+ end
+ return;
+ end
+ end
+ end
+ entry.kind = kind;
+ entry.x = x;
+ entry.y = y;
+ entry.count = 1;
+ if ( fishid ) then
+ entry.fish = {};
+ entry.fish[fishid] = 1;
+ end
+ tinsert(FishingBuddy_Info["FishSchools"][zidx], entry);
+ return true;
+end
+FishingBuddy.Schools.AddFishingSchool = AddFishingSchool;
+
+local function IsFishingHole(text)
+ if ( text ) then
+ for match, info in SCHOOLS do
+ if ( string.find(text, match) ) then
+ return info;
+ end
+ end
+ end
+end
+FishingBuddy.Schools.IsFishingHole = IsFishingHole;
+
+local function CheckFishingHole(text, fishid)
+ local info = IsFishingHole(text);
+ if ( info ) then
+ if ( Gatherer_AddGatherHere and
+ FishingBuddy.GetSetting("UseGatherer") == 1 ) then
+ Gatherer_AddGatherHere(info.gather, 0, info.gather, 2);
+ end
+ if ( AddFishingSchool(info.kind, fishid) and
+ FishingBuddy.GetSetting("ShowNewFishies") == 1 ) then
+ local zone,_ = FishingBuddy.GetZoneInfo();
+ FishingBuddy.Print(FishingBuddy.ADDSCHOOLMSG, text, zone);
+ end
+ end
+end
+FishingBuddy.Schools.CheckFishingHole = CheckFishingHole;
+
+local function GetSchools(zidx)
+ if ( type(zidx) == "string" ) then
+ zidx = FishingBuddy.GetZoneIndex(zidx);
+ end
+ if ( FishingBuddy_Info["FishSchools"] and FishingBuddy_Info["FishSchools"][zidx] ) then
+ return FishingBuddy_Info["FishSchools"][zidx];
+ else
+ return {};
+ end
+end
+FishingBuddy.Schools.GetSchools = GetSchools;
+
+FishingBuddy.Schools.Init = function()
+ -- hook into Gatherer
+ SCHOOLS[FishingBuddy.SCHOOL] = {
+ ["gather"] = TREASURE_FISHNODE,
+ ["kind"] = FishingBuddy.SCHOOL_FISH,
+ };
+ SCHOOLS[FishingBuddy.FLOATING_WRECKAGE] = {
+ ["gather"] = TREASURE_FISHWRECK,
+ ["kind"] = FishingBuddy.SCHOOL_WRECKAGE,
+ };
+ SCHOOLS[FishingBuddy.FLOATING_DEBRIS] = {
+ ["gather"] = TREASURE_FISHWRECK,
+ ["kind"] = FishingBuddy.SCHOOL_DEBRIS,
+ };
+ SCHOOLS[FishingBuddy.ELEM_WATER] = {
+ ["gather"] = TREASURE_FISHELEM,
+ ["kind"] = FishingBuddy.SCHOOL_WATER,
+ };
+ SCHOOLS[FishingBuddy.OIL_SPILL] = {
+ ["gather"] = TREASURE_FISHWRECK,
+ ["kind"] = FishingBuddy.SCHOOL_OIL,
+ };
+end
+
+local function CollapseHoles()
+ if ( FishingBuddy_Info["FishSchools"] ) then
+ local zonecopy = {};
+ for zidx,holes in FishingBuddy_Info["FishSchools"] do
+ local copy = {};
+ for _,hole in holes do
+ tinsert(copy, hole);
+ end
+ zonecopy[zidx] = copy;
+ end
+ for zidx,holes in zonecopy do
+ FishingBuddy_Info["FishSchools"][zidx] = nil;
+ for _,hole in holes do
+
+ FishingBuddy.Dump(hole);
+
+ if ( hole.fish ) then
+ for f,c in hole.fish do
+ for i in 1,c do
+ AddFishingSchool(hole.kind, f, zidx, hole.x, hole.y);
+ end
+ end
+ else
+ AddFishingSchool(hole.kind, nil, zidx, hole.x, hole.y);
+ end
+ end
+ end
+ end
+end
+FishingBuddy.Schools.CollapseHoles = CollapseHoles;
diff --git a/FishingSetup.lua b/FishingSetup.lua
new file mode 100644
index 0000000..1eba225
--- /dev/null
+++ b/FishingSetup.lua
@@ -0,0 +1,127 @@
+-- FishingSetup
+--
+-- Load out translation strings and such
+
+FishingBuddy.VERSION = GetAddOnMetadata("FishingBuddy", "Version");
+FishingBuddy.CURRENTVERSION = 8800;
+
+FishingBuddy.Colors = {};
+FishingBuddy.Colors.RED = "ffff0000";
+FishingBuddy.Colors.GREEN = "ff00ff00";
+FishingBuddy.Colors.BLUE = "ff0000ff";
+FishingBuddy.Colors.YELLOW = "ff00ffff";
+FishingBuddy.Colors.PURPLE = "ffff00ff";
+FishingBuddy.Colors.WHITE = "ffffffff";
+
+FishingBuddy.DEFAULT_MINIMAP_POSITION = 256;
+
+local Setup = {};
+
+Setup.FixupThis = function(tag, what)
+ if ( type(what) == "table" ) then
+ for idx,str in what do
+ what[idx] = Setup.FixupThis(tag, str);
+ end
+ return what;
+ elseif ( type(what) == "string" ) then
+ local pattern = "#([A-Z0-9_]+)#";
+ local s,e,w = string.find(what, pattern);
+ while ( w ) do
+ if ( type(FishingBuddy[w]) == "string" ) then
+ local s1 = strsub(what, 1, s-1);
+ local s2 = strsub(what, e+1);
+ what = s1..FishingBuddy[w]..s2;
+ s,e,w = string.find(what, pattern);
+ elseif ( FishingBuddy.Colors[w] ) then
+ local s1 = strsub(what, 1, s-1);
+ local s2 = strsub(what, e+1);
+ what = s1..FishingBuddy.Colors[w]..s2;
+ s,e,w = string.find(what, pattern);
+ else
+ -- stop if we can't find something to replace it with
+ w = nil;
+ end
+ end
+ return what;
+ else
+ FishingBuddy.Debug("tag "..tag.." type "..type(what));
+ FishingBuddy.Dump(what);
+ end
+end
+
+Setup.FixupStrings = function(locale)
+ local translation = FishingTranslations["enUS"];
+ for tag,_ in translation do
+ FishingBuddy[tag] = Setup.FixupThis(tag, FishingBuddy[tag]);
+ end
+end
+
+Setup.FixupBindings = function()
+ local translation = FishingTranslations["enUS"];
+ for tag,str in translation do
+ if ( string.find(tag, "^BINDING") ) then
+ setglobal(tag, FishingBuddy[tag]);
+ FishingBuddy[tag] = nil;
+ end
+ end
+end
+
+local missing = {};
+Setup.LoadTranslation = function(lang, record)
+ local translation = FishingTranslations[lang];
+ for tag,value in translation do
+ if ( not FishingBuddy[tag] ) then
+ FishingBuddy[tag] = value;
+ if ( record ) then
+ missing[tag] = 1;
+ end
+ end
+ end
+end
+
+Setup.Translate = function()
+ local locale = GetLocale();
+ if ( FBEnEspagnolFlag ) then
+ locale = "esES";
+ end
+ --locale = "deDE";
+ Setup.LoadTranslation(locale);
+ if ( locale ~= "enUS" ) then
+ Setup.LoadTranslation("enUS");
+ end
+ Setup.FixupStrings(locale);
+ Setup.FixupBindings();
+end
+
+Setup.Translate();
+
+-- throw all this away now that we're done with it
+Setup = nil;
+-- dump the memory we've allocated for all the translations
+FishingTranslations = nil;
+
+local byweeks = {};
+byweeks[FishingBuddy.ABBREV_JANUARY] = 0;
+byweeks[FishingBuddy.ABBREV_APRIL] = 13;
+byweeks[FishingBuddy.ABBREV_JULY] = 26;
+byweeks[FishingBuddy.ABBREV_OCTOBER] = 39;
+byweeks[FishingBuddy.ABBREV_DECEMBER] = 52;
+
+FishingBuddy.BYWEEKS_TABLE = byweeks;
+
+FishingBuddy.KEYS_NONE = 0;
+FishingBuddy.KEYS_SHIFT = 1;
+FishingBuddy.KEYS_CTRL = 2;
+FishingBuddy.KEYS_ALT = 3;
+FishingBuddy.Keys = {};
+FishingBuddy.Keys[FishingBuddy.KEYS_NONE] = FishingBuddy.KEYS_NONE_TEXT;
+FishingBuddy.Keys[FishingBuddy.KEYS_SHIFT] = FishingBuddy.KEYS_SHIFT_TEXT;
+FishingBuddy.Keys[FishingBuddy.KEYS_CTRL] = FishingBuddy.KEYS_CTRL_TEXT;
+FishingBuddy.Keys[FishingBuddy.KEYS_ALT] = FishingBuddy.KEYS_ALT_TEXT;
+
+FishingBuddy.SCHOOL_FISH = 0;
+FishingBuddy.SCHOOL_WRECKAGE = 1;
+FishingBuddy.SCHOOL_DEBRIS = 2;
+FishingBuddy.SCHOOL_WATER = 3;
+FishingBuddy.SCHOOL_TASTY = 4;
+FishingBuddy.SCHOOL_OIL = 5;
diff --git a/FishingTrackingFrame.lua b/FishingTrackingFrame.lua
new file mode 100644
index 0000000..cdfd4d2
--- /dev/null
+++ b/FishingTrackingFrame.lua
@@ -0,0 +1,387 @@
+-- Handle tracking cycle fish
+
+FishingBuddy.TrackingFrame = {};
+
+local GRAPH_HEIGHT = 120;
+
+local trackingWordMap = {
+ ["WEEKLY"] = FishingBuddy.WEEKLY,
+ ["HOURLY"] = FishingBuddy.HOURLY,
+ [FishingBuddy.WEEKLY] = "WEEKLY",
+ [FishingBuddy.HOURLY] = "HOURLY",
+};
+
+local byhours = {
+ [13759] = {
+ ["enUS"] = "Raw Nightfin Snapper",
+ ["ruRU"] = "Сырой ночной луциан",
+ ["deDE"] = "Roher Nachtflossenschnapper",
+ ["frFR"] = "Lutjan nagenuit cru",
+ ["c"] = { r = 0.5, g = 0.5, b = 1.0, a = 0.75 },
+ },
+ [13760] = {
+ ["enUS"] = "Raw Sunscale Salmon",
+ ["ruRU"] = "Сырой радужный лосось",
+ ["deDE"] = "Roher Sonnenschuppenlachs",
+ ["frFR"] = "Saumon sol\195\169caille cru",
+ ["c"] = { r = 0.8, g = 0.8, b = 0.1, a = 0.75 },
+ },
+};
+local byweeks = {
+ [13756] = {
+ ["enUS"] = "Raw Summer Bass",
+ ["ruRU"] = "Сырой летний окунь",
+ ["deDE"] = "Roher Sommerbarsch",
+ ["frFR"] = "Perche estivale crue",
+ ["c"] = { r = 1.0, g = 1.0, b = 0.0, a = 0.75 },
+ },
+ [13755] = {
+ ["enUS"] = "Winter Squid",
+ ["ruRU"] = "Зимний кальмар",
+ ["deDE"] = "Winterkalmar",
+ ["frFR"] = "Calmar hivernal",
+ ["c"] = { r = 0.4, g = 0.1, b = 0.4, a = 0.75 },
+ },
+};
+
+local function UntrackThis(id, name)
+ if ( not byhours[id] and not byweeks[id] ) then
+ for how in FishingBuddy_Info["FishTracking"] do
+ if ( FishingBuddy_Info["FishTracking"][how][id] ) then
+ FishingBuddy_Info["FishTracking"][how][id] = nil;
+ FishingBuddy.Print(FishingBuddy.NOTRACKMSG, name);
+ end
+ end
+ else
+ FishingBuddy.Message(FishingBuddy.NOTRACKERRMSG);
+ end
+end
+
+local function TrackThis(how, id, color, name)
+ if ( not FishingBuddy_Info["FishTracking"][how] ) then
+ FishingBuddy_Info["FishTracking"][how] = {};
+ end
+ local limit = 23;
+ if ( how == "WEEKLY" ) then
+ limit = 52;
+ end
+ if ( not FishingBuddy_Info["FishTracking"][how][id] ) then
+ FishingBuddy_Info["FishTracking"][how][id] = {};
+ FishingBuddy_Info["FishTracking"][how][id].data = {};
+ for i=0,limit,1 do
+ FishingBuddy_Info["FishTracking"][how][id].data[i] = 0;
+ end
+ FishingBuddy_Info["FishTracking"][how][id].data.n = limit+1;
+ end
+ if ( name and not FishingBuddy_Info["FishTracking"][how][id].name ) then
+ FishingBuddy_Info["FishTracking"][how][id].name = name;
+ end
+ if ( color ) then
+ if ( type(color) == "string") then
+ local a = tonumber(string.sub(color,1,2),16);
+ local r = tonumber(string.sub(color,3,4),16);
+ local g = tonumber(string.sub(color,5,6),16);
+ local b = tonumber(string.sub(color,7,8),16);
+ color = { a = a, r = r, g = g, b = b };
+ end
+ FishingBuddy_Info["FishTracking"][how][id].color = color;
+ end
+end
+FishingBuddy.TrackThis = TrackThis;
+
+FishingBuddy.Commands[FishingBuddy.TRACK] = {};
+FishingBuddy.Commands[FishingBuddy.TRACK].args = {};
+FishingBuddy.Commands[FishingBuddy.TRACK].args[1] = "[%w]+";
+FishingBuddy.Commands[FishingBuddy.TRACK].args[2] = "|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[.-%]|h|r";
+FishingBuddy.Commands[FishingBuddy.TRACK].help = FishingBuddy.TRACKING_HELP;
+FishingBuddy.Commands[FishingBuddy.TRACK].func =
+ function(how, fishlink)
+ if ( how and (how == FishingBuddy.HOURLY or
+ how == FishingBuddy.WEEKLY)) then
+ local c, i, n = FishingBuddy.SplitFishLink(fishlink);
+ if ( i ) then
+ TrackThis(trackingWordMap[how], i, c, n);
+ FishingBuddy.Print(FishingBuddy.TRACKINGMSG, n, how);
+ return true;
+ end
+ end
+ end;
+FishingBuddy.Commands[FishingBuddy.NOTRACK] = {};
+FishingBuddy.Commands[FishingBuddy.NOTRACK].args = {};
+FishingBuddy.Commands[FishingBuddy.NOTRACK].args[1] = "|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[.-%]|h|r";
+FishingBuddy.Commands[FishingBuddy.NOTRACK].help = FishingBuddy.TRACKING_HELP;
+FishingBuddy.Commands[FishingBuddy.NOTRACK].func =
+ function(fishlink)
+ local c, i, n = FishingBuddy.SplitFishLink(fishlink);
+ if ( i ) then
+ UntrackThis(i, n);
+ return true;
+ end
+ end;
+FishingBuddy.Commands[FishingBuddy.TRACKING] = {};
+FishingBuddy.Commands[FishingBuddy.TRACKING].help = FishingBuddy.TRACKING_HELP;
+FishingBuddy.Commands[FishingBuddy.TRACKING].func =
+ function()
+ local pr = FishingBuddy.Print;
+ for jdx in FishingBuddy_Info["FishTracking"] do
+ local how = trackingWordMap[jdx];
+ pr("Tracking "..how);
+ local ft = FishingBuddy_Info["FishTracking"];
+ for id in ft[jdx] do
+ local name;
+ if ( ft[jdx][id].name ) then
+ name = ft[jdx][id].name;
+ else
+ name = id;
+ end
+ local line = name.."; ";
+ for k,v in ft[jdx][id].data do
+ line = line.." "..k..": "..v;
+ end
+ pr(line);
+ end
+ end
+ return true;
+ end;
+
+FishingBuddy.InitTracking = function()
+ if ( not FishingBuddy_Info["FishTracking"] ) then
+ FishingBuddy_Info["FishTracking"] = { };
+ end
+ for k,v in byhours do
+ TrackThis("HOURLY", k, v.c);
+ end
+ for k,v in byweeks do
+ TrackThis("WEEKLY", k, v.c);
+ end
+end
+
+FishingBuddy.AddTracking = function(id, name)
+ local ft = FishingBuddy_Info["FishTracking"];
+ local index, how;
+
+ -- clean up fish removed from the tracking system
+ local hourly = ft["HOURLY"][id];
+ local weekly = ft["WEEKLY"][id];
+ if ( hourly and hourly.nevermore ) then
+ FishingBuddy_Info["FishTracking"]["HOURLY"][id] = nil;
+ end
+ if ( weekly and weekly.nevermore ) then
+ FishingBuddy_Info["FishTracking"]["WEEKLY"][id] = nil;
+ end
+
+ ft = FishingBuddy_Info["FishTracking"];
+ if ( ft["HOURLY"][id] ) then
+ how = "HOURLY";
+ index,_ = GetGameTime();
+ elseif ( ft["WEEKLY"][id] ) then
+ how = "WEEKLY";
+ index = date("%W");
+ else
+ return false;
+ end
+ if ( not FishingBuddy_Info["FishTracking"][how][id].name ) then
+ FishingBuddy_Info["FishTracking"][how][id].name = name;
+ end
+ index = tonumber(index);
+
+ local p = FishingBuddy.printable;
+ FishingBuddy_Info["FishTracking"][how][id].data[index] =
+ FishingBuddy_Info["FishTracking"][how][id].data[index] + 1;
+ return true;
+end
+
+local function PlotData(graph, num, bw, bs, graphdata, plotthese, hlabels)
+ local maxval = 0;
+ local width = 0;
+ local line;
+ GraphHandler.ClearPlot(graph);
+ for _,info in graphdata do
+ if ( info.maxval and info.maxval > maxval ) then
+ maxval = info.maxval;
+ end
+ local w = info.count * (bw+bs);
+ if ( w > width ) then
+ width = w;
+ end
+ end
+ local delta = math.mod(maxval, 5);
+ if ( delta > 0 ) then
+ maxval = maxval + (5 - delta);
+ end
+ graph.maxVal = maxval;
+ graph.barWidth = bw;
+ graph.barSpacing = bs;
+ local count = num;
+ for idx,fishid in plotthese do
+ local info = graphdata[fishid];
+ local c = info.color;
+ GraphHandler.PlotLegend(graph, num-count+1,
+ info.name, info.item, info.texture,
+ c.r, c.g, c.b);
+ _ = GraphHandler.PlotData(graph, info.data, num-count, 1,
+ c.r, c.g, c.b);
+ if ( line ) then
+ line = line.." / "..info.name;
+ else
+ line = info.name;
+ end
+ count = count - 1;
+ end
+ local values = {};
+ local delta = maxval/5;
+ for v=0,5 do
+ values[string.format("%d", v*delta)] = v;
+ end
+ GraphHandler.PlotGrid(graph, line or "", values, width, hlabels);
+end
+
+local function UpdateGraphData(id, info)
+ local maxval = 0;
+ local n = table.getn(info.data);
+ info.count = n;
+ -- we're zero based
+ n = n - 1;
+ for idx=0,n do
+ if ( info.data[idx] > maxval ) then
+ maxval = info.data[idx];
+ end
+ end
+ info.maxval = maxval;
+ info.data = info.data;
+ if ( not info.color ) then
+ info.color = {};
+ else
+ if ( type(info.color) == "string") then
+ local a = tonumber(string.sub(color,1,2),16);
+ local r = tonumber(string.sub(color,3,4),16);
+ local g = tonumber(string.sub(color,5,6),16);
+ local b = tonumber(string.sub(color,7,8),16);
+ info.color = { a = a, r = r, g = g, b = b };
+ end
+ end
+ local name;
+ info.item, info.texture, _, _, _, name = FishingBuddy.GetFishie(id);
+ local loc = GetLocale();
+ if ( not info.name ) then
+ if ( byhours[id] and byhours[id][loc] ) then
+ info.name = byhours[id][loc];
+ elseif ( byweeks[d] and byweeks[id][loc] ) then
+ info.name = byweeks[id][loc];
+ elseif ( not name ) then
+ info.name = FishingBuddy.FISH.." ("..id..")";
+ else
+ info.name = name;
+ end
+ end
+ info.name = FishingBuddy.StripRaw(info.name);
+end
+
+local function DrawTrackingGraph(how, num, bw, bs)
+ local fi = FishingBuddy_Info["FishTracking"];
+ local graph;
+ local labels;
+ if ( how == "HOURLY" ) then
+ graph = getglobal("FishingTrackingFrameGraph1");
+ labels = {["00:00"] = 0, ["06:00"] = 6, ["12:00"] = 12, ["18:00"] = 18, ["23:59"] = 24};
+ if ( not num ) then
+ num = 2;
+ bw = 5;
+ bs = 5;
+ end
+ else
+ graph = getglobal("FishingTrackingFrameGraph2");
+ labels = FishingBuddy.BYWEEKS_TABLE;
+ if ( not num ) then
+ num = 2;
+ bw = 3;
+ bs = 2;
+ end
+ end
+ local plotthese = {};
+ local count = 0;
+ graph.tracking = how;
+ for id,info in fi[how] do
+ UpdateGraphData(id, info);
+ if ( count < num and fi[how][id].plot == 1 ) then
+ count = count + 1;
+ tinsert(plotthese, id);
+ end
+ end
+ PlotData(graph, num, bw, bs, fi[how], plotthese, labels);
+end
+
+local function DrawTrackingGraphs()
+ DrawTrackingGraph("HOURLY");
+ DrawTrackingGraph("WEEKLY");
+end
+
+local function PlotFishToggle(fishid, how)
+ local tab = FishingBuddy_Info["FishTracking"][how];
+ if ( not tab[fishid].plot ) then
+ tab[fishid].plot = 1;
+ else
+ tab[fishid].plot = 1 - tab[fishid].plot;
+ end
+ DrawTrackingGraph(how);
+end
+
+local PlotToggleFunctions = {};
+local function PlotMakeToggle(fishid, how)
+ if ( not PlotToggleFunctions[fishid] ) then
+ local id = fishid;
+ local h = how;
+ PlotToggleFunctions[fishid] = function() PlotFishToggle(id, h); end;
+ end
+ return PlotToggleFunctions[fishid];
+end
+
+local function PlotMenuInitialize()
+ local fi = FishingBuddy_Info["FishTracking"];
+ local ff = FishingBuddy_Info["Fishies"];
+ local how = this.tracking;
+ local locale = GetLocale();
+ for id,_ in fi[how] do
+ if ( not fi[how][id].plot ) then
+ fi[how][id].plot = 1;
+ end
+ info = {};
+ if ( ff[id] and ff[id].name ) then
+ info.text = ff[id].name;
+ elseif ( byhours[id] ) then
+ info.text = byhours[id][locale];
+ elseif ( byweeks[id] ) then
+ info.text = byweeks[id][locale];
+ end
+ if ( info.text ) then
+ info.func = PlotMakeToggle(id, how);
+ info.checked = ( fi[how][id].plot == 1 );
+ UIDropDownMenu_AddButton(info);
+ end
+ end
+end
+
+FishingBuddy.TrackingFrame.OnClick = function(button, graph)
+ if ( button == "RightButton" ) then
+ local menu = getglobal("FishingBuddyGraphMenu");
+ menu.tracking = this.tracking;
+ menu.point = "CENTER";
+ menu.relativePoint = "CENTER";
+ UIDropDownMenu_Initialize(menu, PlotMenuInitialize, "MENU");
+ FishingBuddy.ToggleDropDownMenu(1, nil, menu, this, 0, 0);
+ end
+end
+
+FishingBuddy.TrackingFrame.OnShow = function()
+ DrawTrackingGraphs();
+end
+
+FishingBuddy.TrackingFrame.OnEnter = function()
+ GameTooltip_AddNewbieTip(FishingBuddy.TRACKINGFRAME, 1.0, 1.0, 1.0,
+ FishingBuddy.TRACKINGFRAME_CLICKS, 1);
+end
+
+FishingBuddy.TrackingFrame.OnLeave = function()
+ GameTooltip:Hide();
+end
+
diff --git a/FishingTrackingFrame.xml b/FishingTrackingFrame.xml
new file mode 100644
index 0000000..8e68b9c
--- /dev/null
+++ b/FishingTrackingFrame.xml
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(0);
+ UIDropDownMenu_SetWidth(180);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.TrackingFrame.OnClick(arg1);
+
+
+ FishingBuddy.TrackingFrame.OnEnter();
+
+
+ FishingBuddy.TrackingFrame.OnLeave();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FishingBuddy.TrackingFrame.OnClick(arg1);
+
+
+ FishingBuddy.TrackingFrame.OnEnter();
+
+
+ FishingBuddy.TrackingFrame.OnLeave();
+
+
+
+
+
+
+ FishingBuddy.TrackingFrame.OnShow();
+
+
+
+
diff --git a/FishingWatcher.lua b/FishingWatcher.lua
new file mode 100644
index 0000000..71d231a
--- /dev/null
+++ b/FishingWatcher.lua
@@ -0,0 +1,373 @@
+-- Display the fish you're catching and/or have caught in a live display
+
+FishingBuddy.WatchFrame = {};
+
+local MAX_FISHINGWATCH_LINES = 20;
+local WATCHDRAGGER_SHOW_DELAY = 0.2;
+
+local WATCHDRAGGER_FADE_TIME = 0.15;
+
+local function PlaceDraggerFrame()
+ local where = FishingBuddy.GetSetting("WatcherLocation");
+ if ( not where ) then
+ where = {};
+ where.x = 0;
+ where.y = -384;
+ end
+ FishingWatchDrag:ClearAllPoints();
+ FishingWatchDrag:SetPoint("TOPLEFT", "UIParent", "TOPLEFT",
+ where.x, where.y);
+end
+
+local function ShowDraggerFrame()
+ if ( not FishingWatchDrag:IsVisible() ) then
+ FishingWatchFrame:Show();
+ local width = FishingWatchFrame:GetWidth();
+ local height = FishingWatchFrame:GetHeight();
+ FishingWatchDrag:SetHeight(height);
+ FishingWatchDrag:SetWidth(width);
+ FishingWatchTab:SetText(FishingBuddy.NAME);
+ PanelTemplates_TabResize(10, FishingWatchTab);
+ FishingWatchDrag:Show();
+ FishingWatchTab:Show();
+ UIFrameFadeIn(FishingWatchDrag, WATCHDRAGGER_FADE_TIME, 0, 0.15);
+ UIFrameFadeIn(FishingWatchTab, WATCHDRAGGER_FADE_TIME, 0, 1.0);
+ GameTooltip_AddNewbieTip(FishingBuddy.NAME, 1.0, 1.0, 1.0,
+ FishingBuddy.WATCHERCLICKHELP, 1);
+ end
+end
+
+local function HideDraggerFrame(save)
+ if ( FishingWatchDrag:IsVisible() ) then
+ if ( save ) then
+ FishingWatchFrame:Show();
+ local qx = UIParent:GetLeft()
+ local qy = UIParent:GetTop();
+ local wx = FishingWatchDrag:GetLeft()
+ local wy = FishingWatchDrag:GetTop();
+ local where;
+ if ( wx and wy ) then
+ where = {};
+ where.x = wx - qx;
+ where.y = wy - qy;
+ end
+ FishingBuddy.SetSetting("WatcherLocation", where);
+ end
+ UIFrameFadeOut(FishingWatchDrag, WATCHDRAGGER_FADE_TIME, 0.15, 0);
+ UIFrameFadeOut(FishingWatchTab, WATCHDRAGGER_FADE_TIME, 1.0, 0);
+ FishingWatchDrag:Hide();
+ FishingWatchTab:Hide();
+ GameTooltip:Hide();
+ end
+end
+
+local function ResetWatcherFrame(update)
+ FishingWatchTab:Show();
+ FishingWatchDrag:Show();
+ FishingWatchDrag:ClearAllPoints();
+ FishingWatchDrag:SetPoint("CENTER", "UIParent", "CENTER", 0, 0);
+ HideDraggerFrame(true);
+ if ( update ) then
+ FishingBuddy.WatchUpdate();
+ end
+end
+
+FishingBuddy.ShowDraggerFrame = ShowDraggerFrame;
+FishingBuddy.HideDraggerFrame = HideDraggerFrame;
+FishingBuddy.PlaceDraggerFrame = PlaceDraggerFrame;
+FishingBuddy.ResetWatcherFrame = ResetWatcherFrame;
+
+FishingBuddy.Commands[FishingBuddy.WATCHER] = {};
+FishingBuddy.Commands[FishingBuddy.WATCHER].help = FishingBuddy.WATCHER_HELP;
+FishingBuddy.Commands[FishingBuddy.WATCHER].func =
+ function(what)
+ if ( what and ( what == FishingBuddy.RESET ) ) then
+ ResetWatcherFrame(true);
+ return true;
+ end
+ end;
+
+-- fix old data
+local function UpdateUnknownZone(zone, subzone, zidx, sidx)
+ local uzidx = FishingBuddy.GetZoneIndex(FishingBuddy.UNKNOWN);
+ if ( uzidx ) then
+ local fh = FishingBuddy_Info["FishingHoles"];
+ for usidx in fh[uzidx] do
+ local uszone = FishingBuddy_Info["SubZones"][uzidx][usidx];
+ if ( uszone == subzone ) then
+ for k,v in fh[uzidx][usidx] do
+ if ( fh[zidx][sidx][k] ) then
+ fh[zidx][sidx][k] = fh[zidx][sidx][k] + v;
+ else
+ fh[zidx][sidx][k] = v;
+ end
+ end
+ for k,_ in fh[uzidx][usidx] do
+ fh[uzidx][usidx][k] = nil;
+ end
+ end
+ end
+ end
+end
+
+-- Fish watcher functions
+FishingBuddy.WatchUpdate = function()
+ if ( FishingWatchFrame:IsVisible() ) then
+ HideDraggerFrame();
+ FishingWatchFrame:Hide();
+ for i=1, MAX_FISHINGWATCH_LINES, 1 do
+ local line = getglobal("FishingWatchLine"..i);
+ line:Hide();
+ end
+ end
+
+ local reset = FishingBuddy.GetSetting("ResetWatcher");
+ if ( not reset or reset < 1 ) then
+ ResetWatcherFrame(false);
+ FishingBuddy.SetSetting("ResetWatcher", 1);
+ end
+
+ local zone, subzone = FishingBuddy.GetZoneInfo();
+ local zidx, sidx = FishingBuddy.GetZoneIndex(zone, subzone);
+
+ UpdateUnknownZone();
+
+ if ( FishingBuddy.GetSetting("WatchFishies") == 0 ) then
+ return;
+ end
+
+ if ( FishingBuddy.GetSetting("WatchOnlyWhenFishing") == 1 and
+ not FishingBuddy.API.IsFishingPole() ) then
+ return;
+ end
+
+ local fz = FishingBuddy_Info["FishingHoles"][zidx];
+ local current = FishingBuddy.currentFishies;
+ local ff = FishingBuddy_Info["Fishies"];
+ local fishsort = {};
+ local totalCount = 0;
+ local totalCurrent = 0;
+ local gotDiffs = false;
+
+ if ( fz and fz[sidx] ) then
+ for fishid in fz[sidx] do
+ local info = {};
+ if ( not FishingBuddy_Info["HiddenFishies"][fishid] ) then
+ info.text = ff[fishid].name;
+ end
+ info.count = fz[sidx][fishid];
+ totalCount = totalCount + info.count;
+ if ( current[sidx] ) then
+ info.current = current[sidx][fishid] or 0;
+ else
+ info.current = 0;
+ end
+ if ( info.current > 0 and info.current ~= info.count ) then
+ gotDiffs = true;
+ end
+ totalCurrent = totalCurrent + info.current;
+ tinsert(fishsort, info);
+ end
+
+-- if ( totalCount == 0 and totalCurrent == 0 ) then
+-- return;
+-- end
+
+ FishingBuddy.FishSort(fishsort);
+ end
+
+ local fishingWatchMaxWidth = 0;
+ local tempWidth;
+ local index = 1;
+ local start = 1;
+ local dopercent = FishingBuddy.GetSetting("WatchFishPercent");
+
+ if ( FishingBuddy.GetSetting("WatchCurrentZone") == 1 ) then
+ local entry = getglobal("FishingWatchLine"..index);
+ local line = zone.." : "..subzone;
+ entry:SetText(line);
+ local tempWidth = entry:GetWidth();
+ if ( tempWidth > fishingWatchMaxWidth ) then
+ fishingWatchMaxWidth = tempWidth;
+ end
+ entry:Show();
+ index = index + 1;
+ end
+ if ( FishingBuddy.GetSetting("WatchCurrentSkill") == 1 ) then
+ local entry = getglobal("FishingWatchLine"..index);
+ local skill, mods = FishingBuddy.GetCurrentSkill();
+ local line = "Skill: |cff00ff00"..skill.."+"..mods.."|r";
+ local StartedFishing = FishingBuddy.StartedFishing;
+ if ( StartedFishing ) then
+ local elapsed = GetTime() - StartedFishing;
+ local t = math.floor(elapsed);
+ local seconds = math.mod(t, 60);
+ t = math.floor(t / 60);
+ local minutes = math.mod(t, 60);
+ local hours = math.floor(t / 60);
+ line = line.." Elapsed: ";
+ if ( hours < 10 ) then
+ line = line.."0";
+ end
+ line = line..hours..":";
+ if ( minutes < 10 ) then
+ line = line.."0";
+ end
+ line = line..minutes..":";
+ if ( seconds < 10 ) then
+ line = line.."0";
+ end
+ line = line..seconds;
+ end
+
+ entry:SetText(line);
+ local tempWidth = entry:GetWidth();
+ if ( tempWidth > fishingWatchMaxWidth ) then
+ fishingWatchMaxWidth = tempWidth;
+ end
+ entry:Show();
+ index = index + 1;
+ end
+
+ for j=1,table.getn(fishsort),1 do
+ local info = fishsort[j];
+ if( index <= MAX_FISHINGWATCH_LINES ) then
+ local entry = getglobal("FishingWatchLine"..index);
+ local fishie = info.text;
+ if ( fishie ) then
+ fishie = FishingBuddy.StripRaw(fishie);
+ local amount = info.count;
+ local fishietext = fishie.." ("..amount;
+ if ( dopercent == 1 ) then
+ local percent = format("%.1f", ( amount / totalCount ) * 100);
+ fishietext = fishietext.." : "..percent.."%";
+ end
+ if ( gotDiffs ) then
+ amount = info.current;
+ local color;
+ fishietext = fishietext..", |c"..FishingBuddy.Colors.GREEN..amount;
+ if ( dopercent == 1 ) then
+ local percent = format("%.1f", ( amount / totalCurrent ) * 100);
+ fishietext = fishietext.." : "..percent.."%";
+ end
+ fishietext = fishietext.."|r";
+ end
+ fishietext = fishietext..")";
+ entry:SetText(fishietext);
+ tempWidth = entry:GetWidth();
+ entry:Show();
+ if ( tempWidth > fishingWatchMaxWidth ) then
+ fishingWatchMaxWidth = tempWidth;
+ end
+ index = index + 1;
+ end
+ end
+ end
+
+ FishingWatchFrame:SetHeight((index - 1) * 13);
+ FishingWatchFrame:SetWidth(fishingWatchMaxWidth + 10);
+ ShowDraggerFrame();
+ PlaceDraggerFrame();
+ FishingWatchFrame:Show();
+end
+
+FishingBuddy.WatchFrame.OnLoad = function()
+ this:ClearAllPoints();
+ this:SetPoint("TOPLEFT", "FishingWatchDrag", "TOPLEFT", 0, 0);
+
+ -- Make everything draw at least once
+ FishingWatchDrag:Show();
+ FishingWatchTab:Show();
+ FishingWatchDrag:Hide();
+ FishingWatchTab:Hide();
+end
+
+local hover;
+FishingBuddy.WatchFrame.OnUpdate = function(elapsed)
+ if ( FishingWatchFrame:IsVisible() ) then
+ if ( MouseIsOver(FishingWatchFrame) or
+ ( FishingWatchTab:IsVisible() and MouseIsOver(FishingWatchTab) ) ) then
+ local xPos, yPos = GetCursorPosition();
+ if ( hover ) then
+ if ( hover.xPos == xPos and hover.yPos == yPos ) then
+ hover.hoverTime = hover.hoverTime + elapsed;
+ else
+ hover.hoverTime = 0;
+ hover.xPos = xPos;
+ hover.yPos = yPos;
+ end
+ else
+ hover = {};
+ hover.hoverTime = 0;
+ hover.xPos = xPos;
+ hover.yPos = yPos;
+ end
+ if ( hover.hoverTime > WATCHDRAGGER_SHOW_DELAY ) then
+ ShowDraggerFrame();
+ end
+ else
+ HideDraggerFrame(true);
+ hover = nil;
+ end
+ elseif ( hover ) then
+ HideDraggerFrame(true);
+ hover = nil;
+ end
+end
+
+FishingBuddy.WatchFrame.OnMouseDown = function()
+ if ( arg1 == "LeftButton" ) then
+ FishingWatchDrag:StartMoving();
+ end
+end
+
+FishingBuddy.WatchFrame.OnMouseUp = function()
+ if ( arg1 == "LeftButton" ) then
+ FishingWatchDrag:StopMovingOrSizing();
+ end
+end
+
+local function HiddenFishToggle(id)
+ if ( FishingBuddy_Info["HiddenFishies"][id] ) then
+ FishingBuddy_Info["HiddenFishies"][id] = nil;
+ else
+ FishingBuddy_Info["HiddenFishies"][id] = true;
+ end;
+ FishingBuddy.WatchUpdate();
+end
+
+-- save some memory by keeping one copy of each one
+local WatcherToggleFunctions = {};
+-- let's use closures
+local function WatcherMakeToggle(fishid)
+ if ( not WatcherToggleFunctions[fishid] ) then
+ local id = fishid;
+ WatcherToggleFunctions[fishid] = function() HiddenFishToggle(id); end;
+ end
+ return WatcherToggleFunctions[fishid];
+end
+FishingBuddy.WatchFrame.MakeToggle = WatcherMakeToggle;
+
+local function WatchMenu_Initialize()
+ local zidx, sidx = FishingBuddy.GetZoneIndex();
+ local fz = FishingBuddy_Info["FishingHoles"][zidx];
+ if ( fz and fz[sidx] ) then
+ local ff = FishingBuddy_Info["Fishies"];
+ for fishid in fz[sidx] do
+ info = {};
+ info.text = ff[fishid].name;
+ info.func = WatcherMakeToggle(fishid);
+ info.checked = ( not FishingBuddy_Info["HiddenFishies"][fishid] );
+ info.keepShownOnClick = 1;
+ UIDropDownMenu_AddButton(info);
+ end
+ end
+end
+
+FishingBuddy.WatchFrame.OnClick = function()
+ if ( arg1 == "RightButton" ) then
+ local menu = getglobal("FishingBuddyWatcherMenu");
+ UIDropDownMenu_Initialize(menu, WatchMenu_Initialize, "MENU");
+ ToggleDropDownMenu(level, nil, menu, "FishingWatchDrag", 0, 0);
+ end
+end
diff --git a/FishingWatcher.xml b/FishingWatcher.xml
new file mode 100644
index 0000000..9896fb1
--- /dev/null
+++ b/FishingWatcher.xml
@@ -0,0 +1,258 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterForClicks("RightButtonUp");
+
+
+ FishingBuddy.WatchFrame.OnClick();
+
+
+ FishingBuddy.WatchFrame.OnMouseDown();
+
+
+ FishingBuddy.WatchFrame.OnMouseUp();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterForClicks("RightButtonUp");
+
+
+ FishingBuddy.WatchFrame.OnClick();
+
+
+ FishingBuddy.WatchFrame.OnMouseDown();
+
+
+ FishingBuddy.WatchFrame.OnMouseUp();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(0);
+ UIDropDownMenu_SetWidth(180);
+
+
+
+
+
+
+ FishingBuddy.WatchFrame.OnLoad();
+
+
+ FishingBuddy.WatchFrame.OnUpdate(arg1);
+
+
+
+
diff --git a/GraphHandler.lua b/GraphHandler.lua
new file mode 100644
index 0000000..ab28dc5
--- /dev/null
+++ b/GraphHandler.lua
@@ -0,0 +1,251 @@
+-- Do graph stuff
+-- This should be a separate addon someday
+
+GraphHandler = {};
+GraphHandler.Legend = {};
+
+GraphHandler.Legend.OnEnter = function()
+ if( this.item or this.tooltop ) then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ if (this.item and this.item ~= "") then
+ GameTooltip:SetHyperlink("item:"..this.item);
+ elseif (this.tooltip) then
+ GameTooltip:SetText(this.tooltip);
+ end
+ end
+end
+
+GraphHandler.Legend.OnLeave = function()
+ if( this.item or this.tooltop ) then
+ this.updateToolTip = nil;
+ GameTooltip:Hide();
+ end
+end
+
+GraphHandler.Legend.OnClick = function(button)
+ if ( button == "LeftButton" ) then
+ if( IsShiftKeyDown() and this.item ) then
+ GraphHandler.Legend.ChatLink(this.item, this.name, this.color);
+ end
+ end
+end
+
+GraphHandler.Legend.ChatLink = FishingBuddy.ChatLink;
+
+GraphHandler.BAR = "BAR";
+GraphHandler.LEGEND = "LEGEND";
+GraphHandler.LINE = "LINE";
+GraphHandler.LABEL = "LABEL";
+GraphHandler.TEXT = "TEXT";
+
+GraphHandler.InitElements = function()
+ if ( not this.elements ) then
+ this.elements = {};
+ this.elements[GraphHandler.BAR] = {};
+ this.elements[GraphHandler.LINE] = {};
+ this.elements[GraphHandler.LEGEND] = {};
+ this.elements[GraphHandler.LABEL] = {};
+ this.elements[GraphHandler.TEXT] = {};
+ end
+end
+
+local function SetColorBar(bar, base, x, y, width, height, r, g, b)
+ local name;
+ if ( type(bar) == "STRING" ) then
+ name = bar;
+ bar = getglobal(name);
+ elseif ( bar ) then
+ name = bar:GetName();
+ end
+ if ( bar ) then
+ if ( not r ) then
+ r = 1.0;
+ g = 1.0;
+ b = 1.0;
+ end
+ if ( base ) then
+ local tex = getglobal(name.."Texture");
+ if ( x and y ) then
+ bar:ClearAllPoints();
+ bar:SetPoint("BOTTOMLEFT", base, "BOTTOMLEFT", x, y);
+ end
+ if ( width ) then
+ bar:SetWidth(width);
+ end
+ if ( height ) then
+ bar:SetHeight(height);
+ end
+ tex:SetVertexColor(r, g, b);
+ bar:Show();
+ else
+ bar:Hide();
+ end
+ end
+end
+
+-- Registration functions
+
+GraphHandler.Register = function(kind, what)
+ local frame = this;
+ local lastframe = nil;
+ for idx=1,5 do
+ frame = frame:GetParent();
+ if ( frame == lastframe ) then
+ break;
+ end
+ if ( frame and frame.elements ) then
+ if ( not frame.elements[kind] ) then
+ frame.elements[kind] = {};
+ end
+ tinsert(frame.elements[kind], what);
+ break;
+ end
+ lastframe = frame;
+ end
+end
+
+GraphHandler.ClearPlot = function(frame)
+ for _,elem in { GraphHandler.BAR, GraphHandler.LEGEND } do
+ for idx,what in frame.elements[elem] do
+ what:Hide();
+ end
+ end
+end
+
+GraphHandler.PlotData = function(frame, data, offset, skip, r, g, b)
+ local limit = table.getn(data);
+ local start = 1;
+ if ( data[0] ) then
+ start = 0;
+ limit = limit - 1;
+ end
+
+ local bdx=offset+1;
+ local bwid = frame.barWidth;
+ local bspc = frame.barSpacing;
+ local maxval = frame.maxVal;
+ local xoff = offset*bspc;
+ local yoff = 0;
+ local graphHeight = frame:GetHeight();
+ for idx=start,limit,1 do
+ local bar = frame.elements[GraphHandler.BAR][bdx];
+ bdx = bdx + skip + 1;
+ if ( bar ) then
+ if ( (maxval > 0) and (data[idx] > 0) ) then
+ local height = (data[idx]*graphHeight)/maxval;
+ SetColorBar(bar, frame, xoff, 0, bwid, height, r, g, b);
+ else
+ bar:Hide();
+ end
+ end
+ xoff = xoff + bwid + skip*bspc;
+ end
+ return xoff - skip*bspc;
+end
+
+GraphHandler.PlotLegend = function(frame, ldx, name, item, texture, r, g, b)
+ local legend = frame.elements[GraphHandler.LEGEND][ldx];
+ if ( legend ) then
+ local name = legend:GetName();
+ local icon = getglobal(name.."Icon");
+ local tex = getglobal(name.."IconTexture");
+ local color = getglobal(name.."Color");
+-- SetColorBar(color, legend, nil, nil, nil, nil, r, g, b);
+ SetColorBar(color, legend, 0, 1, 10, 16, r, g, b);
+ color:Show();
+ icon:Show();
+ tex:SetTexture(texture);
+ tex:Show();
+ legend:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -(ldx-1)*21);
+ legend.item = item;
+ legend.name = name;
+ legend:Show();
+ end
+end
+
+GraphHandler.PlotGrid = function(frame, label, texth, width, textv, height)
+ local ldx=1;
+ local tdx=1;
+ if ( not width ) then
+ width = frame:GetWidth();
+ end
+ if ( not height ) then
+ height = frame:GetHeight();
+ end
+ if ( label ) then
+ local button = frame.elements[GraphHandler.TEXT][tdx];
+ if ( button ) then
+ local text = getglobal(button:GetName().."T");
+ text:SetText(label);
+ text:SetPoint("BOTTOM", frame, "BOTTOM", 0, -28);
+ text:SetVertexColor(1.0, 1.0, 1.0);
+ text:Show();
+ tdx = tdx + 1;
+ end
+ end
+ if ( texth ) then
+ local linesh = 0;
+ for _,_ in texth do
+ linesh = linesh + 1;
+ end
+ local offset = height/(linesh-1);
+ for label,tick in texth do
+ local line = frame.elements[GraphHandler.LINE][ldx];
+ if ( line ) then
+ ldx = ldx + 1;
+ line:SetHeight(1);
+ line:SetWidth(width);
+ line:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, tick*offset);
+ line:SetAlpha(0.5);
+ line:Show();
+ local button = frame.elements[GraphHandler.TEXT][tdx];
+ if ( button ) then
+ local text = getglobal(button:GetName().."T");
+ if ( type(label) ~= "string" ) then
+ label = string.format("%3d", label);
+ end
+ text:SetText(label);
+ text:SetPoint("LEFT", line, "LEFT", -(text:GetWidth()+4), 0);
+ tdx = tdx + 1;
+ end
+ end
+ end
+ end
+ if ( textv ) then
+ local linesv = 0;
+ for _,_ in textv do
+ linesv = linesv + 1;
+ end
+ local offset = frame.barSpacing + frame.barWidth;
+ for label,tick in textv do
+ local line = frame.elements[GraphHandler.LINE][ldx];
+ if ( line ) then
+ local xpos = tick*offset;
+ ldx = ldx + 1;
+ line:SetHeight(height);
+ line:SetWidth(1);
+ line:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", xpos, 0);
+ line:SetAlpha(0.5);
+ line:Show();
+ local button = frame.elements[GraphHandler.TEXT][tdx];
+ if ( button ) then
+ local text = getglobal(button:GetName().."T");
+ if ( type(label) ~= "string" ) then
+ label = string.format("%3d", label);
+ end
+ text:SetText(label);
+ local wid = text:GetWidth();
+ if ( xpos < wid ) then
+ text:SetPoint("TOPLEFT", line, "BOTTOMLEFT", 0, -4);
+ elseif ( xpos > (width - wid) ) then
+ text:SetPoint("TOPRIGHT", line, "BOTTOMRIGHT", 0, -4);
+ else
+ text:SetPoint("TOP", line, "BOTTOM", 0, -4);
+ end
+ text:Show();
+ tdx = tdx + 1;
+ end
+ end
+ end
+ end
+end
diff --git a/GraphHandler.xml b/GraphHandler.xml
new file mode 100644
index 0000000..40d008a
--- /dev/null
+++ b/GraphHandler.xml
@@ -0,0 +1,211 @@
+
+
+
+
+
+ GraphHandler.InitElements();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterEvent("VARIABLES_LOADED");
+
+
+ GraphHandler.Register(GraphHandler.BAR, this);
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterEvent("VARIABLES_LOADED");
+
+
+ GraphHandler.Register(GraphHandler.LINE, this);
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterEvent("VARIABLES_LOADED");
+
+
+ GraphHandler.Register(GraphHandler.TEXT, this);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:RegisterForClicks("LeftButtonUp");
+
+
+ GraphHandler.Legend.OnClick(arg1);
+
+
+
+
+
+
+ this:SetFrameLevel(this:GetFrameLevel() + 1);
+ this:RegisterEvent("VARIABLES_LOADED");
+
+
+ GraphHandler.Register(GraphHandler.LEGEND, this);
+
+
+ GraphHandler.Legend.OnEnter();
+
+
+ GraphHandler.Legend.OnLeave();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Icons/Fishing-Icon.tga b/Icons/Fishing-Icon.tga
new file mode 100644
index 0000000..0e86986
Binary files /dev/null and b/Icons/Fishing-Icon.tga differ
diff --git a/Icons/MiniMapArrow.blp b/Icons/MiniMapArrow.blp
new file mode 100644
index 0000000..f7f42d9
Binary files /dev/null and b/Icons/MiniMapArrow.blp differ
diff --git a/Icons/MiniMapArrow0.tga b/Icons/MiniMapArrow0.tga
new file mode 100644
index 0000000..9046d30
Binary files /dev/null and b/Icons/MiniMapArrow0.tga differ
diff --git a/Icons/MiniMapArrow10.tga b/Icons/MiniMapArrow10.tga
new file mode 100644
index 0000000..9f580d3
Binary files /dev/null and b/Icons/MiniMapArrow10.tga differ
diff --git a/Icons/MiniMapArrow100.tga b/Icons/MiniMapArrow100.tga
new file mode 100644
index 0000000..f55eb64
Binary files /dev/null and b/Icons/MiniMapArrow100.tga differ
diff --git a/Icons/MiniMapArrow110.tga b/Icons/MiniMapArrow110.tga
new file mode 100644
index 0000000..156d447
Binary files /dev/null and b/Icons/MiniMapArrow110.tga differ
diff --git a/Icons/MiniMapArrow120.tga b/Icons/MiniMapArrow120.tga
new file mode 100644
index 0000000..11f277d
Binary files /dev/null and b/Icons/MiniMapArrow120.tga differ
diff --git a/Icons/MiniMapArrow130.tga b/Icons/MiniMapArrow130.tga
new file mode 100644
index 0000000..6cb802b
Binary files /dev/null and b/Icons/MiniMapArrow130.tga differ
diff --git a/Icons/MiniMapArrow140.tga b/Icons/MiniMapArrow140.tga
new file mode 100644
index 0000000..077af19
Binary files /dev/null and b/Icons/MiniMapArrow140.tga differ
diff --git a/Icons/MiniMapArrow150.tga b/Icons/MiniMapArrow150.tga
new file mode 100644
index 0000000..83cff32
Binary files /dev/null and b/Icons/MiniMapArrow150.tga differ
diff --git a/Icons/MiniMapArrow160.tga b/Icons/MiniMapArrow160.tga
new file mode 100644
index 0000000..ed709e5
Binary files /dev/null and b/Icons/MiniMapArrow160.tga differ
diff --git a/Icons/MiniMapArrow170.tga b/Icons/MiniMapArrow170.tga
new file mode 100644
index 0000000..11ddd43
Binary files /dev/null and b/Icons/MiniMapArrow170.tga differ
diff --git a/Icons/MiniMapArrow180.tga b/Icons/MiniMapArrow180.tga
new file mode 100644
index 0000000..abc2f1c
Binary files /dev/null and b/Icons/MiniMapArrow180.tga differ
diff --git a/Icons/MiniMapArrow190.tga b/Icons/MiniMapArrow190.tga
new file mode 100644
index 0000000..9493656
Binary files /dev/null and b/Icons/MiniMapArrow190.tga differ
diff --git a/Icons/MiniMapArrow20.tga b/Icons/MiniMapArrow20.tga
new file mode 100644
index 0000000..311fcb8
Binary files /dev/null and b/Icons/MiniMapArrow20.tga differ
diff --git a/Icons/MiniMapArrow200.tga b/Icons/MiniMapArrow200.tga
new file mode 100644
index 0000000..0906eff
Binary files /dev/null and b/Icons/MiniMapArrow200.tga differ
diff --git a/Icons/MiniMapArrow210.tga b/Icons/MiniMapArrow210.tga
new file mode 100644
index 0000000..3fc2b8f
Binary files /dev/null and b/Icons/MiniMapArrow210.tga differ
diff --git a/Icons/MiniMapArrow220.tga b/Icons/MiniMapArrow220.tga
new file mode 100644
index 0000000..462226e
Binary files /dev/null and b/Icons/MiniMapArrow220.tga differ
diff --git a/Icons/MiniMapArrow230.tga b/Icons/MiniMapArrow230.tga
new file mode 100644
index 0000000..ee166ff
Binary files /dev/null and b/Icons/MiniMapArrow230.tga differ
diff --git a/Icons/MiniMapArrow240.tga b/Icons/MiniMapArrow240.tga
new file mode 100644
index 0000000..eac0c3d
Binary files /dev/null and b/Icons/MiniMapArrow240.tga differ
diff --git a/Icons/MiniMapArrow250.tga b/Icons/MiniMapArrow250.tga
new file mode 100644
index 0000000..75b96cc
Binary files /dev/null and b/Icons/MiniMapArrow250.tga differ
diff --git a/Icons/MiniMapArrow260.tga b/Icons/MiniMapArrow260.tga
new file mode 100644
index 0000000..561c932
Binary files /dev/null and b/Icons/MiniMapArrow260.tga differ
diff --git a/Icons/MiniMapArrow270.tga b/Icons/MiniMapArrow270.tga
new file mode 100644
index 0000000..3eb4c43
Binary files /dev/null and b/Icons/MiniMapArrow270.tga differ
diff --git a/Icons/MiniMapArrow280.tga b/Icons/MiniMapArrow280.tga
new file mode 100644
index 0000000..53df2b0
Binary files /dev/null and b/Icons/MiniMapArrow280.tga differ
diff --git a/Icons/MiniMapArrow290.tga b/Icons/MiniMapArrow290.tga
new file mode 100644
index 0000000..58b08fe
Binary files /dev/null and b/Icons/MiniMapArrow290.tga differ
diff --git a/Icons/MiniMapArrow30.tga b/Icons/MiniMapArrow30.tga
new file mode 100644
index 0000000..0892650
Binary files /dev/null and b/Icons/MiniMapArrow30.tga differ
diff --git a/Icons/MiniMapArrow300.tga b/Icons/MiniMapArrow300.tga
new file mode 100644
index 0000000..a876d68
Binary files /dev/null and b/Icons/MiniMapArrow300.tga differ
diff --git a/Icons/MiniMapArrow310.tga b/Icons/MiniMapArrow310.tga
new file mode 100644
index 0000000..5a99a45
Binary files /dev/null and b/Icons/MiniMapArrow310.tga differ
diff --git a/Icons/MiniMapArrow320.tga b/Icons/MiniMapArrow320.tga
new file mode 100644
index 0000000..05bb867
Binary files /dev/null and b/Icons/MiniMapArrow320.tga differ
diff --git a/Icons/MiniMapArrow330.tga b/Icons/MiniMapArrow330.tga
new file mode 100644
index 0000000..74d8087
Binary files /dev/null and b/Icons/MiniMapArrow330.tga differ
diff --git a/Icons/MiniMapArrow340.tga b/Icons/MiniMapArrow340.tga
new file mode 100644
index 0000000..142b779
Binary files /dev/null and b/Icons/MiniMapArrow340.tga differ
diff --git a/Icons/MiniMapArrow350.tga b/Icons/MiniMapArrow350.tga
new file mode 100644
index 0000000..e05593b
Binary files /dev/null and b/Icons/MiniMapArrow350.tga differ
diff --git a/Icons/MiniMapArrow40.tga b/Icons/MiniMapArrow40.tga
new file mode 100644
index 0000000..c2bbf91
Binary files /dev/null and b/Icons/MiniMapArrow40.tga differ
diff --git a/Icons/MiniMapArrow50.tga b/Icons/MiniMapArrow50.tga
new file mode 100644
index 0000000..e161fd4
Binary files /dev/null and b/Icons/MiniMapArrow50.tga differ
diff --git a/Icons/MiniMapArrow60.tga b/Icons/MiniMapArrow60.tga
new file mode 100644
index 0000000..a5398f2
Binary files /dev/null and b/Icons/MiniMapArrow60.tga differ
diff --git a/Icons/MiniMapArrow70.tga b/Icons/MiniMapArrow70.tga
new file mode 100644
index 0000000..3c6c756
Binary files /dev/null and b/Icons/MiniMapArrow70.tga differ
diff --git a/Icons/MiniMapArrow80.tga b/Icons/MiniMapArrow80.tga
new file mode 100644
index 0000000..fcc499a
Binary files /dev/null and b/Icons/MiniMapArrow80.tga differ
diff --git a/Icons/MiniMapArrow90.tga b/Icons/MiniMapArrow90.tga
new file mode 100644
index 0000000..145dc6e
Binary files /dev/null and b/Icons/MiniMapArrow90.tga differ
diff --git a/README.md b/README.md
index 7250d1d..e612913 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,2 @@
# FishingBuddy
-WoW 1.12.1 Addon. This is v0.8.9 Beta 11 with my own minor localization fix.
-
-⚠️⚠️⚠️ **PLEASE READ THE DOWNLOAD INSTRUCTIONS** ⚠️⚠️⚠️
-
-⚠️ **This is not your typical download and rename the folder installation.** ⚠️
-
-# Download Instructions:
-
-• Click on the green "Code" button in the top right-ish.
-• Download ZIP
-• Open the "FishingBuddy-main" folder inside the ZIP.
-• Extract all 5 folders, `OutfitDisplayFrame`,`FishingBuddy`, `FB_TrackingFrame`, `FB_Titan`, `FB_OutfitDisplayFrame` into `..Interface\Addons\`
+vanilla world of warcraft addon that I've made updates to in order to fix in-game bugs
diff --git a/changes.txt b/changes.txt
new file mode 100644
index 0000000..5d87af6
--- /dev/null
+++ b/changes.txt
@@ -0,0 +1,263 @@
+Version 0.8.8e
+- Split out FBEnEspagnol addon to a separate download (new feature
+
+Version 0.8.8d
+- Update toc for patch 1.12
+- Small cleanup changes
+
+Version 0.8.8c
+- Handle "Oil Spills" as fishing pools
+- Fix an intermittent text alignment bug in the locations window
+- Make FishingBuddyFu for Fubar 2.0 work nicely (mostly expose some functions)
+
+Version 0.8.8b
+- Add tracking selection menu to locations window
+
+Version 0.8.8a
+- Fix a nil error in the tracking popup if you haven't caught one of the
+ default fish
+- '/fb updatedb' print out a message
+- Grab the names of fish we catch if we don't know it already (old data updating)
+
+Version 0.8.8
+- Improved cycle fish tracking -- right-click to choose fish to graph
+- Update the TastyFish count every time the window is shown during the
+ Exravaganza so that our count is always 'right'
+- Fix window always showing bug
+
+Version 0.8.7g
+- Fix a typo introduced in version f
+- Really, really check for Pat Nagle's Fish Terminator correctly (thanks Saur!)
+
+Version 0.8.7f
+- Put changes from d and e into the same release
+
+Version 0.8.7g
+- Fix a typo introduced in version f
+- Really, really check for Pat Nagle's Fish Terminator correctly
+
+Version 0.8.7f
+- Put changes from d and e into the same release
+
+Version 0.8.7e
+- Fix missing color 'YELLOW'
+- Fix translation errors that were causing string.format errors in German and Spanish
+- Fix problems with the Terminator
+
+Version 0.8.7d
+- Fix broken minimap enable logic for menus
+- Fix nil error in startup conversion of old versions
+
+Version 0.8.7c
+- Fix incompatibility with version 1.11 and highlight text
+
+Version 0.8.7b
+- Clean up event handling some more (only listen when we're fishing)
+- Fix 'doubled' fishing location display for new fishing areas
+
+Version 0.8.7a
+- Hopefully fix an intermittent bug that crashes the client during
+ the Extravaganza when leaving Booty Bay
+- Stop losing the OutfitDisplayFrame outfit when logging out
+- Should correctly reset the Watcher Window for all toons
+- Add in 'FBEnEspagnol' for Spanish-speaking fisherbuddies
+- Use the now-builtin Outfitter 'find by stat' function
+
+Version 0.8.7
+- Integration with Gatherer (depends on the tooltip when you cast)
+- Add a 'hide these icky fish' menu to the watcher window
+- Put the keybinding for 'Suit Up and Go Fishing!' back in
+- Add an option to only fish from pools during the Extravaganza
+- Better (and more) French translation support from krogh
+- Rework debugging output so that people don't get surprised by it anymore
+- Rework zone and subzone storage to reduce space
+- Don't save default values (smaller saved vars, faster loading)
+- Tune event handling for faster world transitions
+- Move a lot of information into tooltips in the display window
+- Removed 'Fast Cast' again since patch 1.10.1 breaks it
+- Fix translation loader to actually work (even in English!)
+- Rewrite Extravaganza code and hopefully fix the crashes
+- Add an offset menu to handle differences between game and machine time
+- Fix the display bug when switching between locations and fishes
+- If more than one outfit switcher is available, allow a choice
+- Don't allow a recast if the fishing loot window is up
+- Add 'updatedb' command to link info for fish with missing data (can disconnect!)
+
+Version 0.8.6h
+- Fast Cast is back!
+
+Version 0.8.6g
+- Fixed a nil reference bug in binding the keys that happens to some people (but
+ this makes easy cast not work, I still need to figure out what's happening)
+- Made the Fish Watcher window relative to UIParent and implement 'hover' dragging
+- Fixed the right-click menu in InfoBar support
+- Made click-to-move support a little more predictable. If you don't have a casting
+ modifer set, then click-to-move is turned off while you're fishing.
+
+Version 0.8.6f
+- Remove some debugging that broke when DevTools wasn't installed
+
+Version 0.8.6e
+- Easy Cast is back (Fast Cast is no more). Thanks to the Cosmos team who
+ figured out the appropriate place for hooking in the handling code -- it
+ was a snap to add in!
+- Removed the "Suit up and go fishing" stuff since we don't need it any more
+
+Version 0.8.6d
+- Fix a bunch of small errors that never showed up before
+- Add 'mouse fishing' option that binds the middle button (BUTTON3) to
+ 'cast now' (may not be necessary since 'Suit up and go fishing' works...)
+
+Version 0.8.6c
+- Mark OutfitDisplayFrame as version 1.10 compatible
+
+Version 0.8.6b
+- Update for patch 1.10 (11000)
+- Partial Spanish translation, thanks to fili
+- Some fixes that now don't make much difference because of 1.10
+
+Version 0.8.6a
+- Fixes for handling Eternium enchant correctly
+- Fix bug in 'Suit up and go fishing' handler
+
+Version 0.8.6
+- Rework easy cast to work with 1.10 -- no dice yet though :-(
+- Add "Suit up and go fishing" binding for an alternate 1.10 when "Easy Cast" no longer works
+- Outfitter support
+- Translation handling completely rewritten to eliminate missing strings
+ in translations
+- Fix for Eternium Line enchant (the tooltip string changed)
+
+Version 0.8.5g
+- Include OutfitDisplayFrame fix for nil error when fewer than five bags
+
+Version 0.8.5f
+- Auto-set sound volumes to make the bobber noise stand out (Good suggestion SBaL!)
+
+Version 0.8.5e
+- Don't count "Nat Pagle's Fish Terminator" as a fishing pole, even if it looks like one
+
+Version 0.8.5d
+- Fix a nil error in comparison after we've shrunk a table
+
+Version 0.8.5c
+- Fix nil error in cleanup command
+- Missing string in French translation for checking not to lure while clicking on the
+ bobber (it's still not the right translation though, hint hint!)
+
+Version 0.8.5b
+- Handle defaulting to 'English' correctly if we don't have a valid translation
+
+Version 0.8.5a
+- Fix French localization file
+
+Version 0.8.5
+- Add partial French translation, thanks to Corwin Whitehorn
+- Support for Titan v2.08
+- Support for InfoBar
+- Rewritten to drastically reduce global namespace pollution
+- Rewrote database displays to reduce memory usage
+- Use item ids instead of names in fish database to make things smaller
+- Rewritten graphing subsystem for future improvements
+- Use per-character variable saving to simplify data access and structures
+- Added 'cleanup' command to remove stale settings
+- Add modifier key support for easy cast
+- Show number of Tastyfish caught so far
+- Add partial French translation, thanks to Corwin Whitehorn
+- Try supporting ModWatcher
+- Fix for menu popup outside of minimap button
+- Don't do 'easy lures' if we're about to click on the bobber
+
+Version 0.8.4f
+- Change line endings to DOS again, seems to fix some LUA loading errors
+- Fix location scrollbar position for 1.9
+- Update to new numbering scheme for version
+- Fix a bug catching tracking fish in the last week of the year
+- Fix some small bugs that affect brand-new toons
+- Notice if we can't display fish tooltips instead of disconnecting
+- Fix bug where bringing up the outfit window would lose
+ what you were wearing before
+- Fishing Extravaganza countdown timer
+- Keep track of Tastyfish "schooling" locations
+
+Version 0.8.3
+- Update style and skill messages in outfit display to handle new 'dressing room' feature
+- Make sure that errors in switching outfits don't erase what we changed out of
+- Handle elapsed time even if OutfitDisplayFrame is disabled
+- Make sure we're not already switching outfits before we try again
+- Improved ButtonHole support
+
+Version 0.8.2
+- 'Cycle fish' graphs for the main cycle fish (additional fish coming soon)
+- New minimap button support
+- Display current zone in the fish watcher
+- Show elapsed time in the fish watcher (not perfect yet)
+- Fish watcher frame is moveable
+- Support for 'auto fishing lures'
+- Style points added for some of the Extravaganza rewards
+- Improved support for languages (removed static strings)
+- Support for 'ButtonHole' -- if that addon gets finished it'll be way cool
+- OutfitDisplayFrame support improved
+
+Version 0.8.1d
+- Better German help. Thanks blackrat!
+- '/fb import' import information from Impp's fishinfo, DataFish, or Fishinfo2 databases
+- '/fb current reset' to restart the current session fish counts
+- Some small internal code cleanup
+
+Version 0.8.1
+- Fixed an error in the German help system (I hope!)
+- '/fb watcher unlock/lock/reset' to move the fish watcher
+- Display percentage per zone when viewing 'by fish' so you can find those hot spots
+
+Version 0.8
+- Display your current skill in the watch frame
+- Track fish by zone and subzone (converts old data as you visit your old fishing haunts)
+- Track minimum skill for locations and for fish types
+- Full Titan panel support
+- Basic myAddOns support
+- Keeping up with the Jones' and added 'Easy Lure' just like Mugendai has :-)
+- A much better German translation (outfit switching should work now too) -- thanks blackrat!
+- Sort by number of fish caught
+- Should work with 'click to move' turned on
+- Track 'cycle fish' information (very preliminary)
+- OutfitDisplayFrame is now optional if you have an equipment manager you prefer
+
+Version 0.7.9c
+- Fix the I can't believe it worked! bug when looking for the Fishing skill
+
+Version 0.7.9b
+- It works even if you've never used Fishing Buddy before!
+
+Version 0.7.9
+- Really fix the per-server settings
+
+I aplogize for those people whose options got lost -- this time I got it right! I have
+no idea why the zip file didn't get uploaded last night, but the new one is good. Thank
+you for your patience!
+
+Version 0.7.8
+- a very preliminary German translation
+- myAddOns support
+- prefs are now stored by server for each toon
+
+The Titan panel support is still preliminary -- I want to make it default to 'on' and have a better icon. There are still things I'd like to have options for (like sorting the watch panel various ways and making it movable), but I'm going to concentrate on the outfit pieces so that they work for more situations.
+
+Thanks for all of your support!
+
+Version 0.7.7
+- Fix ugly display when switching between fish and locations
+- Added Titan panel support (ugly icon, need to polish up my image skills and make a nice gold one)
+- Sort the 'Fish Watcher' by name (for now)
+- Added key bindings for window toggle and outfit switching
+- Internal cleanups, prep for storing toon prefs by server
+
+Auto-loot (shift right click) works for me 'as is' -- I'll have to play with key mappings to see if there's one that stops this from working...
+
+Version 0.7.6
+- Add an option to leave off those pesky percentages
+- Add an option to only watch the fish while you're actually fishing
+- Update the version of OutfitDisplayFrame
+
+Version 0.7.5
+- fix a bad memory leak on the outfit display page
diff --git a/future.txt b/future.txt
new file mode 100644
index 0000000..f51b849
--- /dev/null
+++ b/future.txt
@@ -0,0 +1,40 @@
+Future features
+
+- Count tastyfish in your bag instead of as you catch them (lrdx)
+- Built-in notepad (Kiiingy)
+- "fish trash" feature (Jaim Sandar)
+* only fish in schools during Extravaganza (Lrdx)
+- multi-machine database merge (Alcasius)
+* mute everything but bobber sounds (SBaL)
+- current inventory fish count (islandercaleb)
+- more summary information while fishing (time now/session fish now/session) (Xantandor)
+- Grand totals in fish window
+- select specific frame to show when icons are clicked (Talyn)
+- remove quest items from the list of things caught (zino)
+- separate out pool fish from everything else for counting and percentages
+* save the show fish/locations choice (Dark Imakuni)
+* display both lifetime and current fish info in the watcher (LBlaze)
+* Save helm/cloak settings per outfit in ODF (Valzic)
+* remember tastyfish pool locations (KayJayDK)
+*/- Track cycle fish (Bruntlief)
+* Show current zone in watcher (Buio)
+* Force item slot empty in ODF (Dark Imakuni)
+* Minimap icon (Tarklash)
+- Skinning buddy (Devonkross)
+* elapsed fishing time (Anakar)
+* show current skill level in watcher (Valzic)
+* Titan Panel support (Dark Imakuni)
+* Only show counts -- no percentages (Dark Imakuni)
+* Gatherer integration (Vreejack)
+- Recipe list for fish (Paul2200)
+- display total fish caught all time and this session (truefreak)
+- fish caught database per toon (Filius)
+* Outfitter support (lots)
+* Fishing watcher movable (lots)
+* Save fishing level information (Yeoman, RamahP)
+- Lost fish count (RamahP)
+- HUD for fishing (lures, target fish?, counts, etc.)
+- Graphical fish watcher window, i.e. icons with counts
+- Font/size selection for watcher window (Fritos)
+- Auto-open support for fished items (chests, bloated fish, clams)
+- Expand fish pool tracking (i.e. display them like tastyfish schools)
diff --git a/localization.de.lua b/localization.de.lua
new file mode 100644
index 0000000..1384f0a
--- /dev/null
+++ b/localization.de.lua
@@ -0,0 +1,200 @@
+-- Deutsche
+-- lower upper
+-- a umlaut \195\164 \195\132
+-- o umlaut \195\192 \195\150
+-- u umlaut \195\188 \195\156
+
+FishingTranslations["deDE"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "\195\188bersicht, wo welche Fische gefangen wurden",
+ DESCRIPTION2 = "und Handhabung deiner Fischereiausr\195\188stung.",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Anzeige von Fischen nach Fanggebieten",
+ LOCATIONS_TAB = "Fische",
+ OUTFITS_INFO = "W\195\164hlen aus, was du beim Fischen tragen willst",
+ OUTFITS_TAB = "Ausr\195\188stung",
+ OPTIONS_INFO = " Einstellungen",
+ OPTIONS_TAB = "Einstellungen",
+ TRACKING_INFO = "Zeige graphische #NAME#-Anzeige der letzten F\195\164nge",
+ TRACKING_TAB = "Saisonfische",
+
+ POINT = "Punkt",
+ POINTS = "Punkte",
+
+ RAW = "Roher",
+ FISH = "Fische",
+
+ BOBBER_NAME = "Blinker",
+ FISHINGSKILL = "Angeln",
+ HELP = "Hilfe",
+ SWITCH = "wechseln",
+ IMPORT = "importiere",
+ TRACK = "Aufzeichnung",
+ NOTRACK = "Aufzeichnung-nicht",
+ TRACKING = "aufzeichnen",
+
+ -- Thanks Maischter!
+ SCHOOL = "Schwarm", -- e.g. '\195\150lige Schwarzmaul Schwarm'
+ FLOATING_WRECKAGE = "Schwimmende Wrackteile",
+ FLOATING_DEBRIS = "Schwimmende Tr\195\188mmer",
+ ELEM_WATER = "Elementarwasser",
+ OIL_SPILL = "\195\150lpest",
+
+ ADD = "hinzuf\195\188gen",
+ REPLACE = "ersetze",
+ UPDATE = "update",
+ CURRENT = "Session",
+ RESET = "reset",
+ CLEANUP = "cleanup",
+ CHECK = "check",
+ NOW = "now",
+
+ WATCHER = "Watcher",
+ WATCHER_LOCK = "fixieren",
+ WATCHER_UNLOCK = "freigeben",
+
+ UNKNOWN = "unbekannt",
+ WEEKLY = "w\195\182chentlich",
+ HOURLY = "st\195\188ndlich",
+
+ SHOWFISHIES = "Nach Fischnamen",
+ SHOWFISHIES_INFO = "Anzeigen Fischlog gruppiert nach Fischart.",
+ SHOWLOCATIONS = "Nach Fanggebieten",
+ SHOWLOCATIONS_INFO = "Anzeigen Fischlog gruppiert nach Fanggebiet.",
+ SWITCHOUTFIT = "Ausr\195\188stung wechseln",
+ SWITCHOUTFIT_INFO = "Schalter zwischen der Fischereiausstattung und was Sie vorher trugen.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Zeige neue Fische",
+ CONFIG_SHOWNEWFISHIES_INFO = "Zeigt im Chat-Log an, wenn ein neuer Fisch an der gegenw\195\164rtige Position gefangen wird.",
+ CONFIG_FISHWATCH_ONOFF = "Fisch-W\195\164chter",
+ CONFIG_FISHWATCH_INFO = "Zeigt in einer eigenen Chat-Anzeige die Fische an, die an der gegenw\195\164rtigen Location gefangen wurden.",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Zeige Fishing-Skill an",
+ CONFIG_FISHWATCHSKILL_INFO = "Zeigt deinen gegenw\195\164rtigen Fishing-Skill im Fanggebiet an.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Zone des Fanggebietes",
+ CONFIG_FISHWATCHZONE_INFO = "Zeigt die gegenw\195\164rtige Zone im Fanggebiet an.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Nur beim Fischen",
+ CONFIG_FISHWATCHONLY_INFO = "Anzeige nur beim Fischen",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Prozent je Fischart",
+ CONFIG_FISHWATCHPERCENT_INFO = "Zeigt den Prozentsatz der gefangenen Fische je Fischart in der Anzeige",
+ CONFIG_ONLYMINE_ONOFF = "Angel der Fischeriausr\195\188stung",
+ CONFIG_ONLYMINE_INFO = "Wenn aktiviert, wird \"Einfaches Werfen\" nur die Angel der aktuellen Fischereiausr\195\188stung checken (nicht nach weitern/besseren Angeln suchen).",
+ CONFIG_EASYLURES_ONOFF = "Automatischer K\195\182der",
+ CONFIG_EASYLURES_INFO = "Wenn aktiviert, wird falls erforderlich ein K\195\182der an der Angel angebracht, bevor man mit dem Angeln beginnt.",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Zeige Zonen",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Zeigt Zonen und Sub-Zonen an.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Sortiere nach Anzahl gefangener Fische",
+ CONFIG_SORTBYPERCENT_INFO = "Anzeige sortiert nach Zahl der gefangenen Fische, anstelle von Fischnamen.",
+ CONFIG_STVTIMER_ONOFF = "Angelwettbewerb-Timer.",
+ CONFIG_STVTIMER_INFO = "Wenn Sie erm\195\182glicht werden, zeigen Sie einen Countdowntimer f\195\188r den Anfang des Fischens Extravaganza und ein Countdown vom Timer nach links an.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "Verwenden Sie ButtonHole",
+ CONFIG_USEBUTTONHOLE_INFO = "Wenn es erm\195\182glicht wird, steuert das ButtonHole-addon die minimaptaste. Nehmen bewirkt auf dem folgenden LOGON.",
+
+ CONFIG_SKILL_INFO = "Gesamtausstattungs-Bonus.",
+ CONFIG_SKILL_TEXT = "Angeln ",
+ CONFIG_STYLISH_INFO = "Styling-Punkte, inspiriert durch die Draznars Fishing-FAQ auf den (englischen) WoW-Foren.",
+ CONFIG_STYLISH_TEXT = "Styling: ",
+
+ CLICKTOSWITCH_ONOFF = "Zum Wechseln der Ausr\195\188stung klicken.",
+ CLICKTOSWITCH_INFO = "Wenn aktiviert, wechselt ein Linksklcik die Ausr\195\188stung, statt nur das #NAME#-Fenster zu \195\182ffnen.",
+
+ LEFTCLICKTODRAG = "Link-Klicken zum Schleppen",
+
+ MINIMAPBUTTONPLACEMENT = "Ikon-Plazierung",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Erlaubt dir, das #NAME#-Ikon um die Minimap zu verschieben",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Anzeigen des Minimapikons",
+ CONFIG_MINIMAPBUTTON_INFO = "Zeige #NAME#-Ikon auf der Minimap an.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Erh\195\182hen Sie Fischent\195\182ne",
+ CONFIG_ENHANCESOUNDS_INFO = "Maximieren Sie Klangvolumen und setzen Sie umgebende Ausgabe herab, um das bobber noise zu lassen wahrnehmbareres beim Fischen.",
+
+ -- messages
+ FAILEDINIT = "Initialisierte nicht richtig.",
+ IMPORTMSG = "Importierte '%s'-Datenbank.",
+ NOIMPORTMSG = "Datenbanken Impp, DataFish oder FishInfo2 nicht gefunden.",
+ ADDFISHIEMSG = "Hinzuf\195\188gen von %s Position %s.",
+ CURSORBUSY = "Konnte Ausr\195\188stung nicht wechseln, da Computer mit anderen Aktivit\195\164ten besch\195\164ftigt!",
+ NOOUTFITDEFINED = "Sie haben keine Ausr\195\188stungsteile in Ihrer Fischenausstattung angegeben.",
+ NODATAMSG = "Keine Fischdaten vorhanden.",
+ TRACKINGMSG = "Aufzeichnung '%s' (%s).",
+ TOOFASTMSG = "Kann Ausr\195\188stung nicht schnell wechseln.",
+ NOTRACKERRMSG = "Kann nicht R\195\188ckstellung saisonfisch entfernen.",
+ NOTRACKMSG = "Saisonfisch '%s' entfernt.",
+ POLEALREADYEQUIPPED = "Sie werden bereits f\195\188r Fischen ausger\195\188stet.",
+ CANTSWITCHBACK = "Sie haben bereits Ihre Fischenausr\195\188stung entfernt.",
+ CLEANUP_NONEMSG = "Keine alten Einstellungen bleiben.",
+ CLEANUP_WILLMSG = "Alte Einstellungen restlich f\195\188r |c#GREEN#%s|r: %s.",
+ CLEANUP_DONEMSG = "Alte Einstellungen entfernt f\195\188r |c#GREEN#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "Es gibt keine alten Einstellungen f\195\188r Spieler |c#GREEN#%s|r.",
+
+ NOTLINKABLE = "",
+
+ TIMETOGO = "Angelwettbewerb beginnt in %d:%02d",
+ TIMELEFT = "Angelwettbewerb endet in %d:%02d",
+
+ STVZONENAME = "Stranglethorn",
+
+ TOOLTIP_HINT = "Hinweis:";
+ TOOLTIP_HINTSWITCH = "wechselt ein Linksklcik die Ausr\195\188stung",
+ TOOLTIP_HINTTOGGLE = "das #NAME#-Fenster zu \195\182ffnen.",
+
+ -- Key binding support
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#",
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "#NAME# anzeigen",
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Ausr\195\188stung wechseln",
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "#NAME# Zonen-Fenster anzeigen",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OUT = "#NAME# Outfit-Fenster anzeigen",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_TRK = "#NAME# Tracking-Fenster anzeigen",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "#NAME# Optionen-Fenster anzeigen",
+};
+
+FishingTranslations["deDE"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Importiere Impp's Fishinfo or FishInfo2 Daten.",
+};
+
+FishingTranslations["deDE"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " wechsele deine Fischereiausr\195\188stung und -kleidung.",
+};
+
+FishingTranslations["deDE"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r oder |c#GREEN##WATCHER_UNLOCK#|r oder |c#GREEN##RESET#|r]",
+ " fixieren .. Fixieren des Watcher-Fenster,",
+ " freigeben .. Entriegeln zum Verschieben,",
+ " reset .. Zur\195\188ckstellen",
+};
+
+FishingTranslations["deDE"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Zur\195\188ckstellen der w\195\164hrend der gegenw\195\164rtigen Session gefangenen Fische.",
+ };
+FishingTranslations["deDE"].CLEANUP_HELP = {
+ "|c#GREEN#/fb #CLEANUP#|r [|c#GREEN##CHECK#|r or |c#GREEN##NOW#|r]",
+ " S\195\164ubern Sie herauf alte Einstellungen. |c#GREEN##CHECK#|r verzeichnet",
+ " die alten Einstellungen, die von |c#GREEN##NOW#|r entfernt werden.",
+};
+
+FishingTranslations["deDE"].TRACKING_HELP = {
+ "|c#GREEN#/fb #TRACK#|r [|c#GREEN##HOURLY#|r oder |c#GREEN##WEEKLY#|r] |c#PURPLE#|r",
+ " zeichne die Angeldauer f\195\188r die angegebenen",
+ " Fischart (ein Shift-Klick Link) auf",
+ "|c#GREEN#/fb #NOTRACK#|r |c#PURPLE#|r",
+ " remove the specified fish (a shift click link) from the tracker",
+ "|c#GREEN#/fb #TRACKING#|r",
+ " eine einfache Anzeige, wann die gefangenen",
+ " Fische gefangen wurden",
+};
+
+FishingTranslations["deDE"].PRE_HELP = {
+ "Du kannst |c#GREEN#/fishingbuddy|r oder |c#GREEN#/fb|r f\195\188r alle Befehle benutzen",
+ "|c#GREEN#/fb|r: schaltet das Fenster ein/aus.",
+ "|c#GREEN#/fb #HELP#|r: zeigt diesern Hilfetext",
+};
+FishingTranslations["deDE"].POST_HELP = {
+ "Du kannst die Fensteraktivierung und den",
+ "Befehl zum Wechseln deiner Ausstattung in den",
+ "\"Tastaturbelegungen\" festlegen.",
+};
diff --git a/localization.es.lua b/localization.es.lua
new file mode 100644
index 0000000..5309d93
--- /dev/null
+++ b/localization.es.lua
@@ -0,0 +1,142 @@
+FishingTranslations["esES"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "Seguimiento de las capturas que has hecho",
+ DESCRIPTION2 = "y maneja tu ca\195\177a de pescar.",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Muestra info de zona de pesca",
+ LOCATIONS_TAB = "Zona",
+ OUTFITS_INFO = "Desviste los que llevas cuando pescas",
+ OUTFITS_TAB = "Equipos",
+ OPTIONS_INFO = "Establece #NAME# opciones",
+ OPTIONS_TAB = "Opciones",
+ TRACKING_INFO = "Muestra #NAME# informaci\195\179on de pesca ciclica",
+ TRACKING_TAB = "Seguimiento",
+
+ POINT = "punto",
+ POINTS = "puntos",
+
+ RAW = "Crudo",
+ FISH = "Pesca",
+
+ BOBBER_NAME = "Anzuelo",
+ FISHINGSKILL = "Pesca",
+ HELP = "ayuda",
+ SWITCH = "cambia",
+ IMPORT = "importa",
+ TRACK = "sigue",
+ NOTRACK = "no siguas",
+ TRACKING = "siguiendo",
+
+ OIL_SPILL = "Perdita de Petro'leo",
+
+ ADD = "a\195\177de",
+ REPLACE = "reemplaza",
+ UPDATE = "actualiza",
+ CURRENT = "actual",
+ RESET = "resetea",
+ CLEANUP = "limpia",
+ CHECK = "chequea",
+ NOW = "ahora",
+
+ NOREALM = "reino desconocido",
+
+ WATCHER = "observador",
+ WATCHER_LOCK = "bloquea",
+ WATCHER_UNLOCK = "desbloquea",
+
+ UNKNOWN = "Desconocido",
+ WEEKLY = "Semanal",
+ HOURLY = "Por hora",
+
+ KEYS_LABEL_TEXT = "Modificadores:",
+ KEYS_NONE_TEXT = "Ninguno",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "Control",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Muestra Pez",
+ SHOWFISHIES_INFO = "Muestra historial de pesca por tipo de pez.",
+
+ SHOWLOCATIONS = "Ubicaciones",
+ SHOWLOCATIONS_INFO = "Muestra hostorial de pesca por zona de pesca.",
+
+ SWITCHOUTFIT = "Cambia",
+ SWITCHOUTFIT_INFO = "Cambia entre el equipo de pesca y lo que llevabas puesto.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Muestra nuevos peces",
+ CONFIG_SHOWNEWFISHIES_INFO = "Muestra un mensaje en el chat cuando la captura es nueva en el \195\161rea actual.",
+ CONFIG_FISHWATCH_ONOFF = "Observador",
+ CONFIG_FISHWATCH_INFO = "Muestra un texto con la captura en el \195\161rea actual.",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Muestra habilidad actual",
+ CONFIG_FISHWATCHSKILL_INFO = "Muestra habilidad y mods en el \195\161rea de observaci\195\179n.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Muestra zona actual",
+ CONFIG_FISHWATCHZONE_INFO = "Muestra zona actual en el \195\161rea de observaci\195\179n.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Solo cuando pescas",
+ CONFIG_FISHWATCHONLY_INFO = "Solo muestra capturas en el observador si estas pescando actualmente",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Muestra porcentaje capturado",
+ CONFIG_FISHWATCHPERCENT_INFO = "Muestra el porcentaje de cada tipo de pez en el observador",
+ CONFIG_EASYLURES_ONOFF = "Se\195\177uelo facil",
+ CONFIG_EASYLURES_INFO = "Si activado, se aplicar\195\161 un se\195\177uelo a tu ca\195\177a antes de empezar a pescar siempre que lo necesites.",
+ CONFIG_ONLYMINE_ONOFF = "Equipa solo ca\195\177a",
+ CONFIG_ONLYMINE_INFO = "Si activado, captura facil solo cequear\195\161 si llevas la ca\195\177a (p.ej. no buscar\195\161 todas las posibilidades).",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Muestra zonas",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Muestra zonas y subzonas.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Por n\195\186mero de capturas",
+ CONFIG_SORTBYPERCENT_INFO = "Ordena la pantalla con el n\195\186mero de peces capturadas y no por el nombre.",
+ CONFIG_STVTIMER_ONOFF = "Marcador de Fishing Extravaganza",
+ CONFIG_STVTIMER_INFO = "Si activado, muestra la cuenta atras para el comienzo de Fishing Extravaganza y muestra el tiempo restante.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "Usa ButtonHole",
+ CONFIG_USEBUTTONHOLE_INFO = "Si activo, al addon ButtonHole controlar\195\161 el bot\195\179n del minimapa. Hace efecto al siguiente login.",
+
+ CONFIG_SKILL_INFO = "Bonus de equipo total.",
+ CONFIG_SKILL_TEXT = "Pescando ",
+ CONFIG_STYLISH_TEXT = "Estilo: ",
+
+ CONFIG_OUTFITTER_TEXT = "Bonus equipo habilidad: %s\r\nPuntuacion estilo Draznar's: %d ";
+
+ CLICKTOSWITCH_ONOFF = "Click para cambiar",
+ CLICKTOSWITCH_INFO = "Si activado, click-izq. Cambia equipos, sino saltar\195\161la ventana Fishing Buddy.",
+
+ LEFTCLICKTODRAG = "Click-izq para mover",
+
+ MINIMAPBUTTONPLACEMENT = "Posici\195\179n Bot\195\179n",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Permite mover el #NAME# icono alrdedor del minimapa",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Muestra icono minimapa",
+ CONFIG_MINIMAPBUTTON_INFO = "Muestra un #NAME# icono en el minimapa.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Activa sonidos de pesca",
+ CONFIG_ENHANCESOUNDS_INFO = "Maximiza el vol\195\186men y minimiza el vol\195\186men del ambiente para que se aprecie mejor el sonido cuando se pesca.",
+
+ -- messages
+ FAILEDINIT = "No inicializ\195\179 correctamente.",
+ IMPORTMSG = "BaseDatos '%s' importada.",
+ NOIMPORTMSG = "No Impp, DataFish, o FishInfo2 BasesDatos encontradas.",
+ ADDFISHIEMSG = "A\195\177diendo %s a zona %s.",
+ CURSORBUSYMSG = "no pudo cambiar por estar el cursor ocupado!",
+ NOOUTFITDEFINED = "No tienes objetos en tu equipo de pesca.",
+ NODATAMSG = "No datos pesca disponibles.",
+ TRACKINGMSG = "Segumiento '%s' %s.",
+ NOTRACKERRMSG = "No puede borrar pesca ciclica.",
+ NOTRACKMSG = "Pesca ciclica borrada '%s'.",
+ POLEALREADYEQUIPPED = "Ya estas equipado para pescar.",
+ CANTSWITCHBACK = "Ya te has quitado el equipamiento de pesca.",
+ CLEANUP_NONEMSG = "No quedan antig\195\186os ajustes.",
+ CLEANUP_WILLMSG = "Ajustes antig\195\186os quedan para |c#GREEN#%s|r: %s.",
+ CLEANUP_DONEMSG = "Borrados ajustes antig\195\186os para |c#GREEN#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "No hay ajustes antig\195\186os para jugador |c#GREEN#%s|r.",
+
+ NOTLINKABLE = "",
+
+ TIMETOGO = "Extravaganza comienza en %d:%02d",
+ TIMELEFT = "Extravaganza acaba en %d:%02d",
+
+ STVZONENAME = "Stranglethorn Vale",
+
+ TOOLTIP_HINT = "Consejo:",
+ TOOLTIP_HINTSWITCH = "click para cambiar equipos",
+ TOOLTIP_HINTTOGGLE = "click para mostar #NAME# ventana.",
+};
+
+
diff --git a/localization.fr.lua b/localization.fr.lua
new file mode 100644
index 0000000..274acdc
--- /dev/null
+++ b/localization.fr.lua
@@ -0,0 +1,150 @@
+FishingTranslations["frFR"] = {
+ NAME = "Fishing Buddy";
+ DESCRIPTION1 = "Se souvient des poissons pris et";
+ DESCRIPTION2 = "organise votre \195\169quipement.";
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Affiche les informations de p\195\170che locales";
+ LOCATIONS = "Localisations";
+ OUTFITS_INFO = "Pr\195\169pare votre equipement de p\195\170che";
+ OUTFITS = "Equipement";
+ OPTIONS_INFO = "R\195\168gle les options";
+ OPTIONS = "Options";
+ TRACKING_INFO = "Affiche les donn\195\169es sur les poissons";
+ TRACKING = "Archives";
+
+ POINT = "point";
+ POINTS = "points";
+
+ RAW = "Raw";
+
+ BOBBER_NAME = "Fishing Bobber";
+ FISHINGSKILL = "P\195\170che";
+ HELP = "Aide";
+ SWITCH = "switch";
+ IMPORT = "import";
+ TRACK = "track";
+ NOTRACK = "notrack";
+ TRACKING = "tracking";
+
+ ADD = "add";
+ REPLACE = "replace";
+ UPDATE = "update";
+ CURRENT = "current";
+ RESET = "reset";
+ CLEANUP = "cleanup";
+ CHECK = "check";
+ NOW = "NOW";
+
+ WATCHER = "watcher";
+ WATCHER_LOCK = "lock";
+ WATCHER_UNLOCK = "unlock";
+
+ UNKNOWN = "Inconnu";
+ WEEKLY = "Hebdomadaire";
+ HOURLY = "toutes les heures";
+
+ KEYS_LABEL_TEXT = "Touches:",
+ KEYS_NONE_TEXT = "Aucune",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "CTRL",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Poissons";
+ SHOWFISHIES_INFO = "Affiche vos prises class\195\169es par type de poisson.";
+
+ SHOWLOCATIONS = "Montrer les zones";
+ SHOWLOCATIONS_INFO = "Affiche vos prises class\195\169es par r\195\169gions.";
+
+ SWITCHOUTFIT = "Equipement";
+ SWITCHOUTFIT_INFO = "Vous habille avec votre \195\169quipement de p\195\170che, ou vous r\195\169habille comme avant.";
+
+ CONFIG_SKILL_TEXT = "P\195\170che ";
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Montrer les nouveaux poissons",
+ CONFIG_SHOWNEWFISHIES_INFO = "Affiche un message dans la zone de texte quand un nouveau poisson est p\195\169ch\195\169.",
+ CONFIG_FISHWATCH_ONOFF = "Archives des poissons",
+ CONFIG_FISHWATCH_INFO = "Affiche une zone de texte avec les poissons d\195\169j\195\160 p\195\169ch\195\169s dans la zone courante.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Seulement en p\195\169chant",
+ CONFIG_FISHWATCHONLY_INFO = "Montrer seulement les poissons lorsque vous \195\170tes en train de p\195\169cher.",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Niveau actuel",
+ CONFIG_FISHWATCHSKILL_INFO = "Affiche votre niveau courant en p\195\170che ainsi que les am\195\169liorations dans la zone de texte.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Zone courante",
+ CONFIG_FISHWATCHZONE_INFO = "Affiche la zone courante dans la zone de texte.",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Montrer les pourcentages",
+ CONFIG_FISHWATCHPERCENT_INFO = "Affiche les pourcentages pour chaque type de poissons dans la zone de texte.",
+ CONFIG_EASYCAST_ONOFF = "Lancer la ligne facilement",
+ CONFIG_EASYCAST_INFO = "Si activ\195\169, lorsque votre canne \195\160 p\195\170che est \195\169quip\195\169e, un clic droit lance la ligne.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Trier par quantit\195\169 de poissons",
+ CONFIG_SORTBYPERCENT_INFO = "Trie l'affichage par quantit\195\169 de poissons p\195\169ch\195\169s au lieu du nom.",
+ CONFIG_STVTIMER_ONOFF = "Timer du concours de p\195\170che",
+ CONFIG_STVTIMER_INFO = "Si activ\195\169, un compteur sera affich\195\169 indiquant le temps restant avant le debut et la fin du concours.",
+ CONFIG_USEGATHERER_ONOFF = "Utiliser Gatherer",
+ CONFIG_USEGATHERER_INFO = "Si activ\195\169, un compteur sera affich\195\169 indiquant le temps restant avant le debut et la fin du concours.",
+
+ CLICKTOSWITCH_ONOFF = "Clique pour changer";
+ CLICKTOSWITCH_INFO = "Si activ\195\169, un clic gauche change l'\195\169quipement, si d\195\169sactiv\195\169, affiche la fen\195\170tre.";
+
+ LEFTCLICKTODRAG = "Clique gauche pour bouger";
+
+ MINIMAPBUTTONPLACEMENT = "Position du bouton";
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Permet de bouger le bouton de #NAME# autour de la minimap";
+ CONFIG_MINIMAPBUTTON_ONOFF = "Affiche le bouton de la minimap.";
+ CONFIG_MINIMAPBUTTON_INFO = "Affiche le bouton de #NAME# pr\195\168s de la minimap.";
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Augmentez les bruits de p\195\170che";
+ CONFIG_ENHANCESOUNDS_INFO = "Maximisez le volume sain et r\195\169duisez au minimum le volume ambiant pour faire le bobber \195\169bruiter plus apparent tout en p\195\170chant.";
+
+ TIMETOGO = "Le concours de p\195\170che commence dans %d:%02d";
+ TIMELEFT = "Le concours de p\195\170che se termine dans %d:%02d";
+
+ STVZONENAME = "Vall\195\169e de Strangleronce";
+
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#";
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "Toggle:#NAME#(Fen\195\170tre)";
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Changer l'\195\169quipement";
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "Toggle: #NAME# (Panneau de r\195\169gion)";
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OUT = "Toggle: #NAME# (Panneau d'\195\169quipement)";
+ BINDING_NAME_TOGGLEFISHINGBUDDY_TRK = "Toggle: #NAME# (Panneau de donn\195\169es)";
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "Toggle: #NAME# (Panneau d'options)";
+
+ ABBREV_APRIL = "Avr",
+};
+
+FishingTranslations["frFR"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Importe les donn\195\169es d'Impp's fishinfo ou de FishInfo2.",
+};
+FishingTranslations["frFR"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " Change l'\195\169quipement (si OutfitDisplayFrame ou Outfitter est charg\195\169)",
+};
+FishingTranslations["frFR"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r or |c#GREEN##WATCHER_UNLOCK#|r or |c#GREEN##RESET#|r]",
+ " D\195\169v\195\169rouille pour bouger la fen\195\170tre,",
+ " lock pour arr\195\170ter, reset pour mettre a z\195\169ro",
+};
+FishingTranslations["frFR"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Met a z\195\169ro des poissons pris durant cette session.",
+};
+FishingTranslations["frFR"].TRACKING_HELP = {
+ "|c#GREEN#/fb #TRACK#|r [|c#GREEN##HOURLY#|r or |c#GREEN##WEEKLY#|r] |c#PURPLE#|r",
+ " Surveille le temps de prise pour ce poisson (Maj-Click)",
+ "|c#GREEN#/fb #NOTRACK#|r |c#PURPLE#|r",
+ " Retire ce poisson (Maj-Click) du surveillant",
+ "|c#GREEN#/fb #TRACKING#|r",
+ " Un mauvais affichage du moment de prise d'un poisson surveill\195\169",
+};
+
+FishingTranslations["frFR"].PRE_HELP = {
+ "Vous pouvez utiliser |c#GREEN#/fishingbuddy|r ou |c#GREEN#/fb|r pour toutes les commandes",
+ "|c#GREEN#/fb|r: seul, affiche/cache la fen\195\170tre de FishingBuddy",
+ "|c#GREEN#/fb #HELP#|r: affiche ce message",
+};
+FishingTranslations["frFR"].POST_HELP = {
+ "Vous pouvez assigner une touche pour afficher/cacher la fen\195\170tre et/ou",
+ "changer d'\195\169quipement dans la fen\195\170tre \"Raccourcis\".",
+};
diff --git a/localization.lua b/localization.lua
new file mode 100644
index 0000000..d1d7e81
--- /dev/null
+++ b/localization.lua
@@ -0,0 +1,272 @@
+-- default to American English
+
+FishingTranslations = {};
+FishingTranslations["enUS"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "Keep track of the fish you've caught",
+ DESCRIPTION2 = "and manage your fishing gear.",
+ DESCRIPTION = "#DESCRIPTION1# #DESCRIPTION2#",
+
+ ID = "FishingBuddy",
+
+ WINDOW_TITLE = "#NAME# v#VERSION#",
+ FISHINGTEXTURE = "Interface\\Icons\\Trade_Fishing",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Show fishing location information",
+ LOCATIONS_TAB = "Locations",
+ OUTFITS_INFO = "Pick out what to wear when fishing",
+ OUTFITS_TAB = "Outfits",
+ OPTIONS_INFO = "Set #NAME# options",
+ OPTIONS_TAB = "Options",
+ TRACKING_INFO = "Show #NAME# cycle fish information",
+ TRACKING_TAB = "Tracking",
+
+ POINT = "point",
+ POINTS = "points",
+
+ RAW = "Raw",
+ FISH = "Fish",
+
+ BOBBER_NAME = "Fishing Bobber",
+ FISHINGSKILL = "Fishing",
+ HELP = "help",
+ SWITCH = "switch",
+ IMPORT = "import",
+ TRACK = "track",
+ NOTRACK = "notrack",
+ TRACKING = "tracking",
+ UPDATEDB = "updatedb",
+ FORCE = "force",
+
+ SCHOOL = "School", -- e.g. 'Oily Blackmouth School'
+ FLOATING_WRECKAGE = "Floating Wreckage",
+ FLOATING_DEBRIS = "Floating Debris",
+ ELEM_WATER = "Elemental Water",
+ OIL_SPILL = "Oil Spill",
+
+ ADD = "add",
+ REPLACE = "replace",
+ UPDATE = "update",
+ CURRENT = "current",
+ RESET = "reset",
+ CLEANUP = "cleanup",
+ CHECK = "check",
+ NOW = "now",
+
+ NOREALM = "unknown realm",
+
+ WATCHER = "watcher",
+ WATCHER_LOCK = "lock",
+ WATCHER_UNLOCK = "unlock",
+
+ UNKNOWN = "Unknown",
+ WEEKLY = "weekly",
+ HOURLY = "hourly",
+
+ OFFSET_LABEL_TEXT = "Offset:";
+
+ KEYS_LABEL_TEXT = "Modifiers:",
+ KEYS_NONE_TEXT = "None",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "Control",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Show fish",
+ SHOWFISHIES_INFO = "Display fishing history grouped by fish type.",
+
+ SHOWLOCATIONS = "Locations",
+ SHOWLOCATIONS_INFO = "Display fishing history grouped by where caught.",
+
+ SWITCHOUTFIT = "Switch",
+ SWITCHOUTFIT_INFO = "Switch between the fishing outfit and what you were wearing before.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Show new fish",
+ CONFIG_SHOWNEWFISHIES_INFO = "Display a message in the chat area when a new fish for the current location is caught.",
+ CONFIG_FISHWATCH_ONOFF = "Fish watcher",
+ CONFIG_FISHWATCH_INFO = "Display a text overlay with the fish caught in the current location.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Only while fishing",
+ CONFIG_FISHWATCHONLY_INFO = "Only watch the fish caught when we're actually fishing",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Current skill",
+ CONFIG_FISHWATCHSKILL_INFO = "Display your current fishing skill and mods in the fish watch area.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Current zone",
+ CONFIG_FISHWATCHZONE_INFO = "Display the current zone in the fish watch area.",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Show percentages",
+ CONFIG_FISHWATCHPERCENT_INFO = "Display the percentage of each kind of fish on the watch display",
+ CONFIG_SUITUPFIRST_ONOFF = "Dress for success",
+ CONFIG_SUITUPFIRST_INFO = "Put on your fishing outfit if you're not wearing it when the binding key is pressed",
+ CONFIG_EASYCAST_ONOFF = "Easy Cast",
+ CONFIG_EASYCAST_INFO = "If enabled, then when a fishing pole is equipped and you right click, you will cast the line.",
+ CONFIG_EASYLURES_ONOFF = "Easy Lures",
+ CONFIG_EASYLURES_INFO = "If enabled, a lure will applied to your fishing pole before you start fishing, whenever you need one.",
+ CONFIG_ONLYMINE_ONOFF = "Outfit Pole Only",
+ CONFIG_ONLYMINE_INFO = "If enabled, easy cast will only check for your outfit's fishing pole (i.e. it won't search all possible poles for a match).",
+ CONFIG_MOUSEFISHING_ONOFF = "Mouse fishing",
+ CONFIG_MOUSEFISHING_INFO = "If enabled, left-click throws your line and right-click loots the bobber",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Show Zones",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Display both zones and subzones.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Sort by number caught",
+ CONFIG_SORTBYPERCENT_INFO = "Order displays by the number of fish caught instead of by name.",
+ CONFIG_STVTIMER_ONOFF = "Fishing Extravaganza timer",
+ CONFIG_STVTIMER_INFO = "If enabled, display a countdown timer for the start of the Fishing Extravaganza and a countdown of the timer left.",
+ CONFIG_STVPOOLSONLY_ONOFF = "Only cast in pools",
+ CONFIG_STVPOOLSONLY_INFO = "If enabled, easy cast will only be enabled if the cursor is over a fishing hole.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "Use ButtonHole",
+ CONFIG_USEBUTTONHOLE_INFO = "If enabled, the ButtonHole addon will control the minimap button. Takes effect on the next login.",
+ CONFIG_USEGATHERER_ONOFF = "Use Gatherer",
+ CONFIG_USEGATHERER_INFO = "If enabled, #NAME# will inform Gatherer about fishing holes.",
+
+ CONFIG_SKILL_INFO = "Total outfit skill bonus.",
+ CONFIG_SKILL_TEXT = "Fishing ",
+ CONFIG_STYLISH_INFO = "Style points loosely inspired by Draznar's Fishing FAQ in the WoW forums.",
+ CONFIG_STYLISH_TEXT = "Style: ",
+
+ CONFIG_OUTFITTER_TEXT = "Outfit skill bonus: %s\r\nDraznar's style score: %d ",
+
+ CLICKTOSWITCH_ONOFF = "Click to switch",
+ CLICKTOSWITCH_INFO = "If enabled, a left click switches outfits, otherwise it brings up the Fishing Buddy window.",
+
+ LEFTCLICKTODRAG = "Left-click to drag",
+ RIGHTCLICKFORMENU = "Right-click for menu",
+ WATCHERCLICKHELP = "#LEFTCLICKTODRAG#\n#RIGHTCLICKFORMENU#",
+
+ MINIMAPBUTTONPLACEMENT = "Button Placement",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Allows you to move the #NAME# icon around the minimap",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Display minimap icon",
+ CONFIG_MINIMAPBUTTON_INFO = "Display a #NAME# icon on the minimap.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Enhance fishing sounds",
+ CONFIG_ENHANCESOUNDS_INFO = "Maximize sound volume and minimize ambient volume to make the bobber noise more noticeable while fishing.",
+
+ TRACKINGFRAME = "Tracking Frame",
+ TRACKINGFRAME_RIGHTCLICK = "Right-click to draw graphs for fish",
+ TRACKINGFRAME_LEFTCLICK = "Left-click to choose fish to track",
+-- TRACKINGFRAME_CLICKS = "#TRACKINGFRAME_RIGHTCLICK#\r#TRACKINGFRAME_LEFTCLICK#",
+ TRACKINGFRAME_CLICKS = "#TRACKINGFRAME_RIGHTCLICK#",
+
+ TRACKFISHHOURLY = "Track this fish hourly",
+ TRACKFISHWEEKLY = "Track this fish weekly",
+ HIDEINWATCHER = "Display this fish in the watcher",
+
+ -- messages
+ COMPATIBLE_SWITCHER = "No compatible outfit switcher found.",
+ TOOMANYFISHERMEN = "You have more than one easy cast mod installed.",
+ FAILEDINIT = "Did not initialize correctly.",
+ IMPORTMSG = "Imported '%s' database.",
+ NOIMPORTMSG = "No Impp, DataFish, or FishInfo2 databases found.",
+ ADDFISHIEMSG = "Adding %s to location %s.",
+ ADDSCHOOLMSG = "Adding '%s' to location %s.",
+ CURSORBUSYMSG = "Couldn't switch because the cursor is busy!",
+ NOOUTFITDEFINED = "You don't have any items in your fishing outfit.",
+ NODATAMSG = "No fishing data available.",
+ TRACKINGMSG = "Tracking '%s' %s.",
+ NOTRACKERRMSG = "Can't remove default cycle fish.",
+ NOTRACKMSG = "Removed cycle fish '%s'.",
+ POLEALREADYEQUIPPED = "You're already equipped for fishing.",
+ CANTSWITCHBACK = "You've already removed your fishing equipment.",
+ CLEANUP_NONEMSG = "No old settings remain.",
+ CLEANUP_WILLMSG = "Old settings remaining for |c#RED#%s|r: %s.",
+ CLEANUP_DONEMSG = "Old settings removed for |c#RED#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "There are no old settings for player |c#GREEN#%s|r.",
+ NONEAVAILABLE_MSG = "None available",
+ UPDATEDB_MSG = "Updated %d fish names.",
+
+ MINIMUMSKILL = "Minimum skill: %d",
+ NOTLINKABLE = "",
+ CAUGHTTHISMANY = "Caught %d",
+ CAUGHTTHISTOTAL = "Total %d",
+ FISHTYPES = "Fish types: %d",
+
+ DASH = " -- ",
+ FISHCAUGHT = "%d %s",
+ TIMETOGO = "Extravaganza starts in %d:%02d",
+ TIMELEFT = "Extravaganza ends in %d:%02d",
+ FATLADYSINGS = "|c#RED#Extravaganza is over|r (%d:%02d left)",
+ RIGGLE_BASSBAIT = "^Riggle Bassbait .*: .*! (.*) .*!$",
+
+ STVZONENAME = "Stranglethorn Vale",
+
+ TOOLTIP_HINT = "Hint:",
+ TOOLTIP_HINTSWITCH = "click to switch outfits",
+ TOOLTIP_HINTTOGGLE = "click to show the #NAME# window.",
+
+ -- months for Tracking frame
+ ABBREV_JANUARY = "Jan",
+ ABBREV_APRIL = "Apr",
+ ABBREV_JULY = "Jul",
+ ABBREV_OCTOBER = "Oct",
+ ABBREV_DECEMBER = "Dec",
+
+ -- Key binding support
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#",
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "Toggle #NAME# Window",
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Switch Fishing Outfit",
+ BINDING_NAME_FISHINGBUDDY_GOFISHING = "Suit up and go fishing",
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "Toggle #NAME# Locations Pane",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OUT = "Toggle #NAME# Outfit Pane",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_TRK = "Toggle #NAME# Tracking Pane",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "Toggle #NAME# Options Pane",
+};
+
+FishingTranslations["enUS"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Import Impp's fishinfo or FishInfo2 data.",
+};
+FishingTranslations["enUS"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " swap outfits (if OutfitDisplayFrame or Outfitter is available)",
+};
+FishingTranslations["enUS"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r or |c#GREEN##WATCHER_UNLOCK#|r or |c#GREEN##RESET#|r]",
+ " Unlock the watcher to move the window,",
+ " lock to stop, reset to reset",
+};
+FishingTranslations["enUS"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Reset the fish caught during the current session.",
+};
+FishingTranslations["enUS"].UPDATEDB_HELP = {
+ "|c#GREEN#/fb #UPDATEDB# [#FORCE#]|r",
+ " Try and find the names of all the fish we don't know already.",
+ " An attempt is made to skip 'rare' fish that may disconnect you",
+ " from the server -- use the '#FORCE#' option to override the check.",
+};
+FishingTranslations["enUS"].CLEANUP_HELP = {
+ "|c#GREEN#/fb #CLEANUP#|r [|c#GREEN#f#CHECK#|r or |c#GREEN##NOW#|r]",
+ " Clean up old settings. |c#GREEN##CHECK#|r lists which",
+ " settings will be removed by |c#GREEN##NOW#|r.",
+};
+FishingTranslations["enUS"].TRACKING_HELP = {
+ "|c#GREEN#/fb #TRACK#|r [|c#GREEN##HOURLY#|r or |c#GREEN##WEEKLY#|r] |c#PURPLE#|r",
+ " track the catch times for the specified fish (a shift click link)",
+ "|c#GREEN#/fb #NOTRACK#|r |c#PURPLE#|r",
+ " remove the specified fish (a shift click link) from the tracker",
+ "|c#GREEN#/fb #TRACKING#|r",
+ " a really bad display of when tracked fish were caught",
+};
+
+FishingTranslations["enUS"].PRE_HELP = {
+ "You can use |c#GREEN#/fishingbuddy|r or |c#GREEN#/fb|r for all commands",
+ "|c#GREEN#/fb|r: by itself, toggle the Fishing Buddy window",
+ "|c#GREEN#/fb #HELP#|r: display this message",
+};
+FishingTranslations["enUS"].POST_HELP = {
+ "You can bind both the window toggle and the outfit",
+ " switch command to keys in the \"Key Bindings\" window.",
+};
+
+FishingTranslations["enUS"].HELPMSG = {
+ "@PRE_HELP",
+ "@SWITCH_HELP",
+ "@WATCHER_HELP",
+ "@CURRENT_HELP",
+ "@CLEANUP_HELP",
+ "@IMPORT_HELP",
+ "@TRACKING_HELP",
+ "@UPDATEDB_HELP",
+ " ",
+ "@POST_HELP",
+};
+
diff --git a/localization.ru.lua b/localization.ru.lua
new file mode 100644
index 0000000..9999eae
--- /dev/null
+++ b/localization.ru.lua
@@ -0,0 +1,258 @@
+-- Version : Russian ( by Maus )
+
+
+FishingTranslations["ruRU"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "Отслеживает какую рыбу и где вы поймали",
+ DESCRIPTION2 = "и помогает управлять вашим рыболовским снарежением.",
+ DESCRIPTION = "#DESCRIPTION1# #DESCRIPTION2#",
+
+ ID = "FishingBuddy",
+
+ WINDOW_TITLE = "#NAME# вер. #VERSION#",
+ FISHINGTEXTURE = "Interface\\Icons\\Trade_Fishing",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Отображает информацию о расположении рыбы",
+ LOCATIONS_TAB = "Располож",
+ OUTFITS_INFO = "Выбрать что снарядить во время рыбалки",
+ OUTFITS_TAB = "Снаряжение",
+ OPTIONS_INFO = "Настройки #NAME#",
+ OPTIONS_TAB = "Настройки",
+ TRACKING_INFO = "Отображает #NAME# информацию о рыбе",
+ TRACKING_TAB = "Отслеживание",
+
+ POINT = "очко",
+ POINTS = "очков",
+
+ RAW = "сырой",
+ FISH = "Рыба",
+
+ BOBBER_NAME = "Поплавок",
+ FISHINGSKILL = "Рыбная ловля",
+ HELP = "help",
+ SWITCH = "switch",
+ IMPORT = "import",
+ TRACK = "track",
+ NOTRACK = "notrack",
+ TRACKING = "tracking",
+ UPDATEDB = "updatedb",
+ FORCE = "force",
+
+ SCHOOL = "косяк", -- e.g. 'Oily Blackmouth School'
+ FLOATING_WRECKAGE = "Плавающие обломки",
+ FLOATING_DEBRIS = "Плавающий мусор",
+ ELEM_WATER = "Первородная вода",
+ OIL_SPILL = "Нефтяное пятно",
+
+ ADD = "add",
+ REPLACE = "replace",
+ UPDATE = "update",
+ CURRENT = "current",
+ RESET = "reset",
+ CLEANUP = "cleanup",
+ CHECK = "check",
+ NOW = "now",
+
+ NOREALM = "неизвестный сервер",
+
+ WATCHER = "watcher",
+ WATCHER_LOCK = "lock",
+ WATCHER_UNLOCK = "unlock",
+
+ UNKNOWN = "Unknown",
+ WEEKLY = "weekly",
+ HOURLY = "hourly",
+
+ OFFSET_LABEL_TEXT = "Смещение:";
+
+ KEYS_LABEL_TEXT = "Клавиша:",
+ KEYS_NONE_TEXT = "Нету",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "Control",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Рыба",
+ SHOWFISHIES_INFO = "Показать весь ваш улов, сгруппированный по названию рыбы.",
+
+ SHOWLOCATIONS = "Локации",
+ SHOWLOCATIONS_INFO = "Показать весь ваш улов, отсортированно по зоне ловли.",
+
+ SWITCHOUTFIT = "Переключение",
+ SWITCHOUTFIT_INFO = "Переключение между снаряжением для рыбной ловли и тем, что было надето на вас раньше.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Новая рыба",
+ CONFIG_SHOWNEWFISHIES_INFO = "Выводит сообщение в окно чата, когда вы поймали новую рыбы в текущем месте.",
+ CONFIG_FISHWATCH_ONOFF = "Наблюдатель",
+ CONFIG_FISHWATCH_INFO = "Отображать текстовый фрейм с информацией о пойманных рыбках в текущем месте.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Только во время рыбалки",
+ CONFIG_FISHWATCHONLY_INFO = "Наблюдатель будет активен только во время рыбалки",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Текущий навык",
+ CONFIG_FISHWATCHSKILL_INFO = "Показывать текущий уровень навыка и его модификаторы.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Текущая зона",
+ CONFIG_FISHWATCHZONE_INFO = "Показывать текущую локацию.",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "В процентах",
+ CONFIG_FISHWATCHPERCENT_INFO = "Отображать проценты для каждой рыбки в наблюдателе.",
+ CONFIG_SUITUPFIRST_ONOFF = "Одежда для успеха",
+ CONFIG_SUITUPFIRST_INFO = "Положите на рыбное снаряжение, если вы не используете его когда нажата клавиша связывания.",
+ CONFIG_EASYCAST_ONOFF = "Простая ловля",
+ CONFIG_EASYCAST_INFO = "Если активно, то когда ваша удочка надета и кликните пкм, вы забросите удочку.",
+ CONFIG_EASYLURES_ONOFF = "Авто-наживка",
+ CONFIG_EASYLURES_INFO = "Наживка будет автоматически применяться к вашей удочке, если это необходимо, конечно.",
+ CONFIG_ONLYMINE_ONOFF = "Одеть только удочку",
+ CONFIG_ONLYMINE_INFO = "Если включено, во время простой ловли будет проверяться ваше снаряжение только на наличие удочки.",
+ CONFIG_MOUSEFISHING_ONOFF = "Рыбалка мышкой",
+ CONFIG_MOUSEFISHING_INFO = "Если активно, лкм забросить удочку, пкм выудить.",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Зоны",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Показывать зоны и подзоны.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Сорт по улову",
+ CONFIG_SORTBYPERCENT_INFO = "Упорядочить информацию об улове по его количеству, а не по алфавиту.",
+ CONFIG_STVTIMER_ONOFF = "Рыболовный таймер Рыбомании",
+ CONFIG_STVTIMER_INFO = "Если включено, отображает обратный отсчет времени до начал Рыбомании и обратный отсчет после.",
+ CONFIG_STVPOOLSONLY_ONOFF = "Забрасывать только в водоёмы",
+ CONFIG_STVPOOLSONLY_INFO = "Простая ловля будет применяться только тогда, когда курсор находится над водоёмом.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "Use ButtonHole",
+ CONFIG_USEBUTTONHOLE_INFO = "If enabled, the ButtonHole addon will control the minimap button. Takes effect on the next login.",
+ CONFIG_USEGATHERER_ONOFF = "Использовать Gatherer",
+ CONFIG_USEGATHERER_INFO = "Если активно, #NAME# известит о рыбной лунке.",
+
+ CONFIG_SKILL_INFO = "Общий бонус к навыку от снаряжения.",
+ CONFIG_SKILL_TEXT = "Рыбалка ",
+ CONFIG_STYLISH_INFO = "Style points loosely inspired by Draznar's Fishing FAQ in the WoW forums.",
+ CONFIG_STYLISH_TEXT = "Style: ",
+
+ CONFIG_OUTFITTER_TEXT = "Бонус от снарежения: %s\r\nСчет (в стиле Draznar'а): %d ",
+
+ CLICKTOSWITCH_ONOFF = "Клик для смени набора",
+ CLICKTOSWITCH_INFO = "Левый клик будет переключать выбранный набор экипировки, вместо того, чтобы открывать главное окно #NAME#.",
+
+ LEFTCLICKTODRAG = "[Левый-клик] - перемещение",
+ RIGHTCLICKFORMENU = "[Правый-клик] - меню",
+ WATCHERCLICKHELP = "#LEFTCLICKTODRAG#\n#RIGHTCLICKFORMENU#",
+
+ MINIMAPBUTTONPLACEMENT = "Размещение",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Позволяет перемещать иконку #NAME# у мини-карты",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Иконка у мини карты",
+ CONFIG_MINIMAPBUTTON_INFO = "Показывать иконку #NAME# у мини карте.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Повысить громкость",
+ CONFIG_ENHANCESOUNDS_INFO = "Во время рыбалки, #NAME# увеличит громкость звука до максимума и уменьшит громкость звука окружающей среды до минимума.",
+
+ TRACKINGFRAME = "Tracking Frame",
+ TRACKINGFRAME_RIGHTCLICK = "Right-click to draw graphs for fish",
+ TRACKINGFRAME_LEFTCLICK = "Left-click to choose fish to track",
+-- TRACKINGFRAME_CLICKS = "#TRACKINGFRAME_RIGHTCLICK#\r#TRACKINGFRAME_LEFTCLICK#",
+ TRACKINGFRAME_CLICKS = "#TRACKINGFRAME_RIGHTCLICK#",
+
+ TRACKFISHHOURLY = "Track this fish hourly",
+ TRACKFISHWEEKLY = "Track this fish weekly",
+ HIDEINWATCHER = "Display this fish in the watcher",
+
+ -- messages
+ COMPATIBLE_SWITCHER = "Не найдено подходящего снаряжения.",
+ TOOMANYFISHERMEN = "У вас установлен другой аддон для простой ловли.",
+ FAILEDINIT = "Инициализация выполнена с ошибками.",
+ IMPORTMSG = "Imported '%s' database.",
+ NOIMPORTMSG = "No Impp, DataFish, or FishInfo2 databases found.",
+ ADDFISHIEMSG = "добавлено: %s, к локации %s.",
+ ADDSCHOOLMSG = "добавлено: '%s', к локации %s.",
+ CURSORBUSYMSG = "Couldn't switch because the cursor is busy!",
+ NOOUTFITDEFINED = "You don't have any items in your fishing outfit.",
+ NODATAMSG = "Не обнаружено данных.",
+ TRACKINGMSG = "Tracking '%s' %s.",
+ NOTRACKERRMSG = "Can't remove default cycle fish.",
+ NOTRACKMSG = "Removed cycle fish '%s'.",
+ POLEALREADYEQUIPPED = "You're already equipped for fishing.",
+ CANTSWITCHBACK = "You've already removed your fishing equipment.",
+ CLEANUP_NONEMSG = "Старых настроек не обнаружено.",
+ CLEANUP_WILLMSG = "Обнаружены старые настройки для |c#RED#%s|r: %s.",
+ CLEANUP_DONEMSG = "Старые настройки удалены для |c#RED#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "Не обнаружено старых настроек у игрока |c#GREEN#%s|r.",
+ NONEAVAILABLE_MSG = "Недоступно",
+ UPDATEDB_MSG = "Обновлено название рыбы: %d.",
+
+ MINIMUMSKILL = "Минимальный навык: %d",
+ NOTLINKABLE = "<Создание ссылки невозможно>",
+ CAUGHTTHISMANY = "Поймано %d",
+ CAUGHTTHISTOTAL = "Всего %d",
+ FISHTYPES = "Типы рыб: %d",
+
+ DASH = " -- ",
+ FISHCAUGHT = "%d %s",
+ TIMETOGO = "Начало Рыбомании через %d:%02d",
+ TIMELEFT = "Конец Рыбомании через %d:%02d",
+ FATLADYSINGS = "|c#RED#Окончание Рыбомании|r (осталось %d:%02d)",
+ RIGGLE_BASSBAIT = "^Риггл Мормыш .*: .*! (.*) .*!$",
+
+ STVZONENAME = "Тернистая долина",
+
+ TOOLTIP_HINT = "Cовет:",
+ TOOLTIP_HINTSWITCH = "кликните, чтобы переключить набор снаряжения",
+ TOOLTIP_HINTTOGGLE = "кликните, чтобы открыть окно #NAME#.",
+
+ -- months for Tracking frame
+ ABBREV_JANUARY = "Янв",
+ ABBREV_APRIL = "Апр",
+ ABBREV_JULY = "Ию",
+ ABBREV_OCTOBER = "Окт",
+ ABBREV_DECEMBER = "Дек",
+
+ -- Key binding support
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#",
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "Переключение окна #NAME#",
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Переключение наборов снаряжения",
+ BINDING_NAME_FISHINGBUDDY_GOFISHING = "Экипироваться и начать рыбалку",
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "Переключение окна локаций #NAME#",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OUT = "Переключение окна снаряжения #NAME#",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_TRK = "Переключение окна отслеживания #NAME#",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "Переключение окна опций #NAME#",
+};
+
+FishingTranslations["ruRU"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Import Impp's fishinfo or FishInfo2 data.",
+};
+FishingTranslations["ruRU"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " переключение между набора снаряжения (если доступны OutfitDisplayFrame или Outfitter)",
+};
+FishingTranslations["ruRU"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r or |c#GREEN##WATCHER_UNLOCK#|r or |c#GREEN##RESET#|r]",
+ " unlock - разблокировать окно наблюдателя для его перемещения,",
+ " lock - блокировать, reset - установить позицию по-умолчанию",
+};
+FishingTranslations["ruRU"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Сбросить количество пойманной рыбы в этой сессии.",
+};
+FishingTranslations["ruRU"].UPDATEDB_HELP = {
+ "|c#GREEN#/fb #UPDATEDB# [#FORCE#]|r",
+ " Попробовать найти названия рыб, которые ещё не известны #NAME#.",
+ " Во время поиска не проверяются 'редкие' рыбы, которые могут",
+ " привести к отключения от сервера -- используйте опцию '#FORCE#' для их принудительной проверки.",
+};
+FishingTranslations["ruRU"].CLEANUP_HELP = {
+ "|c#GREEN#/fb #CLEANUP#|r [|c#GREEN#f#CHECK#|r or |c#GREEN##NOW#|r]",
+ " Очистка старых настроек. |c#GREEN##CHECK#|r - выдать список настроек,",
+ " которые будут удалены опцией |c#GREEN##NOW#|r.",
+};
+FishingTranslations["ruRU"].TRACKING_HELP = {
+ "|c#GREEN#/fb #TRACK#|r [|c#GREEN##HOURLY#|r or |c#GREEN##WEEKLY#|r] |c#PURPLE#|r",
+ " track the catch times for the specified fish (a shift click link)",
+ "|c#GREEN#/fb #NOTRACK#|r |c#PURPLE#|r",
+ " remove the specified fish (a shift click link) from the tracker",
+ "|c#GREEN#/fb #TRACKING#|r",
+ " a really bad display of when tracked fish were caught",
+};
+
+FishingTranslations["ruRU"].PRE_HELP = {
+ "You can use |c#GREEN#/fishingbuddy|r or |c#GREEN#/fb|r for all commands",
+ "|c#GREEN#/fb|r: переключение главного окна Fishing Buddy",
+ "|c#GREEN#/fb #HELP#|r: показать это сообщение",
+};
+FishingTranslations["ruRU"].POST_HELP = {
+ "Вы можете назначить клавиши для аддона в окне \"Назначение клавиш\"",
+};
+
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..c4e7252
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,64 @@
+Fishing Buddy
+-------------
+
+ Yet another fishing support add-on. It's a combination of TackleBox,
+ Impp's Fishing Info and a fishing outfit manager all rolled into one. I
+ wrote it both to provide some functionality that was missing from all
+ of the other fishing add-ons I was using and to learn to do add-ons.
+
+ Features:
+ - 'Easy Cast' lets you right-click to cast your line. Use the same mouse
+ button for looting and casting. A double-click will force another cast early
+ - 'Fish Watcher' lets you see the fish you've caught here before (or
+ the fish that you've caught in the current session)
+ - Display your current skill level and the time since you started fishing
+ - Choose your fishing outfit and change into it easily
+ - Support for automatically adding a lure to your fishing pole
+ - Full Titan Panel support
+ - myAddOns support
+ - Preliminary support for tracking 'cycle fish' such as the Nightfin
+ Snapper so you know when to go looking for them
+
+ Example commands:
+ /fishingbuddy or /fb
+ toggle the display of the Fishing Buddy window
+ /fb help
+ print the list of Fishing Buddy commands
+ /fb switch
+ wear your chosen fishing outfit, or change back
+
+ There are two actual add-ons -- the second one, OutfitDisplayFrame,
+ handles the pretty pane to set up your fishing outfit (it's next on
+ the list to be made into something more general that anyone can use).
+ The OutfitDisplayFrame addon can be safely left out if you have a
+ preferred equipment manager.
+
+ alt-clicking on an item in your outfit display will clear it
+
+ Silly stuff:
+ In addition to displaying the fishing bonus for your fishing outfit,
+ it also displays your 'style points' as inferred from Draznar's
+ Fishing FAQ (http://wow.toshimo.com/viewtopic.php?t=272).
+
+ Thanks to the authors of:
+
+ TackleBox -- still adding cool features to keep up with!
+ Impp's Fishing DB
+ QuickWeaponSwap
+ GuildMap
+
+ and many, many others!
+
+ Feel free to send comments to Sutorix=AT=hotmail.com.
+
+Installation
+------------
+
+1. Unzip the 'FishingBuddyVERSION.zip' file
+2. If your unzip program allows you to specify a location, then
+ unzip it into the "Interface/AddOns" folder contained in your
+ WoW folder (the location that WoW was installed)
+3. If your unzip program doesn't let you specify the destination,
+ then find your WoW folder (where it was installed) and drag
+ the 'FishingBuddy' and 'OutfitDisplayFrame' folder into the
+ 'Interface/AddOns' folder.