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.

817 lines
33 KiB

local MOUSE_UPDATE_RATE = 1/60; --1/25
local PARTICLE_LIFESPAN = 2; --2 seconds
local ERASE_SPEED = 96;
local PIXEL_SCALE = 1;
local ERASE_DELAY = -3;
local tinsert = table.insert;
local strsplit = strsplit;
local gsub = string.gsub;
local strlen = string.len;
local strlenutf8 = strlenutf8;
local sqrt = math.sqrt;
local cos = math.cos;
local sin = math.sin;
local pow = math.pow;
local modf = math.modf;
local ceil = math.ceil;
local pi = math.pi;
local GetCursorPosition = GetCursorPosition;
local function Lerp(startValue, endValue, amount)
--print(amount)
return (1 - amount) * startValue + amount * endValue;
end
local function LerpSnap(startValue, endValue, amount)
if amount > 1 then
return endValue
end
return (1 - amount) * startValue + amount * endValue;
end
local function LerpCycle(startValue, endValue, amount)
if amount > 1 then
local r = amount % 2;
if r > 1 then
amount = 2 - r;
else
amount = r;
end
end
return (1 - amount) * startValue + amount * endValue;
end
local function inOutSine(startValue, endValue, amount)
return (startValue - endValue) / 2 * (cos(pi * amount) - 1) + startValue
end
local function inOutSineCycle(startValue, endValue, amount)
if amount > 1 then
local r = amount % 2;
if r > 1 then
amount = 2 - r;
else
amount = r;
end
end
return (startValue - endValue) / 2 * (cos(pi * amount) - 1) + startValue
end
local function outQuart(startValue, endValue, amount)
if amount > 1 then
amount = 1;
elseif amount < 0 then
amount = 0;
end
amount = amount - 1;
return (startValue - endValue) * (pow(amount, 4) - 1) + startValue
end
local function Distance(x, y)
return sqrt(x*x + y*y)
end
local function Mixin(object, mixin)
for k, v in pairs(mixin) do
object[k] = v;
end
return object;
end
local function UTF8toChars(input)
local list = {};
local len = strlen(input);
local index = 1;
local lenutf8 = 0;
while index <= len do
local c = string.byte(input, index)
local offset = 1
if c < 0xc0 then
offset = 1
elseif c < 0xe0 then
offset = 2
elseif c < 0xf0 then
offset = 3
elseif c < 0xf8 then
offset = 4
elseif c < 0xfc then
offset = 5
end
local str = string.sub(input, index, index + offset-1)
index = index + offset;
lenutf8 = lenutf8 + 1;
tinsert(list, str);
end
return list, lenutf8
end
local defaultContainer = CreateFrame("Frame");
--defaultContainer:Hide();
--------------------------------------------------------------------------------------------------------
local DataProvider = {};
function DataProvider:GetLetterBinaryzation(letter)
--32*32
return self.letters[letter];
end
--------------------------------------------------------------------------------------------------------
--Particle System
local DynamicParticleMixin = {};
function DynamicParticleMixin:SetPosition(point, relativeTo, relativePoint, x, y)
self:SetPoint(point, relativeTo, relativePoint, x, y);
self.point = point;
self.relativeTo = relativeTo;
self.relativePoint = relativePoint;
self.x0 = x;
self.y0 = y;
self.left = self:GetLeft();
self:ResetMotion();
end
function DynamicParticleMixin:SetOffset(x, y)
self:SetPoint(self.point, self.relativeTo, self.relativePoint, self.x0 + x, self.y0 + y);
end
function DynamicParticleMixin:ResetMotion()
self.isActive = true;
self.accuX, self.accuY = 0, 0;
self.vX, self.vY = 0, 0;
self.lifespan = 0;
end
function DynamicParticleMixin:SetAccumulativeOffset(relX, relY)
self.accuX, self.accuY = self.accuX + relX, self.accuY + relY;
self:SetOffset(self.accuX, self.accuY)
end
function DynamicParticleMixin:SetOffsetByAcceleration(aX, aY, elapsed)
self.lifespan = self.lifespan + elapsed;
self.vX = self.vX + aX * elapsed;
if self.vX > 600 then
self.vX = 600
end
self.vY = self.vY + aY * elapsed;
self.accuX, self.accuY = self.accuX + self.vX*elapsed, self.accuY + self.vY*elapsed;
self:SetOffset(self.accuX, self.accuY);
if self.lifespan > PARTICLE_LIFESPAN then
self:Kill();
return false;
else
return true
end
end
function DynamicParticleMixin:SetPixelSize(a)
self:SetSize(a, a);
end
function DynamicParticleMixin:Kill()
self:Hide();
self.isActive = nil;
end
local ParticleSystem = {};
ParticleSystem.objects = {};
ParticleSystem.numObjects = 0;
ParticleSystem.numMaxParticles = 1000;
function ParticleSystem:Accquire(index)
if index > self.numMaxParticles then
index = index - self.numMaxParticles;
end
if not self.objects[index] then
self.objects[index] = defaultContainer:CreateTexture(nil, "OVERLAY", "NarciDynamicTextParticleTemplate");
self.numObjects = self.numObjects + 1;
Mixin(self.objects[index], DynamicParticleMixin);
end
self.objects[index]:Show();
return self.objects[index];
end
function ParticleSystem:NewParticle()
local object = defaultContainer:CreateTexture(nil, "OVERLAY", "NarciDynamicTextParticleTemplate");
Mixin(object, DynamicParticleMixin);
return object
end
function ParticleSystem:KillAll()
for i = 1, #self.objects do
self.objects[i]:SetParent(defaultContainer);
self.objects[i]:ClearAllPoints();
self.objects[i]:Hide();
end
end
function ParticleSystem:CreateLetter(container, letter, offsetX, offsetY, amp, texAmp, particleColor, step)
--ParticleSystem:KillAll();
local data = DataProvider:GetLetterBinaryzation(letter);
local res = 32;
local pixelSize = 1;
local obj;
local index, row, col;
local particles = {};
local particlePos = {};
local r, g, b;
amp = amp or 1;
texAmp = texAmp or 1;
if particleColor then
r, g, b = unpack(particleColor);
else
r, g, b = 0.75, 0.86, 0.84;
end
step = step or 1;
if data then
for i = 1, #data, step do
index = data[i];
col = ((index - 1) % res);
row = modf(index / res);
obj = ParticleSystem:NewParticle(i); --Accquire
obj:ClearAllPoints();
obj:SetPixelSize(2*texAmp); --pixelSize * PIXEL_SCALE
obj:SetParent(container);
obj:SetPosition("TOPLEFT", container, "TOPLEFT", amp*(col*pixelSize + offsetX), amp*(-row*pixelSize + offsetY));
--particles[i] = obj;
tinsert(particles, obj);
particlePos[obj] = {row = row, col = col};
obj:SetVertexColor(r, g, b);
end
end
local fromLeft = true;
if fromLeft then
local sortFunc = function(a, b)
if particlePos[a].col == particlePos[b].col then
return particlePos[a].row < particlePos[b].row
else
return particlePos[a].col < particlePos[b].col
end
end
table.sort(particles, sortFunc);
end
return particles
end
--------------------------------------------------------------------------------------------------------
local function CreateDynamicTextGroup(parentFrame)
local object = CreateFrame("Frame", nil, parentFrame, "NarciDynamicTextGroupTemplate");
return object
end
NarciAPI.CreateDynamicTextGroup = CreateDynamicTextGroup;
local function PrintLetter(letter)
ParticleSystem:KillAll();
local data = DataProvider:GetLetterBinaryzation(letter);
local res = 32;
local pixelSize = 1;
local obj;
local index, row, col;
local container = NarciDynamicTextGroupTemplate;
if data then
for i = 1, #data do
index = data[i];
col = ((index - 1) % res);
row = modf(index / res);
obj = ParticleSystem:Accquire(i);
obj:ClearAllPoints();
obj:SetPixelSize(pixelSize);
obj:SetPosition("TOPLEFT", container, "TOPLEFT", col*pixelSize, -row*pixelSize);
end
end
end
NarciAPI.PrintLetter = PrintLetter
--------------------------------------------------------------------------------------------------------
local DynamicFontStringMixin = {};
function DynamicFontStringMixin:SetFontType(fontObject)
if fontObject ~= self.fontType then
self:SetFontObject(fontObject);
self.fontType = fontObject;
end
end
function DynamicFontStringMixin:IsActive()
return self.isActive;
end
function DynamicFontStringMixin:SetCharacter(txt)
self:SetText(txt);
self.isActive = true;
end
function DynamicFontStringMixin:Release()
self:SetText(nil);
self.isActive = nil;
self:ClearAllPoints();
self:SetParent(defaultContainer);
end
function DynamicFontStringMixin:SetPosition(point, relativeTo, relativePoint, x, y)
self:SetPoint(point, relativeTo, relativePoint, x, y);
self.point = point;
self.relativeTo = relativeTo;
self.relativePoint = relativePoint;
self.x0 = x;
self.y0 = y;
end
function DynamicFontStringMixin:SetOffset(x, y)
self:SetPoint(self.point, self.relativeTo, self.relativePoint, self.x0 + x, self.y0 + y);
self.hitRectY = -y;
end
function DynamicFontStringMixin:IsInRange()
return self:IsMouseOver(0, self.hitRectY or 0, 0, 0);
end
function DynamicFontStringMixin:SetValue(v, a)
self:SetTextColor(v, v, v, a);
end
local function GetPressure(distance)
if distance < 0 then
distance = -distance;
end
local p = 24 - 0.5 * distance;
local b = 1.5 - 0.025 * distance;
if p < 0 then
p = 0;
end
if b < 0.5 then
b = 0.5;
elseif b > 1 then
b = 1;
end
return p, b
end
local function TestOnUpdate(textGroup, elapsed)
textGroup.t = textGroup.t + elapsed;
if textGroup.t > MOUSE_UPDATE_RATE then
--print(elapsed)
textGroup.t = 0;
local numObjects = #textGroup.objects;
--[[
for i = 1, numObjects do
if textGroup.objects[i]:IsInRange() then
local uiScale = UIParent:GetEffectiveScale();
local centerObj = textGroup.objects[i];
local cursorX, cursorY = GetCursorPosition();
local x, y = centerObj:GetCenter();
local w0 = centerObj:GetWidth();
local diffX = x - cursorX;
print(diffX)
centerObj:SetOffset( 0, GetPressure(diffX) );
for j = i + 1, numObjects do
diffX = textGroup.objects[j]:GetCenter() - cursorX;
textGroup.objects[j]:SetOffset( 0, GetPressure(diffX) );
end
for j = i - 1, 1, -1 do
diffX = textGroup.objects[j]:GetCenter() - cursorX;
textGroup.objects[j]:SetOffset( 0, GetPressure(diffX) );
end
return
end
end
--]]
for i = 1, numObjects do
local uiScale = UIParent:GetEffectiveScale();
--local obj;
local cursorX, cursorY = GetCursorPosition();
--cursorX = cursorX / uiScale
local x, y = textGroup.objects[i]:GetCenter();
local diffX = cursorX - x;
local diffY = cursorY - y;
diffY = diffY * 0.8;
local p, v = GetPressure( Distance(diffX, diffY) );
textGroup.objects[i]:SetOffset(0, p);
textGroup.objects[i]:SetValue(v);
end
end
end
--------------------------------------------------------------------------------------------------------
local FontStringPool = {};
FontStringPool.objects = {};
FontStringPool.numObjects = 0;
function FontStringPool:AccquireAndSetCharacter(textGroup, txt)
local obj;
for i = 1, self.numObjects do
obj = self.objects[i];
if not obj:IsActive() then
obj:SetCharacter(txt);
return obj
end
end
obj = textGroup:CreateFontString(textGroup, "OVERLAY", "NarciDynamicFontStringTemplate");
Mixin(obj, DynamicFontStringMixin);
obj:SetCharacter(txt);
tinsert(self.objects, obj);
self.numObjects = self.numObjects + 1;
return obj
end
--------------------------------------------------------------------------------------------------------
--Public
NarciDynamicTextGroupMixin = {};
function NarciDynamicTextGroupMixin:PlayClipText()
local f = self.updateFrame;
if not f then
f = CreateFrame("Frame");
f:Hide();
f.t = 0;
self.updateFrame = f;
end
local clip = self.ClipFrame;
local translationX = clip:GetWidth() + 2;
local duration = translationX/ERASE_SPEED;
f.t = ERASE_DELAY;
f:SetScript("OnUpdate", function(f, elapsed)
f.t = f.t + elapsed;
if f.t > 0 then
local offsetX = Lerp(0, translationX, f.t/duration);
if f.t > duration then
offsetX = translationX;
f:Hide();
end
clip:SetPoint("LEFT", self, "LEFT", offsetX, 0);
end
end)
f:Show();
clip:SetPoint("LEFT", self, "LEFT", 0, 0);
end
function NarciDynamicTextGroupMixin:SetText(txt)
self:SetSize(8, 8);
local characters, lenutf8 = UTF8toChars(txt);
self.fullText = txt;
self.objects = {};
local obj, char;
local totalWidth = 0;
local container = self.ClipFrame;
for i = 1, lenutf8 do
char = characters[i];
print(char)
obj = FontStringPool:AccquireAndSetCharacter(self, char);
obj:ClearAllPoints();
obj:SetParent(container);
self.objects[i] = obj;
obj:SetPosition("LEFT", self, "LEFT", totalWidth, 0);
totalWidth = totalWidth + obj:GetWidth();
end
self:SetWidth(totalWidth);
self:SetHeight(obj:GetHeight());
container:SetWidth(totalWidth);
--container:SetHeight(obj:GetHeight());
--self:SetScript("OnUpdate", TestOnUpdate);
end
function NarciDynamicTextGroupMixin:SetTextParticle(letter, offsetX, offsetY, amp, texAmp, color, step)
offsetX = offsetX or 0;
if not self.particles then
self.particles = {};
end
tinsert(self.particles, ParticleSystem:CreateLetter(self, letter, offsetX, offsetY, amp, texAmp, color, step));
end
function NarciDynamicTextGroupMixin:SetTextColor(r, g, b, a)
self.FontString1:SetTextColor(r, g, b, a);
end
function NarciDynamicTextGroupMixin:SetAlphaGradient(startPos)
self.FontString1:SetAlphaGradient(startPos, 8);
end
--/run NarciDynamicTextGroupTemplate:PlayFadeIn()
function NarciDynamicTextGroupMixin:PlayFadeIn()
local len = strlenutf8(self.FontString1:GetText());
self.fromPos = 0;
self.toPos = len;
self.duration = len/20;
self.t = 0;
self:SetScript("OnUpdate", function(self, elapsed)
self.t = self.t + elapsed;
local offset = Lerp(self.fromPos, self.toPos, self.t / self.duration)
self:SetAlphaGradient(offset);
if self.t >= self.duration then
self:SetScript("OnUpdate", nil);
end
end);
end
--/run NarciDynamicTextGroupTemplate:PlayFreeFall()
function NarciDynamicTextGroupMixin:PlayFreeFall()
local numObjects = #self.objects;
self.duration = 4;
self.t = 0;
local offsetXPerSec = 256;
local offsetYPerSec = -128;
for i = 1, numObjects do
self.objects[i]:SetOffset(0, 0);
self.objects[i]:SetAlpha(1);
end
self:SetScript("OnUpdate", function(self, elapsed)
local t = self.t + elapsed;
self.t = t;
offsetYPerSec = inOutSine(-128, 256, t/self.duration);
for i = 1, numObjects do
local oT = t - (i - 1)*0.5;
if oT > 0 then
local offsetX = offsetXPerSec * (oT)^2;
local offsetY = offsetYPerSec * (oT)^2;
self.objects[i]:SetOffset(offsetX, offsetY);
local alpha = 1 - oT*0.8;
if alpha < 0 then
alpha = 0;
end
self.objects[i]:SetAlpha(alpha)
end
end
if self.t >= self.duration then
--self:SetScript("OnUpdate", nil);
end
end);
end
--/run NarciDynamicTextGroupTemplate:PlayFlyIn()
function NarciDynamicTextGroupMixin:PlayFlyIn()
self.t = 0;
local numObjects = #self.objects;
local duration = 0.6;
for i = 1, numObjects do
self.objects[i]:SetValue(1, 0);
end
self:SetScript("OnUpdate", function(self, elapsed)
local t = self.t + elapsed;
self.t = t;
for i = 1, numObjects do
local oT = t - (i - 1)*0.1;
if oT > 0 then
local offsetX = 0;
local offsetY = outQuart(-128, 0, oT/duration);
if offsetY > 0 then
offsetY = 0;
end
self.objects[i]:SetOffset(offsetX, offsetY);
local alpha = 1 + offsetY / 64;
if alpha < 0 then
alpha = 0;
end
--self.objects[i]:SetAlpha(alpha);
local v = 1 - (oT - 2);
if v < 0.5 then
v = 0.5;
end
self.objects[i]:SetValue(v, alpha);
end
end
end);
end
--/run NarciDynamicTextGroupTemplate:PlayWind()
function NarciDynamicTextGroupMixin:PlayWind()
self.duration = 4;
self.t = ERASE_DELAY;
self.counter = 0;
local particleGroup;
local numGroup = #self.particles
local weights = {};
local leftMost = 9999;
local numParticles = 0;
for o = 1, numGroup do
particleGroup = self.particles[o];
local numObjects = #particleGroup;
local left;
for i = 1, numObjects do
particleGroup[i]:SetOffset(0, 0);
particleGroup[i]:SetAlpha(1);
particleGroup[i]:ResetMotion();
left = particleGroup[i].left;
if left < leftMost then
leftMost = left;
end
end
local random = math.random;
weights[o] = {};
for i = 1, numObjects do
weights[o][i] = random(100, 200)/100;
--print(weights[i])
end
end
print("Left Base: "..leftMost)
--Reassign Time Offset based on position: left to right
for o = 1, numGroup do
particleGroup = self.particles[o];
for i = 1, #particleGroup do
particleGroup[i].timeOffset = (leftMost - particleGroup[i].left)/ERASE_SPEED;
numParticles = numParticles + 1;
end
end
print("numParticles: "..numParticles)
local offsetXPerSec = 512;
local offsetYPerSec = 0;
local accX, accY; --acceleration
self:SetScript("OnUpdate", function(self, elapsed)
local t = self.t + elapsed;
self.t = t;
local oT;
local pIndex = 0;
local isLive;
local numLive = 0;
for gIndex = 1, numGroup do
particleGroup = self.particles[gIndex];
for i = 1, #particleGroup do
pIndex = pIndex + 1;
oT = t + particleGroup[i].timeOffset;
if oT > 0 then
if particleGroup[i].isActive then
offsetYPerSec = inOutSineCycle(40, -50, t/2);
accX = offsetXPerSec * weights[gIndex][i];
accY = offsetYPerSec * weights[gIndex][i];
local alpha = 1 - oT*1;
if alpha < 0 then
alpha = 0;
particleGroup[i]:Hide();
else
if alpha > 1 then
alpha = 1;
end
particleGroup[i]:Show();
end
particleGroup[i]:SetAlpha(alpha);
isLive = particleGroup[i]:SetOffsetByAcceleration(accX, accY, elapsed);
if isLive then
numLive = numLive + 1;
end
end
else
particleGroup[i]:Hide();
end
end
end
self.counter = self.counter + elapsed;
if self.counter > 0.5 then
self.counter = 0;
print("Active Particles: "..numLive);
end
if self.t > 1 and numLive < 4 then
self:SetScript("OnUpdate", nil);
end
end);
end
local letterWidth = {
D = 17,
W = 24,
R = 20,
e = 14,
a = 14,
h = 12,
i = 10,
p = 16,
r = 13,
s = 13,
t = 14,
l = 13,
['\''] = 10,
space = 15,
}
function NarciDynamicTextGroupMixin:OnLoad()
if false then return end
self.t = 0;
local txt = "Rae'shalare"; -- in like in the old classic versions of WoW.";
self:SetText(txt);
local letters, numLetters = UTF8toChars(txt);
local offsetX = -8 ---numLetters * 20 / 2;
local offsetY = 2.5;
local letter;
local totalWidth = 0;
local extraWidth;
for i = 1, #letters do
letter = letters[i];
if letter and letter ~= " " then
self:SetTextParticle(letter, offsetX + PIXEL_SCALE*( totalWidth ), offsetY, nil, nil, nil, 4);
extraWidth = letterWidth[letter];
else
extraWidth = letterWidth.space;
end
totalWidth = totalWidth + extraWidth;
end
txt = "Rae sha are";
letters, numLetters = UTF8toChars(txt);
totalWidth = 0;
for i = 1, #letters do
letter = letters[i];
if letter and letter ~= " " then
self:SetTextParticle(letter, offsetX + PIXEL_SCALE*( totalWidth ), offsetY - 4, 1, 0.8, {0, 0, 0}, 4);
extraWidth = letterWidth[letter];
else
extraWidth = letterWidth.space;
end
totalWidth = totalWidth + extraWidth;
end
--Create Sigil
local sigOffsetX = 27;
local sigOffsetY = 42;
tinsert(self.particles, ParticleSystem:CreateLetter(self, "SylvanasBackground", sigOffsetX, sigOffsetY, 2, 1.5, {0, 0, 0} ));
tinsert(self.particles, ParticleSystem:CreateLetter(self, "SylvanasDark", sigOffsetX, sigOffsetY, 2, 1.4, {0.29, 0.37, 0.41}));
tinsert(self.particles, ParticleSystem:CreateLetter(self, "SylvanasLight", sigOffsetX, sigOffsetY, 2, 1.4 ));
tinsert(self.particles, ParticleSystem:CreateLetter(self, "SylvanasBlood", sigOffsetX, sigOffsetY, 2, 1.5, {1, 0, 0} ));
letters = UTF8toChars("le e ar lte D ep i e");
extraWidth = 0;
offsetX = -112;
offsetY = 34;
for i = 1, #letters do
letter = letters[i];
if letter and letter ~= " " then
self:SetTextParticle(letter, offsetX + PIXEL_SCALE*( totalWidth ), offsetY, 0.4, 0.8, {0.53, 0.7, 0.741}, 2);
extraWidth = letterWidth[letter];
else
extraWidth = letterWidth.space;
end
totalWidth = totalWidth + extraWidth;
end
end
NarciItemCelebrationMixin = {};
function NarciItemCelebrationMixin:OnLoad()
NarciAPI.SetBorderTexture(self.Sigil, "Sylvanas");
self.Sigil:SetParent(self.DynamicText.ClipFrame);
self.Header:SetParent(self.DynamicText.ClipFrame);
end
function NarciItemCelebrationMixin:PlayCelebration()
UIFrameFadeIn(self, 0.25, 0, 1);
self.DynamicText:PlayWind();
self.DynamicText:PlayClipText();
end
--/run NarciItemCelebrationFrame:PlayCelebration();
--------------------------------------------------------------------------------------------------------
DataProvider.letters = {
--32*32
D = {169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 265, 266, 267, 275, 276, 277, 278, 297, 298, 299, 308, 309, 310, 311, 329, 330, 331, 341, 342, 343, 344, 361, 362, 363, 373, 374, 375, 376, 393, 394, 395, 406, 407, 408, 425, 426, 427, 438, 439, 440, 457, 458, 459, 470, 471, 472, 489, 490, 491, 502, 503, 504, 521, 522, 523, 534, 535, 536, 553, 554, 555, 566, 567, 568, 585, 586, 587, 597, 598, 599, 600, 617, 618, 619, 629, 630, 631, 649, 650, 651, 660, 661, 662, 663, 681, 682, 683, 691, 692, 693, 694, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 777, 778, 779, 780, 781, 782, 783, 784, 785},
W = {164, 165, 166, 175, 176, 177, 186, 187, 188, 189, 196, 197, 198, 207, 208, 209, 210, 218, 219, 220, 228, 229, 230, 231, 238, 239, 240, 241, 242, 250, 251, 252, 261, 262, 263, 270, 271, 272, 273, 274, 282, 283, 284, 293, 294, 295, 302, 303, 304, 305, 306, 307, 313, 314, 315, 316, 325, 326, 327, 334, 335, 337, 338, 339, 345, 346, 347, 357, 358, 359, 360, 365, 366, 367, 369, 370, 371, 377, 378, 379, 390, 391, 392, 397, 398, 399, 402, 403, 409, 410, 411, 422, 423, 424, 429, 430, 431, 434, 435, 436, 441, 442, 454, 455, 456, 461, 462, 466, 467, 468, 472, 473, 474, 487, 488, 492, 493, 494, 498, 499, 500, 504, 505, 506, 519, 520, 521, 524, 525, 526, 531, 532, 533, 536, 537, 538, 551, 552, 553, 556, 557, 563, 564, 565, 568, 569, 583, 584, 585, 587, 588, 589, 595, 596, 597, 599, 600, 601, 616, 617, 619, 620, 621,
628, 629, 631, 632, 633, 648, 649, 650, 651, 652, 653, 660, 661, 662, 663, 664, 665, 680, 681, 682, 683, 684, 692, 693, 694, 695, 696, 712, 713, 714, 715, 716, 724, 725, 726, 727, 728, 745, 746, 747, 748, 757, 758, 759, 760, 777, 778, 779, 789, 790, 791, 792},
R = {171, 172, 173, 174, 175, 176, 177, 178, 179, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 267, 268, 269, 276, 277, 278, 279, 299, 300, 301, 308, 309, 310, 311, 331, 332, 333, 341, 342, 343, 363, 364, 365, 373, 374, 375, 395, 396, 397, 404, 405, 406, 407, 427, 428, 429, 435, 436, 437, 438, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 523, 524, 525, 526, 527, 528, 529, 530, 531, 555, 556, 557, 562, 563, 564, 587, 588, 589, 594, 595, 596, 619, 620, 621, 627, 628, 629, 651, 652, 653, 659, 660, 661, 662, 683, 684, 685, 692, 693, 694, 715, 716, 717, 725, 726, 727, 747, 748, 749, 757, 758, 759, 760, 779, 780, 781, 790, 791, 792},
a = {332, 333, 334, 335, 336, 337, 338, 339, 340, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 396, 397, 402, 403, 404, 405, 435, 436, 437, 467, 468, 469, 499, 500, 501, 525, 526, 527, 528, 529, 530, 531, 532, 533, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 586, 587, 588, 589, 595, 596, 597, 618, 619, 620, 627, 628, 629, 650, 651, 652, 659, 660, 661, 682, 683, 684, 691, 692, 693, 714, 715, 716, 717, 721, 722, 723, 724, 725, 747, 748, 749, 750, 751, 752, 753, 754, 756, 757, 780, 781, 782, 783, 784, 785, 788, 789},
e = {334, 335, 336, 337, 338, 339, 340, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 396, 397, 398, 403, 404, 405, 406, 427, 428, 429, 436, 437, 438, 459, 460, 461, 469, 470, 471, 491, 492, 493, 501, 502, 503, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 587, 588, 589, 619, 620, 621, 651, 652, 653, 683, 684, 685, 686, 716, 717, 718, 719, 725, 726, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 782, 783, 784, 785, 786, 787, 788, 789},
h = {138, 139, 140, 170, 171, 172, 202, 203, 204, 234, 235, 236, 266, 267, 268, 298, 299, 300, 330, 331, 332, 335, 336, 337, 338, 339, 340, 341, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 394, 395, 396, 397, 398, 399, 403, 404, 405, 406, 426, 427, 428, 429, 436, 437, 438, 458, 459, 460, 461, 468, 469, 470, 490, 491, 492, 493, 500, 501, 502, 522, 523, 524, 532, 533, 534, 554, 555, 556, 564, 565, 566, 586, 587, 588, 596, 597, 598, 618, 619, 620, 628, 629, 630, 650, 651, 652, 660, 661, 662, 682, 683, 684, 692, 693, 694, 714, 715, 716, 724, 725, 726, 746, 747, 748, 756, 757, 758, 778, 779, 780, 788, 789, 790},
i = {144, 145, 175, 176, 177, 178, 207, 208, 209, 335, 336, 337, 367, 368, 369, 399, 400, 401, 431, 432, 433, 463, 464, 465, 495, 496, 497, 527, 528, 529, 559, 560, 561, 591, 592, 593, 623, 624, 625, 655, 656, 657, 687, 688, 689, 719, 720, 721, 751, 752, 753, 783, 784, 785},
p = {330, 331, 332, 335, 336, 337, 338, 339, 340, 362, 363, 364, 366, 367, 368, 369, 370, 371, 372, 373, 394, 395, 396, 397, 398, 403, 404, 405, 406, 426, 427, 428, 429, 436, 437, 438, 458, 459, 460, 461, 468, 469, 470, 471, 490, 491, 492, 501, 502, 503, 522, 523, 524, 533, 534, 535, 554, 555, 556, 565, 566, 567, 586, 587, 588, 597, 598, 599, 618, 619, 620, 621, 629, 630, 631, 650, 651, 652, 653, 660, 661, 662, 663, 682, 683, 684, 685, 686, 692, 693, 694, 714, 715, 716, 717, 718, 719, 722, 723, 724, 725, 726, 746, 747, 748, 750, 751, 752, 753, 754, 755, 756, 757, 778, 779, 780, 783, 784, 785, 786, 787, 788, 810, 811, 812, 842, 843, 844, 874, 875, 876, 906, 907, 908, 938, 939, 940, 970, 971, 972, 1003, 1004},
r = {333, 334, 335, 338, 339, 340, 341, 365, 366, 367, 369, 370, 371, 372, 373, 397, 398, 399, 400, 401, 402, 403, 429, 430, 431, 432, 433, 461, 462, 463, 464, 493, 494, 495, 496, 525, 526, 527, 557, 558, 559, 589, 590, 591, 621, 622, 623, 653, 654, 655, 685, 686, 687, 717, 718, 719, 749, 750, 751, 781, 782, 783},
s = {333, 334, 335, 336, 337, 338, 339, 340, 341, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 396, 397, 398, 404, 427, 428, 429, 460, 461, 462, 492, 493, 494, 495, 496, 525, 526, 527, 528, 529, 530, 558, 559, 560, 561, 562, 563, 564, 593, 594, 595, 596, 597, 627, 628, 629, 659, 660, 661, 691, 692, 693, 716, 717, 722, 723, 724, 725, 748, 749, 750, 751, 752, 753, 754, 755, 756, 780, 781, 782, 783, 784, 785, 786, 787},
t = {239, 240, 271, 272, 302, 303, 304, 333, 334, 335, 336, 337, 338, 339, 340, 341, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 398, 399, 400, 401, 430, 431, 432, 462, 463, 464, 494, 495, 496, 526, 527, 528, 558, 559, 560, 590, 591, 592, 622, 623, 624, 654, 655, 656, 686, 687, 688, 689, 718, 719, 720, 721, 722, 751, 752, 753, 754, 755, 756, 757, 784, 785, 786, 787, 788, 789},
l = {143, 144, 145, 175, 176, 177, 207, 208, 209, 239, 240, 241, 271, 272, 273, 303, 304, 305, 335, 336, 337, 367, 368, 369, 399, 400, 401, 431, 432, 433, 463, 464, 465, 495, 496, 497, 527, 528, 529, 559, 560, 561, 591, 592, 593, 623, 624, 625, 655, 656, 657, 687, 688, 689, 719, 720, 721, 751, 752, 753, 783, 784, 785},
['\'']= {175, 176, 177, 208, 209, 240, 241, 272, 273, 304, 305, 336, 337, 368, 369},
SylvanasBackground = {174, 175, 176, 179, 204, 205, 206, 207, 208, 212, 213, 235, 236, 237, 238, 239, 240, 245, 246, 265, 266, 267, 268, 269, 270, 271, 273, 274, 279, 280, 295, 296, 297, 298, 300, 301, 302, 305, 306, 307, 312, 313, 314, 326, 327, 330, 336, 338, 339, 340, 344, 345, 346, 347, 359, 360, 363, 368, 373, 376, 377, 378, 379, 391, 392, 394, 395, 401, 409, 410, 411, 423, 426, 427, 436, 443, 465, 505, 519, 520, 531, 532, 533, 534, 535, 536, 537, 538, 539, 551, 552, 553, 554, 563, 564, 565, 566, 569, 570, 571, 585, 586, 597, 618, 619, 625, 628, 629, 649, 650, 651, 656, 657, 660, 662, 666, 667, 679, 680, 681, 682, 683, 684, 689, 691, 692, 693, 694, 697, 698, 699, 712, 713, 716, 724, 725, 726, 730, 754, 755, 757, 758, 787, 788, 819, 820, 851},
SylvanasBlood = {84, 116, 150, 168, 169, 184, 199, 200, 202, 228, 229, 230, 231, 232, 260, 261, 262, 285, 293, 294, 317, 325, 326, 357, 375, 389, 413, 414, 453, 454, 676, 677, 708, 730, 731, 742, 743, 761, 762, 763, 766, 775, 793, 794, 823, 824, 845},
SylvanasDark = {16, 17, 47, 48, 49, 50, 77, 78, 79, 80, 81, 82, 84, 108, 109, 110, 112, 115, 116, 117, 138, 139, 140, 145, 149, 150, 151, 152, 168, 169, 182, 183, 184, 185, 199, 200, 201, 202, 210, 216, 217, 218, 219, 228, 229, 230, 231, 232, 242, 243, 244, 250, 251, 252, 253, 260, 261, 262, 276, 277, 278, 284, 285, 293, 294, 309, 310, 316, 317, 325, 326, 333, 334, 342, 343, 349, 357, 365, 366, 367, 374, 375, 389, 397, 398, 404, 407, 408, 413, 414, 421, 425, 430, 431, 432, 434, 435, 437, 438, 439, 440, 441, 445, 453, 454, 455, 456, 457, 458, 459, 462, 463, 464, 466, 467, 470, 471, 472, 473, 474, 475, 476, 477, 490, 491, 492, 493, 494, 495, 498, 503, 504, 506, 507, 508, 509, 517, 523, 524, 525, 526, 527, 549, 555, 556, 557, 558, 581, 588, 599, 600, 601, 602, 605, 613, 623, 631, 632, 633, 646, 654, 664, 676, 677, 678, 708, 720, 728, 729, 730, 731, 741, 742, 743, 746, 750, 751, 752, 760, 761, 762, 763, 764, 766, 775, 776, 777, 778, 783, 784, 785, 793, 794, 809, 810, 811, 812, 815, 816, 817, 823, 824, 842, 843, 844, 845, 848, 849, 876, 877, 878, 879, 881, 910, 911, 912, 913, 919, 944, 945,
952},
SylvanasLight = {49, 116, 117, 139, 149, 150, 151, 169, 183, 184, 185, 210, 217, 218, 243, 251, 252, 276, 277, 278, 284, 285, 309, 310, 342, 343, 366, 375, 407, 430, 437, 438, 440, 441, 463, 464, 467, 470, 471, 495, 524, 525, 526, 555, 556, 557, 558, 720, 752, 776, 777, 783, 784, 810, 811, 816, 843, 844, 845, 877, 878, 911, 912},
}