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.
540 lines
17 KiB
540 lines
17 KiB
local _, addon = ...
|
|
local L = Narci.L;
|
|
local Gemma = addon.Gemma;
|
|
local AtlasUtil = Gemma.AtlasUtil;
|
|
local DataProvider = {};
|
|
local GemManagerMixin = {};
|
|
DataProvider.GemManagerMixin = GemManagerMixin;
|
|
|
|
Gemma:AddDataProvider("Pandaria", DataProvider);
|
|
|
|
local PATH = "Interface/AddOns/Narcissus/Art/Modules/GemManager/";
|
|
local TEXTURE_NAME = "TimerunningPandaria.png";
|
|
|
|
local GetItemGemID = C_Item.GetItemGemID;
|
|
local GetItemNumSockets = C_Item.GetItemNumSockets; --10.2.7
|
|
local IsEquippableItem = C_Item.IsEquippableItem;
|
|
local GetItemInfoInstant = C_Item.GetItemInfoInstant;
|
|
local GetInventoryItemLink = GetInventoryItemLink;
|
|
|
|
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}
|
|
--role: bits 000 (Tank/Healer/DPS): Tank 100(4), DPS 001(1), H/D 011(3), H 010(2)
|
|
|
|
--Total: 12
|
|
[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
|
|
[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, 427031, 7, 25}, --Heroic Leap
|
|
[216629] = {2, 427053, 7, 05}, --Blink
|
|
|
|
--Total: 25
|
|
[219944] = {3, 444455, 2, 03}, --Bloodthirsty Coral: Damage taken to Healing
|
|
[219818] = {3, 429007, 7, 06}, --Brilliance: Party Resouce Regen
|
|
[219817] = {3, 429026, 7, 18}, --Freedom: Ckear Loss of Control
|
|
[219801] = {3, 427064, 7, 00}, --Ankh of Reincarnation: Self-rez
|
|
[219977] = {3, 428854, 4, 21}, --Grounding: Redirect Harmful Spell
|
|
[219527] = {3, 443855, 7, 63}, --Vampiric Aura: +Leech, Party Leech
|
|
[219523] = {3, 443834, 1, 57}, --Storm Overload: AoE, Control
|
|
[219516] = {3, 443670, 3, 54}, --Static Charge: Heal or Damage
|
|
[219389] = {3, 443498, 3, 30}, --Lightning Rod: Crit on Ally or Dot on Enemy
|
|
[217964] = {3, 441209, 2, 27}, --Holy Martyr: Damage Taken to Party Healing
|
|
[217961] = {3, 441198, 2, 42}, --Righteous Frency: Healing Proc Haste on Ally
|
|
[217957] = {3, 441165, 2, 15}, --Deliverance: Store Healing. Healing when Low HP
|
|
[217927] = {3, 441150, 2, 45}, --Savior: Healing Low HP Ally Grants Ward
|
|
[217907] = {3, 441115, 4, 72}, --Warmth: +Healing Taken, Redistribute Overhealing
|
|
[217903] = {3, 441092, 3, 69}, --Vindication: Damage Done Heals Allies
|
|
[216651] = {3, 436586, 3, 48}, --Searing Light: Healing to Heal and AoE Damage
|
|
[216650] = {3, 436583, 7, 36}, --Memory of Vegeance: For every 10s, gain primary stat for every 5% missing HP
|
|
[216649] = {3, 436578, 1, 09}, --Brittle: Store Damage Done, Death Trigger AoE
|
|
[216648] = {3, 436577, 7, 12}, --Cold Front: Allies Ward, Enemies Debuff
|
|
[216647] = {3, 436571, 1, 24}, --Hailstorm: AoE and Debuff
|
|
[216628] = {3, 436467, 3, 66}, --Victory Fire: Enemy Death trigger AoE Damage and Healing
|
|
[216627] = {3, 429230, 2, 60}, --Tinkmaster's Shield: Ward after not being damaged for 5s
|
|
[216626] = {3, 429378, 1, 51}, --Slay: Extra Damage to Low Health Enemy
|
|
[216625] = {3, 429373, 1, 39}, --Quick Strike: Melee Ability Triggers Additional Autoattacks
|
|
[216624] = {3, 436461, 5, 33}, --Mark of Arrogance: Dot on Attackers
|
|
|
|
[210715] = {4, nil, 0, 32}, --Mastery +
|
|
[216640] = {4, nil, 0, 22}, --Mastery ++
|
|
[211106] = {4, nil, 0, 12}, --Mastery +++
|
|
[211108] = {4, nil, 0, 02}, --Mastery +++, STAM
|
|
[210714] = {4, nil, 0, 30}, --Crit +
|
|
[216644] = {4, nil, 0, 20}, --Crit ++
|
|
[211123] = {4, nil, 0, 10}, --Crit +++
|
|
[211102] = {4, nil, 0, 00}, --Crit +++, STAM
|
|
[210681] = {4, nil, 0, 31}, --Haste +
|
|
[216643] = {4, nil, 0, 21}, --Haste ++
|
|
[211107] = {4, nil, 0, 11}, --Haste +++
|
|
[211110] = {4, nil, 0, 01}, --Haste +++, STAM
|
|
[220371] = {4, nil, 0, 33}, --Vers +
|
|
[220372] = {4, nil, 0, 23}, --Vers ++
|
|
[220374] = {4, nil, 0, 13}, --Vers +++
|
|
[220373] = {4, nil, 0, 03}, --Vers +++, STAM
|
|
[220367] = {4, nil, 0, 35}, --Armor +
|
|
[220368] = {4, nil, 0, 25}, --Armor ++
|
|
[220370] = {4, nil, 0, 15}, --Armor +++
|
|
[220369] = {4, nil, 0, 05}, --Armor +++, STAM
|
|
[211109] = {4, nil, 0, 36}, --Regen +
|
|
[216642] = {4, nil, 0, 26}, --Regen ++
|
|
[211125] = {4, nil, 0, 16}, --Regen +++
|
|
[211105] = {4, nil, 0, 06}, --Regen +++, STAM
|
|
[210717] = {4, nil, 0, 37}, --Leech +
|
|
[216641] = {4, nil, 0, 27}, --Leech ++
|
|
[210718] = {4, nil, 0, 17}, --Leech +++
|
|
[211103] = {4, nil, 0, 07}, --Leech +++, STAM
|
|
[210716] = {4, nil, 0, 38}, --Speed +
|
|
[216639] = {4, nil, 0, 28}, --Speed ++
|
|
[211124] = {4, nil, 0, 18}, --Speed +++
|
|
[211101] = {4, nil, 0, 08}, --Speed +++, STAM
|
|
};
|
|
|
|
local CUSTOM_SORT_ORDER = {
|
|
[219944] = 2,
|
|
[219818] = 12,
|
|
[219817] = 8,
|
|
[219801] = 4,
|
|
[219977] = 1,
|
|
|
|
[219527] = 24,
|
|
[219523] = 6,
|
|
[219516] = 23,
|
|
[219389] = 13,
|
|
[217964] = 5,
|
|
|
|
[217961] = 14,
|
|
[217957] = 25,
|
|
[217927] = 20,
|
|
[217907] = 9,
|
|
[217903] = 17,
|
|
|
|
[216651] = 18,
|
|
[216650] = 7,
|
|
[216649] = 15,
|
|
[216648] = 11,
|
|
[216647] = 16,
|
|
|
|
[216628] = 22,
|
|
[216627] = 19,
|
|
[216626] = 10,
|
|
[216625] = 21,
|
|
[216624] = 3,
|
|
};
|
|
|
|
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
|
|
|
|
return GEM_DATA[a][4] < GEM_DATA[b][4]
|
|
end
|
|
|
|
function DataProvider:GetSortedItemList()
|
|
if self.gemList then return self.gemList end;
|
|
|
|
local tinsert = table.insert;
|
|
local tsort = table.sort;
|
|
|
|
local tbl = {};
|
|
local numTypes = #GEM_TYPES;
|
|
|
|
for i = 1, numTypes do
|
|
tbl[i] = {};
|
|
end
|
|
|
|
for itemID, data in pairs(GEM_DATA) do
|
|
local gemType = data[1];
|
|
tinsert(tbl[gemType], itemID);
|
|
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
|
|
|
|
function DataProvider:IsGemActive(itemID)
|
|
return true
|
|
end
|
|
|
|
function DataProvider:IsGemCollected(itemID)
|
|
return true
|
|
end
|
|
|
|
local function GetNumSocketsForSlot(slotID)
|
|
local itemLink = GetInventoryItemLink("player", slotID);
|
|
if itemLink then
|
|
return GetItemNumSockets(itemLink) or 0
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
function DataProvider:DoesPlayerHaveHead()
|
|
return GetNumSocketsForSlot(SLOT_ID.HEAD) > 0
|
|
end
|
|
|
|
function DataProvider:DoesPlayerHaveFeet()
|
|
return GetNumSocketsForSlot(SLOT_ID.FEET) > 0
|
|
end
|
|
|
|
local function GetItemGemFromSlot(slotID, index)
|
|
local itemLink = GetInventoryItemLink("player", slotID);
|
|
if itemLink then
|
|
return GetItemGemID(itemLink, index);
|
|
end
|
|
end
|
|
|
|
function DataProvider:GetHeadGem()
|
|
return GetItemGemFromSlot(SLOT_ID.HEAD, 1)
|
|
end
|
|
|
|
function DataProvider:GetFeetGem()
|
|
return GetItemGemFromSlot(SLOT_ID.FEET, 1)
|
|
end
|
|
|
|
function DataProvider:GetGemSpell(itemID)
|
|
if GEM_DATA[itemID] then
|
|
return GEM_DATA[itemID][2]
|
|
end
|
|
end
|
|
|
|
|
|
|
|
function DataProvider:ResetBagInfo()
|
|
self.gemCount = {};
|
|
end
|
|
|
|
local function BagSearch_ProcessItem(self, itemLink)
|
|
if IsEquippableItem(itemLink) then
|
|
for index = 1, GetItemNumSockets(itemLink) do
|
|
local itemID = GetItemGemID(itemLink, index);
|
|
if itemID and GEM_DATA[itemID] then
|
|
if not self.gemCount[itemID] then
|
|
self.gemCount[itemID] = 1;
|
|
else
|
|
self.gemCount[itemID] = self.gemCount[itemID] + 1;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
local itemID = GetItemInfoInstant(itemLink);
|
|
if GEM_DATA[itemID] then
|
|
if not self.gemCount[itemID] then
|
|
self.gemCount[itemID] = 1;
|
|
else
|
|
self.gemCount[itemID] = self.gemCount[itemID] + 1;
|
|
end
|
|
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,
|
|
},
|
|
},
|
|
|
|
bagSearchProcessor = BagSearch_ProcessItem,
|
|
};
|
|
|
|
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
|
|
|
|
function GemManagerMixin:ShowMajors()
|
|
self.useSlotFrame = true;
|
|
|
|
local shape = "BigSquare";
|
|
local container = self.SlotFrame;
|
|
|
|
local numButtons = 0;
|
|
local button1, button2;
|
|
|
|
if DataProvider:DoesPlayerHaveHead() then
|
|
local itemID = DataProvider:GetHeadGem();
|
|
local gems = DataProvider:GetItemListByType(1); --debug
|
|
itemID = gems[1];
|
|
local button = self:SetupMajorSlotButton(itemID);
|
|
|
|
numButtons = numButtons + 1;
|
|
button1 = button;
|
|
end
|
|
|
|
if DataProvider:DoesPlayerHaveFeet() then
|
|
local itemID = DataProvider:GetFeetGem();
|
|
local gems = DataProvider:GetItemListByType(2); --debug
|
|
itemID = gems[1];
|
|
local button = self:SetupMajorSlotButton(itemID);
|
|
|
|
numButtons = numButtons + 1;
|
|
if not button1 then
|
|
button1 = button;
|
|
else
|
|
button2 = button;
|
|
end
|
|
end
|
|
|
|
if numButtons == 0 then
|
|
|
|
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
|
|
end
|
|
|
|
self.SlotFrame.ButtonHighlight:SetShape(shape);
|
|
end
|
|
|
|
function GemManagerMixin:ShowGemList()
|
|
local gemType = 1;
|
|
local gems = DataProvider:GetItemListByType(gemType);
|
|
self.GemList:SetItemList(gems, DataProvider:GetGemTypeName(gemType));
|
|
|
|
self:OpenGemList();
|
|
end
|
|
|
|
function GemManagerMixin:ShowTraits()
|
|
self.useSlotFrame = true;
|
|
|
|
local shape = "Hexagon";
|
|
local diagonal = 46;
|
|
local gap = 4;
|
|
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 contentWidth = 6 * offsetX - gap;
|
|
local contentHeight = 5 * deltaYPerRow + diagonal;
|
|
|
|
local frameWidth = container:GetWidth();
|
|
local frameHeight = container:GetHeight();
|
|
|
|
local paddingX = (frameWidth - contentWidth) * 0.5;
|
|
local paddingY = (frameHeight - contentHeight) * 0.5;
|
|
|
|
local refX = frameWidth * 0.5;
|
|
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 = 0, 0;
|
|
local x, y;
|
|
|
|
for index, itemID in ipairs(gems) do
|
|
button = self:AcquireSlotButton(shape);
|
|
button:ResetButtonSize();
|
|
button.borderTextures = BorderTextures_Hexagon;
|
|
|
|
if row == 1 then
|
|
col = col + 1;
|
|
end
|
|
|
|
if col > maxCol then
|
|
maxCol = maxCol + 1;
|
|
col = 1;
|
|
row = row + 1;
|
|
|
|
fromX = refX - (row - 1) * deltaXPerRow;
|
|
fromY = refY - (row - 1) * deltaYPerRow;
|
|
end
|
|
|
|
if (row == 7 and col == 1) then
|
|
col = col + 1;
|
|
end
|
|
|
|
x = fromX + (col - 1) * offsetX;
|
|
y = fromY;
|
|
button:SetPoint("CENTER", self.SlotFrame, "TOPLEFT", x, y);
|
|
button:SetItem(itemID);
|
|
|
|
col = col + 1;
|
|
end
|
|
|
|
self.TooltipFrame:ClearAllPoints();
|
|
self.TooltipFrame:SetPoint("TOP", container, "CENTER", 0, -contentHeight * 0.5 - 16);
|
|
self.TooltipFrame:SetDescriptionLine(6);
|
|
|
|
self.SlotFrame.ButtonHighlight:SetShape(shape);
|
|
|
|
local shine = self.SlotFrame.ButtonShine;
|
|
shine.Mask:SetTexture(PATH.."IconMask-"..shape, "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE");
|
|
shine.Mask:SetSize(38, 38);
|
|
shine.Texture:SetTexture(PATH.."SlotShine");
|
|
shine.Texture:SetSize(48, 48);
|
|
shine.Texture:SetBlendMode("ADD");
|
|
|
|
self:UpdateSlots();
|
|
end
|
|
|
|
function GemManagerMixin:UpdateSlots()
|
|
for index, button in ipairs(self.slotButtons) do
|
|
if button:IsShown() then
|
|
if DataProvider:IsGemActive(button.itemID) then
|
|
button:SetActive();
|
|
elseif DataProvider:IsGemCollected(button.itemID) then
|
|
button:SetInactive();
|
|
else
|
|
button:SetUncollected();
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function GemManagerMixin:ShowStats()
|
|
self.useSlotFrame = false;
|
|
end
|
|
|
|
|
|
do
|
|
Gemma.BagSearch:AddOnStartCallback(function()
|
|
DataProvider:ResetBagInfo();
|
|
end);
|
|
end
|