local sct_CRIT_FADEINTIME = 0.3; local sct_CRIT_HOLDTIME = 2.0; local sct_CRIT_FADEOUTTIME = 0.5; local sct_CRIT_X_OFFSET = 100; local sct_CRIT_Y_OFFSET = 75; local sct_CRIT_SIZE_PERCENT = 1.25; local sct_CRIT_FLASH_SIZE_PERCENT = 2; local sct_MAX_SPEED = .025; local sct_MIN_UPDATE_SPEED = .01; local sct_SIDE_POINT = 210; local sct_MAX_DISTANCE = 150; local sct_DIRECTION = 1; local sct_SPRINKLER_START = 18 local sct_SPRINKLER_STEP = -3; local sct_SPRINKLER_RADIUS = 20; local sct_SPRINKLER = sct_SPRINKLER_START; --Animation System variables local sct_TEXTCOUNT = 30 -- Number of text that can animate local arrAniData = {}; -- table to hold texts to animate local arrAniData2 = {}; SCT.ArrayAniData = {arrAniData, arrAniData2}; ---------------------- --Display the Text function SCT:DisplayText(msg, color, iscrit, type, frame, anitype) local adat, curDir; local startpos, lastpos, textsize; --Set up text animation adat = self:GetNextAniObj(frame); --set override animation adat.anitype = anitype or adat.anitype; --If its a crit hit, increase the size if (iscrit) then adat.textsize = adat.textsize * sct_CRIT_SIZE_PERCENT; if (self.db.profile["STICKYCRIT"]) then adat.crit = true; local critcount = self:CritCount(adat.frame); adat.posY = (adat.toppoint + adat.posY)/2; --if there are other Crits active, set offset. if (critcount > 0) then local randomposx = random(-1,1); local randomposy = random(-1,1); if randomposx == 0 and randomposy == 0 then randomposy = 1 end; adat.posX = adat.posX + (randomposx*sct_CRIT_X_OFFSET); adat.posY = adat.posY + (randomposy*sct_CRIT_Y_OFFSET); end --if flash crits are on if (self.db.profile["FLASHCRIT"]) then adat.critsize = adat.textsize * sct_CRIT_FLASH_SIZE_PERCENT; if (adat.textsize > 32) then adat.textsize = 32 end; end end end --if its not a sticky critm set up normal text start position if (adat.crit ~= true) then if (adat.anitype == 1) then --get the last known point of active items lastpos = self:MinPoint(adat.frame) if (not adat.direction) then --move the position down if ((lastpos - adat.posY) <= adat.textsize) then adat.posY = adat.posY - (adat.textsize - (lastpos - adat.posY)); end --if its gone too far down, stop if (adat.posY < (adat.bottompoint - sct_MAX_DISTANCE)) then adat.posY = (adat.bottompoint - sct_MAX_DISTANCE) adat.posX = adat.posX + (random(-1,1)*sct_CRIT_X_OFFSET) end adat.addY = self.db.profile["MOVEMENT"]; else adat.posY = adat.toppoint --move the position up if ((adat.posY - lastpos) <= adat.textsize) then adat.posY = adat.posY + (adat.textsize - (adat.posY - lastpos)); end --if its gone too far up, stop if (adat.posY > (adat.toppoint + sct_MAX_DISTANCE)) then adat.posY = (adat.toppoint + sct_MAX_DISTANCE) adat.posX = adat.posX + (random(-1,1)*sct_CRIT_X_OFFSET) end adat.addY = -1*self.db.profile["MOVEMENT"]; end else --get direction type if (adat.sidedir == 1) then sct_DIRECTION = sct_DIRECTION * -1; curDir = sct_DIRECTION; elseif (adat.sidedir == 2) then if (type=="event") then curDir = -1 else curDir = 1 end elseif (adat.sidedir == 3) then if (type=="event") then curDir = 1 else curDir = -1 end elseif (adat.sidedir == 4) then curDir = 1; elseif (adat.sidedir == 5) then curDir = -1; end adat.sidedir = curDir; --set animation start pos. if (adat.anitype == 2) then adat.addY = random(3,6); adat.posX = adat.posX - (20 * adat.sidedir); elseif (adat.anitype == 3) then adat.posX = adat.posX - (55 * adat.sidedir); adat.posY = adat.bottompoint + (random(0,200) - 100); adat.addX = self.db.profile["MOVEMENT"]; elseif (adat.anitype == 4) then adat.posX = adat.posX - (20 * adat.sidedir); adat.addY = random(8,13); adat.addX = random(8,13); elseif (adat.anitype == 5) then adat.posX = adat.posX - (20 * adat.sidedir); adat.addY = random(10,15); adat.addX = random(10,15); elseif (adat.anitype == 6) then adat.addX = sct_SPRINKLER; adat.addY = math.sqrt((sct_SPRINKLER_RADIUS ^ 2) - math.abs((sct_SPRINKLER ^ 2))) if ( adat.direction) then adat.addY = adat.addY * -1; end sct_SPRINKLER = sct_SPRINKLER + sct_SPRINKLER_STEP; if (sct_SPRINKLER < (sct_SPRINKLER_START * -1)) then sct_SPRINKLER = sct_SPRINKLER_START; end end end end --set default color if none if (not color) then color = {r = 1.0, g = 1.0, b = 1.0} end --If they want to tag all self events if (self.db.profile["SHOWSELF"]) then msg = SCT.LOCALS.SelfFlag..msg..SCT.LOCALS.SelfFlag end --set up text self:SetFontSize(adat, adat.font, adat.textsize, adat.fontshadow); adat:SetTextColor(color.r, color.g, color.b); adat:SetAlpha(adat.alpha); adat:SetPoint("CENTER", "UIParent", "CENTER", adat.posX, adat.posY); adat:SetText(msg); adat:Show(); tinsert(self.ArrayAniData[adat.frame], adat); --Start up onUpdate if (not SCT_ANIMATION_FRAME:IsVisible()) then SCT_ANIMATION_FRAME:Show(); end end ---------------------- -- Upate animations that are being used function SCT:UpdateAnimation(elapsed) local anyActive = false; local i, key, value; for i = 1, table.getn(self.ArrayAniData) do for key, value in self.ArrayAniData[i] do if (value:IsShown()) then anyActive = true; self:DoAnimation(value, elapsed); end end end --if none are active, stop onUpdate; if ((anyActive ~= true) and (SCT_ANIMATION_FRAME:IsVisible())) then SCT_ANIMATION_FRAME:Hide(); end end ---------------------- --Move text to get the animation function SCT:DoAnimation(aniData, elapsed) local speed = self.db.profile["ANIMATIONSPEED"] / 1000; --If a crit aniData.lastupdate = aniData.lastupdate + elapsed; if (aniData.crit) then self:CritAnimation(aniData,speed); --else normal text or event text else --if its time to update, move the text step positions while (aniData.lastupdate > speed) do --calculate animation if (aniData.anitype == 1) then self:VerticalAnimation(aniData); elseif (aniData.anitype == 2) then self:RainbowAnimation(aniData); elseif (aniData.anitype == 3) then self:HorizontalAnimation(aniData); elseif (aniData.anitype == 4) then self:AngledDownAnimation(aniData); elseif (aniData.anitype == 5) then self:AngledUpAnimation(aniData); elseif (aniData.anitype == 6) then self:SprinklerAnimation(aniData); end --set update on FPS mode if (self.db.profile["FPSMODE"]) then aniData.lastupdate = aniData.lastupdate - speed; else aniData.lastupdate = 0; end --move text aniData:SetAlpha(aniData.alpha); aniData:SetPoint("CENTER", "UIParent", "CENTER", aniData.posX, aniData.posY); --reset when alpha is 0 if (aniData.alpha <= 0) then self:AniReset(aniData); end end end end ---------------------- --Do Crit Animation function SCT:CritAnimation(aniData,speed) local elapsedTime = aniData.lastupdate; local fadeInTime = sct_CRIT_FADEINTIME; if ( elapsedTime < fadeInTime ) then local alpha = (elapsedTime / fadeInTime); alpha = alpha * aniData.alpha; aniData:SetAlpha(alpha); --if flash crits are on if (aniData.critsize) then local critsize = floor(aniData.critsize - ((aniData.critsize - aniData.textsize)*(elapsedTime/sct_CRIT_FADEINTIME))); aniData:SetTextHeight(critsize); end; return; end --if flash crits are on, reset size to make sure its clean for display if (aniData.critsize) then aniData:SetTextHeight(aniData.textsize); aniData.critsize = nil; end local holdTime = (sct_CRIT_HOLDTIME * (speed/sct_MAX_SPEED)); if ( elapsedTime < (fadeInTime + holdTime) ) then aniData:SetAlpha(aniData.alpha); return; end local fadeOutTime = sct_CRIT_FADEOUTTIME; if ( elapsedTime < (fadeInTime + holdTime + fadeOutTime) ) then local alpha = 1 - ((elapsedTime - holdTime - fadeInTime) / fadeOutTime); alpha = alpha * aniData.alpha; aniData:SetAlpha(alpha); return; end --reset crit self:AniReset(aniData); end ---------------------- --Do Vertical Animation function SCT:VerticalAnimation(aniData) local step = math.abs(aniData.addY); local alphastep = 0.01 * step; local max = sct_MAX_DISTANCE*.66 aniData.delay = aniData.delay + 1; if (aniData.delay > (max/step)) then aniData.alpha = aniData.alpha - alphastep; end aniData.posY = aniData.posY + aniData.addY; end ---------------------- --Do Rainbow Animation function SCT:RainbowAnimation(aniData) if (aniData.addY > 0) then aniData.addY = aniData.addY - 0.22 else aniData.addY = aniData.addY - (0.18 * (self.db.profile["MOVEMENT"]/2)); end if aniData.addY < -7 then aniData.addY = -7 end ; aniData.posY = aniData.posY + aniData.addY; aniData.posX = aniData.posX - 2.2 * aniData.sidedir; if ( aniData.posY < (aniData.bottompoint - sct_MAX_DISTANCE) ) then aniData.alpha = aniData.alpha - 0.05; end end ---------------------- --Do Horizontal Animation function SCT:HorizontalAnimation(aniData) local step = math.abs(aniData.addX); local alphastep = 0.01 * step; local max = sct_SIDE_POINT*.5 aniData.delay = aniData.delay + 1; if (aniData.delay > (max/step)) then aniData.alpha = aniData.alpha - alphastep; end aniData.posX = aniData.posX - (aniData.addX * aniData.sidedir); end ---------------------- --Do Angled Down Animation function SCT:AngledDownAnimation(aniData) if (aniData.delay <= 13) then aniData.delay = aniData.delay + 1; aniData.posY = aniData.posY - aniData.addY; aniData.posX = aniData.posX - aniData.addX * aniData.sidedir; elseif (aniData.delay <= 35) then aniData.delay = aniData.delay + 1; aniData.posY = aniData.posY + (random(0,70) - 35) * 0.02; aniData.posX = aniData.posX + (random(0,70) - 35) * 0.02; elseif (aniData.delay <= 50) then aniData.delay = aniData.delay + 1; else aniData.posY = aniData.posY + self.db.profile["MOVEMENT"]; aniData.posX = aniData.posX - self.db.profile["MOVEMENT"] * aniData.sidedir; aniData.alpha = aniData.alpha - 0.02; end end ---------------------- --Do Angled Up Animation function SCT:AngledUpAnimation(aniData) if (aniData.delay <= 13) then aniData.delay = aniData.delay + 1; aniData.posY = aniData.posY + aniData.addY; aniData.posX = aniData.posX - aniData.addX * aniData.sidedir; elseif (aniData.delay <= 35) then aniData.delay = aniData.delay + 1; aniData.posY = aniData.posY + (random(0,70) - 35) * 0.02; aniData.posX = aniData.posX + (random(0,70) - 35) * 0.02; elseif (aniData.delay <= 50) then aniData.delay = aniData.delay + 1; else aniData.posY = aniData.posY + self.db.profile["MOVEMENT"]; aniData.alpha = aniData.alpha - 0.02; end end ---------------------- --Do Sprinkler Animation function SCT:SprinklerAnimation(aniData) if (aniData.delay <= (self.db.profile["MOVEMENT"] + 10)) then aniData.delay = aniData.delay + 1; aniData.posY = aniData.posY + aniData.addY; aniData.posX = aniData.posX + aniData.addX; elseif (aniData.delay <= 35) then aniData.delay = aniData.delay + 1; aniData.posY = aniData.posY + (random(0,70) - 35) * 0.02; aniData.posX = aniData.posX + (random(0,70) - 35) * 0.02; elseif (aniData.delay <= 55) then aniData.delay = aniData.delay + 1; else aniData.posY = aniData.posY + (aniData.addY * .1); aniData.posX = aniData.posX + (aniData.addX * .1); aniData.alpha = aniData.alpha - 0.02; end end ---------------------- --count the number of crits active function SCT:CritCount(frame) local count = 0; local key, value; for key, value in self.ArrayAniData[frame] do if (value.crit) and (value.source == "sct") then count = count + 1; end end return count; end ---------------------- --get the min current min point function SCT:MinPoint(frame) local posY, key, value; if (not self.db.profile[self.FRAMES_DATA_TABLE][frame]["DIRECTION"]) then posY = self.db.profile[self.FRAMES_DATA_TABLE][frame]["YOFFSET"] + sct_MAX_DISTANCE; for key, value in self.ArrayAniData[frame] do if ((value:IsShown()) and (value.posY < posY) and (value.anitype == 1) and (not value.crit)) then posY = value.posY; end end else posY = self.db.profile[self.FRAMES_DATA_TABLE][frame]["YOFFSET"]; for key, value in self.ArrayAniData[frame] do if ((value:IsShown()) and (value.posY > posY) and (value.anitype == 1) and (not value.crit)) then posY = value.posY; end end end return posY; end ------------------------- --gets the next available animation object --can be used by SCT addons since public function SCT:GetNextAniObj(frame) local adat, i; local anyAvail = false; --get first now shown for i=1, sct_TEXTCOUNT do adat = getglobal("SCTaniData"..i); if ( not adat:IsShown() ) then anyAvail = true; break; end end --if none availble, get oldest if (not anyAvail) then for i = 1, table.getn(self.ArrayAniData) do adat = self.ArrayAniData[i][1]; if (adat) then break end; end self:AniReset(adat); end --set defaults based on frame adat.frame = frame; adat.posY = self.db.profile[self.FRAMES_DATA_TABLE][frame]["YOFFSET"]; adat.posX = self.db.profile[self.FRAMES_DATA_TABLE][frame]["XOFFSET"]; adat.bottompoint = adat.posY; adat.toppoint = adat.posY + sct_MAX_DISTANCE; adat.font = self.db.profile[self.FRAMES_DATA_TABLE][frame]["FONT"]; adat.fontshadow = self.db.profile[self.FRAMES_DATA_TABLE][frame]["FONTSHADOW"]; adat.textsize = self.db.profile[self.FRAMES_DATA_TABLE][frame]["TEXTSIZE"]; adat.alpha = self.db.profile[self.FRAMES_DATA_TABLE][frame]["ALPHA"]/100; adat.anitype = self.db.profile[self.FRAMES_DATA_TABLE][frame]["ANITYPE"]; adat.anisidetype = self.db.profile[self.FRAMES_DATA_TABLE][frame]["ANISIDETYPE"]; adat.direction = self.db.profile[self.FRAMES_DATA_TABLE][frame]["DIRECTION"]; adat.sidedir = self.db.profile[self.FRAMES_DATA_TABLE][frame]["ANISIDETYPE"]; return adat end ---------------------- --Rest the text animation function SCT:AniReset(aniData) local i, key, value --remove it from display table for i = 1, table.getn(self.ArrayAniData) do for key, value in self.ArrayAniData[i] do if ( value == aniData ) then tremove(self.ArrayAniData[i], key); break; end end end --reset all setings aniData.crit = false; aniData.critsize = nil; aniData.posY = 0; aniData.posX = 0; aniData.addY = 0; aniData.addX = 0; aniData.alpha = 0; aniData.lastupdate = 0; aniData.delay = 0; aniData.source = "sct"; aniData:SetAlpha(aniData.alpha); aniData:Hide(); aniData:SetPoint("CENTER", "UIParent", "CENTER", aniData.posX, aniData.posY); end ---------------------- --Rest all the text animations function SCT:AniResetAll() for i=1, sct_TEXTCOUNT do local aniData = getglobal("SCTaniData"..i); self:AniReset(aniData); end end ------------------------ --Initial animation settings function SCT:AniInit() self:AniResetAll(); self:SetMsgFont(SCT_MSG_FRAME); SCT_MSG_FRAME:SetPoint("CENTER", "UIParent", "CENTER", self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGXOFFSET"], self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGYOFFSET"]); SCT_MSG_FRAME:SetTimeVisible(self.db.profile[self.FRAMES_DATA_TABLE][SCT.MSG]["MSGFADE"]); self:SetDmgFont(); end