Add an options window with an on/off switch

/unitscan now opens an options window (no minimap icon) with a button
that turns scanning on or off and checkboxes for the alert sound, the
screen flash and the built-in zone list. Your own targets can be added
or removed from the window. Settings are saved per character in
unitscan_settings.

/unitscan on, /unitscan off and /unitscan list do the same from chat;
/unitscan <name> still adds or removes a target.
This commit is contained in:
2026-10-27 00:08:05 +00:00
parent 0a1002827b
commit 919534f3d8
3 changed files with 294 additions and 26 deletions
+10 -4
View File
@@ -5,10 +5,12 @@
## Description
This fork extends [unitscan-turtle](https://github.com/GryllsAddons/unitscan-turtle) by provinding a prepopulated list of dangerous elite mobs, rares, and other units. This version is especially useful if you're playing Turtle WoW's hardcore mode.
## Download
If using the launcher use this url: https://github.com/RetroCro/unitscan-turtle-hc.git
This fork adds an options window, opened with /unitscan, with an on/off switch for scanning and switches for the alert sound, the screen flash and the built-in zone list. Original addon: https://github.com/RetroCro/unitscan-turtle-hc
Download: [https://github.com/RetroCro/unitscan-turtle-hc/archive/refs/heads/master.zip](https://github.com/RetroCro/unitscan-turtle-hc/archive/refs/heads/master.zip)
## Download
If using the launcher use this url: https://git.octowow.st/git/shaga/unitscan-turtle-hc.git
Download: [https://git.octowow.st/git/shaga/unitscan-turtle-hc/archive/master.zip](https://git.octowow.st/git/shaga/unitscan-turtle-hc/archive/master.zip)
Copy folder to your Turtle WoW Addons folder ex: twmoa_1171\Interface\AddOns\unitscan-turtle-hc
@@ -64,10 +66,14 @@ The list of units can be found in [zone targets.lua](https://raw.githubuserconte
**You can move the unitscan frame by holding CTRL+SHIFT+LEFT CLICK dragging.**
**/unitscan** *lists the active scan targets*
**/unitscan** *opens the options window*
**/unitscan on**, **/unitscan off** *turns scanning on or off*
**/unitscan list** *lists the active scan targets in chat*
**/unitscan name** *adds/removes **name** to/from the active scan targets*
**/unitscantarget** *targets the most recently found target*
The options window has the on/off switch, switches for the alert sound, the screen flash and the built-in zone list, and a box to add or remove your own targets. The options are saved per character.
You can add custom targets to find players or targets not included in the zone targets list by using the command /unitscan *name*.
Please Note: Targets added using /unitscan *name* will be removed from active scan targets after they are found. For a permanenet solution, edit [zone targets.lua](https://raw.githubusercontent.com/RetroCro/unitscan-turtle-hc/refs/heads/master/zonetargets.lua) and add a line entry for that unit.
+3 -2
View File
@@ -1,8 +1,9 @@
## Interface: 11200
## Author: RetroCro
## Title: unitscan|cff00ff98Turtle-HC
## Version: 1.0.5
## Notes: Unit scanner with flashy alert
## Version: 1.1.0
## Notes: Unit scanner with flashy alert. /unitscan opens the options.
## SavedVariables: unitscan_targets
## SavedVariablesPerCharacter: unitscan_settings
unitscan.lua
zonetargets.lua
+281 -20
View File
@@ -2,8 +2,12 @@ local unitscan = CreateFrame'Frame'
unitscan:SetScript('OnUpdate', function() unitscan.UPDATE() end)
unitscan:SetScript('OnEvent', function()
if event == "VARIABLES_LOADED" then
unitscan.load_settings()
unitscan.LOAD()
unitscan.scan = true
if not unitscan_settings.enabled then
unitscan.print('scanning is off, type /unitscan to turn it on')
end
elseif event == "PLAYER_REGEN_DISABLED" then
-- in combat
-- disable scanning
@@ -29,6 +33,7 @@ unitscan:SetScript('OnEvent', function()
else
unitscan.load_zonetargets()
end
unitscan.config_refresh()
end)
unitscan:RegisterEvent'VARIABLES_LOADED'
@@ -47,6 +52,24 @@ local CHECK_INTERVAL = 1
unitscan_targets = {}
local DEFAULTS = {
enabled = true, -- scanning on/off
sound = true, -- alert sound
flash = true, -- red screen flash
zonetargets = true, -- built-in list from zonetargets.lua
}
function unitscan.load_settings()
if type(unitscan_settings) ~= 'table' then
unitscan_settings = {}
end
for key, value in pairs(DEFAULTS) do
if unitscan_settings[key] == nil then
unitscan_settings[key] = value
end
end
end
do
local last_played
@@ -62,6 +85,17 @@ do
end
end
function unitscan.alert()
if unitscan_settings.sound then
unitscan.play_sound()
end
if unitscan_settings.flash then
unitscan.flash.animation:Play()
end
unitscan.button:set_target()
unitscan.config_refresh()
end
function unitscan.load_zonetargets()
unitscan_zone_targets()
end
@@ -92,20 +126,18 @@ do
if name == unitscan.target(name) then
unitscan.foundTarget = name
unitscan.toggle_target(name)
unitscan.play_sound()
unitscan.flash.animation:Play()
unitscan.button:set_target()
unitscan.alert()
end
unitscan.restoreTarget()
end
if not unitscan_settings.zonetargets then return end
for name, _ in unitscan_zonetargets do
if strupper(name) == unitscan.target(name) then
unitscan.foundTarget = name
unitscan.foundTarget = name
unitscan.toggle_zonetarget(name)
unitscan.play_sound()
unitscan.flash.animation:Play()
unitscan.button:set_target()
unitscan.alert()
end
unitscan.restoreTarget()
end
@@ -174,8 +206,13 @@ function unitscan.LOAD()
end
self:Show()
end
function flash.animation:Stop()
self.t0 = nil
self:Hide()
flash:SetAlpha(0)
end
end
local button = CreateFrame("Button", "unitscan_button", UIParent)
button:Hide()
unitscan.button = button
@@ -376,7 +413,8 @@ end
do
unitscan.last_check = GetTime()
function unitscan.UPDATE()
if unitscan.scan then
-- unitscan.button exists once LOAD has run, after the settings are loaded
if unitscan.scan and unitscan.button and unitscan_settings.enabled then
if GetTime() - unitscan.last_check >= CHECK_INTERVAL then
unitscan.last_check = GetTime()
if (unitscan.reloadtimer and (unitscan.last_check >= unitscan.reloadtimer)) then
@@ -433,23 +471,246 @@ function unitscan.toggle_zonetarget(name)
unitscan.reloadtimer = GetTime() + 90
end
end
function unitscan.print_targets()
unitscan.print("Added targets:")
for _, key in ipairs(unitscan.sorted_targets()) do
unitscan.print(key)
end
-- zone targets
unitscan.print("Zone targets:")
for _, key in ipairs(unitscan.sorted_zonetargets()) do
unitscan.print(key)
end
end
function unitscan.set_enabled(enabled)
unitscan_settings.enabled = enabled
if enabled then
unitscan.print('scanning on')
else
-- dismiss an alert that is still showing
unitscan.button:Hide()
unitscan.flash.animation:Stop()
unitscan.print('scanning off')
end
unitscan.config_refresh()
end
function unitscan.count_zonetargets()
local count = 0
for _ in pairs(unitscan_zonetargets or {}) do
count = count + 1
end
return count
end
function unitscan.config_create()
local frame = CreateFrame('Frame', 'unitscan_config', UIParent)
unitscan.config = frame
frame:Hide()
frame:SetWidth(320)
frame:SetHeight(328)
frame:SetPoint('CENTER', UIParent, 0, 80)
frame:SetFrameStrata'DIALOG'
frame:SetMovable(true)
frame:SetClampedToScreen(true)
frame:EnableMouse(true)
frame:RegisterForDrag'LeftButton'
frame:SetScript('OnDragStart', function() this:StartMoving() end)
frame:SetScript('OnDragStop', function() this:StopMovingOrSizing() end)
frame:SetScript('OnShow', function() unitscan.config_refresh() end)
frame:SetBackdrop{
bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]],
edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]],
tile = true,
tileSize = 32,
edgeSize = 32,
insets = {left = 11, right = 12, top = 12, bottom = 11},
}
-- close with Escape
tinsert(UISpecialFrames, 'unitscan_config')
do
local header = frame:CreateTexture(nil, 'ARTWORK')
header:SetTexture[[Interface\DialogFrame\UI-DialogBox-Header]]
header:SetWidth(256)
header:SetHeight(64)
header:SetPoint('TOP', 0, 12)
local title = frame:CreateFontString(nil, 'OVERLAY', 'GameFontNormal')
title:SetPoint('TOP', header, 0, -14)
title:SetText'unitscan'
local close = CreateFrame('Button', nil, frame, 'UIPanelCloseButton')
close:SetPoint('TOPRIGHT', -6, -6)
end
do
local status = frame:CreateFontString(nil, 'OVERLAY', 'GameFontHighlight')
frame.status = status
status:SetPoint('TOP', 0, -32)
local toggle = CreateFrame('Button', 'unitscan_config_toggle', frame, 'UIPanelButtonTemplate')
frame.toggle = toggle
toggle:SetWidth(160)
toggle:SetHeight(24)
toggle:SetPoint('TOP', 0, -52)
toggle:SetScript('OnClick', function()
unitscan.set_enabled(not unitscan_settings.enabled)
end)
end
do
local function checkbox(key, label, y)
local check = CreateFrame('CheckButton', 'unitscan_config_' .. key, frame, 'UICheckButtonTemplate')
frame[key] = check
check:SetWidth(26)
check:SetHeight(26)
check:SetPoint('TOPLEFT', 20, y)
getglobal(check:GetName() .. 'Text'):SetText(label)
check:SetScript('OnClick', function()
if this:GetChecked() then
PlaySound'igMainMenuOptionCheckBoxOn'
else
PlaySound'igMainMenuOptionCheckBoxOff'
end
unitscan_settings[key] = this:GetChecked() and true or false
unitscan.config_refresh()
end)
end
checkbox('sound', 'Play the alert sound', -86)
checkbox('flash', 'Flash the screen', -112)
checkbox('zonetargets', 'Scan for the zone list (rares and elites)', -138)
local zone = frame:CreateFontString(nil, 'OVERLAY', 'GameFontHighlightSmall')
frame.zone = zone
zone:SetPoint('TOPLEFT', 48, -168)
zone:SetWidth(250)
zone:SetJustifyH'LEFT'
end
do
local label = frame:CreateFontString(nil, 'OVERLAY', 'GameFontNormal')
label:SetPoint('TOPLEFT', 22, -194)
label:SetText'Your targets'
local list = CreateFrame('Button', 'unitscan_config_list', frame, 'UIPanelButtonTemplate')
list:SetWidth(90)
list:SetHeight(20)
list:SetPoint('TOPRIGHT', -22, -190)
list:SetText'List in chat'
list:SetScript('OnClick', function() unitscan.print_targets() end)
local input = CreateFrame('EditBox', 'unitscan_config_input', frame, 'InputBoxTemplate')
frame.input = input
input:SetWidth(170)
input:SetHeight(20)
input:SetPoint('TOPLEFT', 30, -216)
input:SetAutoFocus(false)
input:SetMaxLetters(64)
input:SetScript('OnEnterPressed', function() unitscan.config_add() end)
local add = CreateFrame('Button', 'unitscan_config_add', frame, 'UIPanelButtonTemplate')
add:SetWidth(96)
add:SetHeight(22)
add:SetPoint('LEFT', input, 'RIGHT', 6, 0)
add:SetText'Add / Remove'
add:SetScript('OnClick', function() unitscan.config_add() end)
local targets = frame:CreateFontString(nil, 'OVERLAY', 'GameFontHighlightSmall')
frame.targets = targets
targets:SetPoint('TOPLEFT', 22, -244)
targets:SetWidth(276)
targets:SetHeight(36)
targets:SetJustifyH'LEFT'
targets:SetJustifyV'TOP'
end
do
local note = frame:CreateFontString(nil, 'OVERLAY', 'GameFontDisableSmall')
note:SetPoint('BOTTOM', 0, 32)
note:SetText'A target you add is removed once it is found.'
local help = frame:CreateFontString(nil, 'OVERLAY', 'GameFontDisableSmall')
help:SetPoint('BOTTOM', 0, 18)
help:SetText'Drag to move. /unitscan on, off, list, <name>'
end
end
function unitscan.config_toggle()
if not unitscan.config then
unitscan.config_create()
end
if unitscan.config:IsShown() then
unitscan.config:Hide()
else
unitscan.config:Show()
end
end
function unitscan.config_add()
local input = unitscan.config.input
local _, _, name = strfind(input:GetText(), '^%s*(.-)%s*$')
if name ~= '' then
unitscan.toggle_target(name)
end
input:SetText''
input:ClearFocus()
unitscan.config_refresh()
end
function unitscan.config_refresh()
local frame = unitscan.config
if not (frame and frame:IsShown()) then return end
if not unitscan_settings.enabled then
frame.status:SetText'Scanning: |cffff2020off|r'
frame.toggle:SetText'Turn scanning on'
else
if unitscan.scan then
frame.status:SetText'Scanning: |cff20ff20on|r'
else
frame.status:SetText'Scanning: |cffffd100paused in combat|r'
end
frame.toggle:SetText'Turn scanning off'
end
frame.sound:SetChecked(unitscan_settings.sound and true or nil)
frame.flash:SetChecked(unitscan_settings.flash and true or nil)
frame.zonetargets:SetChecked(unitscan_settings.zonetargets and true or nil)
frame.zone:SetText(GetZoneText() .. ': ' .. unitscan.count_zonetargets() .. ' on the zone list')
if unitscan_settings.zonetargets then
frame.zone:SetTextColor(1, 1, 1)
else
frame.zone:SetTextColor(.5, .5, .5)
end
local targets = unitscan.sorted_targets()
if targets[1] then
frame.targets:SetText(table.concat(targets, ', '))
else
frame.targets:SetText'|cff808080none|r'
end
end
SLASH_UNITSCAN1 = '/unitscan'
function SlashCmdList.UNITSCAN(parameter)
local _, _, name = strfind(parameter, '^%s*(.-)%s*$')
local command = strlower(name)
if name == '' then
unitscan.print("Added targets:")
for _, key in ipairs(unitscan.sorted_targets()) do
unitscan.print(key)
end
-- zone targets
unitscan.print("Zone targets:")
for _, key in ipairs(unitscan.sorted_zonetargets()) do
unitscan.print(key)
end
unitscan.config_toggle()
elseif command == 'on' then
unitscan.set_enabled(true)
elseif command == 'off' then
unitscan.set_enabled(false)
elseif command == 'list' then
unitscan.print_targets()
else
unitscan.toggle_target(name)
unitscan.config_refresh()
end
end