diff --git a/mods/skip-gossip.lua b/mods/skip-gossip.lua index 0dfe14d..e929184 100644 --- a/mods/skip-gossip.lua +++ b/mods/skip-gossip.lua @@ -1,128 +1,138 @@ -local L, T = ShaguTweaks.L, ShaguTweaks.T - -local module = ShaguTweaks:register({ - title = T["Skip Gossip Text"], - description = T["Skip gossip text when interacting with NPCs unless holding shift."], - expansions = { ["vanilla"] = true, ["tbc"] = nil }, - category = nil, - enabled = nil, -}) - -module.enable = function(self) - local actions = CreateFrame("Frame", nil, UIParent) - - local professions = { - "battlemaster", - "taxi", - "trainer", - "vendor", - "banker", - } - - local phrases = { - -- Bank - "I would like to check my deposit box", - - -- Vanilla - "Teleport me to the Molten Core", - - -- Turtle WoW - -- Alliance - "Please open a portal to Alah'Thalas", - "Please open a portal to Stormwind", - -- Horde - "Open a portal to Amani'Alor", - - -- ruRU - "Я хотел бы проверить свою ячейку.", -- Bank - "*Прикоснуться к нестабильному кристаллу Провала.*", -- MC entrance - "\*Положить руку на сферу.\*", -- BWL entrance - --"Thank you, Stable Master. Please take the animal.", -- AV quest locales_broadcast_text id6681 - "Благодарю тебя. Пожалуйста, возьми питомца.", -- AV quest locales_broadcast_text id6681 - "С удовольствием. Уж очень они воняют!", -- AV quest - "Конфета или Жизнь!", - } - - local ignore = { - -- npcs named here will be ignored - "Goblin Brainwashing Device", - } - - function actions:Gossip() - if actions.gossip then - local name = GossipFrameNpcNameText:GetText() - local GossipOptions = {} - local title - - title,GossipOptions[1],_,GossipOptions[2],_,GossipOptions[3],_,GossipOptions[4],_,GossipOptions[5] = GetGossipOptions() - - -- Ported from LazyPig: "title" here is actually the text of the - -- FIRST gossip option. Keep an unmutated copy before the - -- word-stripping below, so we can gate the talent trainer - -- confirmation on it. - local rawTitle = title - - if name then - for _, npc in pairs(ignore) do - if name == npc then - return true - end - end - end - - -- Ported from LazyPig: if a "binder" (innkeeper hearthstone) - -- option is present and we are NOT currently at our bind - -- point, don't auto-skip anything in this menu at all. - for i = 1, 5 do - if not GossipOptions[i] then break end - if GossipOptions[i] == "binder" then - local bind = GetBindLocation() - if not (bind == GetSubZoneText() or bind == GetZoneText() - or bind == GetRealZoneText() or bind == GetMinimapZoneText()) then - return - end - end - end - - for i = 1, 5 do - if not GossipOptions[i] then break end - - if GossipOptions[i] == "gossip" then - title = string.gsub(title, "%W", "") - - for _, phrase in pairs(phrases) do - phrase = string.gsub(phrase, "%W", "") - - if phrase == title then - SelectGossipOption(i) - break - end - end - elseif GossipOptions[i] == "trainer" and rawTitle == "Reset my talents." then - -- Ported from LazyPig: don't auto-confirm a talent - -- reset, always require a manual click. - else - for _, profession in pairs(professions) do - if profession == GossipOptions[i] then - SelectGossipOption(i) - break - end - end - end - end - end - end - - actions:RegisterEvent("GOSSIP_SHOW") - actions:RegisterEvent("GOSSIP_CLOSED") - actions:SetScript("OnEvent", function() - if (event == "GOSSIP_SHOW") then - actions.gossip = true - if not IsShiftKeyDown() then - actions:Gossip() - end - elseif (event == "GOSSIP_CLOSED") then - actions.gossip = nil - end - end) -end \ No newline at end of file +local T = ShaguTweaks.T +local API = ShaguTweaks.API + +local module = ShaguTweaks:register({ + title = T["Skip Gossip Text"], + description = T["Skip gossip text when interacting with NPCs unless holding shift."], + expansions = { ["vanilla"] = true, ["tbc"] = nil }, + category = nil, + enabled = nil, +}) + +local professions = { + battlemaster = true, + taxi = true, + trainer = true, + vendor = true, + banker = true, +} + +local ignore = { + ["Goblin Brainwashing Device"] = true, +} + +-- Strip spacing and punctuation while preserving non-ASCII letters. Using +-- %W here can erase Cyrillic text entirely on the 1.12 Lua client, causing +-- unrelated ruRU gossip options to compare as the same empty string. +local function NormalizePhrase(text) + if not text then return end + return string.gsub(text, "[%s%p]", "") +end + +local phrases = { + -- Bank + "I would like to check my deposit box", + + -- Vanilla + "Teleport me to the Molten Core", + + -- Turtle WoW + -- Alliance + "Please open a portal to Alah'Thalas", + "Please open a portal to Stormwind", + -- Horde + "Open a portal to Amani'Alor", + + -- ruRU + "Я хотел бы проверить свою ячейку.", -- Bank + "*Прикоснуться к нестабильному кристаллу Провала.*", -- MC entrance + "\\*Положить руку на сферу.\\*", -- BWL entrance + --"Thank you, Stable Master. Please take the animal.", -- AV quest locales_broadcast_text id6681 + "Благодарю тебя. Пожалуйста, возьми питомца.", -- AV quest locales_broadcast_text id6681 + "С удовольствием. Уж очень они воняют!", -- AV quest + "Конфета или Жизнь!", +} + +local normalizedPhrases = {} +for i = 1, table.getn(phrases) do + local phrase = NormalizePhrase(phrases[i]) + if phrase and phrase ~= "" then + normalizedPhrases[phrase] = true + end +end + +module.enable = function(self) + -- Reuse a single event frame so repeated enable() calls cannot stack gossip + -- handlers and select the same option more than once. + if not self.actions then + self.actions = CreateFrame("Frame", nil, UIParent) + end + + local actions = self.actions + + function actions:Gossip() + if not actions.gossip then return end + + local name = GossipFrameNpcNameText:GetText() + if name and ignore[name] then + return true + end + + local title, option1, _, option2, _, option3, _, option4, _, option5 = GetGossipOptions() + local rawTitle = title + + -- Ported from LazyPig: if a "binder" (innkeeper hearthstone) option is + -- present and we are NOT currently at our bind point, don't auto-skip + -- anything in this menu at all. + local bind + if option1 == "binder" or option2 == "binder" or option3 == "binder" + or option4 == "binder" or option5 == "binder" then + bind = GetBindLocation() + if not (bind == GetSubZoneText() or bind == GetZoneText() + or bind == GetRealZoneText() or bind == GetMinimapZoneText()) then + return + end + end + + -- "title" is the text of the first gossip option. Keep this historical + -- LazyPig behavior, but normalize it once instead of once per option and + -- once per configured phrase. + local normalizedTitle = NormalizePhrase(title) + + local function HandleOption(optionType, index) + if not optionType then return end + + if optionType == "gossip" then + if normalizedTitle and normalizedPhrases[normalizedTitle] then + SelectGossipOption(index) + return true + end + elseif optionType == "trainer" and rawTitle == "Reset my talents." then + -- Never auto-confirm a talent reset; always require a manual click. + return + elseif professions[optionType] then + SelectGossipOption(index) + return true + end + end + + if HandleOption(option1, 1) then return end + if HandleOption(option2, 2) then return end + if HandleOption(option3, 3) then return end + if HandleOption(option4, 4) then return end + HandleOption(option5, 5) + end + + actions:RegisterEvent("GOSSIP_SHOW") + actions:RegisterEvent("GOSSIP_CLOSED") + actions:SetScript("OnEvent", function() + if event == "GOSSIP_SHOW" then + actions.gossip = true + if not API.IsShiftKeyDown() then + actions:Gossip() + end + elseif event == "GOSSIP_CLOSED" then + actions.gossip = nil + end + end) +end