From 4e2e27aa8fa6ba47b9c91f8f362c03d6b07ee362 Mon Sep 17 00:00:00 2001 From: Vati Date: Thu, 9 Apr 2026 16:12:16 +0400 Subject: [PATCH] feat: auto loot and clam opener --- Core/AutoLoot.lua | 47 +++++++++++++ Core/ClamOpener.lua | 155 +++++++++++++++++++++++++++++++++++++++++++ Core/Database.lua | 6 ++ Core/Main.lua | 15 +++++ Guda.toc | 2 + Localization.lua | 71 ++++++++++++++++++++ UI/SettingsPopup.lua | 87 ++++++++++++++++++++++++ UI/SettingsPopup.xml | 26 ++++++++ 8 files changed, 409 insertions(+) create mode 100644 Core/AutoLoot.lua create mode 100644 Core/ClamOpener.lua diff --git a/Core/AutoLoot.lua b/Core/AutoLoot.lua new file mode 100644 index 0000000..083821f --- /dev/null +++ b/Core/AutoLoot.lua @@ -0,0 +1,47 @@ +-- Guda AutoLoot +-- TurtleWoW with SuperWoW removes the hardcoded shift-autoloot and exposes: +-- * SetAutoloot(0|1) — global client autoloot toggle +-- * LootSlot(slot, forceloot) — forceloot=1 is REQUIRED to actually loot +-- We prefer SetAutoloot when present (lets the client handle everything), +-- and also fall back to a LOOT_OPENED handler that calls LootSlot(slot, 1) +-- so this works on clients without SuperWoW too. + +local addon = Guda + +local AutoLoot = {} +addon.Modules.AutoLoot = AutoLoot + +local function ApplyClientSetting() + local enabled = Guda.Modules.DB and Guda.Modules.DB:GetSetting("autoLoot") + if SetAutoloot then + SetAutoloot(enabled and 1 or 0) + elseif SetAutoLootDefault then + SetAutoLootDefault(enabled and true or false) + end +end + +local function OnLootOpened() + if not (Guda.Modules.DB and Guda.Modules.DB:GetSetting("autoLoot")) then + return + end + -- If SuperWoW's SetAutoloot is present and enabled, the client has + -- already looted everything before LOOT_OPENED reaches us — this loop + -- is a no-op safety net for normal clients and any leftovers (BoP + -- confirms, etc.). + local n = GetNumLootItems() + if not n or n == 0 then return end + for slot = n, 1, -1 do + LootSlot(slot, 1) -- forceloot=1 for SuperWoW compatibility + if ConfirmLootSlot then ConfirmLootSlot(slot) end + end +end + +function AutoLoot:Initialize() + addon.Modules.Events:Register("LOOT_OPENED", OnLootOpened, "AutoLoot") + ApplyClientSetting() +end + +-- Called by the settings checkbox so the client toggle flips immediately. +function AutoLoot:Apply() + ApplyClientSetting() +end diff --git a/Core/ClamOpener.lua b/Core/ClamOpener.lua new file mode 100644 index 0000000..3c91de7 --- /dev/null +++ b/Core/ClamOpener.lua @@ -0,0 +1,155 @@ +-- Guda ClamOpener +-- Walks the player's bags and uses each clam in turn until none remain. +-- Triggered by /guda openclams. Stops on UI_ERROR_MESSAGE so a full inventory +-- (or any other error from UseContainerItem) cleanly aborts the run. + +local addon = Guda +local L = Guda_L + +local ClamOpener = {} +addon.Modules.ClamOpener = ClamOpener + +-- Hardcoded vanilla clam item IDs +local CLAM_IDS = { + [5523] = true, -- Small Barnacled Clam + [5524] = true, -- Thick-shelled Clam + [7973] = true, -- Big-mouth Clam + [15874] = true, -- Soft-shelled Clam +} + +local OPEN_DELAY = 0.3 -- seconds between opens; lets loot/bag updates settle +local running = false +local silentRun = false + +-- Find the next clam in player bags. Returns bagID, slotID, itemLink or nil. +local function FindNextClam() + for bagID = 0, 4 do + local numSlots = GetContainerNumSlots(bagID) + if numSlots and numSlots > 0 then + for slotID = 1, numSlots do + local link = GetContainerItemLink(bagID, slotID) + if link then + local _, _, idStr = string.find(link, "item:(%d+)") + local itemID = idStr and tonumber(idStr) + if itemID and CLAM_IDS[itemID] then + return bagID, slotID + end + end + end + end + end + return nil +end + +local function StopRun(reason) + if not running then return end + running = false + -- Don't unregister BAG_UPDATE — it's the auto-trigger. Only drop the + -- per-run UI_ERROR_MESSAGE listener. + addon.Modules.Events:UnregisterOwner("ClamOpener_Run") + if reason and not silentRun then + addon:Print(reason) + end + silentRun = false +end + +local function OpenNext() + if not running then return end + + if CursorHasItem() then + -- Cursor is busy with something else; try again shortly. + Guda_ScheduleTimer(OPEN_DELAY, OpenNext) + return + end + + local bagID, slotID = FindNextClam() + if not bagID then + StopRun(L["No more clams to open."]) + return + end + + UseContainerItem(bagID, slotID) + Guda_ScheduleTimer(OPEN_DELAY, OpenNext) +end + +-- Stop on UI_ERROR_MESSAGE (e.g. inventory full). UseContainerItem fires this +-- the same frame on failure, so any error after we start counts as an abort. +local function OnUIError() + if not running then return end + local msg = arg1 + StopRun(string.format(L["Clam opener stopped: %s"], tostring(msg or "error"))) +end + +-- silent: true to suppress chat messages (used by auto-trigger). +function ClamOpener:Open(silent) + if running then + if not silent then + addon:Print(L["Clam opener is already running."]) + end + return + end + + -- Quick sanity check so we don't print "stopped" without ever starting. + if not FindNextClam() then + if not silent then + addon:Print(L["No clams found in your bags."]) + end + return + end + + running = true + silentRun = silent and true or false + addon.Modules.Events:Register("UI_ERROR_MESSAGE", OnUIError, "ClamOpener_Run") + if not silent then + addon:Print(L["Opening clams..."]) + end + OpenNext() +end + +-- Returns true if any blocking window (loot/mail/trade/merchant/bank/auction) +-- is currently open. We don't want to UseContainerItem while these are active — +-- it can race the open window or get queued and lost. +local function IsBlockingWindowOpen() + local frames = { + "LootFrame", "MailFrame", "TradeFrame", "MerchantFrame", + "BankFrame", "AuctionFrame", + -- Guda's own bank/mail frames too + "Guda_BankFrame", "Guda_MailboxFrame", + } + for _, name in ipairs(frames) do + local f = getglobal(name) + if f and f.IsShown and f:IsShown() then + return true + end + end + return false +end + +-- Initialize auto-open. Triggers: +-- * BAG_UPDATE — catches clams that arrived without a blocking window. +-- * LOOT_CLOSED — the common case: clam looted from a corpse. +-- * MAIL_CLOSED — clam received via mail. +-- * TRADE_CLOSED — clam received via trade. +-- * BANKFRAME_CLOSED — clam withdrawn from bank. +-- Each trigger defers ~0.15s and then attempts a silent Open(); the running +-- guard, the FindNextClam check, and the IsBlockingWindowOpen guard absorb +-- the noise of multiple events firing in quick succession. +function ClamOpener:Initialize() + local function tryAutoOpen() + if running then return end + if not (Guda.Modules.DB and Guda.Modules.DB:GetSetting("autoOpenClams")) then + return + end + Guda_ScheduleTimer(0.15, function() + if running then return end + if IsBlockingWindowOpen() then return end + ClamOpener:Open(true) + end) + end + + addon.Modules.Events:Register("BAG_UPDATE", tryAutoOpen, "ClamOpener") + addon.Modules.Events:Register("LOOT_CLOSED", tryAutoOpen, "ClamOpener") + addon.Modules.Events:Register("MAIL_CLOSED", tryAutoOpen, "ClamOpener") + addon.Modules.Events:Register("TRADE_CLOSED", tryAutoOpen, "ClamOpener") + addon.Modules.Events:Register("BANKFRAME_CLOSED", tryAutoOpen, "ClamOpener") +end diff --git a/Core/Database.lua b/Core/Database.lua index a37b49f..b5de537 100644 --- a/Core/Database.lua +++ b/Core/Database.lua @@ -147,6 +147,12 @@ function DB:Initialize() if Guda_CharDB.settings.autoLockSetItems == nil then Guda_CharDB.settings.autoLockSetItems = true end + if Guda_CharDB.settings.autoLoot == nil then + Guda_CharDB.settings.autoLoot = false + end + if Guda_CharDB.settings.autoOpenClams == nil then + Guda_CharDB.settings.autoOpenClams = false + end -- Auto-detect pfUI on first load (theme not yet set) if Guda_CharDB.settings.theme == nil then diff --git a/Core/Main.lua b/Core/Main.lua index a458b9a..21b1a85 100644 --- a/Core/Main.lua +++ b/Core/Main.lua @@ -82,6 +82,16 @@ function Main:Initialize() addon:Error("Tooltip module not loaded!") end + -- Initialize auto-loot handler (LOOT_OPENED listener) + if addon.Modules.AutoLoot and addon.Modules.AutoLoot.Initialize then + addon.Modules.AutoLoot:Initialize() + end + + -- Initialize clam opener (registers BAG_UPDATE for auto-open) + if addon.Modules.ClamOpener and addon.Modules.ClamOpener.Initialize then + addon.Modules.ClamOpener:Initialize() + end + -- Setup slash commands Main:SetupSlashCommands() @@ -133,6 +143,10 @@ function Main:SetupSlashCommands() -- Sort bank addon.Modules.SortEngine:SortBank() + elseif msg == "openclams" or msg == "clams" then + -- Open all clams in bags + addon.Modules.ClamOpener:Open() + elseif msg == "debug" then -- Toggle debug addon.DEBUG = not addon.DEBUG @@ -255,6 +269,7 @@ function Main:SetupSlashCommands() addon:Print(L["/guda settings - Open settings"]) addon:Print(L["/guda sort - Sort bags"]) addon:Print(L["/guda sortbank - Sort bank"]) + addon:Print(L["/guda openclams - Open all clams in bags"]) addon:Print(L["/guda track - Toggle item tracking"]) addon:Print(L["/guda debug - Toggle debug mode"]) addon:Print(L["/guda debugsort - Toggle sort debug output"]) diff --git a/Guda.toc b/Guda.toc index 0fc37b0..21a61b4 100644 --- a/Guda.toc +++ b/Guda.toc @@ -21,6 +21,8 @@ Core\Utils.lua Core\ItemDetection.lua Core\CategoryManager.lua Core\Tooltip.lua +Core\ClamOpener.lua +Core\AutoLoot.lua Data\BagScanner.lua Data\BankScanner.lua diff --git a/Localization.lua b/Localization.lua index 1b08a91..13efd07 100644 --- a/Localization.lua +++ b/Localization.lua @@ -58,6 +58,17 @@ L["/guda mail - Toggle mailbox"] = "/guda mail - Toggle mailbox" L["/guda settings - Open settings"] = "/guda settings - Open settings" L["/guda sort - Sort bags"] = "/guda sort - Sort bags" L["/guda sortbank - Sort bank"] = "/guda sortbank - Sort bank" +L["/guda openclams - Open all clams in bags"] = "/guda openclams - Open all clams in bags" +L["Auto Loot"] = "Auto Loot" +L["Automatically loot all items when looting a corpse or container."] = "Automatically loot all items when looting a corpse or container." +L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] = "Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option, or apply the launcher's 'Always auto-loot' tweak (which makes the client autoloot independently of this addon)." +L["Auto Open Clams"] = "Auto Open Clams" +L["Automatically open clams in your bags when you loot one."] = "Automatically open clams in your bags when you loot one." +L["Opening clams..."] = "Opening clams..." +L["No clams found in your bags."] = "No clams found in your bags." +L["No more clams to open."] = "No more clams to open." +L["Clam opener is already running."] = "Clam opener is already running." +L["Clam opener stopped: %s"] = "Clam opener stopped: %s" L["/guda track - Toggle item tracking"] = "/guda track - Toggle item tracking" L["/guda debug - Toggle debug mode"] = "/guda debug - Toggle debug mode" L["/guda debugsort - Toggle sort debug output"] = "/guda debugsort - Toggle sort debug output" @@ -343,6 +354,18 @@ local locale = GetLocale and GetLocale() or "enUS" if locale == "zhCN" then -- Chinese (Simplified) + L["Auto Loot"] = "自动拾取" + L["Automatically loot all items when looting a corpse or container."] = "拾取尸体或容器时自动拾取所有物品。" + L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] = "自动拾取需要 SuperWoW 客户端模组。安装 SuperWoW 以启用此选项,或应用启动器的 'Always auto-loot' 调整(客户端将独立于此插件自动拾取)。" + L["Auto Open Clams"] = "自动打开蚌壳" + L["Automatically open clams in your bags when you loot one."] = "拾取蚌壳后自动打开背包中的蚌壳。" + L["/guda openclams - Open all clams in bags"] = "/guda openclams - 打开背包中所有蚌壳" + L["Opening clams..."] = "正在打开蚌壳..." + L["No clams found in your bags."] = "背包中没有找到蚌壳。" + L["No more clams to open."] = "没有更多蚌壳可打开。" + L["Clam opener is already running."] = "蚌壳打开器已在运行。" + L["Clam opener stopped: %s"] = "蚌壳打开器已停止:%s" + -- Init / lifecycle L["Initializing..."] = "正在初始化..." L["Initializing UI..."] = "正在初始化界面..." @@ -595,6 +618,18 @@ if locale == "zhCN" then elseif locale == "esES" then -- Spanish + L["Auto Loot"] = "Saqueo automático" + L["Automatically loot all items when looting a corpse or container."] = "Saquea automáticamente todos los objetos al saquear un cadáver o contenedor." + L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] = "El saqueo automático requiere la modificación de cliente SuperWoW. Instala SuperWoW para habilitar esta opción, o aplica el ajuste 'Always auto-loot' del lanzador (el cliente saqueará automáticamente, independientemente de este addon)." + L["Auto Open Clams"] = "Abrir almejas automáticamente" + L["Automatically open clams in your bags when you loot one."] = "Abre automáticamente las almejas de tus bolsas cuando saqueas una." + L["/guda openclams - Open all clams in bags"] = "/guda openclams - Abrir todas las almejas de las bolsas" + L["Opening clams..."] = "Abriendo almejas..." + L["No clams found in your bags."] = "No se encontraron almejas en tus bolsas." + L["No more clams to open."] = "No hay más almejas para abrir." + L["Clam opener is already running."] = "El abridor de almejas ya está en ejecución." + L["Clam opener stopped: %s"] = "Abridor de almejas detenido: %s" + L["Initializing..."] = "Inicializando..." L["Initializing UI..."] = "Inicializando interfaz..." L["Ready! Type /guda to open bags"] = "¡Listo! Escribe /guda para abrir las bolsas" @@ -832,6 +867,18 @@ elseif locale == "esES" then elseif locale == "ptBR" then -- Portuguese (Brazilian) + L["Auto Loot"] = "Saque automático" + L["Automatically loot all items when looting a corpse or container."] = "Saqueia automaticamente todos os itens ao saquear um cadáver ou recipiente." + L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] = "O saque automático requer a modificação de cliente SuperWoW. Instale o SuperWoW para habilitar esta opção, ou aplique o ajuste 'Always auto-loot' do lançador (o cliente saqueará automaticamente, independentemente deste addon)." + L["Auto Open Clams"] = "Abrir mariscos automaticamente" + L["Automatically open clams in your bags when you loot one."] = "Abre automaticamente os mariscos nas suas bolsas quando você saqueia um." + L["/guda openclams - Open all clams in bags"] = "/guda openclams - Abrir todos os mariscos nas bolsas" + L["Opening clams..."] = "Abrindo mariscos..." + L["No clams found in your bags."] = "Nenhum marisco encontrado nas suas bolsas." + L["No more clams to open."] = "Não há mais mariscos para abrir." + L["Clam opener is already running."] = "O abridor de mariscos já está em execução." + L["Clam opener stopped: %s"] = "Abridor de mariscos parado: %s" + L["Initializing..."] = "Inicializando..." L["Initializing UI..."] = "Inicializando interface..." L["Ready! Type /guda to open bags"] = "Pronto! Digite /guda para abrir as bolsas" @@ -1069,6 +1116,18 @@ elseif locale == "ptBR" then elseif locale == "deDE" then -- German + L["Auto Loot"] = "Automatisches Plündern" + L["Automatically loot all items when looting a corpse or container."] = "Plündere automatisch alle Gegenstände von Leichen und Behältern." + L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] = "Automatisches Plündern erfordert die SuperWoW-Clienterweiterung. Installiere SuperWoW, um diese Option zu aktivieren, oder wende den Launcher-Tweak 'Always auto-loot' an (dann plündert der Client unabhängig von diesem Addon automatisch)." + L["Auto Open Clams"] = "Muscheln automatisch öffnen" + L["Automatically open clams in your bags when you loot one."] = "Öffnet automatisch Muscheln in deinen Taschen, wenn du eine erbeutest." + L["/guda openclams - Open all clams in bags"] = "/guda openclams - Alle Muscheln in den Taschen öffnen" + L["Opening clams..."] = "Öffne Muscheln..." + L["No clams found in your bags."] = "Keine Muscheln in deinen Taschen gefunden." + L["No more clams to open."] = "Keine weiteren Muscheln zu öffnen." + L["Clam opener is already running."] = "Der Muschelöffner läuft bereits." + L["Clam opener stopped: %s"] = "Muschelöffner gestoppt: %s" + L["Initializing..."] = "Initialisiere..." L["Initializing UI..."] = "Initialisiere Oberfläche..." L["Ready! Type /guda to open bags"] = "Bereit! Tippe /guda um die Taschen zu öffnen" @@ -1306,6 +1365,18 @@ elseif locale == "deDE" then elseif locale == "ruRU" then -- Russian + L["Auto Loot"] = "Автосбор" + L["Automatically loot all items when looting a corpse or container."] = "Автоматически собирать все предметы при обыске трупов и контейнеров." + L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] = "Автосбор требует клиентскую модификацию SuperWoW. Установите SuperWoW, чтобы включить эту опцию, или примените твик лаунчера 'Always auto-loot' (тогда клиент будет автоматически собирать добычу независимо от этого аддона)." + L["Auto Open Clams"] = "Автооткрытие моллюсков" + L["Automatically open clams in your bags when you loot one."] = "Автоматически открывать моллюсков в сумках, как только один из них получен." + L["/guda openclams - Open all clams in bags"] = "/guda openclams - Открыть всех моллюсков в сумках" + L["Opening clams..."] = "Открытие моллюсков..." + L["No clams found in your bags."] = "В ваших сумках нет моллюсков." + L["No more clams to open."] = "Больше моллюсков для открытия нет." + L["Clam opener is already running."] = "Открывалка моллюсков уже работает." + L["Clam opener stopped: %s"] = "Открывалка моллюсков остановлена: %s" + L["Initializing..."] = "Инициализация..." L["Initializing UI..."] = "Инициализация интерфейса..." L["Ready! Type /guda to open bags"] = "Готово! Введите /guda, чтобы открыть сумки" diff --git a/UI/SettingsPopup.lua b/UI/SettingsPopup.lua index 3ba7339..d86baf2 100644 --- a/UI/SettingsPopup.lua +++ b/UI/SettingsPopup.lua @@ -341,6 +341,20 @@ function Guda_SettingsPopup_OnShow(self) whiteItemsJunkCheckbox:SetChecked(whiteItemsJunk and 1 or 0) end + -- Auto Loot checkbox + local autoLootCheckbox = getglobal("Guda_SettingsPopup_AutoLootCheckbox") + if autoLootCheckbox then + local autoLoot = Guda.Modules.DB:GetSetting("autoLoot") and true or false + autoLootCheckbox:SetChecked(autoLoot and 1 or 0) + end + + -- Auto Open Clams checkbox + local autoOpenClamsCheckbox = getglobal("Guda_SettingsPopup_AutoOpenClamsCheckbox") + if autoOpenClamsCheckbox then + local autoOpenClams = Guda.Modules.DB:GetSetting("autoOpenClams") and true or false + autoOpenClamsCheckbox:SetChecked(autoOpenClams and 1 or 0) + end + if bagViewDropdown then UIDropDownMenu_SetSelectedValue(bagViewDropdown, bagViewType) UIDropDownMenu_SetText(bagViewType == "single" and "Single" or "Category", bagViewDropdown) @@ -1425,6 +1439,79 @@ function Guda_SettingsPopup_ShowCategoryCountCheckbox_OnClick(self) end end +-- Auto Loot Checkbox OnLoad +function Guda_SettingsPopup_AutoLootCheckbox_OnLoad(self) + local text = getglobal(self:GetName().."Text") + if text then + text:SetText(Guda_L["Auto Loot"]) + local font, _, flags = text:GetFont() + if font then text:SetFont(font, 13, flags) end + end + + -- TurtleWoW requires SuperWoW for any addon-driven autoloot to work + -- (both SetAutoloot and LootSlot are gated). If it's not present, disable + -- the checkbox and explain why in the tooltip. + local hasSuperWoW = SetAutoloot ~= nil + if hasSuperWoW then + self.tooltipText = Guda_L["Automatically loot all items when looting a corpse or container."] + self:Enable() + if text then text:SetTextColor(1, 1, 1) end + else + self.tooltipText = Guda_L["Auto Loot requires the SuperWoW client mod. Install SuperWoW to enable this option."] + self:Disable() + if text then text:SetTextColor(0.5, 0.5, 0.5) end + end + + local enabled = false + if Guda and Guda.Modules and Guda.Modules.DB then + enabled = Guda.Modules.DB:GetSetting("autoLoot") and true or false + end + self:SetChecked(enabled and 1 or 0) +end + +-- Auto Loot Checkbox OnClick +function Guda_SettingsPopup_AutoLootCheckbox_OnClick(self) + local isChecked = self:GetChecked() == 1 + if Guda and Guda.Modules and Guda.Modules.DB then + Guda.Modules.DB:SetSetting("autoLoot", isChecked) + end + -- Apply immediately to the client (SuperWoW's SetAutoloot or vanilla + -- SetAutoLootDefault) so the toggle takes effect on the next loot. + if Guda.Modules.AutoLoot and Guda.Modules.AutoLoot.Apply then + Guda.Modules.AutoLoot:Apply() + end +end + +-- Auto Open Clams Checkbox OnLoad +function Guda_SettingsPopup_AutoOpenClamsCheckbox_OnLoad(self) + local text = getglobal(self:GetName().."Text") + if text then + text:SetText(Guda_L["Auto Open Clams"]) + local font, _, flags = text:GetFont() + if font then text:SetFont(font, 13, flags) end + end + + self.tooltipText = Guda_L["Automatically open clams in your bags when you loot one."] + + local enabled = false + if Guda and Guda.Modules and Guda.Modules.DB then + enabled = Guda.Modules.DB:GetSetting("autoOpenClams") and true or false + end + self:SetChecked(enabled and 1 or 0) +end + +-- Auto Open Clams Checkbox OnClick +function Guda_SettingsPopup_AutoOpenClamsCheckbox_OnClick(self) + local isChecked = self:GetChecked() == 1 + if Guda and Guda.Modules and Guda.Modules.DB then + Guda.Modules.DB:SetSetting("autoOpenClams", isChecked) + end + -- If enabling, kick off an immediate run for any clams already in bags. + if isChecked and Guda.Modules.ClamOpener then + Guda.Modules.ClamOpener:Open(true) + end +end + -- Auto Vendor Junk Checkbox OnLoad function Guda_SettingsPopup_AutoVendorJunkCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") diff --git a/UI/SettingsPopup.xml b/UI/SettingsPopup.xml index 7b34cd4..b5ba6fb 100644 --- a/UI/SettingsPopup.xml +++ b/UI/SettingsPopup.xml @@ -342,6 +342,32 @@ Guda_SettingsPopup_AutoVendorJunkCheckbox_OnClick(this) + + + + + + + + + + Guda_SettingsPopup_AutoLootCheckbox_OnLoad(this) + Guda_SettingsPopup_AutoLootCheckbox_OnClick(this) + + + + + + + + + + + + Guda_SettingsPopup_AutoOpenClamsCheckbox_OnLoad(this) + Guda_SettingsPopup_AutoOpenClamsCheckbox_OnClick(this) + +