Files
FishingBuddy/FishingLocationsFrame.lua
Roman Kharitonov 4671cbd714 Merge ilithyia-addons fork (v0.8.8e)
- Russian localization (by Maus)
- FishingSchools: track fishing pools, Gatherer integration
- FishingOutfitter: Outfitter addon integration
- Interface 11200 (patch 1.12 support)
- Improved options system with dependencies
- Better watcher frame positioning
- Various bugfixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 23:45:01 +10:00

665 lines
22 KiB
Lua
Executable File

-- 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