Files
RuskiCandyBuckets/ns.lua

439 lines
11 KiB
Lua

local _G = _G
local ipairs = ipairs
local pairs = pairs
local string_format = string.format
local table_insert = table.insert
local table_remove = table.remove
local time = time
local type = type
local CreateFrame = CreateFrame
local GetCurrentMapAreaID = GetCurrentMapAreaID
local GetCurrentMapContinent = GetCurrentMapContinent
local GetMapNameByID = GetMapNameByID
local GetQuestsCompleted = GetQuestsCompleted
local IsAddOnLoaded = IsAddOnLoaded
local IsModifierKeyDown = IsModifierKeyDown
local UnitFactionGroup = UnitFactionGroup
local addonName, ns = ...
ns.modules = {}
ns.widgets = {}
ns.quests = {}
function ns.quests:CacheQuests(force)
if force or not self.updated or time() - self.updated >= 1 then
self.updated = time()
GetQuestsCompleted(self)
end
end
function ns.quests:IsCompleted(questID)
self:CacheQuests()
return self[questID]
end
-- local HBD = LibStub("HereBeDragons-1.0")
local HBDPins = LibStub("HereBeDragons-Pins-1.0")
local worldMapFrame = WorldMapButton
local IsAcceptedZone
do
local empty = {}
local useEmpty = false
IsAcceptedZone = setmetatable({}, {
__index = function(self, i)
if useEmpty then
self[i] = empty
return empty
end
self[i] = {}
return self[i]
end
})
local continents = { GetMapContinents() }
local numContinents = #continents
local continent = 0
local zones
local numZones
for i = 1, numContinents, 2 do
continent = continent + 1
zones = { GetMapZones(continent) }
numZones = #zones
for j = 1, numZones, 2 do
IsAcceptedZone[continent][zones[j]] = false
end
end
IsAcceptedZone[1][13] = true -- Kalimdor
IsAcceptedZone[2][14] = true -- Eastern Kingdoms
IsAcceptedZone[3][466] = true -- Outland
IsAcceptedZone[4][485] = true -- Northrend
IsAcceptedZone[5][751] = true -- The Maelstrom
IsAcceptedZone[6][862] = true -- Pandaria
IsAcceptedZone[7][962] = true -- Draenor
IsAcceptedZone[8][1007] = true -- Broken Isles
-- Vashj'ir
for k, v in ipairs({ 610, 613, 614, 615 }) do
IsAcceptedZone[2][v] = false
end
-- Northrend: Dalaran
for k, v in ipairs({ 485, 504, 510, 924 }) do -- Northrend, Dalaran#504, Crystalsong Forest, Dalaran#924
IsAcceptedZone[4][v] = false
end
-- Garrison
for k, v in ipairs({ 971, 973, 991, 974, 975, 976, 980, 990, 981, 982 }) do -- garrisonsmvalliance, garrisonsmvalliance_tier1, garrisonsmvalliance_tier2, garrisonsmvalliance_tier3, garrisonsmvalliance_tier4, garrisonffhorde, garrisonffhorde_tier1, garrisonffhorde_tier2, garrisonffhorde_tier3, garrisonffhorde_tier4
IsAcceptedZone[7][v] = true
end
useEmpty = true
end
local WaypointAddons = {}
do
-- enable for other parts of the addon to use this interface
ns.WaypointAddons = WaypointAddons
-- TomTom (v50400-1.0.0)
table_insert(WaypointAddons, {
name = "TomTom",
func = function(self, widget, everything)
if everything then
for _, node in ipairs(widget.module.nodes) do
TomTom:AddMFWaypoint(node.area, node.level, node.x, node.y, {
title = string_format("%s (%s, %d)", widget.module.title, GetMapNameByID(node.area), node.quest),
minimap = true,
crazy = true,
})
end
end
TomTom:AddMFWaypoint(widget.node.area, widget.node.level, widget.node.x, widget.node.y, {
title = string_format("%s (%s, %d)", widget.module.title, GetMapNameByID(widget.node.area),
widget.node.quest),
minimap = true,
crazy = true,
})
if everything then
TomTom:SetClosestWaypoint()
end
end,
})
-- TomTomLite (v50100-1.0.0)
table_insert(WaypointAddons, {
name = "TomTomLite",
func = function(self, widget, everything)
if everything then
for _, node in ipairs(widget.module.nodes) do
TomTomLite:AddWaypoint(node.area, node.level, node.x, node.y, {
title = string_format("%s (%s, %d)", widget.module.title, GetMapNameByID(node.area), node.quest),
})
end
end
TomTomLite:AddWaypoint(widget.node.area, widget.node.level, widget.node.x, widget.node.y, {
title = string_format("%s (%s, %d)", widget.module.title, GetMapNameByID(widget.node.area),
widget.node.quest),
})
end,
})
-- prepare some nice looking strings explaning what addons that are implemented
local numAddons = #WaypointAddons
local supportedAddons = "... darn! Seems like I forgot to actually add waypoint support"
if numAddons > 0 then
supportedAddons = ""
end
for index, addon in ipairs(WaypointAddons) do
supportedAddons = supportedAddons .. addon.name
if index < numAddons then
if index == numAddons - 1 then
supportedAddons = supportedAddons .. " or "
else
supportedAddons = supportedAddons .. ", "
end
end
end
supportedAddons = supportedAddons .. "."
-- get first loaded addon
function WaypointAddons:GetAddon()
for _, addon in ipairs(WaypointAddons) do
if IsAddOnLoaded(addon.name) then
return addon
end
end
end
-- apply a waypoint or all the waypoints on the first active addon
local informed
function WaypointAddons:Set(widget, everything)
local addon = WaypointAddons:GetAddon()
if addon then
addon:func(widget, everything)
elseif not informed then
DEFAULT_CHAT_FRAME:AddMessage("These waypoint addons are supported: " .. supportedAddons, 1, 1, 0)
informed = 1
end
end
end
function ns:GetNormalizedHolidayTexture(texture)
if texture == 235461 or texture == 235462 then
return 235460
elseif texture == 235470 or texture == 235471 then
return 235469
elseif texture == 235473 or texture == 235474 then
return 235472
end
return texture
end
function ns:CanLoadEvent(texture)
return type(ns.modules[texture]) == "table" and not ns.modules[texture].loaded
end
function ns:CanUnloadEvent(texture)
return type(ns.modules[texture]) == "table" and ns.modules[texture].loaded
end
function ns:LoadEvent(texture)
local loaded = ns.modules[texture]:load()
if loaded then
ns:UpdateNodes()
end
return loaded
end
function ns:UnloadEvent(texture)
local module = ns.modules[texture]
local remove = {}
for _, node in pairs(module.nodes) do
if node then
ns:RemoveNode(node)
table_insert(remove, node)
end
end
while #remove > 0 do
local removeNode = table_remove(remove, 1)
for index, node in pairs(module.nodes) do
if node == removeNode then
table_remove(module.nodes, index)
break
end
end
end
module.loaded = false
ns:UpdateNodes()
return true
end
function ns:GetPlayerFaction()
local faction = UnitFactionGroup("player")
local factionId
if faction == "Alliance" then
factionId = 1
elseif faction == "Horde" then
factionId = 2
end
return factionId
end
if not CandyBucketsDB then CandyBucketsDB = {} end
function ns:IsQuestCompleted(questID)
-- Hijack this and make it read from CandyBucketsDB
-- Something like CandyBucketsDB[UnitName("player")][questID]
-- Then write to this by listening for quest completed event
-- return ns.quests:IsCompleted(questID)
if not CandyBucketsDB then CandyBucketsDB = {} end
if not CandyBucketsDB[UnitName("player")] then CandyBucketsDB[UnitName("player")] = {} end
return CandyBucketsDB[UnitName("player")][questID]
end
local frame = CreateFrame("Frame")
frame:RegisterEvent("QUEST_TURNED_IN")
frame:SetScript("OnEvent", function(self, event, questID)
if not CandyBucketsDB then CandyBucketsDB = {} end
if not CandyBucketsDB[UnitName("player")] then CandyBucketsDB[UnitName("player")] = {} end
CandyBucketsDB[UnitName("player")][questID] = true
end)
function ns:QuestCompleted(questID)
ns.quests:CacheQuests(1)
ns.quests[questID] = true
for _, module in pairs(ns.modules) do
if module.loaded then
local remove = {}
for _, node in pairs(module.nodes) do
if node.quest == questID then
ns:RemoveNode(node)
table_insert(remove, node)
end
end
while #remove > 0 do
local removeNode = table_remove(remove, 1)
for index, node in pairs(module.nodes) do
if node == removeNode then
table_remove(module.nodes, index)
break
end
end
end
end
end
end
function ns:UpdateNodes()
if not worldMapFrame:IsVisible() then
return
end
local continent = IsAcceptedZone[GetCurrentMapContinent()]
local zone = continent[GetCurrentMapAreaID()]
for _, module in pairs(ns.modules) do
if module.loaded then
for _, node in pairs(module.nodes) do
if not ns:IsQuestCompleted(node.quest) then
if zone == false or (zone == true and continent[node.area] == false) then
ns:CreateOrUpdateWidget(node, module)
else
ns:RemoveNode(node)
end
else
ns:QuestCompleted(node.quest)
end
end
end
end
end
function ns:RemoveNode(node)
local widget = ns:GetWidget(node)
if widget then
widget:Hide()
HBDPins:RemoveWorldMapIcon(addonName, widget)
widget.node, widget.module = nil
end
end
function ns:GetWidget(node, createIfNotFound)
-- find node by reference
for i = 1, #ns.widgets do
local widget = ns.widgets[i]
if widget:IsShown() and widget.node == node then
return widget
end
end
if createIfNotFound then
-- find available
for i = 1, #ns.widgets do
local widget = ns.widgets[i]
if not widget:IsShown() then
return widget
end
end
-- create widget
local widget = ns:CreateWidget()
table_insert(ns.widgets, widget)
return widget
end
end
local function WidgetOnShowFullscreenCheck(widget, ...)
widget:SetFrameStrata(worldMapFrame:GetFrameStrata())
widget:SetFrameLevel(worldMapFrame:GetFrameLevel() + 1000)
if widget.node and widget.module then
widget.module.OnShow(widget)
end
end
function ns:CreateOrUpdateWidget(node, module)
local widget = ns:GetWidget(node, true)
widget.node, widget.module = node, module
if node and module then
widget.icon:SetTexture(module.texture)
widget:SetScript("OnEnter", module.OnEnter)
widget:SetScript("OnLeave", module.OnLeave)
widget:SetScript("OnClick", ns.WidgetOnClick)
else
widget.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
widget:SetScript("OnEnter", nil)
widget:SetScript("OnLeave", nil)
widget:SetScript("OnClick", nil)
end
widget:SetScript("OnShow", WidgetOnShowFullscreenCheck)
widget:SetScript("OnHide", WidgetOnShowFullscreenCheck)
widget:SetParent(worldMapFrame)
widget:SetFrameStrata("DIALOG")
widget:SetFrameLevel(255)
widget:Hide() -- will be shown by HBD when added to the world map (triggers OnShow)
HBDPins:AddWorldMapIconMF(addonName, widget, node.area, node.level, node.x, node.y)
end
function ns:CreateWidget()
local widget = CreateFrame("Button")
widget:Hide()
widget:SetSize(16, 16)
widget:RegisterForClicks("AnyUp")
widget.icon = widget:CreateTexture(nil, "OVERLAY", 2)
widget.icon:SetAllPoints()
widget.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
-- widget.icon:SetTexCoord(.15, .85, .15, .85) -- can't when we use a mask
widget.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask")
widget.border = widget:CreateTexture(nil, "OVERLAY", 1)
-- widget.border:SetPoint("TOPLEFT", -1, 1)
-- widget.border:SetPoint("BOTTOMRIGHT", 1, -1)
-- widget.border:SetTexture(0, 0, 0, 1)
return widget
end
function ns.WidgetOnClick(self, button)
if button == "LeftButton" then
WaypointAddons:Set(self, IsModifierKeyDown())
elseif button == "RightButton" then
if not CandyBucketsDB then CandyBucketsDB = {} end
if not CandyBucketsDB[UnitName("player")] then CandyBucketsDB[UnitName("player")] = {} end
CandyBucketsDB[UnitName("player")][self.node.quest] = true
self:RemoveNode(self.node)
end
end