-- classic support

-- WoW flavor
--
-- @return .ClassicEra = true/false for Classic Era
--         .BCC        = true/false for BCC
--         .WotLKC     = true/false for WotLKC
--         .CataC      = true/false for CataC
--         .MoPC       = true/false for MoPC
--         .SL         = true/false for SL
--         .DF         = true/false for DF
--         .TWW        = true/false for TWW
local isWoWFlavor = {
	ClassicEra = false,
	BCC = false,
	WotLKC = false,
	CataC = false,
	MoPC = false,
	SL = false,
	DF = false,
	TWW = false
};

if (_G["WOW_PROJECT_ID"] == _G["WOW_PROJECT_CLASSIC"]) then
	isWoWFlavor.ClassicEra = true;
elseif (_G["WOW_PROJECT_ID"] == _G["WOW_PROJECT_BURNING_CRUSADE_CLASSIC"]) then
	isWoWFlavor.BCC = true;
elseif (_G["WOW_PROJECT_ID"] == _G["WOW_PROJECT_WRATH_CLASSIC"]) then
	isWoWFlavor.WotLKC = true;
elseif (_G["WOW_PROJECT_ID"] == _G["WOW_PROJECT_CATACLYSM_CLASSIC"]) then
	isWoWFlavor.CataC = true;
elseif (_G["WOW_PROJECT_ID"] == _G["WOW_PROJECT_MISTS_CLASSIC"]) then
	isWoWFlavor.MoPC = true;
else -- retail
	if (_G["LE_EXPANSION_LEVEL_CURRENT"] == _G["LE_EXPANSION_SHADOWLANDS"]) then
		isWoWFlavor.SL = true;
	elseif (_G["LE_EXPANSION_LEVEL_CURRENT"] == _G["LE_EXPANSION_DRAGONFLIGHT"]) then
		isWoWFlavor.DF = true;
	else
		isWoWFlavor.TWW = true;
	end
end

-- GearScore algorithms
local LFF_GEAR_SCORE_ALGORITHM = {
	TacoTip = 1, -- TacoTip's GearScore algorithm
	TipTac = 2 -- TipTac's GearScore algorithm
};

-- differences between WoW flavors
--
-- @return .guildNameInPlayerUnitTip                                   = true/false if the guild name is included in the player unit tip (since bc)
--         .specializationAndClassTextInPlayerUnitTip                  = true/false if a specialization and class text is included in the player unit tip (since df 10.1.5)
--         .rightClickForFrameSettingsTextInUnitTip                    = true/false if a right-click for frame settings is included in the unit tip (since tww 11.0.7)
--         .clickForSettingsTextInCurrencyTip                          = true/false if a click for settings is included in the currency tip (since tww 11.0.0)
--         .needsSuppressingErrorMessageAndSpeechWhenCallingCanInspect = true/false for suppressing error message and speech when calling CanInspect() (till mopc)
--         .talentsAvailableForInspectedUnit                           = true/false if getting talents from other players is available (since bc 2.3.0)
--         .numTalentTrees                                             = number of talent trees
--         .talentIconAvailable                                        = true/false if talent icon is available (since bc)
--         .roleIconAvailable                                          = true/false if role icon is available (since MoP 5.0.4)
--         .specializationAvailable                                    = true/false if specialization is available (since MoP 5.0.4)
--         .itemLevelOfFirstRaidTierSet                                = item level of first raid tier set. false if not defined (yet).
--         .GameTooltipSetPaddingWithLeftAndTop                        = true/false if GameTooltip:SetPadding() has the optional left and top parameters (since BfA 8.2.0)
--         .GameTooltipFadeOutNotBeCalledForWorldFrameUnitTips         = true/false if GameTooltip:FadeOut() will not be called for worldframe unit tips (till mopc)
--         .ShoppingTooltipHasCompareHeader                            = true/false if ShoppingTooltip1/2.CompareHeader exist (since tww 11.2.7)
--         .barMarginAdjustment                                        = bar margin adjustment (since bc till mopc)
--         .experienceBarDockedToInterfaceBar                          = true/false if experience bar is docked to interface bar (till df 10.0.0)
--         .experienceBarFrame                                         = frame of experience bar
--         .experienceBarMaxLevelBack                                  = max level to search back in frame chain to search for frame of experience bar
--         .realGetSpellLinkAvailable                                  = true/false if the real GetSpellLink() is available (since bc 2.3.0). in classic era this function only returns the spell name instead of a spell link.
--         .relatedExpansionForItemAvailable                           = true/false if C_Item.GetItemInfo() return the related expansion for an item (parameter expansionID) (since Legion 7.1.0)
--         .defaultGearScoreAlgorithm                                  = default GearScore algorithm
--         .optionsSliderTemplate                                      = options slider template ("OptionsSliderTemplate". since df 10.0.0, catac 4.4.0 and 1.15.4 "UISliderTemplateWithLabels")
--         .skyriding                                                  = true/false if skyriding is available (since df 10.0.2)
--         .challengeMode                                              = true/false if challenge mode is available (since Legion 7.0.3)
local hasWoWFlavor = {
	guildNameInPlayerUnitTip = true,
	specializationAndClassTextInPlayerUnitTip = true,
	rightClickForFrameSettingsTextInUnitTip = true,
	clickForSettingsTextInCurrencyTip = true,
	needsSuppressingErrorMessageAndSpeechWhenCallingCanInspect = false,
	talentsAvailableForInspectedUnit = true,
	numTalentTrees = 2,
	talentIconAvailable = true,
	roleIconAvailable = true,
	specializationAvailable = true,
	itemLevelOfFirstRaidTierSet = false,
	GameTooltipSetPaddingWithLeftAndTop = true,
	GameTooltipFadeOutNotBeCalledForWorldFrameUnitTips = false,
	ShoppingTooltipHasCompareHeader = true,
	barMarginAdjustment = 0,
	experienceBarFrame = MainStatusTrackingBarContainer,
	experienceBarDockedToInterfaceBar = false,
	realGetSpellLinkAvailable = true,
	relatedExpansionForItemAvailable = true,
	defaultGearScoreAlgorithm = LFF_GEAR_SCORE_ALGORITHM.TipTac,
	optionsSliderTemplate = "UISliderTemplateWithLabels",
	skyriding = (C_MountJournal and C_MountJournal.SwapDynamicFlightMode and true or false), -- see MountJournalDynamicFlightModeButtonMixin:OnClick() in "Blizzard_MountCollection.lua"
	challengeMode = (C_ChallengeMode and C_ChallengeMode.IsChallengeModeActive and true or false)
};

if (isWoWFlavor.ClassicEra) then
	hasWoWFlavor.guildNameInPlayerUnitTip = false;
	hasWoWFlavor.talentsAvailableForInspectedUnit = false;
	hasWoWFlavor.talentIconAvailable = false;
	hasWoWFlavor.realGetSpellLinkAvailable = false;
end
if (isWoWFlavor.ClassicEra) or (isWoWFlavor.BCC) or (isWoWFlavor.WotLKC) then
	hasWoWFlavor.defaultGearScoreAlgorithm = LFF_GEAR_SCORE_ALGORITHM.TacoTip;
end
if (isWoWFlavor.ClassicEra) or (isWoWFlavor.BCC) or (isWoWFlavor.WotLKC) or (isWoWFlavor.CataC) then
	hasWoWFlavor.numTalentTrees = 3;
	hasWoWFlavor.roleIconAvailable = false;
	hasWoWFlavor.specializationAvailable = false;
end
if (isWoWFlavor.ClassicEra) or (isWoWFlavor.BCC) or (isWoWFlavor.WotLKC) or (isWoWFlavor.CataC) or (isWoWFlavor.MoPC) then
	hasWoWFlavor.needsSuppressingErrorMessageAndSpeechWhenCallingCanInspect = true;
	hasWoWFlavor.GameTooltipSetPaddingWithLeftAndTop = false;
	hasWoWFlavor.GameTooltipFadeOutNotBeCalledForWorldFrameUnitTips = true;
	hasWoWFlavor.relatedExpansionForItemAvailable = false;
end
if (isWoWFlavor.WotLKC) or (isWoWFlavor.SL) then
	hasWoWFlavor.optionsSliderTemplate = "OptionsSliderTemplate";
end
if (isWoWFlavor.ClassicEra) or (isWoWFlavor.BCC) or (isWoWFlavor.WotLKC) or (isWoWFlavor.CataC) or (isWoWFlavor.MoPC) or (isWoWFlavor.SL) then
	hasWoWFlavor.specializationAndClassTextInPlayerUnitTip = false;
	hasWoWFlavor.experienceBarDockedToInterfaceBar = true;
	hasWoWFlavor.experienceBarFrame = (MainMenuExpBar or MainStatusTrackingBarContainer);
	hasWoWFlavor.experienceBarMaxLevelBack = (MainMenuExpBar and 1 or MainStatusTrackingBarContainer and 3);
end
if (isWoWFlavor.ClassicEra) or (isWoWFlavor.BCC) or (isWoWFlavor.WotLKC) or (isWoWFlavor.CataC) or (isWoWFlavor.MoPC) or (isWoWFlavor.SL) or (isWoWFlavor.DF) then
	hasWoWFlavor.rightClickForFrameSettingsTextInUnitTip = false;
