|
|
|
|
local _, addon = ...
|
|
|
|
|
local L = Narci.L;
|
|
|
|
|
local DoesItemExistByID = addon.DoesItemExistByID;
|
|
|
|
|
local Gemma = addon.Gemma;
|
|
|
|
|
local AtlasUtil = Gemma.AtlasUtil;
|
|
|
|
|
local BagScan = Gemma.BagScan;
|
|
|
|
|
local DataProvider = {};
|
|
|
|
|
local GemManagerMixin = {};
|
|
|
|
|
DataProvider.GemManagerMixin = GemManagerMixin;
|
|
|
|
|
Gemma:AddDataProvider("Pandaria", DataProvider);
|
|
|
|
|
|
|
|
|
|
local BagUtil = {};
|
|
|
|
|
|
|
|
|
|
local pairs = pairs;
|
|
|
|
|
local ipairs = ipairs;
|
|
|
|
|
local tsort = table.sort;
|
|
|
|
|
|
|
|
|
|
local PATH = "Interface/AddOns/Narcissus/Art/Modules/GemManager/";
|
|
|
|
|
|
|
|
|
|
local GetItemGemID = C_Item.GetItemGemID;
|
|
|
|
|
local GetItemNumSockets = C_Item.GetItemNumSockets; --10.2.7
|
|
|
|
|
local IsEquippableItem = C_Item.IsEquippableItem;
|
|
|
|
|
local GetItemInfoInstant = C_Item.GetItemInfoInstant;
|
|
|
|
|
local GetItemCount = C_Item.GetItemCount;
|
|
|
|
|
local GetInventoryItemLink = GetInventoryItemLink;
|
|
|
|
|
local GetCVarBool = C_CVar.GetCVarBool;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local MainFrame;
|
|
|
|
|
|
|
|
|
|
local GEM_TYPES = {
|
|
|
|
|
[1] = "META",
|
|
|
|
|
[2] = "COGWHEEL",
|
|
|
|
|
[3] = "TINKER",
|
|
|
|
|
[4] = "PRISMATIC",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local SLOT_ID = {
|
|
|
|
|
HEAD = 1,
|
|
|
|
|
FEET = 8,
|
|
|
|
|
|
|
|
|
|
SHOULDER = 3,
|
|
|
|
|
WRIST = 9,
|
|
|
|
|
HANDS = 10,
|
|
|
|
|
WAIST = 6,
|
|
|
|
|
|
|
|
|
|
NECK = 2,
|
|
|
|
|
CHEST = 5,
|
|
|
|
|
LEGS = 7,
|
|
|
|
|
RING1 = 11,
|
|
|
|
|
RING2 = 12,
|
|
|
|
|
TRINKET1 = 13,
|
|
|
|
|
TRINKET2 = 14,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local GEM_DATA = {
|
|
|
|
|
--[itemID] = {type, spellID, role, uiOrder, scaleWithIlvl}
|
|
|
|
|
--role: bits 000 (Tank/Healer/DPS): Tank 100(4), DPS 001(1), H/D 011(3), H 010(2)
|
|
|
|
|
|
|
|
|
|
--Total: 11
|
|
|
|
|
[221982] = {1, 447598, 4, 00}, --Bulwark of the Black Ox: Charge, Taunt, Ward
|
|
|
|
|
[221977] = {1, 447566, 1, 20}, --Funeral Pyre: Stat, Self Harm
|
|
|
|
|
[220211] = {1, 444954, 2, 60}, --Precipice of Madness: Ward
|
|
|
|
|
[220120] = {1, 444677, 4, 70}, --Soul Tether: Redirect Damage
|
|
|
|
|
[220117] = {1, 444622, 2, 90}, --Ward of Salvation: Restore HP, Overhealing to Ward, AoE
|
|
|
|
|
[219878] = {1, 444128, 7, 85}, --Tireless Spirit: Reduce Resouce Cost
|
|
|
|
|
[219386] = {1, 443389, 7, 35}, --Locus of Power: Stats
|
|
|
|
|
--[216974] = {1, 437495, 1, 40}, --Morphing Elements: Summon Portal, AoE
|
|
|
|
|
[216711] = {1, 426268, 3, 10}, --Chi-ji, the Red Crane --426268, 437018
|
|
|
|
|
[216695] = {1, 437011, 3, 30}, --Lifestorm: Damage then Restore HP and Haste
|
|
|
|
|
[216671] = {1, 426748, 7, 80}, --Thundering Orb: Transform, DR, Movement
|
|
|
|
|
[216663] = {1, 435313, 1, 50}, --Oblivion Sphere: Crit Damage Taken, AoE, Control
|
|
|
|
|
|
|
|
|
|
--Total:17
|
|
|
|
|
[218110] = {2, 441759, 7, 45}, --Soulshape
|
|
|
|
|
[218109] = {2, 441749, 7, 10}, --Death's Advance
|
|
|
|
|
[218108] = {2, 441741, 7, 05}, --Dark Pack
|
|
|
|
|
[218082] = {2, 441617, 7, 55}, --Spiritwalker's Grace (Cast while Moving)
|
|
|
|
|
[218046] = {2, 441576, 7, 50}, --Spirit Walk
|
|
|
|
|
[218045] = {2, 441569, 7, 20}, --Door of Shadows
|
|
|
|
|
[218044] = {2, 441564, 7, 35}, --Pursuit of Justice (Passive)
|
|
|
|
|
[218043] = {2, 441559, 7, 80}, --Wild Charge
|
|
|
|
|
[218005] = {2, 441493, 7, 65}, --Stampeding Roar
|
|
|
|
|
[218004] = {2, 441479, 7, 75}, --Vanish
|
|
|
|
|
[218003] = {2, 441467, 7, 30}, --Leap of Faith
|
|
|
|
|
[217989] = {2, 441348, 7, 70}, --Trailblazer
|
|
|
|
|
[217983] = {2, 441299, 7, 15}, --Disengage
|
|
|
|
|
[216632] = {2, 427030, 7, 60}, --Sprint
|
|
|
|
|
[216631] = {2, 427026, 7, 40}, --Roll
|
|
|
|
|
[216630] = {2, 427033, 7, 25}, --Heroic Leap
|
|
|
|
|
[216629] = {2, 427053, 7, 05}, --Blink
|
|
|
|
|
|
|
|
|
|
--Total: 36
|
|
|
|
|
[219801] = {3, 427064, 7, 00}, --Ankh of Reincarnation: Self-rez
|
|
|
|
|
[212366] = {3, 429270, 3, 28}, --Arcanist's Edge: Consume shield to deal damage *
|
|
|
|
|
[219944] = {3, 444455, 2, 03}, --Bloodthirsty Coral: Damage taken to Healing
|
|
|
|
|
[219818] = {3, 429007, 7, 06}, --Brilliance: Party Resouce Regen
|
|
|
|
|
[216649] = {3, 436578, 1, 09}, --Brittle: Store Damage Done, Death Trigger AoE
|
|
|
|
|
[216648] = {3, 436577, 7, 12}, --Cold Front: Allies Ward, Enemies Debuff
|
|
|
|
|
[217957] = {3, 441165, 2, 15}, --Deliverance: Store Healing. Healing when Low HP
|
|
|
|
|
[212694] = {3, 433362, 3, 29}, --Enkindle: Grant shield, Damage attackers, Increase haste *
|
|
|
|
|
[212749] = {3, 433361, 1, 102}, --Explosive Barrage: AoE
|
|
|
|
|
[212365] = {3, 429389, 1, 103}, --Fervor: Consume HP to deal holy damage
|
|
|
|
|
[219817] = {3, 429026, 7, 18}, --Freedom: Ckear Loss of Control
|
|
|
|
|
[212916] = {3, 436528, 5, 104}, --Frost Armor: Damage and slow attackers
|
|
|
|
|
[219777] = {3, 428854, 4, 21}, --Grounding: Redirect Harmful Spell
|
|
|
|
|
[217964] = {3, 441209, 2, 27}, --Holy Martyr: Damage Taken to Party Healing
|
|
|
|
|
[216647] = {3, 436571, 1, 24}, --Hailstorm: AoE and Debuff
|
|
|
|
|
[212758] = {3, 433360, 1, 105}, --Incendiary Terror: Damage and Horrify
|
|
|
|
|
[219389] = {3, 443498, 3, 30}, --Lightning Rod: Crit on Ally or Dot on Enemy
|
|
|
|
|
[216624] = {3, 436461, 5, 33}, --Mark of Arrogance: Dot on Attackers
|
|
|
|
|
[216650] = {3, 436583, 7, 36}, --Memory of Vegeance: For every 10s, gain primary stat for every 5% missing HP
|
|
|
|
|
[212759] = {3, 433358, 1, 106}, --Metero Storm: AoE and stun
|
|
|
|
|
[212361] = {3, 427054, 1, 107}, --Opportunist: Grant crit when damaging stunned enemey
|
|
|
|
|
[216625] = {3, 429373, 1, 39}, --Quick Strike: Melee Ability Triggers Additional Autoattacks
|
|
|
|
|
[217961] = {3, 441198, 2, 42}, --Righteous Frenzy: Healing Proc Haste on Ally
|
|
|
|
|
[217927] = {3, 441150, 2, 45}, --Savior: Healing Low HP Ally Grants Ward
|
|
|
|
|
[216651] = {3, 436586, 3, 48}, --Searing Light: Healing to Heal and AoE Damage
|
|
|
|
|
[216626] = {3, 429378, 1, 51}, --Slay: Extra Damage to Low Health Enemy
|
|
|
|
|
[219452] = {3, 443670, 3, 54}, --Static Charge: Heal or Damage
|
|
|
|
|
[219523] = {3, 443834, 1, 57}, --Storm Overload: AoE, Control
|
|
|
|
|
[212362] = {3, 436465, 1, 108}, --Sunstrider's Flourish: Crit cause AoE
|
|
|
|
|
[216627] = {3, 429230, 2, 60}, --Tinkmaster's Shield: Ward after not being damaged for 5s
|
|
|
|
|
[219527] = {3, 443855, 7, 63}, --Vampiric Aura: +Leech, Party Leech
|
|
|
|
|
[216628] = {3, 436467, 3, 66}, --Victory Fire: Enemy Death trigger AoE Damage and Healing
|
|
|
|
|
[217903] = {3, 441092, 3, 69}, --Vindication: Damage Done Heals Allies
|
|
|
|
|
[217907] = {3, 441115, 4, 72}, --Warmth: +Healing Taken, Redistribute Overhealing
|
|
|
|
|
[212760] = {3, 433356, 1, 109}, --Wildfire: Dot, Spreading
|
|
|
|
|
[219516] = {3, 443787, 7, 110}, --Windweaver: +Movement Speed, Falling damage immunity, chance to increase party haste
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[210714] = {4, nil, 1, 30}, --Crit +
|
|
|
|
|
[216644] = {4, nil, 1, 20}, --Crit ++
|
|
|
|
|
[211123] = {4, nil, 1, 10}, --Crit +++
|
|
|
|
|
[211102] = {4, nil, 1, 00}, --Crit +++, STAM
|
|
|
|
|
[210681] = {4, nil, 2, 31}, --Haste +
|
|
|
|
|
[216643] = {4, nil, 2, 21}, --Haste ++
|
|
|
|
|
[211107] = {4, nil, 2, 11}, --Haste +++
|
|
|
|
|
[211110] = {4, nil, 2, 01}, --Haste +++, STAM
|
|
|
|
|
[210715] = {4, nil, 3, 32}, --Mastery +
|
|
|
|
|
[216640] = {4, nil, 3, 22}, --Mastery ++
|
|
|
|
|
[211106] = {4, nil, 3, 12}, --Mastery +++
|
|
|
|
|
[211108] = {4, nil, 3, 02}, --Mastery +++, STAM
|
|
|
|
|
[220371] = {4, nil, 4, 33}, --Vers +
|
|
|
|
|
[220372] = {4, nil, 4, 23}, --Vers ++
|
|
|
|
|
[220374] = {4, nil, 4, 13}, --Vers +++
|
|
|
|
|
[220373] = {4, nil, 4, 03}, --Vers +++, STAM
|
|
|
|
|
[220367] = {4, nil, 5, 35}, --Armor +
|
|
|
|
|
[220368] = {4, nil, 5, 25}, --Armor ++
|
|
|
|
|
[220370] = {4, nil, 5, 15}, --Armor +++
|
|
|
|
|
[220369] = {4, nil, 5, 05}, --Armor +++, STAM
|
|
|
|
|
--[211109] = {4, nil, 6, 36}, --Regen +
|
|
|
|
|
--[216642] = {4, nil, 6, 26}, --Regen ++
|
|
|
|
|
--[211125] = {4, nil, 6, 16}, --Regen +++
|
|
|
|
|
--[211105] = {4, nil, 6, 06}, --Regen +++, STAM
|
|
|
|
|
[210717] = {4, nil, 6, 37}, --Leech +
|
|
|
|
|
[216641] = {4, nil, 6, 27}, --Leech ++
|
|
|
|
|
[210718] = {4, nil, 6, 17}, --Leech +++
|
|
|
|
|
[211103] = {4, nil, 6, 07}, --Leech +++, STAM
|
|
|
|
|
[210716] = {4, nil, 7, 38}, --Speed +
|
|
|
|
|
[216639] = {4, nil, 7, 28}, --Speed ++
|
|
|
|
|
[211124] = {4, nil, 7, 18}, --Speed +++
|
|
|
|
|
[211101] = {4, nil, 7, 08}, --Speed +++, STAM
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local CUSTOM_SORT_ORDER = {
|
|
|
|
|
[219801] = 3, --Ankh of Reincarnation
|
|
|
|
|
[212366] = 26, --Arcanist's Edge
|
|
|
|
|
[219944] = 10, --Bloodthirsty Coral
|
|
|
|
|
[219818] = 13, --Brilliance
|
|
|
|
|
[216649] = 11, --Brittle
|
|
|
|
|
[216648] = 16, --Cold Front
|
|
|
|
|
[217957] = 36, --Deliverance
|
|
|
|
|
[212694] = 8, --Enkindle
|
|
|
|
|
[212749] = 30, --Explosive Barrage
|
|
|
|
|
[212365] = 32, --Fervor
|
|
|
|
|
[219817] = 2, --Freedom
|
|
|
|
|
[212916] = 4, --Frost Armor
|
|
|
|
|
[219777] = 1, --Grounding
|
|
|
|
|
[216647] = 22, --Hailstorm
|
|
|
|
|
[217964] = 5, --Holy Martyr
|
|
|
|
|
[212758] = 31, --Incendiary Terror
|
|
|
|
|
[219389] = 33, --Lightning Rod
|
|
|
|
|
[216624] = 7, --Mark of Arrogance
|
|
|
|
|
[216650] = 9, --Memory of Vegeance
|
|
|
|
|
[212759] = 23, --Metero Storm
|
|
|
|
|
[212361] = 12, --Opportunist
|
|
|
|
|
[216625] = 29, --Quick Strike
|
|
|
|
|
[217961] = 27, --Righteous Frenzy
|
|
|
|
|
[217927] = 28, --Savior
|
|
|
|
|
[216651] = 35, --Searing Light
|
|
|
|
|
[216626] = 19, --Slay
|
|
|
|
|
[219452] = 14, --Static Charge
|
|
|
|
|
[219523] = 18, --Storm Overload
|
|
|
|
|
[212362] = 24, --Sunstrider's Flourish
|
|
|
|
|
[216627] = 21, --Tinkmaster's Shield
|
|
|
|
|
[219527] = 20, --Vampiric Aura
|
|
|
|
|
[216628] = 34, --Victory Fire
|
|
|
|
|
[217903] = 25, --Vindication
|
|
|
|
|
[217907] = 6, --Warmth
|
|
|
|
|
[212760] = 17, --Wildfire
|
|
|
|
|
[219516] = 15, --Windweaver
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local FALLBACK_TINKERS = {
|
|
|
|
|
--When player doesn't own all saved tinkers and have empty sockets. Prioritize DPS gem
|
|
|
|
|
216626, 219389, 212694, 219516, 212749, 212365,
|
|
|
|
|
212758, 216647, 212362, 212760, 216649, 212759,
|
|
|
|
|
219818, 216648, 219523, 219452, 216651, 216628,
|
|
|
|
|
212916, 212366, 219801, 219944, 217957, 219817,
|
|
|
|
|
219777, 217964, 216624, 216650, 212361, 216625,
|
|
|
|
|
217961, 217927, 216627, 219527, 217903, 217907,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local STAT_GEMS = {
|
|
|
|
|
[1] = {210714, 216644, 211123, 211102}, --Crit
|
|
|
|
|
[2] = {210681, 216643, 211107, 211110}, --Haste
|
|
|
|
|
[3] = {210715, 216640, 211106, 211108}, --Mastery
|
|
|
|
|
[4] = {220371, 220372, 220374, 220373}, --Vers
|
|
|
|
|
[5] = {220367, 220368, 220370, 220369}, --Armor
|
|
|
|
|
--[6] = {211109, 216642, 211125, 211105}, --Regen
|
|
|
|
|
[6] = {210717, 216641, 210718, 211103}, --Leech
|
|
|
|
|
[7] = {210716, 216639, 211124, 211101}, --Speed
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local GEM_REMOVAL_TOOL = {"spell", 433397};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local STATS_DATA = {
|
|
|
|
|
--Data change dynamically
|
|
|
|
|
--{name, }
|
|
|
|
|
{STAT_CRITICAL_STRIKE, },
|
|
|
|
|
{STAT_HASTE, },
|
|
|
|
|
{STAT_MASTERY, },
|
|
|
|
|
{STAT_VERSATILITY, },
|
|
|
|
|
{STAT_ARMOR, },
|
|
|
|
|
--{L["Stat Health Regen"], },
|
|
|
|
|
{STAT_LIFESTEAL, },
|
|
|
|
|
{STAT_SPEED},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local function SortFunc_UIOrder(a, b)
|
|
|
|
|
if CUSTOM_SORT_ORDER[a] and CUSTOM_SORT_ORDER[b] then
|
|
|
|
|
return CUSTOM_SORT_ORDER[a] < CUSTOM_SORT_ORDER[b]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if GEM_DATA[a][4] and GEM_DATA[b][4] then
|
|
|
|
|
return GEM_DATA[a][4] < GEM_DATA[b][4]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return a < b
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetSortedItemList()
|
|
|
|
|
--Loaded once when used
|
|
|
|
|
|
|
|
|
|
if self.gemList then return self.gemList end;
|
|
|
|
|
|
|
|
|
|
local tinsert = table.insert;
|
|
|
|
|
local tsort = tsort;
|
|
|
|
|
|
|
|
|
|
local tbl = {};
|
|
|
|
|
local numTypes = #GEM_TYPES;
|
|
|
|
|
|
|
|
|
|
for i = 1, numTypes do
|
|
|
|
|
tbl[i] = {};
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for itemID, data in pairs(GEM_DATA) do
|
|
|
|
|
if DoesItemExistByID(itemID) then
|
|
|
|
|
local gemType = data[1];
|
|
|
|
|
tinsert(tbl[gemType], itemID);
|
|
|
|
|
Gemma:SetGemRemovalTool(itemID, GEM_REMOVAL_TOOL);
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for gemType, gems in pairs(tbl) do
|
|
|
|
|
tsort(gems, SortFunc_UIOrder);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.gemList = tbl;
|
|
|
|
|
|
|
|
|
|
return tbl
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetGemTypeName(gemType)
|
|
|
|
|
local lookup = "EMPTY_SOCKET_"..GEM_TYPES[gemType];
|
|
|
|
|
if _G[lookup] then
|
|
|
|
|
return _G[lookup]
|
|
|
|
|
else
|
|
|
|
|
return GEM_TYPES[gemType]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetItemListByType(gemType)
|
|
|
|
|
local itemList = self:GetSortedItemList();
|
|
|
|
|
return itemList[gemType];
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function GetNumSocketsForSlot(slotID)
|
|
|
|
|
local itemLink = GetInventoryItemLink("player", slotID);
|
|
|
|
|
if itemLink then
|
|
|
|
|
return GetItemNumSockets(itemLink) or 0
|
|
|
|
|
else
|
|
|
|
|
return 0
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function GetItemGemFromSlot(slotID, index)
|
|
|
|
|
local itemLink = GetInventoryItemLink("player", slotID);
|
|
|
|
|
if itemLink then
|
|
|
|
|
return GetItemGemID(itemLink, index);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:DoesPlayerHaveHead()
|
|
|
|
|
return GetNumSocketsForSlot(SLOT_ID.HEAD) > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:DoesPlayerHaveFeet()
|
|
|
|
|
return GetNumSocketsForSlot(SLOT_ID.FEET) > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetHeadGem()
|
|
|
|
|
return GetItemGemFromSlot(SLOT_ID.HEAD, 1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetFeetGem()
|
|
|
|
|
return GetItemGemFromSlot(SLOT_ID.FEET, 1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetGemType(itemID)
|
|
|
|
|
if GEM_DATA[itemID] then
|
|
|
|
|
return GEM_DATA[itemID][1]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetGemSpell(itemID)
|
|
|
|
|
if GEM_DATA[itemID] then
|
|
|
|
|
return GEM_DATA[itemID][2]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetStatType(itemID)
|
|
|
|
|
if self:GetGemType(itemID) == 4 then
|
|
|
|
|
return GEM_DATA[itemID][3]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetConflictGemItemID(itemID)
|
|
|
|
|
local gemType = self:GetGemType(itemID);
|
|
|
|
|
if gemType == 1 then
|
|
|
|
|
local existingGem = self:GetHeadGem();
|
|
|
|
|
if itemID ~= existingGem then
|
|
|
|
|
return existingGem
|
|
|
|
|
end
|
|
|
|
|
elseif gemType == 2 then
|
|
|
|
|
local existingGem = self:GetFeetGem();
|
|
|
|
|
if itemID ~= existingGem then
|
|
|
|
|
return existingGem
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetActiveGems()
|
|
|
|
|
return BagUtil.activeGemList
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do --Scan bag and equipment slot
|
|
|
|
|
function BagUtil:ResetBagInfo()
|
|
|
|
|
self.gemCount = {}; --Including all locations
|
|
|
|
|
self.bagGemCount = {}; --Including those in equipment
|
|
|
|
|
self.bagUsedGemCount = {}; --Gems in your bag equipment
|
|
|
|
|
self.slotData = {};
|
|
|
|
|
self.gemTypeAvailable = {};
|
|
|
|
|
self.activeGemCount = {};
|
|
|
|
|
self.activeGemList = nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function SortFunc_ActiveTraits(itemID1, itemID2)
|
|
|
|
|
local type1 = GEM_DATA[itemID1][1];
|
|
|
|
|
local type2 = GEM_DATA[itemID2][1];
|
|
|
|
|
|
|
|
|
|
if type1 ~= type2 then
|
|
|
|
|
return type1 < type2
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return itemID1 < itemID2
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function BagUtil:OnScanComplete()
|
|
|
|
|
if not self.activeGemCount then return end;
|
|
|
|
|
|
|
|
|
|
local gemType, statType;
|
|
|
|
|
local traitList = {};
|
|
|
|
|
local statList = {};
|
|
|
|
|
local n = 0;
|
|
|
|
|
for itemID, count in pairs(self.activeGemCount) do
|
|
|
|
|
gemType = DataProvider:GetGemType(itemID);
|
|
|
|
|
if gemType then
|
|
|
|
|
if gemType == 4 then
|
|
|
|
|
statType = GEM_DATA[itemID][3];
|
|
|
|
|
if not statList[statType] then
|
|
|
|
|
local name = STATS_DATA[statType][1];
|
|
|
|
|
statList[statType] = {0, name};
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
statList[statType][1] = statList[statType][1] + count;
|
|
|
|
|
else
|
|
|
|
|
n = n + 1;
|
|
|
|
|
traitList[n] = itemID;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
tsort(traitList, SortFunc_ActiveTraits);
|
|
|
|
|
|
|
|
|
|
self.activeGemList = {
|
|
|
|
|
traits = traitList,
|
|
|
|
|
stats = statList,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (not Gemma.MainFrame:IsShown()) and Gemma.PaperdollWidget:IsShown() and DataProvider:ShouldShowGreenDot() then
|
|
|
|
|
Gemma.MainFrame:Show();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function BagUtil_ProcessItem(itemLink, id1, id2)
|
|
|
|
|
if IsEquippableItem(itemLink) then
|
|
|
|
|
local numSockets = GetItemNumSockets(itemLink);
|
|
|
|
|
local slotData;
|
|
|
|
|
|
|
|
|
|
if (not id2) and (numSockets > 0) then
|
|
|
|
|
--id1: slotID
|
|
|
|
|
slotData = {
|
|
|
|
|
gems = {},
|
|
|
|
|
numSockets = numSockets,
|
|
|
|
|
numMissing = 0,
|
|
|
|
|
};
|
|
|
|
|
BagUtil.slotData[id1] = slotData;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for index = 1, numSockets do
|
|
|
|
|
local itemID = GetItemGemID(itemLink, index);
|
|
|
|
|
if itemID and GEM_DATA[itemID] then
|
|
|
|
|
if not BagUtil.gemCount[itemID] then
|
|
|
|
|
BagUtil.gemCount[itemID] = 1;
|
|
|
|
|
else
|
|
|
|
|
BagUtil.gemCount[itemID] = BagUtil.gemCount[itemID] + 1;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if id2 then
|
|
|
|
|
--when there are supported gems in you bag
|
|
|
|
|
local gemType = DataProvider:GetGemType(itemID);
|
|
|
|
|
if not BagUtil.gemTypeAvailable[gemType] then
|
|
|
|
|
BagUtil.gemTypeAvailable[gemType] = true;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not BagUtil.bagGemCount[itemID] then
|
|
|
|
|
BagUtil.bagGemCount[itemID] = 0;
|
|
|
|
|
end
|
|
|
|
|
BagUtil.bagGemCount[itemID] = BagUtil.bagGemCount[itemID] + 1;
|
|
|
|
|
|
|
|
|
|
if not BagUtil.bagUsedGemCount[itemID] then
|
|
|
|
|
BagUtil.bagUsedGemCount[itemID] = 0;
|
|
|
|
|
end
|
|
|
|
|
BagUtil.bagUsedGemCount[itemID] = BagUtil.bagUsedGemCount[itemID] + 1;
|
|
|
|
|
else
|
|
|
|
|
if not BagUtil.activeGemCount[itemID] then
|
|
|
|
|
BagUtil.activeGemCount[itemID] = 0;
|
|
|
|
|
end
|
|
|
|
|
BagUtil.activeGemCount[itemID] = BagUtil.activeGemCount[itemID] + 1;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not id2 then
|
|
|
|
|
slotData.gems[index] = itemID;
|
|
|
|
|
if not itemID then
|
|
|
|
|
slotData.numMissing = slotData.numMissing + 1;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
local itemID = GetItemInfoInstant(itemLink);
|
|
|
|
|
if GEM_DATA[itemID] then
|
|
|
|
|
if not BagUtil.gemCount[itemID] then
|
|
|
|
|
BagUtil.gemCount[itemID] = 1;
|
|
|
|
|
else
|
|
|
|
|
BagUtil.gemCount[itemID] = BagUtil.gemCount[itemID] + 1; --stackCount of stat gem isn't relevant here
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if id2 then
|
|
|
|
|
local gemType = DataProvider:GetGemType(itemID);
|
|
|
|
|
if not BagUtil.gemTypeAvailable[gemType] then
|
|
|
|
|
BagUtil.gemTypeAvailable[gemType] = true;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not BagUtil.bagGemCount[itemID] then
|
|
|
|
|
BagUtil.bagGemCount[itemID] = 0;
|
|
|
|
|
end
|
|
|
|
|
BagUtil.bagGemCount[itemID] = BagUtil.bagGemCount[itemID] + 1;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local AdditionalScanSlots;
|
|
|
|
|
|
|
|
|
|
function BagUtil:InitiateScan()
|
|
|
|
|
if not AdditionalScanSlots then
|
|
|
|
|
AdditionalScanSlots = {};
|
|
|
|
|
local n = 0;
|
|
|
|
|
for slotName, slotID in pairs(SLOT_ID) do
|
|
|
|
|
n = n + 1;
|
|
|
|
|
AdditionalScanSlots[n] = slotID;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
BagScan:SetProcessor(BagUtil_ProcessItem, AdditionalScanSlots);
|
|
|
|
|
BagScan:FullUpdate();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function BagUtil:StopScan()
|
|
|
|
|
BagScan:StopIfProcessorSame(BagUtil_ProcessItem);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local CallbackRegistry = addon.CallbackRegistry;
|
|
|
|
|
|
|
|
|
|
local function PaperdollWidget_OnShow()
|
|
|
|
|
BagUtil:InitiateScan();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function PaperdollWidget_OnHide()
|
|
|
|
|
BagUtil:StopScan();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
CallbackRegistry:Register("PaperdollWidget.Gem.OnShow", PaperdollWidget_OnShow);
|
|
|
|
|
CallbackRegistry:Register("PaperdollWidget.Gem.OnHide", PaperdollWidget_OnHide);
|
|
|
|
|
|
|
|
|
|
CallbackRegistry:Register("GemManager.BagScan.OnStart", BagUtil.ResetBagInfo, BagUtil);
|
|
|
|
|
CallbackRegistry:Register("GemManager.BagScan.OnStop", BagUtil.OnScanComplete, BagUtil);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local TINKER_SLOT = {
|
|
|
|
|
SLOT_ID.SHOULDER, SLOT_ID.WRIST, SLOT_ID.HANDS, SLOT_ID.WAIST,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
do --Use the result from bag scan
|
|
|
|
|
local META_SLOT = { SLOT_ID.HEAD };
|
|
|
|
|
|
|
|
|
|
local COGWHEEL_SLOT = { SLOT_ID.FEET };
|
|
|
|
|
|
|
|
|
|
local PRISMATIC_SLOT = {
|
|
|
|
|
SLOT_ID.CHEST, SLOT_ID.LEGS, SLOT_ID.TRINKET1, SLOT_ID.TRINKET2, SLOT_ID.NECK, SLOT_ID.RING1, SLOT_ID.RING2
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetSlotSocketsCount(slots, gemType)
|
|
|
|
|
local slotData = BagUtil.slotData;
|
|
|
|
|
local totalSockets = 0;
|
|
|
|
|
local totalMissing = 0;
|
|
|
|
|
|
|
|
|
|
for _, slotID in ipairs(slots) do
|
|
|
|
|
if slotData[slotID] then
|
|
|
|
|
totalSockets = totalSockets + slotData[slotID].numSockets;
|
|
|
|
|
totalMissing = totalMissing + slotData[slotID].numMissing;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local anySpareGemInBags = BagUtil.gemTypeAvailable and BagUtil.gemTypeAvailable[gemType]
|
|
|
|
|
|
|
|
|
|
return totalSockets, totalMissing, anySpareGemInBags
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetMetaSocketCount()
|
|
|
|
|
return self:GetSlotSocketsCount(META_SLOT, 1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetCogwheelSocketCount()
|
|
|
|
|
return self:GetSlotSocketsCount(COGWHEEL_SLOT, 2)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetTinkerSocketCount()
|
|
|
|
|
return self:GetSlotSocketsCount(TINKER_SLOT, 3)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetPrismaticSocketCount()
|
|
|
|
|
return self:GetSlotSocketsCount(PRISMATIC_SLOT, 4)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetGemInventorySlotAndIndex(itemID)
|
|
|
|
|
if not self:IsGemCollected(itemID) then return end;
|
|
|
|
|
|
|
|
|
|
for slotID, slotData in pairs(BagUtil.slotData) do
|
|
|
|
|
for socketIndex = 1, slotData.numSockets do
|
|
|
|
|
if slotData.gems[socketIndex] == itemID then
|
|
|
|
|
return slotID, socketIndex
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:CanSwapGemInOneStep(itemID)
|
|
|
|
|
--You will have to perform two actions if the target socket is occupied and
|
|
|
|
|
--the gem you want to insert is in another equipment
|
|
|
|
|
local existingGem = self:GetConflictGemItemID(itemID);
|
|
|
|
|
local inbagCount = self:GetInBagGemCount(itemID);
|
|
|
|
|
local spareCount = GetItemCount(itemID);
|
|
|
|
|
|
|
|
|
|
if existingGem and (inbagCount > 0 and spareCount == 0) then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetBestSlotToPlaceGem(itemID)
|
|
|
|
|
if not self:IsGemCollected(itemID) then return end;
|
|
|
|
|
|
|
|
|
|
local gemType = self:GetGemType(itemID);
|
|
|
|
|
if not gemType then return end;
|
|
|
|
|
|
|
|
|
|
local slots;
|
|
|
|
|
|
|
|
|
|
if gemType == 1 then
|
|
|
|
|
slots = META_SLOT;
|
|
|
|
|
elseif gemType == 2 then
|
|
|
|
|
slots = COGWHEEL_SLOT;
|
|
|
|
|
elseif gemType == 3 then
|
|
|
|
|
slots = TINKER_SLOT;
|
|
|
|
|
elseif gemType == 4 then
|
|
|
|
|
slots = PRISMATIC_SLOT;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local slotData;
|
|
|
|
|
|
|
|
|
|
for _, slotID in ipairs(slots) do
|
|
|
|
|
slotData = BagUtil.slotData[slotID];
|
|
|
|
|
if slotData then
|
|
|
|
|
for socketIndex = 1, slotData.numSockets do
|
|
|
|
|
if slotData.gems[socketIndex] == nil then
|
|
|
|
|
return slotID, socketIndex
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetInBagGemCount(itemID)
|
|
|
|
|
return BagUtil.bagGemCount and BagUtil.bagGemCount[itemID] or 0;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetInBagUsedGemCount(itemID)
|
|
|
|
|
return BagUtil.bagUsedGemCount and BagUtil.bagUsedGemCount[itemID] or 0;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetOnPlayerGemCount(itemID)
|
|
|
|
|
return BagUtil.activeGemCount[itemID] and BagUtil.activeGemCount[itemID] or 0;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:IsGemActive(itemID)
|
|
|
|
|
return self:GetOnPlayerGemCount(itemID) > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:IsGemCollected(itemID)
|
|
|
|
|
return BagUtil.gemCount[itemID] and BagUtil.gemCount[itemID] > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:ShouldShowGreenDot()
|
|
|
|
|
local totalSockets, totalMissing, anySpareGemInBags;
|
|
|
|
|
local showGreenDot;
|
|
|
|
|
|
|
|
|
|
if not showGreenDot then
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = self:GetMetaSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not showGreenDot then
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = self:GetCogwheelSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not showGreenDot then
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = self:GetTinkerSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not showGreenDot then
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = self:GetPrismaticSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return showGreenDot
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
local ACTION_BUTTON_METHODS = {
|
|
|
|
|
[1] = "SetAction_RemovePandariaMetaGem",
|
|
|
|
|
[2] = "SetAction_RemovePandariaGem",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetActionButtonMethod(itemID)
|
|
|
|
|
local gemType = self:GetGemType(itemID);
|
|
|
|
|
if gemType == 1 or gemType == 2 then
|
|
|
|
|
return ACTION_BUTTON_METHODS[1]
|
|
|
|
|
elseif gemType == 3 then
|
|
|
|
|
return ACTION_BUTTON_METHODS[2]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DataProvider.schematic = {
|
|
|
|
|
background = "remix-ui-bg",
|
|
|
|
|
topDivider = "remix-ui-divider",
|
|
|
|
|
|
|
|
|
|
tabData = {
|
|
|
|
|
{
|
|
|
|
|
name = L["Pandamonium Gem Category 1"], --Major
|
|
|
|
|
method = "ShowMajors",
|
|
|
|
|
background = nil,
|
|
|
|
|
useCustomTooltip = false,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
name = L["Pandamonium Gem Category 2"], --Tinker
|
|
|
|
|
method = "ShowTraits",
|
|
|
|
|
background = "remix-ui-tinker-bg",
|
|
|
|
|
useCustomTooltip = true,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
name = L["Pandamonium Gem Category 3"], --Prismatic
|
|
|
|
|
method = "ShowStats",
|
|
|
|
|
background = nil,
|
|
|
|
|
useCustomTooltip = false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local BorderTextures_Hexagon = {
|
|
|
|
|
active = "remix-hexagon-yellow",
|
|
|
|
|
inactive = "remix-hexagon-grey",
|
|
|
|
|
available = "remix-hexagon-green",
|
|
|
|
|
dimmed = "remix-hexagon-darkyellow",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
local BorderTextures_BigSquare = {
|
|
|
|
|
active = "remix-bigsquare-yellow",
|
|
|
|
|
inactive = "remix-bigsquare-grey",
|
|
|
|
|
available = "remix-bigsquare-green",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function sin(deg)
|
|
|
|
|
return math.sin(math.rad(deg));
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function cos(deg)
|
|
|
|
|
return math.cos(math.rad(deg));
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function CreateSlotShadow(self, slotButton)
|
|
|
|
|
local shadow = self:AcquireTexture("Back", "BACKGROUND");
|
|
|
|
|
AtlasUtil:SetAtlas(shadow, "remix-bigsquare-shadow");
|
|
|
|
|
shadow:SetPoint("CENTER", slotButton, "CENTER", 0, 0);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:SetupMajorSlotButton(itemID)
|
|
|
|
|
local button = self:AcquireSlotButton("BigSquare");
|
|
|
|
|
button.borderTextures = BorderTextures_BigSquare;
|
|
|
|
|
button:SetButtonSize(64, 53); --buttonSize, iconSize
|
|
|
|
|
|
|
|
|
|
if itemID then
|
|
|
|
|
button:SetItem(itemID);
|
|
|
|
|
button:SetActive();
|
|
|
|
|
else
|
|
|
|
|
button:ClearItem();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local shadow = self:AcquireTexture("Back", "BACKGROUND");
|
|
|
|
|
AtlasUtil:SetAtlas(shadow, "remix-bigsquare-shadow");
|
|
|
|
|
shadow:SetPoint("CENTER", button, "CENTER", 0, 0);
|
|
|
|
|
|
|
|
|
|
return button
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function TooltipFunc_EmptyMeta(tooltip)
|
|
|
|
|
tooltip:SetText(EMPTY_SOCKET_META, 1, 1, 1);
|
|
|
|
|
tooltip:AddLine(L["Click To Show Gem List"], 0.098, 1.000, 0.098, true);
|
|
|
|
|
tooltip:Show();
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function TooltipFunc_EmptyCogwheel(tooltip)
|
|
|
|
|
tooltip:SetText(EMPTY_SOCKET_COGWHEEL, 1, 1, 1);
|
|
|
|
|
tooltip:AddLine(L["Click To Show Gem List"], 0.098, 1.000, 0.098, true);
|
|
|
|
|
tooltip:Show();
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function OnClickFunc_ShowMetaGemList(self, mouseButton)
|
|
|
|
|
if DataProvider:GetHeadGem() and mouseButton == "RightButton" then
|
|
|
|
|
MainFrame.autoShowGemList = 1;
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
GemManagerMixin.ShowGemList(MainFrame, 1);
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function OnClickFunc_ShowCogwheelGemList(self, mouseButton)
|
|
|
|
|
if DataProvider:GetFeetGem() and mouseButton == "RightButton" then
|
|
|
|
|
MainFrame.autoShowGemList = 2;
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
GemManagerMixin.ShowGemList(MainFrame, 2);
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function OnClickFunc_CloseGemList(self, mouseButton)
|
|
|
|
|
if mouseButton == "RightButton" then
|
|
|
|
|
--if not DataProvider:IsGemActive(self.itemID) then
|
|
|
|
|
MainFrame:CloseGemList();
|
|
|
|
|
return true
|
|
|
|
|
--end
|
|
|
|
|
elseif mouseButton == "LeftButton" then
|
|
|
|
|
if DataProvider:IsGemActive(self.itemID) then
|
|
|
|
|
MainFrame:CloseGemList();
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:ShowMajors()
|
|
|
|
|
MainFrame = self;
|
|
|
|
|
self.useSlotFrame = true;
|
|
|
|
|
|
|
|
|
|
local shape = "BigSquare";
|
|
|
|
|
local container = self.SlotFrame;
|
|
|
|
|
|
|
|
|
|
local numButtons = 0;
|
|
|
|
|
local button1, button2;
|
|
|
|
|
|
|
|
|
|
local newlyEquippedSocket;
|
|
|
|
|
|
|
|
|
|
if DataProvider:DoesPlayerHaveHead() then
|
|
|
|
|
local itemID = DataProvider:GetHeadGem();
|
|
|
|
|
local button = self:SetupMajorSlotButton(itemID);
|
|
|
|
|
|
|
|
|
|
numButtons = numButtons + 1;
|
|
|
|
|
button1 = button;
|
|
|
|
|
|
|
|
|
|
local typeIcon = self:AcquireTexture("Front");
|
|
|
|
|
AtlasUtil:SetAtlas(typeIcon, "gemtypeicon-offensive");
|
|
|
|
|
typeIcon:SetPoint("CENTER", button, "BOTTOM", 0, 0);
|
|
|
|
|
|
|
|
|
|
button.onClickFunc = OnClickFunc_ShowMetaGemList;
|
|
|
|
|
|
|
|
|
|
if itemID then
|
|
|
|
|
typeIcon:SetDesaturation(0);
|
|
|
|
|
else
|
|
|
|
|
typeIcon:SetDesaturation(1);
|
|
|
|
|
button.tooltipFunc = TooltipFunc_EmptyMeta;
|
|
|
|
|
local _, _, anySpareGemInBags = DataProvider:GetPrismaticSocketCount(); --GetMetaSocketCount
|
|
|
|
|
if anySpareGemInBags then
|
|
|
|
|
button:SetSelectable();
|
|
|
|
|
else
|
|
|
|
|
button:SetUncollected();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (not self.headGemID) and itemID then
|
|
|
|
|
newlyEquippedSocket = button;
|
|
|
|
|
end
|
|
|
|
|
self.headGemID = itemID;
|
|
|
|
|
else
|
|
|
|
|
self.headGemID = nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if DataProvider:DoesPlayerHaveFeet() then
|
|
|
|
|
local itemID = DataProvider:GetFeetGem();
|
|
|
|
|
local button = self:SetupMajorSlotButton(itemID);
|
|
|
|
|
|
|
|
|
|
numButtons = numButtons + 1;
|
|
|
|
|
if not button1 then
|
|
|
|
|
button1 = button;
|
|
|
|
|
else
|
|
|
|
|
button2 = button;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local typeIcon = self:AcquireTexture("Front");
|
|
|
|
|
AtlasUtil:SetAtlas(typeIcon, "gemtypeicon-movement");
|
|
|
|
|
typeIcon:SetPoint("CENTER", button, "BOTTOM", 0, 0);
|
|
|
|
|
|
|
|
|
|
button.onClickFunc = OnClickFunc_ShowCogwheelGemList;
|
|
|
|
|
|
|
|
|
|
if itemID then
|
|
|
|
|
typeIcon:SetDesaturation(0);
|
|
|
|
|
else
|
|
|
|
|
typeIcon:SetDesaturation(1);
|
|
|
|
|
button.tooltipFunc = TooltipFunc_EmptyCogwheel;
|
|
|
|
|
local _, _, anySpareGemInBags = DataProvider:GetCogwheelSocketCount();
|
|
|
|
|
if anySpareGemInBags then
|
|
|
|
|
button:SetSelectable();
|
|
|
|
|
else
|
|
|
|
|
button:SetUncollected();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (not self.feetGemID) and itemID then
|
|
|
|
|
if newlyEquippedSocket then
|
|
|
|
|
newlyEquippedSocket = nil;
|
|
|
|
|
else
|
|
|
|
|
newlyEquippedSocket = button;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
self.feetGemID = itemID;
|
|
|
|
|
else
|
|
|
|
|
self.feetGemID = nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if numButtons == 0 then
|
|
|
|
|
self:ShowNoSocketAlert(true);
|
|
|
|
|
else
|
|
|
|
|
if numButtons == 2 then
|
|
|
|
|
local offsetX = 8;
|
|
|
|
|
local offsetY = 16;
|
|
|
|
|
button1:SetPoint("BOTTOMRIGHT", container, "CENTER", -offsetX, offsetY);
|
|
|
|
|
button2:SetPoint("TOPLEFT", container, "CENTER", offsetX, -offsetY);
|
|
|
|
|
elseif numButtons == 1 then
|
|
|
|
|
button1:SetPoint("CENTER", container, "CENTER", 0, 0);
|
|
|
|
|
end
|
|
|
|
|
self:ShowNoSocketAlert(false);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.SlotFrame.ButtonHighlight:SetShape(shape);
|
|
|
|
|
self.UpdateCurrentTab = self.UpdateMajors;
|
|
|
|
|
|
|
|
|
|
if self.autoShowGemList then
|
|
|
|
|
self:ShowGemList(self.autoShowGemList);
|
|
|
|
|
self.autoShowGemList = nil;
|
|
|
|
|
else
|
|
|
|
|
if newlyEquippedSocket then
|
|
|
|
|
self:CloseGemList();
|
|
|
|
|
|
|
|
|
|
local shine = self.SlotFrame.ButtonShine;
|
|
|
|
|
shine.Mask:SetTexture(PATH.."IconMask-"..shape, "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE");
|
|
|
|
|
shine.Mask:SetSize(53, 53);
|
|
|
|
|
shine.Texture:SetTexture(PATH.."SlotShine");
|
|
|
|
|
shine.Texture:SetSize(80, 80);
|
|
|
|
|
shine.Texture:SetBlendMode("ADD");
|
|
|
|
|
|
|
|
|
|
self:ShineSlot(newlyEquippedSocket);
|
|
|
|
|
else
|
|
|
|
|
self:UpdateGemList();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:UpdateMajors()
|
|
|
|
|
self:ReleaseContent();
|
|
|
|
|
self:ShowMajors();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:UpdateGemList()
|
|
|
|
|
if self.GemList:IsShown() and self.gemType then
|
|
|
|
|
local activeGemID;
|
|
|
|
|
if self.gemType == 1 then
|
|
|
|
|
activeGemID = DataProvider:GetHeadGem();
|
|
|
|
|
elseif self.gemType == 2 then
|
|
|
|
|
activeGemID = DataProvider:GetFeetGem();
|
|
|
|
|
end
|
|
|
|
|
self.GemList.activeGemID = activeGemID;
|
|
|
|
|
self.GemList:UpdatePage();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:ShowGemList(gemType)
|
|
|
|
|
self.gemType = gemType;
|
|
|
|
|
|
|
|
|
|
if not gemType then return end;
|
|
|
|
|
|
|
|
|
|
local activeGemID;
|
|
|
|
|
if gemType == 1 then
|
|
|
|
|
activeGemID = DataProvider:GetHeadGem();
|
|
|
|
|
elseif gemType == 2 then
|
|
|
|
|
activeGemID = DataProvider:GetFeetGem();
|
|
|
|
|
end
|
|
|
|
|
self.GemList.activeGemID = activeGemID;
|
|
|
|
|
|
|
|
|
|
local gems = DataProvider:GetItemListByType(gemType);
|
|
|
|
|
self.GemList.onClickFunc = OnClickFunc_CloseGemList;
|
|
|
|
|
self.GemList:SetItemList(gems, DataProvider:GetGemTypeName(gemType), DataProvider);
|
|
|
|
|
|
|
|
|
|
self:OpenGemList();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:ShowTraits()
|
|
|
|
|
self.useSlotFrame = true;
|
|
|
|
|
|
|
|
|
|
local shape = "Hexagon";
|
|
|
|
|
local diagonal = 40; --46
|
|
|
|
|
local gap = 1;
|
|
|
|
|
local container = self.SlotFrame;
|
|
|
|
|
|
|
|
|
|
local deltaXPerRow = ((diagonal * cos(30)) + gap) * 0.5;
|
|
|
|
|
local deltaYPerRow = (diagonal * cos(30) + gap) * cos(30);
|
|
|
|
|
local offsetX = diagonal * cos(30) + gap;
|
|
|
|
|
|
|
|
|
|
local contentHeight = 5 * deltaYPerRow + diagonal;
|
|
|
|
|
|
|
|
|
|
local frameWidth = container:GetWidth();
|
|
|
|
|
local frameHeight = container:GetHeight();
|
|
|
|
|
|
|
|
|
|
local paddingY = (frameHeight - contentHeight) * 0.5;
|
|
|
|
|
|
|
|
|
|
local refX = frameWidth * 0.5;
|
|
|
|
|
refX = 0;
|
|
|
|
|
local refY = (deltaYPerRow - diagonal * 0.5) - paddingY;
|
|
|
|
|
|
|
|
|
|
local gemType = 3; --Tinker
|
|
|
|
|
local gems = DataProvider:GetItemListByType(gemType);
|
|
|
|
|
|
|
|
|
|
local button;
|
|
|
|
|
local row = 1;
|
|
|
|
|
local col = 1;
|
|
|
|
|
local maxCol = 1;
|
|
|
|
|
local fromX, fromY = refX, refY;
|
|
|
|
|
local x, y;
|
|
|
|
|
|
|
|
|
|
for index, itemID in ipairs(gems) do
|
|
|
|
|
button = self:AcquireSlotButton(shape);
|
|
|
|
|
button:ResetButtonSize();
|
|
|
|
|
button.borderTextures = BorderTextures_Hexagon;
|
|
|
|
|
|
|
|
|
|
if col > maxCol then
|
|
|
|
|
maxCol = maxCol + 1;
|
|
|
|
|
col = 1;
|
|
|
|
|
row = row + 1;
|
|
|
|
|
|
|
|
|
|
fromX = refX - (row - 1) * deltaXPerRow;
|
|
|
|
|
fromY = refY - (row - 1) * deltaYPerRow;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
x = fromX + (col - 1) * offsetX;
|
|
|
|
|
y = fromY;
|
|
|
|
|
button:SetPoint("CENTER", self.SlotFrame, "TOP", x, y);
|
|
|
|
|
button:SetItem(itemID);
|
|
|
|
|
|
|
|
|
|
col = col + 1;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if self.SlotFrame.ButtonHighlight then
|
|
|
|
|
self.SlotFrame.ButtonHighlight:SetShape(shape);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local shine = self.SlotFrame.ButtonShine;
|
|
|
|
|
if shine then
|
|
|
|
|
shine.Mask:SetTexture(PATH.."IconMask-"..shape, "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE");
|
|
|
|
|
shine.Mask:SetSize(32, 32);
|
|
|
|
|
shine.Texture:SetTexture(PATH.."SlotShine");
|
|
|
|
|
shine.Texture:SetSize(48, 48);
|
|
|
|
|
shine.Texture:SetBlendMode("ADD");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.UpdateCurrentTab = self.UpdateSlots;
|
|
|
|
|
|
|
|
|
|
if not self.isLoadoutPlanner then
|
|
|
|
|
if self.TooltipFrame then
|
|
|
|
|
self.TooltipFrame:ClearAllPoints();
|
|
|
|
|
self.TooltipFrame:SetPoint("TOP", container, "CENTER", 0, -contentHeight * 0.5 - 44);
|
|
|
|
|
|
|
|
|
|
if GetCVarBool("colorblindMode") then
|
|
|
|
|
self.TooltipFrame:SetDescriptionLine(7);
|
|
|
|
|
else
|
|
|
|
|
self.TooltipFrame:SetDescriptionLine(6);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self:UpdateSlots();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:UpdateSlots()
|
|
|
|
|
if not self.slotButtons then return end;
|
|
|
|
|
|
|
|
|
|
local totalSockets, totalMissing, anySpareGemInBags = DataProvider:GetTinkerSocketCount();
|
|
|
|
|
self:SetPointDisplayAmount(totalMissing);
|
|
|
|
|
|
|
|
|
|
local chooseItem = totalMissing > 0;
|
|
|
|
|
|
|
|
|
|
for index, button in ipairs(self.slotButtons) do
|
|
|
|
|
if button:IsShown() then
|
|
|
|
|
if DataProvider:IsGemActive(button.itemID) then
|
|
|
|
|
if chooseItem then
|
|
|
|
|
button:SetDimmed();
|
|
|
|
|
else
|
|
|
|
|
button:SetActive();
|
|
|
|
|
end
|
|
|
|
|
elseif DataProvider:IsGemCollected(button.itemID) then
|
|
|
|
|
if chooseItem then
|
|
|
|
|
button:SetAvailable();
|
|
|
|
|
else
|
|
|
|
|
button:SetInactive();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
button:SetUncollected();
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do --Stats Assignment Tab
|
|
|
|
|
function DataProvider:GetNumAvailableGemForStat(statType)
|
|
|
|
|
local gems = STAT_GEMS[statType];
|
|
|
|
|
local total = 0;
|
|
|
|
|
|
|
|
|
|
if gems then
|
|
|
|
|
for _, itemID in ipairs(gems) do
|
|
|
|
|
total = total + self:GetInBagGemCount(itemID);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return total
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetBestStatGemToRemove(statType)
|
|
|
|
|
--From lower tier to higher
|
|
|
|
|
local gems = STAT_GEMS[statType];
|
|
|
|
|
if gems then
|
|
|
|
|
for _, itemID in ipairs(gems) do
|
|
|
|
|
if self:IsGemActive(itemID) then
|
|
|
|
|
return itemID
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetBestStatGemToInsert(statType)
|
|
|
|
|
--From higher tier to lower
|
|
|
|
|
local gems = STAT_GEMS[statType];
|
|
|
|
|
if gems then
|
|
|
|
|
local itemID;
|
|
|
|
|
for i = #gems, 1, -1 do
|
|
|
|
|
itemID = gems[i];
|
|
|
|
|
if self:GetInBagGemCount(itemID) > 0 then
|
|
|
|
|
return itemID
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetBestStatGemForAction(statType, direction)
|
|
|
|
|
if direction > 0 then --Insert gem
|
|
|
|
|
return self:GetBestStatGemToInsert(statType)
|
|
|
|
|
else --remove gem
|
|
|
|
|
return self:GetBestStatGemToRemove(statType)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetAvailableGemListForStat(statType)
|
|
|
|
|
--Used in Loadout Action
|
|
|
|
|
local gems = STAT_GEMS[statType];
|
|
|
|
|
local statGemCount = {};
|
|
|
|
|
|
|
|
|
|
if gems then
|
|
|
|
|
local itemID, inBagCount, spareCount;
|
|
|
|
|
local n = 0;
|
|
|
|
|
|
|
|
|
|
for i = #gems, 1, -1 do
|
|
|
|
|
itemID = gems[i];
|
|
|
|
|
|
|
|
|
|
inBagCount = self:GetInBagUsedGemCount(itemID);
|
|
|
|
|
spareCount = GetItemCount(itemID);
|
|
|
|
|
|
|
|
|
|
--if inBagCount > 0 or spareCount > 0 then
|
|
|
|
|
local tbl = {
|
|
|
|
|
itemID = itemID,
|
|
|
|
|
inBagCount = inBagCount,
|
|
|
|
|
spareCount = spareCount,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
n = n + 1;
|
|
|
|
|
statGemCount[n] = tbl;
|
|
|
|
|
--end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return statGemCount
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:ShowStats()
|
|
|
|
|
self.useSlotFrame = true;
|
|
|
|
|
|
|
|
|
|
local buttonHeight = 24;
|
|
|
|
|
local gap = 0.2; --Compensation for IsMouseOver()
|
|
|
|
|
local numButtons = #STATS_DATA;
|
|
|
|
|
local container = self.SlotFrame;
|
|
|
|
|
local fromY = -0.5 * (container:GetHeight() - (numButtons * (buttonHeight + gap) -gap));
|
|
|
|
|
|
|
|
|
|
local button;
|
|
|
|
|
|
|
|
|
|
for i, statData in ipairs(STATS_DATA) do
|
|
|
|
|
button = self:AcquireStatButton();
|
|
|
|
|
button:SetPoint("TOP", container, "TOP", 0, fromY + (1 - i) * (buttonHeight + gap));
|
|
|
|
|
button:SetName(statData[1]);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.UpdateCurrentTab = self.UpdateStats;
|
|
|
|
|
|
|
|
|
|
if not self.isLoadoutPlanner then
|
|
|
|
|
self:UpdateStats();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:UpdateStats()
|
|
|
|
|
local totalSockets, totalMissing, anySpareGemInBags = DataProvider:GetPrismaticSocketCount();
|
|
|
|
|
local isEditMode;
|
|
|
|
|
|
|
|
|
|
if totalMissing > 0 then
|
|
|
|
|
isEditMode = true;
|
|
|
|
|
self.PointsDisplay:SetAmount(totalMissing);
|
|
|
|
|
self.PointsDisplay:Show();
|
|
|
|
|
else
|
|
|
|
|
isEditMode = false;
|
|
|
|
|
self.PointsDisplay:Hide();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local activeGems = DataProvider:GetActiveGems();
|
|
|
|
|
local activeStatsGems = activeGems and activeGems.stats;
|
|
|
|
|
|
|
|
|
|
local button, count;
|
|
|
|
|
|
|
|
|
|
for i, statData in ipairs(STATS_DATA) do
|
|
|
|
|
button = self.statButtons[i];
|
|
|
|
|
count = activeStatsGems[i] and activeStatsGems[i][1] or 0;
|
|
|
|
|
button:SetCount(count);
|
|
|
|
|
button:SetPlusButtonVisibility( isEditMode and DataProvider:GetNumAvailableGemForStat(i) > 0 );
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function GemManagerMixin:UpdateTabGreenDot()
|
|
|
|
|
BagScan:FullUpdate();
|
|
|
|
|
|
|
|
|
|
local totalSockets, totalMissing, anySpareGemInBags;
|
|
|
|
|
local showGreenDot;
|
|
|
|
|
|
|
|
|
|
--Meta and cogwheel are on the same tab
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = DataProvider:GetMetaSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
|
|
|
|
|
if not showGreenDot then
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = DataProvider:GetCogwheelSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.tabButtons[1].GreenDot:SetShown(showGreenDot);
|
|
|
|
|
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = DataProvider:GetTinkerSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
self.tabButtons[2].GreenDot:SetShown(showGreenDot);
|
|
|
|
|
|
|
|
|
|
totalSockets, totalMissing, anySpareGemInBags = DataProvider:GetPrismaticSocketCount();
|
|
|
|
|
showGreenDot = totalMissing > 0 and anySpareGemInBags;
|
|
|
|
|
self.tabButtons[3].GreenDot:SetShown(showGreenDot);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do --Loadout
|
|
|
|
|
local function AddSlotGemCountToTable(tbl, slotID, gemType)
|
|
|
|
|
local itemLink = GetInventoryItemLink("player", slotID);
|
|
|
|
|
if itemLink then
|
|
|
|
|
local gemItemID, statType;
|
|
|
|
|
for socketIndex = 1, GetItemNumSockets(itemLink) do
|
|
|
|
|
gemItemID = GetItemGemID(itemLink, socketIndex);
|
|
|
|
|
if gemItemID then
|
|
|
|
|
--local gemType = DataProvider:GetGemType(gemItemID);
|
|
|
|
|
if gemType == 3 then
|
|
|
|
|
table.insert(tbl, gemItemID);
|
|
|
|
|
elseif gemType == 4 then
|
|
|
|
|
statType = DataProvider:GetStatType(gemItemID);
|
|
|
|
|
if not tbl[statType] then
|
|
|
|
|
tbl[statType] = 0;
|
|
|
|
|
end
|
|
|
|
|
tbl[statType] = tbl[statType] + 1;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetEquippedLoadoutGemInfo()
|
|
|
|
|
--[[--Structure:
|
|
|
|
|
{
|
|
|
|
|
head = 221977,
|
|
|
|
|
feet = 218110,
|
|
|
|
|
tinker = {219801, 212366, 219944, 219818},
|
|
|
|
|
stats1 = { --Chest Legs
|
|
|
|
|
crit = 1,
|
|
|
|
|
haste = 2,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
stats2 = {}, --Trinkets
|
|
|
|
|
stats3 = {}, --Neck/Rings
|
|
|
|
|
}
|
|
|
|
|
--]]
|
|
|
|
|
|
|
|
|
|
local gemInfo = {};
|
|
|
|
|
|
|
|
|
|
gemInfo.head = self:GetHeadGem();
|
|
|
|
|
gemInfo.feet = self:GetFeetGem();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gemInfo.tinker = {};
|
|
|
|
|
for _, slotID in ipairs(TINKER_SLOT) do
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.tinker, slotID, 3);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
tsort(gemInfo.tinker);
|
|
|
|
|
|
|
|
|
|
gemInfo.stats1 = {};
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats1, SLOT_ID.CHEST, 4);
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats1, SLOT_ID.LEGS, 4);
|
|
|
|
|
|
|
|
|
|
gemInfo.stats2 = {};
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats2, SLOT_ID.TRINKET1, 4);
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats2, SLOT_ID.TRINKET2, 4);
|
|
|
|
|
|
|
|
|
|
gemInfo.stats3 = {};
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats3, SLOT_ID.NECK, 4);
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats3, SLOT_ID.RING1, 4);
|
|
|
|
|
AddSlotGemCountToTable(gemInfo.stats3, SLOT_ID.RING2, 4);
|
|
|
|
|
|
|
|
|
|
return gemInfo
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:IsLeftStatGemBetter(gem1, gem2)
|
|
|
|
|
if GEM_DATA[gem1][3] == GEM_DATA[gem2][3] then
|
|
|
|
|
return GEM_DATA[gem1][4] < GEM_DATA[gem2][4]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetFallbackTinkers(numEmptySockets, requiredTinker)
|
|
|
|
|
local tbl = {};
|
|
|
|
|
local n = 0;
|
|
|
|
|
|
|
|
|
|
requiredTinker = requiredTinker or {};
|
|
|
|
|
|
|
|
|
|
for _, itemID in ipairs(FALLBACK_TINKERS) do
|
|
|
|
|
if (not requiredTinker[itemID]) and (self:IsGemCollected(itemID) and not self:IsGemActive(itemID)) then
|
|
|
|
|
n = n + 1;
|
|
|
|
|
if n <= numEmptySockets then
|
|
|
|
|
tbl[n] = itemID;
|
|
|
|
|
else
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return tbl
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetFallbackMajorGem(gemType, requiredGem)
|
|
|
|
|
local gems = self:GetItemListByType(gemType);
|
|
|
|
|
for _, itemID in ipairs(gems) do
|
|
|
|
|
if (itemID ~= requiredGem) and (self:IsGemCollected(itemID) and not self:IsGemActive(itemID)) then
|
|
|
|
|
return itemID;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetFallbackMeta(requiredGem)
|
|
|
|
|
return self:GetFallbackMajorGem(1, requiredGem)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function DataProvider:GetFallbackCogwheel(requiredGem)
|
|
|
|
|
return self:GetFallbackMajorGem(2, requiredGem)
|
|
|
|
|
end
|
|
|
|
|
end
|