2.4.3.8606/FrameXML/BuffFrame.lua
BUFF_FLASH_TIME_ON = 0.75;
BUFF_FLASH_TIME_OFF = 0.75;
BUFF_MIN_ALPHA = 0.3;
BUFF_WARNING_TIME = 31;
BUFF_DURATION_WARNING_TIME = 60;
BUFFS_PER_ROW = 8;
BUFF_MAX_DISPLAY = 32;
BUFF_ACTUAL_DISPLAY = 0;
DEBUFF_MAX_DISPLAY = 16
DEBUFF_ACTUAL_DISPLAY = 0;
BUFF_ROW_SPACING = 0;
 
DebuffTypeColor = { };
DebuffTypeColor["none"]	= { r = 0.80, g = 0, b = 0 };
DebuffTypeColor["Magic"]	= { r = 0.20, g = 0.60, b = 1.00 };
DebuffTypeColor["Curse"]	= { r = 0.60, g = 0.00, b = 1.00 };
DebuffTypeColor["Disease"]	= { r = 0.60, g = 0.40, b = 0 };
DebuffTypeColor["Poison"]	= { r = 0.00, g = 0.60, b = 0 };
 
 
function BuffFrame_OnLoad()
	BuffFrame.BuffFrameUpdateTime = 0;
	BuffFrame.BuffFrameFlashTime = 0;
	BuffFrame.BuffFrameFlashState = 1;
	BuffFrame.BuffAlphaValue = 1;
	this:RegisterEvent("PLAYER_AURAS_CHANGED");
end
 
function BuffFrame_OnEvent(event)
	if ( event == "PLAYER_AURAS_CHANGED" ) then
		BuffFrame_Update();
	end
end
 
function BuffFrame_Update()
	-- Handle Buffs
	BUFF_ACTUAL_DISPLAY = 0;
	for i=1, BUFF_MAX_DISPLAY do
		if ( BuffButton_Update("BuffButton", i, "HELPFUL") ) then
			BUFF_ACTUAL_DISPLAY = BUFF_ACTUAL_DISPLAY + 1;
		end
	end
 
	-- Handle debuffs
	for i=1, DEBUFF_MAX_DISPLAY do
		if ( BuffButton_Update("DebuffButton", i, "HARMFUL") ) then
			DEBUFF_ACTUAL_DISPLAY = DEBUFF_ACTUAL_DISPLAY + 1;
		end
	end
end
 
function BuffButton_Update(buttonName, index, filter)
	-- Valid tokens for "filter" include: HELPFUL, HARMFUL, CANCELABLE, NOT_CANCELABLE
	local icon, color, debuffType, debuffSlot, buffCount, count;
 
	local buffIndex, untilCancelled = GetPlayerBuff(index, filter);
	local buffName = buttonName..index;
	local buff = getglobal(buffName);
	local buffDuration = getglobal(buffName.."Duration");
 
	if ( buffIndex == 0 ) then
		-- No buff so hide it if it exists
		if ( buff ) then
			buff:Hide();
			buffDuration:Hide();
		end
		return nil;
	else
		-- If buff button doesn't exist make it
		if ( not buff ) then
			if ( filter == "HELPFUL" ) then
				buff = CreateFrame("Button", buffName, BuffFrame, "BuffButtonTemplate");
			else
				buff = CreateFrame("Button", buffName, BuffFrame, "BuffButtonHarmful");
			end
 
			buffDuration = getglobal(buffName.."Duration");
		end
		-- Anchor Buff
		BuffButton_UpdateAnchors(buttonName, index, filter);
		-- Setup Buff
		buff:SetID(buffIndex);
		buff.untilCancelled = untilCancelled;
		buff:SetAlpha(1.0);
		buff:Show();
		if ( SHOW_BUFF_DURATIONS == "1" ) then
			buffDuration:Show();
		else
			buffDuration:Hide();
		end
 
		-- Set Texture
		icon = getglobal(buffName.."Icon");
		icon:SetTexture(GetPlayerBuffTexture(buffIndex));
 
		-- Set the number of applications of an aura if its a debuff
		buffCount = getglobal(buffName.."Count");
		count = GetPlayerBuffApplications(buffIndex);
		if ( count > 1 ) then
			buffCount:SetText(count);
			buffCount:Show();
		else
			buffCount:Hide();
		end
 
		-- Set color of debuff border based on dispel class.
		if ( filter == "HARMFUL" ) then
			debuffType = GetPlayerBuffDispelType(buffIndex);
			debuffSlot = getglobal(buffName.."Border");
			if ( debuffType ) then
				color = DebuffTypeColor[debuffType];
			else
				color = DebuffTypeColor["none"];
			end
 
			if ( debuffSlot ) then
				debuffSlot:SetVertexColor(color.r, color.g, color.b);
			end
 
			if ( not debuffType ) then
				debuffType = "none";
			end
		end
 
		-- Refresh tooltip
		if ( GameTooltip:IsOwned(buff) ) then
			GameTooltip:SetPlayerBuff(buffIndex);
		end
	end
	return 1;