end
if (isWoWFlavor.CataC) or (isWoWFlavor.MoPC) then
	hasWoWFlavor.barMarginAdjustment = -1;
end
if (isWoWFlavor.MoPC) or (isWoWFlavor.SL) then
	hasWoWFlavor.numTalentTrees = 0;
end
if (isWoWFlavor.DF) then
	hasWoWFlavor.skyriding = (GetAchievementInfo(15794) and true or false) -- see DRAGONRIDING_ACCOUNT_ACHIEVEMENT_ID in "Blizzard_DragonflightLandingPage.lua"
end
hasWoWFlavor.itemLevelOfFirstRaidTierSet = 
	isWoWFlavor.ClassicEra and  66 or -- Cenarion Vestments (Druid, Tier 1)
	isWoWFlavor.BCC        and 120 or -- Chestguard of Malorne (Druid, Tier 4)
	isWoWFlavor.WotLKC     and 213 or -- Valorous Dreamwalker Robe (Druid, Tier 7)
	isWoWFlavor.CataC      and 359 or -- Stormrider's Robes (Druid, Tier 11)
	isWoWFlavor.MoPC       and 397 or -- Deep Earth Robes (Druid, Tier 13)
	isWoWFlavor.DF         and 395 or -- Lost Landcaller's Robes (Druid, Tier 29)
	isWoWFlavor.TWW        and 571;   -- Hide of the Greatlynx (Druid, Tier 32)

local function GetSpellInfo(spellIdentifier)
	-- since tww 11.0.0
	if (C_Spell) and (C_Spell.GetSpellInfo) then
		if (not spellIdentifier) then
			return nil;
		end
		
		local spellInfo = C_Spell.GetSpellInfo(spellIdentifier);
		
		if (not spellInfo) then
			return nil;
		end
		
		return spellInfo.name, _, spellInfo.iconID, spellInfo.castTime, spellInfo.minRange, spellInfo.maxRange, spellInfo.spellID, spellInfo.originalIconID;
	end
	
	-- before tww 11.0.0
	return _G.GetSpellInfo(spellIdentifier); -- [18.07.19] 8.0/BfA: 2nd param "rank/nameSubtext" now returns nil
end

-- get spell link
--
-- @param  spellIdentifier  spell id, name, name(subtext) or link
-- @param  glyphID          optional. glyph id.
-- @return spellLink
local function GetSpellLink(spellIdentifier, glyphID)
	-- since tww 11.0.0
	if (C_Spell) and (C_Spell.GetSpellLink) then
		if (not spellIdentifier) then
			return nil;
		end
		
		return C_Spell.GetSpellLink(spellIdentifier, glyphID);
	end
	
	-- before tww 11.0.0
	if (not hasWoWFlavor.realGetSpellLinkAvailable) then
		local spellInfo = self:GetSpellInfo(spellIdentifier);
		
		return format("|c%s|Hspell:%d:0|h[%s]|h|r", "FF71D5FF", spellInfo and spellInfo.spellID, spellInfo and spellInfo.name);
	end
	
	return _G.GetSpellLink(spellIdentifier);
end

local function SendChatMessage(message, chatType, languageID, target)
	-- since tww 11.2.0
	if (C_ChatInfo) and (C_ChatInfo.SendChatMessage) then
		C_ChatInfo.SendChatMessage(message, chatType, languageID, target);
		return;
	end
	
	-- before tww 11.2.0
	_G.SendChatMessage(message, chatType, languageID, target);
end

function Comix_OnLoad()

  -- Registering Events --

  Comix_Frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")

  Comix_Frame:RegisterEvent("UPDATE_STEALTH")
  Comix_Frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
  Comix_Frame:RegisterEvent("PLAYER_TARGET_CHANGED")
  Comix_Frame:RegisterEvent("CHAT_MSG_TEXT_EMOTE")
  Comix_Frame:RegisterEvent("CHAT_MSG_EMOTE")
  Comix_Frame:RegisterEvent("CHAT_MSG_YELL")
  Comix_Frame:RegisterEvent("UNIT_HEALTH")
  Comix_Frame:RegisterEvent("UNIT_SPELLCAST_SENT")
  Comix_Frame:RegisterEvent("RESURRECT_REQUEST")
  Comix_Frame:RegisterEvent("PLAYER_ALIVE")
  Comix_Frame:RegisterEvent("PLAYER_UNGHOST")
  Comix_Frame:RegisterEvent("PLAYER_DEAD")
  Comix_Frame:RegisterEvent("READY_CHECK")
  Comix_Frame:RegisterEvent("PLAYER_LOGIN")

  ComixVersion = C_AddOns.GetAddOnMetadata( 'Comix', 'Version' );
  ComixOptionsHeader = "Comix Options "..ComixVersion;

  -- Saying Hello --
  DEFAULT_CHAT_FRAME:AddMessage("Comix "..ComixVersion.." sais: Hello you there, this AddOn is enabled by default! Standby while I'm loading resources!",0.7,0.7,1);

  SlashCmdList["ComixJoke"] = Comix_BadJoke;
  SLASH_ComixJoke1 = "/badjoke";

  SlashCmdList["ComixFail"] = Comix_Fail;
  SLASH_ComixFail1 = "/fail";

  SlashCmdList["ComixAwesome"] = Comix_Awesome;
  SLASH_ComixAwesome1 = "/awesome";

  SlashCmdList["ComixDrama"] = Comix_Drama;
  SLASH_ComixDrama1 = "/drama";

  SlashCmdList["ComixReload"] = Comix_ReloadUI;
  SLASH_ComixReload1 = "/rl";

  Comix_dontfireonalive = false;
  Comix_loaded = false;
  Comix_unghosted = false;
  Comix_dead = false;
  
  Comix_isStealthed = IsStealthed();
  Comix_stealthed_isPlaying = false;
  Comix_stealthed_timestamp = 0;
  Comix_stealthed_soundHandle = nil;

  -- Setting variables --
  Comix_ShakeEnabled = false;
  Comix_ShakeDuration = 1;
  Comix_ShakeIntensity = 70;
  Comix_ShakeOffset = 1;
  Comix_x_coord = 0;
  Comix_y_coord = 0;
  Comix_Max_Scale = 2;
  ComixCurrentFrameCt = 1;
  ComixCritCount = 0;
  ComixBuffCount = 0;
  ComixAniSpeed = 2;
  ComixMaxCrits = 3;
  ComixKillCount = 0;
  Comix_CritPercent = 100;
  Comix_CritGap = 0;
  Comix_FinishHimGap = 20;
  Comix_Overkill = 75;
  Comix_CurrentImage = nil;

  Comix_Frames = {};
  Comix_FramesScale = {}
  Comix_FramesVisibleTime = {}
  Comix_FramesStatus = {}
  Comix_textures = {};
  Comix_CritSoundsEnabled = true;
  Comix_CritHealsEnabled = true;
  Comix_SpecialsEnabled = true;
  Comix_KillCountEnabled = true;
  Comix_DeathSoundEnabled = true;
  ComixKillCountSoundPlayed = false;
  Comix_HuggedNotFound = false;
  Comix_AddOnEnabled = true;
  Comix_SoundEnabled = true;
  Comix_BS_Update = false;
  Comix_BSEnabled = true;
  Comix_DemoShoutEnabled = true;
  Comix_ZoneEnabled = false;
  Comix_FinishTarget = true;
  Comix_BamEnabled = false;
  Comix_ImagesEnabled = true;
  Comix_FinishhimEnabled = true;

  Comix_CritGapEnabled = false;
  Comix_OverkillEnabled = true;
  Comix_OneHit = false;

  Comix_PublicObjections = true;
  Comix_ObjectionSoundsEnabled = true;
  Comix_ObjectionImagesEnabled = true;

  Comix_BsShortDuration = true;
  Comix_HealorDmg = true;
  Comix_PlayerClass = UnitClass("player")

  Comix_CritFlashEnabled = true;
  Comix_HealFlashEnabled = true;
  Comix_BSSounds = true;
  Comix_DSSounds = true;
  Comix_BounceSoundEnabled = true;
  Comix_JumpCount = 0;
  Comix_StealthSoundEnabled = true;
  Comix_ResSoundEnabled = true;
  Comix_ReadySoundEnabled = true;

  Comix_AbilitySoundsEnabled = true;

  -- Hug Counter Variables --
  Comix_Hugs = {}
  Comix_Hugged = {}
  Comix_HugName = {}
  Comix_HugName[1] = UnitName("player")
  Comix_Hugs[1] = 0
  Comix_Hugged[1] = 0

  -- These might be deprecated after the unit speed check change, don't remove util code is cleaned up more --
  Comix_forward = false;
  Comix_back = false;
  Comix_left = false;
  Comix_right = false;

  -- Calling functions to Create Frames and Load The Images/Sounds --
  Comix_CreateFrames();
  Comix_LoaddaShite();
  Comix_TimeSinceLastUpdate = 0;
  Comix_DongSound(ComixSpecialSounds, 6);

  Comix_DefaultWorldFramePoints = {}; -- for making sure the screen shakes are putting the world frame back in the right place

  -- Establish actual game version used for Classic / Retail API changes
  Comix_GameToc = select(4, GetBuildInfo());

  -- Slash Commands --
  SlashCmdList["Comix"] = Comix_Command;
  SLASH_Comix1 = "/Comix";
  SLASH_Comix2 = "/comix";
  SLASH_Comix3 = "/Comixreloaded";
  SLASH_Comix4 = "/comixreloaded";
  if Comix_GameToc < 20000 then
    SLASH_Comix5 = "/Comixclassic";
    SLASH_Comix6 = "/comixclassic";
  end
end

local function startReadyCheck()
  if Comix_AddOnEnabled then
    if Comix_ReadySoundEnabled then
      Comix_DongSound(ComixReadySounds, fastrandom(1, ComixReadySoundsCt));
    end
  end
end

hooksecurefunc("DoReadyCheck", startReadyCheck)

local function PlayBounceSound()
  if Comix_AddOnEnabled then
    local boing, landed = false, false;

    -- Check if player is moving. Used for mount boings
    if GetUnitSpeed("player") > 0 then
      boing = true;
    end

    -- Check if player is already in the air, this is to prevent sounds while already jumping.
    if IsFalling() == false then
      landed = true;
    end

    if not UnitOnTaxi("player") then
      if IsMounted() then
        if Comix_GameToc >= 20000 then
          -- DEFAULT_CHAT_FRAME:AddMessage("After TBC - Flying exists",1,0,0);
          -- DEFAULT_CHAT_FRAME:AddMessage(Comix_GameToc,1,0,0);
          if not IsFlying() and landed and not IsSwimming() then
            -- DEFAULT_CHAT_FRAME:AddMessage("Triggers when jumping in TBC or later, not flying, not in the air, not swimming",1,0,0);
            if boing then
              Comix_JumpCount = Comix_JumpCount + 1;
            end
            if Comix_BounceSoundEnabled and boing then
              Comix_DongSound(ComixSpecialSounds, 8);
            end
          end
        else
          if landed and not IsSwimming() then
            -- DEFAULT_CHAT_FRAME:AddMessage("Classic - Flying API doesn't exist yet",1,0,0);
            -- DEFAULT_CHAT_FRAME:AddMessage(Comix_GameToc,1,0,0);
            if boing then
              Comix_JumpCount = Comix_JumpCount + 1;
            end
            if Comix_BounceSoundEnabled and boing then
              Comix_DongSound(ComixSpecialSounds, 8);
            end
          end
        end
      else
        if Comix_GameToc < 20000 then
          if landed and not IsSwimming() then
            -- DEFAULT_CHAT_FRAME:AddMessage("Triggers when jumping unmounted in Classic, not in the air, not swimming",1,0,0);
            Comix_JumpCount = Comix_JumpCount + 1;
            if Comix_BounceSoundEnabled and landed then
              Comix_DongSound(ComixSpecialSounds, 8);
            end
          end
        else
          if not IsFlying() and landed and not IsSwimming() then
            -- DEFAULT_CHAT_FRAME:AddMessage("Triggers when jumping in TBC or later, unmounted, with extra check for druid flightform, not in the air, not swimming",1,0,0);
            Comix_JumpCount = Comix_JumpCount + 1;
            if Comix_BounceSoundEnabled then
              Comix_DongSound(ComixSpecialSounds, 8);
            end
          end
        end
      end
    end
  end
end

hooksecurefunc("JumpOrAscendStart", PlayBounceSound)

-- These might be deprecated. Need to clean up more code to make sure --
local function forwardstart()
  Comix_forward = true;
end

hooksecurefunc("MoveForwardStart", forwardstart)

local function forwardstop()
  Comix_forward = false;
end

hooksecurefunc("MoveForwardStop", forwardstop)

local function backstart()
  Comix_back = true;
end

hooksecurefunc("MoveBackwardStart", backstart)

local function backstop()
  Comix_back = false;
end

hooksecurefunc("MoveBackwardStop", backstop)

local function leftstart()
  Comix_left = true;
end

hooksecurefunc("StrafeLeftStart", leftstart)

local function leftstop()
  Comix_left = false;
end

hooksecurefunc("StrafeLeftStop", leftstop)

local function rightstart()
  Comix_right = true;
end

hooksecurefunc("StrafeRightStart", rightstart)

local function rightstop()
  Comix_right = false;
end

hooksecurefunc("StrafeRightStop", rightstop)

local function KillCount()
  if Comix_KillCountEnabled then

    --if strfind(arg1,getglobal("COMIX_YOUUP")) then
    ComixKillCount = ComixKillCount +1;
    ComixKillCountSoundPlayed = false;
    --end

    if ComixKillCountSoundPlayed == false then
      if ComixKillCount == 2 then
        Comix_DongSound(ComixKillCountSounds,1)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 5 then
        Comix_DongSound(ComixKillCountSounds,2)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 8 then
        Comix_DongSound(ComixKillCountSounds,3)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 10 then
        Comix_DongSound(ComixKillCountSounds,4)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 15 then
        Comix_DongSound(ComixKillCountSounds,5)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 20 then
        Comix_DongSound(ComixKillCountSounds,6)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 30 then
        Comix_DongSound(ComixKillCountSounds,7)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 40 then
        Comix_DongSound(ComixKillCountSounds,8)
        ComixKillCountSoundPlayed = true
      elseif ComixKillCount == 50 then
        Comix_DongSound(ComixKillCountSounds,9)
        ComixKillCountSoundPlayed = true
      end
    end
  end
end

-- Stealthed and Moving Sounds
local function PlayStealthSound()
	if (not Comix_AddOnEnabled) or (not Comix_StealthSoundEnabled) then
		return;
	end
	
	if (not Comix_stealthed_isPlaying) or (Comix_stealthed_isPlaying) and (GetTime() - Comix_stealthed_timestamp > 7.1) then -- length of sound file exceeded
		local willPlay, soundHandle = Comix_DongSound(ComixSpecialSounds, 20);
		Comix_stealthed_isPlaying = true;
		Comix_stealthed_timestamp = GetTime();
		Comix_stealthed_soundHandle = soundHandle;
	end
end

local function StopStealthSound()
	if (Comix_stealthed_isPlaying) then
		Comix_StopDongSound(Comix_stealthed_soundHandle);
		Comix_stealthed_isPlaying = false;
		Comix_stealthed_timestamp = 0;
		Comix_stealthed_soundHandle = nil;
	end
end

-- handle events
function Comix_OnEvent(self, event, ...)
  --DEFAULT_CHAT_FRAME:AddMessage("ON EVENT LOLZ",0,0,1);
  --local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18 = select(1, ...)
  local timestamp, subEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, extraArg1, spellName, spellSchool, damageAmount, overkillAmount, extraArg6, critical, extraArg8, extraArg9, extraArg10 = CombatLogGetCurrentEventInfo()

  if (Comix_AddOnEnabled) then

    if event == "PLAYER_LOGIN" then
      --this gets the position of the world frame at player login or during an interface reload so that it knows where it should be
      for i = 1, WorldFrame:GetNumPoints() do
        local point, frame, relPoint, xOffset, yOffset = WorldFrame:GetPoint(i);
        --DEFAULT_CHAT_FRAME:AddMessage("p- "..point..",r- "..relPoint..",xO- "..xOffset..",yO- "..yOffset)
        Comix_DefaultWorldFramePoints[i] = {
          ["point"] = point,
          ["frame"] = frame,
          ["relPoint"] = relPoint,
          ["xOffset"] = xOffset,
          ["yOffset"] = yOffset,
        }
      end
    end

    if event == "COMBAT_LOG_EVENT_UNFILTERED" then
      --DEFAULT_CHAT_FRAME:AddMessage("COMBAT_LOG_EVENT_UNFILTERED fired "..select(2, ...));
      --DEFAULT_CHAT_FRAME:AddMessage("Should fire on self event "..select(2, ...));

      -- debug spells ;)
      --if sourceName == UnitName("player") then
      --  DEFAULT_CHAT_FRAME:AddMessage("tS:"..timestamp.." / subEvent: "..subEvent.." / eA1: "..tostring(extraArg1).." / spellName: "..tostring(spellName).." / spellSchool: "..tostring(spellSchool).." / damage: "..tostring(damageAmount).." / overkill: "..tostring(overkillAmount).." / eA6: "..tostring(extraArg6).." / critical: "..tostring(critical).." / eA8: "..tostring(extraArg8).." / eA9: "..tostring(extraArg9) .." / eA10: "..tostring(extraArg10));
      --end


      if subEvent == "SPELL_AURA_APPLIED" then
        if sourceName == UnitName("player") then
          --DEFAULT_CHAT_FRAME:AddMessage("Should fire on self event "..arg10);
          if spellName == COMIX_BS then
            if Comix_BSEnabled then
              Comix_Pic(0, 0,ComixSpecialImages[1])

              if Comix_BSSounds then
                Comix_DongSound(ComixSpecialSounds,1)
              end
            end
          elseif spellName == COMIX_DS or spellName == COMIX_DR then
            if Comix_DemoShoutEnabled then
              Comix_Pic(0, 0,ComixSpecialImages[2])

              if Comix_DSSounds then
                Comix_DongSound(ComixSpecialSounds,fastrandom(2,3))
              end
            end
          end
        end
      end


      if sourceFlags ~= nil then
        if bit.band(sourceFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) > 0 then
          if subEvent == "SPELL_HEAL" then
            if sourceName == UnitName("player") then
              --don't do anything for heals casted by player here
            else
              if destName == UnitName("player") then --someone cast a heal on the player we need to fire on a crit
                if critical == true then
                  if Comix_CritGapEnabled == true then
                    if damageAmount < Comix_CritGap then
                      return --nothin to see here
                    end
                  end
                  if fastrandom(1,100) <= Comix_CritPercent then
                    --heal cast on the player crit fire off stuff
                    --DEFAULT_CHAT_FRAME:AddMessage("heal crit fire friendly");
                    if Comix_HealFlashEnabled then
                      Comix_ScreenFlash(0, 1, 0, 1);
                      --UIFrameFlash( Comix_FrameFlash2, 0.5, 0.5, 2, false, 1, 0);
                    end
                    Comix_CallPic(ComixHolyHealImages[fastrandom(1, ComixHolyHealImagesCt)])
                    if Comix_CritHealsEnabled then
                      Comix_DongSound(ComixHealingSounds,fastrandom(1,ComixHealingSoundsCt))
                    end
                  end
                end
              end
            end
            --DEFAULT_CHAT_FRAME:AddMessage("Spell heal!! firing target = "..arg7);
          end
        end
      end

      if bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) > 0 then
        if subEvent == "PARTY_KILL" then
          --DEFAULT_CHAT_FRAME:AddMessage("Should fire on self event "..arg2);
          KillCount()
        end
        --DEFAULT_CHAT_FRAME:AddMessage("Should fire on self event "..arg2);
        if subEvent == "SPELL_HEAL" then
          --DEFAULT_CHAT_FRAME:AddMessage("Spell heal firing arg11 = "..tostring(arg12).." "..arg13);
          if critical == true then
            if Comix_CritGapEnabled == true then
              if damageAmount < Comix_CritGap then
                return --nothin to see here
              end
            end

            if fastrandom(1,100) <= Comix_CritPercent then
              --DEFAULT_CHAT_FRAME:AddMessage("heal crit fire mine");
              if Comix_HealFlashEnabled then
                if destName == UnitName("player") then
                  --UIFrameFlash( Comix_FrameFlash2, 0.5, 0.5, 2, false, 1, 0); --self
                  Comix_ScreenFlash(0, 1, 0, 1);
                else
                  Comix_ScreenFlash(0, 1, 0, 2);
                  --	UIFrameFlash( Comix_FrameFlash4, 0.5, 0.5, 2, false, 1, 0);
                end
              end

              Comix_CallPic(ComixHolyHealImages[fastrandom(1, ComixHolyHealImagesCt)])
              if Comix_CritHealsEnabled then
                Comix_DongSound(ComixHealingSounds,fastrandom(1,ComixHealingSoundsCt))
              end
            end
          end
        end
        if subEvent == "SPELL_DAMAGE" or subEvent == "RANGE_DAMAGE" then
          --DEFAULT_CHAT_FRAME:AddMessage("spell/range_dmg fired "..arg10.." "..arg11.." "..arg15.." "..arg15.." "..tostring(critical));
          --DEFAULT_CHAT_FRAME:AddMessage("spell/range_dmg fired "..arg12 - arg13.." "..arg13 / (arg12 - arg13))

          --DEFAULT_CHAT_FRAME:AddMessage(damageAmount);
          --DEFAULT_CHAT_FRAME:AddMessage(overkillAmount);
          if Comix_OverkillEnabled == true and damageAmount ~= nil then

            if (damageAmount - overkillAmount) == 1 then
              --do nothing on training dummy
            else
              if overkillAmount / (damageAmount - overkillAmount) > Comix_Overkill / 100 then
                Comix_CallPic(ComixOverkillImages[fastrandom(1, ComixOverkillImagesCt)]);
                --DEFAULT_CHAT_FRAME:AddMessage("overkill")
              end
            end
          end

          --DEFAULT_CHAT_FRAME:AddMessage("crittest "..tostring(critical));
    			if extraArg10 == true then -- extraArg10 is critical with spelldamage
            if Comix_CritGapEnabled == true then

              if damageAmount < Comix_CritGap then
                return --nothin to see here
              end

            end


            if fastrandom(1,100) <= Comix_CritPercent then
              if Comix_ShakeEnabled then
                -- Disabled due to errors
                --Comix_ShakeScreen()
              end

              ComixCritCount = ComixCritCount + 1

              if ComixCritCount >= ComixMaxCrits then
                if Comix_SpecialsEnabled then
                  Comix_DongSound(ComixSpecialSounds,4)
                end
                Comix_Pic(Comix_x_coord+fastrandom(-15,15),Comix_y_coord+fastrandom(-20,20),ComixSpecialImages[3])
                ComixCritCount = 0
              end



              if Comix_CritSoundsEnabled then
                Comix_DongSound(ComixSounds)
              end
              if Comix_CritFlashEnabled then
                Comix_ScreenFlash(1, 0, 0, 2);
                --UIFrameFlash( Comix_FrameFlash3, 0.5, 0.5, 2, false, 1, 0);
              end

              if spellSchool == 16 then
                Comix_CallPic(ComixFrostImages[fastrandom(1,ComixFrostImagesCt)]);
              elseif spellSchool == 20 then
                Comix_CallPic(ComixFrostfireImages[fastrandom(1,ComixFrostfireImagesCt)]);
              elseif spellSchool == 4 then
                Comix_CallPic(ComixFireImages[fastrandom(1,ComixFireImagesCt)]);
              elseif spellSchool == 2 then
                Comix_CallPic(ComixHolyDmgImages[fastrandom(1,ComixHolyDmgImagesCt)]);
              elseif spellSchool == 8 then
                Comix_CallPic(ComixNatureImages[fastrandom(1,ComixNatureImagesCt)]);
              elseif spellSchool == 32 then
                Comix_CallPic(ComixShadowImages[fastrandom(1,ComixShadowImagesCt)]);
              elseif spellSchool == 36 then
                Comix_CallPic(ComixShadowflameImages[fastrandom(1,ComixShadowflameImagesCt)]);
              elseif spellSchool == 48 then
                Comix_CallPic(ComixShadowfrostImages[fastrandom(1,ComixShadowfrostImagesCt)]);
              elseif spellSchool == 64 then
                Comix_CallPic(ComixArcaneImages[fastrandom(1,ComixArcaneImagesCt)]);
              elseif spellSchool == 72 then
                Comix_CallPic(ComixSpellstormImages[fastrandom(1,ComixSpellstormImagesCt)]);
              elseif spellSchool == 1 then
                Comix_CallPic(ComixImages[fastrandom(1,ComixImagesCt)]);
              end

            end
          else
            ComixCritCount = 0
          end


        end

        if subEvent == "SWING_DAMAGE" then
          damageAmount = select(12, ...) -- update damage and overkill for swing
          overkillAmount = select(13, ...)

          if Comix_OverkillEnabled == true and damageAmount ~= nil then
            if (damageAmount - overkillAmount) == 1 then
              --do nothing on training dummy
            else
              if overkillAmount / (damageAmount - overkillAmount) > Comix_Overkill / 100 then
                Comix_CallPic(ComixOverkillImages[fastrandom(1, ComixOverkillImagesCt)]);
                --DEFAULT_CHAT_FRAME:AddMessage("overkill")
              end
            end
          end

          if critical == true then

            if Comix_CritGapEnabled == true then

              if damageAmount == nil or damageAmount < Comix_CritGap then
                return --nothin to see here
              end

            end


            if fastrandom(1,100) <= Comix_CritPercent then
              if Comix_ShakeEnabled then
                Comix_ShakeScreen()
              end
              ComixCritCount = ComixCritCount + 1

              if ComixCritCount >= ComixMaxCrits then
                if Comix_SpecialsEnabled then
                  Comix_DongSound(ComixSpecialSounds,4)
                end
                Comix_Pic(Comix_x_coord+fastrandom(-15,15),Comix_y_coord+fastrandom(-20,20),ComixSpecialImages[3])
                ComixCritCount = 0
              end

              if Comix_CritSoundsEnabled then
                Comix_DongSound(ComixSounds)
              end
              if Comix_CritFlashEnabled then
                Comix_ScreenFlash(1, 0, 0, 2);
                --UIFrameFlash( Comix_FrameFlash3, 0.5, 0.5, 2, false, 1, 0);
              end

              Comix_CallPic(ComixImages[fastrandom(1,ComixImagesCt)])
            end
          else
            ComixCritCount = 0
          end
        end
      end

    end




    if event == "READY_CHECK" then

      if Comix_ReadySoundEnabled then
        Comix_DongSound(ComixReadySounds, fastrandom(1, ComixReadySoundsCt));
      end
    end

    if event == "UNIT_HEALTH" then
      -- finish him --
      if Comix_FinishhimEnabled then
        if Comix_FinishTarget then
          if UnitHealth("target") > 0 and (not UnitIsFriend("player", "target")) then
            local TargetHealth = (UnitHealth("target") / UnitHealthMax("target")) * 100
            if TargetHealth < Comix_FinishHimGap then
              Comix_DongSound(ComixSpecialSounds,12)
              Comix_FinishTarget = false
              Comix_OneHit = true;
            end
          end
        end
      end
    end


    if event == "PLAYER_DEAD" then
      --DEFAULT_CHAT_FRAME:AddMessage("dead",1,0,0)
      Comix_unghosted = false;
      Comix_dead = true
      -- Oh poor guy ... you died ... noob :P --
      if Comix_DeathSoundEnabled then
        --if UnitIsDead("player") and strfind(arg1, getglobal("COMIX_YOUUP")) then
        Comix_CallPic(ComixDeathImages[fastrandom(1, ComixDeathImagesCt)]);
        Comix_DongSound(ComixDeathSounds,fastrandom(1,ComixDeathSoundsCt))
        ComixKillCount = 0;
        --end
      end

    end


    --res sound--
    if event == "RESURRECT_REQUEST" then
      --DEFAULT_CHAT_FRAME:AddMessage("res",1,0,0)
      Comix_unghosted = false;
      Comix_dontfireonalive = true;
      if Comix_ResSoundEnabled then
        Comix_DongSound(ComixResSounds, fastrandom(1, ComixResSoundsCt));
      end
    end

    -- zone change sounds --
    if event == "ZONE_CHANGED_NEW_AREA" then
      local ininstance, instancetype = IsInInstance();


      if ininstance then
        if instancetype == "party" or instancetype == "raid" then
          if Comix_SpecialsEnabled then
            DEFAULT_CHAT_FRAME:AddMessage("[Dr. Evil] yells: Ladies and Gentlemen, Welcome to my Underground Lair!",1,0,0)
            Comix_DongSound(ComixSpecialSounds, 16); -- if specials are on we want a different sound when entering an instance, whether zone sounds are on or not --
          else
            if Comix_ZoneEnabled then
              Comix_DongSound(ComixZoneSounds,fastrandom(1,ComixZoneSoundsCt))
            end
          end
        else
          if Comix_ZoneEnabled then
            Comix_DongSound(ComixZoneSounds,fastrandom(1,ComixZoneSoundsCt))
          end
        end
      else
        if Comix_ZoneEnabled then
          Comix_DongSound(ComixZoneSounds,fastrandom(1,ComixZoneSoundsCt))
        end
      end


    end





    if event == "CHAT_MSG_EMOTE" then

      if Comix_SpecialsEnabled then
	    local arg1 = select(1, ...)
        if arg1 ~= nil then
          if strfind(arg1, COMIX_BADJOKE) then
            Comix_DongSound(ComixSpecialSounds, 17);
          end
          if strfind(arg1, COMIX_DRAMAEMOTE) then
            Comix_DongSound(ComixSpecialSounds, 19);
          end
        end
      end
    end

    -- These ability triggers seem bugged. Need more testing, but doesn't look like the event throws any arg at all
    -- Might be misunderstanding the trigger, but doesn't seem right at least
    -- Ability Sounds Checks - well besides cannibalize and sprint/dash --
    if event == "UNIT_SPELLCAST_SENT" then
	  local spellID = select(4, ...)
	  local spellName = GetSpellInfo(spellID)
      --DEFAULT_CHAT_FRAME:AddMessage("Debug unit_spellcast_sent trigger - Arg2 = "..arg2,1,0,0)
      if Comix_DemoShoutEnabled then
        if spellName == COMIX_DS or spellName == COMIX_DR then
          Comix_Pic(0, 0,ComixSpecialImages[2])
        end
      end
      if Comix_AbilitySoundsEnabled then
        if spellName == COMIX_ICEBLOCK then
          Comix_DongSound(ComixAbilitySounds, 2);
        elseif spellName == COMIX_CANNIBALIZE then
          Comix_DongSound(ComixAbilitySounds, 1);
        elseif spellName == COMIX_SPRINT or spellName == COMIX_DASH or spellName == COMIX_TIGER_DASH or spellName == COMIX_ASPECT or spellName == COMIX_STAMPEDING_ROAR then
          Comix_DongSound(ComixSpecialSounds,11)
        elseif spellName == COMIX_DS or spellName == COMIX_DR then
          if Comix_DemoShoutEnabled then
            if Comix_DSSounds then
              Comix_DongSound(ComixSpecialSounds,fastrandom(2,3))
            end
          end
        end
      end
    end



    -- Special Target Sounds --
    if event == "PLAYER_TARGET_CHANGED" then
      Comix_FinishTarget = true;

      if UnitName("target") == nil then
        return
      end

      if UnitName("target") == _G["COMIX_BIGGLESWORTH"] then
        Comix_DongSound(ComixSpecialSounds,5)
        DEFAULT_CHAT_FRAME:AddMessage("[Dr. Evil] yells: That makes me angry and when Dr. Evil gets angry Mr. Bigglesworth gets upset and when Mr. Bigglesworth gets upset...... PPL DIE!!!!!!!!11111oneoneoneoneeleveneleven",1,0,0)
        DEFAULT_CHAT_FRAME:AddMessage("[Venomia] yells: I COMMAND YOU!!! LEAVE THE CAT ALIVE OR YOU GET -50DKP!!!! (rly)",1,0,0)

      elseif UnitName("target") == _G["COMIX_REPAIRBOT"] or UnitName("target") == _G["COMIX_REPAIRBOT2"] then
        Comix_DongSound(ComixSpecialSounds,7)
        DEFAULT_CHAT_FRAME:AddMessage("["..UnitName("target").."]".." says: All your base, r belong to us")

      elseif UnitName("target") == _G["COMIX_MUFFIN"] then
        Comix_DongSound(ComixSpecialSounds, 10)
        DEFAULT_CHAT_FRAME:AddMessage("Do you know the Muffin Man???", 0,1,0)

      end

    end



    -- Stealthed and Moving Sounds --
    if event == "UPDATE_STEALTH" then
		if (IsStealthed()) then
			Comix_isStealthed = true;
		else
			Comix_isStealthed = false;
			StopStealthSound();
		end
	end



    -- Hug Coounter / Objections .. FU String Manipulation!!! --
    if event == "CHAT_MSG_TEXT_EMOTE" then
	  local arg1, arg2 = select(1, ...)

      if arg1 ~= nil then
		-- Objections
        if strfind(arg1, _G["COMIX_OBJECT"]) or strfind(arg1, _G["COMIX_OBJECTS"]) or strfind(arg1, _G["COMIX_OBJECTTO"]) or strfind(arg1, _G["COMIX_OBJECTSTO"]) then
          --			DEFAULT_CHAT_FRAME:AddMessage("OBJECTION from "..arg2.." "..UnitSex(arg2), 0,1,0)

          if UnitInParty(arg2) or UnitInRaid(arg2) then
            if Comix_ObjectionImagesEnabled then
              Comix_CallPic("portrait", arg2)
              Comix_CallPic(ComixSpecialImages[5])
            end

            if Comix_ObjectionSoundsEnabled then
              if UnitSex(arg2) == 3 then
                Comix_DongSound(ComixObjectionSounds, fastrandom(3, 4))
              else
                Comix_DongSound(ComixObjectionSounds, fastrandom(1, 2))
              end
            end

          else
            if Comix_PublicObjections then
              if Comix_ObjectionImagesEnabled then
                Comix_CallPic(ComixSpecialImages[5])
              end

              if Comix_ObjectionSoundsEnabled then
                Comix_DongSound(ComixObjectionSounds, fastrandom(1, 4))
              end

            end

          end
        end

		-- Hug Coounter
        if strfind(arg1, _G["COMIX_HUG"]) or strfind(arg1, _G["COMIX_HUGS"]) then
          local HuggerNotFound = true
          local HuggedNotFound = true
          local comix_the_hugger = nil
          local comix_the_hugged_one = nil
		  local guid = select(12, ...)
		  local playerName, playerRealm = select(6, GetPlayerInfoByGUID(guid))
		  local playerNameWithRealm = playerName.."-"..playerRealm
		  local comix_youup_trimmed = _G["COMIX_YOUUP"]:gsub("%s+", "")
		  local comix_youlow_trimmed = _G["COMIX_YOULOW"]:gsub("%s+", "")
          local huggerInTextStart, huggerInTextEnd = strfind(arg1, "[^ .,!?:;]+")
		  local gappie = nil

		  if huggerInTextStart then
		    -- get hugger
		    comix_the_hugger = strsub(arg1, huggerInTextStart, huggerInTextEnd)
			
			if strfind(comix_the_hugger, comix_youup_trimmed) then
              comix_the_hugger = UnitName("player")
            end

            -- get the hugged one
			if strfind(arg1, _G["COMIX_HUGS"]) then
              gappie = tonumber(_G["COMIX_HUGSGAP"])
            elseif strfind(arg1, _G["COMIX_HUG"]) then
              gappie = tonumber(_G["COMIX_HUGGAP"])
            end

		    if gappie then
		      gappie = gappie + huggerInTextEnd - huggerInTextStart + 1
              comix_the_hugged_one = strsub(arg1, strfind(arg1,"[^ .,!?:;]+",gappie))

			  if strfind(comix_the_hugged_one, comix_youlow_trimmed) then
                comix_the_hugged_one = UnitName("player")
              end
		    end
		  end

		  -- check if hugger / the hugged one already exists in list
          for i, line in ipairs(Comix_HugName) do
            if Comix_HugName[i] == comix_the_hugger then
              if not strfind(arg1, _G["COMIX_NEED"]) then
                Comix_Hugs[i] = Comix_Hugs[i]+1
                HuggerNotFound = false
              end
            end

            if Comix_HugName[i] == comix_the_hugged_one then
              Comix_Hugged[i] = Comix_Hugged[i]+1
              HuggedNotFound = false
            end
          end

          -- add hugger / the hugged one in list if not existing
		  if HuggedNotFound then
            if not strfind(arg1, _G["COMIX_NEED"]) then
              Comix_HugName[getn(Comix_HugName)+1] = comix_the_hugged_one
              Comix_Hugged[getn(Comix_HugName)] = 1
              Comix_Hugs[getn(Comix_HugName)] = 0
              Comix_HuggedNotFound = false;
            end
          end

          if HuggerNotFound then
            if not strfind(arg1, _G["COMIX_NEED"]) then
              Comix_HugName[getn(Comix_HugName)+1] = comix_the_hugger
              Comix_Hugs[getn(Comix_HugName)] = 1
              Comix_Hugged[getn(Comix_HugName)] = 0
              Comix_HuggedNotFound = false;
            end
          end

          -- sort list by most hugged players
		  for i, line in ipairs(Comix_HugName) do
            for j, line in ipairs(Comix_HugName) do
              if Comix_Hugged[i] > Comix_Hugged[j] then
                local Comix_TempHugged = Comix_Hugged[j]
                local Comix_TempHugs = Comix_Hugs[j]
                local Comix_TempHugName = Comix_HugName[j]
                Comix_Hugged[j] = Comix_Hugged[i]
                Comix_Hugs[j] = Comix_Hugs[i]
                Comix_HugName[j] = Comix_HugName[i]
                Comix_Hugged[i] = Comix_TempHugged
                Comix_Hugs[i] = Comix_TempHugs
                Comix_HugName[i] = Comix_TempHugName
              end
            end
          end
        end
      end
    end




  end
end

function Comix_ShakeScreen()
  if Comix_AddOnEnabled then
    if Comix_ShakeEnabled then
      if not Comix_IsShaking then
        Comix_OldWorldFramePoints = {};
        for i = 1, WorldFrame:GetNumPoints() do
          local point, frame, relPoint, xOffset, yOffset = WorldFrame:GetPoint(i);
          --DEFAULT_CHAT_FRAME:AddMessage("p- "..point..",r- "..relPoint..",xO- "..xOffset..",yO- "..yOffset)
          --need to make sure the offset is the same as the default one
          --DEFAULT_CHAT_FRAME:AddMessage(tostring(Comix_DefaultWorldFramePoints[i]["xOffset"]))
          if xOffset ~= Comix_DefaultWorldFramePoints[i]["xOffset"] then
            --DEFAULT_CHAT_FRAME:AddMessage("X OFFSET "..xOffset.." WRONG using default "..Comix_DefaultWorldFramePoints[i]["xOffset"])
            xOffset = Comix_DefaultWorldFramePoints[i]["xOffset"]

          end

          if yOffset ~= Comix_DefaultWorldFramePoints[i]["yOffset"] then
            --	DEFAULT_CHAT_FRAME:AddMessage("Y OFFSET "..yOffset.." WRONG using default "..Comix_DefaultWorldFramePoints[i]["yOffset"])
            yOffset = Comix_DefaultWorldFramePoints[i]["yOffset"]
          end


          Comix_OldWorldFramePoints[i] = {
            ["point"] = point,
            ["frame"] = frame,
            ["relPoint"] = relPoint,
            ["xOffset"] = xOffset,
            ["yOffset"] = yOffset,
          }
        end
        Comix_IsShaking = Comix_ShakeDuration;
      end
    end
  end
end

Comix_UpdateInterval = .008
Comix_TimeSinceLastUpdate = 0
function Comix_OnUpdate(self, elapsed)
  if elapsed == nil then
    elapsed = 0
  end
  -- DEFAULT_CHAT_FRAME:AddMessage("ding "..elapsed);

  Comix_TimeSinceLastUpdate = Comix_TimeSinceLastUpdate + elapsed;

  while (Comix_TimeSinceLastUpdate > Comix_UpdateInterval) do

    -- ScreenShake
    --			if type(Comix_IsShaking) == "number" then
    --			Comix_IsShaking = Comix_IsShaking - elapsed;
    --			if Comix_IsShaking <= 0 then
    --				WorldFrame:ClearAllPoints();
    --				for index, value in pairs(Comix_OldWorldFramePoints) do
    --					WorldFrame:SetPoint(value.point, value.xOffset, value.yOffset);
    --				end
    --				Comix_IsShaking = false;
    --			else
    --				WorldFrame:ClearAllPoints();
    --				local moveBy;
    --				moveBy = fastrandom(-100, 100)/(101 - Comix_ShakeIntensity - (Comix_ShakeOffset - 1));
    --				for index, value in pairs(Comix_OldWorldFramePoints) do
    --					WorldFrame:SetPoint(value.point, value.xOffset + moveBy, value.yOffset + moveBy);
    --				end
    --			end
    --		end

    -- The Picture Animation
	local velocityScaleUp = 12.5;
	local holdTime = 0.75;
	local velocityScaleDown = velocityScaleUp * 5;
	
    for i = 1,5 do
      if Comix_Frames[i] ~= nil then
        if Comix_Frames[i]:IsVisible() then
          if Comix_FramesStatus[i] == 0 then
            Comix_FramesScale[i] = Comix_FramesScale[i]*(1+velocityScaleUp*Comix_UpdateInterval*ComixAniSpeed);
            if Comix_FramesScale[i] >= Comix_Max_Scale then
              Comix_FramesScale[i] = Comix_Max_Scale
              Comix_FramesStatus[i] = 1
            end
            Comix_Frames[i]:SetScale(Comix_FramesScale[i])
          elseif Comix_FramesStatus[i] == 1 then
            Comix_FramesScale[i] = Comix_Max_Scale--Comix_FramesScale[i]*0.8
            Comix_Frames[i]:SetScale(Comix_FramesScale[i])
            if Comix_FramesScale[i] >= Comix_Max_Scale*0.4 then
              Comix_FramesStatus[i] = 2
            end
          elseif Comix_FramesStatus[i] == 2 then
            Comix_FramesVisibleTime[i] = Comix_FramesVisibleTime[i] + Comix_UpdateInterval
            if Comix_FramesVisibleTime[i] >= holdTime/(ComixAniSpeed/2) then
              Comix_FramesStatus[i] = 3
            end
          elseif Comix_FramesStatus[i] == 3 then
            Comix_FramesScale[i] = Comix_FramesScale[i]*(1-velocityScaleUp*Comix_UpdateInterval*ComixAniSpeed)
            Comix_Frames[i]:SetScale(Comix_FramesScale[i])
            if Comix_FramesScale[i] <= 0.2 then
              Comix_Frames[i]:Hide()
              Comix_FramesStatus[i] = 0
              Comix_FramesScale[i] = 0.2
              Comix_FramesVisibleTime[i] = 0
            end
          end
        end
      end
    end
	
	-- Stealthed and Moving Sounds
	if (Comix_isStealthed) then
		local currentUnitSpeed = GetUnitSpeed("player");
		
		if (currentUnitSpeed > 0) then
			PlayStealthSound();
		else
			StopStealthSound();
		end
	end
	
    Comix_TimeSinceLastUpdate = Comix_TimeSinceLastUpdate-Comix_UpdateInterval;
  end
end

function Comix_Command(Nerd)

  Nerd = strlower(Nerd)

  if (Nerd == "create") then
    DEFAULT_CHAT_FRAME:AddMessage("Me Creates: Hello World")
    Comix_DongSound(ComixSpecialSounds,15)

    --elseif(Nerd == "deathtest") then
    --Comix_CallPic(ComixDeathImages[fastrandom(1, ComixDeathImagesCt)]);

    -- elseif(Nerd == "test1") then
    -- Comix_ScreenFlash(1, 0, 0, 1);


    -- elseif(Nerd == "test2") then
    -- Comix_ScreenFlash(1, 0, 1, 1);


    -- elseif(Nerd == "test3") then
    -- Comix_ScreenFlash(1, 0, 0, 2);


    -- elseif(Nerd == "test4") then
    -- Comix_ScreenFlash(0, 1, 1, 2);
  elseif (Nerd == "help") then
    DEFAULT_CHAT_FRAME:AddMessage("------------Comix Help-------------")
    DEFAULT_CHAT_FRAME:AddMessage("Fail/Awesome - type /fail or /awesome to use that feature")
    DEFAULT_CHAT_FRAME:AddMessage("the link will be placec where there is a ~~ in the string")
    DEFAULT_CHAT_FRAME:AddMessage("make sure you put where you want it sent too")
    DEFAULT_CHAT_FRAME:AddMessage("party - send to party, raid - send to raid, player name - send to player")
    DEFAULT_CHAT_FRAME:AddMessage("etc, other options are guild, yell, say, channel numbers also work")
    DEFAULT_CHAT_FRAME:AddMessage("Example - /fail raid wow this raid is ~~")
    DEFAULT_CHAT_FRAME:AddMessage("this will send - wow this raid is [Supermassive Fail] - to your raid group")
    DEFAULT_CHAT_FRAME:AddMessage("\nDrama - /drama will fire the drama detector")
    DEFAULT_CHAT_FRAME:AddMessage("Bad jokes - /badjoke will use the bad joke detector, can be aimed at your target")
    DEFAULT_CHAT_FRAME:AddMessage("\nEverthing else should be explained in the tooltips, im too lazy to type any more :P")
    DEFAULT_CHAT_FRAME:AddMessage("About - /comix about will give version and author name")

  elseif (Nerd == "hide") then
    Comix_Framehide();

  elseif (Nerd == "pic") then
    Comix_CallPic(ComixImages[fastrandom(1,ComixImagesCt)]);

  elseif (Nerd == "specialpic") then
    Comix_CallPic(ComixSpecialImages[fastrandom(1,ComixSpecialCt)]);

  elseif (Nerd == "clearhug") then
    for i, line in ipairs(Comix_HugName) do
      Comix_HugName[i] = nil ;
      Comix_Hugged[i] = nil;
      Comix_Hugs[i] = nil;
    end
    Comix_HugName[1] = UnitName("player")
    Comix_Hugs[1] = 0
    Comix_Hugged[1] = 0

  elseif (Nerd == "showhug") then
    for i = 1,5 do
      if Comix_HugName[i] ~= nil then
        DEFAULT_CHAT_FRAME:AddMessage("[Hug Report]: "..Comix_HugName[i].." has been hugged " ..Comix_Hugged[i].." times and Hugged "..Comix_Hugs[i].." times",0,0,1)
      end
    end

  elseif (Nerd == "reporthug") then
    for i = 1,5 do
      if Comix_HugName[i] ~= nil then
        SendChatMessage("[Hug Report]: "..Comix_HugName[i].." has been hugged " ..Comix_Hugged[i].." times and Hugged "..Comix_Hugs[i].." times", "SAY")
      end
    end

  elseif (Nerd == "clearjump") then
    Comix_JumpCount = 0;
    DEFAULT_CHAT_FRAME:AddMessage("Jump Counter Reset",0,0,1)

  elseif (Nerd == "showjump") then
    DEFAULT_CHAT_FRAME:AddMessage("[Jump Report]: "..UnitName("player").." has jumped " ..Comix_JumpCount.." times",0,0.5,1)


  elseif (Nerd == "reportjump") then
    SendChatMessage("[Jump Report]: "..UnitName("player").." has jumped " ..Comix_JumpCount.." times", "SAY")

  elseif (Nerd == "about") then
    DEFAULT_CHAT_FRAME:AddMessage("[Comix]: Author: Darool @ Quel'Thalas & Nixxen / Version: "..ComixVersion,0,0.5,1)
  
  else
    comix_options_frame:Show()
  end
end

function Comix_BadJoke()
  if UnitIsPlayer("target") and not UnitIsUnit("target", "player") then
    SendChatMessage(COMIX_JOKEEMOTE2A..UnitName("target")..COMIX_JOKEEMOTE2B, "EMOTE");
  else
    SendChatMessage(COMIX_JOKEEMOTE1, "EMOTE");
  end
end

function Comix_Drama()
  SendChatMessage(COMIX_DRAMAEMOTE, "EMOTE");
end

function Comix_ReloadUI()
  ReloadUI()
end

local function msgSender(message,link)
  local command, txt = message:match("^(%S*)%s*(.-)$")
  local fl = GetDefaultLanguage("PLAYER")
  txt = gsub(txt,"~~",link)
  if command == "say" or command == "emote" or command == "yell" or command == "instance" or command == "party" or command == "guild" or command == "officer" or command == "raid" or command == "rw" or command == "bg" or command == "afk" or command == "dnd" then
    if command == "instance" then
      command = "instance_chat"
    end
    if command == "bg" then
      command = "battleground"
    end
    if command == "rw" then
      command = "raid_warning"
    end
    SendChatMessage(txt,command)
  elseif tonumber(command) ~= nil and tonumber(command) > 0 and tonumber(command) < 100 then
    SendChatMessage(txt,"channel",fl,command)
  else
    SendChatMessage(txt,"whisper",fl,command)
  end
end

function Comix_Fail(msg)
  if isWoWFlavor.ClassicEra then
	DEFAULT_CHAT_FRAME:AddMessage("[Comix]: /fail isn't available in classic era",0,0.5,1)
	return;
  end
  -- local link = GetSpellLink(65311) -- Even though GetSpellLink() is available in WotLKC, it doesn't return a valid link for spell id 65311.
  local name, _, icon, castTime, minRange, maxRange, spellID = GetSpellInfo(65311);
  local link = format("|c%s|Hspell:%d:0|h[%s]|h|r", "FF71D5FF", spellID, name);
  msgSender(msg,link)
end

function Comix_Awesome(msg)
  if isWoWFlavor.ClassicEra then
	DEFAULT_CHAT_FRAME:AddMessage("[Comix]: /awesome isn't available in classic era",0,0.5,1)
	return;
  end
  -- local link = GetSpellLink(58783) -- Even though GetSpellLink() is available in WotLKC, it doesn't return a valid link for spell id 58783.
  local name, rank, icon, castTime, minRange, maxRange, spellID = GetSpellInfo(58783);
  local link = format("|c%s|Hspell:%d:0|h[%s]|h|r", "FF71D5FF", spellID, name);
  msgSender(msg, link)
end



function Comix_DongSound(SoundTable,Sound)
  if not Comix_AddOnEnabled then
    return
  end
  if Comix_SoundEnabled then
    if SoundTable == ComixSounds then
      if Comix_BamEnabled then
        return PlaySoundFile("Interface\\AddOns\\Comix\\Sounds\\"..ComixSpecialSounds[13])
      else
        local randsound = fastrandom(1,ComixSoundsCt)
        return PlaySoundFile("Interface\\AddOns\\Comix\\Sounds\\"..SoundTable[randsound]);
      end
    elseif SoundTable == "customcomixsound" then
      return PlaySoundFile(Sound)

    else
      return PlaySoundFile("Interface\\AddOns\\Comix\\Sounds\\"..SoundTable[Sound]);
    end
  end
end



function Comix_StopDongSound(soundHandle)
  if not Comix_AddOnEnabled then
    return
  end
  if Comix_SoundEnabled then
    StopSound(soundHandle);
  end
end



function Comix_Pic(x,y,Pic, name)

  if Comix_ImagesEnabled then
    -- Resetting Frames animation values --
    if Comix_Frames[ComixCurrentFrameCt]:IsVisible() then
      Comix_Frames[ComixCurrentFrameCt]:Hide()
    end
    Comix_FramesStatus[ComixCurrentFrameCt] = 0
    Comix_FramesScale[ComixCurrentFrameCt] = 0.2
    Comix_FramesVisibleTime[ComixCurrentFrameCt] = 0

    -- Setting Texture --
    if Pic == "portrait" then
      SetPortraitTexture(Comix_textures[ComixCurrentFrameCt], name);
    elseif name == "customcomixpic" then
      Comix_textures[ComixCurrentFrameCt]:SetTexture(Pic);
    else
      Comix_textures[ComixCurrentFrameCt]:SetTexture("Interface\\Addons\\Comix\\"..Pic);
    end
  end
  Comix_textures[ComixCurrentFrameCt]:SetAllPoints(Comix_Frames[ComixCurrentFrameCt]);
  Comix_Frames[ComixCurrentFrameCt].texture = Comix_textures[ComixCurrentFrameCt];

  -- Positioning Frame --
  if Pic == "portrait" then
    Comix_Frames[ComixCurrentFrameCt]:SetPoint("Center",-150,-50);
  else
    Comix_Frames[ComixCurrentFrameCt]:SetPoint("Center",x,y);
  end
  Comix_Frames[ComixCurrentFrameCt]:Show();

  -- Increasing Current Frame or resetting it to 1 --
  if ComixCurrentFrameCt == 5 then
    ComixCurrentFrameCt = 1
  else
    ComixCurrentFrameCt = ComixCurrentFrameCt +1
  end
end

function Comix_LoaddaShite()

-- Counting Normal Images --
ComixImagesCt = getn(ComixImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixImagesCt.." piccus",0.3,0.3,0.3)

-- Counting Images in Image-Sets --
ComixFireImagesCt = getn(ComixFireImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixFireImagesCt.." piccus",0.3,0.3,1)

ComixFrostImagesCt = getn(ComixFrostImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixFrostImagesCt.." piccus",0.3,1,1)

ComixFrostfireImagesCt = getn(ComixFrostfireImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixFrostfireImagesCt.." piccus",0.3,1,1)

ComixSpellstormImagesCt = getn(ComixSpellstormImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixSpellstormImagesCt.." piccus",0.3,1,1)

ComixShadowflameImagesCt = getn(ComixShadowflameImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixSpellstormImagesCt.." piccus",0.3,1,1)

ComixShadowfrostImagesCt = getn(ComixShadowfrostImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixSpellstormImagesCt.." piccus",0.3,1,1)

ComixShadowImagesCt = getn(ComixShadowImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixShadowImagesCt.." piccus",0.3,1,0.3)

ComixNatureImagesCt = getn(ComixNatureImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixNatureImagesCt.." piccus",1,1,0.3)

ComixArcaneImagesCt = getn(ComixArcaneImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixArcaneImagesCt.." piccus",1,0.3,0.3)

ComixHolyHealImagesCt = getn(ComixHolyHealImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixHolyHealImagesCt.." piccus",0.5,0.5,0.5)

ComixHolyDmgImagesCt = getn(ComixHolyDmgImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixHolyDmgImagesCt.." piccus",0.5,0.5,0.5)

ComixDeathImagesCt = getn(ComixDeathImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixDeathImagesCt.." piccus",0.5,0.5,0.5)

ComixOverkillImagesCt = getn(ComixOverkillImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixOverkillImagesCt.." piccus",0.5,0.5,0.5)

-- Counting Normal Sounds --
ComixSoundsCt = getn(ComixSounds)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixSoundsCt.." sounds",1,0.3,1)

-- Counting Zone Sounds --
ComixZoneSoundsCt = getn(ComixZoneSounds)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixZoneSoundsCt.." sounds",1,1,1)

-- Counting One hit Sounds --
ComixOneHitSoundsCt = getn(ComixOneHitSounds)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixOneHitSoundsCt.." sounds",1,1,1)

-- Counting Healing Sounds --
ComixHealingSoundsCt = getn(ComixHealingSounds)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixHealingSoundsCt.." sounds",1,1,1)


-- Counting Specials --
ComixSpecialCt = getn(ComixSpecialImages)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixSpecialCt.." specials",1,0.3,0.3)

-- Counting Ability Sounds --
ComixAbilitySoundsCt = getn(ComixAbilitySounds)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixAbilitySoundsCt.." sounds",1,1,1)

-- Counting Death Sounds --
ComixDeathSoundsCt = getn(ComixDeathSounds)
DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixDeathSoundsCt.." sounds",1,1,1)

-- Counting Ready check Sounds --
ComixReadySoundsCt = getn(ComixReadySounds)

-- Counting Res Sounds --
ComixResSoundsCt = getn(ComixResSounds)

DEFAULT_CHAT_FRAME:AddMessage("Me loaded "..ComixReadySoundsCt.." sounds",1,1,1)

DEFAULT_CHAT_FRAME:AddMessage("Open options GUI with /comix or get Slashcommands with /comix help",0.7,0.7,1)

end

function Comix_Framehide()
  for i,line in ipairs(Comix_Frames) do
    Comix_Frames[i]:Hide();
    DEFAULT_CHAT_FRAME:AddMessage("Hiding Comix_Frames["..i.."]")
  end
end



function Comix_CallPic(Image, name)
  if not Comix_AddOnEnabled then
    return
  end

  if Comix_ImagesEnabled then
    -- Creating x,y Coordinates --
    Comix_x_coord = fastrandom(-120,120)
    if Comix_x_coord <= 0 then
      Comix_x_coord = Comix_x_coord -40
    else
      Comix_x_coord= Comix_x_coord +40
    end

    if (abs(Comix_x_coord)<75) then
      local y_buffer = 50
      Comix_y_coord = fastrandom(y_buffer,130)
    else
      Comix_y_coord = fastrandom(0,130)
    end

    -- Finally handing over x,y Coords and the image to show --
    Comix_CurrentImage = Image
    Comix_Pic(Comix_x_coord,Comix_y_coord,Image, name, gen)
  end

end



function Comix_CreateFrames()
  -- Creating 5 Frames, creating 5 Textures and setting FramesScale, FramesVisibleTime & FramesStatus--
  for i = 1,5 do
    -- Create Frame --
    Comix_Frames[i] = CreateFrame("Frame","ComixFrame"..i,UIParent)
    Comix_Frames[i]:SetWidth(128);
    Comix_Frames[i]:SetHeight(128);
    Comix_Frames[i]:Hide()
    -- Create texture for each frame --
    Comix_textures[i] = Comix_Frames[i]:CreateTexture(nil,"BACKGROUND")
    -- Setting FramesScale, FramesVisibleTime & FramesStatus  to 0 --
    Comix_FramesScale[i] = 0.2
    Comix_FramesVisibleTime[i] = 0
    Comix_FramesStatus[i] = 0
  end


  Comix_FrameFlashTexture:SetVertexColor(1,0,0);

end


--Functions for outside mods to access comix functions easier also for ComixPlus support
function Comix_CustomPic(path)
  Comix_CallPic(path, "customcomixpic");
end

function Comix_CustomSound(path)
  Comix_DongSound("customcomixsound", path);
end

function Comix_ScreenFlash(r, g, b, size)

  if size < 1 then
    size = 1
  end

  if size > 2 then
    size = 2
  end

  Comix_FrameFlashTexture:SetTexture("Interface\\Addons\\Comix\\Images\\flash"..size..".tga")

  Comix_FrameFlashTexture:SetVertexColor(r, g, b)


  Comix_UIFrameFlash( Comix_FrameFlash, 0.5, 0.5, 2, false, 1, 0);

end

function Comix_ActivatePlus()
  comixheader:SetText("Comix Options +")
end

-- own UIFrameFlash() implementation, because calling this blizzard function causes taint. error with e.g. ADDON_ACTION_BLOCKED popped up after level up.
local FLASHFRAMES = {};
local frameFlashManager = CreateFrame("FRAME");
local UIFrameFlashTimers = {};
local UIFrameFlashTimerRefCount = {};

-- Function to start a frame flashing
function Comix_UIFrameFlash(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
	if ( frame ) then
		local index = 1;
		-- If frame is already set to flash then return
		while FLASHFRAMES[index] do
			if ( FLASHFRAMES[index] == frame ) then
				return;
			end
			index = index + 1;
		end

		if (syncId) then
			frame.syncId = syncId;
			if (UIFrameFlashTimers[syncId] == nil) then
				UIFrameFlashTimers[syncId] = 0;
				UIFrameFlashTimerRefCount[syncId] = 0;
			end
			UIFrameFlashTimerRefCount[syncId] = UIFrameFlashTimerRefCount[syncId]+1;
		else
			frame.syncId = nil;
		end

		-- Time it takes to fade in a flashing frame
		frame.fadeInTime = fadeInTime;
		-- Time it takes to fade out a flashing frame
		frame.fadeOutTime = fadeOutTime;
		-- How long to keep the frame flashing, -1 means forever
		frame.flashDuration = flashDuration;
		-- Show the flashing frame when the fadeOutTime has passed
		frame.showWhenDone = showWhenDone;
		-- Internal timer
		frame.flashTimer = 0;
		-- How long to hold the faded in state
		frame.flashInHoldTime = flashInHoldTime;
		-- How long to hold the faded out state
		frame.flashOutHoldTime = flashOutHoldTime;

		tinsert(FLASHFRAMES, frame);

		frameFlashManager:SetScript("OnUpdate", Comix_UIFrameFlash_OnUpdate);
	end
end

-- Called every frame to update flashing frames
function Comix_UIFrameFlash_OnUpdate(self, elapsed)
	local frame;
	local index = #FLASHFRAMES;

	-- Update timers for all synced frames
	for syncId, timer in pairs(UIFrameFlashTimers) do
		UIFrameFlashTimers[syncId] = timer + elapsed;
	end

	while FLASHFRAMES[index] do
		frame = FLASHFRAMES[index];
		frame.flashTimer = frame.flashTimer + elapsed;

		if ( (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
			Comix_UIFrameFlashStop(frame);
		else
			local flashTime = frame.flashTimer;
			local alpha;

			if (frame.syncId) then
				flashTime = UIFrameFlashTimers[frame.syncId];
			end

			flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0));
			if (flashTime < frame.fadeInTime) then
				alpha = flashTime/frame.fadeInTime;
			elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)) then
				alpha = 1;
			elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime) then
				alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime);
			else
				alpha = 0;
			end

			frame:SetAlpha(alpha);
			frame:Show();
		end

		-- Loop in reverse so that removing frames is safe
		index = index - 1;
	end

	if ( #FLASHFRAMES == 0 ) then
		self:SetScript("OnUpdate", nil);
	end
end

-- Function to stop flashing
function Comix_UIFrameFlashStop(frame)
	tDeleteItem(FLASHFRAMES, frame);
	frame:SetAlpha(1.0);
	frame.flashTimer = nil;
	if (frame.syncId) then
		UIFrameFlashTimerRefCount[frame.syncId] = UIFrameFlashTimerRefCount[frame.syncId]-1;
		if (UIFrameFlashTimerRefCount[frame.syncId] == 0) then
			UIFrameFlashTimers[frame.syncId] = nil;
			UIFrameFlashTimerRefCount[frame.syncId] = nil;
		end
		frame.syncId = nil;
	end
	if ( frame.showWhenDone ) then
		frame:Show();
	else
		frame:Hide();
	end
end
