initial commit

This commit is contained in:
Torsten Brendgen
2026-04-10 21:30:31 +02:00
commit fc5a8aa361
108 changed files with 40568 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Button name="HMGTMapOverlayPinTemplate" mixin="HMGTMapOverlayPinMixin" virtual="true">
<Size x="16" y="16" />
<Scripts>
<OnLoad method="OnLoad" />
<OnEnter method="OnMouseEnter" />
<OnLeave method="OnMouseLeave" />
<OnClick method="OnClick" />
</Scripts>
</Button>
</Ui>

View File

@@ -0,0 +1,37 @@
local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
local MEDIA_PATH = "Interface\\AddOns\\HailMaryGuildTools\\Modules\\MapOverlay\\Media\\"
local BLIP_TEXTURE = "Interface\\Minimap\\ObjectIconsAtlas"
-- Curated list of allowed Map Overlay icons.
-- Add, remove, or reorder entries here without touching the runtime module.
-- Supported fields per icon:
-- key, label, texture
-- atlasIndex + atlasSize = "32x32" (optionally textureWidth, textureHeight, atlasColumns)
-- or exact iconCoords = { left, right, top, bottom }
-- or exact cell = { col, row } for fixed 32x32 sheets
-- Note: 32x32 ObjectIconsAtlas minimap blips are rendered through Blizzard's
-- legacy ObjectIcons coordinate path internally, so the visible crop stays exact.
HMGT.MapOverlayIconConfig = {
defaultKey = "default",
icons = {
{ key = "default", label = "Default", texture = MEDIA_PATH .. "DefaultIcon.png" },
{ key = "auctionhouse", label = "Auction House", texture = BLIP_TEXTURE, atlasIndex = 16, atlasSize = "32x32", aliases = { "auction_house" } },
{ key = "bank", label = "Bank", texture = BLIP_TEXTURE, atlasIndex = 17, atlasSize = "32x32" },
{ key = "battlemaster", label = "Battlemaster", texture = BLIP_TEXTURE, atlasIndex = 18, atlasSize = "32x32" },
{ key = "classtrainer", label = "Class Trainer", texture = BLIP_TEXTURE, atlasIndex = 19, atlasSize = "32x32", aliases = { "class_trainer" } },
{ key = "fooddrink", label = "Food & Drink", texture = BLIP_TEXTURE, atlasIndex = 21, atlasSize = "32x32", aliases = { "food_drink" } },
{ key = "innkeeper", label = "Innkeeper", texture = BLIP_TEXTURE, atlasIndex = 22, atlasSize = "32x32" },
{ key = "poisons", label = "Poisons", texture = BLIP_TEXTURE, atlasIndex = 24, atlasSize = "32x32" },
{ key = "professiontrainer", label = "Profession Trainer", texture = BLIP_TEXTURE, atlasIndex = 25, atlasSize = "32x32", aliases = { "profession_trainer" } },
{ key = "reagents", label = "Reagents", texture = BLIP_TEXTURE, atlasIndex = 26, atlasSize = "32x32" },
{ key = "repairs", label = "Repairs", texture = BLIP_TEXTURE, atlasIndex = 27, atlasSize = "32x32" },
{ key = "blueblip", label = "Blue Blip", texture = BLIP_TEXTURE, atlasIndex = 0, atlasSize = "32x32", aliases = { "blip_blue" } },
{ key = "lightblueblip", label = "Light Blue Blip", texture = BLIP_TEXTURE, atlasIndex = 1, atlasSize = "32x32", aliases = { "blip_lightblue" } },
{ key = "redblip", label = "Red Blip", texture = BLIP_TEXTURE, atlasIndex = 2, atlasSize = "32x32", aliases = { "blip_red" } },
{ key = "yellowblip", label = "Yellow Blip", texture = BLIP_TEXTURE, atlasIndex = 3, atlasSize = "32x32", aliases = { "blip_yellow" } },
{ key = "greenblip", label = "Green Blip", texture = BLIP_TEXTURE, atlasIndex = 4, atlasSize = "32x32", aliases = { "blip_green" } },
},
}

View File