end
 
 
 
function BuffFrame_OnUpdate(elapsed)
	if ( BuffFrame.BuffFrameUpdateTime > 0 ) then
		BuffFrame.BuffFrameUpdateTime = BuffFrame.BuffFrameUpdateTime - elapsed;
	else
		BuffFrame.BuffFrameUpdateTime = BuffFrame.BuffFrameUpdateTime + TOOLTIP_UPDATE_TIME;
	end
 
	BuffFrame.BuffFrameFlashTime = BuffFrame.BuffFrameFlashTime - elapsed;
	if ( BuffFrame.BuffFrameFlashTime < 0 ) then
		local overtime = -BuffFrame.BuffFrameFlashTime;
		if ( BuffFrame.BuffFrameFlashState == 0 ) then
			BuffFrame.BuffFrameFlashState = 1;
			BuffFrame.BuffFrameFlashTime = BUFF_FLASH_TIME_ON;
		else
			BuffFrame.BuffFrameFlashState = 0;
			BuffFrame.BuffFrameFlashTime = BUFF_FLASH_TIME_OFF;
		end
		if ( overtime < BuffFrame.BuffFrameFlashTime ) then
			BuffFrame.BuffFrameFlashTime = BuffFrame.BuffFrameFlashTime - overtime;
		end
	end
 
	if ( BuffFrame.BuffFrameFlashState == 1 ) then
		BuffFrame.BuffAlphaValue = (BUFF_FLASH_TIME_ON - BuffFrame.BuffFrameFlashTime) / BUFF_FLASH_TIME_ON;
	else
		BuffFrame.BuffAlphaValue = BuffFrame.BuffFrameFlashTime / BUFF_FLASH_TIME_ON;
	end
	BuffFrame.BuffAlphaValue = (BuffFrame.BuffAlphaValue * (1 - BUFF_MIN_ALPHA)) + BUFF_MIN_ALPHA;
end
 
function BuffButton_OnLoad()
	-- Valid tokens for "buffFilter" include: HELPFUL, HARMFUL, CANCELABLE, NOT_CANCELABLE
	this:RegisterForClicks("RightButtonUp");
end
 
function BuffButton_OnUpdate()
	local buffDuration = getglobal(this:GetName().."Duration");
	if ( this.untilCancelled == 1 ) then
		buffDuration:Hide();
		return;
	end
 
	local buffIndex = this:GetID();
	local timeLeft = GetPlayerBuffTimeLeft(buffIndex);
	if ( timeLeft < BUFF_WARNING_TIME ) then
		this:SetAlpha(BuffFrame.BuffAlphaValue);
	else
		this:SetAlpha(1.0);
	end
 
	-- Update duration
	BuffFrame_UpdateDuration(this, timeLeft);
 
	if ( BuffFrame.BuffFrameUpdateTime > 0 ) then
		return;
	end
	if ( GameTooltip:IsOwned(this) ) then
		GameTooltip:SetPlayerBuff(buffIndex);
	end
end
 
function BuffButton_OnClick()
	CancelPlayerBuff(this:GetID());
end
 
function BuffButtons_UpdatePositions()
	if ( SHOW_BUFF_DURATIONS == "1" ) then
		BUFF_ROW_SPACING = 15;
	else
		BUFF_ROW_SPACING = 5;
	end
	BuffFrame_Update();
end
 
function BuffButton_UpdateAnchors(buttonName, index, filter)
	local rows = ceil(BUFF_ACTUAL_DISPLAY/BUFFS_PER_ROW);
	local buff = getglobal(buttonName..index);
	local buffHeight = TempEnchant1:GetHeight();
 
	if ( filter == "HELPFUL" ) then
		if ( (index > 1) and (mod(index, BUFFS_PER_ROW) == 1) ) then
			-- New row
			if ( index == BUFFS_PER_ROW+1 ) then
				buff:SetPoint("TOP", TempEnchant1, "BOTTOM", 0, -BUFF_ROW_SPACING);
			else
				buff:SetPoint("TOP", getglobal(buttonName..(index-BUFFS_PER_ROW)), "BOTTOM", 0, -BUFF_ROW_SPACING);
			end
		elseif ( index == 1 ) then
			buff:SetPoint("TOPRIGHT", BuffFrame, "TOPRIGHT", 0, 0);
		else
			buff:SetPoint("RIGHT", getglobal(buttonName..(index-1)), "LEFT", -5, 0);
		end
	else
		-- Position debuffs
		if ( (index > 1) and (mod(index, BUFFS_PER_ROW) == 1) ) then
			-- New row
			buff:SetPoint("TOP", getglobal(buttonName..(index-BUFFS_PER_ROW)), "BOTTOM", 0, -BUFF_ROW_SPACING);
		elseif ( index == 1 ) then
			if ( rows < 2 ) then
				buff:SetPoint("TOPRIGHT", TempEnchant1, "BOTTOMRIGHT", 0, -1*((2*BUFF_ROW_SPACING)+buffHeight));
			else
				buff:SetPoint("TOPRIGHT", TempEnchant1, "BOTTOMRIGHT", 0, -rows*(BUFF_ROW_SPACING+buffHeight));
			end
		else
			buff:SetPoint("RIGHT", getglobal(buttonName..(index-1)), "LEFT", -5, 0);
		end
	end
end
 
 
function BuffFrame_Enchant_OnUpdate(elapsed)
	local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo();
 
	-- No enchants, kick out early
	if ( not hasMainHandEnchant and not hasOffHandEnchant ) then
		TempEnchant1:Hide();
		TempEnchant1Duration:Hide();
		TempEnchant2:Hide();
		TempEnchant2Duration:Hide();
		BuffFrame:SetPoint("TOPRIGHT", "TemporaryEnchantFrame", "TOPRIGHT", 0, 0);
		return;
	end
	-- Has enchants
	local enchantButton;
	local textureName;
	local buffAlphaValue;
	local enchantIndex = 0;
	if ( hasOffHandEnchant ) then
		enchantIndex = enchantIndex + 1;
		textureName = GetInventoryItemTexture("player", 17);
		TempEnchant1:SetID(17);
		TempEnchant1Icon:SetTexture(textureName);
		TempEnchant1:Show();
 
		-- Show buff durations if necessary
		if ( offHandExpiration ) then
			offHandExpiration = offHandExpiration/1000;
		end
		BuffFrame_UpdateDuration(TempEnchant1, offHandExpiration);
 
		-- Handle flashing
		if ( offHandExpiration and offHandExpiration < BUFF_WARNING_TIME ) then
			TempEnchant1:SetAlpha(BuffFrame.BuffAlphaValue);
		else
			TempEnchant1:SetAlpha(1.0);
		end
 
	end
	if ( hasMainHandEnchant ) then
		enchantIndex = enchantIndex + 1;
		enchantButton = getglobal("TempEnchant"..enchantIndex);
		textureName = GetInventoryItemTexture("player", 16);
		enchantButton:SetID(16);
		getglobal(enchantButton:GetName().."Icon"):SetTexture(textureName);
		enchantButton:Show();
 
		-- Show buff durations if necessary
		if ( mainHandExpiration ) then
			mainHandExpiration = mainHandExpiration/1000;
		end
 
		BuffFrame_UpdateDuration(enchantButton, mainHandExpiration);
 
		-- Handle flashing
		if ( mainHandExpiration and mainHandExpiration < BUFF_WARNING_TIME ) then
			enchantButton:SetAlpha(BuffFrame.BuffAlphaValue);
		else
			enchantButton:SetAlpha(1.0);
		end
	end
	--Hide unused enchants
	for i=enchantIndex+1, 2 do
		getglobal("TempEnchant"..i):Hide();
		getglobal("TempEnchant"..i.."Duration"):Hide();
	end
 
	-- Position buff frame
	TemporaryEnchantFrame:SetWidth(enchantIndex * 32);
	BuffFrame:SetPoint("TOPRIGHT", "TemporaryEnchantFrame", "TOPLEFT", -5, 0);
end
 
function BuffFrame_EnchantButton_OnLoad()
	this:RegisterForClicks("RightButtonUp");
end
 
function BuffFrame_EnchantButton_OnUpdate()
	-- Update duration
	if ( GameTooltip:IsOwned(this) ) then
		BuffFrame_EnchantButton_OnEnter();
	end
end
 
function BuffFrame_EnchantButton_OnEnter()
	GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT");
	GameTooltip:SetInventoryItem("player", this:GetID());
end
 
function BuffFrame_EnchantButton_OnClick()
	if ( this:GetID() == 16 ) then
		CancelItemTempEnchantment(1);
	elseif ( this:GetID() == 17 ) then
		CancelItemTempEnchantment(2);
	end;
end
 
function BuffFrame_UpdateDuration(buffButton, timeLeft)
	local duration = getglobal(buffButton:GetName().."Duration");
	if ( SHOW_BUFF_DURATIONS == "1" and timeLeft ) then
		duration:SetFormattedText(SecondsToTimeAbbrev(timeLeft));
		if ( timeLeft < BUFF_DURATION_WARNING_TIME ) then
			duration:SetVertexColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
		else
			duration:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
		end
		duration:Show();
	else
		duration:Hide();
	end
end
 
function RefreshBuffs(button, showBuffs, unit)
	local buttonName = button:GetName();
	local name, rank, icon, debuffType, debuffStack, debuffColor, unitStatus, statusColor;
	local debuffTotal = 0;
	button.hasDispellable = nil;
 
	for i=1, MAX_PARTY_DEBUFFS do
 
		local debuffBorder = getglobal(buttonName.."Debuff"..i.."Border");
		local debuffIcon = getglobal(buttonName.."Debuff"..i.."Icon");
 
		if ( unit == "party"..i ) then
			unitStatus = getglobal(buttonName.."Status");
		end
		-- Show all buffs and debuffs
		if ( showBuffs == 1 ) then
			name, rank, icon = UnitBuff(unit, i, SHOW_CASTABLE_BUFFS);
			debuffBorder:Show();
		-- Show all debuffs
		elseif ( showBuffs == 0 ) then
			name, rank, icon, debuffStack, debuffType = UnitDebuff(unit, i);
			debuffBorder:Show();
		-- Show dispellable debuffs (value nil or anything ~= 0 or 1)
		else
			name, rank, icon, debuffStack, debuffType = UnitDebuff(unit, i, SHOW_DISPELLABLE_DEBUFFS);
			debuffBorder:Show();
		end
 
		if ( icon ) then
			debuffIcon:SetTexture(icon);
			if ( debuffType ) then
				debuffColor = DebuffTypeColor[debuffType];
				statusColor = DebuffTypeColor[debuffType];
				button.hasDispellable = 1;
				debuffTotal = debuffTotal + 1;
			else
				debuffColor = DebuffTypeColor["none"];
			end
			debuffBorder:SetVertexColor(debuffColor.r, debuffColor.g, debuffColor.b);
			getglobal(buttonName.."Debuff"..i):Show();
		else
			getglobal(buttonName.."Debuff"..i):Hide();
		end
	end
	-- Reset unitStatus overlay graphic timer
	if ( button.numDebuffs ) then
		if ( debuffTotal >= button.numDebuffs ) then
			button.debuffCountdown = 30;
		end
	end
	if ( unitStatus and statusColor ) then
		unitStatus:SetVertexColor(statusColor.r, statusColor.g, statusColor.b);
	end
end