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.
2561 lines
79 KiB
2561 lines
79 KiB
local GlobalAddonName, ExRT = ...
|
|
|
|
ExRT.F.FUNC_FILE_LOADED = true
|
|
|
|
local UnitName, GetTime, GetCursorPosition, UnitIsUnit = UnitName, GetTime, GetCursorPosition, UnitIsUnit
|
|
local select, floor, tonumber, tostring, string_sub, string_find, string_len, bit_band, type, unpack, pairs, format, strsplit = select, floor, tonumber, tostring, string.sub, string.find, string.len, bit.band, type, unpack, pairs, format, strsplit
|
|
local string_gsub, string_match = string.gsub, string.match
|
|
local RAID_CLASS_COLORS, COMBATLOG_OBJECT_TYPE_MASK, COMBATLOG_OBJECT_CONTROL_MASK, COMBATLOG_OBJECT_REACTION_MASK, COMBATLOG_OBJECT_AFFILIATION_MASK, COMBATLOG_OBJECT_SPECIAL_MASK = RAID_CLASS_COLORS, COMBATLOG_OBJECT_TYPE_MASK, COMBATLOG_OBJECT_CONTROL_MASK, COMBATLOG_OBJECT_REACTION_MASK, COMBATLOG_OBJECT_AFFILIATION_MASK, COMBATLOG_OBJECT_SPECIAL_MASK
|
|
local UnitGroupRolesAssigned = UnitGroupRolesAssigned or ExRT.NULLfunc
|
|
local GetRaidRosterInfo = GetRaidRosterInfo
|
|
local GetItemInfo, GetItemInfoInstant = C_Item and C_Item.GetItemInfo or GetItemInfo, C_Item and C_Item.GetItemInfoInstant or GetItemInfoInstant
|
|
|
|
do
|
|
local antiSpamArr = {}
|
|
function ExRT.F.AntiSpam(numantispam,addtime)
|
|
local t = GetTime()
|
|
if not antiSpamArr[numantispam] or antiSpamArr[numantispam] < t then
|
|
antiSpamArr[numantispam] = t + addtime
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
function ExRT.F.ResetAntiSpam(numantispam)
|
|
antiSpamArr[numantispam] = nil
|
|
end
|
|
end
|
|
|
|
do
|
|
--Used GLOBALS: CUSTOM_CLASS_COLORS
|
|
|
|
local classColorArray = nil
|
|
function ExRT.F.classColor(class)
|
|
classColorArray = type(CUSTOM_CLASS_COLORS)=="table" and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
|
|
if classColorArray and classColorArray.colorStr then
|
|
return classColorArray.colorStr
|
|
else
|
|
return "ffbbbbbb"
|
|
end
|
|
end
|
|
|
|
function ExRT.F.classColorNum(class)
|
|
classColorArray = type(CUSTOM_CLASS_COLORS)=="table" and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
|
|
if classColorArray then
|
|
return classColorArray.r,classColorArray.g,classColorArray.b
|
|
else
|
|
return 0.8,0.8,0.8
|
|
end
|
|
end
|
|
|
|
function ExRT.F.classColorByGUID(guid)
|
|
local class,_ = ""
|
|
if guid and guid ~= "" and guid ~= "0000000000000000" then
|
|
_,class = GetPlayerInfoByGUID(guid)
|
|
end
|
|
return ExRT.F.classColor(class)
|
|
end
|
|
end
|
|
|
|
function ExRT.F.clearTextTag(text,SpellLinksEnabled)
|
|
if text then
|
|
text = string_gsub(text,"|c........","")
|
|
text = string_gsub(text,"|r","")
|
|
text = string_gsub(text,"|T.-:0|t ","")
|
|
text = string_gsub(text,"|HExRT:.-|h(.-)|h","%1")
|
|
if SpellLinksEnabled then
|
|
text = string_gsub(text,"|H(spell:.-)|h(.-)|h","|cff71d5ff|H%1|h[%2]|h|r")
|
|
else
|
|
text = string_gsub(text,"|H(spell:.-)|h(.-)|h","%2")
|
|
end
|
|
return text
|
|
end
|
|
end
|
|
|
|
function ExRT.F.splitLongLine(text,maxLetters,SpellLinksEnabled)
|
|
maxLetters = maxLetters or 250
|
|
local result = {}
|
|
repeat
|
|
local lettersNow = maxLetters
|
|
if SpellLinksEnabled then
|
|
local lastC = 0
|
|
local lastR = 0
|
|
for i=1,(maxLetters-1) do
|
|
local word = string.sub(text,i,i+1)
|
|
if word == "|c" then
|
|
lastC = i
|
|
elseif word == "|r" then
|
|
lastR = i
|
|
end
|
|
end
|
|
if lastC > 0 and lastC > lastR then
|
|
lettersNow = lastC - 1
|
|
end
|
|
end
|
|
|
|
local utf8pos = 1
|
|
local textLen = string.len(text)
|
|
while true do
|
|
local char = string.sub(text,utf8pos,utf8pos)
|
|
local c = char:byte()
|
|
|
|
local lastPos = utf8pos
|
|
|
|
if c > 0 and c <= 127 then
|
|
utf8pos = utf8pos + 1
|
|
elseif c >= 194 and c <= 223 then
|
|
utf8pos = utf8pos + 2
|
|
elseif c >= 224 and c <= 239 then
|
|
utf8pos = utf8pos + 3
|
|
elseif c >= 240 and c <= 244 then
|
|
utf8pos = utf8pos + 4
|
|
else
|
|
utf8pos = utf8pos + 1
|
|
end
|
|
|
|
if utf8pos > lettersNow then
|
|
lettersNow = lastPos - 1
|
|
break
|
|
elseif utf8pos >= textLen then
|
|
break
|
|
end
|
|
end
|
|
result[#result + 1] = string.sub(text,1,lettersNow)
|
|
text = string.sub(text,lettersNow+1)
|
|
until string.len(text) < maxLetters
|
|
if string.len(text) > 0 then
|
|
result[#result + 1] = text
|
|
end
|
|
return unpack(result)
|
|
end
|
|
|
|
function ExRT.F:SetScaleFix(scale)
|
|
local l = self:GetLeft()
|
|
local t = self:GetTop()
|
|
local s = self:GetScale()
|
|
if not l or not t or not s then return end
|
|
|
|
s = scale / s
|
|
|
|
self:SetScale(scale)
|
|
local f = self:GetScript("OnDragStop")
|
|
|
|
self:ClearAllPoints()
|
|
self:SetPoint("TOPLEFT",UIParent,"BOTTOMLEFT",l / s,t / s)
|
|
|
|
if f then f(self) end
|
|
end
|
|
|
|
function ExRT.F:SetScaleFixTR(scale)
|
|
--local l = self:GetLeft() + self:GetWidth() * self:GetEffectiveScale()
|
|
local l = self:GetRight()
|
|
local t = self:GetTop()
|
|
local s = self:GetScale()
|
|
if not l or not t or not s then return end
|
|
|
|
s = scale / s
|
|
|
|
self:SetScale(scale)
|
|
local f = self:GetScript("OnDragStop")
|
|
|
|
self:ClearAllPoints()
|
|
self:SetPoint("TOPRIGHT",UIParent,"BOTTOMLEFT",l / s,t / s)
|
|
|
|
if f then f(self) end
|
|
end
|
|
|
|
function ExRT.F:GetCursorPos()
|
|
local x_f,y_f = GetCursorPosition()
|
|
local s = self.GetEffectiveScale and self:GetEffectiveScale() or self:GetParent():GetEffectiveScale()
|
|
x_f, y_f = x_f/s, y_f/s
|
|
local x,y = self:GetLeft(),self:GetTop()
|
|
x = x_f-x
|
|
y = (y_f-y)*(-1)
|
|
return x,y
|
|
end
|
|
|
|
do
|
|
local function FindAllParents(self,obj)
|
|
while obj do
|
|
if obj == self then
|
|
return true
|
|
end
|
|
obj = obj:GetParent()
|
|
end
|
|
end
|
|
function ExRT.F:IsInFocus(x,y,childs)
|
|
if not x then
|
|
x,y = ExRT.F.GetCursorPos(self)
|
|
end
|
|
local obj
|
|
if GetMouseFoci then
|
|
obj = GetMouseFoci()[1]
|
|
else
|
|
obj = GetMouseFocus()
|
|
end
|
|
if x > 0 and y > 0 and x < self:GetWidth() and y < self:GetHeight() and (obj == self or (childs and FindAllParents(self,obj))) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F:LockMove(isLocked,touchTexture,dontTouchMouse)
|
|
if isLocked then
|
|
if touchTexture then touchTexture:SetColorTexture(0,0,0,0.3) end
|
|
self:SetMovable(true)
|
|
if not dontTouchMouse then self:EnableMouse(true) end
|
|
else
|
|
if touchTexture then touchTexture:SetColorTexture(0,0,0,0) end
|
|
self:SetMovable(false)
|
|
if not dontTouchMouse then self:EnableMouse(false) end
|
|
end
|
|
end
|
|
|
|
local MAX_RAID_GROUP = 5
|
|
if ExRT.isClassic and not ExRT.isBC then
|
|
MAX_RAID_GROUP = 8
|
|
end
|
|
local DIFF_TO_MAX_GROUP = {
|
|
[8] = 1, --party mythic
|
|
[1] = 1, --party normal
|
|
[2] = 1, --party hc
|
|
[14] = 6, --raid normal
|
|
[15] = 6, --raid hc
|
|
[16] = 4, --raid mythic
|
|
[3] = 2, --10ppl
|
|
[5] = 2, --10ppl
|
|
[9] = 8, --40ppl
|
|
[186] = 8, --classic 40ppl
|
|
[148] = 4, --classic 20ppl
|
|
[185] = 4, --classic 20ppl
|
|
[175] = 2, --bc 10ppl
|
|
[176] = 5, --bc 25ppl
|
|
[151] = 6, --lfr
|
|
[17] = 6, --lfr
|
|
[7] = 5, --lfr [legacy]
|
|
[33] = 6, --timewalk raid
|
|
[18] = 8, --event 40ppl
|
|
[193] = 2, --10ppl hc
|
|
[194] = 5, --25ppl hc
|
|
}
|
|
function ExRT.F.GetRaidDiffMaxGroup()
|
|
local _,instance_type,difficulty = GetInstanceInfo()
|
|
if (instance_type == "party" or instance_type == "scenario") and not IsInRaid() then
|
|
return 1
|
|
elseif instance_type ~= "raid" then
|
|
return 8
|
|
elseif difficulty and DIFF_TO_MAX_GROUP[difficulty] then
|
|
return DIFF_TO_MAX_GROUP[difficulty]
|
|
else
|
|
return MAX_RAID_GROUP
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GetDifficultyForCooldownReset()
|
|
local _,_,difficulty = GetInstanceInfo()
|
|
if difficulty == 3 or difficulty == 4 or difficulty == 5 or difficulty == 6 or difficulty == 7 or difficulty == 14 or difficulty == 15 or difficulty == 16 or difficulty == 17 or (ExRT.isLK and (difficulty == 175 or difficulty == 176 or difficulty == 193 or difficulty == 194)) then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function ExRT.F.Round(i)
|
|
return floor(i+0.5)
|
|
end
|
|
|
|
function ExRT.F.NumberInRange(i,mi,mx,incMi,incMx)
|
|
if i and ((incMi and i >= mi) or (not incMi and i > mi)) and ((incMx and i <= mx) or (not incMx and i < mx)) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
function ExRT.F.delUnitNameServer(unitName)
|
|
unitName = strsplit("-",unitName)
|
|
return unitName
|
|
end
|
|
|
|
function ExRT.F.UnitCombatlogname(unit)
|
|
local name,server = UnitName(unit or "?")
|
|
if name and server and server~="" then
|
|
name = name .. "-" .. server
|
|
end
|
|
return name
|
|
end
|
|
|
|
do
|
|
local old_types = {
|
|
Player = 0,
|
|
Creature = 3,
|
|
Pet = 4,
|
|
Vehicle = 5,
|
|
GameObject = 6, --NEW
|
|
Vignette = 7, --NEW
|
|
Item = 8, --NEW Item:976:0:4000000003A91C1A
|
|
Uniq = 9, --NEW
|
|
}
|
|
function ExRT.F.GetUnitTypeByGUID(guid)
|
|
if guid then
|
|
local _type = string_match(guid,"^([A-z]+)%-")
|
|
if _type then
|
|
return old_types[_type]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.UnitIsPlayerOrPet(guid)
|
|
local id = ExRT.F.GetUnitTypeByGUID(guid)
|
|
if id == 0 or id == 4 then
|
|
return true
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GetUnitInfoByUnitFlag(unitFlag,infoType)
|
|
--> TYPE
|
|
if infoType == 1 then
|
|
return bit_band(unitFlag,COMBATLOG_OBJECT_TYPE_MASK)
|
|
--[1024]="player", [2048]="NPC", [4096]="pet", [8192]="GUARDIAN", [16384]="OBJECT"
|
|
|
|
--> CONTROL
|
|
elseif infoType == 2 then
|
|
return bit_band(unitFlag,COMBATLOG_OBJECT_CONTROL_MASK)
|
|
--[256]="by players", [512]="by NPC",
|
|
|
|
--> REACTION
|
|
elseif infoType == 3 then
|
|
return bit_band(unitFlag,COMBATLOG_OBJECT_REACTION_MASK)
|
|
--[16]="FRIENDLY", [32]="NEUTRAL", [64]="HOSTILE"
|
|
|
|
--> Controller affiliation
|
|
elseif infoType == 4 then
|
|
return bit_band(unitFlag,COMBATLOG_OBJECT_AFFILIATION_MASK)
|
|
--[1]="player", [2]="PARTY", [4]="RAID", [8]="OUTSIDER"
|
|
|
|
--> Special
|
|
elseif infoType == 5 then
|
|
return bit_band(unitFlag,COMBATLOG_OBJECT_SPECIAL_MASK)
|
|
--Not all ! [65536]="TARGET", [131072]="FOCUS", [262144]="MAINTANK", [524288]="MAINASSIST"
|
|
end
|
|
end
|
|
|
|
function ExRT.F.UnitIsFriendlyByUnitFlag(unitFlag)
|
|
if ExRT.F.GetUnitInfoByUnitFlag(unitFlag,2) == 256 then
|
|
return true
|
|
end
|
|
end
|
|
|
|
function ExRT.F.UnitIsFriendlyByUnitFlag2(unitFlag)
|
|
local reaction = ExRT.F.GetUnitInfoByUnitFlag(unitFlag or 0,3)
|
|
if reaction == 16 then
|
|
return true
|
|
elseif reaction == 32 then
|
|
if ExRT.F.GetUnitInfoByUnitFlag(unitFlag,2) == 256 then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.dprint(...)
|
|
return nil
|
|
end
|
|
function ExRT.F.dtime(...)
|
|
return nil
|
|
end
|
|
if ExRT.isDev then --debug or debug ultra
|
|
ExRT.F.dprint = function(...)
|
|
print(...)
|
|
end
|
|
local debugprofilestop = debugprofilestop
|
|
local lastTime = nil
|
|
ExRT.F.dtime = function(arg,...)
|
|
if arg and lastTime then
|
|
arg[#arg+1] = {debugprofilestop() - lastTime,...}
|
|
else
|
|
lastTime = debugprofilestop()
|
|
end
|
|
end
|
|
end
|
|
|
|
local GetSpellLink = C_Spell and C_Spell.GetSpellLink or GetSpellLink
|
|
function ExRT.F.LinkSpell(SpellID,SpellLink)
|
|
if not SpellLink then
|
|
SpellLink = GetSpellLink(SpellID)
|
|
end
|
|
if SpellLink then
|
|
if ChatEdit_GetActiveWindow() then
|
|
ChatEdit_InsertLink(SpellLink)
|
|
else
|
|
ChatFrame_OpenChat(SpellLink)
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.LinkItem(itemID, itemLink)
|
|
if not itemLink then
|
|
if not itemID then
|
|
return
|
|
end
|
|
itemLink = select(2,GetItemInfo(itemID))
|
|
end
|
|
if not itemLink then
|
|
return
|
|
end
|
|
if IsModifiedClick("DRESSUP") then
|
|
return DressUpItemLink(itemLink)
|
|
else
|
|
if ChatEdit_GetActiveWindow() then
|
|
ChatEdit_InsertLink(itemLink)
|
|
else
|
|
ChatFrame_OpenChat(itemLink)
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.shortNumber(num)
|
|
if num < 1000 then
|
|
return tostring(num)
|
|
elseif num < 1000000 then
|
|
return format("%.1fk",num/1000)
|
|
elseif num < 1000000000 then
|
|
return format("%.2fm",num/1000000)
|
|
else
|
|
return format("%.3fM",num/1000000000)
|
|
end
|
|
end
|
|
|
|
function ExRT.F.classIconInText(class,size)
|
|
if CLASS_ICON_TCOORDS[class] then
|
|
size = size or 0
|
|
if class == "EVOKER" then
|
|
return "|Tinterface\\icons\\classicon_evoker:"..size..":"..size.."|t"
|
|
else
|
|
return "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:"..size..":"..size..":0:0:256:256:".. floor(CLASS_ICON_TCOORDS[class][1]*256) ..":"..floor(CLASS_ICON_TCOORDS[class][2]*256) ..":"..floor(CLASS_ICON_TCOORDS[class][3]*256) ..":"..floor(CLASS_ICON_TCOORDS[class][4]*256) .."|t"
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GUIDtoID(guid)
|
|
local type,_,serverID,instanceID,zoneUID,id,spawnID = strsplit("-", guid or "")
|
|
return tonumber(id or 0)
|
|
end
|
|
|
|
function ExRT.F.table_copy(table1,table2)
|
|
table.wipe(table2)
|
|
for key,val in pairs(table1) do
|
|
table2[key] = val
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_copy2(table1)
|
|
local table2 = {}
|
|
for key,val in pairs(table1) do
|
|
if type(val) == 'table' then
|
|
table2[key] = ExRT.F.table_copy2(val)
|
|
else
|
|
table2[key] = val
|
|
end
|
|
end
|
|
return table2
|
|
end
|
|
|
|
function ExRT.F.table_wipe(arr)
|
|
if not arr or type(arr) ~= "table" then
|
|
return
|
|
end
|
|
for key,val in pairs(arr) do
|
|
if type(val) == "table" then
|
|
ExRT.F.table_wipe(val)
|
|
end
|
|
arr[key] = nil
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_find(arr,subj,pos)
|
|
if pos then
|
|
for j=1,#arr do
|
|
if arr[j][pos] == subj then
|
|
return j
|
|
end
|
|
end
|
|
else
|
|
for j=1,#arr do
|
|
if arr[j] == subj then
|
|
return j
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_find2(arr,subj)
|
|
for key,val in pairs(arr) do
|
|
if val == subj then
|
|
return key
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_find3(arr,subj,pos)
|
|
for j=1,#arr do
|
|
if arr[j][pos] == subj then
|
|
return arr[j]
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_len(arr)
|
|
local len = 0
|
|
for _ in pairs(arr) do
|
|
len = len + 1
|
|
end
|
|
return len
|
|
end
|
|
|
|
function ExRT.F.table_add(arr,add)
|
|
for i=1,#add do
|
|
arr[#arr+1] = add[i]
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_add2(arr,add)
|
|
for key,val in pairs(add) do
|
|
arr[key] = val
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_keys(arr)
|
|
local r = {}
|
|
for key,val in pairs(arr) do
|
|
r[#r+1] = key
|
|
end
|
|
return r
|
|
end
|
|
|
|
do
|
|
local function swap(array, index1, index2)
|
|
array[index1], array[index2] = array[index2], array[index1]
|
|
end
|
|
local math_random = math.random
|
|
function ExRT.F.table_shuffle(array)
|
|
local counter = #array
|
|
while counter > 1 do
|
|
local index = math_random(counter)
|
|
swap(array, index, counter)
|
|
counter = counter - 1
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local printDiff = false
|
|
local printTable = nil
|
|
local function cmp(t1,t2,r,p)
|
|
local c,t = 0,0
|
|
if type(t1) ~= "table" or type(t2) ~= "table" then
|
|
return c, t
|
|
end
|
|
p = p or "."
|
|
for k,v in pairs(t1) do
|
|
if type(v) == "table" then
|
|
if type(t2[k]) == "table" then
|
|
local c2,t2 = cmp(v,t2[k],false,p..k..".")
|
|
c = c + c2
|
|
t = t + t2
|
|
else
|
|
t = t + 1
|
|
if printTable then
|
|
printTable[p..k] = true
|
|
elseif printDiff then
|
|
print(p..k)
|
|
end
|
|
end
|
|
else
|
|
t = t + 1
|
|
if t1[k] == t2[k] then
|
|
c = c + 1
|
|
elseif type(v) == "number" and type(t2[k]) == "number" and tostring(v) == tostring(t2[k]) then
|
|
c = c + 1
|
|
elseif printTable then
|
|
printTable[p..k] = true
|
|
elseif printDiff then
|
|
print(p..k)
|
|
end
|
|
end
|
|
end
|
|
if not r then
|
|
local c2,t2 = cmp(t2,t1,true,p)
|
|
c = c + c2
|
|
t = t + t2
|
|
end
|
|
return c, t
|
|
end
|
|
function ExRT.F.table_compare(t1,t2,showDiff)
|
|
printDiff = showDiff
|
|
if type(printDiff) == "table" then
|
|
printTable = printDiff
|
|
printDiff = nil
|
|
else
|
|
printTable = nil
|
|
end
|
|
local c, t = cmp(t1,t2)
|
|
|
|
return c / max(1,t), c, t
|
|
end
|
|
end
|
|
|
|
function ExRT.F.table_rewrite(t1,t2)
|
|
local toRemove = {}
|
|
for k,v in pairs(t1) do
|
|
if not t2[k] then
|
|
toRemove[k] = true
|
|
elseif type(v) == "table" and type(t2[k]) == "table" then
|
|
ExRT.F.table_rewrite(v,t2[k])
|
|
else
|
|
t1[k] = t2[k]
|
|
end
|
|
end
|
|
for k,v in pairs(toRemove) do
|
|
t1[k] = nil
|
|
end
|
|
for k,v in pairs(t2) do
|
|
if not t1[k] then
|
|
t1[k] = v
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.tohex(num,size)
|
|
return format("%0"..(size or "1").."X",num)
|
|
end
|
|
|
|
function ExRT.F.UnitInGuild(unit)
|
|
unit = ExRT.F.delUnitNameServer(unit)
|
|
local gplayers = GetNumGuildMembers() or 0
|
|
for i=1,gplayers do
|
|
local name = GetGuildRosterInfo(i)
|
|
if name and ExRT.F.delUnitNameServer(name) == unit then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function ExRT.F.chatType(toSay)
|
|
local isInInstance = IsInGroup(LE_PARTY_CATEGORY_INSTANCE)
|
|
local isInParty = IsInGroup()
|
|
local isInRaid = IsInRaid()
|
|
local playerName = nil
|
|
local chat_type = (isInInstance and "INSTANCE_CHAT") or (isInRaid and "RAID") or (isInParty and "PARTY")
|
|
if not chat_type and not toSay then
|
|
chat_type = "WHISPER"
|
|
playerName = UnitName("player")
|
|
elseif not chat_type then
|
|
chat_type = "SAY"
|
|
end
|
|
return chat_type, playerName
|
|
end
|
|
|
|
function ExRT.F.IsBonusOnItem(link,bonus)
|
|
if link then
|
|
local _,itemID,enchant,gem1,gem2,gem3,gem4,suffixID,uniqueID,level,specializationID,upgradeType,instanceDifficultyID,numBonusIDs,restLink = strsplit(":",link,15)
|
|
if restLink then
|
|
local bonuses = {strsplit(":",strsplit("|h",restLink),nil)}
|
|
numBonusIDs = tonumber(numBonusIDs) or 0
|
|
local isTable = type(bonus) == "table"
|
|
for i = 1, numBonusIDs do
|
|
local bonusID = tonumber(bonuses[i]) or -999
|
|
if (isTable and bonus[bonusID]) or (not isTable and bonusID == bonus) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GetItemBonuses(link)
|
|
if link then
|
|
local _,itemID,enchant,gem1,gem2,gem3,gem4,suffixID,uniqueID,level,specializationID,upgradeType,instanceDifficultyID,numBonusIDs,restLink = strsplit(":",link,15)
|
|
numBonusIDs = tonumber(numBonusIDs or "?") or 0
|
|
local bonusStr = ""
|
|
for i=1,numBonusIDs do
|
|
local bonus = select(i,strsplit(":",restLink))
|
|
if bonus then
|
|
bonusStr = bonusStr .. bonus .. ":"
|
|
end
|
|
end
|
|
bonusStr = strtrim(bonusStr,":")
|
|
return bonusStr,numBonusIDs
|
|
end
|
|
return "",0
|
|
end
|
|
--/dump GMRT.F.GetItemBonuses(select(2,GameTooltip:GetItem()))
|
|
|
|
function ExRT.F.IsPlayerRLorOfficer(unitName)
|
|
local shortName = ExRT.F.delUnitNameServer(unitName)
|
|
for i=1,GetNumGroupMembers() do
|
|
--if name and (name == unitName or ExRT.F.delUnitNameServer(name) == shortName) then
|
|
if UnitIsUnit(unitName,"raid"..i) or UnitIsUnit(shortName,"raid"..i) then
|
|
local name,rank = GetRaidRosterInfo(i)
|
|
if rank > 0 then
|
|
return rank
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
-- nil: not in party or raid
|
|
-- false: no rl, no officer
|
|
-- 1: officer
|
|
-- 2: rl
|
|
end
|
|
|
|
function ExRT.F.GetPlayerParty(unitName)
|
|
for i=1,GetNumGroupMembers() do
|
|
local name,_,subgroup = GetRaidRosterInfo(i)
|
|
if UnitIsUnit(name,unitName) then
|
|
return subgroup
|
|
end
|
|
end
|
|
return 0
|
|
end
|
|
|
|
function ExRT.F.GetOwnPartyNum()
|
|
for i=1,GetNumGroupMembers() do
|
|
local name,_,subgroup = GetRaidRosterInfo(i)
|
|
if UnitIsUnit(name,'player') then
|
|
return subgroup
|
|
end
|
|
end
|
|
return 1
|
|
end
|
|
|
|
function ExRT.F.CreateAddonMsg(...)
|
|
local result = ""
|
|
for i=1,select('#',...) do
|
|
local a = select(i,...)
|
|
result = result..(result ~= "" and "\t" or "")..tostring(a)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function ExRT.F.GetPlayerRole()
|
|
local role = UnitGroupRolesAssigned('player')
|
|
if role == "HEALER" then
|
|
local _,class = UnitClass('player')
|
|
return role, (class == "PALADIN" or class == "MONK") and "MHEALER" or "RHEALER"
|
|
elseif role ~= "DAMAGER" then
|
|
--TANK, NONE
|
|
return role
|
|
else
|
|
local _,class = UnitClass('player')
|
|
local isMelee = (class == "WARRIOR" or class == "PALADIN" or class == "ROGUE" or class == "DEATHKNIGHT" or class == "MONK" or class == "DEMONHUNTER")
|
|
if class == "DRUID" then
|
|
isMelee = GetSpecialization() ~= 1
|
|
elseif class == "SHAMAN" then
|
|
isMelee = GetSpecialization() == 2
|
|
elseif class == "HUNTER" then
|
|
isMelee = GetSpecialization() == 3
|
|
end
|
|
if isMelee then
|
|
return role, "MDD"
|
|
else
|
|
return role, "RDD"
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GetUnitRole(unit)
|
|
local role = UnitGroupRolesAssigned(unit)
|
|
if role == "HEALER" then
|
|
local _,class = UnitClass(unit)
|
|
return role, (class == "PALADIN" or class == "MONK") and "MHEALER" or "RHEALER"
|
|
elseif role ~= "DAMAGER" then
|
|
--TANK, NONE
|
|
return role
|
|
else
|
|
local _,class = UnitClass(unit)
|
|
local isMelee = (class == "WARRIOR" or class == "PALADIN" or class == "ROGUE" or class == "DEATHKNIGHT" or class == "MONK" or class == "DEMONHUNTER")
|
|
if class == "DRUID" then
|
|
isMelee = not (UnitPowerType(unit) == 8) --astral power
|
|
elseif class == "SHAMAN" then
|
|
isMelee = UnitPowerMax(unit) >= 150
|
|
elseif class == "HUNTER" then
|
|
isMelee = (ExRT.A.Inspect and UnitName(unit) and ExRT.A.Inspect.db.inspectDB[UnitName(unit)] and ExRT.A.Inspect.db.inspectDB[UnitName(unit)].spec) == 255
|
|
end
|
|
if isMelee then
|
|
return role, "MDD"
|
|
else
|
|
return role, "RDD"
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.TextureToText(textureName,widthInText,heightInText,textureWidth,textureHeight,leftTexCoord,rightTexCoord,topTexCoord,bottomTexCoord)
|
|
return "|T"..textureName..":"..(widthInText or 0)..":"..(heightInText or 0)..":0:0:"..textureWidth..":"..textureHeight..":"..
|
|
format("%d",leftTexCoord*textureWidth)..":"..format("%d",rightTexCoord*textureWidth)..":"..format("%d",topTexCoord*textureHeight)..":"..format("%d",bottomTexCoord*textureHeight).."|t"
|
|
end
|
|
function ExRT.F.GetRaidTargetText(icon,size)
|
|
size = size or 0
|
|
return ExRT.F.TextureToText([[Interface\TargetingFrame\UI-RaidTargetingIcons]],size,size,256,256,((icon-1)%4)/4,((icon-1)%4+1)/4,floor((icon-1)/4)/4,(floor((icon-1)/4)+1)/4)
|
|
end
|
|
|
|
function ExRT.F.IterateMediaData(mediaType)
|
|
local list
|
|
if LibStub then
|
|
local loaded,media = pcall(LibStub,"LibSharedMedia-3.0")
|
|
if loaded and media then
|
|
list = media:HashTable(mediaType)
|
|
end
|
|
end
|
|
return next, list or {}
|
|
end
|
|
|
|
--[[
|
|
for index, name, subgroup, class, guid, rank, level, online, isDead, combatRole in ExRT.F.IterateRoster do
|
|
<...>
|
|
end
|
|
]]
|
|
function ExRT.F.IterateRoster(maxGroup,index)
|
|
index = (index or 0) + 1
|
|
maxGroup = maxGroup or 8
|
|
|
|
if IsInRaid() then
|
|
if index > GetNumGroupMembers() then
|
|
return
|
|
end
|
|
local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML, combatRole = GetRaidRosterInfo(index)
|
|
if subgroup > maxGroup then
|
|
return ExRT.F.IterateRoster(maxGroup,index)
|
|
end
|
|
local guid = UnitGUID(name or "raid"..index)
|
|
name = name or ""
|
|
return index, name, subgroup, fileName, guid, rank, level, online, isDead, combatRole
|
|
else
|
|
local name, rank, subgroup, level, class, fileName, online, isDead, combatRole, _
|
|
|
|
local unit = index == 1 and "player" or "party"..(index-1)
|
|
|
|
local guid = UnitGUID(unit)
|
|
if not guid then
|
|
return
|
|
end
|
|
|
|
subgroup = 1
|
|
name, _ = UnitName(unit)
|
|
name = name or ""
|
|
if _ then
|
|
name = name .. "-" .. _
|
|
end
|
|
class, fileName = UnitClass(unit)
|
|
|
|
if UnitIsGroupLeader(unit) then
|
|
rank = 2
|
|
else
|
|
rank = 1
|
|
end
|
|
|
|
level = UnitLevel(unit)
|
|
|
|
if UnitIsConnected(unit) then
|
|
online = true
|
|
end
|
|
|
|
if UnitIsDeadOrGhost(unit) then
|
|
isDead = true
|
|
end
|
|
|
|
combatRole = UnitGroupRolesAssigned(unit)
|
|
|
|
return index, name, subgroup, fileName, guid, rank, level, online, isDead, combatRole
|
|
end
|
|
end
|
|
|
|
function ExRT.F.vpairs(t)
|
|
local prev
|
|
local function it()
|
|
local k,v = next(t,prev)
|
|
prev = k
|
|
return v
|
|
end
|
|
return it
|
|
end
|
|
|
|
function ExRT.F:SafeCall(func, ...)
|
|
local res, arg1, arg2, arg3, arg4, arg5, arg6, arg7 = xpcall(func, geterrorhandler(), ...)
|
|
if res then
|
|
return arg1, arg2, arg3, arg4, arg5, arg6, arg7
|
|
end
|
|
end
|
|
|
|
do
|
|
-- UTF8
|
|
|
|
-- returns the number of bytes used by the UTF-8 character at byte i in s
|
|
-- also doubles as a UTF-8 character validator
|
|
local function utf8charbytes(s, i)
|
|
-- argument defaults
|
|
i = i or 1
|
|
|
|
-- argument checking
|
|
if type(s) ~= "string" then
|
|
error("bad argument #1 to 'utf8charbytes' (string expected, got ".. type(s).. ")")
|
|
end
|
|
if type(i) ~= "number" then
|
|
error("bad argument #2 to 'utf8charbytes' (number expected, got ".. type(i).. ")")
|
|
end
|
|
|
|
local c = strbyte(s, i)
|
|
|
|
-- determine bytes needed for character, based on RFC 3629
|
|
-- validate byte 1
|
|
if c > 0 and c <= 127 then
|
|
-- UTF8-1
|
|
return 1
|
|
|
|
elseif c >= 194 and c <= 223 then
|
|
-- UTF8-2
|
|
local c2 = strbyte(s, i + 1)
|
|
|
|
if not c2 then
|
|
error("UTF-8 string terminated early")
|
|
end
|
|
|
|
-- validate byte 2
|
|
if c2 < 128 or c2 > 191 then
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
|
|
return 2
|
|
|
|
elseif c >= 224 and c <= 239 then
|
|
-- UTF8-3
|
|
local c2 = strbyte(s, i + 1)
|
|
local c3 = strbyte(s, i + 2)
|
|
|
|
if not c2 or not c3 then
|
|
error("UTF-8 string terminated early")
|
|
end
|
|
|
|
-- validate byte 2
|
|
if c == 224 and (c2 < 160 or c2 > 191) then
|
|
error("Invalid UTF-8 character")
|
|
elseif c == 237 and (c2 < 128 or c2 > 159) then
|
|
error("Invalid UTF-8 character")
|
|
elseif c2 < 128 or c2 > 191 then
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
|
|
-- validate byte 3
|
|
if c3 < 128 or c3 > 191 then
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
|
|
return 3
|
|
|
|
elseif c >= 240 and c <= 244 then
|
|
-- UTF8-4
|
|
local c2 = strbyte(s, i + 1)
|
|
local c3 = strbyte(s, i + 2)
|
|
local c4 = strbyte(s, i + 3)
|
|
|
|
if not c2 or not c3 or not c4 then
|
|
error("UTF-8 string terminated early")
|
|
end
|
|
|
|
-- validate byte 2
|
|
if c == 240 and (c2 < 144 or c2 > 191) then
|
|
error("Invalid UTF-8 character")
|
|
elseif c == 244 and (c2 < 128 or c2 > 143) then
|
|
error("Invalid UTF-8 character")
|
|
elseif c2 < 128 or c2 > 191 then
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
|
|
-- validate byte 3
|
|
if c3 < 128 or c3 > 191 then
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
|
|
-- validate byte 4
|
|
if c4 < 128 or c4 > 191 then
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
|
|
return 4
|
|
|
|
else
|
|
error("Invalid UTF-8 character")
|
|
end
|
|
end
|
|
|
|
function ExRT.F.utf8len(s)
|
|
local pos = 1
|
|
local bytes = strlen(s)
|
|
local len = 0
|
|
|
|
while pos <= bytes do
|
|
len = len + 1
|
|
pos = pos + utf8charbytes(s, pos)
|
|
end
|
|
|
|
return len
|
|
end
|
|
|
|
-- functions identically to string.sub except that i and j are UTF-8 characters
|
|
-- instead of bytes
|
|
function ExRT.F.utf8sub(s, i, j)
|
|
-- argument defaults
|
|
j = j or -1
|
|
|
|
local pos = 1
|
|
local bytes = strlen(s)
|
|
local len = 0
|
|
|
|
-- only set l if i or j is negative
|
|
local l = (i >= 0 and j >= 0) or ExRT.F.utf8len(s)
|
|
local startChar = (i >= 0) and i or l + i + 1
|
|
local endChar = (j >= 0) and j or l + j + 1
|
|
|
|
-- can't have start before end!
|
|
if startChar > endChar then
|
|
return ""
|
|
end
|
|
|
|
-- byte offsets to pass to string.sub
|
|
local startByte, endByte = 1, bytes
|
|
|
|
while pos <= bytes do
|
|
len = len + 1
|
|
|
|
if len == startChar then
|
|
startByte = pos
|
|
end
|
|
|
|
pos = pos + utf8charbytes(s, pos)
|
|
|
|
if len == endChar then
|
|
endByte = pos - 1
|
|
break
|
|
end
|
|
end
|
|
|
|
return strsub(s, startByte, endByte)
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GetFirstTableInText(str)
|
|
local strlen = str:len()
|
|
local i = 1
|
|
local deep = 0
|
|
local start
|
|
local inStr
|
|
local inWideStr
|
|
local wideStrEqCount = 0
|
|
while i <= strlen do
|
|
local b = str:byte(i)
|
|
if not start and not inStr and b == 123 then
|
|
start = i
|
|
elseif start and not inStr and b == 123 then
|
|
deep = deep + 1
|
|
elseif start and not inStr and b == 125 then
|
|
if deep <= 0 then
|
|
return str:sub(start,i)
|
|
else
|
|
deep = deep - 1
|
|
end
|
|
elseif not inStr and b == 34 then --"
|
|
inStr = i
|
|
elseif inStr and not inWideStr and b == 92 then --\
|
|
i = i + 1
|
|
elseif inStr and not inWideStr and b == 34 then --"
|
|
inStr = false
|
|
elseif not inStr and b == 91 then -- [ = [
|
|
local k = i + 1
|
|
local eqc = 0
|
|
while k <= strlen do
|
|
local c1 = str:byte(k)
|
|
if c1 == 61 then
|
|
eqc = eqc + 1
|
|
elseif c1 == b then
|
|
inStr = i
|
|
inWideStr = i
|
|
wideStrEqCount = eqc
|
|
break
|
|
else
|
|
break
|
|
end
|
|
k = k + 1
|
|
end
|
|
elseif inStr and inWideStr and b == 93 then -- ] = ]
|
|
local k = i + 1
|
|
local eqc = 0
|
|
while k <= strlen do
|
|
local c1 = str:byte(k)
|
|
if c1 == 61 then
|
|
eqc = eqc + 1
|
|
elseif c1 == b then
|
|
if eqc == wideStrEqCount then
|
|
i = k
|
|
inStr = false
|
|
inWideStr = false
|
|
end
|
|
break
|
|
else
|
|
break
|
|
end
|
|
k = k + 1
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
do
|
|
local chatWindow = nil
|
|
local activeChat = "RAID"
|
|
local activeName = ""
|
|
local UpdateLines = nil
|
|
local function CreateChatWindow()
|
|
chatWindow = ELib:Template("ExRTDialogModernTemplate",UIParent)
|
|
_G["MRTToChatWindow"] = chatWindow
|
|
chatWindow:SetSize(400,300)
|
|
chatWindow:SetPoint("CENTER")
|
|
chatWindow:SetFrameStrata("DIALOG")
|
|
chatWindow:SetClampedToScreen(true)
|
|
chatWindow:EnableMouse(true)
|
|
chatWindow:SetMovable(true)
|
|
chatWindow:RegisterForDrag("LeftButton")
|
|
chatWindow:SetDontSavePosition(true)
|
|
chatWindow:SetScript("OnDragStart", function(self)
|
|
self:StartMoving()
|
|
end)
|
|
chatWindow:SetScript("OnDragStop", function(self)
|
|
self:StopMovingOrSizing()
|
|
end)
|
|
|
|
chatWindow.border = ExRT.lib:Shadow(chatWindow,20)
|
|
|
|
chatWindow.title:SetText(ExRT.L.ChatwindowName)
|
|
|
|
chatWindow.box = ExRT.lib:MultiEdit(chatWindow):Size(230,265):Point(10,-23):Font('x',11)
|
|
|
|
local chats = {
|
|
{"ME",ExRT.L.ChatwindowChatSelf},
|
|
{"SAY",ExRT.L.ChatwindowChatSay},
|
|
{"PARTY",ExRT.L.ChatwindowChatParty},
|
|
{"INSTANCE_CHAT",ExRT.L.ChatwindowChatInstance},
|
|
{"RAID",ExRT.L.ChatwindowChatRaid},
|
|
{"WHISPER",ExRT.L.ChatwindowChatWhisper},
|
|
{"TARGET",ExRT.L.ChatwindowChatWhisperTarget},
|
|
{"GUILD",ExRT.L.ChatwindowChatGuild},
|
|
{"OFFICER",ExRT.L.ChatwindowChatOfficer},
|
|
}
|
|
|
|
chatWindow.dropDown = ExRT.lib:DropDown(chatWindow,130,#chats):Size(130):Point(255,-60):SetText(ExRT.L.ChatwindowChatRaid)
|
|
chatWindow.dropDownText = ExRT.lib:Text(chatWindow,ExRT.L.ChatwindowChannel,10):Size(350,14):Point("BOTTOMLEFT",chatWindow.dropDown,"TOPLEFT",5,2):Color():Shadow()
|
|
for i=1,#chats do
|
|
local chatData = chats[i]
|
|
chatWindow.dropDown.List[i] = {
|
|
text = chatData[2],
|
|
notCheckable = true,
|
|
justifyH = "CENTER",
|
|
arg1 = chatData[1],
|
|
arg2 = chatData[2],
|
|
func = function (this,arg1,arg2)
|
|
chatWindow.dropDown:SetText(arg2)
|
|
ExRT.lib:DropDownClose()
|
|
activeChat = arg1
|
|
end
|
|
}
|
|
end
|
|
|
|
chatWindow.target = ExRT.lib:Edit(chatWindow):Size(130,20):Point(255,-115):OnChange(function (self)
|
|
activeName = self:GetText()
|
|
end)
|
|
chatWindow.targetText = ExRT.lib:Text(chatWindow,ExRT.L.ChatwindowNameEB,10):Size(350,14):Point("BOTTOMLEFT",chatWindow.target,"TOPLEFT",5,2):Bottom():Color():Shadow()
|
|
|
|
chatWindow.button = ExRT.lib:Button(chatWindow,ExRT.L.ChatwindowSend):Size(130,22):Point(255,-150):OnClick(function (self)
|
|
local lines = {strsplit("\n", chatWindow.box.EditBox:GetText())}
|
|
local channel = activeChat
|
|
local whisper = activeName
|
|
if channel == "TARGET" then
|
|
channel = "WHISPER"
|
|
whisper = ExRT.F.UnitCombatlogname("target")
|
|
if not whisper then
|
|
return
|
|
end
|
|
end
|
|
if channel == "ME" then
|
|
for i=1,#lines do
|
|
if lines[i] ~= "" then
|
|
print(lines[i])
|
|
end
|
|
end
|
|
chatWindow:Hide()
|
|
return
|
|
end
|
|
if whisper == "" then
|
|
whisper = nil
|
|
end
|
|
for i=1,#lines do
|
|
if lines[i] ~= "" then
|
|
SendChatMessage(lines[i],channel,nil,whisper)
|
|
end
|
|
end
|
|
chatWindow:Hide()
|
|
end)
|
|
|
|
chatWindow.helpText = ExRT.lib:Text(chatWindow,ExRT.L.ChatwindowHelp,10):Size(130,100):Point("TOP",chatWindow.button,"BOTTOM",0,-10):Top():Color():Shadow()
|
|
|
|
chatWindow.chk1 = ExRT.lib:Check(chatWindow,"Option 1"):Point(255,-260):OnClick(function()
|
|
UpdateLines()
|
|
end)
|
|
end
|
|
function UpdateLines()
|
|
local lines = chatWindow.lines
|
|
if not lines or type(lines)~="table" then
|
|
return
|
|
end
|
|
local editData = ""
|
|
local linesCount = #lines
|
|
local clearTags = chatWindow.clearTags
|
|
local option1 = chatWindow.option1enabled and chatWindow.chk1:GetChecked() and "%1" or ""
|
|
for i=1,linesCount do
|
|
local thisLine = lines[i]
|
|
if thisLine ~= "" then
|
|
thisLine = thisLine:gsub("@1@(.-)@1#",option1)
|
|
if clearTags then
|
|
thisLine = ExRT.F.clearTextTag(thisLine)
|
|
end
|
|
if strlen(thisLine) > 254 then
|
|
thisLine = strjoin("\n",ExRT.F.splitLongLine(thisLine,254))
|
|
end
|
|
editData = editData .. thisLine
|
|
if i ~= linesCount then
|
|
editData = editData .. "\n"
|
|
end
|
|
end
|
|
end
|
|
chatWindow.box.EditBox:SetText(editData)
|
|
end
|
|
function ExRT.F:ToChatWindow(lines,clearTags,option1Name)
|
|
if not lines or type(lines)~="table" then
|
|
return
|
|
end
|
|
if not chatWindow then
|
|
CreateChatWindow()
|
|
end
|
|
chatWindow.lines = lines
|
|
chatWindow.clearTags = clearTags
|
|
chatWindow.option1enabled = option1Name
|
|
if option1Name then
|
|
chatWindow.chk1.text:SetText(option1Name)
|
|
chatWindow.chk1:SetChecked(false)
|
|
chatWindow.chk1:Show()
|
|
else
|
|
chatWindow.chk1:Hide()
|
|
end
|
|
UpdateLines()
|
|
chatWindow:Show()
|
|
end
|
|
end
|
|
|
|
do
|
|
local alertWindow = nil
|
|
local alertFunc = nil
|
|
local alertArg1 = nil
|
|
local function CreateWindow()
|
|
alertWindow = ExRT.lib:Popup():Size(500,65)
|
|
alertWindow:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
|
|
alertWindow.EditBox = ExRT.lib:Edit(alertWindow):Size(480,16):Point("TOP",0,-20)
|
|
|
|
alertWindow.OK = ExRT.lib:Button(alertWindow,ACCEPT):Size(130,20):Point("TOP",0,-40):OnClick(function (self)
|
|
alertWindow:Hide()
|
|
local input = alertWindow.EditBox:GetText()
|
|
alertFunc(alertArg1,input)
|
|
end)
|
|
|
|
alertWindow.EditBox:SetScript("OnEnterPressed",function (self)
|
|
self:GetParent().OK:Click("LeftButton")
|
|
end)
|
|
end
|
|
function ExRT.F.ShowInput(text,func,arg1,onlyNum,defText,funcOnEdit)
|
|
if not alertWindow then
|
|
CreateWindow()
|
|
end
|
|
alertWindow.OK:Enable()
|
|
alertWindow.title:SetText(text)
|
|
alertWindow.EditBox:SetScript("OnTextChanged",funcOnEdit)
|
|
alertWindow.EditBox:SetText(defText or "")
|
|
alertWindow:ClearAllPoints()
|
|
alertWindow:SetPoint("CENTER",UIParent,0,0)
|
|
alertFunc = func
|
|
alertArg1 = arg1
|
|
if onlyNum then
|
|
alertWindow.EditBox:SetNumeric(true)
|
|
else
|
|
alertWindow.EditBox:SetNumeric(false)
|
|
end
|
|
alertWindow:Show()
|
|
alertWindow.EditBox:SetFocus()
|
|
end
|
|
function ExRT.F.ShowText(text)
|
|
if not alertWindow then
|
|
CreateWindow()
|
|
end
|
|
alertWindow.title:SetText("")
|
|
alertWindow:ClearAllPoints()
|
|
alertWindow:SetPoint("CENTER",UIParent,0,0)
|
|
alertWindow.EditBox:SetNumeric(false)
|
|
alertWindow.EditBox:SetText(text)
|
|
alertWindow:Show()
|
|
alertWindow.EditBox:SetFocus()
|
|
alertFunc = ExRT.NULLfunc
|
|
end
|
|
end
|
|
|
|
---------------> Chat links hook <---------------
|
|
do
|
|
local chatLinkFormat = "|HMRT:%s:0|h|cffffff00[MRT: %s]|r|h"
|
|
local funcTable = {}
|
|
local function createChatHook()
|
|
local SetHyperlink = ItemRefTooltip.SetHyperlink
|
|
function ItemRefTooltip:SetHyperlink(link, ...)
|
|
local funcName = link:match("^MRT:([^:]+):")
|
|
if funcName then
|
|
local func = funcTable[funcName]
|
|
if not func then
|
|
return
|
|
end
|
|
func()
|
|
else
|
|
SetHyperlink(self, link, ...)
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.CreateChatLink(funcName,func,stringName)
|
|
if createChatHook then createChatHook() createChatHook = nil end
|
|
if not funcName or not stringName or type(func) ~= "function" then
|
|
return ""
|
|
end
|
|
funcTable[funcName] = func
|
|
return chatLinkFormat:format(funcName,stringName)
|
|
end
|
|
end
|
|
---------------> Export Window <---------------
|
|
do
|
|
local exportWindow
|
|
function ExRT.F:Export(stringData,hideTextInfo,windowName,onChangeFunc)
|
|
if not exportWindow then
|
|
exportWindow = ELib:Popup(ExRT.L.Export):Size(650,615)
|
|
exportWindow.Edit = ELib:MultiEdit(exportWindow):Point("TOP",0,-20):Size(640,575)
|
|
exportWindow.TextInfo = ELib:Text(exportWindow,ExRT.L.ExportInfo,11):Color():Point("BOTTOM",0,3):Size(640,15):Bottom():Left()
|
|
exportWindow:SetScript("OnHide",function(self)
|
|
self.Edit:SetText("")
|
|
end)
|
|
exportWindow.Next = ExRT.lib:Button(exportWindow,">>>"):Size(100,16):Point("BOTTOMRIGHT",0,0):OnClick(function (self)
|
|
self.now = self.now + 1
|
|
self:SetText(">>> "..self.now.."/"..#exportWindow.hugeText)
|
|
exportWindow.Edit:SetText(exportWindow.hugeText[self.now])
|
|
exportWindow.Edit.EditBox:HighlightText()
|
|
exportWindow.Edit.EditBox:SetFocus()
|
|
if self.now == #exportWindow.hugeText then
|
|
self:Hide()
|
|
end
|
|
end)
|
|
end
|
|
exportWindow.title:SetText(windowName or ExRT.L.Export)
|
|
exportWindow.Edit.OnTextChanged = onChangeFunc
|
|
exportWindow:NewPoint("CENTER",UIParent,0,0)
|
|
exportWindow.TextInfo:SetShown(not hideTextInfo)
|
|
exportWindow:Show()
|
|
if #stringData > 200000 then
|
|
exportWindow.hugeText = {}
|
|
while stringData and stringData ~= "" do
|
|
local newText = stringData:sub(1,200000)..strsplit("\n",stringData:sub(200001))
|
|
exportWindow.hugeText[#exportWindow.hugeText+1] = newText
|
|
stringData = select(2,strsplit("\n",stringData:sub(200001),2))
|
|
end
|
|
exportWindow.Next.now = 0
|
|
exportWindow.Next:Show()
|
|
exportWindow.Next:Click()
|
|
else
|
|
exportWindow.hugeText = nil
|
|
exportWindow.Next:Hide()
|
|
exportWindow.Edit:SetText(stringData)
|
|
exportWindow.Edit.EditBox:HighlightText()
|
|
exportWindow.Edit.EditBox:SetFocus()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
do
|
|
local exportWindow
|
|
local pendingToShow
|
|
function ExRT.F:Export2(stringData)
|
|
if not exportWindow then
|
|
exportWindow = ExRT.lib:Popup("Export"):Size(650,50)
|
|
exportWindow.Edit = ExRT.lib:Edit(exportWindow):Point("TOP",0,-20):Size(640,25)
|
|
exportWindow:SetScript("OnHide",function(self)
|
|
self.Edit:SetText("")
|
|
self.onEnterFunc = nil
|
|
if pendingToShow then
|
|
stringData = select(2,next(pendingToShow))
|
|
if not stringData then
|
|
pendingToShow = nil
|
|
return
|
|
end
|
|
tremove(pendingToShow, 1)
|
|
C_Timer.After(0,function()
|
|
exportWindow.Edit:SetText(stringData)
|
|
exportWindow:Show()
|
|
end)
|
|
end
|
|
end)
|
|
exportWindow.Edit:SetScript("OnEditFocusGained", function(self)
|
|
self:HighlightText()
|
|
end)
|
|
exportWindow.Edit:SetScript("OnMouseUp", function(self, button)
|
|
self:HighlightText()
|
|
if button == "RightButton" then
|
|
self:GetParent():Hide()
|
|
end
|
|
end)
|
|
exportWindow.Edit:SetScript("OnKeyUp", function(self, c)
|
|
if (c == "c" or c == "C") and IsControlKeyDown() then
|
|
self:GetParent():Hide()
|
|
end
|
|
end)
|
|
exportWindow.Edit:SetScript("OnEnterPressed",function(self)
|
|
if self:GetParent().onEnterFunc then
|
|
self:GetParent().onEnterFunc(self:GetText())
|
|
self:GetParent():Hide()
|
|
end
|
|
end)
|
|
function exportWindow:OnShow()
|
|
self.Edit:SetFocus()
|
|
end
|
|
elseif exportWindow:IsShown() then
|
|
if not pendingToShow then
|
|
pendingToShow = {}
|
|
end
|
|
pendingToShow[#pendingToShow+1] = stringData
|
|
return
|
|
|
|
end
|
|
|
|
if type(stringData) == "function" then
|
|
exportWindow.onEnterFunc = stringData
|
|
stringData = ""
|
|
else
|
|
exportWindow.onEnterFunc = nil
|
|
end
|
|
|
|
if type(stringData) == "table" then
|
|
stringData = table.concat(ExRT.F.TableToText(stringData))
|
|
elseif type(stringData) ~= "string" then
|
|
stringData = tostring(stringData)
|
|
end
|
|
|
|
exportWindow:NewPoint("CENTER",UIParent,0,0)
|
|
exportWindow.Edit:SetText(stringData)
|
|
exportWindow:Show()
|
|
end
|
|
end
|
|
|
|
---------------> Import/Export data <---------------
|
|
do
|
|
local function StringToText(str)
|
|
if str:find("\n") then
|
|
local n = 0
|
|
if str:find("%]$") then
|
|
n = n + 1
|
|
end
|
|
while str:find("%["..string.rep("=",n).."%[") or str:find("%]"..string.rep("=",n).."%]") do
|
|
n = n + 1
|
|
end
|
|
return "["..string.rep("=",n).."["..str.."]"..string.rep("=",n).."]", true
|
|
else
|
|
return "\""..str:gsub("\\","\\\\"):gsub("\"","\\\"").."\""
|
|
end
|
|
end
|
|
|
|
local function IterateTable(t)
|
|
local prev
|
|
local index = 1
|
|
local indexMax
|
|
local isIndexDone
|
|
local function it()
|
|
if not indexMax then
|
|
local v = t[index]
|
|
if v then
|
|
index = index + 1
|
|
return index-1, v, true
|
|
else
|
|
indexMax = index - 1
|
|
end
|
|
end
|
|
local k,v = next(t,prev)
|
|
prev = k
|
|
while k and type(k)=="number" and k >= 1 and k <= indexMax do
|
|
k,v = next(t,prev)
|
|
prev = k
|
|
end
|
|
return k, v, false
|
|
end
|
|
return it
|
|
end
|
|
|
|
function ExRT.F.TableToText(t,e,b)
|
|
b = b or {}
|
|
b[t] = true
|
|
e = e or {"{"}
|
|
local ignoreIndex = false
|
|
for k,v,isIndex in IterateTable(t) do
|
|
local newline = ""
|
|
local ignore = true
|
|
if type(v) == "boolean" or type(v) == "number" or type(v) == "string" or type(v) == "table" then
|
|
ignore = false
|
|
end
|
|
if type(v) == "table" and b[v] then
|
|
ignore = true
|
|
end
|
|
if ignore then
|
|
ignoreIndex = true
|
|
elseif isIndex and not ignoreIndex then
|
|
elseif type(k)=="number" then
|
|
newline = newline .. "["..k.."]="
|
|
elseif type(k)=="string" then
|
|
if k:match("[A-Za-z_][A-Za-z_0-9]*") == k then
|
|
newline = newline .. k .. "="
|
|
else
|
|
local kstr, ismultiline = StringToText(k)
|
|
newline = newline .. "["..(ismultiline and " " or "")..kstr..(ismultiline and " " or "").."]="
|
|
end
|
|
elseif type(k)=="boolean" then
|
|
newline = newline .. "["..(k and "true" or "false").."]="
|
|
else
|
|
ignore = true
|
|
end
|
|
if not ignore then
|
|
local tableToExplore
|
|
if type(v)=="number" then
|
|
newline = newline .. v .. ","
|
|
elseif type(v)=="string" then
|
|
newline = newline .. StringToText(v)..","
|
|
elseif type(v)=="boolean" then
|
|
newline = newline ..(v and "true" or "false")..","
|
|
elseif type(v)=="table" then
|
|
newline = newline .."{"
|
|
tableToExplore = v
|
|
end
|
|
e[#e+1] = newline
|
|
if tableToExplore then
|
|
ExRT.F.TableToText(tableToExplore,e,b)
|
|
e[#e] = e[#e] .. ","
|
|
end
|
|
end
|
|
end
|
|
e[#e] = e[#e]:gsub(",$","")
|
|
e[#e+1] = "}"
|
|
return e
|
|
end
|
|
|
|
local string_byte = string.byte
|
|
function ExRT.F.TextToTable(str,map,offset)
|
|
if not map and string_byte(str, 1) == 123 then
|
|
str = str:sub(2,-2) --Expect valid table here
|
|
end
|
|
local strlen = str:len()
|
|
local i = 1
|
|
local prev = 1
|
|
map = map or {}
|
|
offset = offset or 0
|
|
|
|
local inTable, inString, inWideString
|
|
local startTable, wideStringEqCount = 1, 0
|
|
|
|
while i <= strlen do
|
|
local b1 = string_byte(str, i)
|
|
if not inString and not inTable and b1 == 123 then
|
|
inTable = 0
|
|
startTable = i
|
|
elseif not inString and inTable and b1 == 123 then
|
|
inTable = inTable + 1
|
|
elseif not inString and inTable and b1 == 125 then
|
|
if inTable == 0 then
|
|
map[startTable+offset] = i + offset
|
|
map[startTable+0.5+offset] = 1
|
|
inTable = false
|
|
else
|
|
inTable = inTable - 1
|
|
end
|
|
elseif not inString and b1 == 34 then --"
|
|
if map[i+offset+0.5] == 2 then
|
|
i = map[i+offset] - offset
|
|
else
|
|
inString = i
|
|
end
|
|
elseif inString and not inWideString and b1 == 92 then --\
|
|
i = i + 1
|
|
elseif inString and not inWideString and b1 == 34 then --"
|
|
map[inString+offset] = i + offset
|
|
map[inString+0.5+offset] = 2
|
|
inString = false
|
|
elseif not inString and b1 == 91 then -- [ = [
|
|
if map[i+offset+0.5] == 3 then
|
|
i = map[i+offset] - offset
|
|
else
|
|
local k = i + 1
|
|
local eqc = 0
|
|
while k <= strlen do
|
|
local c1 = string_byte(str, k)
|
|
if c1 == 61 then
|
|
eqc = eqc + 1
|
|
elseif c1 == b1 then
|
|
inString = i
|
|
inWideString = i
|
|
i = k
|
|
wideStringEqCount = eqc
|
|
break
|
|
else
|
|
break
|
|
end
|
|
k = k + 1
|
|
end
|
|
end
|
|
elseif inString and inWideString and b1 == 93 then -- ] = ]
|
|
local k = i + 1
|
|
local eqc = 0
|
|
while k <= strlen do
|
|
local c1 = string_byte(str, k)
|
|
if c1 == 61 then
|
|
eqc = eqc + 1
|
|
elseif c1 == b1 then
|
|
if eqc == wideStringEqCount then
|
|
i = k
|
|
map[inWideString+offset] = i + offset
|
|
map[inWideString+0.5+offset] = 3
|
|
inString = false
|
|
inWideString = false
|
|
end
|
|
break
|
|
else
|
|
break
|
|
end
|
|
k = k + 1
|
|
end
|
|
end
|
|
if not inString and not inTable and (b1 == 44 or i == strlen) then --,
|
|
map[-prev-offset] = i - (b1 == 44 and 1 or 0) + offset
|
|
prev = i + 1
|
|
end
|
|
i = i + 1
|
|
end
|
|
|
|
local res = {}
|
|
local numKey = 1
|
|
i = 1
|
|
while i <= strlen do
|
|
if map[-i-offset] then
|
|
local s, e = i, map[-i-offset] - offset
|
|
local k = s
|
|
local key, value
|
|
local isError
|
|
prev = k
|
|
while k <= e do
|
|
if map[k+offset] then
|
|
if map[k+0.5+offset] == 1 then
|
|
value = ExRT.F.TextToTable( str:sub(k+1,map[k+offset]-offset-1) ,map,k+offset)
|
|
elseif map[k+0.5+offset] == 2 then
|
|
value = str:sub(k + 1,map[k+offset]-offset-1):gsub("\\\"","\""):gsub("\\\\","\\")
|
|
elseif map[k+0.5+offset] == 3 then
|
|
value = str:sub(k,map[k+offset]-offset):gsub("^%[=*%[",""):gsub("%]=*%]$","")
|
|
end
|
|
k = map[k+offset] + 1 - offset
|
|
else
|
|
local b1 = string_byte(str, k)
|
|
if b1 == 61 then --=
|
|
if value then
|
|
key = value
|
|
value = nil
|
|
else
|
|
key = str:sub(prev, k-1):trim()
|
|
if key:find("^%[") and key:find("%]$") then
|
|
key = key:gsub("^%[",""):gsub("%]$","")
|
|
if tonumber(key) then
|
|
key = tonumber(key)
|
|
end
|
|
elseif key == "true" then
|
|
key = true
|
|
elseif key == "false" then
|
|
key = false
|
|
elseif tonumber(key) then
|
|
key = tonumber(key)
|
|
else
|
|
key = key:match("[A-Za-z_][A-Za-z_0-9]*")
|
|
end
|
|
if not key then
|
|
isError = true
|
|
break
|
|
end
|
|
end
|
|
prev = k + 1
|
|
elseif k == e and not value then
|
|
value = str:sub(prev, k):trim()
|
|
if value == "true" then
|
|
value = true
|
|
elseif value == "false" then
|
|
value = false
|
|
else
|
|
value = tonumber(value)
|
|
end
|
|
end
|
|
k = k + 1
|
|
end
|
|
end
|
|
if not isError then
|
|
if not key then
|
|
key = numKey
|
|
numKey = numKey + 1
|
|
end
|
|
res[key] = value
|
|
end
|
|
i = map[-i-offset] - offset
|
|
end
|
|
i = i + 1
|
|
end
|
|
return res
|
|
end
|
|
|
|
function ExRT.F.CreateImportExportWindows()
|
|
local function ImportOnUpdate(self, elapsed)
|
|
self.tmr = self.tmr + elapsed
|
|
if self.tmr >= 0.1 then
|
|
self.tmr = 0
|
|
self:SetScript("OnUpdate",nil)
|
|
local str = table.concat(self.buff):trim()
|
|
self.parent:Hide()
|
|
|
|
self.buff = {}
|
|
self.buffPos = 0
|
|
|
|
if self.parent.ImportFunc then
|
|
self.parent:ImportFunc(str)
|
|
end
|
|
end
|
|
end
|
|
|
|
local importWindow = ELib:Popup(ExRT.L.Import.." "..ExRT.L.ImportHelp):Size(650,100)
|
|
importWindow.Edit = ELib:MultiEdit(importWindow):Point("TOP",0,-20):Size(640,75)
|
|
importWindow:SetScript("OnHide",function(self)
|
|
self.Edit:SetText("")
|
|
end)
|
|
importWindow:SetScript("OnShow",function(self)
|
|
self.Edit.EditBox.buffPos = 0
|
|
self.Edit.EditBox.tmr = 0
|
|
self.Edit.EditBox.buff = {}
|
|
self.Edit.EditBox:SetFocus()
|
|
end)
|
|
importWindow.Edit.EditBox:SetMaxBytes(1)
|
|
importWindow.Edit.EditBox:SetScript("OnChar", function(self, c)
|
|
self.buffPos = self.buffPos + 1
|
|
self.buff[self.buffPos] = c
|
|
self:SetScript("OnUpdate",ImportOnUpdate)
|
|
end)
|
|
importWindow.Edit.EditBox.parent = importWindow
|
|
|
|
|
|
local exportWindow = ELib:Popup(ExRT.L.Export):Size(650,50)
|
|
exportWindow.Edit = ELib:Edit(exportWindow):Point("TOP",0,-20):Size(640,25)
|
|
exportWindow:SetScript("OnHide",function(self)
|
|
self.Edit:SetText("")
|
|
end)
|
|
exportWindow.Edit:SetScript("OnEditFocusGained", function(self)
|
|
self:HighlightText()
|
|
end)
|
|
exportWindow.Edit:SetScript("OnMouseUp", function(self, button)
|
|
self:HighlightText()
|
|
if button == "RightButton" then
|
|
self:GetParent():Hide()
|
|
end
|
|
end)
|
|
exportWindow.Edit:SetScript("OnKeyUp", function(self, c)
|
|
if (c == "c" or c == "C") and IsControlKeyDown() then
|
|
self:GetParent():Hide()
|
|
end
|
|
end)
|
|
function exportWindow:OnShow()
|
|
self.Edit:SetFocus()
|
|
end
|
|
|
|
return importWindow, exportWindow
|
|
end
|
|
end
|
|
|
|
-------------------> Data <--------------------
|
|
|
|
ExRT.GDB.ClassSpecializationIcons = {
|
|
[62] = "Interface\\Icons\\Spell_Holy_MagicalSentry",
|
|
[63] = "Interface\\Icons\\Spell_Fire_FireBolt02",
|
|
[64] = "Interface\\Icons\\Spell_Frost_FrostBolt02",
|
|
[65] = "Interface\\Icons\\Spell_Holy_HolyBolt",
|
|
[66] = "Interface\\Icons\\Ability_Paladin_ShieldoftheTemplar",
|
|
[70] = "Interface\\Icons\\Spell_Holy_AuraOfLight",
|
|
[71] = "Interface\\Icons\\Ability_Warrior_SavageBlow",
|
|
[72] = "Interface\\Icons\\Ability_Warrior_InnerRage",
|
|
[73] = "Interface\\Icons\\Ability_Warrior_DefensiveStance",
|
|
[102] = "Interface\\Icons\\Spell_Nature_StarFall",
|
|
[103] = "Interface\\Icons\\Ability_Druid_CatForm",
|
|
[104] = "Interface\\Icons\\Ability_Racial_BearForm",
|
|
[105] = "Interface\\Icons\\Spell_Nature_HealingTouch",
|
|
[250] = "Interface\\Icons\\Spell_Deathknight_BloodPresence",
|
|
[251] = "Interface\\Icons\\Spell_Deathknight_FrostPresence",
|
|
[252] = "Interface\\Icons\\Spell_Deathknight_UnholyPresence",
|
|
[253] = "INTERFACE\\ICONS\\ability_hunter_bestialdiscipline",
|
|
[254] = "Interface\\Icons\\Ability_Hunter_FocusedAim",
|
|
[255] = "INTERFACE\\ICONS\\ability_hunter_camouflage",
|
|
[256] = "Interface\\Icons\\Spell_Holy_PowerWordShield",
|
|
[257] = "Interface\\Icons\\Spell_Holy_GuardianSpirit",
|
|
[258] = "Interface\\Icons\\Spell_Shadow_ShadowWordPain",
|
|
[259] = "Interface\\Icons\\Ability_Rogue_DeadlyBrew",
|
|
[260] = "Interface\\Icons\\INV_Sword_30",
|
|
[261] = "Interface\\Icons\\Ability_Stealth",
|
|
[262] = "Interface\\Icons\\Spell_Nature_Lightning",
|
|
[263] = "Interface\\Icons\\Spell_Shaman_ImprovedStormstrike",
|
|
[264] = "Interface\\Icons\\Spell_Nature_MagicImmunity",
|
|
[265] = "Interface\\Icons\\Spell_Shadow_DeathCoil",
|
|
[266] = "Interface\\Icons\\Spell_Shadow_Metamorphosis",
|
|
[267] = "Interface\\Icons\\Spell_Shadow_RainOfFire",
|
|
[268] = "Interface\\Icons\\spell_monk_brewmaster_spec",
|
|
[269] = "Interface\\Icons\\spell_monk_windwalker_spec",
|
|
[270] = "Interface\\Icons\\spell_monk_mistweaver_spec",
|
|
[577] = "Interface\\Icons\\ability_demonhunter_specdps",
|
|
[581] = "Interface\\Icons\\ability_demonhunter_spectank",
|
|
[1467] = "Interface\\Icons\\classicon_evoker_devastation",
|
|
[1468] = "Interface\\Icons\\classicon_evoker_preservation",
|
|
[1473] = "Interface\\Icons\\classicon_evoker_augmentation",
|
|
}
|
|
|
|
ExRT.GDB.ClassList = {
|
|
"WARRIOR",
|
|
"PALADIN",
|
|
"HUNTER",
|
|
"ROGUE",
|
|
"PRIEST",
|
|
"DEATHKNIGHT",
|
|
"SHAMAN",
|
|
"MAGE",
|
|
"WARLOCK",
|
|
"MONK",
|
|
"DRUID",
|
|
"DEMONHUNTER",
|
|
"EVOKER",
|
|
}
|
|
|
|
ExRT.GDB.ClassSpecializationList = {
|
|
["WARRIOR"] = {71, 72, 73},
|
|
["PALADIN"] = {65, 66, 70},
|
|
["HUNTER"] = {253, 254, 255},
|
|
["ROGUE"] = {259, 260, 261},
|
|
["PRIEST"] = {256, 257, 258},
|
|
["DEATHKNIGHT"] = {250, 251, 252},
|
|
["SHAMAN"] = {262, 263, 264},
|
|
["MAGE"] = {62, 63, 64},
|
|
["WARLOCK"] = {265, 266, 267},
|
|
["MONK"] = {268, 269, 270},
|
|
["DRUID"] = {102, 103, 104, 105},
|
|
["DEMONHUNTER"] = {577, 581},
|
|
["EVOKER"] = {1467, 1468, 1473},
|
|
}
|
|
|
|
ExRT.GDB.ClassArmorType = {
|
|
WARRIOR="PLATE",
|
|
PALADIN="PLATE",
|
|
HUNTER="MAIL",
|
|
ROGUE="LEATHER",
|
|
PRIEST="CLOTH",
|
|
DEATHKNIGHT="PLATE",
|
|
SHAMAN="MAIL",
|
|
MAGE="CLOTH",
|
|
WARLOCK="CLOTH",
|
|
MONK="LEATHER",
|
|
DRUID="LEATHER",
|
|
DEMONHUNTER="LEATHER",
|
|
EVOKER="MAIL",
|
|
}
|
|
|
|
ExRT.GDB.ClassSpecializationRole = {
|
|
[62] = 'RANGE',
|
|
[63] = 'RANGE',
|
|
[64] = 'RANGE',
|
|
[65] = 'HEAL',
|
|
[66] = 'TANK',
|
|
[70] = 'MELEE',
|
|
[71] = 'MELEE',
|
|
[72] = 'MELEE',
|
|
[73] = 'TANK',
|
|
[102] = 'RANGE',
|
|
[103] = 'MELEE',
|
|
[104] = 'TANK',
|
|
[105] = 'HEAL',
|
|
[250] = 'TANK',
|
|
[251] = 'MELEE',
|
|
[252] = 'MELEE',
|
|
[253] = 'RANGE',
|
|
[254] = 'RANGE',
|
|
[255] = 'MELEE',
|
|
[256] = 'HEAL',
|
|
[257] = 'HEAL',
|
|
[258] = 'RANGE',
|
|
[259] = 'MELEE',
|
|
[260] = 'MELEE',
|
|
[261] = 'MELEE',
|
|
[262] = 'RANGE',
|
|
[263] = 'MELEE',
|
|
[264] = 'HEAL',
|
|
[265] = 'RANGE',
|
|
[266] = 'RANGE',
|
|
[267] = 'RANGE',
|
|
[268] = 'TANK',
|
|
[269] = 'MELEE',
|
|
[270] = 'HEAL',
|
|
[577] = 'MELEE',
|
|
[581] = 'TANK',
|
|
[1467] = 'RANGE',
|
|
[1468] = 'HEAL',
|
|
[1473] = 'RANGE',
|
|
}
|
|
|
|
ExRT.GDB.ClassID = {
|
|
WARRIOR=1,
|
|
PALADIN=2,
|
|
HUNTER=3,
|
|
ROGUE=4,
|
|
PRIEST=5,
|
|
DEATHKNIGHT=6,
|
|
SHAMAN=7,
|
|
MAGE=8,
|
|
WARLOCK=9,
|
|
MONK=10,
|
|
DRUID=11,
|
|
DEMONHUNTER=12,
|
|
EVOKER=13,
|
|
}
|
|
|
|
if ExRT.isCata then
|
|
ExRT.GDB.ClassSpecializationList = {
|
|
WARRIOR = {746,815,845}, --Arms,Fury,Protection
|
|
PALADIN = {831,839,855}, --Holy,Protection,Retribution
|
|
HUNTER = {811,807,809}, --Beast Mastery,Marksmanship,Survival
|
|
ROGUE = {182,181,183}, --Assassination,Combat,Subtlety
|
|
PRIEST = {760,813,795}, --Discipline,Holy,Shadow
|
|
DEATHKNIGHT = {398,399,400}, --Blood,Frost,Unholy
|
|
SHAMAN = {261,263,262}, --Elemental,Enhancement,Restoration
|
|
MAGE = {799,851,823}, --Arcane,Fire,Frost
|
|
WARLOCK = {871,867,865}, --Affliction,Demonology,Destruction
|
|
DRUID = {752,750,748}, --Balance,Feral Combat,Restoration
|
|
}
|
|
|
|
ExRT.GDB.ClassSpecializationIcons = {
|
|
[181] = 132090,
|
|
[182] = 132292,
|
|
[183] = 132320,
|
|
[261] = 136048,
|
|
[262] = 136052,
|
|
[263] = 136051,
|
|
[398] = 135770,
|
|
[399] = 135773,
|
|
[400] = 135775,
|
|
[746] = 132355,
|
|
[748] = 136041,
|
|
[750] = 132276,
|
|
[752] = 136096,
|
|
[760] = 135940,
|
|
[795] = 136207,
|
|
[799] = 135932,
|
|
[807] = 236179,
|
|
[809] = 461113,
|
|
[811] = 461112,
|
|
[813] = 237542,
|
|
[815] = 132347,
|
|
[823] = 135846,
|
|
[831] = 135920,
|
|
[839] = 236264,
|
|
[845] = 132341,
|
|
[851] = 135810,
|
|
[855] = 135873,
|
|
[865] = 136186,
|
|
[867] = 136172,
|
|
[871] = 136145,
|
|
}
|
|
|
|
ExRT.GDB.ClassSpecializationRole = {
|
|
[181] = "MELEE",
|
|
[182] = "MELEE",
|
|
[183] = "MELEE",
|
|
[261] = "RANGE",
|
|
[262] = "HEAL",
|
|
[263] = "MELEE",
|
|
[398] = "TANK",
|
|
[399] = "MELEE",
|
|
[400] = "MELEE",
|
|
[746] = "MELEE",
|
|
[748] = "HEAL",
|
|
[750] = "MELEE",
|
|
[752] = "RANGE",
|
|
[760] = "HEAL",
|
|
[795] = "RANGE",
|
|
[799] = "RANGE",
|
|
[807] = "RANGE",
|
|
[809] = "RANGE",
|
|
[811] = "RANGE",
|
|
[813] = "HEAL",
|
|
[815] = "MELEE",
|
|
[823] = "RANGE",
|
|
[831] = "HEAL",
|
|
[839] = "TANK",
|
|
[845] = "TANK",
|
|
[851] = "RANGE",
|
|
[855] = "MELEE",
|
|
[865] = "RANGE",
|
|
[867] = "RANGE",
|
|
[871] = "RANGE",
|
|
}
|
|
end
|
|
|
|
|
|
if ExRT.isClassic then
|
|
--GetClassInfo
|
|
local classLocalizateEngine = {}
|
|
if LocalizedClassList then
|
|
local classList = LocalizedClassList()
|
|
MergeTable(classLocalizateEngine, classList)
|
|
elseif FillLocalizedClassList then
|
|
FillLocalizedClassList(classLocalizateEngine)
|
|
end
|
|
|
|
ExRT.Classic.GetClassInfo = function(id)
|
|
return classLocalizateEngine[ ExRT.GDB.ClassList[id] ] or "unk"
|
|
end
|
|
|
|
--GetSpecializationInfoByID
|
|
local specializationData = {
|
|
[62] = {name="Arcane",class=8,role="DAMAGER",desc="Manipulates raw Arcane magic, destroying enemies with overwhelming power.|n|nPreferred Weapon: Staff, Wand, Dagger, Sword",icon=135932},
|
|
[63] = {name="Fire",class=8,role="DAMAGER",desc="Focuses the pure essence of Fire magic, assaulting enemies with combustive flames.|n|nPreferred Weapon: Staff, Wand, Dagger, Sword",icon=135810},
|
|
[64] = {name="Frost",class=8,role="DAMAGER",desc="Freezes enemies in their tracks and shatters them with Frost magic.|n|nPreferred Weapon: Staff, Wand, Dagger, Sword",icon=135846},
|
|
[65] = {name="Holy",class=2,role="HEALER",desc="Invokes the power of the Light to heal and protect allies and vanquish evil from the darkest corners of the world.|n|nPreferred Weapon: Sword, Mace, and Shield",icon=135920},
|
|
[66] = {name="Protection",class=2,role="TANK",desc="Uses Holy magic to shield $Ghimself:herself; and defend allies from attackers.|n|nPreferred Weapon: Sword, Mace, Axe, and Shield",icon=236264},
|
|
[70] = {name="Retribution",class=2,role="DAMAGER",desc="A righteous crusader who judges and punishes opponents with weapons and Holy magic.|n|nPreferred Weapon: Two-Handed Sword, Mace, Axe",icon=135873},
|
|
[71] = {name="Arms",class=1,role="DAMAGER",desc="A battle-hardened master of weapons, using mobility and overpowering attacks to strike $Ghis:her; opponents down.|n|nPreferred Weapon: Two-Handed Axe, Mace, Sword",icon=132355},
|
|
[72] = {name="Fury",class=1,role="DAMAGER",desc="A furious berserker unleashing a flurry of attacks to carve $Ghis:her; opponents to pieces.|n|nPreferred Weapons: Dual Two-Handed Axes, Maces, Swords",icon=132347},
|
|
[73] = {name="Protection",class=1,role="TANK",desc="A stalwart protector who uses a shield to safeguard $Ghimself:herself; and $Ghis:her; allies.|n|nPreferred Weapon: Axe, Mace, Sword, and Shield",icon=132341},
|
|
[74] = {name="Ferocity",class=0,role="DAMAGER",desc="Driven by a frenzied persistence to pursue prey, these beasts stop at nothing to achieve victory; even death is temporary for these predators.",icon=236159},
|
|
[79] = {name="Cunning",class=0,role="DAMAGER",desc="",icon=132150},
|
|
[81] = {name="Tenacity",class=0,role="TANK",desc="",icon=132121},
|
|
[102] = {name="Balance",class=11,role="DAMAGER",desc="Can shapeshift into a powerful Moonkin, balancing the power of Arcane and Nature magic to destroy enemies.|n|nPreferred Weapon: Staff, Dagger, Mace",icon=136096},
|
|
[103] = {name="Feral",class=11,role="DAMAGER",desc="Takes on the form of a great cat to deal damage with bleeds and bites.|n|nPreferred Weapon: Staff, Polearm",icon=132115},
|
|
[104] = {name="Guardian",class=11,role="TANK",desc="Takes on the form of a mighty bear to absorb damage and protect allies.|n|nPreferred Weapon: Staff, Polearm",icon=132276},
|
|
[105] = {name="Restoration",class=11,role="HEALER",desc="Channels powerful Nature magic to regenerate and revitalize allies.|n|nPreferred Weapon: Staff, Dagger, Mace",icon=136041},
|
|
[250] = {name="Blood",class=6,role="TANK",desc="A dark guardian who manipulates and corrupts life energy to sustain $Ghimself:herself; in the face of an enemy onslaught.|n|nPreferred Weapon: Two-Handed Axe, Mace, Sword",icon=135770},
|
|
[251] = {name="Frost",class=6,role="DAMAGER",desc="An icy harbinger of doom, channeling runic power and delivering vicious weapon strikes.|n|nPreferred Weapons: Dual Axes, Maces, Swords",icon=135773},
|
|
[252] = {name="Unholy",class=6,role="DAMAGER",desc="A master of death and decay, spreading infection and controlling undead minions to do $Ghis:her; bidding.|n|nPreferred Weapon: Two-Handed Axe, Mace, Sword",icon=135775},
|
|
[253] = {name="Beast Mastery",class=3,role="DAMAGER",desc="A master of the wild who can tame a wide variety of beasts to assist $Ghim:her; in combat.|n|nPreferred Weapon: Bow, Crossbow, Gun",icon=461112},
|
|
[254] = {name="Marksmanship",class=3,role="DAMAGER",desc="A master sharpshooter who excels in bringing down enemies from afar.|n|nPreferred Weapon: Bow, Crossbow, Gun",icon=236179},
|
|
[255] = {name="Survival",class=3,role="DAMAGER",desc="An adaptive ranger who favors using explosives, animal venom, and coordinated attacks with their bonded beast.|n|nPreferred Weapon: Polearm, Staff",icon=461113},
|
|
[256] = {name="Discipline",class=5,role="HEALER",desc="Uses magic to shield allies from taking damage as well as heal their wounds.|n|nPreferred Weapon: Staff, Wand, Dagger, Mace",icon=135940},
|
|
[257] = {name="Holy",class=5,role="HEALER",desc="A versatile healer who can reverse damage on individuals or groups and even heal from beyond the grave.|n|nPreferred Weapon: Staff, Wand, Dagger, Mace",icon=237542},
|
|
[258] = {name="Shadow",class=5,role="DAMAGER",desc="Uses sinister Shadow magic and terrifying Void magic to eradicate enemies.|n|nPreferred Weapon: Staff, Wand, Dagger, Mace",icon=136207},
|
|
[259] = {name="Assassination",class=4,role="DAMAGER",desc="A deadly master of poisons who dispatches victims with vicious dagger strikes.|n|nPreferred Weapons: Daggers",icon=236270},
|
|
[260] = {name="Outlaw",class=4,role="DAMAGER",desc="A ruthless fugitive who uses agility and guile to stand toe-to-toe with enemies.|n|nPreferred Weapons: Axes, Maces, Swords, Fist Weapons",icon=236286},
|
|
[261] = {name="Subtlety",class=4,role="DAMAGER",desc="A dark stalker who leaps from the shadows to ambush $Ghis:her; unsuspecting prey.|n|nPreferred Weapons: Daggers",icon=132320},
|
|
[262] = {name="Elemental",class=7,role="DAMAGER",desc="A spellcaster who harnesses the destructive forces of nature and the elements.|n|nPreferred Weapon: Mace, Dagger, and Shield",icon=136048},
|
|
[263] = {name="Enhancement",class=7,role="DAMAGER",desc="A totemic warrior who strikes foes with weapons imbued with elemental power.|n|nPreferred Weapons: Dual Axes, Maces, Fist Weapons",icon=237581},
|
|
[264] = {name="Restoration",class=7,role="HEALER",desc="A healer who calls upon ancestral spirits and the cleansing power of water to mend allies' wounds.|n|nPreferred Weapon: Mace, Dagger, and Shield",icon=136052},
|
|
[265] = {name="Affliction",class=9,role="DAMAGER",desc="A master of shadow magic who specializes in drains and damage-over-time spells.|n|nPreferred Weapon: Staff, Wand, Dagger, Sword",icon=136145},
|
|
[266] = {name="Demonology",class=9,role="DAMAGER",desc="A commander of demons who twists the souls of $Ghis:her; army into devastating power.|n|nPreferred Weapon: Staff, Wand, Dagger, Sword",icon=136172},
|
|
[267] = {name="Destruction",class=9,role="DAMAGER",desc="A master of chaos who calls down fire to burn and demolish enemies.|n|nPreferred Weapon: Staff, Wand, Dagger, Sword",icon=136186},
|
|
[268] = {name="Brewmaster",class=10,role="TANK",desc="A sturdy brawler who uses unpredictable movement and mystical brews to avoid damage and protect allies.|n|nPreferred Weapon: Staff, Polearm",icon=608951},
|
|
[269] = {name="Windwalker",class=10,role="DAMAGER",desc="A martial artist without peer who pummels foes with hands and fists.|n|nPreferred Weapons: Fist Weapons, Axes, Maces, Swords",icon=608953},
|
|
[270] = {name="Mistweaver",class=10,role="HEALER",desc="A healer who masters the mysterious art of manipulating life energies aided by the wisdom of the Jade Serpent.|n|nPreferred Weapon: Staff, Mace, Sword",icon=608952},
|
|
[535] = {name="Ferocity",class=0,role="DAMAGER",desc="Driven by a rabid persistence to pursue prey, these carnivorous beasts stop at nothing to achieve victory; even death is temporary for these predators.",icon=236159},
|
|
[536] = {name="Cunning",class=0,role="DAMAGER",desc="",icon=132150},
|
|
[537] = {name="Tenacity",class=0,role="TANK",desc="",icon=132121},
|
|
[577] = {name="Havoc",class=12,role="DAMAGER",desc="A brooding master of warglaives and the destructive power of Fel magic.|n|nPreferred Weapons: Warglaives, Swords, Axes, Fist Weapons",icon=1247264},
|
|
[581] = {name="Vengeance",class=12,role="TANK",desc="Embraces the demon within to incinerate enemies and protect their allies.|n|nPreferred Weapons: Warglaives, Swords, Axes, Fist Weapons",icon=1247265},
|
|
[1467] = {name="Devastation",class=13,role="DAMAGER",desc="Releases innate power as chaotic Red flames or focused Blue magic to bathe the battlefield in destruction. Preferred Weapon: Staff, Sword, Dagger, Mace",icon=4511811},
|
|
[1468] = {name="Preservation",class=13,role="HEALER",desc="Calls upon the Emerald Dream to rejuvenate life, and the Bronze sands of time to prevent harm. Preferred Weapon: Staff, Sword, Dagger, Mace",icon=4511812},
|
|
[1473] = {name="Augmentation",class=13,role="DAMAGER",desc="Imbues allies with the might of the Black dragons, and bends time & fate in their favor with Bronze magic. Preferred Weapon: Staff, Sword, Dagger, Mace",icon=5198700},
|
|
}
|
|
|
|
ExRT.Classic.GetSpecializationInfoByID = function(id)
|
|
local data = specializationData[id] or ExRT.NULL
|
|
return id, data.name, data.desc, data.icon, data.role, ExRT.GDB.ClassList[data.class]
|
|
end
|
|
end
|
|
|
|
ExRT.GDB.JournalInstance = {
|
|
{0,64,238,63,240,234,227,239,231,237,233,241,229,228,236,232,226,230,311,316,246,0,741,742,743,744}, --Classic
|
|
{1,255,259,256,248,261,262,260,254,257,258,253,252,250,247,251,249,0,745,750,747,748,749,751,746,752}, --Burning Crusade
|
|
{2,285,286,281,282,279,277,273,272,275,274,283,271,280,284,278,276,0,760,754,759,755,756,753,758,757,761}, --Wrath of the Lich King
|
|
{3,64,63,77,65,70,66,68,71,67,69,76,184,185,186,0,73,72,78,74,75,187}, --Cataclysm
|
|
{4,312,313,302,303,321,311,316,246,324,0,322,320,317,330,362,369}, --Mists of Pandaria
|
|
{5,385,537,547,558,536,476,556,559,0,457,477,557,669}, --Warlords of Draenor
|
|
{6,716,767,762,721,727,707,740,726,777,800,860,900,945,0,768,822,959,786,861,875,946}, --Legion
|
|
{7,1012,1001,1041,968,1002,1023,1022,1021,1036,1030,1178,0,1028,1031,1176,1177,1179,1180}, --Battle for Azeroth
|
|
{8,1189,1186,1182,1185,1183,1184,1188,1187,1194,0,1190,1193,1195,1192}, --Shadowlands
|
|
{9,1197,1203,1198,1199,1196,1202,1201,1204,1209,0,1200,1207,1208,1205}, --Dragonflight
|
|
{-1,65,68,313,537,556,767,762,721,740,800,1001,968,1022,1021,1197,1203,1198,1199,1196,1202,1201,1204,1209,0,1200,1207,1208,1205}, --Current Season
|
|
{"11.0",10,1268,1267,1210,1269,1271,1272,1270,1274,0,1273,1278}, --The War Within
|
|
}
|
|
|
|
ExRT.GDB.MapIDToJournalInstance = {
|
|
[2774]=1278,[2690]=1293,[2690]=1293,[2689]=1284,[2688]=1290,[2687]=1283,[2686]=1285,[2685]=1289,[2684]=1288,[2683]=1282,[2682]=1291,[2681]=1281,[2680]=1287,[2679]=1280,[2669]=1274,[2664]=1279,[2662]=1270,
|
|
[2661]=1272,[2660]=1271,[2657]=1273,[2652]=1269,[2651]=1210,[2649]=1267,[2648]=1268,[2579]=1209,[2574]=1205,[2569]=1208,[2559]=1192,[2549]=1207,[2527]=1204,[2526]=1201,[2522]=1200,[2521]=1202,[2520]=1196,
|
|
[2519]=1199,[2516]=1198,[2515]=1203,[2481]=1195,[2451]=1197,[2450]=1193,[2441]=1194,[2296]=1190,[2293]=1187,[2291]=1188,[2290]=1184,[2289]=1183,[2287]=1185,[2286]=1182,[2285]=1186,[2284]=1189,[2217]=1180,
|
|
[2164]=1179,[2097]=1178,[2096]=1177,[2070]=1176,[1877]=1030,[1864]=1036,[1862]=1021,[1861]=1031,[1861]=1031,[1841]=1022,[1822]=1023,[1771]=1002,[1763]=968,[1762]=1041,[1754]=1001,[1753]=945,[1712]=946,
|
|
[1677]=900,[1676]=875,[1651]=860,[1648]=861,[1594]=1012,[1571]=800,[1544]=777,[1530]=786,[1520]=959,[1520]=959,[1520]=959,[1516]=726,[1501]=740,[1493]=707,[1492]=727,[1477]=721,[1466]=762,[1458]=767,[1456]=716,
|
|
[1448]=669,[1358]=559,[1279]=556,[1228]=557,[1228]=557,[1209]=476,[1208]=536,[1205]=457,[1195]=558,[1182]=547,[1176]=537,[1175]=385,[1136]=369,[1098]=362,[1011]=324,[1009]=330,[1008]=317,[1007]=246,[1004]=316,
|
|
[1001]=311,[996]=322,[996]=322,[994]=321,[967]=187,[962]=303,[961]=302,[960]=313,[959]=312,[940]=186,[939]=185,[938]=184,[859]=76,[757]=75,[755]=69,[754]=74,[725]=67,[724]=761,[720]=78,[671]=72,[670]=71,
|
|
[669]=73,[668]=276,[658]=278,[657]=68,[650]=284,[649]=757,[645]=66,[644]=70,[643]=65,[632]=280,[631]=758,[624]=753,[619]=271,[616]=756,[615]=755,[608]=283,[604]=274,[603]=759,[602]=275,[601]=272,[600]=273,
|
|
[599]=277,[595]=279,[585]=249,[580]=752,[578]=282,[576]=281,[575]=286,[574]=285,[568]=77,[565]=746,[564]=751,[560]=251,[558]=247,[557]=250,[556]=252,[555]=253,[554]=258,[553]=257,[552]=254,[550]=749,[548]=748,
|
|
[547]=260,[546]=262,[545]=261,[544]=747,[543]=248,[542]=256,[540]=259,[534]=750,[533]=754,[532]=745,[531]=744,[509]=743,[469]=742,[429]=230,[409]=741,[389]=226,[349]=232,[329]=236,[269]=255,[249]=760,[230]=228,
|
|
[229]=229,[209]=241,[129]=233,[109]=237,[90]=231,[70]=239,[48]=227,[47]=234,[43]=240,[36]=63,[34]=238,[33]=64,
|
|
}
|
|
|
|
ExRT.GDB.EncountersList = {
|
|
{350,652,653,654,655,656,657,658,659,660,661,662},
|
|
{331,651},
|
|
{330,649,650},
|
|
{332,623,624,625,626,627,628},
|
|
{334,730,731,732,733},
|
|
{329,618,619,620,621,622},
|
|
{335,724,725,726,727,728,729},
|
|
{129,519,520,2009,522,521,2010,2011,524,523,525,526,2012,527},
|
|
{130,2002,2003,2004,2005},
|
|
{132,1969,1966,1967,1989,1968},
|
|
{133,2026,2024,2025},
|
|
{136,2030,2027,2029,2028},
|
|
{138,1987,1985,1984,1986},
|
|
{140,1994,1996,1995,1998},
|
|
{141,1094},
|
|
{142,528,2013,530,529,2014,2015,532,531,533,534,2016,535},
|
|
{162,1107,1110,1116,1117,1112,1115,1113,1109,1121,1118,1111,1108,1120,1119,1114},
|
|
{155,1093,1092,1091,1090},
|
|
{147,1132,1136,1139,1142,1140,1137,1131,1135,1141,1164,1165,1166,1133,1138,1134,1143,1130},
|
|
{153,1978,1983,1980,1988,1981},
|
|
{156,1126,1127,1128,1129},
|
|
{157,1971,1972,1973},
|
|
{160,1974,1976,1977,1975},
|
|
{168,2018,2019,2020},
|
|
{171,2022,2023,2021},
|
|
{172,1088,1087,1086,1089,1085},
|
|
{183,2006,2007},
|
|
{184,1999,2001,2000},
|
|
{185,1992,1993,1990},
|
|
{186,1101,1100,1099,1096,1104,1097,1102,1095,1103,1098,1105,1106},
|
|
{200,1147,1149,1148,1150},
|
|
{213,1443,1444,1445,1446},
|
|
{219,593,594,595,596,597,598,599,600},
|
|
{220,492,488,486,487,490,491,493},
|
|
{221,1667,1668,1669,1675,1676,1670,1671,1672},
|
|
{225,1144,1145,1146},
|
|
{226,379,378,380,381,382},
|
|
{230,547,548,549,551,552,553,554,1887},
|
|
{232,663,664,665,666,667,668,669,670,671,672},
|
|
{233,785,784,786,787,788,789,790,791,792,793},
|
|
{234,343,344,345,346,350,347,348,349,361,362,363,364,365,366,367,368},
|
|
{242,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245},
|
|
{246,1935,1936,1937,1938},
|
|
{247,718,719,720,721,722,723},
|
|
{248,1084},
|
|
{250,267,268,269,270,271,272,274,273,275},
|
|
{256,1889,1890},
|
|
{258,1902,1903,1904},
|
|
{260,1908,1909,1910,1911},
|
|
{261,1922,1923,1924},
|
|
{262,1945,1946,1947,1948},
|
|
{263,1942,1943,1944},
|
|
{265,1939,1940,1941},
|
|
{266,1925,1926,1927,1928,1929},
|
|
{267,1930,1931,1932,1933,1934},
|
|
{269,1913,1914,1915,1916},
|
|
{272,1899,1900,250,1901},
|
|
{273,1919,1920,1921},
|
|
{274,1905,1906,1907},
|
|
{277,1052,1053,1054,1055},
|
|
{279,585,586,587,588,589,590,591,592},
|
|
{280,422,423,427,424,425,426,428,429},
|
|
{282,1033,1250,1332},
|
|
{283,1040,1038,1039,1037,1036},
|
|
{285,1027,1024,1022,1023,1025,1026},
|
|
{287,610,611,612,613,614,615,616,617},
|
|
{291,1064,1065,1063,1062,1060,1081},
|
|
{293,1051,1050,1048,1049},
|
|
{294,1030,1032,1028,1029,1082,1083},
|
|
{297,1080,1076,1075,1077,1074,1079,1078},
|
|
{300,1662,1663,1664,1665,1666},
|
|
{301,1656,438,1659,1660,1661},
|
|
{302,444,446,447,448,449,450},
|
|
{306,451,452,453,454,455,456,457,458,459,460,461,462,463},
|
|
{310,1069,1070,1071,1073,1072},
|
|
{317,473,474,476,475,477,478,472,479,480,481,482,483,484,1885},
|
|
{319,709,710,711,712,713,714,715,716,717},
|
|
{322,1045,1044,1046,1047},
|
|
{324,1056,1059,1058,1057},
|
|
{325,1043,1041,1042},
|
|
{328,1035,1034},
|
|
{333,1189,1190,1191,1192,1193,1194},
|
|
{337,1178,1179,1188,1180,1181,1182},
|
|
{339,601,602,603,604,605,606,607,608,609},
|
|
{347,1891,1892,1893},
|
|
{348,1894,1895,1897,1898},
|
|
{367,1197,1204,1205,1206,1200,1185,1203},
|
|
{398,1272,1273,1274},
|
|
{399,1337,1340,1339},
|
|
{401,1881,1882,1883,1884,1271},
|
|
{409,1292,1294,1295,1296,1297,1298,1291,1299},
|
|
{429,1418,1417,1416,1439},
|
|
{431,1422,1421,1420},
|
|
{435,1423,1424,1425},
|
|
{437,1397,1405,1406,1419},
|
|
{439,1412,1413,1414},
|
|
{443,1303,1304,1305,1306},
|
|
{453,1442,1509,1510,1441},
|
|
{456,1409,1505,1506,1431},
|
|
{457,1465,1502,1447,1464},
|
|
{471,1395,1390,1434,1436,1500,1407},
|
|
{474,1507,1504,1463,1498,1499,1501},
|
|
{476,1426,1427,1428,1429,1430},
|
|
{508,1577,1575,1570,1565,1578,1573,1572,1574,1576,1559,1560,1579,1580,1581},
|
|
{554,1563,1564,1571,1587},
|
|
{556,1602,1598,1624,1604,1622,1600,1606,1603,1595,1594,1599,1601,1593,1623,1605},
|
|
{573,1655,1653,1652,1654},
|
|
{574,1677,1688,1679,1682},
|
|
{593,1686,1685,1678,1714},
|
|
{595,1749,1748,1750,1754},
|
|
{601,1698,1699,1700,1701},
|
|
{606,1715,1732,1736},
|
|
|
|
{616,1761,1758,1759,1760,1762},
|
|
{620,1746,1757,1751,1752,1756},
|
|
{624,1755,1770,1801},
|
|
|
|
{703,1805,1806,1807,1808,1809},
|
|
{708,1822,1823,1824},
|
|
{710,1815,1850,1816,1817,1818},
|
|
{713,1810,1811,1812,1813,1814},
|
|
{731,1790,1791,1792,1793},
|
|
{732,1845,1846,1847,1848,1851,1852,1855,1856},
|
|
{733,1836,1837,1838,1839},
|
|
{749,1825,1826,1827,1828,1829},
|
|
{751,1832,1833,1834,1835},
|
|
{761,1868,1869,1870},
|
|
|
|
{790,1879,1880,1888,1917,1950,1951,1952,1953,1949},
|
|
|
|
{809,1957,1954,1961,1960,1964,1965,1959,2017,2031},
|
|
|
|
{845,2055,2057,2039,2053},
|
|
|
|
{903,2065,2066,2067,2068},
|
|
|
|
{934,2084,2085,2086,2087},
|
|
{936,2093,2094,2095,2096},
|
|
{974,2101,2102,2103,2104},
|
|
{1010,2105,2106,2107,2108},
|
|
{1015,2113,2114,2115,2116,2117},
|
|
{1041,2111,2118,2112,2123},
|
|
{1162,2098,2097,2109,2099,2100},
|
|
{1038,2124,2125,2126,2127},
|
|
{1039,2130,2131,2132,2133},
|
|
{1004,2139,2142,2140,2143},
|
|
{1490,2290,2292,2312,2291,2257,2258,2259,2260},
|
|
|
|
{1666,2387,2388,2389,2390},
|
|
{1674,2382,2384,2385,2386},
|
|
{1669,2397,2392,2393},
|
|
{1663,2401,2380,2403,2381},
|
|
{1693,2357,2356,2358,2359},
|
|
{1683,2391,2365,2366,2364,2404},
|
|
{1679,2395,2394,2400,2396},
|
|
{1675,2360,2361,2362,2363},
|
|
|
|
{2096,2570,2568,2567,2569},
|
|
{2071,2555,2556,2557,2558,2559},
|
|
{2093,2637,2636,2581,2580},
|
|
{2080,2613,2612,2610,2611},
|
|
{2097,2562,2563,2564,2565},
|
|
{2095,2609,2606,2623},
|
|
{2073,2582,2585,2583,2584},
|
|
{2082,2615,2616,2617,2618},
|
|
{2190,2666,2667,2668,2669,2670,2671,2672,2672,2673},
|
|
|
|
{"11.0",2316,2816,2861,2836}, --The Rookery:Dung
|
|
{"11.0",2308,2847,2835,2848}, --Priory of the Sacred Flame:Dung
|
|
{"11.0",2303,2829,2826,2787,2788}, --Darkflame Cleft:Dung
|
|
{"11.0",0,2854,2880,2888,2883}, --The Stonevault:Dung
|
|
{"11.0",0,2926,2906,2901}, --Ara-Kara, City of Echoes:Dung
|
|
{"11.0",2335,2900,2931,2929,2930}, --Cinderbrew Meadery:Dung
|
|
{"11.0",0,2837,2838,2839}, --The Dawnbreaker:Dung
|
|
{"11.0",2343,2907,2908,2905,2909}, --City of Threads:Dung
|
|
|
|
{610,1721,1706,1720,1722,1719,1723,1705},--HM
|
|
{596,1696,1691,1693,1694,1689,1692,1690,1713,1695,1704},--BF
|
|
{661,1778,1785,1787,1798,1786,1783,1788,1794,1777,1800,1784,1795,1799},--HFC
|
|
{777,1853,1841,1873,1854,1876,1877,1864},--EN
|
|
{806,1958,1962,2008},--tov
|
|
{764,1849,1865,1867,1871,1862,1886,1842,1863,1872,1866},--nighthold
|
|
{850,2032,2048,2036,2037,2050,2054,2052,2038,2051},--tos
|
|
{909,2076,2074,2064,2070,2075,2082,2069,2088,2073,2063,2092},--antorus
|
|
{1148,2144,2141,2136,2128,2134,2145,2135,2122},--uldir
|
|
{1358,2265,2263,2284,2266,2285,2271,2268,2272,2276,2280,2281}, --bfd
|
|
{1345,2269,2273}, --storms
|
|
{1512,2298,2305,2289,2304,2303,2311,2293,2299}, --ethernal place
|
|
{1582,2329,2327,2334,2328,2336,2333,2331,2335,2343,2345,2337,2344}, --nyalotha
|
|
{1735,2398,2418,2402,2383,2405,2406,2412,2399,2417,2407}, --castle Nathria
|
|
{1998,2423,2433,2429,2432,2434,2430,2436,2431,2422,2435}, --sod
|
|
{2047,2512,2540,2553,2544,2539,2542,2529,2546,2543,2549,2537}, --sfo
|
|
|
|
{2119,2587,2639,2590,2592,2635,2605,2614,2607}, --voti
|
|
{2166,2688,2682,2687,2693,2680,2689,2683,2684,2685}, --a
|
|
{2232,2820,2709,2737,2731,2728,2708,2824,2786,2677}, --d
|
|
|
|
{"11.0",2292,2902,2917,2898,2918,2919,2920,2921,2922}, --Nerub-ar Palace:Raid
|
|
}
|
|
|
|
function ExRT.F.EJ_AutoScan()
|
|
local TIER_MIN = 11
|
|
|
|
local NEW_DATA = {
|
|
encounterIDtoEJ = {},
|
|
EncountersList_dung = {},
|
|
EncountersList_raid = {},
|
|
MapIDToJournalInstance = {},
|
|
JournalInstance = {-2},
|
|
}
|
|
|
|
local encounterMap = {}
|
|
local dungeonPosInsert = 1
|
|
for i=1,#ExRT.GDB.EncountersList do
|
|
local dung = ExRT.GDB.EncountersList[i]
|
|
if dung[1] == 610 then
|
|
dungeonPosInsert = i
|
|
end
|
|
for j=2,#dung do
|
|
encounterMap[ dung[j] ] = true
|
|
end
|
|
end
|
|
local instanceMap = {}
|
|
for i=1,#ExRT.GDB.JournalInstance do
|
|
local tier = ExRT.GDB.JournalInstance[i]
|
|
for j=2,#tier do
|
|
instanceMap[ tier[j] ] = true
|
|
end
|
|
end
|
|
|
|
for i=TIER_MIN,EJ_GetNumTiers() do
|
|
EJ_SelectTier(i)
|
|
|
|
for j=1,2 do
|
|
local isRaid = j == 1 and true or false
|
|
|
|
local instanceIndex = 1
|
|
while EJ_GetInstanceByIndex(instanceIndex,isRaid) do
|
|
local instanceID, iname, description, bgImage, buttonImage1, loreImage, buttonImage2, dungeonAreaMapID, link, shouldDisplayDifficulty, mapID = EJ_GetInstanceByIndex(instanceIndex,isRaid)
|
|
|
|
EJ_SelectInstance(instanceID)
|
|
|
|
local isNewInstance = true
|
|
|
|
local EncountersList_new = {dungeonAreaMapID}
|
|
if dungeonAreaMapID == 0 then
|
|
isNewInstance = false --ignore world bosses
|
|
end
|
|
|
|
local encounterIndex = 1
|
|
while EJ_GetEncounterInfoByIndex(encounterIndex, instanceID) do
|
|
local name, description, journalEncounterID, rootSectionID, link, journalInstanceID, dungeonEncounterID, instanceID = EJ_GetEncounterInfoByIndex(encounterIndex, instanceID)
|
|
|
|
EncountersList_new[#EncountersList_new+1] = dungeonEncounterID
|
|
if dungeonEncounterID and encounterMap[dungeonEncounterID] then
|
|
isNewInstance = false
|
|
end
|
|
|
|
if dungeonEncounterID and not ExRT.GDB.encounterIDtoEJ[dungeonEncounterID] then
|
|
NEW_DATA.encounterIDtoEJ[dungeonEncounterID] = journalEncounterID
|
|
end
|
|
|
|
encounterIndex = encounterIndex + 1
|
|
end
|
|
|
|
if isNewInstance then
|
|
if isRaid then
|
|
tinsert(NEW_DATA.EncountersList_raid, EncountersList_new)
|
|
elseif isNewInstance then
|
|
tinsert(NEW_DATA.EncountersList_dung, EncountersList_new)
|
|
end
|
|
|
|
for k=2,#EncountersList_new do
|
|
encounterMap[ EncountersList_new[k] ] = true
|
|
end
|
|
|
|
--print('EncountersList','added',iname,encounterIndex-1)
|
|
end
|
|
|
|
if mapID and not ExRT.GDB.MapIDToJournalInstance[mapID] then
|
|
NEW_DATA.MapIDToJournalInstance[mapID] = instanceID
|
|
|
|
--print('MapIDToJournalInstance','added',iname)
|
|
end
|
|
|
|
if not instanceMap[instanceID] then
|
|
instanceMap[instanceID] = true
|
|
|
|
tinsert(NEW_DATA.JournalInstance, 2, instanceID)
|
|
|
|
--print('JournalInstance','added',iname)
|
|
end
|
|
|
|
instanceIndex = instanceIndex + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
VMRT.Addon.EJ_CHECK_VER = ExRT.clientUIinterface
|
|
VMRT.Addon.EJ_DATA = NEW_DATA
|
|
VMRT.Addon.EJ_CHECK_VER_PTR = ExRT.clientBuildVersion
|
|
|
|
ExRT.F.EJ_LoadData()
|
|
end
|
|
function ExRT.F.EJ_LoadData()
|
|
if not VMRT.Addon.EJ_DATA then
|
|
return
|
|
end
|
|
local NEW_DATA = VMRT.Addon.EJ_DATA
|
|
|
|
local encounterMap = {}
|
|
local dungeonPosInsert = 1
|
|
for i=1,#ExRT.GDB.EncountersList do
|
|
local dung = ExRT.GDB.EncountersList[i]
|
|
if dung[1] == 610 then
|
|
dungeonPosInsert = i
|
|
end
|
|
for j=2,#dung do
|
|
encounterMap[ dung[j] ] = true
|
|
end
|
|
end
|
|
|
|
for i=1,#NEW_DATA.EncountersList_raid do
|
|
local new_dung = NEW_DATA.EncountersList_raid[i]
|
|
if new_dung[2] and not encounterMap[ new_dung[2] ] then
|
|
tinsert(ExRT.GDB.EncountersList, new_dung)
|
|
end
|
|
end
|
|
for i=1,#NEW_DATA.EncountersList_dung do
|
|
local new_dung = NEW_DATA.EncountersList_dung[i]
|
|
if new_dung[2] and not encounterMap[ new_dung[2] ] then
|
|
tinsert(ExRT.GDB.EncountersList, dungeonPosInsert, new_dung)
|
|
dungeonPosInsert = dungeonPosInsert + 1
|
|
end
|
|
end
|
|
|
|
for k,v in pairs(NEW_DATA.MapIDToJournalInstance) do
|
|
if not ExRT.GDB.MapIDToJournalInstance[k] then
|
|
ExRT.GDB.MapIDToJournalInstance[k] = v
|
|
end
|
|
end
|
|
for k,v in pairs(NEW_DATA.encounterIDtoEJ) do
|
|
if not ExRT.GDB.encounterIDtoEJ[k] then
|
|
ExRT.GDB.encounterIDtoEJ[k] = v
|
|
end
|
|
end
|
|
if #NEW_DATA.JournalInstance > 1 then
|
|
tinsert(ExRT.GDB.JournalInstance,NEW_DATA.JournalInstance)
|
|
end
|
|
end
|
|
|
|
|
|
local ACTUAL_RAID = 1735
|
|
local ACTUAL_DUNG = 1666
|
|
if UnitLevel'player' > 70 then
|
|
ACTUAL_DUNG = 2316
|
|
ACTUAL_RAID = 2292
|
|
elseif UnitLevel'player' > 60 then
|
|
ACTUAL_DUNG = 2096
|
|
ACTUAL_RAID = 2119
|
|
end
|
|
|
|
do
|
|
local function StringVerToNumber(ver)
|
|
local i = 0
|
|
local r = 0
|
|
for n in ver:gmatch("%d+") do
|
|
r = r + tonumber(n) * (10 ^ i)
|
|
i = i - 2
|
|
end
|
|
return r
|
|
end
|
|
local ver_now = StringVerToNumber(GetBuildInfo())
|
|
for i=#ExRT.GDB.EncountersList,1,-1 do
|
|
local t = ExRT.GDB.EncountersList[i]
|
|
if type(t[1]) == "string" then
|
|
if StringVerToNumber(t[1]) > ver_now then
|
|
tremove(ExRT.GDB.EncountersList, i)
|
|
else
|
|
tremove(t, 1)
|
|
end
|
|
elseif t[1] == 2096 then
|
|
--stop loop for old data
|
|
break
|
|
end
|
|
end
|
|
for i=#ExRT.GDB.JournalInstance,1,-1 do
|
|
local t = ExRT.GDB.JournalInstance[i]
|
|
if type(t[1]) == "string" then
|
|
if StringVerToNumber(t[1]) > ver_now then
|
|
tremove(ExRT.GDB.JournalInstance, i)
|
|
else
|
|
tremove(t, 1)
|
|
end
|
|
else
|
|
for j=#t,2,-1 do
|
|
if type(t[j]) == "string" then
|
|
if StringVerToNumber(t[j]) > ver_now then
|
|
tremove(t, j)
|
|
end
|
|
tremove(t, j)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ExRT.F.GetEncountersList(onlyRaid,onlyActual,reverse)
|
|
local new = {}
|
|
|
|
local isActual,isRaid
|
|
for _,v in ipairs(ExRT.GDB.EncountersList) do
|
|
if v[1] == 610 then
|
|
isRaid = true
|
|
isActual = false
|
|
elseif v[1] == ACTUAL_DUNG then
|
|
isActual = true
|
|
elseif v[1] == ACTUAL_RAID then
|
|
isActual = true
|
|
end
|
|
if (not onlyActual or isActual) and (not onlyRaid or isRaid) then
|
|
new[#new+1] = v
|
|
end
|
|
end
|
|
if reverse then
|
|
local len = #new
|
|
for i=1,floor(len/2) do
|
|
new[i], new[len+1-i] = new[len+1-i], new[i]
|
|
end
|
|
end
|
|
return new
|
|
end
|