vanilla-wow-addons – Rev 1
?pathlinks?
-- Gatherer
-- Written by Chandora
GATHERER_VERSION="1.0.0";
--
-- Look, seriously a full half of this code is from MapNotes.
-- The only reason I pinched it and put it in here is I couldn't
-- work out how to extend MapNotes to do what I wanted it to do
-- without actually editing the MapNotes files.
--
-- Full credit to the MapNotes guys
--
-- Global variables
GATHERNOTE_UPDATE_INTERVAL = 0.25;
GATHERNOTE_CHECK_INTERVAL = 5.0;
GATHERER_MAXNUMNOTES = 25;
GATHERER_LOADED = false;
GATHERER_CLOSESTCHECK=0.4;
Gatherer_RecordFlag=0;
Gatherer_currentNode="";
Gatherer_currentAction="";
GatherMap_InCity = false;
Gatherer_LoadCount = 0;
Gatherer_MapOpen = false;
Gatherer_UpdateWorldMap = -1;
Gatherer_InWorld = false;
GatherItems = { };
GatherSkills = { };
GatherZoneData = { }; -- Dict[ZoneName, Tuple[Continent, Zone]]
GatherMainMapItem = { };
-- UI variables
Gatherer_WorldMapDetailFrameWidth = 0;
Gatherer_WorldMapDetailFrameHeight = 0;
Gatherer_WorldMapPlayerFrameLevel = 0;
Gather_Player = UnitName("player");
StaticPopupDialogs["GATHERER_VERSION_DIALOG"] = {
text = TEXT(GATHERER_VERSION_WARNING),
button1 = TEXT(OKAY),
showAlert = 1,
timeout = 0,
};
--- ************************************************************************
-- Utilities
function Gatherer_Round(x)
if( x - math.floor(x) > 0.5) then
x = x + 0.5;
end
return math.floor(x);
end
function Gatherer_GetMenuName(inputName)
local name, info;
if (inputName) then
local firstLetter = string.sub(inputName, 1, 2);
local carReplace = {["\195\160"] = "a", ["\195\161"] = "a", ["\195\162"] = "a", ["\195\163"] = "a", ["\195\164"] = "a",
["\195\168"] = "e", ["\195\169"] = "e", ["\195\170"] = "e", ["\195\171"] = "e",
["\195\180"] = "i", ["\195\173"] = "i", ["\195\174"] = "i", ["\195\175"] = "i",
["\195\179"] = "o", ["\195\180"] = "o", ["\195\181"] = "o", ["\195\182"] = "o",
["\195\185"] = "u", ["\195\186"] = "u", ["\195\187"] = "u", ["\195\188"] = "u"}
local found;
for code, repl in carReplace do
firstLetter, found = string.gsub(firstLetter, code, repl);
if (found > 0) then
break;
end
end
if (found > 0) then
name = string.upper(firstLetter)..(string.sub(inputName, 3) or "");
else
if (GetLocale()=="ruRU") then
name = inputName;
else
name = string.upper(string.sub(inputName, 1, 1))..(string.sub(inputName, 2) or "");
end
end
local iconName, _ = Gatherer_GetDB_IconByGatherName(inputName);
iconName = iconName or inputName;
for _, rareMatch in Gather_RareMatch do
if (iconName == rareMatch) then
name = name.." ["..TYPE_RARE.."]";
break;
end
end
if (Gather_SkillLevel[iconName]) then
name = name.." ["..Gather_SkillLevel[iconName].."]";
end
end
return name, info;
end
-- *************************************************************************
-- Init and command line handler
function Gatherer_OnLoad()
this:RegisterEvent("WORLD_MAP_UPDATE");
this:RegisterEvent("CLOSE_WORLD_MAP"); -- never triggered apparently
this:RegisterEvent("LEARNED_SPELL_IN_TAB"); -- follow current skills
this:RegisterEvent("SPELLS_CHANGED"); -- follow current skills
this:RegisterEvent("SKILL_LINES_CHANGED"); -- follow current skills
this:RegisterEvent("SPELLCAST_START");
this:RegisterEvent("SPELLCAST_STOP");
this:RegisterEvent("SPELLCAST_FAILED");
this:RegisterEvent("CHAT_MSG_ADDON");
-- Events for off world non processing
this:RegisterEvent("PLAYER_ENTERING_WORLD");
this:RegisterEvent("PLAYER_LEAVING_WORLD");
-- Addon Loaded and player login/logout events
this:RegisterEvent("ADDON_LOADED");
this:RegisterEvent("PLAYER_LOGIN");
this:RegisterEvent("PLAYER_LOGOUT");
Gatherer_LoadZoneData();
SLASH_GATHER1 = "/gather";
SLASH_GATHER2 = "/gatherer";
SlashCmdList["GATHER"] = function(msg)
Gatherer_Command(msg);
end
end
function Gatherer_Command(command)
local SETTINGS = Gatherer_Settings;
local i,j, cmd, param = string.find(command, "^([^ ]+) (.+)$");
if (not cmd) then cmd = command; end
if (not cmd) then cmd = ""; end
if (not param) then param = ""; end
if ((cmd == "") or (cmd == "help")) then
local useMinimap = "Off";
if (SETTINGS.useMinimap) then useMinimap = "On"; end
local useMainmap = "Off";
if (SETTINGS.useMainmap) then useMainmap = "On"; end
local mapMinder = "Off";
if (SETTINGS.mapMinder) then mapMinder = "On"; end
local minderTime = "5s";
if (SETTINGS.minderTime) then minderTime = SETTINGS.minderTime.."s"; end
Gatherer_ChatPrint("Usage:");
Gatherer_ChatPrint(" |cffffffff/gather (on|off|toggle)|r |cff2040ff["..useMinimap.."]|r - turns the gather minimap display on and off");
Gatherer_ChatPrint(" |cffffffff/gather mainmap (on|off|toggle)|r |cff2040ff["..useMainmap.."]|r - turns the gather mainmap display on and off");
Gatherer_ChatPrint(" |cffffffff/gather minder (on|off|toggle|<n>)|r |cff2040ff["..mapMinder.."]|r - turns the gather map minder on and off (remembers and reopens your last open main map; within "..minderTime..")");
Gatherer_ChatPrint(" |cffffffff/gather dist <n>|r |cff2040ff["..SETTINGS.maxDist.."]|r - sets the maximum search distance for display (0=infinite(default), typical=10)");
Gatherer_ChatPrint(" |cffffffff/gather num <n>|r |cff2040ff["..SETTINGS.number.."]|r - sets the maximum number of items to display (default=10, up to 25)");
Gatherer_ChatPrint(" |cffffffff/gather fdist <n>|r |cff2040ff["..SETTINGS.fadeDist.."]|r - sets a fade distance (in units) for the icons to fade out by (default = 20)");
Gatherer_ChatPrint(" |cffffffff/gather fperc <n>|r |cff2040ff["..SETTINGS.fadePerc.."]|r - sets the percentage for fade at max fade distance (default = 80 [=80% faded])");
Gatherer_ChatPrint(" |cffffffff/gather theme <name>|r |cff2040ff["..SETTINGS.iconSet.."]|r - sets the icon theme: original, shaded (default), iconic or iconshade");
Gatherer_ChatPrint(" |cffffffff/gather idist <n>|r |cff2040ff["..SETTINGS.miniIconDist.."]|r - sets the minimap distance at which the gather icon will become iconic (0 = off, 1-60 = pixel radius on minimap, default = 40)");
Gatherer_ChatPrint(" |cffffffff/gather herbs (on|off|toggle|auto)|r |cff2040ff["..Gatherer_GetFilterVal("herbs").."]|r - select whether to show herb data on the minimap");
Gatherer_ChatPrint(" |cffffffff/gather mining (on|off|toggle|auto)|r |cff2040ff["..Gatherer_GetFilterVal("mining").."]|r - select whether to show mining data on the minimap");
Gatherer_ChatPrint(" |cffffffff/gather treasure (on|off|toggle|auto)|r |cff2040ff["..Gatherer_GetFilterVal("treasure").."]|r - select whether to show treasure data on the minimap");
Gatherer_ChatPrint(" |cffffffff/gather options|r - show/hide UI Options dialog.");
Gatherer_ChatPrint(" |cffffffff/gather report|r - show/hide report dialog.");
Gatherer_ChatPrint(" |cffffffff/gather search|r - show/hide search dialog.");
Gatherer_ChatPrint(" |cffffffff/gather loginfo (on|off)|r - show/hide logon information.");
Gatherer_ChatPrint(" |cffffffff/gather filterrec (herbs|mining|treasure)|r - link display filter to recording for selected gathering type");
Gatherer_ChatPrint(" |cffffffff/gather debug ([on]|off)|r |cff2040ff["..Gatherer_EBoolean[SETTINGS.debug].."]|r - show/hide debug messages");
Gatherer_ChatPrint(" |cffffffff/gather p2p ([on]|off)|r |cff2040ff["..Gatherer_EBoolean[SETTINGS.p2p].."]|r - enable/disable peer-to-peer functions");
elseif (cmd == "options" ) then
if ( GathererUI_DialogFrame:IsVisible() ) then
GathererUI_HideOptions();
else
GathererUI_ShowOptions();
end
elseif (cmd == "debug") then
if (not param or param == "" or param == "on") then
SETTINGS.debug = true;
Gatherer_ChatPrint("Debug messages enabled");
elseif (param == "off") then
SETTINGS.debug = false;
Gatherer_ChatPrint("Debug messages disabled");
end
elseif (cmd == "p2p") then
if (not param or param == "" or param == "on") then
SETTINGS.p2p = true;
Gatherer_ChatPrint("Peer-to-peer functions enabled");
elseif (param == "off") then
SETTINGS.p2p = false;
Gatherer_ChatPrint("Peer-to-peer functions disabled");
end
elseif (cmd == "report" ) then
showGathererInfo(1);
elseif (cmd == "search" ) then
showGathererInfo(2);
elseif (cmd == "loginfo" ) then
local value;
if (not param or param == "") then value = "on"; else value = param; end
Gatherer_ChatPrint("Setting log information display to "..value);
SETTINGS.logInfo = value;
elseif ( cmd == "filterrec" ) then
local value=-1;
if (not param) then
return;
end;
if ( param == "treasure" ) then
value = 0;
elseif ( param == "herbs" ) then
value = 1;
elseif ( param == "mining" ) then
value = 2;
end
if ( value > -1 ) then
if ( SETTINGS.filterRecording[value] ) then
SETTINGS.filterRecording[value] = nil;
Gatherer_ChatPrint("Turned filter/recording link for "..param.." off.");
else
SETTINGS.filterRecording[value] = 1;
Gatherer_ChatPrint("Turned filter/recording link for "..param.." on.");
end
end
elseif (cmd == "on") then
SETTINGS.useMinimap = true;
Gatherer_OnUpdate(0, true);
SETTINGS.useMinimapText = "on";
Gatherer_ChatPrint("Turned gather minimap display on");
elseif (cmd == "off") then
SETTINGS.useMinimap = false;
SETTINGS.useMinimapText = "off";
Gatherer_OnUpdate(0, true);
Gatherer_ChatPrint("Turned gather minimap display off (still collecting)");
elseif (cmd == "toggle") then
SETTINGS.useMinimap = not SETTINGS.useMinimap;
Gatherer_OnUpdate(0, true);
if (SETTINGS.useMinimap) then
Gatherer_ChatPrint("Turned gather minimap display on");
SETTINGS.useMinimapText = "on";
else
Gatherer_ChatPrint("Turned gather minimap display off (still collecting)");
SETTINGS.useMinimapText = "off";
end
elseif (cmd == "dist") then
local i,j, value = string.find(param, "(%d+)");
if (not value) then value = 0; else value = value + 0.0; end
if (value <= 0) then
SETTINGS.maxDist = 0;
else
SETTINGS.maxDist = value + 0.0;
end
Gatherer_ChatPrint("Setting maximum note distance to "..SETTINGS.maxDist);
Gatherer_OnUpdate(0, true);
elseif (cmd == "fdist") then
local i,j, value = string.find(param, "(%d+)");
if (not value) then value = 0; else value = value + 0.0; end
if (value <= 0) then
SETTINGS.fadeDist = 0;
else
SETTINGS.fadeDist = value + 0.0;
end
Gatherer_ChatPrint("Setting fade distance to "..SETTINGS.fadeDist);
Gatherer_OnUpdate(0, true);
elseif (cmd == "fperc") then
local i,j, value = string.find(param, "(%d+)");
if (not value) then value = 0; else value = value + 0.0; end
if (value <= 0) then
SETTINGS.fadePerc = 0;
else
SETTINGS.fadePerc = value + 0.0;
end
Gatherer_ChatPrint("Setting fade percent at fade distance to "..SETTINGS.fadePerc);
Gatherer_OnUpdate(0, true);
elseif ((cmd == "idist") or (cmd == "icondist")) then
local i,j, value = string.find(param, "(%d+)");
if (not value) then value = 0; else value = value + 0; end
if (value <= 0) then
SETTINGS.miniIconDist = 0;
else
SETTINGS.miniIconDist = value + 0;
end
Gatherer_ChatPrint("Setting iconic distance to "..SETTINGS.miniIconDist);
Gatherer_OnUpdate(0, true);
elseif (cmd == "theme") then
if (Gather_IconSet[param]) then
SETTINGS.iconSet = param;
Gatherer_ChatPrint("Gatherer theme set to "..SETTINGS.iconSet);
else
Gatherer_ChatPrint("Unknown theme: "..param);
end
Gatherer_OnUpdate(0, true);
elseif ((cmd == "num") or (cmd == "number")) then
local i,j, value = string.find(param, "(%d+)");
if (not value) then value = 0; else value = value + 0; end
if (value < 0) then
SETTINGS.number = 10;
elseif (value <= GATHERER_MAXNUMNOTES) then
SETTINGS.number = math.floor(value + 0);
else
SETTINGS.number = GATHERER_MAXNUMNOTES;
end
if (SETTINGS.number == 0) then
SETTINGS.useMinimap = false;
SETTINGS.useMinimapText = "off";
Gatherer_OnUpdate(0, true);
Gatherer_ChatPrint("Turned gather minimap display off (still collecting)");
else
if ((SETTINGS.number > 0) and (SETTINGS.useMinimap == false)) then
SETTINGS.useMinimap = true;
SETTINGS.useMinimapText = "on";
Gatherer_ChatPrint("Turned gather minimap display on");
end
Gatherer_ChatPrint("Displaying "..SETTINGS.number.." notes at once");
Gatherer_OnUpdate(0, true);
end
elseif (cmd == "mainmap") then
if ((param == "false") or (param == "off") or (param == "no") or (param == "0")) then
SETTINGS.useMainmap = false;
elseif (param == "toggle") then
SETTINGS.useMainmap = not SETTINGS.useMainmap;
else
SETTINGS.useMainmap = true;
end
if (SETTINGS.useMainmap) then
Gatherer_ChatPrint("Displaying notes in main map");
Gatherer_WorldMapDisplay:SetText("Hide Items");
else
Gatherer_ChatPrint("Not displaying notes in main map");
Gatherer_WorldMapDisplay:SetText("Show Items");
end
if (SETTINGS.useMainmap and SETTINGS.showWorldMapFilters and SETTINGS.showWorldMapFilters == 1) then
GathererWD_DropDownFilters:Show();
end
elseif (cmd == "minder") then
if ((param == "false") or (param == "off") or (param == "no") or (param == "0")) then
SETTINGS.mapMinder = false;
elseif (param == "toggle") then
SETTINGS.mapMinder = not SETTINGS.mapMinder;
elseif (param == "on") then
SETTINGS.mapMinder = true;
else
local i,j, value = string.find(param, "(%d+)");
if (not value) then value = 0; else value = value + 0; end
if (value <= 0) then
SETTINGS.mapMinder = false;
SETTINGS.minderTime = 0;
else
SETTINGS.mapMinder = true;
SETTINGS.minderTime = value + 0;
end
Gatherer_ChatPrint("Setting map minder timeout to "..SETTINGS.minderTime);
end
if (SETTINGS.mapMinder) then
Gatherer_ChatPrint("Map minder activated at "..SETTINGS.minderTime);
else
Gatherer_ChatPrint("Not minding your map");
end
elseif ((cmd == "herbs") or (cmd == "mining") or (cmd == "treasure")) then
if ((param == "false") or (param == "off") or (param == "no") or (param == "0")) then
Gatherer_SetFilter(cmd, "off");
Gatherer_ChatPrint("Not displaying "..cmd.." notes in minimap");
elseif (param == "on" or param == "On" ) then
Gatherer_SetFilter(cmd, "on");
Gatherer_ChatPrint("Displaying "..cmd.." notes in minimap");
elseif (param == "toggle" or param == "") then
local cur = Gatherer_GetFilterVal(cmd);
if ((cur == "on") or (cur == "auto")) then
cur = "off";
Gatherer_SetFilter(cmd, "off");
Gatherer_ChatPrint("Not displaying "..cmd.." notes in minimap");
else
cur = "on";
Gatherer_SetFilter(cmd, "on");
Gatherer_ChatPrint("Displaying "..cmd.." notes in minimap");
end
else
Gatherer_SetFilter(cmd, "auto");
Gatherer_ChatPrint("Displaying "..cmd.." notes in minimap based on ability");
end
Gatherer_OnUpdate(0, true);
GatherMain_Draw();
end
end
-- *************************************************************************
-- Events Handler
function Gatherer_OnEvent(event)
if (not event) then return; end;
-- Enable/Disable event processing for zoning
if (event == "PLAYER_ENTERING_WORLD" ) then
this:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF"); -- standard gathering event
this:RegisterEvent("UI_ERROR_MESSAGE"); -- event added for impossible to gather item
this:RegisterEvent("CHAT_MSG_LOOT"); -- event added for fishing node
Gatherer_InWorld = true;
elseif (event == "PLAYER_LEAVING_WORLD" ) then
this:UnregisterEvent("CHAT_MSG_SPELL_SELF_BUFF"); -- standard gathering event
this:UnregisterEvent("UI_ERROR_MESSAGE"); -- event added for impossible to gather item
this:UnregisterEvent("CHAT_MSG_LOOT"); -- event added for fishing node
Gatherer_InWorld = false;
-- process loot received message for fishing node trigger
elseif ( event == "CHAT_MSG_LOOT" ) then
local _, _, fishItem = string.find(arg1, GATHERER_ReceivesLoot );
local gfishTooltip = Gatherer_ExtractItemFromTooltip()
if ( fishItem and not UnitExists("mouseover") ) then
Gatherer_ReadBuff(event, fishItem, gfishTooltip);
end
-- process event to record, normally not possible gather (low/inexistant skill)
elseif ( event == "UI_ERROR_MESSAGE" ) then
-- process gather error message
-- need to be in standard gather range to get the correct message to process.
if (arg1 and
(strfind(arg1, GATHERER_REQUIRE.." "..OLD_TRADE_HERBALISM) or strfind(arg1, GATHERER_NOSKILL.." "..OLD_TRADE_HERBALISM) or
strfind(arg1, OLD_TRADE_HERBALISM.." "..GATHERER_NOSKILL) or strfind(arg1, GATHERER_REQUIRE.." "..TRADE_MINING) or
strfind(arg1, GATHERER_NOSKILL.." "..TRADE_MINING) or strfind(arg1, TRADE_MINING.." "..GATHERER_NOSKILL))) then
Gatherer_ReadBuff(event);
end
-- process chatmessages
elseif ( event == "CHAT_MSG_SPELL_SELF_BUFF" ) then
Gatherer_ReadBuff(event);
-- process AddOn communication
elseif strfind(event, "CHAT_MSG_ADDON") then
Gatherer_AddonMessageEvent(arg1, arg2, arg3);
-- process tooltips text for 1.12
elseif ( event == "SPELLCAST_START" ) then
if ( arg1 and (arg1 == GATHER_HERBALISM or arg1 == TRADE_MINING or arg1 == TRADE_OPENING or arg1 =="") ) then
Gatherer_Debug("|cffffffffEvent :|r "..event.." => "..arg1);
Gatherer_currentNode = GameTooltipTextLeft1:GetText();
Gatherer_currentAction = arg1;
Gatherer_Debug("Current node: "..(Gatherer_currentNode or "nil"));
Gatherer_RecordFlag=1;
end
elseif ( event == "SPELLCAST_STOP" and Gatherer_RecordFlag == 1 ) then
Gatherer_ReadBuff(event);
Gatherer_currentNode=nil;
elseif ( event == "SPELLCAST_STOP" and Gatherer_RecordFlag == 0 ) then
Gatherer_currentNode=nil;
Gatherer_RecordFlag = 0;
elseif ( event == "SPELLCAST_FAILED" ) then
Gatherer_RecordFlag = 0;
elseif (event == "WORLD_MAP_UPDATE") then
if (WorldMapFrame:IsVisible()) then
local serverTime = GetTime();
if (Gatherer_Settings.mapMinder == true and Gatherer_MapOpen == false) then
-- Enhancement to open to last opened map if we were there less than a minute ago
-- Otherwise, go to the player's current position
local startContinent, startZone;
if (Gatherer_CloseMap and (serverTime - Gatherer_CloseMap.time < Gatherer_Settings.minderTime)) then
startContinent = Gatherer_CloseMap.continent;
startZone = Gatherer_CloseMap.zone;
else
startContinent, startZone = Gatherer_GetCurrentZone();
end
Gatherer_MapOpen = true;
if ( GetCurrentMapContinent()>0 and startZone and startZone > 0 ) then
SetMapZoom(startContinent, startZone);
end
end
Gatherer_MapOpen = true;
local mapContinent = GetCurrentMapContinent();
local mapZone = GetCurrentMapZone();
Gatherer_CloseMap = { continent = mapContinent, zone = mapZone, time = GetTime() };
GatherMain_Draw();
elseif (Gatherer_MapOpen) then
Gatherer_MapOpen = false;
Gatherer_ChangeMap();
GatherMain_Draw();
end
elseif ( event == "CLOSE_WORLD_MAP") then
-- never called apparently
Gatherer_MapOpen = false;
Gatherer_ChangeMap()
GatherMain_Draw();
elseif( event == "ADDON_LOADED") then
if ( myAddOnsFrame_Register ) then
-- myAddons Support
GathererDetails["name"] = "Gatherer";
GathererDetails["version"] = GATHERER_VERSION;
GathererDetails["author"] = "Norganna";
GathererDetails["website"] = "http://gathereraddon.com";
GathererDetails["category"] = MYADDONS_CATEGORY_PROFESSIONS;
GathererDetails["frame"] = "Gatherer";
GathererDetails["optionsframe"] = "GathererUI_DialogFrame";
-- Register the addon in myAddOns
if(myAddOnsFrame_Register) then
myAddOnsFrame_Register(GathererDetails, GathererHelp);
end
end
if (arg1 and string.lower(arg1) == "gatherer") then
Gatherer_Configuration.Load();
GATHERER_LOADED = true;
Gatherer_sanitizeDatabase(GatherItems)
Gatherer_OnUpdate(0, true);
Gatherer_Print("Gatherer p2p v"..GATHERER_VERSION.." -- Loaded!");
if (Gatherer_Settings.useMainmap == true) then
Gatherer_WorldMapDisplay:SetText("Hide Items");
else
Gatherer_WorldMapDisplay:SetText("Show Items");
end
-- Warning at logon on Gatherer Version number change to check for localization zone change (commented, not needed in 1.12)
--if ( GetLocale() == "deDE" and (not Gatherer_Settings.Version or (Gatherer_Settings.Version and Gatherer_Settings.Version ~= GATHERER_VERSION ))) then
-- StaticPopup_Show("GATHERER_VERSION_DIALOG");
--end
-- record current version number in order to identify the data for backup utilities
Gatherer_Settings.Version = GATHERER_VERSION;
-- Get values for World Map once for all
Gatherer_WorldMapDetailFrameWidth = WorldMapDetailFrame:GetWidth();
Gatherer_WorldMapDetailFrameHeight = WorldMapDetailFrame:GetHeight();
Gatherer_WorldMapPlayerFrameLevel = WorldMapPlayer:GetFrameLevel();
-- New backup format allows the user to permenantly save their data
-- in an automatically restoring file "GatherBase.lua"
-- All data in this file will be loaded "under" the saved data every
-- time the addon loads so that in the event of a savedVariables wipe
-- the next time they run WoW, their data will be back to the last
-- backed up point. (This utility will appear in a later version of
-- Gatherer as a Java applet)
if (GatherItemBase ~= nil) then
for c, cd in GatherItems do
for z, zd in cd do
for n,nd in zd do
for i,id in nd do
local matched = 0;
local max = 0;
for j,jd in GatherItemBase[c][z][n] do
if (math.abs(id.x- jd.y) < 0.05) then
matched = j;
end
max = j;
end
if (matched > 0) then
GatherItemBase[c][z][n][matched] = id;
else
GatherItemBase[c][z][n][max+1] = id;
end
end
end
end
end
GatherItems = GatherItemBase;
end
end
elseif ( event == "PLAYER_LOGIN" ) then
local SETTINGS = Gatherer_Settings;
local useMinimap = (SETTINGS.useMinimap) and "On" or "Off";
local useMainmap = (SETTINGS.useMainmap) and "On" or "Off";
local mapMinder = (SETTINGS.mapMinder) and "On" or "Off";
local minderTime = SETTINGS.minderTime.."s";
if ( SETTINGS.logInfo and SETTINGS.logInfo == "on" ) then
Gatherer_Print("[Player: "..Gather_Player..", Theme: "..SETTINGS.iconSet..", Mainmap: "..useMainmap..", Minimap: "..useMinimap..", MaxDist: "..SETTINGS.maxDist.." units, NoteCount: "..SETTINGS.number..", Fade: "..SETTINGS.fadePerc.."% at "..SETTINGS.fadeDist.." units, IconDist: "..SETTINGS.miniIconDist.."px on minimap, MapMinder: "..mapMinder.." ("..minderTime.."), Filters: herbs="..Gatherer_GetFilterVal("herbs")..", mining="..Gatherer_GetFilterVal("mining")..", treasure="..Gatherer_GetFilterVal("treasure").."]");
end
elseif ( event == "PLAYER_LOGOUT" ) then
Gatherer_Configuration.Save();
elseif ( event == "LEARNED_SPELL_IN_TAB" or event == "SPELLS_CHANGED" ) then
local numSkills = tonumber(GetNumSkillLines());
if ( GetNumSkillLines() > 0 ) then
Gatherer_GetSkills();
end
elseif ( event == "SKILL_LINES_CHANGED" ) then
local numSkills = tonumber(GetNumSkillLines());
if ( GetNumSkillLines() > 0 ) then
Gatherer_GetSkills();
end
else
Gatherer_ChatPrint("Gatherer Unknown event: "..event);
end
end
-- *************************************************************************
-- Filter related functions
local filterConversion = {
["herbs"] = 1,
["mining"] = 2,
["treasure"] = 0,
[0] = 0,
[1] = 1,
[2] = 2,
}
function Gatherer_SetFilter(type, value)
local type = filterConversion[type];
if ( type ) then
Gatherer_Settings.filters[type] = value;
end
end
function Gatherer_GetFilterVal(type)
local type = filterConversion[type];
value = Gatherer_Settings.filters[type];
if (not value) then return "auto"; end
return value;
end
function Gatherer_GetFilter(filter)
local value = Gatherer_GetFilterVal(filter);
local filterVal = false;
if (value == "on") then
filterVal = true;
elseif (value == "off") then
filterVal = false;
elseif (value == "auto") then
if (filter == "treasure") then
filterVal = true;
end
if (not GatherSkills) then
filterVal = true;
end
if ((GatherSkills[filter]) and (GatherSkills[filter] > 0)) then
filterVal = true;
end
end
return filterVal;
end
function Gatherer_GetSkills()
local GatherExpandedHeaders = {};
local i, j;
if ( not GatherSkills ) then GatherSkills = {}; end;
Gatherer:UnregisterEvent("SKILL_LINES_CHANGED");
-- search the skill tree for gathering skills
for i=0, GetNumSkillLines(), 1 do
local skillName, header, isExpanded, skillRank, _, _, _, _, _, _, _, _ = GetSkillLineInfo(i);
-- expand the header if necessary
if ( header and not isExpanded ) then
GatherExpandedHeaders[i] = skillName;
end
end
ExpandSkillHeader(0);
for i=1, GetNumSkillLines(), 1 do
local skillName, header, _, skillRank, _, _, _, _, _, _, _, _ = GetSkillLineInfo(i);
-- check for the skill name
if (skillName and not header) then
if (skillName == TRADE_HERBALISM) then
GatherSkills.herbs = skillRank;
elseif (skillName == TRADE_MINING) then
GatherSkills.mining = skillRank;
end
end
-- once we got both, no need to look the rest
if ( GatherSkills.herbs and GatherSkills.mining ) then
break;
end
end
-- close headers expanded during search process
for i=0, GetNumSkillLines() do
local skillName, header, isExpanded, _, _, _, _, _, _, _, _, _ = GetSkillLineInfo(i);
for j in GatherExpandedHeaders do
if ( header and skillName == GatherExpandedHeaders[j] ) then
CollapseSkillHeader(i);
GatherExpandedHeaders[j] = nil;
end
end
end
end
local function random_choice(t)
if not t then return end
local choiceI = nil;
local choiceO = nil;
local n = 0;
for i, o in pairs(t) do
n = n + 1
if math.random() < (1/n) then
choiceI, choiceO = i, o
end
end
return choiceI, choiceO
end
local function selectRandomGather()
-- type: () -> Tuple[GatherName, Gatherer_EGatherType, Continent, Zone, float, float, IconName, EGatherEventType]
-- returns the arguments set for the Gatherer_BroadcastGather function
local randomContinent, continentData = random_choice(GatherItems);
local randomZone, zoneData = random_choice(continentData);
local randomGather, gatherNodes = random_choice(zoneData);
local nodeIndex, randomNode = random_choice(gatherNodes);
Gatherer_ChatNotify('randomly selected: '..table.concat(
{randomContinent, randomZone, randomGather, nodeIndex}, ', '
), Gatherer_ENotificationType.debug);
if not nodeIndex then
return nil
end
local eventType = 1; -- EGatherEventType.no_skill
-- values don't matter, I just hate lua
local FISHING_GATHERS = {['floating wreckage']=0, ['school']=''};
if FISHING_GATHERS[randomGather] then
eventType = 2; -- EGatherEventType.fishing
end
return
randomGather, randomNode.gtype, randomContinent, randomZone, randomNode.x, randomNode.y,
randomNode.icon, eventType
end
-- *************************************************************************
-- Update related functions
local Gatherer_UpdateTicker = 0.0;
local Gatherer_AnnouncePeriod = 10;
local Gatherer_CycleCount = 0;
local Gatherer_SecondsToAnnounce = Gatherer_AnnouncePeriod;
function Gatherer_TimeCheck(timeDelta)
if (not GatherNotes) then
GatherNotes = { timeDiff=0, checkDiff=0 };
else
GatherNotes.checkDiff = GatherNotes.checkDiff + timeDelta;
if (GatherNotes.checkDiff > GATHERNOTE_CHECK_INTERVAL) then
GatherNotes.checkDiff = 0;
Gatherer_OnUpdate(0,true);
end
end
Gatherer_UpdateTicker = Gatherer_UpdateTicker + arg1;
if( Gatherer_UpdateTicker < 1 ) then
return
end
-- reset seconds counter
Gatherer_UpdateTicker = 0.0;
-- the code below will run not more frequently
-- than once a second
Gatherer_SecondsToAnnounce = Gatherer_SecondsToAnnounce - 1
-- Gatherer_Print('Every second '..Gatherer_SecondsToAnnounce..' seconds.')
if Gatherer_SecondsToAnnounce > 0 then
return
end
-- the code below will run not more frequently
-- than once Gatherer_AnnouncePeriod seconds
if Gatherer_Settings.p2p then
local args = {selectRandomGather()};
-- if failed to get a random node skip cycle
if not args[1] then
return
end
Gatherer_CycleCount = Gatherer_CycleCount + 1
if Gatherer_Settings.debug then
Gatherer_ChatPrint('Gatherer: Cycle #'..Gatherer_CycleCount);
Gatherer_ChatNotify(
'Sending random node once in '..Gatherer_AnnouncePeriod..' seconds.',
Gatherer_ENotificationType.sending
);
Gatherer_ChatNotify(
'args to send: '..table.concat(args, ', '), Gatherer_ENotificationType.sending
);
end
Gatherer_BroadcastGather(unpack(args))
end
Gatherer_SecondsToAnnounce = Gatherer_AnnouncePeriod
end
function Gatherer_OnUpdate(timeDelta, force)
if (not GATHERER_LOADED) then
Gatherer_Print("Gatherer not loaded");
return;
end
local SETTINGS = Gatherer_Settings;
if (Gatherer_InWorld == false ) then
return;
end
if (not SETTINGS.useMinimap) then
Gatherer_HideAll();
return;
end
local recalculate = false;
local needsUpdate = false;
if (not GatherNotes) then
GatherNotes = { timeDiff=0, checkDiff=0 };
needsUpdate = true;
else
GatherNotes.timeDiff = GatherNotes.timeDiff + timeDelta;
if (GatherNotes.timeDiff > GATHERNOTE_UPDATE_INTERVAL) then
needsUpdate = true;
end
end
if (force) then
needsUpdate = true;
recalculate = true;
end
if (needsUpdate) then
GatherNotes.timeDiff = 0;
-- Find the closest gathers
local continent, zone = Gatherer_GetCurrentZone();
if ((continent == 0) or (zone == 0)) then
Gatherer_HideAll();
return;
end
local inCity = GatherMap_InCity;
local zoomLevel = Minimap:GetZoom();
local px, py = Gatherer_PlayerPos();
if ((px == 0) and (py == 0)) then
return;
end
local xMovement = 0; if (ClosestGathers and ClosestGathers.px) then xMovement = math.abs(ClosestGathers.px - px); end
local yMovement = 0; if (ClosestGathers and ClosestGathers.py) then yMovement = math.abs(ClosestGathers.py - py); end
if (not ClosestGathers
or ClosestGathers.playerC ~= continent
or ClosestGathers.playerZ ~= zone
or xMovement + yMovement > 0.01) then
recalculate = true;
end
local displayNumber = 10;
if (SETTINGS.number and SETTINGS.number > 0) then
displayNumber = SETTINGS.number;
end
local playerDeltaX = 0;
local playerDeltaY = 0;
if (recalculate == true) then
ClosestGathers = {};
ClosestGathers = Gatherer_FindClosest(displayNumber);
if (ClosestGathers.count > 0) then
ClosestGathers.inCity = inCity;
ClosestGathers.zoomLevel = zoomLevel;
ClosestGathers.scaleX, ClosestGathers.scaleY = Gatherer_GetMapScale(continent, zone, inCity, zoomLevel);
end
else
if ((inCity ~= ClosestGathers.inCity) or (zoomLevel ~= ClosestGathers.zoomLevel)) then
ClosestGathers.inCity = inCity;
ClosestGathers.zoomLevel = zoomLevel;
ClosestGathers.scaleX, ClosestGathers.scaleY = Gatherer_GetMapScale(continent, zone, inCity, zoomLevel);
end
local absX, absY = Gatherer_AbsCoord(continent, zone, px, py);
playerDeltaX = ClosestGathers.playerX - absX;
playerDeltaY = ClosestGathers.playerY - absY;
end
local maxPos = 0;
if (ClosestGathers and ClosestGathers.count > 0) then
local closestPos, closestGather, closestID;
local currentPos = 1;
for closestPos, closestGather in ClosestGathers.items do
local skip_node = 0;
if ( currentPos > SETTINGS.number ) then skip_node =1; end
if ( skip_node == 0 ) then
-- need to position and label the corresponding button
local gatherNote = getglobal("GatherNote"..currentPos);
local gatherNoteTexture = getglobal("GatherNote"..currentPos.."Texture");
local itemDeltaX = closestGather.deltax+playerDeltaX;
local itemDeltaY = closestGather.deltay+playerDeltaY;
local offsX, offsY, gDist = Gatherer_MiniMapPos(itemDeltaX, itemDeltaY, ClosestGathers.scaleX, ClosestGathers.scaleY);
gatherNote:SetPoint("CENTER", Minimap, "CENTER", offsX, -offsY);
local iconSet = SETTINGS.iconSet;
local iDist = SETTINGS.miniIconDist;
if (not iconSet) then iconSet = "shaded"; end
if (not iDist) then iDist = 38; end
local _, _, sDist = Gatherer_MiniMapPos(iDist/10000, 0, ClosestGathers.scaleX, ClosestGathers.scaleY);
if ((iDist > 0) and (gDist > (math.floor(sDist)-1))) then
iconSet = "iconic";
end
local fadeDist = SETTINGS.fadeDist / 1000;
local fadePerc = SETTINGS.fadePerc / 100;
local alpha = 1.0;
local objDist = Gatherer_Pythag(itemDeltaX, itemDeltaY);
if ((fadeDist > 0) and (fadePerc > 0)) then
local distRatio = objDist / fadeDist ;
alpha = 1.0 - (math.min(1.0, math.max(0.0, distRatio)) * fadePerc);
end
local textureType = closestGather.item.gtype;
local textureIcon = closestGather.item.icon;
if ( type(textureType) == "number" ) then
textureType = Gatherer_EGatherType[textureType];
end
if ( type(textureIcon) == "number" ) then
textureIcon = Gatherer_GetDB_IconIndex(textureIcon, textureType);
end
if (not textureIcon) then textureIcon = "default"; end;
if (SETTINGS.iconSet == "iconshade" )
then
iconSet="iconic";
if ( gDist < (math.floor(sDist)-1) )
then
alpha=0.4;
end
end
if (not Gather_IconSet[iconSet]) then iconSet = "shaded"; end
if (not Gather_IconSet[iconSet][textureType]) then textureType = "Default"; end
local selectedTexture = Gather_IconSet[iconSet][textureType][textureIcon];
if (not selectedTexture) then
selectedTexture = Gather_IconSet[iconSet][textureType]["default"];
end
gatherNoteTexture:SetTexture(selectedTexture);
gatherNote:SetFrameLevel(MiniMapTrackingFrame:GetFrameLevel());
gatherNote:SetAlpha(alpha);
-- Added to allow hiding if under min distance
if ( SETTINGS.NoIconOnMinDist ~= nil and SETTINGS.NoIconOnMinDist == 1 ) then
if ( gDist < (math.floor(sDist)-1) ) then
gatherNote:Hide();
else
gatherNote:Show();
end
elseif ( (not SETTINGS.NoIconOnMinDist or SETTINGS.NoIconOnMinDist == 0) and SETTINGS.alphaUnderMinIcon and gDist < (math.floor(sDist)-1) ) then
if ( SETTINGS.iconSet and SETTINGS.iconSet ~= "iconshade" ) then
gatherNote:SetAlpha(SETTINGS.alphaUnderMinIcon / 100);
end
gatherNote:Show();
else
gatherNote:Show();
end
if (currentPos > maxPos) then maxPos = currentPos; end
currentPos = currentPos + 1;
end
skip_node = 0;
end
end
while (maxPos < GATHERER_MAXNUMNOTES) do
maxPos = maxPos+1;
local gatherNote = getglobal("GatherNote"..maxPos);
if ( gatherNote:IsShown() ) then
gatherNote:Hide();
end
end
end
end
-- *************************************************************************
-- UI related functions
function Gatherer_OnClick() -- function changed to be able to ping through the MiniNote (mostly direct copy) (only change: this -> Minimap)
local x, y = GetCursorPosition();
if ( Minimap.GetEffectiveScale ~= nil ) then
x = x / Minimap:GetEffectiveScale();
y = y / Minimap:GetEffectiveScale();
else
x = x / Minimap:GetScale();
y = y / Minimap:GetScale();
end
local cx, cy = Minimap:GetCenter();
x = x + CURSOR_OFFSET_X - cx;
y = y + CURSOR_OFFSET_Y - cy;
if ( sqrt(x * x + y * y) < (Minimap:GetWidth() / 2) ) then
Minimap:PingLocation(x, y);
end
end
-- *************************************************************************
-- Display functions
function Gatherer_HideAll()
local mmPos = 0;
while (mmPos < GATHERER_MAXNUMNOTES) do
mmPos = mmPos+1;
local gatherNote = getglobal("GatherNote"..mmPos);
gatherNote:Hide();
end
end
function Gatherer_CreateNoteObject(noteNumber)
local button;
local overlayFrameNumber = math.floor((noteNumber - 1000) / 100 + 1);
if(getglobal("GatherMain"..noteNumber)) then
button = getglobal("GatherMain"..noteNumber);
else
Gatherer_Debug("create id "..noteNumber.." frame ".. overlayFrameNumber);
button = CreateFrame("Button" ,"GatherMain"..noteNumber, getglobal("GathererMapOverlayFrame"..overlayFrameNumber), "GatherMainTemplate");
button:SetID(noteNumber);
end
return button;
end
function GatherMain_Draw()
local lastUnused = 1000;
local maxNotes = 1600;
local gatherName, gatherData;
local SETTINGS = Gatherer_Settings;
-- prevent the function from running twice at the same time.
if (Gatherer_UpdateWorldMap == 0 ) then return; end;
Gatherer_UpdateWorldMap = 0;
if ((Gatherer_MapOpen) and (SETTINGS.useMainmap)) then
local mapContinent = GetCurrentMapContinent();
local mapZone = GetCurrentMapZone();
if ((mapContinent > 0) and (mapZone > 0) and (GatherItems[mapContinent]) and (GatherItems[mapContinent][mapZone])) then
for gatherName, gatherData in GatherItems[mapContinent][mapZone] do
local gatherType = "Default";
local specificType = "";
local allowed = true;
local minSetSkillLevel = 0;
local idx_count=0;
specificType = Gatherer_FindOreType(gatherName);
if (specificType) then -- Ore
gatherType = 2;
allowed = Gatherer_GetFilter("mining");
else
specificType = Gatherer_FindTreasureType(gatherName);
if (specificType ) then -- Treasure
gatherType = 0;
allowed = Gatherer_GetFilter("treasure");
else
specificType = Gatherer_FindFishType(gatherName);
if ( specificType ) then -- Treasure Fish
gatherType = 0;
allowed = Gatherer_GetFilter("treasure");
else
-- Herb
specificType = gatherName;
gatherType = 1;
allowed = Gatherer_GetFilter("herbs");
end
end
end
if (not specificType) then
specificType = "default";
end
-- extra filtering options
if (SETTINGS) then
if ( SETTINGS.interested and SETTINGS.interested[gatherType] ) then
for interest_index in SETTINGS.interested[gatherType] do
idx_count= idx_count +1;
end
end
if( gatherType == 2 ) then -- Ore
minSetSkillLevel = SETTINGS.minSetOreSkill;
if ( not minSetSkillLevel ) then minSetSkillLevel = -1; end
elseif ( gatherType == 1 ) then -- Herb
minSetSkillLevel = SETTINGS.minSetHerbSkill;
if ( not minSetSkillLevel ) then minSetSkillLevel = -1; end
end
if ( allowed == true and Gather_SkillLevel[specificType] and
minSetSkillLevel > 0 and
(minSetSkillLevel > Gather_SkillLevel[specificType] or
(SETTINGS.rareOre == 1 and Gather_SkillLevel[Gather_RareMatch[specificType]] and
Gather_SkillLevel[specificType] < Gather_SkillLevel[Gather_RareMatch[specificType]] and
minSetSkillLevel > Gather_SkillLevel[Gather_RareMatch[specificType]] ))
) then
allowed = false;
end
end
if ((allowed == true) and
((SETTINGS == nil) or
(SETTINGS.interested == nil) or (idx_count == 0) or SETTINGS.interested[gatherType] == nil or
(SETTINGS.interested[gatherType][specificType] == true or
(SETTINGS.rareOre == 1 and SETTINGS.interested[gatherType][Gather_RareMatch[specificType]])
)
)
) then
for hPos, gatherInfo in gatherData do
local convertedGatherType="";
local numGatherType, numGatherIcon;
if ( lastUnused > 1000 and lastUnused < maxNotes and mod(lastUnused, 100) == 0 ) then
local overlayFrameNumber = math.floor((lastUnused - 1000 )/100 + 1);
getglobal("GathererMapOverlayFrame"..overlayFrameNumber):Show();
elseif (lastUnused < 1100 and not GathererMapOverlayFrame1:IsShown() ) then
GathererMapOverlayFrame1:Show();
end
if ((gatherInfo.x) and (gatherInfo.y) and (gatherInfo.x>0) and (gatherInfo.y>0) and (lastUnused <= maxNotes)) then
local mainNote = Gatherer_CreateNoteObject(lastUnused);
local mnX,mnY;
mnX = gatherInfo.x / 100 * Gatherer_WorldMapDetailFrameWidth;
mnY = -gatherInfo.y / 100 * Gatherer_WorldMapDetailFrameHeight;
if ( SETTINGS and SETTINGS.IconAlpha ~= nil ) then
mainNote:SetAlpha(SETTINGS.IconAlpha / 100);
else
mainNote:SetAlpha(0.8);
end
mainNote:SetPoint("CENTER", "GathererMapOverlayFrame", "TOPLEFT", mnX, mnY);
if ( SETTINGS and SETTINGS.ToggleWorldNotes and SETTINGS.ToggleWorldNotes == 1)
then
mainNote.toolTip = Gatherer_GetMenuName(gatherName);
else
mainNote.toolTip = Gatherer_GetMenuName(specificType);
end
if ( type(gatherType) == "number" ) then
convertedGatherType = Gatherer_EGatherType[gatherType];
numGatherType = gatherType
else
convertedGatherType = gatherType;
numGatherType = Gatherer_EGatherType[gatherType];
end
if (not Gather_IconSet["iconic"][convertedGatherType]) then
gatherType = "Default";
else
gatherType = convertedGatherType;
end
if ( type(specificType) == "number" ) then
specificType = Gatherer_GetDB_IconIndex(specificType, convertedGatherType);
end
local texture = Gather_IconSet["iconic"][convertedGatherType][specificType];
if (not texture) then
texture = Gather_IconSet["iconic"][gatherType]["default"];
end
if ( gatherInfo.gtype == "Default" or gatherInfo.gtype == 3 ) then
texture = Gather_IconSet["iconic"]["Default"]["default"];
end
local mainNoteTexture = getglobal("GatherMain"..lastUnused.."Texture");
mainNoteTexture:SetTexture(texture);
if ( SETTINGS and SETTINGS.IconSize ~= nil ) then
mainNote:SetWidth(SETTINGS.IconSize);
mainNote:SetHeight(SETTINGS.IconSize);
end
-- setting value for editing
if (type(gatherInfo.icon) == "string" ) then
numGatherIcon = Gather_DB_IconIndex[numGatherType];
else
numGatherIcon = gatherInfo.icon;
end
mainNote.continent = mapContinent;
mainNote.zoneIndex = mapZone;
mainNote.gatherName = gatherName;
mainNote.localIndex = hPos;
mainNote.gatherType = numGatherType;
mainNote.gatherIcon = numGatherIcon;
if ( not mainNote:IsShown() ) then
mainNote:Show();
end
lastUnused = lastUnused + 1;
end
end
end
end
end
end
local i=1000;
for i=lastUnused, maxNotes, 1 do
-- Delay code to try to work around the delay display problem, pause for 50 ms each 100 items
local overlayFrameNumber = math.floor((i - 1000) / 100 +1);
if ( i < maxNotes and mod(i, 100) == 0 )
then
getglobal("GathererMapOverlayFrame"..overlayFrameNumber):Hide();
end
local mainNote = getglobal("GatherMain"..i);
if ( mainNote and mainNote:IsShown() ) then
mainNote:SetPoint("CENTER", "GathererMapOverlayFrame", "TOPLEFT", Gatherer_WorldMapDetailFrameWidth+16, Gatherer_WorldMapDetailFrameHeight+16);
end
end
Gatherer_UpdateWorldMap = -1;
end
function Gatherer_FindClosest(num, interested)
local SETTINGS = Gatherer_Settings;
local gatherLocal = {playerC=0,playerZ=0,playerX=0,playerY=0,px=0,py=0,items={},count=0};
if (not GATHERER_LOADED) then return gatherLocal; end
if (Gatherer_InWorld == false ) then return gatherLocal; end
local continent, zone = Gatherer_GetCurrentZone();
if ((continent == 0) or (zone == 0)) then return gatherLocal; end
local px,py = Gatherer_PlayerPos();
if ((px == 0) and (py == 0)) then return gatherLocal; end
local absPx, absPy = Gatherer_AbsCoord(continent, zone, px, py);
gatherLocal = { playerC=continent, playerZ=zone, playerX=absPx, playerY=absPy, px=px, py=py, items={}, count=0 };
local gatherCount = 0;
local maxAllowable = 0;
if ((SETTINGS.maxDist) and (SETTINGS.maxDist > 0)) then
maxAllowable = SETTINGS.maxDist / 1000;
end
if (not GatherItems[continent] or (GatherItems[continent] and not GatherItems[continent][zone])) then return gatherLocal; end
-- local gatherZone, gathersInZone;
-- for gatherZone, gathersInZone in GatherItems[continent] do
local gatherName, gatherData;
for gatherName, gatherData in GatherItems[continent][zone] do
-- for gatherName, gatherData in gathersInZone do
local gatherType = "Default";
local specificType = "";
local allowed = true;
specificType = Gatherer_FindOreType(gatherName);
if (specificType) then -- Ore
gatherType = 2;
allowed = Gatherer_GetFilter("mining");
else
specificType = Gatherer_FindTreasureType(gatherName);
if (specificType) then -- Treasure
gatherType = 0;
allowed = Gatherer_GetFilter("treasure");
else -- Herb
specificType = gatherName;
gatherType = 1;
allowed = Gatherer_GetFilter("herbs");
end
end
if (not specificType) then
specificType = "default";
end
local idx_count=0;
if (SETTINGS) then
if ( SETTINGS.interested and SETTINGS.interested[gatherType] ) then
for interest_index in SETTINGS.interested[gatherType] do
idx_count= idx_count +1;
end
end
if( gatherType == 2 ) then -- Ore
minSetSkillLevel = SETTINGS.minSetOreSkill;
if ( not minSetSkillLevel ) then minSetSkillLevel = -1; end
elseif ( gatherType == 1 ) then -- Herb
minSetSkillLevel = SETTINGS.minSetHerbSkill;
if ( not minSetSkillLevel ) then minSetSkillLevel = -1; end
end
if ( allowed == true and Gather_SkillLevel[specificType] and
minSetSkillLevel > 0 and
(minSetSkillLevel > Gather_SkillLevel[specificType] or
(SETTINGS.rareOre == 1 and Gather_SkillLevel[Gather_RareMatch[specificType]] and
minSetSkillLevel > Gather_SkillLevel[Gather_RareMatch[specificType]] ))
) then
allowed = false;
end
end
if ((allowed == true) and
((SETTINGS == nil) or
(SETTINGS.interested == nil) or (idx_count == 0) or SETTINGS.interested[gatherType] == nil or
(SETTINGS.interested[gatherType][specificType] == true or
(SETTINGS.rareOre == 1 and SETTINGS.interested[gatherType][Gather_RareMatch[specificType]])
)
)
) then
local maxNum=100;
local gatherInfo;
for _, gatherInfo in gatherData do
local absHx;
local absHy;
if ((not gatherInfo.gtype) or (gatherInfo.gtype == "")) then
gatherInfo.gtype = gatherType;
end
if ((not gatherInfo.icon) or (gatherInfo.icon == "")) then
gatherInfo.icon = Gatherer_GetDB_IconIndex(specificType, gatherType);
end
absHx, absHy = Gatherer_AbsCoord(continent, zone, gatherInfo.x/100, gatherInfo.y/100);
-- absHx, absHy = Gatherer_AbsCoord(continent, gatherZone, gatherInfo.x/100, gatherInfo.y/100); absHx = math.floor(absHx * 100000)/100000;
absHy = math.floor(absHy * 100000)/100000;
if ((absHx ~= 0) and (absHy ~= 0)) then
local maxLocalPos = 0;
local replCandidate = 0;
local dist, deltaX, deltaY = Gatherer_Distance(absPx, absPy, absHx, absHy);
if ((maxAllowable == 0) or (dist < maxAllowable)) then
local localPos, localInfo;
for localPos, localInfo in gatherLocal.items do
if ( localPos <= num ) then
if (localPos > maxLocalPos) then maxLocalPos = localPos; end
-- take node at the same approximate spot into consideration
if ( (abs(gatherInfo.x - localInfo.item.x) <= GATHERER_CLOSESTCHECK or
Gatherer_Round(gatherInfo.x * 10) == Gatherer_Round(localInfo.item.x * 10)) and
(abs(gatherInfo.y - localInfo.item.y) <= GATHERER_CLOSESTCHECK or
Gatherer_Round(gatherInfo.y * 10) == Gatherer_Round(localInfo.item.y * 10)) )
then
replCandidate = maxNum;
maxNum = maxNum + 1;
-- shorter distance
elseif (localInfo.dist > dist) then
if ((replCandidate == 0) or (gatherLocal.items[replCandidate] and (localInfo.dist > gatherLocal.items[replCandidate].dist)))
then
replCandidate = localPos;
end
end
end
end
-- select candidate
if ( maxLocalPos < num ) then
replCandidate = maxLocalPos+1;
elseif ( maxLocalPos == num and gatherLocal.items[replCandidate] and dist > gatherLocal.items[replCandidate].dist ) then
replCandidate = 0;
end
if (replCandidate > 0) then
local setItem = {};
setItem.name = gatherName;
setItem.item = gatherInfo;
setItem.dist = dist;
setItem.deltax = deltaX;
setItem.deltay = deltaY;
gatherLocal["items"][replCandidate] = setItem;
gatherCount = gatherCount+1;
end
end
end
end
end
-- end
end
gatherLocal.count = gatherCount;
return gatherLocal;
end
-- *************************************************************************
-- Coordinates computing related functions
function isMinimapInCity()
local tempzoom = 0;
local inCity = false;
if (GetCVar("minimapZoom") == GetCVar("minimapInsideZoom")) then
if (GetCVar("minimapInsideZoom")+0 >= 3) then
Minimap:SetZoom(Minimap:GetZoom() - 1);
tempzoom = 1;
else
Minimap:SetZoom(Minimap:GetZoom() + 1);
tempzoom = -1;
end
end
if (GetCVar("minimapInsideZoom")+0 == Minimap:GetZoom()) then inCity = true; end
Minimap:SetZoom(Minimap:GetZoom() + tempzoom);
return inCity;
end
function Gatherer_AbsCoord(continent, zone, x, y)
if ((continent == 0) or (zone == 0)) then return x, y; end
local r = GatherRegionData[continent][zone];
local absX = x * r.scale + r.xoffset;
local absY = y * r.scale + r.yoffset;
return absX, absY;
end
function Gatherer_Distance(originX, originY, targetX, targetY)
local dx = (targetX - originX);
local dy = (targetY - originY);
local d = Gatherer_Pythag(dx, dy);
return d, dx, dy;
end
function Gatherer_Pythag(dx, dy)
local d = math.sqrt(dx*dx + dy*dy); -- (a*a) is usually computationally faster than math.pow(a,2)
if (d == 0) then d = 0.0000000001; end -- to avoid divide by zero errors.
return d;
end
function Gatherer_GetMapScale(continent, zone, inCity, zoomLevel)
if ((continent == nil) or (zoomLevel == nil)) then return 0,0; end
if ((not GatherRegionData) or
(not GatherRegionData[continent]) or
(not GatherRegionData[continent].scales) or
(not GatherRegionData[continent].scales[zoomLevel]) or
(not GatherRegionData[continent].scales[zoomLevel].xscale) or
(not GatherRegionData[continent].scales[zoomLevel].yscale)) then
return 0,0;
end
local scaleX = GatherRegionData[continent].scales[zoomLevel].xscale;
local scaleY = GatherRegionData[continent].scales[zoomLevel].yscale;
if (inCity == true) then
local cityScale = GatherRegionData.cityZoom[zoomLevel];
scaleX = scaleX * cityScale;
scaleY = scaleY * cityScale;
end
return scaleX, scaleY;
end
function Gatherer_MiniMapPos(deltaX, deltaY, scaleX, scaleY) -- works out the distance on the minimap
local mapX = deltaX * scaleX;
local mapY = deltaY * scaleY;
local mapDist = 0;
mapDist = Gatherer_Pythag(mapX, mapY);
local mapWidth = Minimap:GetWidth()/2;
local mapHeight = Minimap:GetHeight()/2;
if (Squeenix or (pfUI and pfUI_config["disabled"]["minimap"] ~= "1") or
(simpleMinimap_Skins and simpleMinimap_Skins:GetShape() == "square")) then
if (math.abs(mapX) > mapWidth) then
mapX = (mapWidth)*((mapX<0 and -1) or 1);
end
if (math.abs(mapY) > mapHeight) then
mapY = (mapHeight)*((mapY<0 and -1) or 1);
end
elseif (mapDist >= mapWidth) then
-- Remap it to just inside the minimap, by:converting dx,dy to angle,distance
-- then truncate distance to 58 and convert angle,58 to dx,dy
local flipAxis = 1;
if (mapX == 0) then mapX = 0.0000000001;
elseif (mapX < 0) then flipAxis = -1;
end
local angle = math.atan(mapY / mapX);
mapX = math.cos(angle) * mapWidth * flipAxis;
mapY = math.sin(angle) * mapHeight * flipAxis;
end
return mapX, mapY, mapDist;
end
-- *************************************************************************
-- Recording related functions
-- Test: /script arg1="You perform Herb Gathering on Mageroyal."; Gatherer_ReadBuff("event");
function Gatherer_ReadBuff(event, fishItem, fishTooltip)
local record = false;
local gather, chatline;
local gatherType, gatherIcon, gatherCanonicalName;
local gatherEventType = 0;
if (not arg1 and not event == "SPELLCAST_STOP") then
Gatherer_Print("Gatherer: error, no arg recording aborted.");
Gatherer_RecordFlag = 0;
return;
elseif (arg1) then
chatline = string.gsub(arg1, GATHERER_NOTEXT, "");
end
if ( strfind(event, "CHAT_MSG_LOOT") ) then
-- process loot received message for fishing node recording
gather = Gatherer_FindFishType(fishItem, fishTooltip);
if ( gather ) then
gatherIcon = gather;
gatherType = 0; -- considered as treasure
gatherEventType = 2;
record = true;
end
elseif( strfind(event, "CHAT_MSG") or strfind(event, "CHAT_MSG_SPELL_SELF_BUFF")) then
if (string.find(chatline, HERB_GATHER_STRING)) then
record = true;
gather = string.lower(strsub(chatline, HERB_GATHER_LENGTH, HERB_GATHER_END))
gatherType = 1;
gatherIcon = gather;
elseif (string.find(chatline, ORE_GATHER_STRING)) then
record = true;
gather = string.lower(strsub(chatline, ORE_GATHER_LENGTH, ORE_GATHER_END))
gatherType = 2;
gatherIcon = Gatherer_FindOreType(gather);
if (not gatherIcon) then return; end;
elseif (string.find(chatline, TREASURE_GATHER_STRING)) then
record = true;
gather = string.lower(strsub(chatline, TREASURE_GATHER_LENGTH, TREASURE_GATHER_END));
gatherType = 0;
gatherIcon, gatherCanonicalName = Gatherer_FindTreasureType(gather);
if (not gatherIcon) then return; end;
if ( gatherCanonicalName ) then gather = gatherCanonicalName; end;
end
elseif (strfind(event, "UI_ERROR_MESSAGE") or (strfind(event, "SPELLCAST_STOP") and Gatherer_RecordFlag == 1)) then
-- process event to record, normally not possible gather (low/inexistant skill)
gather = string.lower(Gatherer_ExtractItemFromTooltip());
if ( Gatherer_currentNode and Gatherer_currentNode ~= gather and event == "SPELLCAST_STOP" and Gatherer_RecordFlag == 1) then
gather = string.lower(Gatherer_currentNode);
end;
if (not arg1 and Gatherer_currentAction==nil and event == "SPELLCAST_STOP" and Gatherer_RecordFlag == 1) then
chatline="";
elseif (event ~= "UI_ERROR_MESSAGE" ) then
chatline = Gatherer_currentAction;
end
-- process non gatherable item because of low/lack of skill
if( gather and not gather ~= "" and (strfind(chatline, TRADE_HERBALISM) or strfind(chatline, OLD_TRADE_HERBALISM) or strfind(chatline, GATHER_HERBALISM)) ) then -- Herb
Gatherer_Debug("record Herb");
record = true;
gatherType = 1;
gatherIcon = Gatherer_FindHerbType(gather);
gatherEventType = 1;
elseif (gather and not gather ~= "" and strfind(chatline, TRADE_MINING)) then -- Ore
Gatherer_Debug("record Ore");
record = true;
gatherType = 2;
gatherIcon = Gatherer_FindOreType(gather);
gatherEventType = 1;
elseif(gather and not gather ~= "" and (strfind(chatline, TRADE_OPENING) or chatline=="")) then -- Treasure
Gatherer_Debug("record Treasure");
record = true
gatherType = 0;
gatherIcon, gatherCanonicalName = Gatherer_FindTreasureType(gather);
if ( gatherCanonicalName ) then gather = gatherCanonicalName; end;
gatherEventType = 1;
end
if (not gatherIcon) then
Gatherer_Print("Gatherer: no icon identified, aborting record.");
Gatherer_RecordFlag = 0;
return;
end
if (event == "SPELLCAST_STOP" and Gatherer_RecordFlag == 1) then
gatherEventType = 0;
end
Gatherer_RecordFlag = 0;
else
Gatherer_RecordFlag = 0;
return;
end
if (record == true) then
Gatherer_Debug("record type: "..gatherEventType);
Gatherer_AddGatherHere(gather, gatherType, gatherIcon, gatherEventType);
end
end
local function insertionGatherIndex(gatherList, maxCheckDist, gatherX, gatherY)
-- type: (GatherList, float, float, float) -> Tuple(int, bool, float, float)
-- gatherList - list of the same gather
-- maxCheckDist - two nodes closer than this distance are considered the same node
-- returns: index to insert new gather, whether new node was found, corrected gathering coordinates
local resultIndex = 0;
local lastGather = 0;
local firstNumerationGap = 0;
local count = 0;
local closest = 0;
local newNodeFound = true;
for gatherIndex, gatherData in gatherList do
count = count + 1;
if ( firstNumerationGap == 0 and gatherIndex ~= count ) then
firstNumerationGap = count;
end
local dist, deltaX, deltaY = Gatherer_Distance(gatherX,gatherY, gatherData.x,gatherData.y);
if ((dist < maxCheckDist) and ((closest == 0) or (closest > dist))) then -- same gather
gatherX = (gatherX + gatherData.x) / 2;
gatherY = (gatherY + gatherData.y) / 2;
closest = dist;
resultIndex = gatherIndex;
newNodeFound = false;
end
if (gatherIndex > lastGather) then
lastGather = gatherIndex;
end
end
local thereIsNumerationGap = firstNumerationGap ~= 0;
if (newNodeFound) then
-- need to create a new one (at gatherIndex+1)
resultIndex = lastGather+1;
-- no duplicate but there's a hole, let's fill it
if thereIsNumerationGap then
resultIndex = firstNumerationGap;
end
end
return resultIndex, newNodeFound, gatherX, gatherY
end
function Gatherer_AddGatherToBase(gather, gatherType, gatherC, gatherZ, gatherX, gatherY, iconIndex, gatherEventType, updateCount)
-- type: (GatherName, Gatherer_EGatherType, Continent, Zone, float, float, IconIndex, EGatherEventType, bool) -> bool
-- comparing to the latest official version (2.99.0.0284)
-- this function was brought out into the global space and extended with the updateCount argument.
-- The latter denotes whether the gather count should be incremented.
-- Also it has started to return whether new node was found.
if (not GatherItems[gatherC]) then GatherItems[gatherC] = { }; end
if (not GatherItems[gatherC][gatherZ]) then GatherItems[gatherC][gatherZ] = { }; end
if (not GatherItems[gatherC][gatherZ][gather]) then GatherItems[gatherC][gatherZ][gather] = { }; end
local maxCheckDist = 0.5;
if ( gatherEventType and gatherEventType == 2 ) then maxCheckDist = 1; end
local insertionIndex, newNodeFound;
insertionIndex, newNodeFound, gatherX, gatherY = insertionGatherIndex(
GatherItems[gatherC][gatherZ][gather], maxCheckDist, gatherX, gatherY
);
local countIncrement = 1;
-- when gathered without required skill or received via broacast
if (not updateCount) or (gatherEventType and gatherEventType == 1) then
countIncrement = 0
end
local newCount;
if (GatherItems[gatherC][gatherZ][gather][insertionIndex] == nil) then
GatherItems[gatherC][gatherZ][gather][insertionIndex] = { };
newCount = countIncrement;
else
newCount = GatherItems[gatherC][gatherZ][gather][insertionIndex].count + countIncrement;
end
-- Round off those coordinates
gatherX = math.floor(gatherX * 100)/100;
gatherY = math.floor(gatherY * 100)/100;
assert(type(iconIndex) == 'number')
GatherItems[gatherC][gatherZ][gather][insertionIndex].x = gatherX;
GatherItems[gatherC][gatherZ][gather][insertionIndex].y = gatherY;
GatherItems[gatherC][gatherZ][gather][insertionIndex].gtype = gatherType;
GatherItems[gatherC][gatherZ][gather][insertionIndex].count = newCount;
GatherItems[gatherC][gatherZ][gather][insertionIndex].icon = iconIndex
return newNodeFound;
end
-- this function can be used as an interface by other addons to record things
-- in Gatherer's database, though display is still based only on what is defined
-- in Gatherer items and icons tables.
-- Parameters:
-- gather (string): gather name (string printed in chat)
-- gatherType (number): gather type (0 treasure, 1 herbs, 2 ore)
-- gatherIcon (string): matching icon from Gatherer icon table (match gather name)
-- gatherEventType (number): 0 normal gather, 1 gather without required skill, 2 fishing node
function Gatherer_AddGatherHere(gather, gatherType, gatherIcon, gatherEventType)
-- type: (GatherName, EGatherType, IconName, EGatherEventType) -> nil
assert(type(gatherIcon) == 'string')
if ( Gatherer_Settings.filterRecording[gatherType] and not Gatherer_Settings.interested[gatherType][gatherIcon] ) then
return;
end
local px, py = Gatherer_PlayerPos(1);
if (px == 0 and py == 0) then
--Gatherer_Print("Gatherer: Cannot record item position as client is reporting position 0,0");
return;
end
local gatherContinent, gatherZone = Gatherer_GetCurrentZone();
if (gatherContinent == 0 or gatherZone == 0) then
--Gatherer_Print("Gatherer: Cannot record item, invalid continent/zone.");
return;
end
local gatherX = px * 100;
local gatherY = py * 100;
if (not GatherItems) then
Gatherer_Print("Initializing empty gatherable database");
GatherItems = { };
end
local iconIndex = Gatherer_GetDB_IconIndex(gatherIcon, gatherType);
if Gatherer_Settings.p2p then
-- Broadcast to guild
Gatherer_BroadcastGather(gather, gatherType, gatherContinent, gatherZone, gatherX, gatherY, iconIndex, gatherEventType)
end
Gatherer_AddGatherToBase(gather, gatherType, gatherContinent, gatherZone, gatherX, gatherY, iconIndex, gatherEventType, true);
Gatherer_OnUpdate(0,true);
GatherMain_Draw();
end
-- *************************************************************************
-- Miscellaneous functions (clearing DB, dumping DB content)
function Gatherer_Clear()
Gatherer_Print("Clearing your gather data");
GatherItems = { };
ClosestList = { };
ClosestSearchGather = "";
Gatherer_OnUpdate(0,true);
GatherMain_Draw();
end
function Gatherer_Show()
local gatherCont, gatherZone, gatherName, contData, zoneData, nameData, gatherPos, gatherItem;
for gatherCont, contData in GatherItems do
for gatherZone, zoneData in contData do
for gatherName, nameData in zoneData do
for gatherPos, gatherItem in nameData do
Gatherer_Print(Gatherer_EGatherType[gatherItem.gtype].." "..gatherName.." was found in zone "..gatherCont..":"..gatherZone.." at "..gatherItem.x..","..gatherItem.y.." ("..gatherItem.count.." times)");
end
end
end
end
end
-- *************************************************************************
-- String display related functions
function Gatherer_ChatPrint(str)
-- usually DEFAULT_CHAT_FRAME is the default "General" chat window
if ( DEFAULT_CHAT_FRAME ) then
DEFAULT_CHAT_FRAME:AddMessage(str, 1.0, 0.5, 0.25);
end
end
function Gatherer_Print(str, add)
if ((Gather_LastPrinted) and (str == Gather_LastPrinted)) then
return;
end
Gather_LastPrinted = str;
if (add) then
str = str..": "..add;
end
-- adds a message into the combat log
if(ChatFrame2) then
ChatFrame2:AddMessage(str, 1.0, 1.0, 0.0);
end
end
function Gatherer_Debug(str, add)
if not ( type(Gatherer_DebugFrame) == "table" and Gatherer_DebugFrame.AddMessage ) then
return;
end
if (add) then
str = str..": "..add;
end
Gatherer_DebugFrame:AddMessage("DEBUG: "..str, 1.0, 1.0, 0.0);
end
function Gatherer_TitleCase(str)
if (GetLocale() == "frFR") then return str; end
local function ucaseWord(first, rest)
return string.upper(first)..string.lower(rest)
end
return string.gsub(str, "([a-zA-Z])([a-zA-Z']*)", ucaseWord);
end
function Gatherer_MakeName(frameID)
local tmpClosest = ClosestGathers;
local tmpItemIDtable = { }
local tmpCount = 1;
if ( GATHERER_LOADED ) then
local gatherInfo = tmpClosest.items[frameID];
tmpItemIDtable[tmpCount] = {};
tmpItemIDtable[tmpCount].name = Gatherer_GetMenuName(gatherInfo.name);
tmpItemIDtable[tmpCount].count = gatherInfo.item.count;
tmpItemIDtable[tmpCount].dist = math.floor(gatherInfo.dist*10000)/10;
tmpCount = tmpCount + 1;
for id in tmpClosest.items do
if (id ~= frameID and
(abs(gatherInfo.item.x - tmpClosest.items[id].item.x) <= GATHERER_CLOSESTCHECK or
Gatherer_Round(gatherInfo.item.x * 10) == Gatherer_Round(tmpClosest.items[id].item.x * 10)) and
(abs(gatherInfo.item.y - tmpClosest.items[id].item.y) <= GATHERER_CLOSESTCHECK or
Gatherer_Round(gatherInfo.item.y * 10) == Gatherer_Round(tmpClosest.items[id].item.y * 10))) then
tmpItemIDtable[tmpCount] = {};
tmpItemIDtable[tmpCount].name = Gatherer_GetMenuName(tmpClosest.items[id].name);
tmpItemIDtable[tmpCount].count = tmpClosest.items[id].item.count;
tmpItemIDtable[tmpCount].dist = math.floor(tmpClosest.items[id].dist*10000)/10;
tmpCount = tmpCount + 1;
end
end
else
tmpItemIDtable[1].name = "Unknown";
tmpItemIDtable[1].count = 0;
tmpItemIDtable[1].dist = 0;
end
return tmpItemIDtable;
end
-- *************************************************************************
-- Position/Map related functions
function Gatherer_LoadZoneData()
local continentData = {GetMapContinents()};
for continentIndex, _ in continentData do
local zoneData = {GetMapZones(continentIndex)};
for zoneIndex, zoneName in zoneData do
GatherZoneData[zoneName] = { [1] = continentIndex, [2] = zoneIndex };
end
end
end
function Gatherer_GetCurrentZone()
-- type: () -> Tuple[Continent, Zone]
local zoneData = GatherZoneData[GetRealZoneText()];
if ( zoneData ) then
return zoneData[1], zoneData[2];
else
return 0,0;
end
end
Gatherer_LastZone = {};
function Gatherer_ChangeMap()
local mapContinent = GetCurrentMapContinent();
local mapZone = GetCurrentMapZone();
local minderCurZone = false;
if ((Gatherer_CloseMap ~= nil) and (Gatherer_CloseMap.continent == Gatherer_LastZone.continent) and (Gatherer_CloseMap.zone == Gatherer_LastZone.zone)) then
minderCurZone = true;
end
local playerContinent, playerZone = Gatherer_GetCurrentZone();
Gatherer_LastZone = { continent = playerContinent, zone = playerZone };
if ((playerContinent == 0) or (playerZone == 0)) then return false; end
if ((playerContinent == mapContinent) and (playerZone == mapZone)) then return true; end
if ( GetCurrentMapContinent()>0 and playerZone and playerZone > 0 ) then
if (not WorldMapFrame:IsVisible()) then
SetMapZoom(playerContinent, playerZone);
end
end
local lastTime = 0;
if ((Gatherer_CloseMap ~= nil) and (Gatherer_CloseMap.time ~= nil)) then
lastTime = Gatherer_CloseMap.time;
end
if (minderCurZone) then
Gatherer_MapOpen = false;
Gatherer_CloseMap = { continent = playerContinent, zone = playerZone, time = lastTime };
end
return true;
end
function Gatherer_PlayerPos(forced)
local currentZoneName = GetRealZoneText();
if (currentZoneName ~= Gather_LastZone) then
forced = true;
end
Gather_LastZone = currentZoneName;
if (forced) then Gatherer_ChangeMap(); end
local px, py = GetPlayerMapPosition("player");
if ((px == 0) and (py == 0)) then
if (not forced) then
if (Gatherer_ChangeMap()) then
px, py = GetPlayerMapPosition("player");
else
return 0,0;
end
end
end
return px, py;
end
-- *************************************************************************
-- Special Item handling functions: Database manipulation from world map.
-- following 2 functions have to take scope into account.
function Gatherer_DeleteItem()
local gathIdx = 0;
local zoneIdx = 0;
local cntIdx = 0;
if ( GatherMainMapItem.scope == "Node" ) then
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex] = nil;
elseif ( GatherMainMapItem.scope == "Zone" ) then
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName] = nil;
elseif ( GatherMainMapItem.scope == "Continent" ) then
local search_index;
for search_index in GatherItems[GatherMainMapItem.continent] do
if ( GatherItems[GatherMainMapItem.continent][search_index][GatherMainMapItem.gatherName] ) then
GatherItems[GatherMainMapItem.continent][search_index][GatherMainMapItem.gatherName] = nil;
end
end
elseif ( GatherMainMapItem.scope == "World" ) then
local search_index;
-- continent 1
if ( GatherItems[1] ) then
for search_index in GatherItems[1] do
if ( GatherItems[1][search_index][GatherMainMapItem.gatherName] ) then
GatherItems[1][search_index][GatherMainMapItem.gatherName] = nil;
end
end
end
-- continent 2
if ( GatherItems[2] ) then
for search_index in GatherItems[2] do
if ( GatherItems[2][search_index][GatherMainMapItem.gatherName] ) then
GatherItems[2][search_index][GatherMainMapItem.gatherName] = nil;
end
end
end
end
GatherMain_Draw();
-- clean up for empty zones/continent
for locIdx in GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName] do
gathIdx = gathIdx + 1;
end
if ( gathIdx == 0 ) then
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName] = nil;
for locIdx in GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex] do
zoneIdx = zoneIdx + 1;
end
if ( zoneIdx == 0 ) then
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex] = nil;
--DEFAULT_CHAT_FRAME:AddMessage("Removed zone no data left")
for locIdx in GatherItems[GatherMainMapItem.continent] do
cntIdx = cntIdx + 1;
end
if ( cntIdx == 0 ) then
--DEFAULT_CHAT_FRAME:AddMessage("Removed continents no data left")
GatherItems[GatherMainMapItem.continent] = nil;
end
end
end
GatherMain_Draw();
end
-- Modify Gather Name and/or icon
function Gatherer_ModifyItem()
local newIcon, newGatherName, newType;
local mod_continent = GatherMainMapItem.continent;
local mod_zone = GatherMainMapItem.zoneIndex;
local mod_name = GatherMainMapItem.gatherName;
-- setting new names (NB: icons on world map are deduced from gather name)
if ( GatherMainMapItem.newIcon and GatherMainMapItem.newIcon ~= GatherMainMapItem.gatherIcon ) then
newIcon = GatherMainMapItem.newIcon;
else
newIcon = GatherMainMapItem.gatherIcon;
end
if ( GatherMainMapItem.newType and GatherMainMapItem.newType ~= GatherMainMapItem.gatherType ) then
newType = GatherMainMapItem.newType;
else
newType = GatherMainMapItem.gatherType;
end
if ( GatherMainMapItem.newGatherName ) then
newGatherName = GatherMainMapItem.newGatherName;
else
newGatherName = mod_name;
end
if ( GatherMainMapItem.scope == "Node" ) then
-- remove old entries if gather name different
if ( GatherMainMapItem.newGatherName and mod_name ~= GatherMainMapItem.newGatherName ) then
if ( not GatherItems[mod_continent][mod_zone][newGatherName] ) then
GatherItems[mod_continent][mod_zone][newGatherName] = {};
GatherItems[mod_continent][mod_zone][newGatherName][GatherMainMapItem.localIndex] = GatherItems[mod_continent][mod_zone][mod_name][GatherMainMapItem.localIndex];
GatherItems[mod_continent][mod_zone][mod_name][GatherMainMapItem.localIndex] = nil;
end
end
-- replace icons if different
GatherItems[mod_continent][mod_zone][newGatherName][GatherMainMapItem.localIndex].icon = newIcon;
GatherItems[mod_continent][mod_zone][newGatherName][GatherMainMapItem.localIndex].gtype = newType;
elseif ( GatherMainMapItem.scope == "Zone" ) then
-- remove old entries if gather name different
if ( GatherMainMapItem.newGatherName and mod_name ~= GatherMainMapItem.newGatherName ) then
GatherItems[mod_continent][mod_zone][newGatherName] = {};
GatherItems[mod_continent][mod_zone][newGatherName] = GatherItems[mod_continent][mod_zone][mod_name];
GatherItems[mod_continent][mod_zone][mod_name] = nil;
end
-- replace icons if different
if ( newIcon ~= GatherMainMapItem.gatherIcon ) then
local index;
for index in GatherItems[mod_continent][mod_zone][newGatherName] do
GatherItems[mod_continent][mod_zone][newGatherName][index].icon = newIcon;
end
end
-- replace type if different
if ( newType ~= GatherMainMapItem.gatherType ) then
local index;
for index in GatherItems[mod_continent][mod_zone][newGatherName] do
GatherItems[mod_continent][mod_zone][newGatherName][index].gtype = newType;
end
end
elseif ( GatherMainMapItem.scope == "Continent" ) then
local search_index;
for search_index in GatherItems[mod_continent] do
if ( GatherItems[mod_continent][search_index][mod_name] ) then
-- remove old entries if gather name different
if ( GatherMainMapItem.newGatherName and mod_name ~= GatherMainMapItem.newGatherName ) then
GatherItems[mod_continent][search_index][newGatherName] = {};
GatherItems[mod_continent][search_index][newGatherName] = GatherItems[mod_continent][search_index][mod_name];
GatherItems[mod_continent][search_index][mod_name] = nil;
end
-- replace icons if different
if ( newIcon ~= GatherMainMapItem.gatherIcon ) then
local index;
for index in GatherItems[mod_continent][search_index][newGatherName] do
GatherItems[mod_continent][search_index][newGatherName][index].icon = newIcon;
end
end
-- replace type if different
if ( newType ~= GatherMainMapItem.gatherType ) then
local index;
for index in GatherItems[mod_continent][search_index][newGatherName] do
GatherItems[mod_continent][search_index][newGatherName][index].gtype = newType;
end
end
end
end
elseif ( GatherMainMapItem.scope == "World" ) then
local search_index;
-- continent 1
if ( GatherItems[1] ) then
for search_index in GatherItems[1] do
if ( GatherItems[1][search_index][mod_name] ) then
-- remove old entries if gather name different
if ( GatherMainMapItem.newGatherName and mod_name ~= GatherMainMapItem.newGatherName ) then
GatherItems[1][search_index][newGatherName] = {};
GatherItems[1][search_index][newGatherName] = GatherItems[1][search_index][mod_name];
GatherItems[1][search_index][mod_name] = nil;
end
-- replace icons if different
if ( newIcon ~= GatherMainMapItem.gatherIcon ) then
local index;
for index in GatherItems[1][search_index][newGatherName] do
GatherItems[1][search_index][newGatherName][index].icon = newIcon;
end
end
-- replace type if different
if ( newType ~= GatherMainMapItem.gatherType ) then
local index;
for index in GatherItems[1][search_index][newGatherName] do
GatherItems[1][search_index][newGatherName][index].gtype = newType;
end
end
end
end
end
-- continent 2
if ( GatherItems[2] ) then
for search_index in GatherItems[2] do
if ( GatherItems[2][search_index][mod_name] ) then
-- remove old entries if gather name different
if ( GatherMainMapItem.newGatherName and mod_name ~= GatherMainMapItem.newGatherName ) then
GatherItems[2][search_index][newGatherName] = {};
GatherItems[2][search_index][newGatherName] = GatherItems[2][search_index][mod_name];
GatherItems[2][search_index][mod_name] = nil;
end
-- replace icons if different
if ( newIcon ~= GatherMainMapItem.gatherIcon ) then
local index;
for index in GatherItems[2][search_index][newGatherName] do
GatherItems[2][search_index][newGatherName][index].icon = newIcon;
end
end
-- replace type if different
if ( newType ~= GatherMainMapItem.gatherType ) then
local index;
for index in GatherItems[2][search_index][newGatherName] do
GatherItems[2][search_index][newGatherName][index].gtype = newType;
end
end
end
end
end
end
GatherMain_Draw();
GatherMainMapItem.newIcon = nil;
GatherMainMapItem.newGatherName = nil;
end
-- dropdown menus
function Gatherer_WMDropDownGType_Initialize()
local index;
local info = {};
local iconGtype = GatherMainMapItem.gatherType;
if ( GatherMainMapItem.newType ) then
iconGtype = GatherMainMapItem.newType;
end
for index, value in Gatherer_EGatherType do
if ( type(value) == "number" and value ~= 3 )
then
info.text = index;
info.value = value;
if ( value == iconGtype ) then
info.checked = 1;
else
info.checked = nil;
end
info.func = Gatherer_WMDropDownGType_OnClick;
UIDropDownMenu_AddButton(info);
end
end
if ( type(GatherMainMapItem.gatherType) == "number" )
then
UIDropDownMenu_SetText(Gatherer_EGatherType[GatherMainMapItem.gatherType], Gatherer_WMDropDownGType);
else
UIDropDownMenu_SetText(GatherMainMapItem.gatherType, Gatherer_WMDropDownGType);
end
end
function Gatherer_WMDropDownGType_OnClick()
UIDropDownMenu_SetSelectedID(Gatherer_WMDropDownGType, this:GetID());
GatherMainMapItem.newType = Gatherer_EGatherType[UIDropDownMenu_GetText(Gatherer_WMDropDownGType)];
UIDropDownMenu_ClearAll(Gatherer_WMDropDownIcons);
UIDropDownMenu_Initialize(Gatherer_WMDropDownIcons, Gatherer_WMDropDownIcons_Initialize);
end
function Gatherer_WMDropDownIcons_Initialize()
local index;
local info = {};
local iconGtype = "Default";
if ( GatherMainMapItem.newType ) then
iconGtype = GatherMainMapItem.newType;
else
iconGtype = GatherMainMapItem.gatherType;
end
for index, value in Gather_DB_IconIndex[iconGtype] do
info.text = index;
info.value = value;
if ( value == GatherMainMapItem.gatherIcon and not GatherMainMapItem.newType) then
info.checked = 1;
else
info.checked = nil;
end
info.func = Gatherer_WMDropDownIcons_OnClick;
UIDropDownMenu_AddButton(info);
end
UIDropDownMenu_SetText(Gatherer_GetDB_IconIndex(GatherMainMapItem.gatherIcon, iconGtype), Gatherer_WMDropDownIcons);
end
function Gatherer_WMDropDownIcons_OnClick()
UIDropDownMenu_SetSelectedID(Gatherer_WMDropDownIcons, this:GetID());
GatherMainMapItem.newIcon = Gatherer_GetDB_IconIndex(UIDropDownMenu_GetText(Gatherer_WMDropDownIcons), GatherMainMapItem.gatherType);
end
function Gatherer_WMDropDownScope_Initialize()
local index;
local scope_list = { "Node", "Zone", "Continent", "World" };
local info = {};
GatherMainMapItem.scope = "Node";
for index in scope_list do
info.text = scope_list[index];
info.value = index;
if ( scope_list[index] == "Node" ) then
info.checked = 1;
else
info.checked = nil;
end
info.func = Gatherer_WMDropDownScope_OnClick;
UIDropDownMenu_AddButton(info);
end
UIDropDownMenu_SetSelectedID(Gatherer_WMDropDownScope, 1);
end
function Gatherer_WMDropDownScope_OnClick()
UIDropDownMenu_SetSelectedID(Gatherer_WMDropDownScope, this:GetID());
GatherMainMapItem.scope = UIDropDownMenu_GetText(Gatherer_WMDropDownScope);
end
-- Toggle item to bugged state
-- this one always ignore scope, only done on origin item.
function Gatherer_ToggleBuggedItem()
Gatherer_ChatPrint("Toggling node to bugged state");
local gtype = GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].gtype;
local icon = GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].icon;
if ( GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].icon ~= "default" ) then
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].oldicon = icon;
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].oldgtype = gtype;
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].icon = "default";
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].gtype = "Default";
else
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].icon = GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].oldicon;
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].gtype = GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].oldgtype;
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].oldicon = nil;
GatherItems[GatherMainMapItem.continent][GatherMainMapItem.zoneIndex][GatherMainMapItem.gatherName][GatherMainMapItem.localIndex].oldgtype = nil;
end
GatherMain_Draw();
end