You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.5 KiB
304 lines
8.5 KiB
local myname, ns = ...
|
|
|
|
local core = LibStub("AceAddon-3.0"):GetAddon("SilverDragon")
|
|
local module = core:NewModule("ClickTarget", "AceEvent-3.0")
|
|
local Debug = core.Debug
|
|
|
|
local HBD = LibStub("HereBeDragons-2.0")
|
|
local LibWindow = LibStub("LibWindow-1.1")
|
|
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0")
|
|
|
|
module.Looks = {}
|
|
module.LookConfig = {}
|
|
module.LookReset = {}
|
|
module.defaults = {
|
|
profile = {
|
|
show = true,
|
|
loot = true,
|
|
locked = true,
|
|
style = "SilverDragon",
|
|
closeAfter = 30,
|
|
closeDead = true,
|
|
stacksize = 4,
|
|
announce = "IMMEDIATELY", -- or "OPENLAST"
|
|
announceChannel = "CHANNEL",
|
|
sources = {
|
|
target = false,
|
|
grouptarget = true,
|
|
mouseover = true,
|
|
nameplate = true,
|
|
vignette = true,
|
|
['point-of-interest'] = true,
|
|
chat = true,
|
|
groupsync = true,
|
|
guildsync = false,
|
|
fake = true,
|
|
},
|
|
anchor = {
|
|
point = "BOTTOMRIGHT",
|
|
x = -260,
|
|
y = 270,
|
|
scale = 1,
|
|
},
|
|
style_options = {
|
|
['*'] = {},
|
|
},
|
|
},
|
|
}
|
|
|
|
function module:OnInitialize()
|
|
self.db = core.db:RegisterNamespace("ClickTarget", self.defaults)
|
|
|
|
core.RegisterCallback(self, "Announce")
|
|
core.RegisterCallback(self, "AnnounceLoot")
|
|
core.RegisterCallback(self, "Marked")
|
|
core.RegisterCallback(self, "SeenVignette")
|
|
core.RegisterCallback(self, "SeenLoot")
|
|
self:RegisterEvent("PLAYER_REGEN_ENABLED", "ProcessQueue")
|
|
|
|
self.anchor = self:CreateAnchor()
|
|
|
|
self:RegisterConfig()
|
|
end
|
|
|
|
local pending
|
|
function module:Announce(callback, id, zone, x, y, dead, source, unit, _, vignetteGUID)
|
|
if not self.db.profile.show then return end
|
|
if source:match("^sync") then
|
|
local channel, player = source:match("sync:(.+):(.+)")
|
|
if channel == "GUILD" then
|
|
source = "guildsync"
|
|
else
|
|
source = "groupsync"
|
|
end
|
|
end
|
|
if not self.db.profile.sources[source] then
|
|
Debug("Not showing popup, source disabled", source)
|
|
return
|
|
end
|
|
local data = {
|
|
type = "mob",
|
|
id = id,
|
|
unit = unit,
|
|
source = source,
|
|
dead = dead,
|
|
zone = zone,
|
|
x = x or 0,
|
|
y = y or 0,
|
|
vignetteGUID = vignetteGUID,
|
|
}
|
|
if vignetteGUID then
|
|
local vignetteInfo = C_VignetteInfo.GetVignetteInfo(vignetteGUID)
|
|
if vignetteInfo then
|
|
data.vignetteID = vignetteInfo.vignetteID
|
|
end
|
|
end
|
|
self:Enqueue(data)
|
|
FlashClientIcon() -- If you're tabbed out, bounce the WoW icon if we're in a context that supports that
|
|
data.unit = nil -- can't be trusted to remain the same
|
|
end
|
|
function module:AnnounceLoot(_, name, id, zone, x, y, vignetteGUID)
|
|
if not self.db.profile.loot then return end
|
|
local data = {
|
|
type = "loot",
|
|
id = id,
|
|
name = name,
|
|
zone = zone,
|
|
x = x or 0,
|
|
y = y or 0,
|
|
vignetteGUID = vignetteGUID,
|
|
vignetteID = id,
|
|
}
|
|
self:Enqueue(data)
|
|
FlashClientIcon() -- If you're tabbed out, bounce the WoW icon if we're in a context that supports that
|
|
end
|
|
function module:SeenVignette(_, name, vignetteID, atlasName, uiMapID, x, y, vignetteGUID, mobid)
|
|
if not mobid then return end
|
|
self:UpdateWithData({
|
|
type = "mob",
|
|
id = mobid,
|
|
vignetteGUID = vignetteGUID,
|
|
vignetteID = vignetteID,
|
|
zone = uiMapID,
|
|
x = x,
|
|
y = y,
|
|
source = "vignette",
|
|
})
|
|
end
|
|
function module:SeenLoot(_, name, vignetteID, uiMapID, x, y, vignetteGUID)
|
|
self:UpdateWithData({
|
|
type = "loot",
|
|
id = vignetteID,
|
|
vignetteGUID = vignetteGUID,
|
|
vignetteID = vignetteID,
|
|
zone = uiMapID,
|
|
x = x,
|
|
y = y,
|
|
source = "vignette",
|
|
})
|
|
end
|
|
|
|
function module:CanPoint(uiMapID)
|
|
return core:GetModule("TomTom"):CanPointTo(uiMapID)
|
|
end
|
|
|
|
function module:Point(data)
|
|
local uiMapID, x, y = self:GetPositionFromData(data)
|
|
if uiMapID and x and y then
|
|
-- point to it, without a timeout, and ignoring whether it'll be replacing an existing waypoint
|
|
core:GetModule("TomTom"):PointTo(data.type == "mob" and data.id or data.name, uiMapID, x, y, 0, true)
|
|
end
|
|
end
|
|
|
|
function module:Marked(callback, id, marker, unit)
|
|
for popup in self:EnumerateActive() do
|
|
if popup.data and popup.data.id == id then
|
|
popup:SetRaidIcon(marker)
|
|
end
|
|
end
|
|
end
|
|
|
|
function module:GetGeneralID()
|
|
local channelFormat = GetLocale() == "ruRU" and "%s: %s" or "%s - %s"
|
|
local zoneText = GetZoneText()
|
|
local general = EnumerateServerChannels()
|
|
if zoneText == nil or general == nil then return false end
|
|
local id = GetChannelName(channelFormat:format(general, zoneText))
|
|
return (id and id > 0) and id
|
|
end
|
|
|
|
function module:SendLink(prefix, uiMapID, x, y)
|
|
local message
|
|
if MAP_PIN_HYPERLINK then
|
|
message = ("%s|cffffff00|Hworldmap:%d:%d:%d|h[%s]|h|r"):format(
|
|
prefix and (prefix .. " ") or "",
|
|
uiMapID,
|
|
x * 10000,
|
|
y * 10000,
|
|
-- Can't do this:
|
|
-- core:GetMobLabel(self.data.id) or UNKNOWN
|
|
-- WoW seems to filter out anything which isn't the standard MAP_PIN_HYPERLINK
|
|
MAP_PIN_HYPERLINK
|
|
)
|
|
PlaySound(SOUNDKIT.UI_MAP_WAYPOINT_CHAT_SHARE)
|
|
else
|
|
-- classic
|
|
message = prefix
|
|
end
|
|
-- if you have an open editbox, just paste to it
|
|
if not ChatEdit_InsertLink(message) then
|
|
-- then do whatever's configured
|
|
if self.db.profile.announce == "OPENLAST" then
|
|
ChatFrame_OpenChat(message)
|
|
elseif self.db.profile.announce == "IMMEDIATELY" then
|
|
local generalID
|
|
if self.db.profile.announceChannel == "CHANNEL" then
|
|
generalID = module:GetGeneralID()
|
|
if not generalID then
|
|
ChatFrame_OpenChat(message)
|
|
return
|
|
end
|
|
end
|
|
Debug("SendChatMessage", message, self.db.profile.announceChannel, generalID)
|
|
SendChatMessage(
|
|
message,
|
|
self.db.profile.announceChannel,
|
|
nil, -- use default language
|
|
self.db.profile.announceChannel == "CHANNEL" and generalID or nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
function module:SendLinkToMob(id, uiMapID, x, y)
|
|
local unit = core:FindUnitWithID(id)
|
|
local prefix = core:NameForMob(id, unit)
|
|
if unit then
|
|
prefix = ("%s %s"):format(prefix, ('(' .. math.ceil(UnitHealth(unit) / UnitHealthMax(unit) * 100) .. '%)'))
|
|
end
|
|
self:SendLink(prefix, uiMapID, x, y)
|
|
end
|
|
|
|
function module:SendLinkToLoot(name, uiMapID, x, y)
|
|
self:SendLink(name, uiMapID, x, y)
|
|
end
|
|
|
|
function module:SendLinkFromData(data)
|
|
-- worldmap:uiMapId:x:y
|
|
local uiMapID, x, y = module:GetPositionFromData(data)
|
|
if data.type == "mob" then
|
|
self:SendLinkToMob(data.id, uiMapID, x, y)
|
|
elseif data.type == "loot" then
|
|
self:SendLinkToLoot(data.name, uiMapID, x, y)
|
|
end
|
|
end
|
|
|
|
function module:GetPositionFromData(data, allowFallback)
|
|
local x, y, uiMapID = data.x, data.y, data.zone
|
|
if uiMapID and data.vignetteGUID then
|
|
local position = C_VignetteInfo.GetVignettePosition(data.vignetteGUID, uiMapID)
|
|
if position then
|
|
x, y = position:GetXY()
|
|
end
|
|
end
|
|
if not (x and y and x > 0 and y > 0) and data.type == "mob" then
|
|
uiMapID, x, y = core:GetClosestLocationForMob(data.id)
|
|
end
|
|
if allowFallback and not (x and y and x > 0 and y > 0) then
|
|
-- fall back to sending a link to the current position
|
|
x, y, uiMapID = HBD:GetPlayerZonePosition()
|
|
end
|
|
return uiMapID, x, y
|
|
end
|
|
|
|
function module:CreateAnchor()
|
|
local anchor = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
|
|
anchor:SetSize(250, 100)
|
|
anchor:SetFrameStrata("DIALOG")
|
|
anchor:SetBackdrop({
|
|
bgFile = [[Interface\FriendsFrame\UI-Toast-Background]],
|
|
edgeFile = [[Interface\FriendsFrame\UI-Toast-Border]],
|
|
edgeSize = 12,
|
|
tile = true,
|
|
tileSize = 12,
|
|
insets = { left = 5, right = 5, top = 5, bottom = 5, },
|
|
})
|
|
|
|
anchor:EnableMouse(true)
|
|
anchor:RegisterForDrag("LeftButton")
|
|
anchor:SetClampedToScreen(true)
|
|
anchor:Hide()
|
|
|
|
local title = anchor:CreateFontString(nil, "BORDER", "FriendsFont_Normal")
|
|
title:SetJustifyH("CENTER")
|
|
title:SetJustifyV("MIDDLE")
|
|
title:SetWordWrap(true)
|
|
title:SetPoint("TOPLEFT", anchor, "TOPLEFT", 15, -10)
|
|
title:SetPoint("RIGHT", anchor, "RIGHT", -20, 10)
|
|
title:SetText(myname)
|
|
title:SetWidth(anchor:GetWidth())
|
|
|
|
local text = anchor:CreateFontString(nil, "BORDER", "FriendsFont_Normal")
|
|
text:SetSize(anchor:GetWidth() - 20, 24)
|
|
text:SetJustifyH("MIDDLE")
|
|
text:SetJustifyV("TOP")
|
|
text:SetWordWrap(true)
|
|
text:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -4)
|
|
text:SetText("Target buttons will appear here")
|
|
|
|
local close = CreateFrame("Button", nil, anchor, "UIPanelCloseButton")
|
|
close:SetSize(24, 24)
|
|
close:SetPoint("TOPRIGHT", anchor, "TOPRIGHT", -2, -2)
|
|
|
|
anchor:SetHeight(text:GetStringHeight() + title:GetStringHeight() + 25)
|
|
|
|
LibWindow.RegisterConfig(anchor, self.db.profile.anchor)
|
|
LibWindow.RestorePosition(anchor)
|
|
LibWindow.MakeDraggable(anchor)
|
|
|
|
anchor:HookScript("OnDragStop", function()
|
|
AceConfigRegistry:NotifyChange(myname)
|
|
end)
|
|
|
|
return anchor
|
|
end
|
|
|