@@ -0,0 +1,554 @@
local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
local MapOverlay = HMGT.MapOverlay
if not MapOverlay then return end
if not HMGT_Config or not HMGT_Config.RegisterOptionsProvider then return end
local L = LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME, true) or {}
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0", true)
local MAX_POI_EDITOR_ROWS = 40
local function NotifyOptionsChanged()
if AceConfigRegistry and type(AceConfigRegistry.NotifyChange) == "function" then
AceConfigRegistry:NotifyChange(ADDON_NAME)
end
end
local function MapCategoryValues()
if HMGT.GetMapPOICategoryValues then
return HMGT:GetMapPOICategoryValues()
end
return { default = "Default" }
end
local function GetMapPOIs()
local profile = HMGT.db and HMGT.db.profile
if not profile then
return {}
end
profile.mapOverlay = profile.mapOverlay or {}
profile.mapOverlay.pois = profile.mapOverlay.pois or {}
return profile.mapOverlay.pois
end
local function HasPOIAt(index)
return GetMapPOIs()[index] ~= nil
end
local function HasAnyPOIs()
return GetMapPOIs()[1] ~= nil
end
local function GetPoiCount()
local count = 0
for _ in ipairs(GetMapPOIs()) do
count = count + 1
end
return count
end
local function EnsurePoiDraft(index)
local poi = GetMapPOIs()[index]
if not poi then
return nil
end
HMGT._mapPoiDrafts = HMGT._mapPoiDrafts or {}
local draft = HMGT._mapPoiDrafts[index]
if not draft then
draft = {
mapID = tostring(tonumber(poi.mapID) or ""),
x = string.format("%.2f", tonumber(poi.x) or 0),
y = string.format("%.2f", tonumber(poi.y) or 0),
label = tostring(poi.label or ""),
category = tostring(poi.category or "default"),
}
HMGT._mapPoiDrafts[index] = draft
end
return draft
end
local function BuildPoiEditorGroupArgs()
local function GetPoiTitle(index)
local poi = GetMapPOIs()[index]
if not poi then
return string.format("POI #%d", index)
end
return tostring(poi.label or ("POI " .. index))
end
local args = {
}
for index = 1, MAX_POI_EDITOR_ROWS do
local row = index
args["poi_" .. index] = {
type = "group",
name = function()
return GetPoiTitle(row)
end,
icon = function()
local poi = GetMapPOIs()[row]
if not poi or not MapOverlay.GetCategoryVisual then
return poi and poi.icon or nil
end
local texture = MapOverlay:GetCategoryVisual(poi.category)
return texture or poi.icon or nil
end,
iconCoords = function()
local poi = GetMapPOIs()[row]
if not poi or not MapOverlay.GetCategoryVisual then
return poi and poi.iconCoords or nil
end
local _, iconCoords = MapOverlay:GetCategoryVisual(poi.category)
return iconCoords or poi.iconCoords or nil
end,
order = 20 + index,
hidden = function()
return not HasPOIAt(row)
end,
args = {
details = {
type = "description",
order = 0.5,
width = "full",
name = function()
local poi = GetMapPOIs()[row]
if not poi then
return "POI not found."
end
local categoryValues = MapCategoryValues()
local category = tostring(poi.category or "default")
local categoryLabel = categoryValues[category] or category
return string.format(
"Map-ID: %d\nX: %.2f\nY: %.2f\nIcon: %s",
tonumber(poi.mapID) or 0,
tonumber(poi.x) or 0,
tonumber(poi.y) or 0,
tostring(categoryLabel)
)
end,
},
mapID = {
type = "input",
order = 1,
width = 0.7,
name = L["OPT_MAP_POI_MAPID"] or "Map ID",
get = function()
local draft = EnsurePoiDraft(row)
return (draft and draft.mapID) or ""
end,
set = function(_, value)
local draft = EnsurePoiDraft(row)
if draft then
draft.mapID = value
end
end,
},
x = {
type = "input",
order = 2,
width = 0.7,
name = L["OPT_MAP_POI_X"] or "X (0-100)",
get = function()
local draft = EnsurePoiDraft(row)
return (draft and draft.x) or ""
end,
set = function(_, value)
local draft = EnsurePoiDraft(row)
if draft then
draft.x = value
end
end,
},
y = {
type = "input",
order = 3,
width = 0.7,
name = L["OPT_MAP_POI_Y"] or "Y (0-100)",
get = function()
local draft = EnsurePoiDraft(row)
return (draft and draft.y) or ""
end,
set = function(_, value)
local draft = EnsurePoiDraft(row)
if draft then
draft.y = value
end
end,
},
label = {
type = "input",
order = 4,
width = "full",
name = L["OPT_MAP_POI_LABEL"] or "Label",
get = function()
local draft = EnsurePoiDraft(row)
return (draft and draft.label) or ""
end,
set = function(_, value)
local draft = EnsurePoiDraft(row)
if draft then
draft.label = value
end
end,
},
category = {
type = "select",
order = 5,
width = "full",
name = L["OPT_MAP_POI_CATEGORY"] or "Category",
values = function()
return MapCategoryValues()
end,
get = function()
local draft = EnsurePoiDraft(row)
return (draft and draft.category) or "default"
end,
set = function(_, value)
local draft = EnsurePoiDraft(row)
if draft then
draft.category = value
end
end,
},
waypoint = {
type = "execute",
order = 6,
width = "half",
name = "Waypoint",
func = function()
local poi = GetMapPOIs()[row]
if poi and MapOverlay.ToggleWaypointForPOI then
MapOverlay:ToggleWaypointForPOI(poi)
end
end,
},
update = {
type = "execute",
order = 7,
width = "half",
name = L["OPT_MAP_POI_UPDATE"] or "Update POI",
func = function()
local draft = EnsurePoiDraft(row)
if not draft then
return
end
local ok = HMGT.UpdateMapPOI and HMGT:UpdateMapPOI(row, draft.mapID, draft.x, draft.y, draft.label, nil, draft.category)
if ok then
if HMGT._mapPoiDrafts then
HMGT._mapPoiDrafts[row] = nil
end
HMGT:Print(L["OPT_MAP_POI_UPDATED"] or "HMGT: POI updated")
else
HMGT:Print(L["OPT_MAP_POI_UPDATE_FAILED"] or "HMGT: could not update POI")
end
NotifyOptionsChanged()
end,
},
delete = {
type = "execute",
order = 8,
width = "half",
name = L["OPT_MAP_POI_REMOVE"] or "Remove POI",
func = function()
local ok = HMGT.RemoveMapPOI and HMGT:RemoveMapPOI(row)
if ok then
HMGT._mapPoiDrafts = nil
HMGT:Print(L["OPT_MAP_POI_REMOVED"] or "HMGT: POI removed")
else
HMGT:Print(L["OPT_MAP_POI_REMOVE_FAILED"] or "HMGT: could not remove POI")
end
NotifyOptionsChanged()
end,
},
},
}
end
return args
end
function MapOverlay:GetOptionsGroup()
local group = {
type = "group",
name = L["OPT_MODULE_MAP_OVERLAY"] or "Map Overlay",
order = 30,
childGroups = "tree",
args = {
general = {
type = "group",
order = 1,
name = GENERAL or "General",
args = {
enabled = {
type = "toggle",
order = 1,
width = "full",
name = L["OPT_MAP_ENABLED"] or "Enable map overlay",
get = function()
local profile = HMGT.db and HMGT.db.profile
if not profile then
return true
end
profile.mapOverlay = profile.mapOverlay or {}
return profile.mapOverlay.enabled ~= false
end,
set = function(_, value)
local profile = HMGT.db and HMGT.db.profile
if not profile then
return
end
profile.mapOverlay = profile.mapOverlay or {}
profile.mapOverlay.enabled = value
if MapOverlay.Refresh then
MapOverlay:Refresh()
end
end,
},
iconSize = {
type = "range",
order = 2,
min = 8,
max = 48,
step = 1,
name = L["OPT_MAP_ICON_SIZE"] or "Icon size",
get = function()
local profile = HMGT.db and HMGT.db.profile
if not profile then
return 16
end
profile.mapOverlay = profile.mapOverlay or {}
return profile.mapOverlay.iconSize or 16
end,
set = function(_, value)
local profile = HMGT.db and HMGT.db.profile
if not profile then
return
end
profile.mapOverlay = profile.mapOverlay or {}
profile.mapOverlay.iconSize = value
if MapOverlay.Refresh then
MapOverlay:Refresh()
end
end,
},
alpha = {
type = "range",
order = 3,
min = 0.1,
max = 1,
step = 0.05,
name = L["OPT_MAP_ALPHA"] or "Icon alpha",
get = function()
local profile = HMGT.db and HMGT.db.profile
if not profile then
return 1
end
profile.mapOverlay = profile.mapOverlay or {}
return profile.mapOverlay.alpha or 1
end,
set = function(_, value)
local profile = HMGT.db and HMGT.db.profile
if not profile then
return
end
profile.mapOverlay = profile.mapOverlay or {}
profile.mapOverlay.alpha = value
if MapOverlay.Refresh then
MapOverlay:Refresh()
end
end,
},
showLabels = {
type = "toggle",
order = 4,
width = "full",
name = L["OPT_MAP_SHOW_LABELS"] or "Show labels",
get = function()
local profile = HMGT.db and HMGT.db.profile
if not profile then
return true
end
profile.mapOverlay = profile.mapOverlay or {}
return profile.mapOverlay.showLabels ~= false
end,
set = function(_, value)
local profile = HMGT.db and HMGT.db.profile
if not profile then
return
end
profile.mapOverlay = profile.mapOverlay or {}
profile.mapOverlay.showLabels = value
if MapOverlay.Refresh then
MapOverlay:Refresh()
end
end,
},
poiSection = {
type = "header",
order = 10,
name = L["OPT_MAP_POI_SECTION"] or "Custom POIs",
},
poiSummary = {
type = "description",
order = 10.1,
width = "full",
name = function()
local count = GetPoiCount()
if count <= 0 then
return L["OPT_MAP_POI_EMPTY"] or "No POIs configured."
end
return string.format(
"%s: %d\n%s",
L["OPT_MAP_POI_LIST"] or "Current POIs",
count,
L["OPT_MAP_POI_SELECT_HINT"] or "Select a POI in the tree on the left to edit it."
)
end,
},
draftMapID = {
type = "input",
order = 11,
width = 0.8,
name = L["OPT_MAP_POI_MAPID"] or "Map ID",
get = function()
HMGT._mapDraft = HMGT._mapDraft or {}
if not HMGT._mapDraft.mapID and MapOverlay.GetActiveMapID then
local activeMap = MapOverlay:GetActiveMapID()
if activeMap then
HMGT._mapDraft.mapID = tostring(activeMap)
end
end
return HMGT._mapDraft.mapID or ""
end,
set = function(_, value)
HMGT._mapDraft = HMGT._mapDraft or {}
HMGT._mapDraft.mapID = value
end,
},
useCurrentPosition = {
type = "execute",
order = 11.1,
width = "half",
name = L["OPT_MAP_POI_USE_CURRENT"] or "Use current position",
desc = L["OPT_MAP_POI_USE_CURRENT_DESC"] or "Fill map ID, X and Y from your current player position",
func = function()
HMGT._mapDraft = HMGT._mapDraft or {}
local mapID, x, y = nil, nil, nil
if HMGT.GetCurrentMapPOIData then
mapID, x, y = HMGT:GetCurrentMapPOIData()
end
if mapID and x and y then
HMGT._mapDraft.mapID = tostring(mapID)
HMGT._mapDraft.x = string.format("%.2f", x)
HMGT._mapDraft.y = string.format("%.2f", y)
HMGT:Print(L["OPT_MAP_POI_CURRENT_SET"] or "HMGT: current position copied")
else
HMGT:Print(L["OPT_MAP_POI_CURRENT_FAILED"] or "HMGT: could not determine current position")
end
NotifyOptionsChanged()
end,
},
draftX = {
type = "input",
order = 12,
width = 0.8,
name = L["OPT_MAP_POI_X"] or "X (0-100)",
get = function()
HMGT._mapDraft = HMGT._mapDraft or {}
return HMGT._mapDraft.x or ""
end,
set = function(_, value)
HMGT._mapDraft = HMGT._mapDraft or {}
HMGT._mapDraft.x = value
end,
},
draftY = {
type = "input",
order = 13,
width = 0.8,
name = L["OPT_MAP_POI_Y"] or "Y (0-100)",
get = function()
HMGT._mapDraft = HMGT._mapDraft or {}
return HMGT._mapDraft.y or ""
end,
set = function(_, value)
HMGT._mapDraft = HMGT._mapDraft or {}
HMGT._mapDraft.y = value
end,
},
draftLabel = {
type = "input",
order = 14,
width = "full",
name = L["OPT_MAP_POI_LABEL"] or "Label",
get = function()
HMGT._mapDraft = HMGT._mapDraft or {}
return HMGT._mapDraft.label or ""
end,
set = function(_, value)
HMGT._mapDraft = HMGT._mapDraft or {}
HMGT._mapDraft.label = value
end,
},
draftCategory = {
type = "select",
order = 14.1,
width = "full",
name = L["OPT_MAP_POI_CATEGORY"] or "Category",
values = function()
return MapCategoryValues()
end,
get = function()
HMGT._mapDraft = HMGT._mapDraft or {}
return HMGT._mapDraft.category or "default"
end,
set = function(_, value)
HMGT._mapDraft = HMGT._mapDraft or {}
HMGT._mapDraft.category = value
end,
},
addPoi = {
type = "execute",
order = 15,
width = "half",
name = L["OPT_MAP_POI_ADD"] or "Add POI",
func = function()
HMGT._mapDraft = HMGT._mapDraft or {}
local draft = HMGT._mapDraft
local ok = HMGT.AddMapPOI and HMGT:AddMapPOI(draft.mapID, draft.x, draft.y, draft.label, nil, draft.category or "default")
if ok then
HMGT._mapPoiDrafts = nil
HMGT:Print(L["OPT_MAP_POI_ADDED"] or "HMGT: POI added")
else
HMGT:Print(L["OPT_MAP_POI_ADD_FAILED"] or "HMGT: could not add POI")
end
NotifyOptionsChanged()
end,
},
},
},
},
}
for key, value in pairs(BuildPoiEditorGroupArgs()) do
group.args[key] = value
end
return group
end
HMGT_Config:RegisterOptionsProvider("map.overlay", function()
return {
path = "map.overlay",
order = 30,
group = MapOverlay:GetOptionsGroup(),
}
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB