Quantcast
local SLE, T, E, L, V, P, G = unpack(select(2, ...))
if SLE._Compatibility["DejaCharacterStats"] then return end
--Credits: Dejablue

--GLOBALS: PAPERDOLL_STATCATEGORIES, PAPERDOLL_STATINFO, PaperDollFrame_SetAttackSpeed, PaperDollFrame_SetMovementSpeed, PaperDollFrame_SetLifesteal
--GLOBALS: PaperDollFrame_SetVersatility, PaperDollFrame_SetMastery, PaperDollFrame_SetAvoidance, PaperDollFrame_SetDodge, PaperDollFrame_SetParry
--GLOBALS: PaperDollFrame_SetBlock, PaperDollFrame_SetCritChance, PaperDollFrame_SetHaste
local _G = _G
local math_min, math_max= math.min, math.max

local GetCombatRating, GetCombatRatingBonus = GetCombatRating, GetCombatRatingBonus
local GetMeleeHaste, UnitAttackSpeed = GetMeleeHaste, UnitAttackSpeed
local GetVersatilityBonus = GetVersatilityBonus
local GetMasteryEffect, Mastery_OnEnter = GetMasteryEffect, Mastery_OnEnter
local GetLifesteal = GetLifesteal
local GetAvoidance = GetAvoidance
local GetDodgeChance, GetParryChance, GetBlockChance, GetShieldBlock = GetDodgeChance, GetParryChance, GetBlockChance, GetShieldBlock
local GetSpellCritChance, GetRangedCritChance, GetCritChance, GetCritChanceProvidesParryEffect = GetSpellCritChance, GetRangedCritChance, GetCritChance, GetCritChanceProvidesParryEffect
local GetCritChanceProvidesParryEffect = GetCritChanceProvidesParryEffect
local GetCombatRatingBonusForCombatRatingValue = GetCombatRatingBonusForCombatRatingValue
local GetHaste = GetHaste
local BreakUpLargeNumbers = BreakUpLargeNumbers
local PaperDollFrame_SetLabelAndText = PaperDollFrame_SetLabelAndText
local UnitSex = UnitSex
local PaperDollFrame_UpdateStats = PaperDollFrame_UpdateStats
local PaperDollFrame_SetItemLevel = PaperDollFrame_SetItemLevel
local GetItemLevelColor = GetItemLevelColor
local MovementSpeed_OnEnter, MovementSpeed_OnUpdate = MovementSpeed_OnEnter, MovementSpeed_OnUpdate

local LE_UNIT_STAT_STRENGTH, LE_UNIT_STAT_AGILITY, LE_UNIT_STAT_INTELLECT = LE_UNIT_STAT_STRENGTH, LE_UNIT_STAT_AGILITY, LE_UNIT_STAT_INTELLECT
local STAT_ATTACK_SPEED_BASE_TOOLTIP = STAT_ATTACK_SPEED_BASE_TOOLTIP
local FONT_COLOR_CODE_CLOSE, HIGHLIGHT_FONT_COLOR_CODE = FONT_COLOR_CODE_CLOSE, HIGHLIGHT_FONT_COLOR_CODE
local ATTACK_SPEED = ATTACK_SPEED
local PAPERDOLLFRAME_TOOLTIP_FORMAT = PAPERDOLLFRAME_TOOLTIP_FORMAT
local WEAPON_SPEED = WEAPON_SPEED
local STAT_LIFESTEAL, CR_LIFESTEAL_TOOLTIP, CR_LIFESTEAL = STAT_LIFESTEAL, CR_LIFESTEAL_TOOLTIP, CR_LIFESTEAL
local STAT_CRITICAL_STRIKE, CR_CRIT_SPELL, CR_CRIT_RANGED, CR_CRIT_MELEE, CR_CRIT_TOOLTIP = STAT_CRITICAL_STRIKE, CR_CRIT_SPELL, CR_CRIT_RANGED, CR_CRIT_MELEE, CR_CRIT_TOOLTIP
local CR_CRIT_PARRY_RATING_TOOLTIP, CR_PARRY = CR_CRIT_PARRY_RATING_TOOLTIP, CR_PARRY
local CR_HASTE_MELEE, STAT_HASTE, STAT_HASTE_TOOLTIP, STAT_HASTE_BASE_TOOLTIP = CR_HASTE_MELEE, STAT_HASTE, STAT_HASTE_TOOLTIP, STAT_HASTE_BASE_TOOLTIP
local STAT_BLOCK, BLOCK_CHANCE, CR_BLOCK_TOOLTIP = STAT_BLOCK, BLOCK_CHANCE, CR_BLOCK_TOOLTIP
local STAT_PARRY, PARRY_CHANCE, CR_PARRY_TOOLTIP = STAT_PARRY, PARRY_CHANCE, CR_PARRY_TOOLTIP
local STAT_DODGE, DODGE_CHANCE, CR_DODGE_TOOLTIP, CR_DODGE = STAT_DODGE, DODGE_CHANCE, CR_DODGE_TOOLTIP, CR_DODGE
local STAT_AVOIDANCE, CR_AVOIDANCE_TOOLTIP, CR_AVOIDANCE = STAT_AVOIDANCE, CR_AVOIDANCE_TOOLTIP, CR_AVOIDANCE
local CR_VERSATILITY_DAMAGE_DONE, CR_VERSATILITY_DAMAGE_TAKEN, STAT_VERSATILITY, VERSATILITY_TOOLTIP_FORMAT, CR_VERSATILITY_TOOLTIP = CR_VERSATILITY_DAMAGE_DONE, CR_VERSATILITY_DAMAGE_TAKEN, STAT_VERSATILITY, VERSATILITY_TOOLTIP_FORMAT, CR_VERSATILITY_TOOLTIP
local SHOW_MASTERY_LEVEL, STAT_MASTERY = SHOW_MASTERY_LEVEL, STAT_MASTERY
local MAX_SPELL_SCHOOLS = MAX_SPELL_SCHOOLS
local RED_FONT_COLOR_CODE = RED_FONT_COLOR_CODE

local CA = CharacterArmory
local totalShown = 0

--Replacing broken Blizz function and adding some decimals
--Atteack speed
function PaperDollFrame_SetAttackSpeed(statFrame, unit)
	local meleeHaste = GetMeleeHaste();
	local speed, offhandSpeed = UnitAttackSpeed(unit);
	local displaySpeedxt

	local displaySpeed = T.format("%.2f", speed);
	if ( offhandSpeed ) then
		offhandSpeed = T.format("%.2f", offhandSpeed);
	end
	if ( offhandSpeed ) then
		displaySpeedxt =  BreakUpLargeNumbers(displaySpeed).." / ".. offhandSpeed;
	else
		displaySpeedxt =  BreakUpLargeNumbers(displaySpeed);
	end
	PaperDollFrame_SetLabelAndText(statFrame, WEAPON_SPEED, displaySpeed, false, speed);

	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, ATTACK_SPEED).." "..displaySpeed..FONT_COLOR_CODE_CLOSE;
	statFrame.tooltip2 = T.format(STAT_ATTACK_SPEED_BASE_TOOLTIP, BreakUpLargeNumbers(meleeHaste));

	statFrame:Show();
end

--Moving speed
function PaperDollFrame_SetMovementSpeed(statFrame, unit)
	statFrame.wasSwimming = nil;
	statFrame.unit = unit;
	MovementSpeed_OnUpdate(statFrame);

	statFrame.onEnterFunc = MovementSpeed_OnEnter;
	-- TODO: Fix if we decide to show movement speed
	-- statFrame:SetScript("OnUpdate", MovementSpeed_OnUpdate);

	statFrame:Show();
end

-- Versatility
function PaperDollFrame_SetVersatility(statFrame, unit)
	if ( unit ~= "player" ) then
		statFrame:Hide();
		return;
	end

	local versatility = GetCombatRating(CR_VERSATILITY_DAMAGE_DONE);
	local versatilityDamageBonus = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_DONE) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_DONE);
	local versatilityDamageTakenReduction = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_TAKEN) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_TAKEN);
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_VERSATILITY, T.format("%.2f%%", versatilityDamageBonus) .. " / " .. T.format("%.2f%%", versatilityDamageTakenReduction), false, versatilityDamageBonus);

	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE .. T.format(VERSATILITY_TOOLTIP_FORMAT, STAT_VERSATILITY, versatilityDamageBonus, versatilityDamageTakenReduction) .. FONT_COLOR_CODE_CLOSE;
	statFrame.tooltip2 = T.format(CR_VERSATILITY_TOOLTIP, versatilityDamageBonus, versatilityDamageTakenReduction, BreakUpLargeNumbers(versatility), versatilityDamageBonus, versatilityDamageTakenReduction);

	statFrame:Show();
end

-- Mastery
function PaperDollFrame_SetMastery(statFrame, unit)
	if ( unit ~= "player" ) then
		statFrame:Hide();
		return;
	end
	if (T.UnitLevel("player") < SHOW_MASTERY_LEVEL) then
		statFrame:Hide();
		return;
	end

	local mastery = GetMasteryEffect();
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_MASTERY, T.format("%.2f%%", mastery), false, mastery);
	statFrame.onEnterFunc = Mastery_OnEnter;
	statFrame:Show();
end

-- Leech (Lifesteal)
function PaperDollFrame_SetLifesteal(statFrame, unit)
	if ( unit ~= "player" ) then
		statFrame:Hide();
		return;
	end

	local lifesteal = GetLifesteal();
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_LIFESTEAL, T.format("%.2f%%", lifesteal), false, lifesteal);
	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE .. T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_LIFESTEAL) .. " " .. T.format("%.2f%%", lifesteal) .. FONT_COLOR_CODE_CLOSE;

	statFrame.tooltip2 = T.format(CR_LIFESTEAL_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_LIFESTEAL)), GetCombatRatingBonus(CR_LIFESTEAL));

	statFrame:Show();
end

-- Avoidance
function PaperDollFrame_SetAvoidance(statFrame, unit)
	if ( unit ~= "player" ) then
		statFrame:Hide();
		return;
	end

	local avoidance = GetAvoidance();
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_AVOIDANCE, T.format("%.2f%%", avoidance), false, avoidance);
	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE .. T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_AVOIDANCE) .. " " .. T.format("%.2f%%", avoidance) .. FONT_COLOR_CODE_CLOSE;

	statFrame.tooltip2 = T.format(CR_AVOIDANCE_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_AVOIDANCE)), GetCombatRatingBonus(CR_AVOIDANCE));

	statFrame:Show();
end

-- Dodge Chance
function PaperDollFrame_SetDodge(statFrame, unit)
	if (unit ~= "player") then
		statFrame:Hide();
		return;
	end

	local chance = GetDodgeChance();
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_DODGE, T.format("%.2f%%", chance), false, chance);
	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, DODGE_CHANCE).." "..T.format("%.2f", chance).."%"..FONT_COLOR_CODE_CLOSE;
	statFrame.tooltip2 = T.format(CR_DODGE_TOOLTIP, GetCombatRating(CR_DODGE), GetCombatRatingBonus(CR_DODGE));
	statFrame:Show();
end

-- Parry Chance
function PaperDollFrame_SetParry(statFrame, unit)
	if (unit ~= "player") then
		statFrame:Hide();
		return;
	end

	local chance = GetParryChance();
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_PARRY, T.format("%.2f%%", chance), false, chance);
	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, PARRY_CHANCE).." "..T.format("%.2f", chance).."%"..FONT_COLOR_CODE_CLOSE;
	statFrame.tooltip2 = T.format(CR_PARRY_TOOLTIP, GetCombatRating(CR_PARRY), GetCombatRatingBonus(CR_PARRY));
	statFrame:Show();
end

-- Block Chance
function PaperDollFrame_SetBlock(statFrame, unit)
	if (unit ~= "player") then
		statFrame:Hide();
		return;
	end

	local chance = GetBlockChance();
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_BLOCK, T.format("%.2f%%", chance), false, chance);
	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, BLOCK_CHANCE).." "..T.format("%.2f", chance).."%"..FONT_COLOR_CODE_CLOSE;
	statFrame.tooltip2 = T.format(CR_BLOCK_TOOLTIP, GetShieldBlock());
	statFrame:Show();
end

-- Crit Chance
function PaperDollFrame_SetCritChance(statFrame, unit)
	if ( unit ~= "player" ) then
		statFrame:Hide();
		return;
	end

	local rating;
	local spellCrit, rangedCrit, meleeCrit;
	local critChance;

	-- Start at 2 to skip physical damage
	local holySchool = 2;
	local minCrit = GetSpellCritChance(holySchool);
	statFrame.spellCrit = {};
	statFrame.spellCrit[holySchool] = minCrit;
	local spellCrit;
	for i=(holySchool+1), MAX_SPELL_SCHOOLS do
		spellCrit = GetSpellCritChance(i);
		minCrit = math_min(minCrit, spellCrit);
		statFrame.spellCrit[i] = spellCrit;
	end
	spellCrit = minCrit
	rangedCrit = GetRangedCritChance();
	meleeCrit = GetCritChance();

	if (spellCrit >= rangedCrit and spellCrit >= meleeCrit) then
		critChance = spellCrit;
		rating = CR_CRIT_SPELL;
	elseif (rangedCrit >= meleeCrit) then
		critChance = rangedCrit;
		rating = CR_CRIT_RANGED;
	else
		critChance = meleeCrit;
		rating = CR_CRIT_MELEE;
	end
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_CRITICAL_STRIKE, T.format("%.2f%%", critChance), false, critChance);

	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_CRITICAL_STRIKE).." "..T.format("%.2f%%", critChance)..FONT_COLOR_CODE_CLOSE;
	local extraCritChance = GetCombatRatingBonus(rating);
	local extraCritRating = GetCombatRating(rating);
	if (GetCritChanceProvidesParryEffect()) then
		statFrame.tooltip2 = T.format(CR_CRIT_PARRY_RATING_TOOLTIP, BreakUpLargeNumbers(extraCritRating), extraCritChance, GetCombatRatingBonusForCombatRatingValue(CR_PARRY, extraCritRating));
	else
		statFrame.tooltip2 = T.format(CR_CRIT_TOOLTIP, BreakUpLargeNumbers(extraCritRating), extraCritChance);
	end
	statFrame:Show();
end

-- Haste
function PaperDollFrame_SetHaste(statFrame, unit)
	if ( unit ~= "player" ) then
		statFrame:Hide();
		return;
	end

	local haste = GetHaste();
	local rating = CR_HASTE_MELEE;

	local hasteFormatString;
	if (haste < 0) then
		hasteFormatString = RED_FONT_COLOR_CODE.."%s"..FONT_COLOR_CODE_CLOSE;
	else
		hasteFormatString = "%s";
	end
-- PaperDollFrame_SetLabelAndText Format Change
	PaperDollFrame_SetLabelAndText(statFrame, STAT_HASTE, T.format(hasteFormatString, T.format("%.2f%%", haste)), false, haste);
	statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE .. T.format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_HASTE) .. " " .. T.format(hasteFormatString, T.format("%.2f%%", haste)) .. FONT_COLOR_CODE_CLOSE;

	local _, class = T.UnitClass(unit);
	statFrame.tooltip2 = _G["STAT_HASTE_"..class.."_TOOLTIP"];
	if (not statFrame.tooltip2) then
		statFrame.tooltip2 = STAT_HASTE_TOOLTIP;
	end
	statFrame.tooltip2 = statFrame.tooltip2 .. T.format(STAT_HASTE_BASE_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(rating)), GetCombatRatingBonus(rating));

	statFrame:Show();
end

local PAPERDOLL_AttributesIndexDefaultStats ={
	[1] = "HEALTH",
	[2] = "POWER",
	[3] = "ALTERNATEMANA",
	[4] = "ATTACK_DAMAGE",
	[5] = "ATTACK_AP",
	[6] = "ATTACK_ATTACKSPEED",
	[7] = "SPELLPOWER",
	[8] = "ENERGY_REGEN",
	[9] = "RUNE_REGEN",
	[10] = "FOCUS_REGEN",
	[11] = "MOVESPEED",
}

function CA:ResetAllStats()
	PAPERDOLL_STATCATEGORIES= {
		[1] = {
			categoryFrame = "AttributesCategory",
			stats = {
				[1] = { stat = "STRENGTH", primary = LE_UNIT_STAT_STRENGTH },
				[2] = { stat = "AGILITY", primary = LE_UNIT_STAT_AGILITY },
				[3] = { stat = "INTELLECT", primary = LE_UNIT_STAT_INTELLECT },
				[4] = { stat = "STAMINA" },
				[5] = { stat = "ARMOR" },
				[6] = { stat = "MANAREGEN", roles =  { "HEALER" } },
			},
		},
		[2] = {
			categoryFrame = "EnhancementsCategory",
			stats = {
				[1] = { stat = "CRITCHANCE", hideAt = 0 },
				[2] = { stat = "HASTE", hideAt = 0 },
				[3] = { stat = "MASTERY", hideAt = 0 },
				[4] = { stat = "VERSATILITY", hideAt = 0 },
				[5] = { stat = "LIFESTEAL", hideAt = 0 },
				[6] = { stat = "AVOIDANCE", hideAt = 0 },
				[7] = { stat = "DODGE", roles =  { "TANK" } },
				[8] = { stat = "PARRY", hideAt = 0, roles =  { "TANK" } },
				[9] = { stat = "BLOCK", hideAt = 0, roles =  { "TANK" } },
			},
		},
	};
end

function CA:ToggleStats()
	CA:ResetAllStats()
	for _, value in T.pairs(PAPERDOLL_AttributesIndexDefaultStats) do
		local checked = E.db.sle.Armory.Character.Stats.List[value]
		if checked then
			T.tinsert(PAPERDOLL_STATCATEGORIES[1].stats, { stat = T.format("%s", value) })
		end
	end
	PaperDollFrame_UpdateStats();
end

function CA:PaperDollFrame_UpdateStats()
	totalShown = 0
	local total, equipped = T.GetAverageItemLevel()
	if E.db.sle.Armory.Character.Stats.IlvlFull then
		if E.db.sle.Armory.Character.Stats.IlvlColor then
			local R, G, B = E:ColorGradient((equipped / total), 1, 0, 0, 1, 1, 0, 0, 1, 0)
			local avColor = E.db.sle.Armory.Character.Stats.AverageColor
			_G["CharacterStatsPane"].ItemLevelFrame.Value:SetFormattedText("%s%.2f|r / %s%.2f|r", E:RGBToHex(R, G, B), equipped, E:RGBToHex(avColor.r, avColor.g, avColor.b), total)
		else
			_G["CharacterStatsPane"].ItemLevelFrame.Value:SetFormattedText("%.2f / %.2f", equipped, total)
		end
	else
		_G["CharacterStatsPane"].ItemLevelFrame.Value:SetTextColor(GetItemLevelColor())
		PaperDollFrame_SetItemLevel(_G["CharacterStatsPane"].ItemLevelFrame, "player");
	end

	_G["CharacterStatsPane"].AttributesCategory:SetPoint("TOP", _G["CharacterStatsPane"].ItemLevelFrame, "BOTTOM", 0, 6)

	local level = T.UnitLevel("player");
	local categoryYOffset = 6;
	local statYOffset = 0;

	_G["CharacterStatsPane"].ItemLevelCategory:Show();
	_G["CharacterStatsPane"].ItemLevelFrame:Show();

	local spec = T.GetSpecialization();
	local role = T.GetSpecializationRole(spec);

	_G["CharacterStatsPane"].statsFramePool:ReleaseAll();
	-- we need a stat frame to first do the math to know if we need to show the stat frame
	-- so effectively we'll always pre-allocate
	local statFrame = _G["CharacterStatsPane"].statsFramePool:Acquire();

	local lastAnchor;

	for catIndex = 1, #PAPERDOLL_STATCATEGORIES do
		local catFrame = _G["CharacterStatsPane"][PAPERDOLL_STATCATEGORIES[catIndex].categoryFrame];
		local numStatInCat = 0;
		for statIndex = 1, #PAPERDOLL_STATCATEGORIES[catIndex].stats do
			local stat = PAPERDOLL_STATCATEGORIES[catIndex].stats[statIndex];
			local showStat = true;
			if ( showStat and stat.primary ) then
				local primaryStat = T.select(7, T.GetSpecializationInfo(spec, nil, nil, nil, UnitSex("player")));
				if ( stat.primary ~= primaryStat ) and E.db.sle.Armory.Character.Stats.OnlyPrimary then
					showStat = false;
				end
			end
			if ( showStat and stat.roles ) then
				local foundRole = false;
				for _, statRole in T.pairs(stat.roles) do
					if ( role == statRole ) then
						foundRole = true;
						break;
					end
				end
				showStat = foundRole;
			end
			if ( showStat ) then
				statFrame.onEnterFunc = nil;
				PAPERDOLL_STATINFO[stat.stat].updateFunc(statFrame, "player");
				if ( not stat.hideAt or stat.hideAt ~= statFrame.numericValue ) then
					if ( numStatInCat == 0 ) then
						if ( lastAnchor ) then
							catFrame:SetPoint("TOP", lastAnchor, "BOTTOM", 0, categoryYOffset);
						end
						lastAnchor = catFrame;
						statFrame:SetPoint("TOP", catFrame, "BOTTOM", 0, 6);
					else
						statFrame:SetPoint("TOP", lastAnchor, "BOTTOM", 0, statYOffset);
					end
					if statFrame:IsShown() then
						totalShown = totalShown + 1
						numStatInCat = numStatInCat + 1;
						statFrame.Background:SetShown((numStatInCat % 2) == 0);
						lastAnchor = statFrame;
					end
					-- done with this stat frame, get the next one
					statFrame = _G["CharacterStatsPane"].statsFramePool:Acquire();
				end
			end
		end
		catFrame:SetShown(numStatInCat > 0);
	end
	-- release the current stat frame
	_G["CharacterStatsPane"].statsFramePool:Release(statFrame);
	if totalShown > 16 then
		CA.Scrollbar:Show()
	else
		CA.Scrollbar:Hide()
	end
