---@class QuestieAuto ---@field private private QuestieAutoPrivate local QuestieAuto = QuestieLoader:CreateModule("QuestieAuto"); local _QuestieAuto = QuestieAuto.private ---@type QuestieDB local QuestieDB = QuestieLoader:ImportModule("QuestieDB"); --- COMPATIBILITY --- local C_Timer = QuestieCompat.C_Timer local GetQuestID = QuestieCompat.GetQuestID local shouldRunAuto = true local doneTalking = false local cameFromProgressEvent = false local isAllowedNPC = false local lastAmountOfAvailableQuests = 0 local lastNPCTalkedTo local doneWithAccept = false local lastIndexTried = 1 local lastEvent local MOP_INDEX_AVAILABLE = 7 -- was '5' in Cataclysm local MOP_INDEX_COMPLETE = 6 -- was '4' in Cataclysm -- forward declarations local _SelectAvailableQuest local function ResetModifier() shouldRunAuto = true lastEvent = nil end function QuestieAuto:GOSSIP_SHOW(event, ...) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] GOSSIP_SHOW", event, ...) doneTalking = false if (not shouldRunAuto) then return elseif _QuestieAuto:IsBindTrue(Questie.db.profile.autoModifier) then shouldRunAuto = false Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Modifier-Key down: Disabling QuestieAuto for now") return end lastEvent = "GOSSIP_SHOW" local availableQuests = { QuestieCompat.GetAvailableQuests() } local currentNPC = UnitName("target") if lastNPCTalkedTo ~= currentNPC or #availableQuests ~= lastAmountOfAvailableQuests then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Greeted by a new NPC") lastNPCTalkedTo = currentNPC isAllowedNPC = _QuestieAuto:IsAllowedNPC() lastIndexTried = 1 lastAmountOfAvailableQuests = #availableQuests doneWithAccept = false end if cameFromProgressEvent then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Last event was Progress") cameFromProgressEvent = false lastIndexTried = lastIndexTried + MOP_INDEX_AVAILABLE end -- Turn in complete quests if Questie.db.profile.autocomplete and isAllowedNPC then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Checking active quests from gossip") local completeQuests = { QuestieCompat.GetActiveQuests() } for index = 1, #completeQuests, MOP_INDEX_COMPLETE do _QuestieAuto:CompleteQuestFromGossip(index, completeQuests, MOP_INDEX_COMPLETE) end Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] DONE. Checked all complete quests") end -- Accept new quests if Questie.db.profile.autoaccept and (not doneWithAccept) and isAllowedNPC then if lastIndexTried < #availableQuests then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Checking available quests from gossip") _QuestieAuto:AcceptQuestFromGossip(lastIndexTried, availableQuests, MOP_INDEX_AVAILABLE) return else Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] DONE. Checked all available quests") doneWithAccept = true lastIndexTried = 1 end end end function QuestieAuto:QUEST_PROGRESS(event, ...) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] QUEST_PROGRESS", event, ...) doneTalking = false if (not shouldRunAuto) then return elseif _QuestieAuto:IsBindTrue(Questie.db.profile.autoModifier) then shouldRunAuto = false Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Modifier-Key down: Disabling QuestieAuto for now") return end if Questie.db.profile.autocomplete then if _QuestieAuto:IsAllowedNPC() and _QuestieAuto:IsAllowedQuest() then if IsQuestCompletable() then CompleteQuest() return else Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Quest not completeable. Index", lastIndexTried) end end -- Close the QuestFrame if no quest is completeable again if QuestFrameGoodbyeButton and lastEvent ~= nil then QuestFrameGoodbyeButton:Click() end cameFromProgressEvent = true end lastEvent = "QUEST_PROGRESS" end _SelectAvailableQuest = function(index) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Selecting available quest at index", index) SelectAvailableQuest(index) end function QuestieAuto:QUEST_ACCEPT_CONFIRM(event, ...) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] QUEST_ACCEPT_CONFIRM", event, ...) lastEvent = "QUEST_ACCEPT_CONFIRM" doneTalking = false -- Escort stuff if (Questie.db.profile.autoaccept) then ConfirmAcceptQuest() end end function QuestieAuto:QUEST_GREETING(event, ...) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] QUEST_GREETING", event, GetNumActiveQuests(), ...) lastEvent = "QUEST_GREETING" doneTalking = false if (not shouldRunAuto) then return elseif _QuestieAuto:IsBindTrue(Questie.db.profile.autoModifier) then shouldRunAuto = false Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Modifier-Key down: Disabling QuestieAuto for now") return end if cameFromProgressEvent then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Last event was Progress") cameFromProgressEvent = false lastIndexTried = lastIndexTried + 1 end -- Quest already taken if (Questie.db.profile.autocomplete) then for index = 1, GetNumActiveQuests() do local quest, isComplete = GetActiveTitle(index) Questie:Debug(Questie.DEBUG_DEVELOP, quest, isComplete) if isComplete then SelectActiveQuest(index) end end end if (Questie.db.profile.autoaccept) then local availableQuestsCount = GetNumAvailableQuests() if lastIndexTried == 0 or lastIndexTried > availableQuestsCount then lastIndexTried = 1 end Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] lastIndex:", lastIndexTried) if availableQuestsCount > 0 and lastIndexTried < availableQuestsCount then _SelectAvailableQuest(lastIndexTried) end end end function QuestieAuto:QUEST_DETAIL(event, ...) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] QUEST_DETAIL", event, ...) lastEvent = "QUEST_DETAIL" doneTalking = false if (not shouldRunAuto) then return elseif _QuestieAuto:IsBindTrue(Questie.db.profile.autoModifier) then shouldRunAuto = false Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Modifier-Key down: Disabling QuestieAuto for now") return end -- We really want to disable this in instances, mostly to prevent retards from ruining groups. if (Questie.db.profile.autoaccept and _QuestieAuto:IsAllowedNPC() and _QuestieAuto:IsAllowedQuest(true)) then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] INSIDE", event, ...) local questId = GetQuestID(true) local questLevel if questId and questId ~= 0 then questLevel = QuestieDB.QueryQuestSingle(questId, "questLevel") end if not questLevel then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] No quest object, retrying in 1 second") C_Timer.After(1, function() questId = GetQuestID(true) if questId and questId ~= 0 then questLevel = QuestieDB.QueryQuestSingle(questId, "questLevel") if not questLevel then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] retry failed. Quest", questId, "might not be in the DB!") elseif (not QuestieDB.IsTrivial(questLevel)) or Questie.db.profile.acceptTrivial then Questie:Debug(Questie.DEBUG_INFO, "[QuestieAuto] Questie Auto-Accepting quest:", questId) AcceptQuest() end end end) return end if (not QuestieDB.IsTrivial(questLevel)) or Questie.db.profile.acceptTrivial then Questie:Debug(Questie.DEBUG_INFO, "[QuestieAuto] Questie Auto-Accepting quest:", questId) AcceptQuest() end end end -- I was forced to make decision on offhand, cloak and shields separate from armor but I can't pick up my mind about the reason... function QuestieAuto:QUEST_COMPLETE(event, ...) Questie:Debug(Questie.DEBUG_DEVELOP, "[EVENT] QUEST_COMPLETE", event, ...) lastEvent = "QUEST_COMPLETE" doneTalking = false if (not shouldRunAuto) then return elseif _QuestieAuto:IsBindTrue(Questie.db.profile.autoModifier) then shouldRunAuto = false Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Modifier-Key down: Disabling QuestieAuto for now") return end -- blasted Lands citadel wonderful NPC. They do not trigger any events except quest_complete. -- if not AllowedToHandle() then -- return -- end if (Questie.db.profile.autocomplete) then local questname = GetTitleText() local numOptions = GetNumQuestChoices() Questie:Debug(Questie.DEBUG_DEVELOP, event, questname, numOptions, ...) if numOptions > 1 then Questie:Debug(Questie.DEBUG_INFO, "[QuestieAuto] Multiple rewards (" .. numOptions .. ")! Please choose appropriate reward!") else _QuestieAuto:TurnInQuest(1) Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] Completed quest!") end end end local _QuestFinishedCallback = function() if _QuestieAuto:AllQuestWindowsClosed() then Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] All quest windows closed! Resetting shouldRunAuto") ResetModifier() end end function QuestieAuto:QUEST_FINISHED() Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] QUEST_FINISHED") C_Timer.After(0.5, _QuestFinishedCallback) end function QuestieAuto:QUEST_ACCEPTED() Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] QUEST_ACCEPTED") if Questie.db.profile.bugWorkarounds == true and QuestFrameDetailPanel:IsVisible() == true then QuestFrameCloseButton:Click() end end --[[ TODO: This function already exsists in Privates.lua line 8. Does it belong here or in Privates? function _QuestieAuto:AllQuestWindowsClosed() if GossipFrame and (not GossipFrame:IsVisible()) and GossipFrameGreetingPanel and (not GossipFrameGreetingPanel:IsVisible()) and QuestFrameGreetingPanel and (not QuestFrameGreetingPanel:IsVisible()) and QuestFrameDetailPanel and (not QuestFrameDetailPanel:IsVisible()) and QuestFrameProgressPanel and (not QuestFrameProgressPanel:IsVisible()) and QuestFrameRewardPanel and (not QuestFrameRewardPanel:IsVisible()) then return true end return false end --]] --- The closingCounter needs to reach 1 for QuestieAuto to reset --- Whenever the gossip frame is closed this event is called once, HOWEVER --- when totally stop talking to an NPC this event is called twice. --- Another special case is: If you run away from the NPC the event is called --- just once. function QuestieAuto:GOSSIP_CLOSED() Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto][EVENT] GOSSIP_CLOSED") lastEvent = "GOSSIP_CLOSED" if doneTalking then doneTalking = false Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieAuto] We are done talking to an NPC! Resetting shouldRunAuto") shouldRunAuto = true lastEvent = nil else doneTalking = true end end