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.

607 lines
20 KiB

local unpack = unpack;
local CreateColor = NarciAPI.CreateColor;
local GetItemInfoInstant = C_Item.GetItemInfoInstant;
local GetItemGemID = C_Item.GetItemGemID;
local FILE_PATH_DARK = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/JPG/";
local itemBorderMask = {
[1] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/RegularHeavy", --Regular Hexagon Heavy
[2] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/RegularSolid",
[8001] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Heart",
[9001] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Runeforge",
[9101] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Sylvanas",
[9102] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Garrosh",
[9200] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Progenitor",
[9201] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Menethil",
[9202] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Anduin",
[100701] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/ThreeSocket",
[100101] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/Neltharion",
[100200] = "Interface/AddOns/Narcissus/Art/ItemBorder-Dark/Mask/TreeAndFlame",
}
local itemBorderHeavy = {
--[Quality or Specific Name] = {fileName, border's mask index}
[0] = {"Black", 1},
[1] = {"Black", 1},
[2] = {"Uncommon", 1},
[3] = {"Rare", 1},
[4] = {"Epic", 1},
[5] = {"Legendary", 1},
[6] = {"Artifact", 1},
[7] = {"Heirloom", 1},
[12] = {"Black", 1},
Azerite= {"Azerite", 1},
Heart = {"Heart", 8001},
NZoth = {"NZoth", 1},
BlackDragon = {"BlackDragon", 1}, --8.3 Legendary Cloak / What's its name again?
Runeforge = {"Runeforge", 9001}, --Sylvanas's Legendary Bow
Sylvanas = {"Sylvanas", 9101},
Garrosh = {"Garrosh", 9102},
Progenitor = {"Progenitor", 9200},
Cosmos = {"Cosmos", 2},
Arbiter = {"Arbiter", 2},
Menethil = {"Menethil", 9201},
Varian = {"Varian", 2},
Anduin = {"Anduin", 9202},
Genesis = {"Genesis", 2},
Shield = {"Shield", 1},
Strife = {"Strife", 2},
ThreeSocket_Purple = {"ThreeSocket_Purple", 100701},
Neltharion = {"Neltharion", 100101},
EmeraldDream = {"TreeAndFlame", 100200},
ThreeSocket_Yellow = {"ThreeSocket_Yellow", 100701},
};
local function GetBorderThemeName()
local themeName = NarcissusDB and NarcissusDB.BorderTheme
if true then --not (themeName and type(themeName) ~= "string" and (themeName == "Bright" or themeName == "Dark") )
return "Dark"
else
return themeName
end
end
NarciAPI.GetBorderThemeName = GetBorderThemeName;
local function SetBorderTexture(object, textureKey, themeIndex)
if not themeIndex then
themeIndex = 2;
end
if textureKey == object.textureKey and themeIndex == object.textureThemeIndex then
return
else
object.textureKey = textureKey;
object.textureThemeIndex = themeIndex;
end
local texFile, maskFile;
if themeIndex == 1 then
texFile = itemBorderHeavy[textureKey][1];
maskFile = itemBorderMask[ itemBorderHeavy[textureKey][2] ];
else
texFile = itemBorderHeavy[textureKey][1];
maskFile = itemBorderMask[ itemBorderHeavy[textureKey][2] ];
end
object:SetTexture(FILE_PATH_DARK..texFile);
if not object.BorderMask then
local layer, sublevel = object:GetDrawLayer();
local mask = object:GetParent():CreateMaskTexture(nil, layer, nil, sublevel);
mask:SetPoint("TOPLEFT", object, "TOPLEFT", 0, 0);
mask:SetPoint("BOTTOMRIGHT", object, "BOTTOMRIGHT", 0, 0);
object:AddMaskTexture(mask);
object.BorderMask = mask;
end
object.BorderMask:SetTexture(maskFile, "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE");
end
NarciAPI.SetBorderTexture = SetBorderTexture;
local itemIDxBorderArt = {
--[itemID] = {borderName, vfxName, color, hideItemIcon}
[186429] = {"Garrosh", "Garrosh", CreateColor(235, 91, 80)}, --177057
[186414] = {"Sylvanas", "Sylvanas", CreateColor(148, 188, 203)},
[189852] = {"Cosmos", nil, CreateColor(169, 218, 215)}, --Shadow of the Cosmos
[189862] = {"Arbiter", nil, CreateColor(180, 216, 222)}, --Gravel of the First Arbiter
[189841] = {"Menethil", nil, CreateColor(240, 104, 104)}, --Soulwarped Seal of Wrynn
[189839] = {"Varian", nil, CreateColor(116, 208, 249)}, --Soulwarped Seal of Wrynn
[188262] = {"Anduin", "LigntFall", CreateColor(255, 204, 58)}, --The Lion's Roar
[189845] = {"Shield", nil, nil}, --Ruined Crest of Lordaeron
[189754] = {"Genesis", nil, CreateColor(216, 212, 155)}, --Genesis Lathe
[188253] = {"Strife", "OrangeRune", nil}, --Scars of Fraternal Strife
[203460] = {"ThreeSocket_Purple", "ThreeSocketRing", nil, nil, nil, true}, --Onyx Annulet --CreateColor(255, 171, 0)
[228411] = {"ThreeSocket_Yellow", "ThreeSocketRing", nil, nil, nil, true}, --Cyrce's Circlet
--Progenitor = {"Progenitor", nil, CreateColor(230, 204, 128)}, --Class Sets: Sepulcher of the First Ones
--[visualID] = {borderName, vfxName, color, hideItemIcon}
[1] = {"Neltharion", nil, CreateColor(252, 185, 54)}, --Class Sets: Embers of Neltharion
[2] = {"EmeraldDream", nil, CreateColor(56, 224, 178)}, --Class Sets: Guardians of the Dream
[3] = {"EmeraldDream", nil, CreateColor(56, 224, 178)}, --Class Sets: DF S4 Awakened Raids
[4] = {"Neltharion", nil, CreateColor(252, 185, 54)}, --Class Sets: TWW S2 Undermined
};
itemIDxBorderArt[5] = itemIDxBorderArt[4]; --TEMP Class Sets: TWW S3 Manaforge Omega
local itemVisualGroup = {};
do
for borderVisualID, items in pairs(NarciAPI.GetClassSetGroup()) do
for _, itemID in pairs(items) do
itemVisualGroup[itemID] = borderVisualID;
end
end
end
local function GetBorderArtByItemID(itemID)
if itemVisualGroup[itemID] then
return unpack(itemIDxBorderArt[ itemVisualGroup[itemID] ]);
else
if itemIDxBorderArt[itemID] then
return unpack(itemIDxBorderArt[itemID]);
end
end
end
NarciAPI.GetBorderArtByItemID = GetBorderArtByItemID;
---- Gem Border ----
local gemBorderTexture = {
filePrefix = "Interface/AddOns/Narcissus/Art/GemBorder/Dark/",
[0] = "White", --Empty
[1] = "Primary", --Kraken's Eye
[2] = "Green",
[3] = "Primary", --Prismatic
[4] = "Primary", --Meta
[5] = "Orange", --Orange
[6] = "Purple",
[7] = "Yellow", --Yellow
[8] = "Blue", --Blue
[9] = "Black", --(Other Type)
[10] = "Red", --Red
[11] = "White", --Artifact
[12] = "Crystallic",
};
local specialGemBoder = {
[153714] = 10,
[173125] = 10,
[153715] = 2,
[169220] = 2,
[173126] = 2,
[168636] = 1,
[168637] = 1,
[168638] = 1,
[153707] = 1,
[153708] = 1,
[153709] = 1,
[189723] = 12,
[189722] = 12,
[189732] = 12,
[189560] = 12,
[189763] = 12,
[189724] = 12,
[189725] = 12,
[189726] = 12,
[189762] = 12,
[189727] = 12,
[189728] = 12,
[189729] = 12,
[189730] = 12,
[189731] = 12,
[189764] = 12,
[189733] = 12,
[189734] = 12,
[189760] = 12,
[189761] = 12,
[189735] = 12,
};
local function GetGemBorderTexture(itemSubClassID, itemID)
local index = (itemID and specialGemBoder[itemID]) or itemSubClassID or 0;
return gemBorderTexture.filePrefix..gemBorderTexture[index], index
end
local function SetBorderTheme(theme)
--1.1.2 Override
theme = "Dark";
if theme == "Bright" then
gemBorderTexture.filePrefix = "Interface/AddOns/Narcissus/Art/GemBorder/Bright/";
elseif theme == "Dark" then
gemBorderTexture.filePrefix = "Interface/AddOns/Narcissus/Art/GemBorder/Dark/";
end
end
NarciAPI.SetBorderTheme = SetBorderTheme;
NarciAPI.GetGemBorderTexture = GetGemBorderTexture;
---- Item Border Visual (ModelScene) ----
local PI = math.pi;
local VFXContainer = CreateFrame("Frame", "NarciItemVFXContainer");
function VFXContainer:AcquireAndSetModelScene(parentFrame, effectName)
if not self.models then
self.models = {};
end
local model;
for i = 1, #self.models do
if not self.models[i].isActive then
model = self.models[i];
break
end
end
if model then
model:GetParent().VFX = nil;
else
model = CreateFrame("ModelScene", nil, self, "NarciItemVFXTemplate");
table.insert(self.models, model);
end
model:SetParent(parentFrame);
model:SetUpByName(effectName);
return model
end
function VFXContainer:GetNumModels()
if self.models then
print(#self.models);
else
print(0);
end
end
NarciModelSceneActorMixin = CreateFromMixins(ModelSceneActorMixin);
function NarciModelSceneActorMixin:OnAnimFinished()
if self.oneShot then
if self.finalSequence then
self:SetAnimation(0, 0, 0, self.finalSequence);
else
self:Hide();
end
end
if self.onfinishedCallback then
self.onfinishedCallback();
end
end
--[[
table:modelSceneInfo = {
camera = {zoomDistance = distance, direction = string },
actors = {
{fileID = modelFileID, modelOffset = {x, y}, oneShot = bool, animationID = number, animationSpeed = number},
}
}
--/run NarciItemVFX:SetUpByName("heart")
--]]
---- Display 3 Sockets ----
local SocketContainer;
local function CreateSocketTexture(container)
local texture = container:CreateTexture(nil, "OVERLAY");
texture:SetTexCoord(0.0625, 0.9375, 0.0625, 0.9375);
local mask = container:CreateMaskTexture(nil, "OVERLAY");
mask:SetPoint("TOPLEFT", texture, "TOPLEFT", 0, 0);
mask:SetPoint("BOTTOMRIGHT", texture, "BOTTOMRIGHT", 0, 0);
mask:SetTexture("Interface/AddOns/Narcissus/Art/BasicShapes/Circle64", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE");
texture:AddMaskTexture(mask);
local overlay = container:CreateTexture(nil, "OVERLAY", nil, 3);
overlay:SetPoint("TOPLEFT", texture, "TOPLEFT", 0, 0);
overlay:SetPoint("BOTTOMRIGHT", texture, "BOTTOMRIGHT", 0, 0);
overlay:SetTexture("Interface/AddOns/Narcissus/Art/BasicShapes/Circle-InnerShadow-8");
return texture
end
local function DisplayThreeSockets(vfxFrame)
vfxFrame.effectName = nil; --Cleared this so we can update this container
local slotButton = vfxFrame:GetParent();
if slotButton and slotButton.itemLink then
local ids = {};
local _, socket, icon;
for i = 1, 3 do
local gemID = GetItemGemID(slotButton.itemLink, i)
if gemID then
table.insert(ids, gemID);
end
end
local total = #ids;
if total > 0 then
if not SocketContainer then
SocketContainer = CreateFrame("Frame", nil, vfxFrame);
SocketContainer.sockets = {};
end
if total > 1 then
table.sort(ids);
end
vfxFrame.additionalFrame = SocketContainer;
SocketContainer:SetParent(vfxFrame);
SocketContainer.owner = vfxFrame;
SocketContainer:Show();
end
for i = 1, total do
socket = SocketContainer.sockets[i];
if not socket then
socket = CreateSocketTexture(SocketContainer);
SocketContainer.sockets[i] = socket;
local degree;
if i == 1 then
degree = 0;
elseif i == 2 then
degree = 120;
else
degree = 240;
end
local r = 18;
local x = r * math.cos( math.rad(degree) );
local y = r * math.sin( math.rad(degree) );
socket:SetSize(22, 22);
socket.x, socket.y = x, y;
end
socket:ClearAllPoints();
socket:SetPoint("CENTER", vfxFrame, "CENTER", socket.x, socket.y);
_, _, _, _, icon = GetItemInfoInstant(ids[i]);
socket:SetTexture(icon);
socket:Show();
end
if SocketContainer then
for i = total + 1, #SocketContainer.sockets do
SocketContainer.sockets[i]:Hide();
end
end
end
end
local itemVFXInfo = {
Heart = {
camera = { zoomDistance = 2.65, direction = "LEFT" },
actors = {
{fileID = 165995, alpha = 0.6, },
},
offset = {x = 1, y = -23 },
},
DragonFire = {
camera = { zoomDistance = 1.25 },
actors = {
{fileID = 969794},
},
offset = {x = 8, y = 8 },
},
Runeforge = {
camera = { zoomDistance = 3.5, direction = "TOP" },
actors = {
{fileID = 166011, modelOffset = {0.75, -0.05}, alpha = 0.6, animationSpeed = 0.5, },
{fileID = 166011, modelOffset = {-0.75, -0.05}, alpha = 0.6, animationSpeed = 0.5, },
},
offset = {x = 0, y = 0 },
},
Sylvanas = {
camera = { zoomDistance = 2.65, direction = "RIGHT" },
actors = {
{fileID = 165995, alpha = 1, },
},
offset = {x = 8, y = 10 },
},
Garrosh = {
camera = { zoomDistance = 5, direction = "BOTTOM" },
actors = {
{fileID = 3486623, animationID = 0, animationSpeed = -0.6, modelOffset = {-0.15, 0.24}, alpha = 1, particleScale = 0.1,};
{fileID = 3486623, animationID = 0, animationSpeed = -0.6, modelOffset = {-0.15, 0.24}, alpha = 0.8, particleScale = 0.1,};
{fileID = 3486625, animationID = 0, animationSpeed = -0.6, modelOffset = {0.35, 0}, alpha = 1, particleScale = 0.1,};
{fileID = 3486625, animationID = 0, animationSpeed = -0.6, modelOffset = {0.35, 0}, alpha = 0.8, particleScale = 0.1,};
},
offset = {x = 0, y = 16 },
},
SoulfireChisel = {
camera = { zoomDistance = 3.5, direction = "TOP" },
actors = {
{fileID = 3483468},
},
offset = {x = 0, y = 0},
},
LigntFall = {
camera = { zoomDistance = 10, direction = "FRONT" },
actors = {
{fileID = 2429902, animationID = 158, animationSpeed = 8, modelOffset = {-1, -3.2}, alpha = 0.65, particleScale = 2,};
},
offset = {x = 0, y = 0 },
},
OrangeRune = {
camera = { zoomDistance = 5, direction = "FRONT" },
actors = {
{fileID = 3656114, animationID = 158, modelOffset = {0.2,-0.05}, alpha = 1, particleScale = 1,};
},
offset = {x = 0, y = 0 },
},
ThreeSocketRing = {
setupFunc = DisplayThreeSockets,
},
};
NarciItemVFXMixin = {};
function NarciItemVFXMixin:Activate()
self:Show();
self.isActive = true;
end
function NarciItemVFXMixin:Remove()
self:Hide();
self.isActive = false;
if self.additionalFrame and self.additionalFrame.owner == self then
self.additionalFrame:Hide();
self.additionalFrame = nil;
end
end
function NarciItemVFXMixin:ClearEffects(fromIndex)
if self.effects then
fromIndex = fromIndex or 1;
for i = fromIndex, #self.effects do
self.effects[i]:Hide();
self.effects[i]:ClearModel();
end
end
end
function NarciItemVFXMixin:SetUp(vfxInfo, useCustomPosition)
self:SetFrameLevel( (self:GetParent():GetFrameLevel() or 0) + 2);
self:Activate();
if vfxInfo.setupFunc then
self:ClearAllPoints();
self:SetPoint("CENTER", self:GetParent(), "CENTER", 0, 0);
self:ClearEffects();
vfxInfo.setupFunc(self);
return
end
local camera = self.effectCamera;
if not camera then
camera = CameraRegistry:CreateCameraByType("OrbitCamera");
camera:SetOwningScene(self);
self.effectCamera = camera;
self.activeCamera = camera;
local modelSceneCameraInfo = C_ModelInfo.GetModelSceneCameraInfoByID(114);
camera:ApplyFromModelSceneCameraInfo(modelSceneCameraInfo, 1, 1); --1 ~ CAMERA_TRANSITION_TYPE_IMMEDIATE / CAMERA_MODIFICATION_TYPE_DISCARD
end
local cameraInfo = vfxInfo.camera;
camera:SetZoomDistance(cameraInfo.zoomDistance or 3);
camera:SynchronizeCamera();
local view = cameraInfo.direction;
local actorPitch, actorYaw = 0, 0;
if view then
if type(view) == "string" then
view = string.upper(view);
if view == "FRONT" then
actorPitch = 0;
actorYaw = PI;
elseif view == "BACK" then
actorPitch = 0;
actorYaw = 0;
elseif view == "TOP" then
actorPitch = PI/2;
actorYaw = PI;
elseif view == "BOTTOM" then
actorPitch = -PI/2;
actorYaw = PI;
elseif view == "LEFT" then
actorPitch = 0;
actorYaw = -PI/2;
elseif view == "RIGHT" then
actorPitch = 0;
actorYaw = PI/2;
end
elseif type(view) == "table" then
actorPitch = view[1] or actorPitch;
actorYaw = view[2] or actorYaw;
end
end
if not self.effects then
self.effects = {};
end
local actorInfo;
local actor;
local numEffects = #vfxInfo.actors;
for i = 1, numEffects do
actorInfo = vfxInfo.actors[i];
actor = self.effects[i];
if actorInfo then
if not actor then
actor = self:CreateActor(nil, "NarciModelSceneActorTemplate");
self.effects[i] = actor;
actor:SetPosition(0, 0, 0);
end
actor:SetModelByFileID(actorInfo.fileID);
if actorInfo.modelOffset then
local a = actorInfo.modelOffset[1];
local b = actorInfo.modelOffset[2];
actor:SetPosition(0, a or 0, b or 0);
else
actor:SetPosition(0, 0, 0);
end
if actorInfo.particleScale then
actor:SetParticleOverrideScale(actorInfo.particleScale);
end
actor:SetAlpha(actorInfo.alpha or 1);
actor:SetScale(actorInfo.scale or 1);
actor.oneShot = actorInfo.oneShot;
actor:SetAnimation(actorInfo.animationID or 0, 0, actorInfo.animationSpeed or 1, 0);
actor:SetPitch(actorPitch);
actor:SetYaw(actorYaw);
actor:Show();
else
actor:Hide();
end
end
self:ClearEffects(numEffects + 1);
local frameOffset = vfxInfo.offset;
self:ClearAllPoints();
self.offsetX = frameOffset.x or 0;
self.offsetY = frameOffset.y or 0;
if not useCustomPosition then
self:SetPoint("CENTER", self:GetParent(), "CENTER", self.offsetX, self.offsetY);
end
end
function NarciItemVFXMixin:SetUpByName(effectName, useCustomPosition)
if itemVFXInfo[effectName] then
if effectName ~= self.effectName then
self.effectName = effectName;
self:SetUp(itemVFXInfo[effectName], useCustomPosition);
else
self:Activate();
self:ClearAllPoints();
self:SetPoint("CENTER", self:GetParent(), "CENTER", self.offsetX, self.offsetY);
self:SetFrameLevel( (self:GetParent():GetFrameLevel() or 0) + 2);
end
end
end
function NarciItemVFXMixin:SetOwningFrame()
end