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.
412 lines
11 KiB
412 lines
11 KiB
local _, addon = ...
|
|
local API = addon.API;
|
|
local L = addon.L;
|
|
|
|
local time = time;
|
|
local SearchChatHistory = API.SearchChatHistory;
|
|
local SecondsToTime = API.SecondsToTime;
|
|
|
|
local COOLDOWN_ANNOUNCE = 20;
|
|
local CAN_SEND_MESSAGE = false;
|
|
|
|
local DELENSION = "";
|
|
|
|
local HornButton = CreateFrame("Button");
|
|
HornButton:Hide();
|
|
HornButton:SetSize(20, 20);
|
|
HornButton:SetMotionScriptsWhileDisabled(true);
|
|
HornButton:RegisterForClicks("LeftButtonUp");
|
|
|
|
|
|
local PrivateFrame = CreateFrame("Frame");
|
|
PrivateFrame:Hide();
|
|
|
|
local function AlwaysFalse()
|
|
return false
|
|
end
|
|
PrivateFrame.validateFunc = AlwaysFalse;
|
|
|
|
function PrivateFrame:GetGlobalUnlockTime()
|
|
--This time is stored in our SavedVariable
|
|
local db = PlumberDB;
|
|
|
|
if db and db.announceButtonLockUntil and type(db.announceButtonLockUntil) == "number" then
|
|
local currentTime = time();
|
|
if db.announceButtonLockUntil - currentTime > 60 then
|
|
db.announceButtonLockUntil = currentTime + COOLDOWN_ANNOUNCE;
|
|
end
|
|
return db.announceButtonLockUntil
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:SetGlobalUnlockTime(endTime)
|
|
local db = PlumberDB;
|
|
|
|
if db then
|
|
if endTime then
|
|
db.announceButtonLockUntil = endTime;
|
|
else
|
|
local currentTime = time();
|
|
db.announceButtonLockUntil = currentTime + COOLDOWN_ANNOUNCE;
|
|
end
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:OnUpdate(elapsed)
|
|
self.t = self.t + elapsed;
|
|
if self.t >= 0 then
|
|
self:SetScript("OnUpdate", nil);
|
|
self.t = nil;
|
|
self.endTime = nil;
|
|
if HornButton:IsVisible() then
|
|
self:UpdateValidity();
|
|
end
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:StartLockTimer(forceRestart)
|
|
if (not self.endTime) or forceRestart then
|
|
self.t = -COOLDOWN_ANNOUNCE;
|
|
self.endTime = time() + COOLDOWN_ANNOUNCE;
|
|
PrivateFrame:SetGlobalUnlockTime(self.endTime);
|
|
self:SetScript("OnUpdate", self.OnUpdate);
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:GetLockEndTime()
|
|
return self.endTime or self:GetGlobalUnlockTime();
|
|
end
|
|
|
|
function PrivateFrame:GetLockRemainingSeconds()
|
|
local seconds = self:GetLockEndTime() - time();
|
|
if seconds < 0 then
|
|
seconds = 0;
|
|
end
|
|
return seconds
|
|
end
|
|
|
|
function PrivateFrame:IsButtonInCooldown()
|
|
return self:GetLockRemainingSeconds() > 0
|
|
end
|
|
|
|
function PrivateFrame:CalibrateTimer()
|
|
local remainingSeconds = self:GetLockRemainingSeconds()
|
|
if remainingSeconds <= 0 then
|
|
self:UnlockButton();
|
|
self:SetScript("OnUpdate", nil);
|
|
else
|
|
self:LockButton(1, true);
|
|
self.t = -remainingSeconds;
|
|
self.endTime = time() + remainingSeconds;
|
|
self:SetScript("OnUpdate", self.OnUpdate);
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:UpdateValidity()
|
|
local messageFound = SearchChatHistory(self.validateFunc);
|
|
if messageFound then
|
|
self:LockButton(2, true);
|
|
else
|
|
if not self:IsButtonInCooldown() then
|
|
self:UnlockButton();
|
|
end
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:LockButton(reason, overridePreviousReason)
|
|
if (not self.disableReason) or overridePreviousReason then
|
|
self.disableReason = reason;
|
|
end
|
|
|
|
CAN_SEND_MESSAGE = false;
|
|
HornButton:Disable();
|
|
|
|
--Disable Reason
|
|
--#1 In cooldown (start OnClick)
|
|
--#2 Shared by another player (search chat)
|
|
--#3 Target soon despawn
|
|
end
|
|
|
|
function PrivateFrame:GetLockReason()
|
|
local reason, hasTimer;
|
|
|
|
if self.disableReason == 1 then
|
|
reason = L["Announce Forbidden Reason In Cooldown"];
|
|
hasTimer = true;
|
|
elseif self.disableReason == 2 then
|
|
reason = L["Announce Forbidden Reason Duplicate Message"];
|
|
elseif self.disableReason == 3 then
|
|
reason = L["Announce Forbidden Reason Soon Despawn"];
|
|
else
|
|
reason = TOKEN_MARKET_PRICE_NOT_AVAILABLE or "Not Available";
|
|
end
|
|
|
|
return reason, hasTimer
|
|
end
|
|
|
|
function PrivateFrame:UnlockButton()
|
|
CAN_SEND_MESSAGE = true;
|
|
HornButton:Enable();
|
|
self.disableReason = nil;
|
|
end
|
|
|
|
function PrivateFrame:ListenEvents(state)
|
|
if state then
|
|
self:RegisterEvent("CHAT_MSG_CHANNEL");
|
|
else
|
|
self:UnregisterEvent("CHAT_MSG_CHANNEL");
|
|
end
|
|
end
|
|
|
|
function PrivateFrame:OnShow()
|
|
self:CalibrateTimer();
|
|
self:ListenEvents(true);
|
|
self:UpdateValidity();
|
|
end
|
|
|
|
function PrivateFrame:OnHide()
|
|
self:ListenEvents(false);
|
|
end
|
|
|
|
PrivateFrame:SetScript("OnShow", PrivateFrame.OnShow);
|
|
PrivateFrame:SetScript("OnHide", PrivateFrame.OnHide);
|
|
|
|
PrivateFrame:SetScript("OnEvent", function(self, event, ...)
|
|
local text = ...
|
|
if text and self.validateFunc(text) then
|
|
self:LockButton(2, true);
|
|
end
|
|
end);
|
|
|
|
|
|
function HornButton:OnMouseDown(button)
|
|
if self:IsEnabled() and button == "LeftButton" then
|
|
self.Icon:SetPoint("CENTER", self, "CENTER", 0, -1);
|
|
end
|
|
end
|
|
|
|
function HornButton:OnMouseUp()
|
|
self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
|
|
end
|
|
|
|
function HornButton:GetAnnounceText()
|
|
if self.sourceFunction then
|
|
return self.sourceFunction()
|
|
end
|
|
end
|
|
|
|
function HornButton:SetAnnouceTextSource(sourceFunction)
|
|
self.sourceFunction = sourceFunction;
|
|
end
|
|
|
|
function HornButton:OnClick()
|
|
local success, msg = self:GetAnnounceText();
|
|
|
|
if not success then
|
|
local reasonCode = msg;
|
|
PrivateFrame:LockButton(reasonCode, true);
|
|
return
|
|
end
|
|
|
|
if CAN_SEND_MESSAGE and msg then
|
|
--print(msg);
|
|
local channelID = C_ChatInfo.GetGeneralChannelID();
|
|
if channelID then
|
|
SendChatMessage(msg, "CHANNEL", nil, channelID);
|
|
else
|
|
UIErrorsFrame:AddExternalErrorMessage("Could not find General Chat channel.");
|
|
end
|
|
PrivateFrame:LockButton(1, true);
|
|
PrivateFrame:StartLockTimer(true);
|
|
end
|
|
end
|
|
|
|
function HornButton:OnEnable()
|
|
self.Icon:SetDesaturated(false);
|
|
self.Icon:SetVertexColor(1, 1, 1);
|
|
self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
|
|
self:RefreshOnEnter();
|
|
end
|
|
|
|
function HornButton:OnDisable()
|
|
self.Icon:SetDesaturated(true);
|
|
self.Icon:SetVertexColor(0.8, 0.8, 0.8);
|
|
self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
|
|
self.Highlight:Hide();
|
|
self:RefreshOnEnter();
|
|
end
|
|
|
|
function HornButton:RefreshOnEnter()
|
|
if self:IsVisible() and self:IsMouseOver() then
|
|
self:OnEnter();
|
|
end
|
|
end
|
|
|
|
function HornButton:OnShow()
|
|
--PrivateFrame:Show();
|
|
end
|
|
|
|
function HornButton:OnHide()
|
|
self:SetScript("OnUpdate", nil);
|
|
PrivateFrame:Hide();
|
|
end
|
|
|
|
function HornButton:UpdateTooltipTimer()
|
|
self:OnEnter();
|
|
end
|
|
|
|
function HornButton:OnEnter()
|
|
local tooltip = GameTooltip;
|
|
tooltip:Hide();
|
|
tooltip:SetOwner(self, "ANCHOR_RIGHT");
|
|
tooltip:SetText(BATTLENET_BROADCAST or "Broadcast", 1, 1, 1);
|
|
|
|
if self:IsEnabled() and CAN_SEND_MESSAGE then
|
|
self.Highlight:Show();
|
|
tooltip:AddLine(L["Announce Location Tooltip"], 1, 0.82, 0, true);
|
|
self.UpdateTooltip = nil;
|
|
else
|
|
self.Highlight:Hide();
|
|
local lockReason, hasTimer = PrivateFrame:GetLockReason();
|
|
tooltip:AddLine(lockReason, 1.000, 0.282, 0.000, true); --WARNING_FONT_COLOR
|
|
if hasTimer then
|
|
local seconds = PrivateFrame:GetLockRemainingSeconds();
|
|
if seconds and seconds > 0 then
|
|
local remainingTime = string.format(L["Available In Format"], SecondsToTime(seconds, true));
|
|
tooltip:AddLine(remainingTime, 1, 0.82, 0, true);
|
|
self.UpdateTooltip = self.UpdateTooltipTimer;
|
|
else
|
|
self.UpdateTooltip = nil;
|
|
end
|
|
else
|
|
self.UpdateTooltip = nil;
|
|
end
|
|
end
|
|
tooltip:Show();
|
|
end
|
|
|
|
function HornButton:OnLeave()
|
|
GameTooltip:Hide();
|
|
self.Highlight:Hide();
|
|
end
|
|
|
|
function HornButton:EnableCursorBlocker(state)
|
|
self.CursorBlocker:SetShown(state);
|
|
end
|
|
|
|
function HornButton:Init()
|
|
local tex = "Interface/AddOns/Plumber/Art/Button/HornButton";
|
|
|
|
self.Highlight = self:CreateTexture(nil, "OVERLAY"); --HIGHLIGHT layers doesn't work well when SetMotionScriptsWhileDisabled = true
|
|
self.Highlight:Hide();
|
|
self.Highlight:SetSize(32, 32);
|
|
self.Highlight:SetPoint("CENTER", self, "CENTER", 0, 0);
|
|
self.Highlight:SetTexture(tex);
|
|
self.Highlight:SetTexCoord(0.5, 1, 0, 1);
|
|
|
|
self.Icon = self:CreateTexture(nil, "ARTWORK");
|
|
self.Icon:SetSize(32, 32);
|
|
self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
|
|
self.Icon:SetTexture(tex);
|
|
self.Icon:SetTexCoord(0, 0.5, 0, 1);
|
|
|
|
self:SetScript("OnMouseDown", self.OnMouseDown);
|
|
self:SetScript("OnMouseUp", self.OnMouseUp);
|
|
self:SetScript("OnClick", self.OnClick);
|
|
self:SetScript("OnEnable", self.OnEnable);
|
|
self:SetScript("OnDisable", self.OnDisable);
|
|
self:SetScript("OnShow", self.OnShow);
|
|
self:SetScript("OnHide", self.OnHide);
|
|
self:SetScript("OnEnter", self.OnEnter);
|
|
self:SetScript("OnLeave", self.OnLeave);
|
|
|
|
local CursorBlocker = CreateFrame("Frame", nil, self);
|
|
self.CursorBlocker = CursorBlocker;
|
|
CursorBlocker:SetSize(40, 40);
|
|
CursorBlocker:Hide();
|
|
CursorBlocker:SetPoint("CENTER", self, "CENTER", 0, 0);
|
|
CursorBlocker:SetFrameStrata("BACKGROUND");
|
|
CursorBlocker:SetFixedFrameStrata(true);
|
|
CursorBlocker:EnableMouse(true);
|
|
|
|
self.Init = nil;
|
|
end
|
|
|
|
function HornButton:SetValidityCheck(validateFunc)
|
|
PrivateFrame.validateFunc = validateFunc or AlwaysFalse;
|
|
end
|
|
|
|
function HornButton:OnUpdate(elapsed)
|
|
self.t = self.t + elapsed;
|
|
if self.t >= 0.5 then
|
|
self:SetScript("OnUpdate", nil);
|
|
if self.callback then
|
|
self.callback();
|
|
self.callback = nil;
|
|
end
|
|
PrivateFrame:Show();
|
|
PrivateFrame:UpdateValidity();
|
|
end
|
|
end
|
|
|
|
function HornButton:ShowAndRequestUpdate(optionalCallback)
|
|
self:Disable();
|
|
self.t = 0;
|
|
self.callback = optionalCallback;
|
|
self:SetScript("OnUpdate", self.OnUpdate);
|
|
self:Show();
|
|
end
|
|
|
|
local function GetAnnounceButton()
|
|
if HornButton.Init then
|
|
HornButton:Init();
|
|
end
|
|
HornButton:Hide();
|
|
|
|
return HornButton
|
|
end
|
|
addon.GetAnnounceButton = GetAnnounceButton;
|
|
|
|
|
|
|
|
do
|
|
local locale = GetLocale();
|
|
if locale == "ruRU" then
|
|
DELENSION = ": ";
|
|
end
|
|
end
|
|
--Debug
|
|
--[[
|
|
local function ProcessChatMessage(msg)
|
|
local uiMapID, x, y = GetWaypointFromText(msg);
|
|
if uiMapID then
|
|
print(uiMapID, x, y)
|
|
end
|
|
end
|
|
|
|
function PrintChatWaypoints()
|
|
SearchChatHistory(ProcessChatMessage);
|
|
end
|
|
|
|
function Debug_WaypointsMatch()
|
|
local uiMapID = C_Map.GetBestMapForUnit("player");
|
|
local posVector = C_Map.GetUserWaypointPositionForMap(uiMapID);
|
|
|
|
if posVector then
|
|
local x, y = posVector:GetXY();
|
|
local LocationDataProvider = API.DreamseedUtil;
|
|
local isClose;
|
|
|
|
for creatureID, position in LocationDataProvider:EnumerateSpawnLocations() do
|
|
isClose = AreWaypointsClose(x, y, position[1], position[2]);
|
|
if isClose then
|
|
local name = LocationDataProvider:GetPlantNameByCreatureID(creatureID);
|
|
print(name)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
--]]
|