local KarmaObj = KarmaAvEnK; local KOH = KarmaObj.Helpers; -- Talents: Icons, if we got time... (or re-use existing!) --[[ local KARMA_TALENT_UNKNOWN = "QMark"; local KARMA_TALENT_DPS_PHYSICAL_MELEE = "RedTriangleM"; local KARMA_TALENT_DPS_PHYSICAL_RANGE = "RedTriangleR"; local KARMA_TALENT_DPS_MAGICAL = "BlueTriangle"; local KARMA_TALENT_HPS = "GreenTriangle"; local KARMA_TALENT_TANK = "GreyCircle"; ]]-- -- Bitfield -- 1-2-4 : HPS (1), TANK (2), DPS (4), Feral(6) -- 8-16 : MELEE(8), RANGED(16) local KARMA_TALENTS_MAXBITPLUS1 = 5; local KARMA_TALENTS = { [0] = { key = "KARMA_MISSING_INFO", color = "|cFF9F9F9F" }, [1] = { key = "KARMA_TALENT_HPS", color = "|cFF00FF00" }, -- spec: Dru/Pal/Shm/Pri [2] = { key = "KARMA_TALENT_TANK", color = "|cFFFFFFFF" }, -- spec: Dru/Pal/War tanks [4] = { key = "KARMA_TALENT_DPS", color = "|cFFFF0000" }, -- spec: all classes [6] = { key = "KARMA_TALENT_FERAL", color = "|cFFFF8080" }, -- spec: Feral [8] = { key = "KARMA_TALENT_MELEE", color = "|cFFFFA0A0" }, -- spec: Moonkin/Feral, ShamanMelee/Ranged [16] = { key = "KARMA_TALENT_RANGED", color = "|cFFFF00FF" } -- spec: Moonkin/Feral, ShamanMelee/Ranged }; -- default talents per class local KARMA_TALENTS_DEFAULT = { [1] = 0, -- druid: HPS/R, FERAL/M, DPS/R [2] = 20, -- hunter: DPS/R [3] = 20, -- mage: DPS/R [4] = 0, -- paladin: HPS/R, TANK/M, DPS/M [5] = 16, -- priest: HPS/R, DPS/R [6] = 12, -- rogue: DPS/M [7] = 0, -- shaman: HPS/R, DPS/M, DPS/R [8] = 8, -- warrior: TANK/M, DPS/M [9] = 20, -- warlock: DPS/R [10] = 8, -- deathknight: TANK/M, DPS/M [11] = 0, -- monk: HPS/R, TANK/M, DPS/M }; -- possible talents local KARMA_TALENT_CLASSMASK = { [1] = 31, -- druid: HPS/R, FERAL/M, DPS/R [2] = 20, -- hunter: DPS/R [3] = 20, -- mage: DPS/R [4] = 31, -- paladin: HPS/R, TANK/M, DPS/M [5] = 21, -- priest: HPS/R, DPS/R [6] = 12, -- rogue: DPS/M [7] = 29, -- shaman: HPS/R, DPS/M, DPS/R [8] = 14, -- warrior: TANK/M, DPS/M [9] = 20, -- warlock: DPS/R [10] = 14, -- deathknight: TANK/M, DPS/M [11] = 31, -- monk: HPS/R, TANK/M, DPS/M }; -- talent tree to probable talent (soon history) local KARMA_TALENT_BYTREE = { [1] = { [1] = 20, [2] = 14, [3] = 17 }, -- druid: DPS/R, Feral, HPS [2] = { [1] = 20, [2] = 20, [3] = 20 }, -- hunter [3] = { [1] = 20, [2] = 20, [3] = 20 }, -- mage [4] = { [1] = 17, [2] = 10, [3] = 12 }, -- paladin: HPS, Tank, DPS/M [5] = { [1] = 17, [2] = 17, [3] = 20 }, -- priest: HPS, HPS, DPS/R [6] = { [1] = 12, [2] = 12, [3] = 12 }, -- rogue [7] = { [1] = 20, [2] = 12, [3] = 17 }, -- shaman: DPS/R, DPS/M, HPS [8] = { [1] = 12, [2] = 12, [3] = 10 }, -- warrior: DPS/M, DPS/M, Tank [9] = { [1] = 20, [2] = 20, [3] = 20 }, -- warlock [10] = { [1] = 10, [2] = 12, [3] = 12 }, -- deathknight: Tank, DPS/M, DPS/M }; local KARMA_DB_L5_RRFFM = { CLASS_ID = "CLSID"; }; local KARMA_DB_L5_RRFFM_TALENTTREE = "TALENTTREE"; KarmaObj.Talents.SpecCount = 1; function KarmaObj.Talents.ClassIDToTalentsDefault(classid) -- KarmaChatDebug("classid = " .. tostring(classid) .. ", K_T_D[classid] = " .. Karma_NilToString(KARMA_TALENTS_DEFAULT[classid])); if (classid ~= nil) then if (classid < 0) then classid = - classid; end if (classid > 0) and (KARMA_TALENTS_DEFAULT[classid] ~= nil) then return KARMA_TALENTS_DEFAULT[classid], KARMA_TALENTS_DEFAULT[classid] ~= KARMA_TALENT_CLASSMASK[classid]; end end return 0, false; end function KarmaObj.Talents.MemberObjSpecNumToTalent(oMember, iSpec) if (type(oMember) == "table") then local oTree = oMember[KARMA_DB_L5_RRFFM_TALENTTREE]; if (type(oTree) == "table") then local classid = oMember[KARMA_DB_L5_RRFFM.CLASS_ID]; if (classid == 0) then classid = KOH.ClassToID(Karma_MemberObject_GetClass(oMember)); end if (classid < 0) then classid = - classid; end if (classid and (classid > 0)) then if (KarmaObj.Const.iTOC >= 50000) then local sSpec = "S_" .. iSpec; if (type(oTree[sSpec]) == "table") then local oTalent = KarmaObj.DB.CG.LocaleTalentGet(oTree[sSpec].Spec); local iResult = 0; if (oTalent.Role == "HEALER") then iResult = 17; elseif (oTalent.Role == "TANK") then iResult = 10; elseif (oTalent.Role == "DAMAGER") then iResult = 4; -- only druid and shaman can be M or R DPS if (classid == 1) then -- druid: 102 = moonkin, 103 = feral cat if (iSpec == 102) then iResult = 20; elseif (iSpec == 103) then iResult = 12; end elseif (classid == 7) then -- shaman: 262 = elemental, 263 = enhancement if (iSpec == 262) then iResult = 20; elseif (iSpec == 263) then iResult = 12; end elseif ((classid == 11) or (classid % 2 == 0)) then -- M: 4, 6, 8, 10, 11, iResult = 12; else -- R: 2, 3, 5, 9, iResult = 20; end end return iResult; elseif (oTree["S_" .. (3 - iSpec)]) then -- system went on Pandaria system, so everyone had to respec, -- => do not assume any old talent data being still valid return end end local iTotal, iTabMaxCnt, iTabMaxIx, iTab = 0, -1; local iNumTabs = 3; if (KarmaObj.Const.iTOC < 50000) then iNumTabs = GetNumTalentTabs(); end for iTab = 1, iNumTabs do local iCnt = oTree["T_" .. iSpec .. "_" .. iTab]; if (iCnt == nil) and (iSpec == 1) then iCnt = oTree["T_" .. iTab]; end if (iCnt) then iTotal = iTotal + iCnt.Points; if (iCnt.Points > iTabMaxCnt) then iTabMaxCnt = iCnt.Points; iTabMaxIx = iTab; end end end if (iTotal > 0) then if (iTabMaxCnt > 40 * iTotal / 71) then return KARMA_TALENT_BYTREE[classid][iTabMaxIx]; end end end end end end function KarmaObj.Talents.TreeObjToStringsObj(oTree, bShiftPressed) local aTrees, timeoftalents = { S_1 = "", S_2 = "" }; if (oTree) and (type(oTree) == "table") then if (oTree.Time) then timeoftalents = oTree.Time; end local sTreeText, value, sTreeName = ""; local iNumSpecs = KarmaObj.Talents.SpecCount; local iNumTabs = 3; if (KarmaObj.Const.iTOC < 50000) then iNumTabs = GetNumTalentTabs(); end local iSpec, iTab; for iSpec = 1, iNumSpecs do for iTab = 1, iNumTabs do if ((oTree["T_" .. iSpec .. "_" .. iTab] ~= nil) or (iSpec == 1) and (oTree["T_" .. iTab] ~= nil)) then -- T_1 .. T_n value = oTree["T_" .. iSpec .. "_" .. iTab]; if (value == nil) and (iSpec == 1) then value = oTree["T_" .. iTab]; end if (sTreeText ~= "") then sTreeText = sTreeText .. " / "; end if (bShiftPressed) then sTreeName = value.Name else -- sTreeName = strsub(value.Name, 1, 4); sTreeName = KarmaObj.UTF8.SubInChars(value.Name, 1, 4); end sTreeText = sTreeText .. sTreeName .. KARMA_WINEL_FRAG_COLONSPACE .. tostring(value.Points); end end if (KarmaObj.Const.iTOC >= 50000) then local sSpec = "S_" .. iSpec; if (type(oTree[sSpec]) == "table") then -- new Pandaria scheme: death of the talent trees aTrees["TIME_" .. iSpec] = oTree[sSpec].Time; local oTalent = KarmaObj.DB.CG.LocaleTalentGet(oTree[sSpec].Spec); if ((type(oTalent) == "table") and (oTalent.Name ~= nil)) then if (bShiftPressed) then sTreeText = oTalent.Name; else sTreeText = KarmaObj.UTF8.SubInChars(oTalent.Name, 1, 4); end end end end aTrees["S_" .. iSpec] = sTreeText; sTreeText = ""; KarmaChatDebug("KOT.TO2SO: Talents[" .. iSpec .. "] = " .. aTrees["S_" .. iSpec]); end end return aTrees, timeoftalents; end function KarmaObj.Talents.MemberObjToStringsObj(oMember, bShiftPressed) local oResult, sSummary = {}, ""; local iNumSpecs = KarmaObj.Talents.SpecCount; local aTalents = { S_1 = "", S_2 = "" }; local iSpec; for iSpec = 1, iNumSpecs do local sTalentText, iDerived = ""; local iTalent, bPattern = Karma_MemberObject_GetTalentID(oMember, iSpec); if (bPattern) then iDerived = KarmaObj.Talents.MemberObjSpecNumToTalent(oMember, iSpec); if (iDerived) then iTalent = iDerived; end end if (iTalent and (iTalent > 0)) then sTalentText = KarmaObj.Talents.TalentIDToColorizedText(iTalent) .. "|r"; if (iDerived) then sTalentText = "[" .. sTalentText .. "]"; end end aTalents["S_" .. iSpec] = sTalentText; KarmaChatDebug("KOT.MO2SO: Talents[" .. iSpec .. "] = " .. aTalents["S_" .. iSpec] .. "/" .. KOH.AllToString(bPattern)); end local oTree = oMember[KARMA_DB_L5_RRFFM_TALENTTREE]; local aTrees, timeoftalents = KarmaObj.Talents.TreeObjToStringsObj(oTree, bShiftPressed); for iSpec = 1, iNumSpecs do local sKey = "S_" .. iSpec; local sText = nil; if (aTalents[sKey] ~= "") then sText = aTalents[sKey]; if (aTrees[sKey] ~= "") then sText = sText .. " {" .. aTrees[sKey] .. "}"; end elseif (aTrees[sKey] ~= "") then sText = aTrees[sKey]; end if ((sText ~= nil) and (sText ~= "")) then -- only add if it's not already there: -- - skip if tree missing and spec equals previous spec if (aTrees[sKey] == "") then local iResCnt, iCurr = #oResult; if ((iResCnt > 0) and (strfind(aTalents[sKey], "%?") ~= nil)) then sText = nil; else for iCurr = 1, iResCnt do if (aTalents["S_" .. iCurr] == aTalents[sKey]) then sText = nil; break; end end end end if (sText) then sText = KARMA_MSG_TIP_TALENT .. KARMA_WINEL_FRAG_COLONSPACE .. sText; if (aTrees["TIME_" .. iSpec]) then sText = sText .. " @" .. date(KARMA_DATEFORMAT .. " %H:%M", aTrees["TIME_" .. iSpec]); end tinsert(oResult, sText); if (strfind(sText, "%?") == nil) then if (aTrees[sKey] == "") then sSummary = sSummary .. " "; else sSummary = sSummary .. " Talents(" .. iSpec .. ")"; end end end end end return oResult, sSummary, timeoftalents; end function KarmaObj.Talents.TalentID2Distance(iTalents) local sDistance = ""; local val = bit.band(iTalents, 24); if (val == 24) then sDistance = KARMA_TALENTS[0].color .. KARMA_MISSING_INFO_SMALL .. "|r"; elseif (val ~= 0) then local oTalents = KARMA_TALENTS[val]; if (oTalents) then local oTalentsLocalized = KARMA_TALENTS_LOCALIZED[oTalents.key]; if (oTalentsLocalized) then sDistance = oTalents.color .. oTalentsLocalized .. "|r"; else sDistance = "?L"; end else sDistance = "?T"; end end return sDistance; end function KarmaObj.Talents.TalentID2TextureDistance(iTalents, iClass) if ((iTalents == 0) or (iTalents == nil)) then return end iClass = math.abs(iClass); local sDistance = ""; if ((bit.band(iTalents, 4) == 4) and -- only dps can choose ((iClass == 1) or (iClass == 7))) then -- Druid, Shaman sDistance = KarmaObj.Talents.TalentID2Distance(iTalents); if (sDistance ~= "") then sDistance = "/" .. sDistance; end end -- "Interface\\LFGFrame\\LFGRole": -- 0.25: dps, 0.5: tank, 0.75: heal if (bit.band(iTalents, 7) == 0) then -- no icon to set :-( return sDistance; end if (bit.band(iTalents, 1) == 1) then -- healer return sDistance, "Interface\\LFGFrame\\LFGRole", 0.75, 1.0; end if (bit.band(iTalents, 6) == 2) then -- tank return sDistance, "Interface\\LFGFrame\\LFGRole", 0.5, 0.75; end if (bit.band(iTalents, 6) == 4) then if (bit.band(iTalents, 24) == 16) then -- dps: ranged if (iClass == 2) then -- hunter return sDistance, "Interface\\Icons\\INV_Ammo_Arrow_01", 0, 1; elseif (iClass == 3) then -- mage return sDistance, "Interface\\Icons\\Spell_Frost_IceStorm", 0, 1; elseif (iClass == 5) then -- priest return sDistance, "Interface\\Icons\\Spell_Shadow_ImprovedVampiricEmbrace", 0, 1; elseif ((iClass == 1) or (iClass == 7)) then -- druid, shaman -- Spell_Shaman_Thunderstorm? return sDistance, "Interface\\Icons\\Spell_Nature_Lightning", 0, 1; elseif (iClass == 9) then -- warlock return sDistance, "Interface\\Icons\\Spell_Shadow_LifeDrain02", 0, 1; end elseif (bit.band(iTalents, 24) == 8) then -- dps: melee if ((iClass == 4) or (iClass == 7)) then -- pala, shaman: hammer return sDistance, "Interface\\Icons\\Ability_Thunderbolt", 0, 1; elseif (iClass == 11) then -- monk return sDistance, "Interface\\Icons\\Spell_Misc_Petheal", 0, 1; end end return sDistance, "Interface\\LFGFrame\\LFGRole", 0.25, 0.5; end if (bit.band(iTalents, 6) == 6) then -- feral/dk hybrid return sDistance, "Interface\\LFGFrame\\LFGRole", 0.25, 0.75; end end function KarmaObj.Talents.TalentIDToColorizedText(talentid) if (talentid) and (talentid > 0) then local talenttext = ""; local subid, _subid; local subval = 1; local skip = false; -- KARMA_TALENTS_MAXBITPLUS1 = 5 -- 1(1) = hps, 2(2) = tank, 3(4) = dps <=> %8 -- 4 (1/16) = melee, 5 (2/24) = ranged <=> %4 / % 24 _subid = 1; for subid = 1, KARMA_TALENTS_MAXBITPLUS1 do --KarmaChatDebug("subid = " .. tostring(subid) .. ", _subid = " .. tostring(_subid) .. ", talentid = " .. tostring(talentid)); -- special cases: if (_subid == 1) then -- neither TANK nor DPS nor HPS set (multispec class) if (talentid % 8) == 0 then talenttext = talenttext .. KARMA_TALENTS[0].color .. KARMA_MISSING_INFO; end end if (_subid == 4) then talenttext = talenttext .. "|r/"; -- neither M nor R set (multispec class) if (talentid % 4 == 0) then talenttext = talenttext .. KARMA_TALENTS[0].color .. KARMA_MISSING_INFO_SMALL; end end -- no more feral dual with MoP *mopes* if (KarmaObj.Const.iTOC < 50000) then -- special case: FERAL = 6 (TANK + DPS) if (_subid == 2) then if (talentid % 4) == 3 then subval = 6; if KARMA_TALENTS[subval] then if KARMA_TALENTS_LOCALIZED[KARMA_TALENTS[subval].key] then talenttext = talenttext .. KARMA_TALENTS[subval].color .. KARMA_TALENTS_LOCALIZED[KARMA_TALENTS[subval].key]; else talenttext = talenttext .. "?L"; end else talenttext = talenttext .. "?T"; end talentid = talentid - 3; talentid = talentid / 4; subval = 8; _subid = _subid + 1; skip = true; end end end if not skip then if (talentid % 2) == 1 then if KARMA_TALENTS[subval] then if KARMA_TALENTS_LOCALIZED[KARMA_TALENTS[subval].key] then talenttext = talenttext .. KARMA_TALENTS[subval].color .. KARMA_TALENTS_LOCALIZED[KARMA_TALENTS[subval].key]; else talenttext = talenttext .. "?L"; end else talenttext = talenttext .. "?T"; end talentid = talentid - 1; end talentid = talentid / 2; subval = subval * 2; else skip = false end _subid = _subid + 1; end if (talenttext ~= nil) then return talenttext .. "|r"; end end return (KARMA_TALENTS[0].color .. KARMA_MISSING_INFO .. "|r"); end function KarmaObj.Talents.ClassMask(iClass) if (type(iClass) == "number") then return KARMA_TALENT_CLASSMASK[iClass]; end end function KarmaObj.Talents.Test() local oMember = Karma_MemberList_GetObject("Kenkkey"); local oData, sSummary, iTime = KarmaObj.Talents.MemberObjToStringsObj(oMember, true); KarmaChatDebug("Test: Result of MemberObjToStringsObj: " .. KOH.TableToString(oData) .. " / " .. sSummary .. " / " .. iTime); end