end

--Creating new scroll
--Scrollframe Parent Frame
CA.ScrollframeParentFrame = CreateFrame("Frame", nil, CharacterFrameInsetRight)
CA.ScrollframeParentFrame:SetSize(198, 352)
CA.ScrollframeParentFrame:SetPoint("TOP", CharacterFrameInsetRight, "TOP", 0, -4)

--Scrollframe
CA.ScrollFrame = CreateFrame("ScrollFrame", nil, CA.ScrollframeParentFrame)
CA.ScrollFrame:SetPoint("TOP")
CA.ScrollFrame:SetSize(CA.ScrollframeParentFrame:GetSize())

--Scrollbar
CA.Scrollbar = CreateFrame("Slider", nil, CA.ScrollFrame, "UIPanelScrollBarTemplate")
CA.Scrollbar:SetPoint("TOPLEFT", CharacterFrameInsetRight, "TOPRIGHT", -12, -20)
CA.Scrollbar:SetPoint("BOTTOMLEFT", CharacterFrameInsetRight, "BOTTOMRIGHT", -12, 18)
CA.Scrollbar:SetMinMaxValues(1, 2)
CA.Scrollbar:SetValueStep(1)
CA.Scrollbar.scrollStep = 1
CA.Scrollbar:SetValue(0)
CA.Scrollbar:SetWidth(8)
CA.Scrollbar:SetScript("OnValueChanged", function (self, value)
	self:GetParent():SetVerticalScroll(value)
end)
E:GetModule("Skins"):HandleScrollBar(CA.Scrollbar)
CA.Scrollbar:Hide()

--CA.ScrollChild Frame
CA.ScrollChild = CreateFrame("Frame", nil, CA.ScrollFrame)
CA.ScrollChild:SetSize(CA.ScrollFrame:GetSize())
CA.ScrollFrame:SetScrollChild(CA.ScrollChild)

CharacterStatsPane:ClearAllPoints()
CharacterStatsPane:SetParent(CA.ScrollChild)
CharacterStatsPane:SetSize(CA.ScrollChild:GetSize())
CharacterStatsPane:SetPoint("TOP", CA.ScrollChild, "TOP", 0, 0)

CharacterStatsPane.ClassBackground:ClearAllPoints()
CharacterStatsPane.ClassBackground:SetParent(CharacterFrameInsetRight)
CharacterStatsPane.ClassBackground:SetPoint("CENTER")

-- Enable mousewheel scrolling
CA.ScrollFrame:EnableMouseWheel(true)
CA.ScrollFrame:SetScript("OnMouseWheel", function(self, delta)
	if totalShown > 16 then
		CA.Scrollbar:SetMinMaxValues(1, 45)
	else
		CA.Scrollbar:SetMinMaxValues(1, 1)
	end

	local cur_val = CA.Scrollbar:GetValue()
	local min_val, max_val = CA.Scrollbar:GetMinMaxValues()

	if delta < 0 and cur_val < max_val then
		cur_val = math_min(max_val, cur_val + 22)
		CA.Scrollbar:SetValue(cur_val)
	elseif delta > 0 and cur_val > min_val then
		cur_val = math_max(min_val, cur_val - 22)
		CA.Scrollbar:SetValue(cur_val)
	end
end)

PaperDollSidebarTab1:HookScript("OnShow", function(self,event)
	CA.ScrollframeParentFrame:Show()
end)

PaperDollSidebarTab1:HookScript("OnClick", function(self,event)
	CA.ScrollframeParentFrame:Show()
end)

PaperDollSidebarTab2:HookScript("OnClick", function(self,event)
	CA.ScrollframeParentFrame:Hide()
end)

PaperDollSidebarTab3:HookScript("OnClick", function(self,event)
	CA.ScrollframeParentFrame:Hide()
end)