You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1160 lines
29 KiB
1160 lines
29 KiB
|
2 years ago
|
local _;
|
||
|
|
|
||
|
|
local strsub = strsub;
|
||
|
|
local InCombatLockdown = InCombatLockdown;
|
||
|
|
local twipe = table.wipe;
|
||
|
|
local tinsert = tinsert;
|
||
|
|
local strfind = strfind;
|
||
|
|
local strsplit = strsplit;
|
||
|
|
local strbyte = strbyte;
|
||
|
|
local floor = floor;
|
||
|
|
local tonumber = tonumber;
|
||
|
|
local select = select;
|
||
|
|
local strmatch = strmatch;
|
||
|
|
local IsInRaid = IsInRaid;
|
||
|
|
local IsInGroup = IsInGroup;
|
||
|
|
local UnitInRange = UnitInRange;
|
||
|
|
local GetRaidRosterInfo = GetRaidRosterInfo;
|
||
|
|
local IsInInstance = IsInInstance;
|
||
|
|
local IsSpellInRange = IsSpellInRange;
|
||
|
|
local GetTime = GetTime;
|
||
|
|
local GetRealZoneText = GetRealZoneText;
|
||
|
|
local GetSpellInfo = GetSpellInfo;
|
||
|
|
local SetMapToCurrentZone = SetMapToCurrentZone;
|
||
|
|
local UnitPowerBarID = UnitPowerBarID;
|
||
|
|
local GetUnitPowerBarInfoByID = GetUnitPowerBarInfoByID;
|
||
|
|
local WorldMapFrame = WorldMapFrame;
|
||
|
|
local GetMouseFocus = GetMouseFocus;
|
||
|
|
local GetPlayerFacing = GetPlayerFacing;
|
||
|
|
local GetSpellBookItemInfo = GetSpellBookItemInfo;
|
||
|
|
local CheckInteractDistance = CheckInteractDistance;
|
||
|
|
local UnitIsUnit = UnitIsUnit;
|
||
|
|
local IsAltKeyDown = IsAltKeyDown;
|
||
|
|
local IsControlKeyDown = IsControlKeyDown;
|
||
|
|
local IsShiftKeyDown = IsShiftKeyDown;
|
||
|
|
local VUHDO_atan2 = math.atan2;
|
||
|
|
local VUHDO_PI, VUHDO_2_PI = math.pi, math.pi * 2;
|
||
|
|
local floor = floor;
|
||
|
|
local pairs = pairs;
|
||
|
|
local type = type;
|
||
|
|
local abs = abs;
|
||
|
|
|
||
|
|
-- talent cache maps for new large Dragonflight talent trees
|
||
|
|
local VUHDO_TALENT_CACHE_SPELL_ID = {
|
||
|
|
-- [<spell ID>] = <spell name>,
|
||
|
|
};
|
||
|
|
|
||
|
|
local VUHDO_TALENT_CACHE_SPELL_NAME = {
|
||
|
|
-- [<spell name>] = <spell ID>,
|
||
|
|
};
|
||
|
|
|
||
|
|
local sEmpty = { };
|
||
|
|
setmetatable(sEmpty, { __newindex = function(aTable, aKey, aValue) VUHDO_xMsg("WARNING: newindex on dummy array: ", aKey, aValue); end });
|
||
|
|
|
||
|
|
-- Common meta tables
|
||
|
|
|
||
|
|
VUHDO_META_EMPTY_ARRAY = {
|
||
|
|
__index = function (aTable, aKey)
|
||
|
|
return sEmpty;
|
||
|
|
end
|
||
|
|
};
|
||
|
|
|
||
|
|
VUHDO_META_NEW_ARRAY = {
|
||
|
|
__index = function(aTable, aKey)
|
||
|
|
local tValue = { };
|
||
|
|
rawset(aTable, aKey, tValue);
|
||
|
|
return tValue;
|
||
|
|
end
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns an array of numbers sequentially found in a string
|
||
|
|
local tNumbers = { };
|
||
|
|
local tIndex;
|
||
|
|
local tDigit;
|
||
|
|
local tIsInNumber;
|
||
|
|
function VUHDO_getNumbersFromString(aName, aMaxAnz)
|
||
|
|
twipe(tNumbers);
|
||
|
|
tIndex = 0;
|
||
|
|
tIsInNumber = false;
|
||
|
|
|
||
|
|
for tCnt = 1, #aName do
|
||
|
|
tDigit = strbyte(aName, tCnt);
|
||
|
|
if tDigit >= 48 and tDigit <= 57 then
|
||
|
|
if tIsInNumber then
|
||
|
|
tNumbers[tIndex] = tNumbers[tIndex] * 10 + tDigit - 48;
|
||
|
|
else
|
||
|
|
tIsInNumber = true;
|
||
|
|
tIndex = tIndex + 1;
|
||
|
|
tNumbers[tIndex] = tDigit - 48;
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if tIndex >= aMaxAnz then return tNumbers; end
|
||
|
|
tIsInNumber = false;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return tNumbers;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
--[[VUHDO_COMBAT_LOG_TRACE = {};
|
||
|
|
local tEntry;
|
||
|
|
function VUHDO_traceCombatLog(anArg1, anArg2, anArg3, anArg4, anArg5, anArg6, anArg7, anArg8, anArg9, anArg10, anArg11, anArg12, anArg13, anArg14)
|
||
|
|
tEntry = "";
|
||
|
|
tEntry = tEntry .. "[1]:" .. (anArg1 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[2]:" .. (anArg2 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[3]:" .. (anArg3 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[4]:" .. (anArg4 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[5]:" .. (anArg5 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[6]:" .. (anArg6 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[7]:" .. (anArg7 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[8]:" .. (anArg8 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[9]:" .. (anArg9 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[10]:" .. (anArg10 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[11]:" .. (anArg11 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[12]:" .. (anArg12 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[13]:" .. (anArg13 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[14]:" .. (anArg14 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[15]:" .. (anArg15 or "<nil>") .. ",";
|
||
|
|
tEntry = tEntry .. "[16]:" .. (anArg16 or "<nil>") .. ",";
|
||
|
|
tinsert(VUHDO_COMBAT_LOG_TRACE, tEntry);
|
||
|
|
end]]
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_tableUniqueAdd(aTable, aValue)
|
||
|
|
for _, tValue in pairs(aTable) do
|
||
|
|
if tValue == aValue then return false; end
|
||
|
|
end
|
||
|
|
|
||
|
|
aTable[#aTable + 1] = aValue;
|
||
|
|
return true;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_tableRemoveValue(aTable, aValue)
|
||
|
|
for tIndex, tValue in pairs(aTable) do
|
||
|
|
if tValue == aValue then tremove(aTable, tIndex); return; end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_tableGetKeyFromValue(aTable, aValue)
|
||
|
|
for tKey, tValue in pairs(aTable) do
|
||
|
|
if tValue == aValue then return tKey; end
|
||
|
|
end
|
||
|
|
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
----------------------------------------------------
|
||
|
|
local VUHDO_RAID_NAMES;
|
||
|
|
local VUHDO_RAID;
|
||
|
|
local VUHDO_UNIT_BUTTONS;
|
||
|
|
local VUHDO_CONFIG;
|
||
|
|
local VUHDO_GROUPS_BUFFS;
|
||
|
|
local VUHDO_BOSS_UNITS;
|
||
|
|
local sRangeSpell;
|
||
|
|
local sIsGuessRange = true;
|
||
|
|
local sScanRange;
|
||
|
|
local sZeroRange = "";
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local VUHDO_updateBouquetsForEvent;
|
||
|
|
function VUHDO_toolboxInitLocalOverrides()
|
||
|
|
VUHDO_RAID_NAMES = _G["VUHDO_RAID_NAMES"];
|
||
|
|
VUHDO_RAID = _G["VUHDO_RAID"];
|
||
|
|
VUHDO_UNIT_BUTTONS = _G["VUHDO_UNIT_BUTTONS"];
|
||
|
|
VUHDO_CONFIG = _G["VUHDO_CONFIG"];
|
||
|
|
VUHDO_GROUPS_BUFFS = _G["VUHDO_GROUPS_BUFFS"];
|
||
|
|
VUHDO_BOSS_UNITS = _G["VUHDO_BOSS_UNITS"];
|
||
|
|
VUHDO_updateBouquetsForEvent = _G["VUHDO_updateBouquetsForEvent"];
|
||
|
|
sScanRange = tonumber(VUHDO_CONFIG["SCAN_RANGE"]);
|
||
|
|
sRangeSpell = VUHDO_CONFIG["RANGE_SPELL"];
|
||
|
|
sIsGuessRange = VUHDO_CONFIG["RANGE_PESSIMISTIC"] or GetSpellInfo(VUHDO_CONFIG["RANGE_SPELL"]) == nil;
|
||
|
|
sZeroRange = "0.0 " .. VUHDO_I18N_YARDS;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
local VUHDO_PROFILE_TIMER;
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_initProfiler()
|
||
|
|
VUHDO_PROFILE_TIMER = GetTime() * 1000;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_seeProfiler()
|
||
|
|
VUHDO_xMsg("D: ", floor(GetTime() * 1000 - VUHDO_PROFILE_TIMER));
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Print chat frame line with no "{Vuhdo} prefix
|
||
|
|
function VUHDO_MsgC(aMessage, aRed, aGreen, aBlue)
|
||
|
|
aRed, aGreen, aBlue = aRed or 1, aGreen or 0.7, aBlue or 0.2;
|
||
|
|
DEFAULT_CHAT_FRAME:AddMessage(aMessage, aRed, aGreen, aBlue);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local function VUHDO_arg2Text(anArg)
|
||
|
|
if anArg == nil then return "<nil>";
|
||
|
|
elseif "function" == type(anArg) then return "<func>";
|
||
|
|
elseif "table" == type(anArg) then return "<table>";
|
||
|
|
elseif "boolean" == type(anArg) then return anArg and "<true>" or "<false>";
|
||
|
|
elseif anArg == "" then return " ";
|
||
|
|
else return anArg; end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Print a standard chat frame
|
||
|
|
function VUHDO_Msg(aMessage, aRed, aGreen, aBlue)
|
||
|
|
VUHDO_MsgC("|cffffe566{VuhDo}|r " .. VUHDO_arg2Text(aMessage), aRed, aGreen, aBlue)
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_xMsg(...)
|
||
|
|
local tText = "";
|
||
|
|
|
||
|
|
for tCnt = 1, select('#', ...) do
|
||
|
|
tText = tText .. tCnt .. "=[" .. VUHDO_arg2Text(select(tCnt, ...)) .. "] ";
|
||
|
|
end
|
||
|
|
VUHDO_MsgC(tText);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_getCurrentGroupType()
|
||
|
|
return IsInRaid() and 2 or IsInGroup() and 1 or 0;
|
||
|
|
end
|
||
|
|
local VUHDO_getCurrentGroupType = VUHDO_getCurrentGroupType;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns unit-prefix, pet-prefix and maximum number of players in a party
|
||
|
|
function VUHDO_getUnitIds()
|
||
|
|
if IsInRaid() then return "raid", "raidpet";
|
||
|
|
elseif IsInGroup() then return "party", "partypet";
|
||
|
|
else return "player", "pet"; end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Extracts unit number from a Unit's name
|
||
|
|
local tUnitNo;
|
||
|
|
function VUHDO_getUnitNo(aUnit)
|
||
|
|
if not aUnit or VUHDO_isSpecialUnit(aUnit) then return 0; end
|
||
|
|
if "player" == aUnit then aUnit = VUHDO_PLAYER_RAID_ID or "player"; end
|
||
|
|
return tonumber(strsub(aUnit, -2, -1)) or tonumber(strsub(aUnit, -1)) or 1;
|
||
|
|
end
|
||
|
|
local VUHDO_getUnitNo = VUHDO_getUnitNo;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns the units subgroup number, or 0 for pets/focus
|
||
|
|
function VUHDO_getUnitGroup(aUnit, anIsPet)
|
||
|
|
if anIsPet or not aUnit or VUHDO_isSpecialUnit(aUnit) then return 0;
|
||
|
|
elseif VUHDO_GROUP_TYPE_RAID == VUHDO_getCurrentGroupType() then
|
||
|
|
return select(3, GetRaidRosterInfo(VUHDO_getUnitNo(aUnit))) or 1;
|
||
|
|
else return 1; end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_isTargetInRange(aUnit)
|
||
|
|
return UnitIsUnit("player", aUnit) or CheckInteractDistance(aUnit, 1);
|
||
|
|
end
|
||
|
|
local VUHDO_isTargetInRange = VUHDO_isTargetInRange;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- FIXME: workaround for Blizzard API bug: https://github.com/Stanzilla/WoWUIBugs/issues/49
|
||
|
|
function VUHDO_unitPhaseReason(aUnit)
|
||
|
|
|
||
|
|
if not aUnit then
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
local tPhaseReason = UnitPhaseReason(aUnit);
|
||
|
|
|
||
|
|
if (tPhaseReason == Enum.PhaseReason.WarMode or tPhaseReason == Enum.PhaseReason.ChromieTime) and UnitIsVisible(aUnit) then
|
||
|
|
return nil;
|
||
|
|
else
|
||
|
|
return tPhaseReason;
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns whether or not a unit is in range
|
||
|
|
function VUHDO_isInRange(aUnit)
|
||
|
|
if "player" == aUnit then
|
||
|
|
return true;
|
||
|
|
elseif VUHDO_isSpecialUnit(aUnit) then
|
||
|
|
return VUHDO_isTargetInRange(aUnit);
|
||
|
|
elseif VUHDO_unitPhaseReason(aUnit) then
|
||
|
|
return false;
|
||
|
|
elseif (sIsGuessRange) then
|
||
|
|
return UnitInRange(aUnit);
|
||
|
|
else
|
||
|
|
local tIsSpellInRange = IsSpellInRange(sRangeSpell, aUnit);
|
||
|
|
|
||
|
|
if tIsSpellInRange ~= nil then
|
||
|
|
return (tIsSpellInRange == 1) and true or false;
|
||
|
|
else
|
||
|
|
return UnitInRange(aUnit);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Parses a aString line into an array of arguments
|
||
|
|
function VUHDO_textParse(aString)
|
||
|
|
aString = strtrim(aString);
|
||
|
|
|
||
|
|
while strfind(aString, " ", 1, true) do
|
||
|
|
aString = gsub(aString, " ", " ");
|
||
|
|
end
|
||
|
|
|
||
|
|
return VUHDO_splitStringQuoted(aString);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Returns a "deep" copy of a table,
|
||
|
|
-- which means containing tables will be copies value-wise, not by reference
|
||
|
|
function VUHDO_deepCopyTable(aTable)
|
||
|
|
local tDestTable = { };
|
||
|
|
|
||
|
|
for tKey, tValue in pairs(aTable) do
|
||
|
|
tDestTable[tKey] = "table" == type(tValue) and VUHDO_deepCopyTable(tValue) or tValue;
|
||
|
|
end
|
||
|
|
|
||
|
|
return tDestTable;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Tokenizes a String into an array of strings, which were delimited by "aChar"
|
||
|
|
function VUHDO_splitString(aText, aChar)
|
||
|
|
return { strsplit(aChar, aText) };
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_splitStringQuoted(aText)
|
||
|
|
|
||
|
|
if VUHDO_strempty(aText) then
|
||
|
|
return { "" };
|
||
|
|
end
|
||
|
|
|
||
|
|
local tSplit = {};
|
||
|
|
local tPrevToken, tQuoteToken;
|
||
|
|
|
||
|
|
for tToken in string.gmatch(aText, "%S+") do
|
||
|
|
local tStartQuote = string.match(tToken, [[^(['"])]]);
|
||
|
|
local tEndQuote = string.match(tToken, [[(['"])$]]);
|
||
|
|
|
||
|
|
if tStartQuote and not tEndQuote and not tQuoteToken then
|
||
|
|
tPrevToken = tToken;
|
||
|
|
tQuoteToken = tStartQuote;
|
||
|
|
elseif tPrevToken and tQuoteToken == tEndQuote then
|
||
|
|
tToken = tPrevToken .. ' ' .. tToken;
|
||
|
|
|
||
|
|
tPrevToken = nil;
|
||
|
|
tQuoteToken = nil;
|
||
|
|
elseif tPrevToken then
|
||
|
|
tPrevToken = tPrevToken .. ' ' .. tToken;
|
||
|
|
end
|
||
|
|
|
||
|
|
if not tPrevToken then
|
||
|
|
tToken = string.gsub(tToken, [[^(['"])]], "");
|
||
|
|
tToken = string.gsub(tToken, [[(['"])$]], "");
|
||
|
|
|
||
|
|
table.insert(tSplit, tToken);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return tSplit;
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
-- returns true if player currently is in a battleground
|
||
|
|
local tType;
|
||
|
|
function VUHDO_isInBattleground()
|
||
|
|
_, tType = IsInInstance();
|
||
|
|
return "pvp" == tType or "arena" == tType;
|
||
|
|
end
|
||
|
|
local VUHDO_isInBattleground = VUHDO_isInBattleground;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns the appropriate addon message channel for player
|
||
|
|
function VUHDO_getAddOnDistribution()
|
||
|
|
return VUHDO_isInBattleground() and "BATTLEGROUND"
|
||
|
|
or VUHDO_GROUP_TYPE_RAID == VUHDO_getCurrentGroupType() and "RAID" or "PARTY";
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns the units rank in a raid which is 0 = raid member, 1 = assist, 2 = leader
|
||
|
|
-- returns 2 if not in raid
|
||
|
|
local tRank, tIsMl, tGroupType;
|
||
|
|
function VUHDO_getUnitRank(aUnit)
|
||
|
|
tGroupType = VUHDO_getCurrentGroupType();
|
||
|
|
if VUHDO_GROUP_TYPE_RAID == tGroupType then
|
||
|
|
_, tRank, _, _, _, _, _, _, _, _, tIsMl = GetRaidRosterInfo(VUHDO_getUnitNo(aUnit));
|
||
|
|
return tRank, tIsMl;
|
||
|
|
elseif VUHDO_GROUP_TYPE_PARTY == tGroupType then return UnitIsGroupLeader(aUnit) and 2 or 0, true;
|
||
|
|
else return 2, true; end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns the players rank in a raid which is 0 = raid member, 1 = assist, 2 = leader
|
||
|
|
-- returns leader if not in raid, and member if solo, as no main tank are needed
|
||
|
|
function VUHDO_getPlayerRank()
|
||
|
|
return VUHDO_getUnitRank("player");
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- returns the raid unit of player eg. "raid13" or "party4"
|
||
|
|
local tRaidUnit;
|
||
|
|
function VUHDO_getPlayerRaidUnit()
|
||
|
|
if VUHDO_GROUP_TYPE_RAID == VUHDO_getCurrentGroupType() then
|
||
|
|
for tCnt = 1, 40 do
|
||
|
|
tRaidUnit = "raid" .. tCnt;
|
||
|
|
if UnitIsUnit("player", tRaidUnit) then return tRaidUnit; end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return "player";
|
||
|
|
end
|
||
|
|
local VUHDO_getPlayerRaidUnit = VUHDO_getPlayerRaidUnit;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_getNumGroupMembers(aGroupId)
|
||
|
|
return #(VUHDO_GROUPS[aGroupId] or sEmpty);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tZone, tIndex, tMap, tMapId, tInfo;
|
||
|
|
function VUHDO_getUnitZoneName(aUnit)
|
||
|
|
tInfo = VUHDO_RAID[aUnit];
|
||
|
|
if not tInfo then return; end
|
||
|
|
|
||
|
|
if "player" == aUnit or tInfo["visible"] then
|
||
|
|
tZone = GetRealZoneText();
|
||
|
|
elseif VUHDO_GROUP_TYPE_RAID == VUHDO_getCurrentGroupType() then
|
||
|
|
tIndex = (VUHDO_RAID[aUnit] or sEmpty)["number"] or 1;
|
||
|
|
_, _, _, _, _, _, tZone = GetRaidRosterInfo(tIndex);
|
||
|
|
else
|
||
|
|
VuhDoScanTooltip:SetOwner(VuhDo, "ANCHOR_NONE");
|
||
|
|
VuhDoScanTooltip:ClearLines();
|
||
|
|
VuhDoScanTooltip:SetUnit(aUnit);
|
||
|
|
|
||
|
|
if VuhDoScanTooltip:NumLines() > 2 then
|
||
|
|
tZone = VuhDoScanTooltipTextLeft3:GetText();
|
||
|
|
end
|
||
|
|
|
||
|
|
if tZone and tZone == "PvP" and VuhDoScanTooltip:NumLines() > 3 then
|
||
|
|
tZone = VuhDoScanTooltipTextLeft4:GetText();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- 8.0.1 build 26567 added restrictions (must be in player's party) on which unit IDs can be queried
|
||
|
|
tMapId = C_Map.GetBestMapForUnit(aUnit);
|
||
|
|
|
||
|
|
if tMapId then
|
||
|
|
tMap = C_Map.GetMapInfo(tMapId);
|
||
|
|
end
|
||
|
|
|
||
|
|
return tZone or (tMap and tMap["name"]) or VUHDO_I18N_UNKNOWN, tMap and tMap["name"] or nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tName, tEnchant;
|
||
|
|
function VUHDO_getWeaponEnchantName(aSlot)
|
||
|
|
VuhDoScanTooltip:SetOwner(VuhDo, "ANCHOR_NONE");
|
||
|
|
VuhDoScanTooltip:ClearLines();
|
||
|
|
VuhDoScanTooltip:SetInventoryItem("player", aSlot);
|
||
|
|
for tCnt = 1, VuhDoScanTooltip:NumLines() do
|
||
|
|
tName = strmatch(_G["VuhDoScanTooltipTextLeft" .. tCnt]:GetText(), "^.+ %(%d+%s+.+%)$");
|
||
|
|
if tName then
|
||
|
|
tEnchant = gsub(tName, " %(.+%)", "");
|
||
|
|
return tEnchant;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return "*";
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_isInSameZone(aUnit)
|
||
|
|
return (VUHDO_RAID[aUnit] or sEmpty)["zone"] == (VUHDO_RAID["player"] or sEmpty)["zone"];
|
||
|
|
end
|
||
|
|
local VUHDO_isInSameZone = VUHDO_isInSameZone;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Returns health of unit info in Percent
|
||
|
|
local tHealthMax;
|
||
|
|
function VUHDO_getUnitHealthPercent(anInfo)
|
||
|
|
tHealthMax = anInfo["healthmax"];
|
||
|
|
return tHealthMax == 0 and 0
|
||
|
|
or anInfo["health"] < tHealthMax and 100 * anInfo["health"] / tHealthMax or 100;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_isSpellKnown(aSpellName)
|
||
|
|
return (type(aSpellName) == "number" and IsSpellKnown(aSpellName))
|
||
|
|
or (type(aSpellName) == "number" and IsPlayerSpell(aSpellName))
|
||
|
|
or GetSpellBookItemInfo(aSpellName) ~= nil
|
||
|
|
or VUHDO_NAME_TO_SPELL[aSpellName] ~= nil and GetSpellBookItemInfo(VUHDO_NAME_TO_SPELL[aSpellName]);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_initTalentSpellCaches()
|
||
|
|
|
||
|
|
local tActiveConfigId = C_ClassTalents.GetActiveConfigID();
|
||
|
|
|
||
|
|
-- on initial PLAYER_ENTER_WORLD talents are not yet available
|
||
|
|
if not tActiveConfigId then
|
||
|
|
return;
|
||
|
|
end
|
||
|
|
|
||
|
|
twipe(VUHDO_TALENT_CACHE_SPELL_ID);
|
||
|
|
twipe(VUHDO_TALENT_CACHE_SPELL_NAME);
|
||
|
|
|
||
|
|
local tConfigInfo = C_Traits.GetConfigInfo(tActiveConfigId);
|
||
|
|
|
||
|
|
for _, tTreeId in pairs(tConfigInfo.treeIDs) do
|
||
|
|
local tTreeNodes = C_Traits.GetTreeNodes(tTreeId);
|
||
|
|
|
||
|
|
for _, tNodeId in pairs(tTreeNodes) do
|
||
|
|
local tNodeInfo = C_Traits.GetNodeInfo(tActiveConfigId, tNodeId);
|
||
|
|
|
||
|
|
if tNodeInfo and tNodeInfo.entryIDsWithCommittedRanks then
|
||
|
|
for _, tEntryId in ipairs(tNodeInfo.entryIDsWithCommittedRanks) do
|
||
|
|
local tEntryInfo = C_Traits.GetEntryInfo(tActiveConfigId, tEntryId);
|
||
|
|
|
||
|
|
if tEntryInfo and tEntryInfo.definitionID then
|
||
|
|
local tDefinitionInfo = C_Traits.GetDefinitionInfo(tEntryInfo.definitionID);
|
||
|
|
|
||
|
|
if tDefinitionInfo and tDefinitionInfo.spellID then
|
||
|
|
local tSpellName = GetSpellInfo(tDefinitionInfo.spellID);
|
||
|
|
|
||
|
|
VUHDO_TALENT_CACHE_SPELL_ID[tDefinitionInfo.spellID] = tSpellName;
|
||
|
|
VUHDO_TALENT_CACHE_SPELL_NAME[tSpellName] = tDefinitionInfo.spellID;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return;
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_getTalentSpellId(aTalentName)
|
||
|
|
|
||
|
|
if type(aTalentName) == "number" then
|
||
|
|
return VUHDO_TALENT_CACHE_SPELL_ID[aTalentName] and aTalentName or nil;
|
||
|
|
else
|
||
|
|
return VUHDO_TALENT_CACHE_SPELL_NAME[aTalentName] or nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_isTalentKnown(aTalentName)
|
||
|
|
return VUHDO_getTalentSpellId(aTalentName) and true or false;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tDeltaSecs;
|
||
|
|
function VUHDO_getDurationTextSince(aStartTime)
|
||
|
|
if not aStartTime then return ""; end
|
||
|
|
|
||
|
|
tDeltaSecs = GetTime() - aStartTime;
|
||
|
|
return tDeltaSecs >= 3600
|
||
|
|
and format("(|cffffffff%.0f:%02d %s|r)", tDeltaSecs / 3600, floor(tDeltaSecs / 60) % 60, VUHDO_I18N_HOURS)
|
||
|
|
or format("(|cffffffff%d:%02d %s|r)", tDeltaSecs / 60, tDeltaSecs % 60, VUHDO_I18N_MINS);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tDistance;
|
||
|
|
function VUHDO_getDistanceText(aUnit)
|
||
|
|
tDistance = VUHDO_getDistanceBetween("player", aUnit);
|
||
|
|
return tDistance ~= nil and tDistance or "player" == aUnit and sZeroRange or VUHDO_I18N_UNKNOWN;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local sTargetUnits = { };
|
||
|
|
function VUHDO_getTargetUnit(aSourceUnit)
|
||
|
|
if not sTargetUnits[aSourceUnit] then
|
||
|
|
sTargetUnits[aSourceUnit] = "player" == aSourceUnit and "target" or aSourceUnit .. "target";
|
||
|
|
end
|
||
|
|
|
||
|
|
return sTargetUnits[aSourceUnit];
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tResurrectionSpells;
|
||
|
|
local tKnownResurrectionSpells;
|
||
|
|
function VUHDO_getResurrectionSpells()
|
||
|
|
tResurrectionSpells = (VUHDO_RESURRECTION_SPELLS[VUHDO_PLAYER_CLASS] or sEmpty)[GetSpecialization() or 0];
|
||
|
|
|
||
|
|
if tResurrectionSpells then
|
||
|
|
tKnownResurrectionSpells = { };
|
||
|
|
|
||
|
|
for _, tResurrectionSpell in ipairs(tResurrectionSpells) do
|
||
|
|
if VUHDO_isSpellKnown(tResurrectionSpell) and IsUsableSpell(tResurrectionSpell) then
|
||
|
|
tinsert(tKnownResurrectionSpells, tResurrectionSpell);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return unpack(tKnownResurrectionSpells);
|
||
|
|
else
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tInfo;
|
||
|
|
function VUHDO_resolveVehicleUnit(aUnit)
|
||
|
|
tInfo = VUHDO_RAID[aUnit] or sEmpty;
|
||
|
|
return tInfo["isPet"] and (VUHDO_RAID[tInfo["ownerUnit"]] or sEmpty)["isVehicle"]
|
||
|
|
and tInfo["ownerUnit"] or aUnit;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_getUnitButtons(aUnit)
|
||
|
|
return VUHDO_UNIT_BUTTONS[aUnit];
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_getUnitButtonsSafe(aUnit)
|
||
|
|
return VUHDO_UNIT_BUTTONS[aUnit] or sEmpty;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_getUnitButtonsPanel(aUnit, aPanelNum)
|
||
|
|
return (VUHDO_UNIT_BUTTONS_PANEL[aUnit] or sEmpty)[aPanelNum] or sEmpty;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tInfo;
|
||
|
|
function VUHDO_shouldScanUnit(aUnit)
|
||
|
|
tInfo = VUHDO_RAID[aUnit] or sEmpty;
|
||
|
|
if not tInfo["connected"] or tInfo["dead"] then return true;
|
||
|
|
elseif sScanRange == 1 then return VUHDO_isInSameZone(aUnit);
|
||
|
|
elseif sScanRange == 2 then return tInfo["visible"];
|
||
|
|
elseif sScanRange == 3 then return tInfo["baseRange"];
|
||
|
|
else return true; end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tNumChars;
|
||
|
|
local tNumCut;
|
||
|
|
local tByte;
|
||
|
|
function VUHDO_utf8Cut(aString, aNumChars)
|
||
|
|
tNumCut = 1;
|
||
|
|
tNumChars = 0;
|
||
|
|
while tNumCut < #aString and tNumChars < aNumChars do
|
||
|
|
tByte = strbyte(aString, tNumCut);
|
||
|
|
|
||
|
|
tNumCut = tNumCut + (
|
||
|
|
tByte < 194 and 1
|
||
|
|
or tByte < 224 and 2
|
||
|
|
or tByte < 240 and 3
|
||
|
|
or tByte < 245 and 4
|
||
|
|
or 1 -- invalid
|
||
|
|
);
|
||
|
|
|
||
|
|
tNumChars = tNumChars + 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
return strsub(aString, 1, tNumCut - 1);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_strempty(aString)
|
||
|
|
if (aString or "") ~= "" then
|
||
|
|
for tCnt = 1, #aString do
|
||
|
|
if strbyte(aString, tCnt) ~= 32 then return false; end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return true;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_tableAddAllKeys(aDestTable, aTableToAdd)
|
||
|
|
for tIndex, tValue in pairs(aTableToAdd) do
|
||
|
|
aDestTable[tIndex] = tValue;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Throttle resetting to current map to avoid conflicts with other addons
|
||
|
|
local tNextTime = 0;
|
||
|
|
local tMap;
|
||
|
|
function VUHDO_setMapToCurrentZone()
|
||
|
|
if tNextTime < GetTime() then
|
||
|
|
tMap = C_Map.GetBestMapForUnit("player");
|
||
|
|
|
||
|
|
if tMap and WorldMapFrame ~= nil then
|
||
|
|
WorldMapFrame:SetMapID(tMap);
|
||
|
|
end
|
||
|
|
|
||
|
|
tNextTime = GetTime() + 2;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
local VUHDO_setMapToCurrentZone = VUHDO_setMapToCurrentZone;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tInfo;
|
||
|
|
function VUHDO_replaceMacroTemplates(aText, aUnit)
|
||
|
|
if aUnit then
|
||
|
|
aText = gsub(aText, "[Vv][Uu][Hh][Dd][Oo]", aUnit);
|
||
|
|
tInfo = VUHDO_RAID[aUnit];
|
||
|
|
if tInfo then
|
||
|
|
aText = gsub(aText, "[Vv][Dd][Nn][Aa][Mm][Ee]", tInfo["name"]);
|
||
|
|
|
||
|
|
if tInfo["petUnit"] then
|
||
|
|
aText = gsub(aText, "[Vv][Dd][Pp][Ee][Tt]", tInfo["petUnit"]);
|
||
|
|
end
|
||
|
|
|
||
|
|
if tInfo["targetUnit"] then
|
||
|
|
aText = gsub(aText, "[Vv][Dd][Tt][Aa][Rr][Gg][Ee][Tt]", tInfo["targetUnit"]);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return aText;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tActionLowerName;
|
||
|
|
local tIsMacroKnown;
|
||
|
|
local tIsSpellKnown;
|
||
|
|
local tIsTalentKnown;
|
||
|
|
function VUHDO_isActionValid(anActionName, anIsCustom, anIsHostile)
|
||
|
|
|
||
|
|
if (anActionName or "") == "" then
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
tActionLowerName = strlower(anActionName);
|
||
|
|
|
||
|
|
if anIsHostile then
|
||
|
|
if (VUHDO_SPELL_KEY_ASSIST == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_FOCUS == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_TARGET == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_EXTRAACTIONBUTTON == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_MOUSELOOK == tActionLowerName) then
|
||
|
|
return VUHDO_I18N_COMMAND, 0.8, 1, 0.8, "CMD";
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if VUHDO_SPELL_KEY_ASSIST == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_FOCUS == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_MENU == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_TELL == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_TARGET == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_EXTRAACTIONBUTTON == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_MOUSELOOK == tActionLowerName
|
||
|
|
or VUHDO_SPELL_KEY_DROPDOWN == tActionLowerName then
|
||
|
|
return VUHDO_I18N_COMMAND, 0.8, 1, 0.8, "CMD";
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
tIsMacroKnown = GetMacroIndexByName(anActionName) ~= 0;
|
||
|
|
tIsSpellKnown = VUHDO_isSpellKnown(anActionName);
|
||
|
|
|
||
|
|
if not tIsSpellKnown then
|
||
|
|
tIsTalentKnown = VUHDO_isTalentKnown(anActionName);
|
||
|
|
end
|
||
|
|
|
||
|
|
if (tIsSpellKnown or tIsTalentKnown) and tIsMacroKnown then
|
||
|
|
VUHDO_Msg(format(VUHDO_I18N_AMBIGUOUS_MACRO, anActionName), 1, 0.3, 0.3);
|
||
|
|
return VUHDO_I18N_WARNING, 1, 0.3, 0.3, "WRN";
|
||
|
|
elseif tIsMacroKnown then
|
||
|
|
return VUHDO_I18N_MACRO, 0.8, 0.8, 1, "MCR";
|
||
|
|
elseif (tIsSpellKnown or tIsTalentKnown) then
|
||
|
|
return VUHDO_I18N_SPELL, 1, 0.8, 0.8, "SPL";
|
||
|
|
elseif IsUsableItem(anActionName) then
|
||
|
|
return VUHDO_I18N_ITEM, 1, 1, 0.8, "ITM";
|
||
|
|
elseif anIsCustom then
|
||
|
|
return "Custom", 0.9, 0.9, 0.2, "CUS";
|
||
|
|
elseif tActionLowerName == "13" then
|
||
|
|
return VUHDO_I18N_TRINKET_1, 1, 1, 0.8, "TKT1";
|
||
|
|
elseif tActionLowerName == "14" then
|
||
|
|
return VUHDO_I18N_TRINKET_2, 1, 1, 0.8, "TKT2";
|
||
|
|
else
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_isAltPowerActive(aUnit)
|
||
|
|
|
||
|
|
local tBarId = UnitPowerBarID(aUnit);
|
||
|
|
local tBarInfo = GetUnitPowerBarInfoByID(tBarId);
|
||
|
|
|
||
|
|
if tBarInfo then
|
||
|
|
return tBarInfo.barType and (not tBarInfo.hideFromOthers or "player" == aUnit);
|
||
|
|
else
|
||
|
|
return false;
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_decompressStringHuffman(aFile)
|
||
|
|
return "string" == type(aFile) and VUHDO_LibCompress:DecompressHuffman(aFile) or aFile;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_compressStringHuffman(aFile)
|
||
|
|
return "string" == type(aFile) and VUHDO_LibCompress:CompressHuffman(aFile) or aFile;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_decompressIfCompressed(aFile)
|
||
|
|
return "string" == type(aFile) and VUHDO_deserializeTable(VUHDO_decompressStringHuffman(aFile)) or aFile;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_decompressOrCopy(aFile)
|
||
|
|
return "string" == type(aFile) and VUHDO_deserializeTable(VUHDO_decompressStringHuffman(aFile)) or VUHDO_deepCopyTable(aFile);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_compressTable(aTable)
|
||
|
|
return type(aTable) == "table" and VUHDO_serializeTable(aTable) or aTable;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_compressAndPackTable(aTable)
|
||
|
|
return type(aTable) == "table" and VUHDO_compressStringHuffman(VUHDO_serializeTable(aTable)) or aTable;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_compressAllBouquets()
|
||
|
|
for tName, _ in pairs(VUHDO_BOUQUETS["STORED"]) do
|
||
|
|
VUHDO_BOUQUETS["STORED"][tName] = VUHDO_compressTable(VUHDO_BOUQUETS["STORED"][tName]);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_decompressAllBouquets()
|
||
|
|
for tName, _ in pairs(VUHDO_BOUQUETS["STORED"]) do
|
||
|
|
VUHDO_BOUQUETS["STORED"][tName] = VUHDO_decompressIfCompressed(VUHDO_BOUQUETS["STORED"][tName]);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tPlayerX, tPlayerY;
|
||
|
|
local tUnitX, tUnitY;
|
||
|
|
local tFacing;
|
||
|
|
local tIsInInstance;
|
||
|
|
function VUHDO_getUnitDirection(aUnit)
|
||
|
|
-- as of patch 7.1 GetPlayerFacing()/GetPlayerMapPosition() do not function inside instances
|
||
|
|
tIsInInstance, _ = IsInInstance();
|
||
|
|
|
||
|
|
if tIsInInstance or (WorldMapFrame ~= nil and WorldMapFrame:IsShown())
|
||
|
|
or (GetMouseFocus() ~= nil and GetMouseFocus():GetName() == nil) then
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
tPlayerX, tPlayerY = VUHDO_getUnitMapPosition("player");
|
||
|
|
if (tPlayerX or 0) + (tPlayerY or 0) <= 0 then
|
||
|
|
VUHDO_setMapToCurrentZone();
|
||
|
|
tPlayerX, tPlayerY = VUHDO_getUnitMapPosition("player");
|
||
|
|
if (tPlayerX or 0) + (tPlayerY or 0) <= 0 then return nil; end
|
||
|
|
end
|
||
|
|
|
||
|
|
tUnitX, tUnitY = VUHDO_getUnitMapPosition(aUnit);
|
||
|
|
if (tUnitX or 0) + (tUnitY or 0) <= 0 then return nil; end
|
||
|
|
|
||
|
|
tFacing = GetPlayerFacing() or 0;
|
||
|
|
tFacing = tFacing < 0 and tFacing + VUHDO_2_PI or tFacing;
|
||
|
|
|
||
|
|
return VUHDO_PI - VUHDO_atan2(tPlayerX - tUnitX, tUnitY - tPlayerY) - tFacing;
|
||
|
|
end
|
||
|
|
local VUHDO_getUnitDirection = VUHDO_getUnitDirection;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
local tDirection;
|
||
|
|
local tConeFactor = 180 / VUHDO_PI;
|
||
|
|
function VUHDO_isInConeInFrontOf(aUnit, aDegrees)
|
||
|
|
if aDegrees >= 360 or "player" == aUnit then return true; end
|
||
|
|
tDirection = VUHDO_getUnitDirection(aUnit);
|
||
|
|
|
||
|
|
if not tDirection then return false;
|
||
|
|
elseif tDirection < 0 then tDirection = tDirection + VUHDO_2_PI; end
|
||
|
|
|
||
|
|
return aDegrees * 0.5 >= 180 - abs(180 - tConeFactor * tDirection);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
--
|
||
|
|
function VUHDO_forceBooleanValue(aRawValue)
|
||
|
|
if aRawValue == nil or aRawValue == 0 or aRawValue == false then return false;
|
||
|
|
else return true; end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_getCurrentKeyModifierString()
|
||
|
|
return format("%s%s%s",
|
||
|
|
IsAltKeyDown() and "alt" or "",
|
||
|
|
IsControlKeyDown() and "ctrl" or "",
|
||
|
|
IsShiftKeyDown() and "shift" or "");
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
-- Helper to serialize a table to a string for pretty printing
|
||
|
|
-- Taken from Lua Users Wiki: http://lua-users.org/wiki/TableUtils
|
||
|
|
function VUHDO_tableValueToString(v)
|
||
|
|
if "string" == type( v ) then
|
||
|
|
v = string.gsub( v, "\n", "\\n" )
|
||
|
|
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
|
||
|
|
return "'" .. v .. "'"
|
||
|
|
end
|
||
|
|
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
|
||
|
|
else
|
||
|
|
return "table" == type( v ) and VUHDO_tableToString( v ) or
|
||
|
|
tostring( v )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_tableKeyToString(k)
|
||
|
|
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
|
||
|
|
return k
|
||
|
|
else
|
||
|
|
return "[" .. VUHDO_tableValueToString( k ) .. "]"
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_tableToString(tbl)
|
||
|
|
local result, done = {}, {}
|
||
|
|
for k, v in ipairs( tbl ) do
|
||
|
|
table.insert( result, VUHDO_tableValueToString( v ) )
|
||
|
|
done[ k ] = true
|
||
|
|
end
|
||
|
|
for k, v in pairs( tbl ) do
|
||
|
|
if not done[ k ] then
|
||
|
|
table.insert( result,
|
||
|
|
VUHDO_tableKeyToString( k ) .. "=" .. VUHDO_tableValueToString( v ) )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return "{" .. table.concat( result, "," ) .. "}"
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_isBossUnit(aUnit)
|
||
|
|
|
||
|
|
return VUHDO_BOSS_UNITS and VUHDO_BOSS_UNITS[aUnit];
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_isSpecialUnit(aUnit)
|
||
|
|
|
||
|
|
return aUnit == "focus" or aUnit == "target" or VUHDO_isBossUnit(aUnit);
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_round(number, digits)
|
||
|
|
|
||
|
|
if digits then
|
||
|
|
local shift = 10 ^ digits;
|
||
|
|
|
||
|
|
return floor(number * shift + 0.5) / shift;
|
||
|
|
else
|
||
|
|
return floor(number + 0.5);
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_unitAura(aUnit, aSpell, aFilter)
|
||
|
|
|
||
|
|
if (aFilter == nil) then
|
||
|
|
aFilter = "HELPFUL";
|
||
|
|
end
|
||
|
|
|
||
|
|
for tCnt = 1, 40 do
|
||
|
|
local tSpellName, tIcon, tCount, tDebuffType, tDuration, tExpirationTime, tSource, tIsStealable, tNameplateShowPersonal, tSpellId, tCanApplyAura, tIsBossDebuff, tNameplateShowAll, tTimeMod, tValue1, tValue2, tValue3 = UnitAura(aUnit, tCnt, aFilter);
|
||
|
|
|
||
|
|
if (aSpell == tSpellName or tonumber(aSpell) == tSpellId) then
|
||
|
|
return tSpellName, tIcon, tCount, tDebuffType, tDuration, tExpirationTime, tSource, tIsStealable, tNameplateShowPersonal, tSpellId, tCanApplyAura, tIsBossDebuff, tNameplateShowAll, tTimeMod, tValue1, tValue2, tValue3;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return nil;
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_unitBuff(aUnit, aSpell)
|
||
|
|
|
||
|
|
return VUHDO_unitAura(aUnit, aSpell, "HELPFUL");
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_unitDebuff(aUnit, aSpell)
|
||
|
|
|
||
|
|
return VUHDO_unitAura(aUnit, aSpell, "HARMFUL");
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function VUHDO_playSoundFile(aSound)
|
||
|
|
|
||
|
|
if (aSound and (aSound == "Interface\\Quiet.ogg" or aSound == "Interface\\Quiet.mp3")) then
|
||
|
|
-- sweep and reset any sound settings referencing the old 'none' LSM default
|
||
|
|
for _, tDebuffInfo in pairs(VUHDO_CONFIG["CUSTOM_DEBUFF"]["STORED_SETTINGS"]) do
|
||
|
|
if (tDebuffInfo["SOUND"] and
|
||
|
|
(tDebuffInfo["SOUND"] == "Interface\\Quiet.ogg" or
|
||
|
|
tDebuffInfo["SOUND"] == "Interface\\Quiet.mp3")) then
|
||
|
|
tDebuffInfo["SOUND"] = nil;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- reset custom debuff default sound if set to old 'none' LSM default
|
||
|
|
if (VUHDO_CONFIG["CUSTOM_DEBUFF"]["SOUND"] and
|
||
|
|
(VUHDO_CONFIG["CUSTOM_DEBUFF"]["SOUND"] == "Interface\\Quiet.ogg" or
|
||
|
|
VUHDO_CONFIG["CUSTOM_DEBUFF"]["SOUND"] == "Interface\\Quiet.mp3")) then
|
||
|
|
VUHDO_CONFIG["CUSTOM_DEBUFF"]["SOUND"] = nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
-- reset standard debuff sound if set to old 'none' LSM default
|
||
|
|
if (VUHDO_CONFIG["SOUND_DEBUFF"] and
|
||
|
|
(VUHDO_CONFIG["SOUND_DEBUFF"] == "Interface\\Quiet.ogg" or
|
||
|
|
VUHDO_CONFIG["SOUND_DEBUFF"] == "Interface\\Quiet.mp3")) then
|
||
|
|
VUHDO_CONFIG["SOUND_DEBUFF"] = nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
-- return success because we've played nothing as requested (eg. Quiet.ogg)
|
||
|
|
return true;
|
||
|
|
end
|
||
|
|
|
||
|
|
local tSuccess, tError = pcall(PlaySoundFile, aSound);
|
||
|
|
|
||
|
|
if not tSuccess then
|
||
|
|
VUHDO_Msg(format(VUHDO_I18N_PLAY_SOUND_FILE_ERR, aSound, tError));
|
||
|
|
end
|
||
|
|
|
||
|
|
return tSuccess;
|
||
|
|
|
||
|
|
end
|
||
|
|
|