diff --git a/DBM-Core/DBM-Core.lua b/DBM-Core/DBM-Core.lua index 1c1f058..837090b 100644 --- a/DBM-Core/DBM-Core.lua +++ b/DBM-Core/DBM-Core.lua @@ -337,6 +337,7 @@ DBM.DefaultOptions = { DontSetIcons = false, DontRestoreIcons = false, DontShowRangeFrame = false, + UseAlternateRangeCheck = false, DontRestoreRange = false, DontShowInfoFrame = false, DontShowHudMap2 = false, diff --git a/DBM-Core/DBM-RangeCheck.lua b/DBM-Core/DBM-RangeCheck.lua index a94eb14..19e9e6b 100644 --- a/DBM-Core/DBM-RangeCheck.lua +++ b/DBM-Core/DBM-RangeCheck.lua @@ -581,10 +581,10 @@ do elseif level == 2 then if menu == "range" then - local ranges = { 5, 6, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 30, 35, 40 } - - for _, r in pairs(ranges) do - if initRangeCheck(r) then + pX, pY = GetPlayerMapPosition("player") + if pX == 0 and pY == 0 then -- если координаты 0.0, добавим дальности из списка предметов + local ranges = { 5, 10, 11, 13, 16, 20, 30, 35, 48 } + for _, r in pairs(ranges) do info = UIDropDownMenu_CreateInfo() info.text = L.RANGECHECK_SETRANGE_TO:format(r) info.func = setRange @@ -592,8 +592,19 @@ do info.checked = (frame.range == r) UIDropDownMenu_AddButton(info, 2) end + else + local ranges = { 5, 6, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 30, 35, 40 } + for _, r in pairs(ranges) do + if initRangeCheck(r) then -- этот чек всегда возвращает false, если координаты 0.0 + info = UIDropDownMenu_CreateInfo() + info.text = L.RANGECHECK_SETRANGE_TO:format(r) + info.func = setRange + info.arg1 = r + info.checked = (frame.range == r) + UIDropDownMenu_AddButton(info, 2) + end -- и поэтому список дальностей пустой + end end - elseif menu == "sounds" then info = UIDropDownMenu_CreateInfo() info.text = L.RANGECHECK_SOUND_OPTION_1 @@ -932,7 +943,70 @@ function onUpdate(self, elapsed) end end else - self:AddLine(L.RANGE_CHECK_ZONE_UNSUPPORTED:format(self.range)) + if GetNumRaidMembers() > 0 then + for i = 1, GetNumRaidMembers() do + local uId = "raid" .. i + if not frame.reverse and not UnitIsUnit(uId, "player") and + not UnitIsDeadOrGhost(uId) and + self.checkFunc(uId, self.range) and + (not self.filter or self.filter(uId)) then + j = j + 1 + color = RAID_CLASS_COLORS[select(2, UnitClass(uId))] or NORMAL_FONT_COLOR + local icon = GetRaidTargetIndex(uId) + local text = icon and ("|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_%d:0|t %s"):format(icon, UnitName(uId)) + or UnitName(uId) + self:AddLine(text, color.r, color.g, color.b) + if j >= 5 then + break + end + elseif frame.reverse and not UnitIsUnit(uId, "player") and + not UnitIsDeadOrGhost(uId) and + not self.checkFunc(uId, self.range) and + (not self.filter or self.filter(uId)) then + j = j + 1 + color = RAID_CLASS_COLORS[select(2, UnitClass(uId))] or NORMAL_FONT_COLOR + local icon = GetRaidTargetIndex(uId) + local text = icon and ("|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_%d:0|t %s"):format(icon, UnitName(uId)) + or UnitName(uId) + self:AddLine(text, color.r, color.g, color.b) + if j >= 5 then + break + end + end + end + elseif GetNumPartyMembers() > 0 then + for i = 1, GetNumPartyMembers() do + local uId = "party" .. i + if not frame.reverse and not UnitIsUnit(uId, "player") and + not UnitIsDeadOrGhost(uId) and + self.checkFunc(uId, self.range) and + (not self.filter or self.filter(uId)) then + j = j + 1 + color = RAID_CLASS_COLORS[select(2, UnitClass(uId))] or NORMAL_FONT_COLOR + local icon = GetRaidTargetIndex(uId) + local text = icon and ("|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_%d:0|t %s"):format(icon, UnitName(uId)) + or UnitName(uId) + self:AddLine(text, color.r, color.g, color.b) + if j >= 5 then + break + end + elseif frame.reverse and not UnitIsUnit(uId, "player") and + not UnitIsDeadOrGhost(uId) and + not self.checkFunc(uId, self.range) and + (not self.filter or self.filter(uId)) then + j = j + 1 + color = RAID_CLASS_COLORS[select(2, UnitClass(uId))] or NORMAL_FONT_COLOR + local icon = GetRaidTargetIndex(uId) + local text = icon and ("|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_%d:0|t %s"):format(icon, UnitName(uId)) + or UnitName(uId) + self:AddLine(text, color.r, color.g, color.b) + if j >= 5 then + break + end + end + end + end + --self:AddLine(L.RANGE_CHECK_ZONE_UNSUPPORTED:format(self.range)) end soundUpdate = soundUpdate + elapsed if soundUpdate >= 5 and j > 0 then @@ -1090,7 +1164,6 @@ do end) end end - for i = 1, numPlayers do local uId = unitID:format(i) if not UnitIsUnit(uId, "player") then @@ -1152,16 +1225,24 @@ do if isInSupportedArea then -- we were in an area with known map dimensions during the last update but looks like we left it isInSupportedArea = false - -- white frame - radarFrame.circle:SetVertexColor(1, 1, 1) - -- hide everything - for _, v in pairs(dots) do - v.dot:Hide() - end - for i = 1, 8 do - charms[i]:Hide() - end end + -- Вместо серого радара показываем текстовый фрейм + setFrames(self, "text") + DBM:AddMsg(L.NO_RANGE) + return + -- if isInSupportedArea then + -- -- we were in an area with known map dimensions during the last update but looks like we left it + -- isInSupportedArea = false + -- -- white frame + -- radarFrame.circle:SetVertexColor(1, 1, 1) + -- -- hide everything + -- for _, v in pairs(dots) do + -- v.dot:Hide() + -- end + -- for i = 1, 8 do + -- charms[i]:Hide() + -- end + -- end end end end @@ -1186,8 +1267,74 @@ end local getDistanceBetween do local mapSizes = DBM.MapSizes + -- Две следующие таблицы позаимствованы с DBM с ретейла + -- https://github.com/DeadlyBossMods/DBM-Retail/blob/9.0.21/DBM-Core/DBM-RangeCheck.lua#L57 + -- Расстояния для проверки через предметы + -- [метров] = itemID + + local itemRanges = { + [5] = 37727, -- Рубиновый желудь + [10] = 34368, -- Настроенные кристаллы-сердечники + [13] = 32321, -- Сеть для ловли скальной пустельги + [16] = 1251, -- Льняные бинты + [20] = 21519, -- Омела + [24] = 31463, -- Кристалл Зеззака + [30] = 34191, -- Горсть снежинок + [35] = 18904, -- Ультрасжиматель Зорбина + [48] = 32698, -- Веревочный аркан + [61] = 32825, -- Пушка души + [77] = 35278, -- Укрепленная сеть + } + + for _, itemId in pairs(itemRanges) do + GetItemInfo(itemId) -- получаем данные о предмете, чтобы он был в кэше и IsItemInRange не возвращал nil + end + + -- Расстояния для проверки через функции api: + -- [метров] = distIndex + -- https://wowpedia.fandom.com/wiki/API_CheckInteractDistance + local apiRanges = { + [10] = 3, -- CheckInteractDistance (Дуэль) + [11] = 2, -- CheckInteractDistance (Обмен) + [30] = 1, -- CheckInteractDistance (Осмотр) + } + + -- собственно, сама проверка с ритейл дбма + -- название, переводящееся как "это снова БК" говорит о многом... + function itsBCAgain(uId, checkrange) + if checkrange then -- в этой ветке возвращается true или false, что нам не подходит + if itemRanges[checkrange] then -- Only query item range for requested active range check + return IsItemInRange(itemRanges[checkrange], uId) and checkrange or 1000 + elseif apiRanges[checkrange] then -- Only query item range for requested active range if no item found for it + return CheckInteractDistance(uId, apiRanges[checkrange]) and checkrange or 1000 + else + return 1000 -- Если ни одна проверка не подходит, просто вернем очень большое значение, чтобы точно было false в mapRangeCheck + end + else -- используем только эту часть, так как нам нужно вернуть числовое значение + -- ID и дистанции взяты с таблиц выше + if IsItemInRange(37727, uId) == 1 then return 5 + -- нужен предмет с рейндж 8, часто встречающаяся дальность на механиках + elseif IsItemInRange(34368, uId) == 1 then return 10 + elseif CheckInteractDistance(uId, 3) == 1 then return 10 + elseif CheckInteractDistance(uId, 2) == 1 then return 11 + elseif IsItemInRange(32321, uId) == 1 then return 13 + elseif IsItemInRange(1251, uId) == 1 then return 16 + elseif IsItemInRange(21519, uId) == 1 then return 20 + elseif IsItemInRange(31463, uId) == 1 then return 24 + elseif CheckInteractDistance(uId, 1) == 1 then return 30 + elseif IsItemInRange(18904, uId) == 1 then return 35 + elseif IsItemInRange(32698, uId) == 1 then return 48 + elseif IsItemInRange(32825, uId) == 1 then return 61 + elseif IsItemInRange(35278, uId) == 1 then return 77 -- макс дальность, после нее IsItemInRange возвращает nil, так как юнит слишком далеко + else return 1000 end -- Если ни одна проверка не подходит, просто вернем очень большое значение, чтобы точно было false в mapRangeCheck + end + end function getDistanceBetween(uId, x, y) + if x == 0 and y == 0 then -- Используем проверку через предметы + --print("Расстояние до "..uId.." = "..itsBCAgain(uId)) + return itsBCAgain(uId) + end if not x then -- If only one arg then 2nd arg is always assumed to be player x, y = GetPlayerMapPosition("player") end @@ -1228,6 +1375,9 @@ do if pX == 0 and pY == 0 then SetMapToCurrentZone() pX, pY = GetPlayerMapPosition("player") + if pX == 0 and pY == 0 then -- координат все еще нет, значит все очень плохо (или мы на Джайне) и надо проверять через предметы и интеракты + return false + end end local levels = mapSizes[GetMapInfo()] if not levels then @@ -1359,6 +1509,7 @@ function rangeCheck:Show(range, filter, bossUnit, reverse) local level = GetCurrentMapDungeonLevel() local usesTerrainMap = DungeonUsesTerrainMap() level = usesTerrainMap and level - 1 or level + --[[ Предыдущий вариант if DBM.Options.RangeFrameFrames == "text" or DBM.Options.RangeFrameFrames == "both" or not DBM.MapSizes[mapName] or (DBM.MapSizes[mapName] and not DBM.MapSizes[mapName][level]) then frame:Show() @@ -1369,6 +1520,22 @@ function rangeCheck:Show(range, filter, bossUnit, reverse) (DBM.MapSizes[mapName] and DBM.MapSizes[mapName][level]) then onUpdateRadar(radarFrame, 1) end + ]] + + if (DBM.MapSizes[mapName] and DBM.MapSizes[mapName][level]) or DBM.Options["UseAlternateRangeCheck"] then + if DBM.Options.RangeFrameFrames == "text" or DBM.Options.RangeFrameFrames == "both" then + frame:Show() + frame:SetOwner(UIParent, "ANCHOR_PRESERVE") + onUpdate(frame, 0) + end + if DBM.Options.RangeFrameFrames == "radar" or DBM.Options.RangeFrameFrames == "both" then + onUpdateRadar(radarFrame, 1) + end + else + DBM:AddMsg(L.RANGE_CHECK_USE_ALTERNATIVE) + -- todo coalaboooy + -- добавить фрейм, аналогичный текстовому фрейму проверки, чтобы юзер видел на экране, что надо включить альтернативную проверку + end end -- todo fxpw diff --git a/DBM-Core/core_locales/enUS.lua b/DBM-Core/core_locales/enUS.lua index e389991..365ebd8 100644 --- a/DBM-Core/core_locales/enUS.lua +++ b/DBM-Core/core_locales/enUS.lua @@ -194,6 +194,7 @@ L.RANGERADAR_BOSS_HEADER = "Boss Range (%d yd)" L.RANGERADAR_IN_RANGE_TEXT = "%d in range (%d yd)"--Multi L.RANGERADAR_IN_RANGE_TEXTONE = "%s (%0.1f yd)"--One target L.RANGE_CHECK_ZONE_UNSUPPORTED = "A %d yard range check is not supported in this zone.\nSupported ranges are 10, 11, 15 and 28 yard." +L.RANGE_CHECK_USE_ALTERNATIVE = "Range check unsupported in this zone. Use \"Rangeframe\" -> \"Use alternate range check\" option." L.LOCK_FRAME = "Frame Locked" L.INFOFRAME_SHOW_SELF = "Always show your power" -- Always show your own power value even if you are below the threshold diff --git a/DBM-Core/core_locales/ruRU.lua b/DBM-Core/core_locales/ruRU.lua index 5868f1e..fc593da 100644 --- a/DBM-Core/core_locales/ruRU.lua +++ b/DBM-Core/core_locales/ruRU.lua @@ -272,6 +272,7 @@ L.RANGERADAR_IN_RANGE_TEXT = "%d в радиусе (%0.1fм)" L.RANGECHECK_IN_RANGE_TEXT = "%d в радиусе" --Text based doesn't need (%dyd), especially since it's not very accurate to the specific yard anyways L.RANGERADAR_IN_RANGE_TEXTONE = "%s (%0.1fм)" --One target L.RANGE_CHECK_ZONE_UNSUPPORTED = "Проверка дистанции %d м. недоступна в этой зоне.\nДоступные дистанции - 10, 11, 15 и 28 м." +L.RANGE_CHECK_USE_ALTERNATIVE = "Проверка дистанции недоступна в этой зоне. Используйте опцию \"Дистанция\" -> \"Включить альтернативную проверку дистанции\"." L.LOCK_FRAME = "Закрепить окно" L.INFOFRAME_SHOW_SELF = "Всегда показывать Вашу энергию" -- Always show your own power value even if you are below the threshold diff --git a/DBM-GUI/locales/enUS.lua b/DBM-GUI/locales/enUS.lua index 5e77a41..71439bc 100644 --- a/DBM-GUI/locales/enUS.lua +++ b/DBM-GUI/locales/enUS.lua @@ -423,6 +423,7 @@ L.SpamBlockNoCountdowns = "Do not play countdown sounds" L.Area_SpamFilter_Misc = "Misc Global Disable & Filter Options" L.SpamBlockNoSetIcon = "Do not set icons on targets" L.SpamBlockNoRangeFrame = "Do not show range frame" +L.UseAlternateRangeCheck = "Use alternate range check if the standart doesn't work. |cffff1919WARNING!|r This option makes check less accurate and works only with text frame, but works in every zone, e.g. Jaina in ICC25 Heroic." L.SpamBlockNoInfoFrame = "Do not show info frame" L.SpamBlockNoHudMap = "Do not show HudMap" L.SpamBlockNoNameplate = "Do not show Nameplate Auras" diff --git a/DBM-GUI/locales/ruRU.lua b/DBM-GUI/locales/ruRU.lua index d6c07ad..2cb4e5c 100644 --- a/DBM-GUI/locales/ruRU.lua +++ b/DBM-GUI/locales/ruRU.lua @@ -350,6 +350,7 @@ L.SpamBlockNoCountdowns = "Не воспроизводить звуки обр L.Area_SpamFilter_Misc = "Разное глобальное отключение и параметры фильтра" L.SpamBlockNoSetIcon = "Не устанавливать метки на цели" L.SpamBlockNoRangeFrame = "Не показывать окно проверки дистанции" +L.UseAlternateRangeCheck = "Включить альтернативную проверку дистанции, если стандартная недоступна. |cffff1919ВНИМАНИЕ!|r Проверка менее точная, и может использоваться только с текстовым окном проверки дистанции, но работает в любых зонах, например на Джайне в ЦЛК 25 гер." L.SpamBlockNoInfoFrame = "Не показывать информационное окно" L.SpamBlockNoHudMap = "Не показывать HudMap" L.SpamBlockNoNameplate = "Не показывать Nameplate Auras (отключает полностью)" diff --git a/DBM-GUI/modules/options/frames/Range.lua b/DBM-GUI/modules/options/frames/Range.lua index eb32dce..6fa92a6 100644 --- a/DBM-GUI/modules/options/frames/Range.lua +++ b/DBM-GUI/modules/options/frames/Range.lua @@ -4,3 +4,4 @@ local panel = DBM_GUI.Cat_Frames:CreateNewPanel(L.Panel_Range, "option") local general = panel:CreateArea(L.Area_General) general:CreateCheckButton(L.SpamBlockNoRangeFrame, true, nil, "DontShowRangeFrame") +general:CreateCheckButton(L.UseAlternateRangeCheck, true, nil, "UseAlternateRangeCheck") \ No newline at end of file