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.
492 lines
16 KiB
492 lines
16 KiB
local _, addon = ...
|
|
local API = addon.API;
|
|
local MainFrame = addon.DialogueUI;
|
|
local IsInteractingWithDialogNPC = API.IsInteractingWithDialogNPC;
|
|
local CancelClosingGossipInteraction = API.CancelClosingGossipInteraction;
|
|
local QuestIsFromAreaTrigger = API.QuestIsFromAreaTrigger;
|
|
local GossipDataProvider = addon.GossipDataProvider;
|
|
local QuestGetAutoAccept = API.QuestGetAutoAccept;
|
|
local ShouldMuteQuestDetail = API.ShouldMuteQuestDetail;
|
|
local CloseQuest = CloseQuest;
|
|
local InCombatLockdown = InCombatLockdown;
|
|
local IsInInstance = IsInInstance;
|
|
local GetQuestID = GetQuestID;
|
|
|
|
|
|
local EVENT_PROCESS_DELAY = 0.017; --Affected by CameraMovement
|
|
local MAINTAIN_CAMERA_POSITION = false;
|
|
local USE_AUTO_QUEST_POPUP = true;
|
|
local DISABLE_DUI_IN_INSTANCE = false;
|
|
local HANDLE_EVENT_EXTERNALLY = false; --If true, Events will be handled by Skimmers
|
|
|
|
|
|
local EL = CreateFrame("Frame");
|
|
local Muter = {};
|
|
|
|
local function GetCustomGossipHandler()
|
|
end
|
|
|
|
local GossipEvents = {
|
|
"GOSSIP_SHOW", "GOSSIP_CLOSED",
|
|
"CONFIRM_TALENT_WIPE", --Classic
|
|
};
|
|
|
|
local QuestEvents = {
|
|
"QUEST_PROGRESS",
|
|
"QUEST_DETAIL",
|
|
"QUEST_FINISHED", --Close QuestFrame
|
|
"QUEST_GREETING", --Offer several quests
|
|
"QUEST_COMPLETE", --Talk to turn in quest
|
|
};
|
|
|
|
local MapEvents = {
|
|
PLAYER_ENTERING_WORLD = true,
|
|
ZONE_CHANGED_NEW_AREA = true,
|
|
};
|
|
|
|
local CloseDialogEvents = {};
|
|
|
|
if not addon.IsToCVersionEqualOrNewerThan(50000) then
|
|
local ClassicEvents = {
|
|
"CONFIRM_TALENT_WIPE", "CONFIRM_TALENT_WIPE",
|
|
};
|
|
|
|
for _, event in ipairs(ClassicEvents) do
|
|
table.insert(GossipEvents, event);
|
|
CloseDialogEvents[event] = true;
|
|
end
|
|
end
|
|
|
|
local function ShouldMuteQuest()
|
|
local questID = GetQuestID();
|
|
return ShouldMuteQuestDetail(questID)
|
|
end
|
|
|
|
function EL:OnManualEvent(event, ...)
|
|
self:SetScript("OnUpdate", nil);
|
|
|
|
if event == "QUEST_FINISHED" or event == "QUEST_FINISHED_FORCED" then
|
|
--For the issue where the quest window fails to close:
|
|
--Sometimes QUEST_FINISHED fires but IsInteractingWithNpcOfType still thinks we are interacting with QuestGiver
|
|
--/dump C_PlayerInteractionManager.IsInteractingWithNpcOfType(Enum.PlayerInteractionType.QuestGiver)
|
|
--print(event, "IS INTERACTING", IsInteractingWithDialogNPC(), GetTimePreciseSec()) --debug
|
|
if (event == "QUEST_FINISHED_FORCED") or (not IsInteractingWithDialogNPC()) then
|
|
self.timeSinceQuestFinish = nil;
|
|
MainFrame:HideUI();
|
|
end
|
|
elseif event == "GOSSIP_SHOW" then
|
|
MainFrame:ShowUI(event);
|
|
elseif event == "GOSSIP_CLOSED" then
|
|
self:OnGossipClosed(...);
|
|
end
|
|
end
|
|
|
|
function EL:OnGossipClosed(interactionIsContinuing)
|
|
if self.customFrame then
|
|
local f = self.customFrame;
|
|
self.customFrame = nil;
|
|
if not InCombatLockdown() then
|
|
HideUIPanel(f);
|
|
end
|
|
return
|
|
end
|
|
|
|
if not IsInteractingWithDialogNPC() then
|
|
if not MainFrame:IsGossipCloseConsumed() then
|
|
--MainFrame:SetInteractionIsContinuing(interactionIsContinuing);
|
|
self.timeSinceQuestFinish = nil;
|
|
MainFrame:HideUI();
|
|
end
|
|
GossipDataProvider:OnInteractStopped();
|
|
end
|
|
end
|
|
|
|
function EL:NegateLastEvent(event)
|
|
if event == self.lastEvent then
|
|
self.lastEvent = nil;
|
|
end
|
|
end
|
|
|
|
function EL:OnEvent(event, ...)
|
|
if HANDLE_EVENT_EXTERNALLY then
|
|
return
|
|
end
|
|
|
|
if event == "GOSSIP_SHOW" then
|
|
self.lastEvent = event;
|
|
local handler = GetCustomGossipHandler(...);
|
|
if handler then
|
|
self.customFrame = handler(...);
|
|
else
|
|
if self:ThrottleGossipEvent() then
|
|
GossipDataProvider:OnInteractWithNPC();
|
|
MainFrame:ShowUI(event); --Depends on the options, we may select the non-gossip one directly without openning the UI
|
|
CancelClosingGossipInteraction();
|
|
end
|
|
end
|
|
|
|
self:NegateLastEvent(event);
|
|
|
|
elseif event == "GOSSIP_CLOSED" then
|
|
self.lastEvent = event;
|
|
self:ProcessEventNextUpdate(0.1);
|
|
--self:OnGossipClosed(...);
|
|
|
|
elseif event == "QUEST_FINISHED" then
|
|
--When the quest giver has more than one quest
|
|
--sometimes there is a delay between QUEST_FINISHED and GOSSIP_SHOW (presumably depends on various of factors including latency)
|
|
--the game determinates interaction then re-engage, messing up ActionCam and gossip info
|
|
--our workaround is setting s delay to this event
|
|
--print(event, GetTimePreciseSec(), IsInteractingWithDialogNPC());
|
|
|
|
local delay = MainFrame:GetQuestFinishedDelay();
|
|
|
|
self.timeSinceQuestFinish = -delay;
|
|
|
|
if self.lastEvent ~= "QUEST_FINISHED_FORCED" then
|
|
self.lastEvent = event;
|
|
self:ProcessEventNextUpdate(delay);
|
|
end
|
|
|
|
elseif event == "QUEST_DETAIL" then
|
|
--Can fire multiple times in rare occasions, possibly due to cross-character progress
|
|
|
|
if ShouldMuteQuest() then
|
|
if API.IsQuestAutoAccepted() then
|
|
API.AcknowledgeAutoAcceptQuest();
|
|
end
|
|
CloseQuest();
|
|
return
|
|
end
|
|
|
|
self.lastEvent = event;
|
|
|
|
local questStartItemID = ...
|
|
|
|
if USE_AUTO_QUEST_POPUP and questStartItemID and questStartItemID ~= 0 then
|
|
addon.WidgetManager:AddAutoQuestPopUp(questStartItemID);
|
|
CloseQuest();
|
|
return
|
|
end
|
|
|
|
if USE_AUTO_QUEST_POPUP and QuestIsFromAreaTrigger() and (QuestGetAutoAccept() or InCombatLockdown()) then
|
|
--"QuestIsFromAreaTrigger" and "QuestGetAutoAccept" Doesn't work in Classic
|
|
--Some quests that triggered upon login aren't "QuestIsFromAreaTrigger"
|
|
addon.WidgetManager:AddAutoQuestPopUp();
|
|
CloseQuest();
|
|
else
|
|
MainFrame:ShowUI(event, questStartItemID);
|
|
end
|
|
|
|
elseif event == "QUEST_PROGRESS" or event == "QUEST_COMPLETE" or event == "QUEST_GREETING" then
|
|
--Sometimes QUEST_FINISHED fires before QUEST_COMPLETE
|
|
self.lastEvent = event;
|
|
MainFrame:ShowUI(event);
|
|
|
|
elseif CloseDialogEvents[event] then
|
|
self.lastEvent = event;
|
|
self.timeSinceQuestFinish = nil;
|
|
MainFrame:HideUI();
|
|
|
|
elseif MapEvents[event] then
|
|
if DISABLE_DUI_IN_INSTANCE then
|
|
Muter:UpdateForInstance();
|
|
end
|
|
end
|
|
|
|
--print(event, GetTimePreciseSec(), ...); --debug
|
|
end
|
|
|
|
function EL:ListenEvents(state)
|
|
local method;
|
|
|
|
if state then
|
|
method = "RegisterEvent";
|
|
self:SetScript("OnEvent", self.OnEvent);
|
|
else
|
|
method= "UnregisterEvent";
|
|
if DISABLE_DUI_IN_INSTANCE then
|
|
self:SetScript("OnEvent", self.OnEvent);
|
|
else
|
|
self:SetScript("OnEvent", nil);
|
|
end
|
|
end
|
|
|
|
for _, event in ipairs(GossipEvents) do
|
|
self[method](self, event);
|
|
end
|
|
|
|
for _, event in ipairs(QuestEvents) do
|
|
self[method](self, event);
|
|
end
|
|
|
|
--self[method](self, "PLAYER_INTERACTION_MANAGER_FRAME_SHOW"); --debug
|
|
--self[method](self, "PLAYER_INTERACTION_MANAGER_FRAME_HIDE");
|
|
end
|
|
|
|
function EL:OnUpdate(elapsed)
|
|
if self.timeSinceQuestFinish then
|
|
self.timeSinceQuestFinish = self.timeSinceQuestFinish + elapsed;
|
|
if self.timeSinceQuestFinish > EVENT_PROCESS_DELAY then
|
|
self.timeSinceQuestFinish = nil;
|
|
if self.lastEvent == "QUEST_FINISHED" or self.lastEvent == "QUEST_FINISHED_FORCED" then
|
|
if not IsInteractingWithDialogNPC() then
|
|
--print("COUNTER STOP", UnitExists("npc"))
|
|
self.processEvent = nil;
|
|
self.lastEvent = nil;
|
|
MainFrame:HideUI();
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.processEvent then
|
|
self.t = self.t + elapsed;
|
|
|
|
if self.t > EVENT_PROCESS_DELAY then
|
|
self.t = 0;
|
|
self.processEvent = nil;
|
|
if self.lastEvent then
|
|
--print("LAST EVENT", self.lastEvent)
|
|
self:OnManualEvent(self.lastEvent);
|
|
self.lastEvent = nil;
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.pauseGossip then
|
|
self.pauseGossip = self.pauseGossip + elapsed;
|
|
if self.pauseGossip >= 0 then
|
|
self.pauseGossip = nil;
|
|
end
|
|
end
|
|
|
|
if not (self.processEvent or self.pauseGossip) then
|
|
self:SetScript("OnUpdate", nil);
|
|
end
|
|
end
|
|
|
|
function EL:ThrottleGossipEvent()
|
|
if not self.pauseGossip then
|
|
self.pauseGossip = 0.016;
|
|
self:SetScript("OnUpdate", self.OnUpdate);
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function EL:ProcessEventNextUpdate(customDelay)
|
|
customDelay = customDelay or 0;
|
|
self.t = -customDelay;
|
|
self.processEvent = true;
|
|
self:SetScript("OnUpdate", self.OnUpdate);
|
|
end
|
|
|
|
do
|
|
local DEFAULT_CAMERA_MODE = 1;
|
|
|
|
local function OnCameraModeChanged(_, mode)
|
|
if mode == 0 then --0: No Zoom
|
|
EVENT_PROCESS_DELAY = 0.017;
|
|
elseif mode == 1 then --1: Zoom to NPC
|
|
if MAINTAIN_CAMERA_POSITION then
|
|
EVENT_PROCESS_DELAY = 0.5;
|
|
else
|
|
EVENT_PROCESS_DELAY = 0.017;
|
|
end
|
|
elseif mode == 2 then --2: Shift camear horizontally
|
|
EVENT_PROCESS_DELAY = 0.5;
|
|
end
|
|
DEFAULT_CAMERA_MODE = mode;
|
|
end
|
|
|
|
addon.CallbackRegistry:Register("Camera.ModeChanged", OnCameraModeChanged, EL);
|
|
|
|
local function Settings_CameraMovement1MaintainPosition(dbValue)
|
|
MAINTAIN_CAMERA_POSITION = dbValue == true;
|
|
if DEFAULT_CAMERA_MODE then
|
|
OnCameraModeChanged(nil, DEFAULT_CAMERA_MODE);
|
|
end
|
|
end
|
|
addon.CallbackRegistry:Register("SettingChanged.CameraMovement1MaintainPosition", Settings_CameraMovement1MaintainPosition);
|
|
|
|
local function ManualTriggerQuestFinished(isAutoComplete)
|
|
--print("TRIGGER FINISH", GetTimePreciseSec()) --debug
|
|
if EL.lastEvent ~= "QUEST_FINISHED_FORCED" then
|
|
EL.lastEvent = "QUEST_FINISHED_FORCED";
|
|
EL:ProcessEventNextUpdate(1.5); --Force trigger QUEST_FINISHED event to close the UI. We use extended delay (1s) due to unavailable server latency
|
|
end
|
|
end
|
|
addon.CallbackRegistry:Register("TriggerQuestFinished", ManualTriggerQuestFinished);
|
|
|
|
local function Settings_AutoQuestPopup(dbValue)
|
|
USE_AUTO_QUEST_POPUP = dbValue ~= false;
|
|
end
|
|
addon.CallbackRegistry:Register("SettingChanged.AutoQuestPopup", Settings_AutoQuestPopup);
|
|
end
|
|
|
|
do --Unlisten events from default UI
|
|
--CustomGossipFrameManager:
|
|
--We need to mute this so HideUI doesn't trigger CloseGossip
|
|
--It handle NPE (Be A Guide) and Torghast Floor Selection
|
|
|
|
|
|
Muter.questEvents = {
|
|
QUEST_GREETING = true,
|
|
QUEST_DETAIL = true,
|
|
QUEST_PROGRESS = true,
|
|
QUEST_COMPLETE = true,
|
|
QUEST_FINISHED = true,
|
|
QUEST_ITEM_UPDATE = true,
|
|
QUEST_LOG_UPDATE = true,
|
|
UNIT_PORTRAIT_UPDATE = true,
|
|
PORTRAITS_UPDATED = true,
|
|
};
|
|
|
|
if addon.IsToCVersionEqualOrNewerThan(50000) then
|
|
Muter.questEvents.LEARNED_SPELL_IN_SKILL_LINE = true;
|
|
else
|
|
Muter.questEvents.LEARNED_SPELL_IN_TAB = true; --Classic
|
|
end
|
|
|
|
local function SetUseDialogueUI(state)
|
|
if state == nil then state = true end;
|
|
|
|
if state then
|
|
if Muter.muted then return end;
|
|
Muter.muted = true;
|
|
EL:ListenEvents(true);
|
|
|
|
if CustomGossipFrameManager then --CustomGossipFrameBase.lua (Retail)
|
|
CustomGossipFrameManager:UnregisterEvent("GOSSIP_SHOW");
|
|
CustomGossipFrameManager:UnregisterEvent("GOSSIP_CLOSED");
|
|
end
|
|
|
|
if GossipFrame then --Classic
|
|
GossipFrame:UnregisterEvent("GOSSIP_SHOW");
|
|
GossipFrame:UnregisterEvent("GOSSIP_CLOSED");
|
|
GossipFrame:UnregisterEvent("QUEST_LOG_UPDATE");
|
|
end
|
|
|
|
local hideQuestFrame = true; --false when we do debug
|
|
if hideQuestFrame then
|
|
QuestFrame:UnregisterAllEvents();
|
|
else
|
|
QuestFrame:SetParent(nil);
|
|
QuestFrame:SetScale(2/3);
|
|
end
|
|
|
|
elseif Muter.muted then
|
|
Muter.muted = false;
|
|
EL:ListenEvents(false);
|
|
|
|
if CustomGossipFrameManager then --CustomGossipFrameBase.lua (Retail)
|
|
CustomGossipFrameManager:RegisterEvent("GOSSIP_SHOW");
|
|
CustomGossipFrameManager:RegisterEvent("GOSSIP_CLOSED");
|
|
end
|
|
|
|
if GossipFrame then --Classic
|
|
GossipFrame:RegisterEvent("GOSSIP_SHOW");
|
|
GossipFrame:RegisterEvent("GOSSIP_CLOSED");
|
|
GossipFrame:RegisterEvent("QUEST_LOG_UPDATE");
|
|
end
|
|
|
|
local hideQuestFrame = true; --false when we do debug
|
|
if hideQuestFrame then
|
|
local qf = QuestFrame;
|
|
for event, valid in pairs(Muter.questEvents) do
|
|
if valid then
|
|
qf:RegisterEvent(event);
|
|
end
|
|
end
|
|
else
|
|
QuestFrame:SetParent(UIParent);
|
|
QuestFrame:SetScale(1);
|
|
end
|
|
end
|
|
|
|
addon.EnableBookUI(state);
|
|
end
|
|
addon.SetUseDialogueUI = SetUseDialogueUI;
|
|
|
|
SetUseDialogueUI(true);
|
|
|
|
function Muter:UpdateForInstance()
|
|
if IsInInstance() then
|
|
SetUseDialogueUI(false);
|
|
else
|
|
SetUseDialogueUI(true);
|
|
end
|
|
end
|
|
|
|
local function Settings_DisableDUIInInstance(dbValue, userInput)
|
|
DISABLE_DUI_IN_INSTANCE = dbValue == true;
|
|
if DISABLE_DUI_IN_INSTANCE then
|
|
for event in pairs(MapEvents) do
|
|
EL:RegisterEvent(event);
|
|
end
|
|
Muter:UpdateForInstance();
|
|
if userInput and IsInInstance() and MainFrame:IsShown() then
|
|
MainFrame:Hide();
|
|
end
|
|
else
|
|
for event in pairs(MapEvents) do
|
|
EL:UnregisterEvent(event);
|
|
end
|
|
SetUseDialogueUI(true);
|
|
end
|
|
end
|
|
addon.CallbackRegistry:Register("SettingChanged.DisableDUIInInstance", Settings_DisableDUIInInstance);
|
|
end
|
|
|
|
do --See Blizzard_UIPanels_Game/CustomGossipFrameBase.lua
|
|
local function HandleNPEGuideGossipShow(textureKit)
|
|
C_AddOns.LoadAddOn("Blizzard_NewPlayerExperienceGuide");
|
|
ShowUIPanel(GuideFrame);
|
|
return GuideFrame
|
|
end
|
|
|
|
local function HandleTorghastLevelPickerGossipShow(textureKit)
|
|
C_AddOns.LoadAddOn("Blizzard_TorghastLevelPicker");
|
|
TorghastLevelPickerFrame:TryShow(textureKit)
|
|
return TorghastLevelPickerFrame
|
|
end
|
|
|
|
local function HandleDelvesDifficultyPickerGossipShow(textureKit) --TWW
|
|
C_AddOns.LoadAddOn("Blizzard_DelvesDifficultyPicker");
|
|
DelvesDifficultyPickerFrame:TryShow(textureKit);
|
|
return DelvesDifficultyPickerFrame
|
|
end
|
|
|
|
local Handlers = {};
|
|
|
|
function EL:RegisterHandler(textureKit, func)
|
|
Handlers[textureKit] = func;
|
|
end
|
|
|
|
function EL:RegisterCustomGossipFrames()
|
|
self:RegisterHandler("npe-guide", HandleNPEGuideGossipShow);
|
|
self:RegisterHandler("skoldushall", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("mortregar", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("coldheartinterstitia", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("fracturechambers", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("soulforges", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("theupperreaches", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("twistingcorridors", HandleTorghastLevelPickerGossipShow);
|
|
self:RegisterHandler("delves-difficulty-picker", HandleDelvesDifficultyPickerGossipShow); --For some reason this textureKit is sometimes nil, causing issue
|
|
end
|
|
EL:RegisterCustomGossipFrames();
|
|
|
|
function GetCustomGossipHandler(textureKit)
|
|
return textureKit and Handlers[textureKit]
|
|
end
|
|
addon.GetCustomGossipHandler = GetCustomGossipHandler;
|
|
end
|
|
|
|
do --DEBUG Skimmer
|
|
local function SetHandleEventExternally(state)
|
|
HANDLE_EVENT_EXTERNALLY = state == true;
|
|
end
|
|
addon.SetHandleEventExternally = SetHandleEventExternally;
|
|
end
|