mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-22 07:36:58 +00:00
1128 lines
36 KiB
Lua
1128 lines
36 KiB
Lua
local ICU_VERSION = "ICU 1.4 - Shanktank's Version";
|
|
|
|
local ICU_MAX_LINES = 10;
|
|
|
|
local ICU_CLASSES = {
|
|
["Warrior"] = { .25, 0, 0, .25; },
|
|
["Mage"] = { .5, .25, 0, .25; },
|
|
["Rogue"] = { .75, .5, 0, .25; },
|
|
["Druid"] = { 1, .75, 0, .25; },
|
|
["Hunter"] = { .25, 0, .25, .5; },
|
|
["Shaman"] = { .5, .25, .25, .5; },
|
|
["Priest"] = { .75, .5, .25, .5; },
|
|
["Warlock"] = { 1, .75, .25, .5; },
|
|
["Paladin"] = { .25, 0, .5, .75; }
|
|
};
|
|
|
|
local ICU_DESCRIPTIONS = {
|
|
["ALERT"] = "ALERT will immediately ping and add a message in the specified chat when you click the blip of a PvP-flagged player of the opposite faction on the minimap",
|
|
["ANNOUNCE"] = "ANNOUNCE will add a message in the specified chat when you click an entry in the popup frame",
|
|
["ANCHOR"] = "ANCHOR sets the location of the frame that pops up when you click a blip on the minimap",
|
|
["PLAYER_COLOR_MODE"] = "PLAYER_COLOR_MODE controls how player rows are colored (CLASS, REACTION, FACTION, CUSTOM)"
|
|
};
|
|
ICU_OPTIONS = {
|
|
["ALERT"] = { "AUTO", "PARTY", "RAID", "SELF", "MTH Message", "OFF"; },
|
|
["ANNOUNCE"] = { "AUTO", "SAY", "YELL", "PARTY", "RAID", "SELF", "MTH Message", "OFF"; },
|
|
["ANCHOR"] = { "TOP", "TOPLEFT", "TOPRIGHT", "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", "LEFT", "RIGHT", "CUSTOM"; },
|
|
["POPUP_HIDE_DELAY"] = { "INSTANT", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"; },
|
|
["HEALTH_TEXT_MODE"] = { "NONE", "PERCENT", "HP", "BOTH"; },
|
|
["PLAYER_COLOR_MODE"] = { "CLASS", "REACTION", "FACTION", "CUSTOM"; }
|
|
};
|
|
|
|
local ICU_PING_X = 0;
|
|
local ICU_PING_Y = 0;
|
|
|
|
local icu_prevtooltip = nil;
|
|
local ICU_ENABLED = false;
|
|
local ICU_HOOK_ACTIVE = false;
|
|
local ICU_Original_Minimap_OnClick = nil;
|
|
local ICU_LAST_ALERT_KEY = "";
|
|
local ICU_LAST_ALERT_AT = 0;
|
|
local ICU_POPUP_MOUSE_OUT_AT = nil;
|
|
local ICU_GetStore;
|
|
local ICU_CustomAnchor = nil;
|
|
local ICU_STORE_CACHE = nil;
|
|
local ICU_POPUP_LAST_UPDATE_AT = 0;
|
|
local ICU_POPUP_UPDATE_INTERVAL = 0.10;
|
|
local ICU_MOUSEOVER_LAST_UPDATE_AT = 0;
|
|
local ICU_MOUSEOVER_UPDATE_INTERVAL = 0.15;
|
|
local ICU_TRACE_ENABLED = false;
|
|
|
|
local ICU_CLASS_COLOR_FALLBACK = {
|
|
WARRIOR = { 0.78, 0.61, 0.43 },
|
|
MAGE = { 0.41, 0.80, 0.94 },
|
|
ROGUE = { 1.00, 0.96, 0.41 },
|
|
DRUID = { 1.00, 0.49, 0.04 },
|
|
HUNTER = { 0.67, 0.83, 0.45 },
|
|
SHAMAN = { 0.00, 0.44, 0.87 },
|
|
PRIEST = { 1.00, 1.00, 1.00 },
|
|
WARLOCK = { 0.58, 0.51, 0.79 },
|
|
PALADIN = { 0.96, 0.55, 0.73 },
|
|
};
|
|
|
|
local ICU_DEFAULT_BG_COLORS = {
|
|
PLAYER_HOSTILE = { 1.00, 0.20, 0.20 },
|
|
PLAYER_NEUTRAL = { 1.00, 0.85, 0.10 },
|
|
PLAYER_FRIENDLY = { 0.20, 0.75, 1.00 },
|
|
NPC_HOSTILE = { 1.00, 0.20, 0.20 },
|
|
NPC_NEUTRAL = { 1.00, 0.85, 0.10 },
|
|
NPC_FRIENDLY = { 0.10, 0.90, 0.10 },
|
|
UNKNOWN = { 0.70, 0.70, 0.70 },
|
|
};
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Auxiliary functions
|
|
--------------------------------------------------------------------------------
|
|
|
|
local function ICU_Print(msg)
|
|
DEFAULT_CHAT_FRAME:AddMessage(msg, 1, 1, 1);
|
|
end
|
|
|
|
local function ICU_PrintMTH(msg)
|
|
if MTH and MTH.Print then
|
|
MTH:Print(msg);
|
|
return;
|
|
end
|
|
ICU_Print(msg);
|
|
end
|
|
|
|
local function ICU_Trace(msg)
|
|
if not ICU_TRACE_ENABLED then
|
|
return;
|
|
end
|
|
ICU_PrintMTH("[ICUTRACE] " .. tostring(msg));
|
|
end
|
|
|
|
local function ICU_CommandTrace(mode)
|
|
local action = string.lower(tostring(mode or "status"));
|
|
if action == "on" or action == "1" or action == "true" then
|
|
ICU_TRACE_ENABLED = true;
|
|
ICU_Trace("trace enabled");
|
|
return;
|
|
elseif action == "off" or action == "0" or action == "false" then
|
|
ICU_Trace("trace disabled");
|
|
ICU_TRACE_ENABLED = false;
|
|
return;
|
|
end
|
|
ICU_PrintMTH("[ICUTRACE] status=" .. tostring(ICU_TRACE_ENABLED and true or false));
|
|
end
|
|
|
|
local function ICU_GetAlertPlayerName(unit, store)
|
|
unit = unit or "target";
|
|
store = store or ICU_GetStore();
|
|
|
|
local baseName = UnitName(unit) or "";
|
|
if baseName == "" then
|
|
return "Unknown";
|
|
end
|
|
|
|
if not store["SHOW_CUSTOM_TITLES"] then
|
|
return baseName;
|
|
end
|
|
|
|
local titledName = UnitPVPName(unit);
|
|
if type(titledName) ~= "string" or titledName == "" then
|
|
return baseName;
|
|
end
|
|
|
|
titledName = string.gsub(titledName, "\r\n", " ");
|
|
titledName = string.gsub(titledName, "\n", " ");
|
|
titledName = string.gsub(titledName, "%s+", " ");
|
|
titledName = string.gsub(titledName, "^%s+", "");
|
|
titledName = string.gsub(titledName, "%s+$", "");
|
|
|
|
if titledName == "" then
|
|
return baseName;
|
|
end
|
|
|
|
return titledName;
|
|
end
|
|
|
|
local function ICU_ClampColor(v)
|
|
v = tonumber(v) or 0;
|
|
if v < 0 then return 0 end
|
|
if v > 1 then return 1 end
|
|
return v;
|
|
end
|
|
|
|
local function ICU_EnsureStoreColors(store)
|
|
if type(store["COLORS"]) ~= "table" then
|
|
store["COLORS"] = {};
|
|
end
|
|
|
|
for key, def in pairs(ICU_DEFAULT_BG_COLORS) do
|
|
local row = store["COLORS"][key];
|
|
if type(row) ~= "table" then
|
|
store["COLORS"][key] = { def[1], def[2], def[3] };
|
|
else
|
|
row[1] = ICU_ClampColor(row[1] ~= nil and row[1] or def[1]);
|
|
row[2] = ICU_ClampColor(row[2] ~= nil and row[2] or def[2]);
|
|
row[3] = ICU_ClampColor(row[3] ~= nil and row[3] or def[3]);
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ICU_GetConfiguredColor(store, key)
|
|
store = store or ICU_GetStore();
|
|
ICU_EnsureStoreColors(store);
|
|
|
|
local row = store["COLORS"][key];
|
|
if type(row) == "table" then
|
|
return row[1], row[2], row[3];
|
|
end
|
|
|
|
local def = ICU_DEFAULT_BG_COLORS[key] or ICU_DEFAULT_BG_COLORS.UNKNOWN;
|
|
return def[1], def[2], def[3];
|
|
end
|
|
|
|
ICU_GetStore = function()
|
|
if type(ICU_STORE_CACHE) == "table" then
|
|
return ICU_STORE_CACHE;
|
|
end
|
|
|
|
local store = nil;
|
|
|
|
if MTH and MTH.GetModuleCharSavedVariables then
|
|
store = MTH:GetModuleCharSavedVariables("icu");
|
|
if type(store) == "table" and MTH.GetModuleSavedVariables and next(store) == nil then
|
|
local accountStore = MTH:GetModuleSavedVariables("icu");
|
|
if type(accountStore) == "table" then
|
|
for key, value in pairs(accountStore) do
|
|
if store[key] == nil then
|
|
store[key] = value;
|
|
end
|
|
end
|
|
ICU_Trace("store migrated account->char (empty char store)");
|
|
end
|
|
end
|
|
end
|
|
|
|
if type(store) ~= "table" then
|
|
ICUvars = ICUvars or {};
|
|
store = ICUvars;
|
|
end
|
|
|
|
if type(ICUvars) == "table" and ICUvars ~= store then
|
|
for key, value in pairs(ICUvars) do
|
|
if store[key] == nil then
|
|
store[key] = value;
|
|
end
|
|
end
|
|
ICU_Trace("store migrated legacy ICUvars -> module store");
|
|
end
|
|
|
|
if store["ALERT"] == nil then
|
|
store["ALERT"] = "MTH Message";
|
|
elseif store["ALERT"] == "SAY" or store["ALERT"] == "YELL" then
|
|
store["ALERT"] = "SELF";
|
|
end
|
|
if store["ANNOUNCE"] == nil then
|
|
store["ANNOUNCE"] = "MTH Message";
|
|
end
|
|
if store["ANCHOR"] == nil then
|
|
store["ANCHOR"] = "BOTTOMRIGHT";
|
|
end
|
|
if store["POPUP_HIDE_DELAY"] == nil then
|
|
store["POPUP_HIDE_DELAY"] = "INSTANT";
|
|
else
|
|
local rawDelay = tostring(store["POPUP_HIDE_DELAY"]);
|
|
if rawDelay ~= "INSTANT" then
|
|
local n = tonumber(rawDelay);
|
|
if not n then
|
|
store["POPUP_HIDE_DELAY"] = "INSTANT";
|
|
else
|
|
n = math.floor(n);
|
|
if n < 1 then
|
|
store["POPUP_HIDE_DELAY"] = "INSTANT";
|
|
elseif n > 10 then
|
|
store["POPUP_HIDE_DELAY"] = "10";
|
|
else
|
|
store["POPUP_HIDE_DELAY"] = tostring(n);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if store["mouseOver"] == nil then
|
|
store["mouseOver"] = false;
|
|
end
|
|
if store["HEALTH_TEXT_MODE"] == nil then
|
|
store["HEALTH_TEXT_MODE"] = "BOTH";
|
|
elseif store["HEALTH_TEXT_MODE"] == "AUTO" then
|
|
store["HEALTH_TEXT_MODE"] = "BOTH";
|
|
end
|
|
if store["PLAYER_COLOR_MODE"] == nil then
|
|
store["PLAYER_COLOR_MODE"] = "CLASS";
|
|
end
|
|
if store["REACTION_ONLY_PVP_PLAYERS"] == nil then
|
|
store["REACTION_ONLY_PVP_PLAYERS"] = true;
|
|
end
|
|
if store["SHOW_GUILD_NAME"] == nil then
|
|
store["SHOW_GUILD_NAME"] = false;
|
|
end
|
|
if store["SHOW_PLAYER_CLASS"] == nil then
|
|
store["SHOW_PLAYER_CLASS"] = true;
|
|
end
|
|
if store["SHOW_PLAYER_RACE"] == nil then
|
|
store["SHOW_PLAYER_RACE"] = true;
|
|
end
|
|
if store["SHOW_CUSTOM_TITLES"] == nil then
|
|
store["SHOW_CUSTOM_TITLES"] = false;
|
|
end
|
|
if store["EXPAND_UP"] == nil then
|
|
store["EXPAND_UP"] = false;
|
|
end
|
|
if store["CUSTOM_ANCHOR_X"] ~= nil then
|
|
store["CUSTOM_ANCHOR_X"] = math.floor((tonumber(store["CUSTOM_ANCHOR_X"]) or 0) + 0.5);
|
|
end
|
|
if store["CUSTOM_ANCHOR_Y"] ~= nil then
|
|
store["CUSTOM_ANCHOR_Y"] = math.floor((tonumber(store["CUSTOM_ANCHOR_Y"]) or 0) + 0.5);
|
|
end
|
|
|
|
ICU_EnsureStoreColors(store);
|
|
|
|
ICU_STORE_CACHE = store;
|
|
ICUvars = store;
|
|
return store;
|
|
end
|
|
|
|
local function ICU_ShouldEmitAlert(key)
|
|
local now = 0;
|
|
if type(GetTime) == "function" then
|
|
now = GetTime();
|
|
end
|
|
|
|
local normalized = tostring(key or "");
|
|
if normalized ~= "" and ICU_LAST_ALERT_KEY == normalized and (now - ICU_LAST_ALERT_AT) < 1.5 then
|
|
return false;
|
|
end
|
|
|
|
ICU_LAST_ALERT_KEY = normalized;
|
|
ICU_LAST_ALERT_AT = now;
|
|
return true;
|
|
end
|
|
|
|
local function ICU_GetPopupHideDelaySeconds(store)
|
|
store = store or ICU_GetStore();
|
|
|
|
local raw = tostring(store["POPUP_HIDE_DELAY"] or "INSTANT");
|
|
if raw == "INSTANT" then
|
|
return 0;
|
|
end
|
|
|
|
local n = tonumber(raw);
|
|
if not n then
|
|
return 0;
|
|
end
|
|
|
|
n = math.floor(n);
|
|
if n < 1 then
|
|
return 0;
|
|
end
|
|
if n > 10 then
|
|
return 10;
|
|
end
|
|
return n;
|
|
end
|
|
|
|
local function ICU_EnsureCustomAnchor(store)
|
|
if ICU_CustomAnchor then
|
|
return ICU_CustomAnchor;
|
|
end
|
|
|
|
store = store or ICU_GetStore();
|
|
|
|
local frame = CreateFrame("Button", "MetaHuntICUAnchor", UIParent);
|
|
frame:SetWidth(220);
|
|
frame:SetHeight(25);
|
|
frame:SetClampedToScreen(true);
|
|
frame:SetMovable(true);
|
|
frame:RegisterForDrag("LeftButton");
|
|
|
|
local px = tonumber(store["CUSTOM_ANCHOR_X"]);
|
|
local py = tonumber(store["CUSTOM_ANCHOR_Y"]);
|
|
if px ~= nil and py ~= nil then
|
|
frame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", px, py);
|
|
ICU_Trace("custom-anchor restore point=TOPLEFT->UIParent:TOPLEFT @(" .. tostring(px) .. "," .. tostring(py) .. ")");
|
|
else
|
|
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 50);
|
|
ICU_Trace("custom-anchor default point=CENTER->UIParent:CENTER @(0,50)");
|
|
end
|
|
|
|
frame:SetScript("OnDragStart", function()
|
|
this = this or this;
|
|
if this and this.StartMoving then
|
|
this:StartMoving();
|
|
end
|
|
end);
|
|
|
|
frame:SetScript("OnDragStop", function()
|
|
this = this or this;
|
|
if not this then return end
|
|
|
|
if this.StopMovingOrSizing then
|
|
this:StopMovingOrSizing();
|
|
end
|
|
|
|
local _, _, _, x, y = this:GetPoint();
|
|
x = tonumber(x);
|
|
y = tonumber(y);
|
|
if not x or not y then return end
|
|
|
|
x = math.floor(x + 0.5);
|
|
y = math.floor(y + 0.5);
|
|
this:ClearAllPoints();
|
|
this:SetPoint("TOPLEFT", UIParent, "TOPLEFT", x, y);
|
|
|
|
local storeNow = ICU_GetStore();
|
|
storeNow["CUSTOM_ANCHOR_X"] = x;
|
|
storeNow["CUSTOM_ANCHOR_Y"] = y;
|
|
ICU_Trace("custom-anchor drag-stop saved x=" .. tostring(x) .. " y=" .. tostring(y));
|
|
ICU_SetPoints();
|
|
end);
|
|
|
|
frame:SetBackdrop({
|
|
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
|
|
edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
|
|
tile = false,
|
|
tileSize = 16,
|
|
edgeSize = 16,
|
|
insets = { left = 5, right = 5, top = 5, bottom = 5 },
|
|
});
|
|
frame:SetBackdropColor(0, 1, 0, 0.6);
|
|
|
|
frame.Text = frame:CreateFontString(nil, "OVERLAY");
|
|
frame.Text:SetFontObject(GameFontNormalSmall);
|
|
frame.Text:ClearAllPoints();
|
|
frame.Text:SetTextColor(1, 1, 1, 1);
|
|
frame.Text:SetWidth(220);
|
|
frame.Text:SetHeight(25);
|
|
frame.Text:SetPoint("TOPLEFT", frame, "TOPLEFT");
|
|
frame.Text:SetJustifyH("CENTER");
|
|
frame.Text:SetJustifyV("MIDDLE");
|
|
frame.Text:SetText("MetaHunt MCU");
|
|
frame:Hide();
|
|
|
|
ICU_CustomAnchor = frame;
|
|
return frame;
|
|
end
|
|
|
|
function ICU_ToggleAnchor()
|
|
local store = ICU_GetStore();
|
|
if store["ANCHOR"] ~= "CUSTOM" then
|
|
store["ANCHOR"] = "CUSTOM";
|
|
ICU_SetPoints();
|
|
ICU_Trace("toggle-anchor forced CUSTOM mode");
|
|
end
|
|
|
|
local anchor = ICU_EnsureCustomAnchor(store);
|
|
if anchor:IsVisible() then
|
|
anchor:Hide();
|
|
else
|
|
anchor:Show();
|
|
end
|
|
end
|
|
|
|
local function ICU_ClampPercent(value)
|
|
local pct = math.floor((tonumber(value) or 0) + 0.5);
|
|
if pct < 0 then
|
|
return 0;
|
|
end
|
|
if pct > 100 then
|
|
return 100;
|
|
end
|
|
return pct;
|
|
end
|
|
|
|
local function ICU_GetHealthLabelAndBar(currentHealth, maxHealth, mode)
|
|
currentHealth = tonumber(currentHealth) or 0;
|
|
maxHealth = tonumber(maxHealth) or 0;
|
|
mode = tostring(mode or "AUTO");
|
|
|
|
if mode == "NONE" then
|
|
return "", nil;
|
|
end
|
|
|
|
local hasMax = maxHealth > 0 and currentHealth <= maxHealth;
|
|
local percent = nil;
|
|
if hasMax then
|
|
percent = ICU_ClampPercent((currentHealth / maxHealth) * 100);
|
|
elseif currentHealth <= 100 then
|
|
percent = ICU_ClampPercent(currentHealth);
|
|
end
|
|
|
|
if mode == "PERCENT" then
|
|
if percent ~= nil then
|
|
return "[" .. percent .. "%]", percent;
|
|
end
|
|
return "[" .. currentHealth .. " HP]", 100;
|
|
elseif mode == "HP" then
|
|
if hasMax then
|
|
return "[" .. currentHealth .. "/" .. maxHealth .. " HP]", percent;
|
|
end
|
|
return "[" .. currentHealth .. " HP]", (percent or 100);
|
|
elseif mode == "BOTH" then
|
|
if hasMax and percent ~= nil then
|
|
return "[" .. currentHealth .. "/" .. maxHealth .. " | " .. percent .. "%]", percent;
|
|
elseif percent ~= nil then
|
|
return "[" .. percent .. "% | " .. currentHealth .. " HP]", percent;
|
|
end
|
|
return "[" .. currentHealth .. " HP]", 100;
|
|
end
|
|
|
|
if hasMax and percent ~= nil then
|
|
return "[" .. percent .. "%]", percent;
|
|
elseif percent ~= nil then
|
|
return "[" .. percent .. "%]", percent;
|
|
end
|
|
return "[" .. currentHealth .. " HP]", 100;
|
|
end
|
|
|
|
local function ICU_GetClassColor(classToken)
|
|
classToken = tostring(classToken or "");
|
|
if classToken == "" then
|
|
return nil;
|
|
end
|
|
|
|
if RAID_CLASS_COLORS and RAID_CLASS_COLORS[classToken] then
|
|
local c = RAID_CLASS_COLORS[classToken];
|
|
return c.r or 1, c.g or 1, c.b or 1;
|
|
end
|
|
|
|
local fallback = ICU_CLASS_COLOR_FALLBACK[classToken];
|
|
if fallback then
|
|
return fallback[1], fallback[2], fallback[3];
|
|
end
|
|
|
|
return nil;
|
|
end
|
|
|
|
local function ICU_GetDisplayColor(unit, classToken, store)
|
|
unit = tostring(unit or "target");
|
|
store = store or ICU_GetStore();
|
|
|
|
if UnitIsPlayer(unit) then
|
|
local mode = tostring(store["PLAYER_COLOR_MODE"] or "CLASS");
|
|
local reactionOnlyPvp = store["REACTION_ONLY_PVP_PLAYERS"] and true or false;
|
|
local myFaction = UnitFactionGroup("player");
|
|
local theirFaction = UnitFactionGroup(unit);
|
|
local hostileByFaction = myFaction and theirFaction and myFaction ~= theirFaction;
|
|
local reaction = UnitReaction(unit, "player");
|
|
local isPvp = UnitIsPVP and UnitIsPVP(unit) and true or false;
|
|
local hostileByPvp = hostileByFaction and isPvp;
|
|
|
|
local function classOrFriendly()
|
|
local cr, cg, cb = ICU_GetClassColor(classToken);
|
|
if cr and cg and cb then
|
|
return cr, cg, cb;
|
|
end
|
|
return ICU_GetConfiguredColor(store, "PLAYER_FRIENDLY");
|
|
end
|
|
|
|
if mode == "REACTION" then
|
|
if reactionOnlyPvp and not isPvp then
|
|
local r, g, b = classOrFriendly();
|
|
return r, g, b;
|
|
end
|
|
|
|
if reaction and reaction <= 3 then
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_HOSTILE");
|
|
return r, g, b;
|
|
elseif reaction and reaction == 4 then
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_NEUTRAL");
|
|
return r, g, b;
|
|
elseif reaction and reaction >= 5 then
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_FRIENDLY");
|
|
return r, g, b;
|
|
end
|
|
elseif mode == "FACTION" then
|
|
if hostileByPvp then
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_HOSTILE");
|
|
return r, g, b;
|
|
end
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_FRIENDLY");
|
|
return r, g, b;
|
|
elseif mode == "CUSTOM" then
|
|
if hostileByPvp then
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_HOSTILE");
|
|
return r, g, b;
|
|
elseif reaction and reaction == 4 then
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_NEUTRAL");
|
|
return r, g, b;
|
|
end
|
|
local r, g, b = ICU_GetConfiguredColor(store, "PLAYER_FRIENDLY");
|
|
return r, g, b;
|
|
end
|
|
|
|
local r, g, b = classOrFriendly();
|
|
return r, g, b;
|
|
end
|
|
|
|
local reaction = UnitReaction(unit, "player");
|
|
if reaction and reaction <= 3 then
|
|
return ICU_GetConfiguredColor(store, "NPC_HOSTILE");
|
|
elseif reaction and reaction == 4 then
|
|
return ICU_GetConfiguredColor(store, "NPC_NEUTRAL");
|
|
elseif reaction and reaction >= 5 then
|
|
return ICU_GetConfiguredColor(store, "NPC_FRIENDLY");
|
|
end
|
|
|
|
return ICU_GetConfiguredColor(store, "UNKNOWN");
|
|
end
|
|
|
|
local function ICU_IsEnabled()
|
|
return ICU_ENABLED and true or false;
|
|
end
|
|
|
|
local function ICU_InstallHook()
|
|
if ICU_HOOK_ACTIVE then
|
|
return;
|
|
end
|
|
|
|
if type(Minimap_OnClick) == "function" then
|
|
ICU_Original_Minimap_OnClick = Minimap_OnClick;
|
|
Minimap_OnClick = ICU_Minimap_OnClick_Event;
|
|
ICU_HOOK_ACTIVE = true;
|
|
end
|
|
end
|
|
|
|
local function ICU_UninstallHook()
|
|
if not ICU_HOOK_ACTIVE then
|
|
return;
|
|
end
|
|
|
|
if Minimap_OnClick == ICU_Minimap_OnClick_Event and type(ICU_Original_Minimap_OnClick) == "function" then
|
|
Minimap_OnClick = ICU_Original_Minimap_OnClick;
|
|
end
|
|
|
|
ICU_HOOK_ACTIVE = false;
|
|
end
|
|
|
|
function ICU_SetEnabled(enabled)
|
|
ICU_ENABLED = enabled and true or false;
|
|
ICU_GetStore();
|
|
|
|
if ICU_ENABLED then
|
|
ICU_InstallHook();
|
|
if ICU_UpdateFrame then
|
|
ICU_UpdateFrame:Show();
|
|
end
|
|
return;
|
|
end
|
|
|
|
ICU_UninstallHook();
|
|
if ICU_UpdateFrame then
|
|
ICU_UpdateFrame:Hide();
|
|
end
|
|
if ICU_CustomAnchor then
|
|
ICU_CustomAnchor:Hide();
|
|
end
|
|
icu_prevtooltip = nil;
|
|
ICU_Clear_Popup();
|
|
end
|
|
|
|
local function ICU_StringifyKeys(tab)
|
|
local str = "";
|
|
|
|
for key, _ in pairs(tab) do
|
|
str = str .. key .. ", ";
|
|
end
|
|
|
|
return string.sub(str, 1, -3);
|
|
end
|
|
|
|
local function ICU_TableHasValue(tab, val)
|
|
for _, v in ipairs(tab) do
|
|
if val == v then
|
|
return true;
|
|
end
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- OnFoo() functions
|
|
--------------------------------------------------------------------------------
|
|
|
|
function ICU_OnLoad()
|
|
this:RegisterEvent("VARIABLES_LOADED");
|
|
|
|
SLASH_ICUTRACE1 = "/icutrace";
|
|
SlashCmdList["ICUTRACE"] = function(msg)
|
|
ICU_CommandTrace(msg);
|
|
end
|
|
|
|
ICU_STORE_CACHE = nil;
|
|
if ICU_UpdateFrame then
|
|
ICU_UpdateFrame:Hide();
|
|
end
|
|
ICU_Clear_Popup();
|
|
end
|
|
|
|
function ICU_OnEvent(event)
|
|
if event == "VARIABLES_LOADED" then
|
|
ICU_STORE_CACHE = nil;
|
|
ICU_GetStore();
|
|
ICU_SetPoints();
|
|
end
|
|
end
|
|
|
|
function ICU_SetPoints()
|
|
local store = ICU_GetStore();
|
|
|
|
if not ICU_Popup then
|
|
return;
|
|
end
|
|
|
|
ICU_Popup:ClearAllPoints();
|
|
|
|
if store["ANCHOR"] == "CUSTOM" then
|
|
local anchor = ICU_EnsureCustomAnchor(store);
|
|
local px = tonumber(store["CUSTOM_ANCHOR_X"]);
|
|
local py = tonumber(store["CUSTOM_ANCHOR_Y"]);
|
|
if px ~= nil and py ~= nil then
|
|
anchor:ClearAllPoints();
|
|
anchor:SetPoint("TOPLEFT", UIParent, "TOPLEFT", px, py);
|
|
end
|
|
|
|
if store["EXPAND_UP"] then
|
|
ICU_Popup:SetPoint("BOTTOMLEFT", anchor, "TOPLEFT", 0, 0);
|
|
else
|
|
ICU_Popup:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, 0);
|
|
end
|
|
return;
|
|
end
|
|
|
|
if ICU_CustomAnchor then
|
|
ICU_CustomAnchor:Hide();
|
|
end
|
|
|
|
if store["ANCHOR"] == "BOTTOMRIGHT" then
|
|
ICU_Popup:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", 0, 0);
|
|
elseif store["ANCHOR"] == "TOPRIGHT" then
|
|
ICU_Popup:SetPoint("BOTTOMRIGHT", "MinimapCluster", "TOPRIGHT", 0, 0);
|
|
elseif store["ANCHOR"] == "BOTTOM" then
|
|
ICU_Popup:SetPoint("TOP", "MinimapCluster", "BOTTOM", 0, 0);
|
|
elseif store["ANCHOR"] == "TOP" then
|
|
ICU_Popup:SetPoint("BOTTOM", "MinimapCluster", "TOP", 0, 0);
|
|
elseif store["ANCHOR"] == "BOTTOMLEFT" then
|
|
ICU_Popup:SetPoint("TOPLEFT", "MinimapCluster", "BOTTOMLEFT", 0, 0);
|
|
elseif store["ANCHOR"] == "TOPLEFT" then
|
|
ICU_Popup:SetPoint("BOTTOMLEFT", "MinimapCluster", "TOPLEFT", 0, 0);
|
|
elseif store["ANCHOR"] == "RIGHT" then
|
|
ICU_Popup:SetPoint("RIGHT", "MinimapCluster", "LEFT", 0, 0);
|
|
elseif store["ANCHOR"] == "LEFT" then
|
|
ICU_Popup:SetPoint("LEFT", "MinimapCluster", "RIGHT", 0, 0);
|
|
end
|
|
end
|
|
|
|
function ICU_Popup_OnUpdate()
|
|
if not ICU_IsEnabled() then
|
|
return;
|
|
end
|
|
|
|
local now = type(GetTime) == "function" and GetTime() or nil;
|
|
if now then
|
|
if (now - (ICU_POPUP_LAST_UPDATE_AT or 0)) < ICU_POPUP_UPDATE_INTERVAL then
|
|
return;
|
|
end
|
|
ICU_POPUP_LAST_UPDATE_AT = now;
|
|
end
|
|
|
|
local store = ICU_GetStore();
|
|
if MouseIsOver(MinimapCluster) or MouseIsOver(ICU_Popup) then
|
|
if ICU_POPUP_MOUSE_OUT_AT then
|
|
ICU_Trace("popup mouse returned -> reset mouse-out timer");
|
|
end
|
|
ICU_POPUP_MOUSE_OUT_AT = nil;
|
|
return;
|
|
end
|
|
|
|
local delay = ICU_GetPopupHideDelaySeconds(store);
|
|
if delay <= 0 then
|
|
ICU_Trace("popup clear reason=delay-instant configured='" .. tostring(store["POPUP_HIDE_DELAY"])
|
|
.. "' resolvedDelay=" .. tostring(delay));
|
|
ICU_Clear_Popup();
|
|
return;
|
|
end
|
|
|
|
if not now then
|
|
ICU_Trace("popup clear reason=no-time-api configured='" .. tostring(store["POPUP_HIDE_DELAY"])
|
|
.. "' resolvedDelay=" .. tostring(delay));
|
|
ICU_Clear_Popup();
|
|
return;
|
|
end
|
|
|
|
if not ICU_POPUP_MOUSE_OUT_AT then
|
|
ICU_POPUP_MOUSE_OUT_AT = now;
|
|
ICU_Trace("popup mouse-out start delay=" .. tostring(delay)
|
|
.. " configured='" .. tostring(store["POPUP_HIDE_DELAY"]) .. "'");
|
|
return;
|
|
end
|
|
|
|
if (now - ICU_POPUP_MOUSE_OUT_AT) >= delay then
|
|
ICU_Trace("popup clear reason=mouse-out-timeout elapsed=" .. string.format("%.2f", (now - ICU_POPUP_MOUSE_OUT_AT))
|
|
.. " delay=" .. tostring(delay)
|
|
.. " configured='" .. tostring(store["POPUP_HIDE_DELAY"]) .. "'");
|
|
ICU_Clear_Popup();
|
|
end
|
|
end
|
|
|
|
function ICU_ButtonClick()
|
|
if not ICU_IsEnabled() then
|
|
return;
|
|
end
|
|
|
|
local store = ICU_GetStore();
|
|
if string.len(this.ICU_DATA) ~= string.len(this:GetText()) then
|
|
local lOriginal_ERR_UNIT_NOT_FOUND = ERR_UNIT_NOT_FOUND;
|
|
local lOriginal_ERR_GENERIC_NO_TARGET = ERR_GENERIC_NO_TARGET;
|
|
ERR_UNIT_NOT_FOUND = "";
|
|
ERR_GENERIC_NO_TARGET = "";
|
|
|
|
TargetByName(this.ICU_DATA);
|
|
|
|
if UnitIsDead("target") then
|
|
ClearTarget();
|
|
end
|
|
|
|
if not IsControlKeyDown() then
|
|
if store["ANNOUNCE"] == "MTH Message" then
|
|
ICU_PrintMTH("ICU -> " .. this:GetText() .. ".");
|
|
elseif store["ANNOUNCE"] == "SELF" then
|
|
ICU_Print("ICU -> " .. this:GetText() .. ".");
|
|
elseif store["ANNOUNCE"] ~= "OFF" then
|
|
if store["ANNOUNCE"] ~= "AUTO" then
|
|
SendChatMessage("ICU -> " .. this:GetText() .. ".", store["ANNOUNCE"]);
|
|
else
|
|
if GetNumRaidMembers() > 0 then
|
|
SendChatMessage("ICU -> " .. this:GetText() .. ".", "RAID");
|
|
elseif GetNumPartyMembers() > 0 then
|
|
SendChatMessage("ICU -> " .. this:GetText() .. ".", "PARTY");
|
|
else
|
|
ICU_Print("ICU -> " .. this:GetText() .. ".");
|
|
end
|
|
end
|
|
end
|
|
else
|
|
ICU_Print("ICU -> " .. this:GetText() .. ".");
|
|
end
|
|
|
|
ERR_UNIT_NOT_FOUND = lOriginal_ERR_UNIT_NOT_FOUND;
|
|
ERR_GENERIC_NO_TARGET = lOriginal_ERR_GENERIC_NO_TARGET;
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- OnFoo() hooked function
|
|
--------------------------------------------------------------------------------
|
|
|
|
function ICU_Minimap_OnClick_Event()
|
|
if not ICU_IsEnabled() then
|
|
if type(ICU_Original_Minimap_OnClick) == "function" then
|
|
ICU_Original_Minimap_OnClick();
|
|
end
|
|
return;
|
|
end
|
|
|
|
if IsShiftKeyDown() then
|
|
if type(ICU_Original_Minimap_OnClick) == "function" then
|
|
ICU_Original_Minimap_OnClick();
|
|
end
|
|
else
|
|
if GameTooltip:IsVisible() and GameTooltipTextLeft1 and GameTooltipTextLeft1:GetText() then
|
|
local x, y = GetCursorPosition();
|
|
x = x / Minimap:GetEffectiveScale();
|
|
y = y / Minimap:GetEffectiveScale();
|
|
|
|
local cx, cy = Minimap:GetCenter();
|
|
ICU_PING_X = x + CURSOR_OFFSET_X - cx;
|
|
ICU_PING_Y = y + CURSOR_OFFSET_Y - cy;
|
|
|
|
ICU_Clear_Popup();
|
|
ICU_Process_Tooltip(GameTooltipTextLeft1:GetText());
|
|
|
|
PlaySound("UChatScrollButton");
|
|
elseif type(ICU_Original_Minimap_OnClick) == "function" then
|
|
ICU_Original_Minimap_OnClick();
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Internal functions
|
|
--------------------------------------------------------------------------------
|
|
|
|
function ICU_Process_Tooltip(tooltip, silent)
|
|
if not ICU_IsEnabled() then
|
|
return;
|
|
end
|
|
|
|
if type(tooltip) ~= "string" or tooltip == "" then
|
|
return;
|
|
end
|
|
|
|
local pos = 0;
|
|
local width = 0;
|
|
local result_line, r, g, b, target, class, health, rank;
|
|
local prev_trg = nil;
|
|
local lOriginal_TargetFrame_OnShow_Event = TargetFrame_OnShow;
|
|
local lOriginal_TargetFrame_OnHide_Event = TargetFrame_OnHide;
|
|
TargetFrame_OnShow = ICU_TargetFrame_OnShow_Event;
|
|
TargetFrame_OnHide = ICU_TargetFrame_OnHide_Event;
|
|
local lOriginal_ERR_UNIT_NOT_FOUND = ERR_UNIT_NOT_FOUND;
|
|
local lOriginal_ERR_GENERIC_NO_TARGET = ERR_GENERIC_NO_TARGET;
|
|
ERR_UNIT_NOT_FOUND = "";
|
|
ERR_GENERIC_NO_TARGET = "";
|
|
|
|
prev_trg = UnitName("target");
|
|
ClearTarget();
|
|
|
|
for target in string.gfind(tooltip, "[^\n]*") do
|
|
if string.len(target) > 0 then
|
|
result_line, class, health, rank, r, g, b = ICU2_Process_Trg(target);
|
|
|
|
if result_line ~= nil then
|
|
pos = pos + 1;
|
|
|
|
if not health then
|
|
health = 0;
|
|
end
|
|
|
|
local button = getglobal("ICU_PopupButton" .. pos .. "Button");
|
|
local bar = getglobal("ICU_PopupButton" .. pos .. "ButtonBar");
|
|
local bg = getglobal("ICU_PopupButton" .. pos .. "ButtonBGBar");
|
|
local ranktex = getglobal("ICU_PopupButton" .. pos .. "ButtonRankIcon");
|
|
|
|
SetPortraitTexture(getglobal("ICU_PopupButton" .. pos .. "ButtonPortraitIcon"), "target");
|
|
|
|
if ICU_CLASSES[class] then
|
|
getglobal("ICU_PopupButton" .. pos .. "ButtonClassIcon"):SetTexCoord(unpack(ICU_CLASSES[class]));
|
|
else
|
|
getglobal("ICU_PopupButton" .. pos .. "ButtonClassIcon"):SetTexCoord(0, .25, 0, .25);
|
|
end
|
|
|
|
getglobal("ICU_PopupButton" .. pos .. "ButtonClassIcon"):SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes");
|
|
|
|
if rank and rank ~= 0 then
|
|
ranktex:SetTexture(format("%s%02d","Interface\\PvPRankBadges\\PvPRank", rank - 4));
|
|
ranktex:Show();
|
|
else
|
|
ranktex:Hide();
|
|
end
|
|
|
|
getglobal("ICU_PopupButton" .. pos):SetBackdropBorderColor(r, g, b);
|
|
bar:SetStatusBarColor(r, g, b, 0.75);
|
|
bar:SetValue(health);
|
|
bg:SetStatusBarColor(r, g, b, 0.1);
|
|
button:SetTextColor(r + 0.3, g + 0.3, b + 0.3);
|
|
button:SetText(result_line);
|
|
button.ICU_DATA = target;
|
|
button:GetParent():Show();
|
|
button:Show();
|
|
|
|
local w = button:GetTextWidth();
|
|
if w > width then
|
|
width = w;
|
|
end
|
|
end
|
|
end
|
|
|
|
if pos >= ICU_MAX_LINES then
|
|
break
|
|
end;
|
|
end
|
|
|
|
TargetFrame_OnShow = lOriginal_TargetFrame_OnShow_Event;
|
|
TargetFrame_OnHide = lOriginal_TargetFrame_OnHide_Event;
|
|
ERR_UNIT_NOT_FOUND = lOriginal_ERR_UNIT_NOT_FOUND;
|
|
ERR_GENERIC_NO_TARGET = lOriginal_ERR_GENERIC_NO_TARGET;
|
|
|
|
if pos > 0 then
|
|
ICU_Display_Popup(pos, width + 10);
|
|
else
|
|
ICU_Clear_Popup();
|
|
end
|
|
end
|
|
|
|
function ICU2_Process_Trg(trg)
|
|
local store = ICU_GetStore();
|
|
|
|
for name in string.gfind(trg, "|c%x%x%x%x%x%x%x%x([^|]+)|r") do
|
|
trg = name;
|
|
end
|
|
|
|
local result_strn = nil;
|
|
local health, rank;
|
|
|
|
TargetByName(trg);
|
|
|
|
if UnitExists("target") and UnitName("target") then
|
|
local _, classToken = UnitClass("target");
|
|
result_strn = trg .. " " .. UnitLevel( "target" );
|
|
|
|
if UnitIsPlayer("target") then
|
|
myFaction, _ = UnitFactionGroup("player");
|
|
theirFaction, _ = UnitFactionGroup("target");
|
|
local isPvp = UnitIsPVP and UnitIsPVP("target") and true or false;
|
|
|
|
if myFaction ~= theirFaction and isPvp and not UnitOnTaxi("target") then
|
|
local enemyName = UnitName("target") or "";
|
|
if ICU_ShouldEmitAlert(enemyName) then
|
|
Minimap:PingLocation(ICU_PING_X, ICU_PING_Y);
|
|
end
|
|
|
|
local alertName = ICU_GetAlertPlayerName("target", store);
|
|
message = "ICU -> " .. alertName .. " " .. UnitLevel("target") .. " " .. UnitRace("target") .. " " .. UnitClass("target");
|
|
|
|
local shouldSendAlertMessage = ICU_ShouldEmitAlert(enemyName .. "-msg");
|
|
if shouldSendAlertMessage and store["ALERT"] == "AUTO" then
|
|
if GetNumRaidMembers() > 0 then
|
|
SendChatMessage(message, "RAID");
|
|
elseif GetNumPartyMembers() > 0 then
|
|
SendChatMessage(message, "PARTY");
|
|
else
|
|
ICU_Print(message);
|
|
end
|
|
elseif shouldSendAlertMessage and store["ALERT"] == "MTH Message" then
|
|
ICU_PrintMTH(message);
|
|
elseif shouldSendAlertMessage and store["ALERT"] == "SELF" then
|
|
ICU_Print(message);
|
|
elseif shouldSendAlertMessage and store["ALERT"] ~= "OFF" and not ((store["ALERT"] == "PARTY" and GetNumPartyMembers() == 0) or (store["ALERT"] == "RAID" and GetNumRaidMembers() == 0)) then
|
|
SendChatMessage(message, store["ALERT"]);
|
|
end
|
|
end
|
|
|
|
local playerRace = UnitRace("target") or "";
|
|
local playerClass = UnitClass("target") or "";
|
|
local playerMeta = {};
|
|
if store["SHOW_PLAYER_RACE"] and playerRace ~= "" then
|
|
table.insert(playerMeta, playerRace);
|
|
end
|
|
if store["SHOW_PLAYER_CLASS"] and playerClass ~= "" then
|
|
table.insert(playerMeta, playerClass);
|
|
end
|
|
if table.getn(playerMeta) > 0 then
|
|
result_strn = result_strn .. " " .. table.concat(playerMeta, " ");
|
|
end
|
|
rank = UnitPVPRank("target");
|
|
local guildname, _, _ = GetGuildInfo("target");
|
|
|
|
if store["SHOW_GUILD_NAME"] and guildname ~= nil and guildname ~= "" then
|
|
result_strn = result_strn .. " <" .. guildname .. ">";
|
|
end
|
|
|
|
local currentHealth = tonumber(UnitHealth("target")) or 0;
|
|
local maxHealth = tonumber(UnitHealthMax("target")) or 0;
|
|
local healthMode = store["HEALTH_TEXT_MODE"] or "AUTO";
|
|
|
|
if UnitInParty("target") or UnitInRaid("target") then
|
|
result_strn = result_strn .. " [" .. currentHealth .. "/" .. maxHealth .. "]";
|
|
if maxHealth > 0 then
|
|
health = currentHealth / maxHealth * 100;
|
|
else
|
|
health = 0;
|
|
end
|
|
else
|
|
local healthLabel, barValue = ICU_GetHealthLabelAndBar(currentHealth, maxHealth, healthMode);
|
|
if healthLabel and healthLabel ~= "" then
|
|
result_strn = result_strn .. " " .. healthLabel;
|
|
end
|
|
health = barValue;
|
|
end
|
|
else
|
|
result_strn = "NPC:- " .. result_strn;
|
|
local currentHealth = tonumber(UnitHealth("target")) or 0;
|
|
local maxHealth = tonumber(UnitHealthMax("target")) or 0;
|
|
local healthMode = store["HEALTH_TEXT_MODE"] or "AUTO";
|
|
local healthLabel, barValue = ICU_GetHealthLabelAndBar(currentHealth, maxHealth, healthMode);
|
|
if healthLabel and healthLabel ~= "" then
|
|
result_strn = result_strn .. " " .. healthLabel;
|
|
end
|
|
health = barValue;
|
|
end
|
|
|
|
local r, g, b = ICU_GetDisplayColor("target", classToken, store);
|
|
|
|
return result_strn, UnitClass("target"), health, rank, r, g, b;
|
|
end
|
|
|
|
return result_strn;
|
|
end
|
|
|
|
function ICU_TargetFrame_OnShow_Event()
|
|
-- Do nothing
|
|
end
|
|
|
|
function ICU_TargetFrame_OnHide_Event()
|
|
CloseDropDownMenus();
|
|
end
|
|
|
|
function ICU_Display_Popup(numTrgs, width)
|
|
if not ICU_IsEnabled() then
|
|
return;
|
|
end
|
|
|
|
for i = 1, 10 do
|
|
getglobal("ICU_PopupButton" .. i):SetWidth(width + 40 + 9);
|
|
getglobal("ICU_PopupButton" .. i .. "Button"):SetWidth(width + 40);
|
|
getglobal("ICU_PopupButton" .. i .. "ButtonBar"):SetWidth(width);
|
|
getglobal("ICU_PopupButton" .. i .. "ButtonBGBar"):SetWidth(width);
|
|
end
|
|
|
|
ICU_Popup:SetWidth(width + 40 + UNITPOPUP_BORDER_WIDTH);
|
|
ICU_Popup:SetHeight(numTrgs * ICU_PopupButton1:GetHeight() + 12);
|
|
ICU_POPUP_MOUSE_OUT_AT = nil;
|
|
ICU_Popup:Show();
|
|
end
|
|
|
|
function ICU_Clear_Popup()
|
|
if not ICU_Popup then
|
|
return;
|
|
end
|
|
|
|
for i = 1, 10 do
|
|
getglobal("ICU_PopupButton" .. i .. "Button"):SetText("");
|
|
getglobal("ICU_PopupButton" .. i).ICU_DATA = "";
|
|
getglobal("ICU_PopupButton" .. i):Hide();
|
|
end
|
|
|
|
ICU_POPUP_MOUSE_OUT_AT = nil;
|
|
ICU_Popup:Hide();
|
|
end
|
|
|
|
function ICU_MouseOverUpdate()
|
|
if not ICU_IsEnabled() then
|
|
return;
|
|
end
|
|
|
|
local now = type(GetTime) == "function" and GetTime() or nil;
|
|
if now then
|
|
if (now - (ICU_MOUSEOVER_LAST_UPDATE_AT or 0)) < ICU_MOUSEOVER_UPDATE_INTERVAL then
|
|
return;
|
|
end
|
|
ICU_MOUSEOVER_LAST_UPDATE_AT = now;
|
|
end
|
|
|
|
local store = ICU_GetStore();
|
|
if not GetMouseFocus then
|
|
return;
|
|
end
|
|
|
|
local focus = GetMouseFocus();
|
|
if not focus then
|
|
return;
|
|
end
|
|
|
|
if store["mouseOver"] and IsControlKeyDown() and MouseIsOver(MinimapCluster) and focus.GetName and focus:GetName() == "Minimap" then
|
|
if GameTooltip and GameTooltip.IsVisible and GameTooltip:IsVisible() and GameTooltipTextLeft1 and GameTooltipTextLeft1.GetText then
|
|
local tooltipText = GameTooltipTextLeft1:GetText();
|
|
if tooltipText ~= icu_prevtooltip then
|
|
ICU_Clear_Popup();
|
|
icu_prevtooltip = tooltipText;
|
|
ICU_Minimap_OnClick_Event();
|
|
end
|
|
end
|
|
end
|
|
end
|