--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| 	Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]


DEFINE_BASECLASS("ixCharMenuPanel")
local PANEL = {}
local margin = SScaleMin(20 / 3)
local hMargin = margin * 0.5
local factionImageW = SScaleMin(300 / 3)
local backHeight = SScaleMin(30 / 3)
local padding = SScaleMin(10 / 3)

function PANEL:CreateCharacterCreation()
	self.characterPanel = self:AddSubpanel("character")
	self.characterPanel:SetTitle("")
	self.characterPanel:SetSize(self:GetSize())
	self.characterPanel.avoidPadding = true

	self.panelCreation = self.characterPanel:Add("Panel")
	self.panelCreation:SetSize(SScaleMin(1500 / 3), ScrH())
	self.panelCreation:Center()

	self:CreateCharacterModel()
	self:CreateCreationInner()
end

function PANEL:GetClothing()
	self.clothingList = {}
	self.ccaClothingList = {}

	for _, v in pairs(ix.item.list) do
		if v.base != "base_bgclothes" then continue end
		if !v.bodyGroups then continue end
		if !v.adminCreation and !v.charCreation then continue end
		if !v.outfitCategory then continue end

		local proxy = v.proxy or {}
		if v.outfitCategory == "Torso" and !proxy.TorsoColor then
			proxy = {TorsoColor = Vector(255 / 255, 255 / 255, 255 / 255)}
		end

		if v.outfitCategory == "Legs" and !proxy.PantsColor then
			proxy = {PantsColor = Vector(255 / 255, 255 / 255, 255 / 255)}
		end

		if v.outfitCategory == "Shoes" and !proxy.ShoesColor then
			proxy = {ShoesColor = Vector(255 / 255, 255 / 255, 255 / 255)}
		end

		if v.adminCreation then
			self.ccaClothingList[v.name] = {
				outfitCategory = v.outfitCategory,
				bg = v.bodyGroups[table.GetKeys(v.bodyGroups)[1]],
				color = proxy,
				uniqueID = v.uniqueID
			}

			continue
		end

		if v.charCreation then
			self.clothingList[v.name] = {
				outfitCategory = v.outfitCategory,
				bg = v.bodyGroups[table.GetKeys(v.bodyGroups)[1]],
				color = proxy,
				uniqueID = v.uniqueID
			}
		end
	end

	return self.clothingList, self.ccaClothingList
end

function PANEL:CreateCreationInner()
	self.clothingList, self.ccaClothingList = self:GetClothing()

	local innerContent = self.panelCreation:Add("Panel")

	self.rightCreation = innerContent:Add("Panel")
	self.rightCreation:Dock(RIGHT)
	self.rightCreation:SetSize(SScaleMin(460 / 3), self.panelCreation:GetTall())
	self.rightCreation:DockMargin(margin, 0, 0, 0)

	self.leftCreation = innerContent:Add("Panel")
	self.leftCreation:Dock(RIGHT)
	self.leftCreation:SetSize(SScaleMin(160 / 3), self.panelCreation:GetTall())

	innerContent:SetSize(self.rightCreation:GetWide() + self.leftCreation:GetWide() + margin, self.panelCreation:GetTall())
	innerContent:Center()

	local x, _ = innerContent:GetPos()
	innerContent:SetPos(x, ScrH() * 0.5 - SScaleMin(743 / 3) * 0.5 + (SScaleMin(150 / 3) * 0.2))

	self.characterModelList:MoveLeftOf(innerContent)

	self:CreateCreationTitles()

	-- Create Left Menu Buttons
	self:CreateCharacterButton()
	self:CreateAppearancesButton()
	self:CreateHairButton()
	self:CreateFaceButton()
	if (ix.special) then
		self:CreateAttributesButton()
	end
	if (ix.skill) then
		self:CreateSkillsButton()
	end
	self:CreateBackgroundButton()
end

function PANEL:Init()
	self.mainButtonList = {}
	self.parent = self:GetParent()
	self.WhitelistCount = self:GetWhitelistFactions()
	self.randomClickSounds = {
		"willardnetworks/charactercreation/boop1.wav",
		"willardnetworks/charactercreation/boop2.wav",
		"willardnetworks/charactercreation/boop3.wav"
	}

	self:ResetPanel()
	self:CreateFactionSelect()
	self:CreateCharacterCreation()
	self:CreateBlackBars()

	-- creation progress panel
	self.progress = self:Add("ixSegmentedProgress")
	self.progress:SetBarColor(ix.config.Get("color"))
	self.progress:SetSize(self.parent:GetWide(), 0)
	self.progress:SetVisible(false)
	self.progress:SizeToContents()
	self.progress:SetPos(0, self.parent:GetTall() - self.progress:GetTall())

	-- setup payload hooks
	self:AddPayloadHook("model", function(value)
		local faction = ix.faction.indices[self.payload.faction]

		if (faction) then
			local model
			if self.payload.gender == "male" and faction:GetModelsMale(LocalPlayer()) then
				model = faction:GetModelsMale(LocalPlayer())[value]
			elseif self.payload.gender == "female" and faction:GetModelsFemale(LocalPlayer()) then
				model = faction:GetModelsFemale(LocalPlayer())[value]
			else
				model = faction:GetModels(LocalPlayer())[value]
			end

			-- assuming bodygroups
			if (istable(model)) then
				self.characterModel:SetModel(model[1], model[2] or 0, model[3])
			else
				self.characterModel:SetModel(model or faction:GetModelsFemale(LocalPlayer())[1])
			end

			if self.characterModel:GetModel():find("models/willardnetworks/citizens/") then
				if faction.index == FACTION_CP then
					model = self.characterModel:GetModel()
					if model then
						model = string.Replace(model, "models/willardnetworks/citizens/", "models/wn7new/metropolice/")
						self.characterModel:SetModel(model)
					end
				end
			end
		end
	end)

	-- setup character creation hooks
	net.Receive("ixCharacterAuthed", function()
		timer.Remove("ixCharacterCreateTimeout")
		if (IsValid(self)) then
			self.awaitingResponse = false
		end

		local id = net.ReadUInt(32)
		local indices = net.ReadUInt(6)
		local charList = {}

		for _ = 1, indices do
			charList[#charList + 1] = net.ReadUInt(32)
		end

		ix.characters = charList

		if (IsValid(self)) then
			self:SlideDown()
		end

		ix.panelCreationActive = false
		ix.gui.mapsceneActive = nil

		if (!IsValid(self) or !IsValid(self.parent)) then
			return
		end

		if (id) then
			self.bMenuShouldClose = true

			net.Start("ixCharacterChoose")
				net.WriteUInt(id, 32)
			net.SendToServer()
		else
			self:SlideDown()
		end
	end)

	net.Receive("ixCharacterAuthFailed", function()
		timer.Remove("ixCharacterCreateTimeout")
		self.awaitingResponse = false

		local fault = net.ReadString()
		local args = net.ReadTable()

		self:SlideDown()

		self.parent.mainPanel:Undim()
		self.parent:ShowNotice(3, L(fault, unpack(args)))
	end)
end

function PANEL:SendPayload()
	if (self.awaitingResponse or !self:VerifyProgression()) then
		return
	end

	self.awaitingResponse = true

	timer.Create("ixCharacterCreateTimeout", 10, 1, function()
		if (IsValid(self) and self.awaitingResponse) then
			self.awaitingResponse = false
			self:SlideDown()

			self.parent.mainPanel:Undim()
			self.parent:ShowNotice(3, L("unknownError"))
		end
	end)

	if self.payload.Prepare then
		self.payload:Prepare()
	end

	net.Start("ixCharacterCreate")
	net.WriteUInt(table.Count(self.payload), 8)

	for k, v in pairs(self.payload) do
		net.WriteString(k)
		net.WriteType(v)
	end

	net.SendToServer()
end

function PANEL:GetMaxAttributePoints(bSkill)
	if bSkill then return 10 end
	return hook.Run("GetDefaultAttributePoints", LocalPlayer(), self.payload) or ix.config.Get("maxAttributes", 30)
end

function PANEL:OnSlideUp()
	self:ResetPayload()
	self:Populate()
	self.progress:SetProgress(1)

	-- the faction subpanel will skip to next subpanel if there is only one faction to choose from,
	-- so we don't have to worry about it here
	self:SetActiveSubpanel("faction", 0)
end

function PANEL:OnSlideDown()
end

function PANEL:ResetPayload(bWithHooks)
	if (bWithHooks) then
		self.hooks = {}
	end

	self.payload = {}

	-- TODO: eh..
	function self.payload.Set(payload, key, value)
		self:SetPayload(key, value)
	end

	function self.payload.AddHook(payload, key, callback)
		self:AddPayloadHook(key, callback)
	end

	function self.payload.Prepare(payload)
		self.payload.Set = nil
		self.payload.AddHook = nil
		self.payload.Prepare = nil
	end
end

function PANEL:SetPayload(key, value)
	self.payload[key] = value
	self:RunPayloadHook(key, value)
end

function PANEL:AddPayloadHook(key, callback)
	if (!self.hooks[key]) then
		self.hooks[key] = {}
	end

	self.hooks[key][#self.hooks[key] + 1] = callback
end

function PANEL:RunPayloadHook(key, value)
	local hooks = self.hooks[key] or {}

	for _, v in ipairs(hooks) do
		v(value)
	end
end

function PANEL:AttachCleanup(panel)
	self.repopulatePanels[#self.repopulatePanels + 1] = panel
end

function PANEL:Populate()

	-- remove panels created for character vars
	for i = 1, #self.repopulatePanels do
		self.repopulatePanels[i]:Remove()
	end

	self.repopulatePanels = {}

	-- payload is empty because we attempted to send it - for whatever reason we're back here again so we need to repopulate
	if (!self.payload.faction) then
		self.payload.faction = FACTION_CITIZEN
	end


	if (!self.bInitialPopulate) then
		-- setup progress bar segments
		if self.WhitelistCount > 1 then
			self.progress:AddSegment("@faction")
		end

		self.progress:AddSegment("character")

		self.progress:SetVisible(false)
	end

	self.bInitialPopulate = true
end

function PANEL:VerifyProgression(name)
	for k, v in SortedPairsByMemberValue(ix.char.vars, "index") do
		if (name ~= nil and (v.category or "character") != name) then
			continue
		end

		local value = self.payload[k]

		if (!v.bNoDisplay or v.OnValidate) then
			if (v.OnValidate) then
				local result = {v:OnValidate(value, self.payload, LocalPlayer())}

				if (result[1] == false) then
					self:GetParent():ShowNotice(3, L(unpack(result, 2)))
					return false
				end
			end

			self.payload[k] = value
		end
	end

	return true
end

-- Faction Stuff
function PANEL:CreateFactionSelect()
	self.factionPanel = self:AddSubpanel("faction", true)
	self.factionPanel:SetTitle("")
	self.factionPanel:SetSize(self.parent:GetSize())
	self.factionPanel.avoidPadding = true

	self.panelFaction = self.factionPanel:Add("Panel")
	self:CreateFactionTitles()
	self:CreateFactionsInner()
end

function PANEL:CreateFactionTitles()
	self.titleLabel = self.panelFaction:Add("DLabel")
	self.titleLabel:SetTextColor(color_white)
	self.titleLabel:SetFont("MainMenuNewTitleFont")
	self.titleLabel:SetText(string.utf8upper("Factions"))
	self.titleLabel:SizeToContents()
	self.titleLabel:SetContentAlignment(5)
	self.titleLabel:Dock(TOP)
	self.titleLabel:DockMargin(0, 0, 0, SScaleMin(50 / 3))
end

function PANEL:CreateFactionsInner()
	local listHeight = SScaleMin(500 / 3)
	local textSize = SScaleMin(70 / 3)
	local listAndText = listHeight + textSize
	local prevNextW, prevNextH = SScaleMin(32 / 3), SScaleMin(32 / 3)
	local panelHeight = self.titleLabel:GetTall() + SScaleMin(50 / 3) + (SScaleMin(20 / 3) * 2) + listAndText + backHeight + margin

	local panelLoadWBelowEqual4 = self.WhitelistCount * (factionImageW + margin)
	local panelLoad4 = 4 * (factionImageW + margin)

	if panelLoadWBelowEqual4 < self.titleLabel:GetWide() then panelLoadWBelowEqual4 = self.titleLabel:GetWide() end
	if panelLoad4 < self.titleLabel:GetWide() then panelLoad4 = self.titleLabel:GetWide() end

	if self.WhitelistCount >= 1 and self.WhitelistCount <= 4 then
		self.panelFaction:SetSize(panelLoadWBelowEqual4, panelHeight)
	elseif self.WhitelistCount > 4 then
		self.panelFaction:SetSize(panelLoad4, panelHeight)
	end

	self.panelFaction:Center()

	local factionListContent = self.panelFaction:Add("Panel")
	factionListContent:SetSize(self.panelFaction:GetWide(), listAndText)
	factionListContent:Dock(TOP)

	self.factionList = factionListContent:Add("Panel")
	self.factionList:SetSize(self.WhitelistCount * (factionImageW + margin), listHeight)

	self.textFaction = factionListContent:Add("Panel")
	self.textFaction:SetSize(self.WhitelistCount * (factionImageW + margin), textSize)
	self.textFaction:SetPos(0, self.factionList:GetTall())

	if self.WhitelistCount > 4 then
		local nextBut = self.factionPanel:Add("DImageButton")
		nextBut:SetSize(prevNextW, prevNextH)
		nextBut:SetImage("willardnetworks/charselect/arrow_right.png")

		nextBut:Center()
		local _, y = nextBut:GetPos()
		nextBut:MoveRightOf(self.panelFaction)
		local x2, _ = nextBut:GetPos()

		nextBut:SetPos(x2 + margin, y)

		nextBut.OnCursorEntered = function()
			surface.PlaySound("helix/ui/rollover.wav")
			nextBut:SetColor( Color( 210, 210, 210, 255 ) )
		end

		nextBut.OnCursorExited = function()
			nextBut:SetColor( color_white )
		end

		nextBut.DoClick = function()
			surface.PlaySound("helix/ui/press.wav")

			local x, y2 = self.factionList:GetPos()
			local x3, y3 = self.textFaction:GetPos()

			local pos1, pos2 = math.Round(math.abs( x )), math.Round(((self.WhitelistCount - 5) * (factionImageW + margin)))

			if pos1 == pos2 or math.abs(pos1 - pos2) <= factionImageW - 10 then
				nextBut:SetVisible(false)
			end

			self.factionList:MoveTo( x - (factionImageW + margin), y2, 0.1, 0, 1 )
			self.textFaction:MoveTo( x3 - (factionImageW + margin), y3, 0.1, 0, 1 )

			if IsValid(self.prevBut) then
				return
			else
				self.prevBut = self.factionPanel:Add("DImageButton")


				self.prevBut:SetSize(prevNextW, prevNextH)
				self.prevBut:SetImage("willardnetworks/charselect/arrow_left.png")

				self.prevBut:Center()
				_, y = self.prevBut:GetPos()
				self.prevBut:MoveLeftOf(self.panelFaction)
				x2, y2 = self.prevBut:GetPos()

				self.prevBut:SetPos(x2 - margin, y)

				self.prevBut.OnCursorEntered = function()
					surface.PlaySound("helix/ui/rollover.wav")
					self.prevBut:SetColor( Color( 210, 210, 210, 255 ) )
				end

				self.prevBut.OnCursorExited = function()
					self.prevBut:SetColor( color_white )
				end

				self.prevBut.DoClick = function()
					surface.PlaySound("helix/ui/press.wav")

					x, y = self.factionList:GetPos()
					x2, y2 = self.textFaction:GetPos()

					if IsValid(nextBut) then
						nextBut:SetVisible(true)
					end

					self.factionList:MoveTo( x + (factionImageW + margin), y, 0.1, 0, 1 )
					self.textFaction:MoveTo( x2 + (factionImageW + margin), y2, 0.1, 0, 1 )

					if IsValid(self.prevBut) then
						pos1, pos2 = math.Round(x, 0), math.Round((0 - (factionImageW + margin)), 0)
						if pos1 == pos2 or math.abs(pos1 - pos2) <= factionImageW - 10 then
							self.prevBut:Remove()
						end
					end
				end
			end
		end
	end

	self:CreateActualFactions()
end

function PANEL:CreateActualFactions()
	for _, v in SortedPairs(ix.faction.teams) do
		if (ix.faction.HasWhitelist(v.index)) then
			local factionImage = v.factionImage
			local button = self.factionList:Add("DImageButton")
			button:SetImage(factionImage or "scripted/breen_fakemonitor_1")
			button:Dock(LEFT)
			button:DockMargin(hMargin, 0, hMargin, 0)
			button:SetSize( factionImageW, self.factionList:GetTall() )
			button.faction = v.index

			button.PaintOver = function(_, w, h)
				surface.SetDrawColor(Color(73, 82, 87, 255))
				surface.DrawOutlinedRect(0, 0, w, h)
			end

			button.Paint = function ( _, w, h )
				surface.SetDrawColor(Color(255, 255, 255, 0))

				if button:IsHovered() then
					button:SetColor( Color( 210, 210, 210, 255 ) )
				else
					button:SetColor( color_white )
				end
			end

			button.DoClick = function(panel)
				surface.PlaySound("helix/ui/press.wav")

				self:SetStandardFactionInfo(panel)
				self.progress:IncrementProgress()
				self:Populate()
				self:SetActiveSubpanel("character")
				self:CheckIfFinished()
				self:FadeInBars()

				self.characterButton.DoClick()

				ix.panelCreationActive = true
				ix.gui.mapsceneActive = self.faction.name
			end

			button.OnCursorEntered = function()
				surface.PlaySound("helix/ui/rollover.wav")
			end
		end
	end

	for _, v in SortedPairs(ix.faction.teams) do
		if (ix.faction.HasWhitelist(v.index)) then
			local insidePanel = self.textFaction:Add("Panel")
			insidePanel:Dock(LEFT)
			insidePanel:SetSize(factionImageW, self.textFaction:GetTall())
			insidePanel:DockMargin(hMargin, 0, hMargin, 0)

			local text = insidePanel:Add("DLabel")
			text:SetFont("TitlesFontNoBoldNoClamp")
			text:SetText(string.utf8upper(v.name))
			text:SizeToContents()
			text:Center()
		end
	end

	self:CreateFactionBack()
end

function PANEL:CreateFactionBack()
	local parent = self:GetParent()

	self.aFontColor = parent.mainPanel.aFontColor or Color(196, 196, 196, 255)
	self.aFontHoverColor = parent.mainPanel.aFontHoverColor or Color(255, 255, 255, 255)
	self.aFontLockedButtonColor = parent.mainPanel.aFontLockedButtonColor or Color(90, 90, 90, 255)

	local backPanel = self.panelFaction:Add("Panel")
	backPanel:Dock(TOP)
	backPanel:DockMargin(0, SScaleMin(20 / 3) * 2, 0, 0)
	backPanel:SetSize(self.panelFaction:GetWide(), SScaleMin(30 / 3))

	self.factionBack = backPanel:Add("DButton")
	self.factionBack:SetText(string.utf8upper(" Retour"))
	self.factionBack:SetContentAlignment(6)
	self.factionBack:SetSize(SScaleMin(90 / 3), SScaleMin(30 / 3))
	self.factionBack:SetTextColor(self.aFontColor)
	self.factionBack:SetFont("MainMenuNewButtonFont")
	self.factionBack:SetTextInset(SScaleMin(10 / 3), 0)
	self.factionBack:Center()

	self.factionBack.Paint = function( this, w, h )
		surface.SetDrawColor(Color(255, 255, 255, 255))
		surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/back_arrow.png"))
		surface.DrawTexturedRect(SScaleMin(10 / 3), (SScaleMin(30 / 3) * 0.5) - (margin * 0.5), margin, margin)
	end

	self.factionBack.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
		self.factionBack:SetTextColor(self.aFontHoverColor)
	end

	self.factionBack.OnCursorExited = function()
		self.factionBack:SetTextColor(self.aFontColor)
	end

	self.factionBack.DoClick = function()
		self.progress:DecrementProgress()

		self:SetActiveSubpanel("faction", 0)
		self:SlideDown()

		self.parent.mainPanel:Undim()
	end
end

-- Creation functions
function PANEL:CreateBlackBar(parent, bDockTop)
	parent:SetType( "Rect" )
	parent:SetColor( Color(0, 0, 0, 0) )
	parent:Dock(bDockTop and TOP or BOTTOM)
	parent:SetSize( ScrW(), math.Clamp(VScale(75 / 3), 0, 75) )
end

function PANEL:CreateBlackBars()
	ix.gui.blackBarTop = self.characterPanel:Add("DShape")
	self:CreateBlackBar(ix.gui.blackBarTop, true)

	ix.gui.blackBarBottom = self.characterPanel:Add("DShape")
	self:CreateBlackBar(ix.gui.blackBarBottom)
end

-- Character creation stuff
-- A function to create the background button in the main menu
function PANEL:CreateBackgroundButton()
	self.backgroundButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.backgroundButton, "background")
	self.backgroundButton.DoClick = function()
		self:ResetModelCam()

		self:ClearSelectedMainButtons()
		self:SetButtonSelected(self.backgroundButton, "background", true)
		surface.PlaySound(table.Random(self.randomClickSounds))

		self:CreateRightMenuTextPanel("background", 60)

		self.backgroundButtonList = {}

		if !table.IsEmpty(self.backgroundButtonList) then
			table.Empty(self.backgroundButtonList)
		end

		if self.faction:GetNoBackground(LocalPlayer()) != true then
			if self.faction.name == "Citoyen" then
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/relocatedcitizen.png", 45, 61, "Citoyen Relocalisé", "Vous venez d'arriver dans cette nouvelle ville, inconnue. Pas de famille, pas de contacts, juste un autre anonyme descendant du train pour commencer une nouvelle vie.", -5, "Bien pour les nouveaux joueurs.")
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/local.png", 34, 61, "Citoyen Local", "Vous vivez ici depuis un bon moment, peut-être même depuis avant l'occupation. D'une manière ou d'une autre, vous avez eu de la chance et n'avez jamais été déplacé. À présent, vous connaissez la ville dans ses moindres détails.", 0)
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/supporter.png", 53, 68, "Citoyen Loyal", "Pour une raison ou une autre, vous avez accepté l'autorité de l'Union, suivez leurs règles et essayez de répondre à leurs attentes. Certains citoyens pourraient ne pas voir d'un bon œil votre collaboration.", 0)
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/outcast.png", 55, 55, "Nomade", "Toujours en mouvement, toujours en cachette. Évitant le regard de l'Union. Vous vivez de vos propres moyens dans les taudis, pour le meilleur ou pour le pire.", 5)
			elseif self.faction.name == "Vortigaunt" then
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/supporter.png", 53, 68, "Biotique", "Asservi, libéré, puis asservi à nouveau. Avec un collier autour de votre cou et la botte de l'Union sur vous, vous devez endurer la torture. Vous, et des milliers d'autres.", 13, "Choisissez celui-ci à moins que vous n'ayez la permission d'utiliser d'autres contextes.")
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/local.png", 34, 61, "Libéré", "Autrefois asservi, désormais libre. Vous avez vécu sous la botte de l'Union, mais ce n'est plus le cas. Soyez prudent, car l'Union a déjà goûté à votre sang et ne fera pas preuve de clémence si elle vous retrouve à nouveau...", 13, "Difficulté élevée - Ne l'utilisez pas sans permission.")
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/outcast.png", 55, 55, "Sauvage", "Vous avez été l'un des rares vortigaunts chanceux à n'avoir jamais été capturé par l'Union. La dernière chaîne autour de votre cou était celle du Nihilanth. L'Union ne sait pas que vous existez.", 15, "Ne l'utilisez pas sans permission.", nil, true)
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/supporter.png", 53, 68, "Collaborateur", "Un traître au peuple vortigaunt qui s'est permis les luxes que l'Union a trompeusement offerts, vous avez ainsi pris le statut de Collaborateur.", 13, "Ne l'utilisez pas sans permission. Ce background commence avec un CID et 50 points de cohésion ainsi qu'une belle paire de pantalons et aucune chaîne.", nil, true)
			elseif self.faction.name == "Union des Travailleurs Civils" then
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/relocatedcitizen.png", 45, 61, "Worker", "You are a worker for the Civil Workers Union under the Combine occupation. You spend your time cleaning infestation or repairing infrastructure.", -8)
				self:CreateBackgroundSelectionPanels("willardnetworks/mainmenu/charcreation/local.png", 34, 61, "Medic", "You are a medic for Civil Medical Union. Your job is to heal the populace, or if you get lucky, operate on both Vortiguants and Civil Protection. Do your duty.", -10)
			end
		else
			local backgroundPanel = self.rightCreation:Add("Panel")
			backgroundPanel:Dock(TOP)
			backgroundPanel:DockMargin(0, 0 - SScaleMin(1 / 3), 0, 0)
			backgroundPanel:SetTall(SScaleMin(140 / 3))
			backgroundPanel.Paint = function(_, w, h)
				surface.SetDrawColor(Color(0, 0, 0, 100))
				surface.DrawRect(0, 0, w, h)

				surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
				surface.DrawOutlinedRect(0, 0, w, h)
			end

			local noBackground = backgroundPanel:Add("DLabel")
			noBackground:Dock(FILL)
			noBackground:SetFont("MenuFontNoClamp")
			noBackground:SetText("Sélection de background non disponible pour cette faction")
			noBackground:SetContentAlignment(5)
		end

		self:CreateFinishPanel(self.skillsButton, false)
	end
end

-- A function to create a single attribute in the attribute panel
function PANEL:CreateAttribute(icon, wIcon, hIcon, title, desc, attribute, bSkill, minorBoost, majorBoost)
	local attributePanelH = SScaleMin(105 / 3)
	local skillDivider = 1.5
	hIcon = (bSkill and hIcon / skillDivider) or hIcon
	wIcon = (bSkill and wIcon / skillDivider) or wIcon

	local attributePanel = self.rightCreation:Add("Panel")
	attributePanel:Dock(TOP)
	attributePanel:DockMargin(0, 0 - SScaleMin(1 / 3), 0, 0)
	attributePanel:SetTall(bSkill and attributePanelH / skillDivider or attributePanelH)
	attributePanel.Paint = function(_, w, h)
		surface.SetDrawColor(Color(0, 0, 0, 100))
		surface.DrawRect(0, 0, w, h)

		surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
		surface.DrawOutlinedRect(0, 0, w, h)

		surface.SetDrawColor(color_white)
		surface.SetMaterial(Material(icon))
		surface.DrawTexturedRect(SScaleMin(90 / 3) * 0.5 - SScaleMin(wIcon / 3) * 0.5, attributePanel:GetTall() * 0.5 - SScaleMin(hIcon / 3) * 0.5, SScaleMin(wIcon / 3), SScaleMin(hIcon / 3))
	end

	local textPanel = attributePanel:Add("Panel")
	textPanel:SetSize(self.rightCreation:GetWide() - (SScaleMin(50 / 3) + SScaleMin(wIcon / 3)) - (SScaleMin(15 / 3) + SScaleMin(50 / 3)), attributePanel:GetTall())
	textPanel:SetPos(SScaleMin(90 / 3), 0)

	local minorAttBoostSkill
	local majorAttBoostSkill
	local attBoostSum = false
	if bSkill then
		minorAttBoostSkill = (minorBoost.skills[attribute] * self.payload.special[minorBoost.uniqueID])
		majorAttBoostSkill = (majorBoost.skills[attribute] * self.payload.special[majorBoost.uniqueID])
		attBoostSum = minorAttBoostSkill + majorAttBoostSkill
	end

	local titleTextPanel = textPanel:Add("Panel")
	titleTextPanel:Dock(TOP)

	local titleText = titleTextPanel:Add("DLabel")
	titleText:SetText(string.utf8upper(title))
	titleText:SetFont("LargerTitlesFontNoClamp")
	titleText:SizeToContents()
	titleText:Dock(LEFT)
	titleText:SetTextColor(Color(255, 204, 0, 255))

	if (bSkill) then
		local boostedLevels = titleTextPanel:Add("DLabel")
		boostedLevels:Dock(FILL)
		boostedLevels:SetContentAlignment(4)
		boostedLevels:SetFont("MenuFontLargerBoldNoFix")
		boostedLevels:SetTextColor(Color(75, 238, 75))
		boostedLevels:SetText("Attribute Levels: +"..attBoostSum)
		boostedLevels:DockMargin(SScaleMin(10 / 3), 0, 0, 0)
		boostedLevels:SizeToContents()
	end

	titleTextPanel:SetSize(titleText:GetSize())

	local descText = textPanel:Add("DLabel")
	descText:SetText(desc)
	descText:SetFont("SmallerTitleFontNoBoldNoClamp")
	descText:SetWrap(true)
	descText:SetAutoStretchVertical(true)
	descText:Dock(TOP)

	textPanel.Paint = function(this, w, h)
		this:SetSize(this:GetWide(), titleText:GetTall() + descText:GetTall())
		this:Center()
		local _, y = this:GetPos()
		this:SetPos(SScaleMin(90 / 3), y - SScaleMin(2 / 3))
	end

	local attributePointsPanel = attributePanel:Add("Panel")
	attributePointsPanel:Dock(RIGHT)
	attributePointsPanel:DockMargin(0, 0, SScaleMin(25 / 3), 0)
	attributePointsPanel:SetSize(SScaleMin(30 / 3), attributePanel:GetTall())

	local upArrow = attributePointsPanel:Add("DImageButton")
	upArrow:Dock(TOP)
	upArrow:SetTall(SScaleMin(9 / 3))
	upArrow:SetImage("willardnetworks/mainmenu/charcreation/uparrow.png")

	local attributePoint = attributePointsPanel:Add("DLabel")
	attributePoint:SetFont("LargerTitlesFontNoClamp")
	attributePoint:Dock(TOP)
	attributePoint:SetText(bSkill and (self.payload.skill[attribute] or "0") or (self.payload.special[attribute] or "0"))
	attributePoint:SetContentAlignment(5)
	attributePoint:SizeToContents()

	local diff = (-SScaleMin(15 / 3) + attributePointsPanel:GetWide()) / 2
	local downArrow = attributePointsPanel:Add("DImageButton")
	downArrow:Dock(TOP)
	downArrow:DockMargin(diff, SScaleMin(5 / 3), diff, 0)
	downArrow:SetTall(SScaleMin(9 / 3))
	downArrow:SetImage("willardnetworks/mainmenu/charcreation/downarrow.png")

	upArrow:DockMargin(diff, attributePointsPanel:GetTall() * 0.5 - upArrow:GetTall() * 0.5 - attributePoint:GetTall() * 0.5 - downArrow:GetTall() * 0.5 - SScaleMin(5 / 3), diff, SScaleMin(5 / 3))

	downArrow.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
	end

	downArrow.DoClick = function()
		if tonumber(attributePoint:GetText()) == 0 then
			return
		end

		surface.PlaySound("helix/ui/press.wav")
		attributePoint:SetText(tostring(tonumber(attributePoint:GetText()) - 1))
		self:AttributesRefresh(attribute, tonumber(attributePoint:GetText()), bSkill)
	end

	upArrow.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
	end

	upArrow.DoClick = function()
		if (bSkill and tonumber(attributePoint:GetText()) == 10) or (!bSkill and tonumber(attributePoint:GetText()) == 5) then
			return
		end

		if self:GetPointsLeft(bSkill) <= 0 then
			return
		end

		surface.PlaySound("helix/ui/press.wav")
		attributePoint:SetText(tostring(tonumber(attributePoint:GetText()) + 1))
		self:AttributesRefresh(attribute, tonumber(attributePoint:GetText()), bSkill)
	end
end

-- A function to create the attributes button in the main menu
function PANEL:CreateAttributesButton()
	self.attributesButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.attributesButton, "attributs")
	self.attributesButton.DoClick = function()
		self:ResetModelCam()
		self:ClearSelectedMainButtons()

		self:SetButtonSelected(self.attributesButton, "attributs", true)
		surface.PlaySound(table.Random(self.randomClickSounds))

		local textPanel = self.rightCreation:Add("Panel")
		textPanel:Dock(TOP)
		textPanel:SetTall(SScaleMin(20 / 3))
		textPanel:DockMargin(0, SScaleMin(55 / 3), 0, padding)

		local panelText = textPanel:Add("DLabel")
		panelText:SetText(string.utf8upper("sélection d'attributs"))
		panelText:SetFont("MenuFontNoClamp")
		panelText:SizeToContents()
		panelText:Dock(LEFT)
		panelText:SetContentAlignment(4)

		if self.faction.noAttributes then
			local noAttributes = self.rightCreation:Add("Panel")
			noAttributes:Dock(TOP)
			noAttributes:DockMargin(0, 0 - SScaleMin(1 / 3), 0, 0)
			noAttributes:SetTall(SScaleMin(140 / 3))
			noAttributes.Paint = function(_, w, h)
				surface.SetDrawColor(Color(0, 0, 0, 100))
				surface.DrawRect(0, 0, w, h)

				surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
				surface.DrawOutlinedRect(0, 0, w, h)
			end

			local noAttributesAvailable = noAttributes:Add("DLabel")
			noAttributesAvailable:Dock(FILL)
			noAttributesAvailable:SetFont("MenuFontNoClamp")
			noAttributesAvailable:SetText("Aucun attribut disponible pour cette faction.")
			noAttributesAvailable:SetContentAlignment(5)
		else
			self.attributesRemaining = textPanel:Add("DLabel")
			self.attributesRemaining:SetFont("TitlesFontNoClamp")
			self.attributesRemaining:DockMargin(0, 0, 0, SScaleMin(3 / 3))
			self.attributesRemaining:Dock(RIGHT)
			self.attributesRemaining:SetContentAlignment(6)
			self.attributesRemaining:SetText(self:GetPointsLeft()..string.utf8upper(" points restants"))
			self.attributesRemaining:SizeToContents()

			self:CreateAttribute("willardnetworks/mainmenu/charcreation/strength.png", 45, 61, "Force", "Boost majeur aux armes \nBoost mineur a la vitesse et au craft", "strength")
			self:CreateAttribute("willardnetworks/mainmenu/charcreation/perception.png", 45, 30, "Perception", "Boost majeur a la cuisine \nBoost mineur a la contrebande et aux armes", "perception")
			self:CreateAttribute("willardnetworks/mainmenu/charcreation/agility.png", 38, 47, "Agilité", "Boost majeur a la contrebande et la vitesse \nBoost mineur a la médecine", "agility")
			self:CreateAttribute("willardnetworks/mainmenu/charcreation/intelligence.png", 48, 29, "Intelligence", "Boost majeur au craft et a la médecine \nBoost mineur a la cuisine", "intelligence")

			self:CreateRightMenuYellowTextPanel("Les attributs restent permanents et ne peuvent être temporairement améliorés qu'avec des objets.", 5)
		end

		self:CreateFinishPanel(self.faceButton, self.skillsButton)
	end
end

-- A function to create the attributes button in the main menu
function PANEL:CreateSkillsButton()
	self.skillsButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.skillsButton, "skills")
	self.skillsButton.DoClick = function()
		self:ResetModelCam()
		self:ClearSelectedMainButtons()

		self:SetButtonSelected(self.skillsButton, "skills", true)
		surface.PlaySound(table.Random(self.randomClickSounds))

		local textPanel = self.rightCreation:Add("Panel")
		textPanel:Dock(TOP)
		textPanel:SetTall(SScaleMin(20 / 3))
		textPanel:DockMargin(0, SScaleMin(55 / 3), 0, padding)

		local panelText = textPanel:Add("DLabel")
		panelText:SetText(string.utf8upper("skills"))
		panelText:SetFont("MenuFontNoClamp")
		panelText:SizeToContents()
		panelText:Dock(LEFT)
		panelText:SetContentAlignment(4)

		self.attributesRemaining = textPanel:Add("DLabel")
		self.attributesRemaining:SetFont("TitlesFontNoClamp")
		self.attributesRemaining:DockMargin(0, 0, 0, SScaleMin(3 / 3))
		self.attributesRemaining:Dock(RIGHT)
		self.attributesRemaining:SetContentAlignment(6)
		self.attributesRemaining:SetText(self:GetPointsLeft(true)..string.utf8upper(" points restants"))
		self.attributesRemaining:SizeToContents()

		local attributes = ix.special.list or {}

		for skillID, skillInfo in pairs(ix.skill.list) do
			if (skillInfo.name == "Vortessence" and self.faction.name != "Vortigaunt") or skillInfo.name == "Commerce" then
				continue
			end

			local skillAttributes = {}

			-- Find the attributes that boost the skill
			for _, v in pairs(attributes) do
				if v.skills then
					if v.skills[skillInfo.uniqueID] then
						skillAttributes[v.skills[skillInfo.uniqueID]] = v
					end
				end
			end

			self:CreateAttribute(skillInfo.icon, 60, 60, skillInfo.name, skillInfo.description, skillID, true, skillAttributes[1], skillAttributes[2])
		end

		self:CreateRightMenuYellowTextPanel("Skills have a maximum level of 50", 5)

		self:CreateFinishPanel(self.attributesButton, self.backgroundButton)
	end
end

-- A function to create a title label at the top of the left side menu
function PANEL:CreateCreationTitle(text, topMargin, bottomMargin)
	local leftCreationTitle = self.leftCreation:Add("DLabel")
	leftCreationTitle:SetFont("CharCreationBoldTitleNoClamp")
	leftCreationTitle:SetText(string.utf8upper(text))
	leftCreationTitle:SizeToContents()
	leftCreationTitle:DockMargin(0, topMargin, 0, bottomMargin)
	leftCreationTitle:Dock(TOP)
end

-- A helper function to create the title labels at top of the left side menu
function PANEL:CreateCreationTitles()
	self:CreateCreationTitle("new", 0, 0)
	self:CreateCreationTitle("character", SScaleMin((0 - 5) / 3), padding)
end

-- A function to create a button in the left menu
function PANEL:CreateMainButton(parent, text)
	parent:SetText(string.utf8upper(text))
	parent:SetFont("WNMenuFontNoClamp")
	parent:SetContentAlignment(4)
	parent:SetTextInset(SScaleMin(35 / 3), 0)
	parent:SetTextColor(Color(200, 200, 200, 255))
	parent:Dock(TOP)
	parent:SetSize(self.leftCreation:GetWide(), SScaleMin(36 / 3))
	parent:DockMargin(0, 0, 0, padding)
	parent.name = text

	parent.OnCursorEntered = function()
		surface.PlaySound("willardnetworks/charactercreation/hover.wav")
	end

	parent.Paint = function(this, w, h)
		self:DrawButtonUnselected(text, this, w, h, true)
	end

	table.insert(self.mainButtonList, parent)
end

-- A function to draw the character model left of the creation
function PANEL:CreateCharacterModel()
	self.characterModelList = self.panelCreation:Add("Panel")
	self.characterModelList:SetSize(SScaleMin(400 / 3), ScrH())
	self.characterModelList:Center()

	self.characterModel = self.characterModelList:Add("ixModelPanel")
	self.characterModel:Dock(FILL)
	self.characterModel:SetModel("models/willardnetworks/citizens/female_01.mdl")
	self.characterModel:SetFOV(26)
	self.characterModel.PaintModel = self.characterModel.Paint

	self.originPos = self.characterModel:GetCamPos()
	self.originLookAt = self.characterModel:GetLookAt()
end

-- A function to create a panel for text in the right side panel
function PANEL:CreateRightMenuTextPanel(text, topMargin)
	local textPanel = self.rightCreation:Add("Panel")
	textPanel:Dock(TOP)
	textPanel:SetTall(margin)
	textPanel:DockMargin(0, SScaleMin(topMargin / 3), 0, padding)

	local panelText = textPanel:Add("DLabel")
	panelText:SetText(string.utf8upper(text))
	panelText:SetFont("MenuFontNoClamp")
	panelText:SizeToContents()
	panelText:Dock(LEFT)
	panelText:SetContentAlignment(4)

	return panelText
end

-- A function to create a text entry in the right side panel
function PANEL:CreateRightMenuTextEntry(parent, text, height, boolMultiline, maxChars, name)
	parent:Dock(TOP)
	parent:SetTall(SScaleMin(height / 3))
	parent:DockMargin(0, 0, 0, padding)
	parent:SetMultiline( boolMultiline )
	parent:SetVerticalScrollbarEnabled( boolMultiline )
	parent:SetEnterAllowed( boolMultiline )
	parent:SetTextColor(Color(200, 200, 200, 255))
	parent:SetCursorColor(Color(200, 200, 200, 255))
	parent:SetFont("MenuFontNoClamp")
	parent:SetPlaceholderText(text or "")
	parent:SetPlaceholderColor( Color(200, 200, 200, 255) )
	if name == "name" then
		parent:SetText(self.payload.name or "")
	elseif name == "desc" then
		parent:SetText(self.payload.description or "")
	end

	parent.Paint = function(this, w, h)
		surface.SetDrawColor(Color(0, 0, 0, 100))
		surface.DrawRect(0, 0, w, h)

		surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
		surface.DrawOutlinedRect(0, 0, w, h)

		if ( this.GetPlaceholderText and this.GetPlaceholderColor and this:GetPlaceholderText() and this:GetPlaceholderText():Trim() != "" and this:GetPlaceholderColor() and ( !this:GetText() or this:GetText() == "" ) ) then

			local oldText = this:GetText()

			local str = this:GetPlaceholderText()
			if ( str:StartWith( "#" ) ) then str = str:utf8sub( 2 ) end
			str = language.GetPhrase( str )

			this:SetText( str )
			this:DrawTextEntryText( this:GetPlaceholderColor(), this:GetHighlightColor(), this:GetCursorColor() )
			this:SetText( oldText )

			return
		end

		this:DrawTextEntryText( this:GetTextColor(), this:GetHighlightColor(), this:GetCursorColor() )
	end

	parent.MaxChars = maxChars
	parent.OnTextChanged = function(parentSelf)
		if name == "name" then
			self.payload:Set("name", parentSelf:GetValue())
		end

		if name == "desc" then
			self.payload:Set("description", parentSelf:GetValue())
		end

		self:CheckIfFinished()
	end
end

-- A function to create a gender button inside a right side panel
function PANEL:CreateGenderButton(parent, icon, w, h, rightMargin, gender)
	parent:SetSize( SScaleMin(w / 3), SScaleMin(h / 3) )
	parent:SetImage( icon )
	parent:Dock(RIGHT)
	parent:DockMargin(0, 0, SScaleMin(rightMargin / 3), 0)
	parent:SetColor(Color(150, 150, 150, 255))

	if self.payload.gender != "male" and self.payload.gender != "female" then
		self.payload:Set("gender", "female")
	end

	if gender == "male" and self.payload.gender == "male" then
		parent:SetColor(Color(255, 204, 0, 255))
	end

	if gender == "female" and self.payload.gender == "female" then
		parent:SetColor(Color(255, 204, 0, 255))
	end

	parent.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
	end

	parent.DoClick = function()

		surface.PlaySound("helix/ui/press.wav")
		parent:SetColor(Color(255, 204, 0, 255))

		if gender == "female" then
			if self.genderButtonMale then
				self.genderButtonMale:SetColor(Color(150, 150, 150, 255))
			end

			self.payload:Set("gender", "female")
			self.payload:Set("model", 1)
		else
			if self.genderButtonFemale then
				self.genderButtonFemale:SetColor(Color(150, 150, 150, 255))
			end

			self.payload:Set("gender", "male")
			self.payload:Set("model", 1)
		end

		self:ResetModelCam()

		local eyeColorTable = self:GetActiveSkinEyeColorTable()

		self.characterModel.Entity:SetSkin(eyeColorTable[1] or 0)
		self.payload.data["skin"] = eyeColorTable[1]

		self.payload.data["groups"] = {}
		self.payload.data["glasses"] = false
		self.payload.data["canread"] = true
		self.payload:Set("hair", {hair = 0, color = self.payload.hair.color})

		self.payload.data.groups[self.beardBodygroups] = 0
		self.payload.data.groups[self.hairBodygroups] = 0

		self:CheckIfFinished()
	end
end

-- A function to create a custom DComboBox
function PANEL:CreateSelectionMenu(parent, width, text, selections)
	local faction = ix.faction.indices[self.payload.faction]

	parent:Dock(LEFT)
	parent:SetWide(SScaleMin(width / 3))

	if (self.payload.data[text] != nil and self.payload.data[text] != "") then
		if (string.utf8len(self.payload.data[text]) > 7) and faction.name != "Vortigaunt" then
			parent:SetText(string.utf8sub(self.payload.data[text], 1, 7).."..")
		elseif faction.name == "Vortigaunt" and string.utf8len(self.payload.data[text]) > 20 then
			parent:SetText(string.utf8sub(self.payload.data[text], 1, 20).."..")
		else
			parent:SetText(self.payload.data[text])
		end
	else
		parent:SetText(string.utf8upper(text))
	end
	parent:DockMargin(0, 0, SScaleMin(13 / 3), 0)
	parent:SetFont("MenuFontNoClamp")
	parent:SetTextColor(Color(200, 200, 200, 255))
	parent:SetContentAlignment(4)
	parent:SetTextInset(padding, 0)
	parent.Paint = function(this, w, h)
		surface.SetDrawColor(Color(0, 0, 0, 100))
		surface.DrawRect(0, 0, w, h)

		surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
		surface.DrawOutlinedRect(0, 0, w, h)

		local alpha = (this:IsHovered()) and 255 or 100
		surface.SetDrawColor(ColorAlpha(color_white, alpha))
		surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/combodownarrow.png"))
		surface.DrawTexturedRect(w - SScaleMin(9 / 3) - padding, h * 0.5 - SScaleMin(5 / 3) * 0.5, SScaleMin(9 / 3), SScaleMin(5 / 3))
	end

	local savedText = parent:GetText()

	parent.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
		savedText = parent:GetText()
		parent:SetText(string.utf8upper(text))
	end

	parent.OnCursorExited = function()
		parent:SetText(string.utf8upper(savedText))
	end

	parent.DoClick = function()
		if text == "couleur des yeux" and (self.payload.faction == FACTION_CITIZEN or self.payload.faction == FACTION_ADMIN or self.payload.faction == FACTION_WORKERS or self.payload.faction == FACTION_MEDICAL) then
			if self.characterModel.Entity:LookupBone("ValveBiped.Bip01_Head1") then
				local eyepos = self.characterModel.Entity:GetBonePosition( self.characterModel.Entity:LookupBone("ValveBiped.Bip01_Head1") )
				if eyepos then
					self.characterModel:SetLookAt(eyepos)

					self.characterModel:SetCamPos(eyepos-Vector(-12, -12, 0))	-- Move cam in front of eyes
					self.characterModel:SetFOV(34)
				end
			end
		else
			self:ResetModelCam()
		end

		surface.PlaySound("helix/ui/press.wav")
		if IsValid(self.dropdownMenu) then
			self.dropdownMenu:Remove()
			return
		end

		self.dropdownMenu = self.panelCreation:Add("DScrollPanel")

		if #selections < 8 then
			self.dropdownMenu:SetSize( SScaleMin(width / 3), #selections * (SScaleMin(36 / 3) / 2) - (#selections * 1) )
		else
			self.dropdownMenu:SetSize( SScaleMin(width / 3), (SScaleMin(36 / 3) / 2 ) * 8 - (#selections * 1) )
		end

		self.dropdownMenu:SetPos(self.panelCreation:ScreenToLocal( parent:LocalToScreen( 0, SScaleMin(36 / 3) ) ))

		self.dropdownMenu.Paint = function(_, w, h)
			surface.SetDrawColor(Color(0, 0, 0, 100))
			surface.DrawRect(0, 0, w, h)

			surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
			surface.DrawOutlinedRect(0, 0, w, h)
		end

		for _, v in pairs(selections) do
			local selectionButton = self.dropdownMenu:Add("DButton")
			selectionButton:Dock(TOP)
			selectionButton:SetTall( SScaleMin(36 / 3) / 2 )
			selectionButton:SetText(string.utf8upper(v))
			selectionButton:DockMargin(0, 0 - SScaleMin(1 / 3), 0, 0)
			selectionButton:SetContentAlignment(4)
			selectionButton:SetTextInset(padding, 0)
			selectionButton:SetFont("WNBackFontNoClamp")

			if text == "langues" then
				local languageText = v != "none" and ix.languages:FindByID(v).name or v
				selectionButton:SetText(string.utf8upper(languageText))
			end

			selectionButton.Paint = function(_, w, h)
				surface.SetDrawColor(Color(0, 0, 0, 100))
				surface.DrawRect(0, 0, w, h)

				surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
				surface.DrawRect(0, 0, w, h)
			end

			selectionButton.DoClick = function()
				surface.PlaySound("helix/ui/press.wav")

				self.payload.data[text] = selectionButton:GetText() or ""

				if text == "couleur des yeux" then
					local eyeColorTable = self:GetActiveSkinEyeColorTable()

					self.characterModel.Entity:SetSkin(eyeColorTable[1] or 0)
					self.payload.data["skin"] = eyeColorTable[1]
				end

				if text == "langues" and v != "none" then
					self.payload.data["languages"] = {v}
				end

				if string.utf8len(selectionButton:GetText()) > 7 and faction.name != "Vortigaunt" then
					parent:SetText(string.utf8sub(selectionButton:GetText(), 1, 7).."..")
				elseif faction.name == "Vortigaunt" and string.utf8len(selectionButton:GetText()) > 20 then
					parent:SetText(string.utf8sub(selectionButton:GetText(), 1, 20).."..")
				else
					parent:SetText(selectionButton:GetText())
				end

				if IsValid(self.dropdownMenu) then
					self.dropdownMenu:Remove()
				end

				self:CheckIfFinished()
			end
		end

		self:CheckIfFinished()
	end
end

-- A function to create a important text panel in the right side menu
function PANEL:CreateRightMenuYellowTextPanel(text, topMargin)
	local textPanel = self.rightCreation:Add("Panel")
	textPanel:Dock(TOP)
	textPanel:SetTall(margin)
	textPanel:DockMargin(0, SScaleMin(topMargin / 3), 0, padding)

	local warningIcon = textPanel:Add("DImage")
	warningIcon:SetSize(SScaleMin(12 / 3), margin)
	warningIcon:Dock(LEFT)
	warningIcon:DockMargin(0, 0, SScaleMin(8 / 3), 0)
	warningIcon:SetImage("willardnetworks/mainmenu/charcreation/warning.png")

	local panelText = textPanel:Add("DLabel")
	panelText:SetText(text)
	panelText:SetFont("WNBackFontNoClamp")
	panelText:SizeToContents()
	panelText:SetTextColor(Color(255, 204, 0, 255))
	panelText:Dock(LEFT)
	panelText:SetContentAlignment(4)

	return panelText
end

-- A function to create the text next/back/finish buttons at the bottom of the right side menu
function PANEL:CreateNextBackFinishButtons(parentBack, parentNext, parentFinish, boolNext)
	local function Paint(_, w, h)
		surface.SetDrawColor(Color(0, 0, 0, 100))
		surface.DrawRect(0, 0, w, h)

		surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
		surface.DrawOutlinedRect(0, 0, w, h)
	end

	parentBack:Dock(LEFT)
	parentBack:SetWide(SScaleMin(100 / 3))
	parentBack:SetText(string.utf8upper("retour"))
	parentBack:SetContentAlignment(6)
	parentBack:SetTextInset(padding, 0)
	parentBack:SetFont("MenuFontNoClamp")
	parentBack.Paint = function(this, w, h)
		Paint(this, w, h)

		surface.SetDrawColor(color_white)
		surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/leftarrow.png"))
		surface.DrawTexturedRect(padding, h * 0.5 - SScaleMin(36 / 3) * 0.5, SScaleMin(7 / 3), SScaleMin(36 / 3))
	end

	parentBack.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
	end

	parentBack.DoClick = function()
		self.progress:DecrementProgress()
		ix.panelCreationActive = false
		ix.gui.mapsceneActive = nil
		ix.gui.blackBarBottom:ColorTo( Color(0, 0, 0, 0), 0, 0 )
		ix.gui.blackBarTop:ColorTo( Color(0, 0, 0, 0), 0, 0 )
		ix.gui.blackBarTop:SetVisible(false)
		ix.gui.blackBarBottom:SetVisible(false)

		if (self.WhitelistCount == 1) then
			self.factionBack:DoClick()
		else
			self:SetActiveSubpanel("faction")
		end

		self:ResetModelCam()
	end

	parentNext:Dock(LEFT)
	parentNext:DockMargin(padding, 0, 0, 0)
	parentNext:SetWide(SScaleMin(100 / 3))
	parentNext:SetText(string.utf8upper("suivant"))
	parentNext:SetContentAlignment(4)
	parentNext:SetTextInset(padding, 0)
	parentNext:SetFont("MenuFontNoClamp")
	parentNext.Paint = function(this, w, h)
		if isbool(boolNext) and boolNext == false then
			parentNext:SetTextColor(Color(255, 255, 255, 30))
			surface.SetDrawColor(255, 255, 255, 5)
			surface.DrawRect(0, 0, w, h)

			surface.SetDrawColor(255, 255, 255, 30)
			surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/rightarrow.png"))
			surface.DrawTexturedRect(w - SScaleMin(7 / 3) - padding, h * 0.5 - SScaleMin(36 / 3) * 0.5, SScaleMin(7 / 3), SScaleMin(36 / 3))

			return
		else
			Paint(this, w, h)
		end

		surface.SetDrawColor(color_white)
		surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/rightarrow.png"))
		surface.DrawTexturedRect(w - SScaleMin(7 / 3) - padding, h * 0.5 - SScaleMin(36 / 3) * 0.5, SScaleMin(7 / 3), SScaleMin(36 / 3))
	end

	parentNext.OnCursorEntered = function()
		if boolNext then
			return
		end

		surface.PlaySound("helix/ui/rollover.wav")
	end

	parentFinish:Dock(LEFT)
	parentFinish:DockMargin(padding, 0, 0, 0)
	parentFinish:SetWide(SScaleMin(100 / 3))
	parentFinish:SetTextColor(Color(255, 255, 255, 30))
	parentFinish:SetText(string.utf8upper("terminer"))
	parentFinish:SetContentAlignment(4)
	parentFinish:SetTextInset(padding, 0)
	parentFinish:SetFont("MenuFontNoClamp")
	parentFinish.Paint = function(_, w, h)
		self:DrawFinishButtonNonAvailable(w, h)
	end
end

-- A function to create a the character button in the left side menu
function PANEL:CreateCharacterButton()
	self.characterButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.characterButton, "identité")
	self.characterButton.DoClick = function()
		self:ClearSelectedMainButtons()
		self:SetButtonSelected(self.characterButton, "identité", true)
		if ix.panelCreationActive == true then
			surface.PlaySound(table.Random(self.randomClickSounds))
		end

		self:CreateRightMenuTextPanel(self.faction:GetNoGender(LocalPlayer()) != true and "nom/sexe" or "nom", 60)

		-- Name
		local nameGenderPanel = self.rightCreation:Add("DTextEntry")
		self:CreateRightMenuTextEntry(nameGenderPanel, "Entrer votre nom ici...", 36, false, 35, "name")

		if self.faction:GetNoGender(LocalPlayer()) != true then
			-- Gender
			self.genderButtonFemale = nameGenderPanel:Add("DImageButton")
			self:CreateGenderButton(self.genderButtonFemale, "willardnetworks/mainmenu/charcreation/female.png", 13, 36, 10, "female")

			self.genderButtonMale = nameGenderPanel:Add("DImageButton")
			self:CreateGenderButton(self.genderButtonMale, "willardnetworks/mainmenu/charcreation/male.png", 16, 36, 5, "male")
		end

		local minLength = ix.config.Get("minNameLength", 4)
		local maxLength = ix.config.Get("maxNameLength", 32)

		local namewarning = self:CreateRightMenuYellowTextPanel("Votre nom doit avoir un minimum de "..minLength.." caractère ("..string.len(self.payload.name or "").." / "..maxLength..")", -1)

		nameGenderPanel.OnTextChanged = function(this)
			self.payload:Set("name", this:GetValue())
			self:CheckIfFinished()

			namewarning:SetText("Votre nom doit avoir un minimum de "..minLength.." caractère ("..string.len(this:GetValue() or "").." / "..maxLength..")")
			namewarning:SizeToContents()
		end

		if self.faction:GetNoGenetics(LocalPlayer()) != true then
			-- Genetics
			self:CreateRightMenuTextPanel("Description Génétique", 10)

			local comboBoxPanel = self.rightCreation:Add("Panel")
			comboBoxPanel:Dock(TOP)
			comboBoxPanel:SetTall(SScaleMin(36 / 3))

			local ageComboBox = comboBoxPanel:Add("DButton")
			if self.faction.name == "Vortigaunt" then
				self:CreateSelectionMenu(ageComboBox, 148, "age", {"jeune (0 - 100)", "jeune adulte (100 - 500)", "adulte (500 - 1000)", "sage (1000 - 1500)", "ancien (1500 - 2000)"})
			else
				self:CreateSelectionMenu(ageComboBox, 100, "age", {"~20 ans", "~30 ans", "~40 ans", "~50 ans"})
			end

			local heightComboBox = comboBoxPanel:Add("DButton")

			if self.faction.name == "Protection Civile" then
				self:CreateSelectionMenu(heightComboBox, 90, "height", {"~1m65", "~1m70", "~1m75", "~1m80", "~1m85", "~1m90"})
			elseif self.faction.name == "Vortigaunt" then
				self:CreateSelectionMenu(heightComboBox, 148, "height", {"~1m65", "~1m70", "~1m75", "~1m80", "~1m85", "~1m90", "~1m95", "~2m"})
			else
				self:CreateSelectionMenu(heightComboBox, 90, "height", {"~1m65", "~1m70", "~1m75", "~1m80", "~1m85", "~1m90"})
			end

			local eyeColorBox = comboBoxPanel:Add("DButton")
			if self.faction.name == "Vortigaunt" then
				self:CreateSelectionMenu(eyeColorBox, 146, "couleur des yeux", {"rouge", "jaune", "orange"})
			else
				self:CreateSelectionMenu(eyeColorBox, 110, "couleur des yeux", {"bleus", "verts", "marrons", "noisettes", "ambres", "gris"})
			end

			self:CreateRightMenuYellowTextPanel("Les valeurs de description génétique restent permanentes.", 10)
		end

		if self.faction.name != "Overwatch AI" then
			local languages = {}
			if (ix.languages) then
				for _, v in pairs(ix.languages.stored) do
					if (!v.notSelectable) then
						table.insert(languages, v.uniqueID)
					end
				end
			end

			table.insert(languages, "none")

			self:CreateRightMenuTextPanel("seconde langue", 10)

			local languageBoxPanel = self.rightCreation:Add("Panel")
			languageBoxPanel:Dock(TOP)
			languageBoxPanel:SetTall(SScaleMin(36 / 3))

			local languageComboBox = languageBoxPanel:Add("DButton")
			self:CreateSelectionMenu(languageComboBox, 110, "langues", languages)
		end

		-- Description
		self:CreateRightMenuTextPanel("description physique", 20)
		local charDescPanel = self.rightCreation:Add("DTextEntry")
		self:CreateRightMenuTextEntry(charDescPanel, "Décrivez ici l'apparence physique de votre personnage...", 130, true, 1000, "desc")

		local minDescLength = ix.config.Get("minDescriptionLength", 16)
		local maxDescLength = ix.config.Get("maxDescriptionLength", 512)
		local descLength = self:CreateRightMenuYellowTextPanel("Votre description doit avoir un minimum de "..minDescLength.." caractères ("..string.len(self.payload.description or "").." / "..maxDescLength..")", -1)

		charDescPanel.OnTextChanged = function(this)
			self.payload:Set("description", this:GetValue())
			self:CheckIfFinished()

			descLength:SetText("Votre description doit avoir un minimum de "..minDescLength.." caractères ("..string.len(this:GetValue()).." / "..maxDescLength..")")
			descLength:SizeToContents()
		end

		self:CreateFinishPanel(false, self.appearancesButton)
	end
end

-- A function to refresh what skins a model has depending on gender etc.
function PANEL:RefreshSkins()
	if !table.IsEmpty(self.skinButtonList) then
		table.Empty(self.skinButtonList)
	end

	if !table.IsEmpty(self.glassesButtonList) then
		table.Empty(self.glassesButtonList)
	end

	for _, v in pairs(self.skinButtonPanel:GetChildren()) do
		v:Remove()
	end

	if self.glassesButtonPanel and IsValid(self.glassesButtonPanel) then
		for _, v in pairs(self.glassesButtonPanel:GetChildren()) do
			v:Remove()
		end
	end

	local eyeColorTable = self:GetActiveSkinEyeColorTable()

	for k, v in pairs(eyeColorTable) do
		local skinButton = self.skinButtonPanel:Add("DButton")
		skinButton:Dock(LEFT)
		skinButton:SetWide(math.Round(self.rightCreation:GetWide() / (#eyeColorTable)) - padding)
		skinButton:DockMargin(0, 0, padding, 0)
		skinButton:SetText(k)
		skinButton:SetFont("MenuFontNoClamp")
		skinButton.name = k

		table.insert(self.skinButtonList, skinButton)

		if self.payload.data["skin"] == v then
			self:SetButtonSelected(skinButton, k, false)
		else
			skinButton.Paint = function(selfSkin, w, h)
				surface.SetDrawColor(Color(0, 0, 0, 100))
				surface.DrawRect(0, 0, w, h)

				surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
				surface.DrawOutlinedRect(0, 0, w, h)
			end
		end

		skinButton.OnCursorEntered = function()
			surface.PlaySound("helix/ui/rollover.wav")
		end

		skinButton.DoClick = function()
			self:ClearSelectedSkins(self.skinButtonList)
			self:SetButtonSelected(skinButton, k, false)
			surface.PlaySound("helix/ui/press.wav")
			self.payload.data["skin"] = v
			self.characterModel.Entity:SetSkin(v)
			if (self.payload.faction == FACTION_CITIZEN or self.payload.faction == FACTION_ADMIN or self.payload.faction == FACTION_WORKERS or self.payload.faction == FACTION_MEDICAL) then
				local bone = self.characterModel.Entity:LookupBone("ValveBiped.Bip01_Head1")
				if (bone) then
					local eyepos = self.characterModel.Entity:GetBonePosition(bone)
					self.characterModel:SetLookAt(eyepos)

					self.characterModel:SetCamPos(eyepos-Vector(-12, -12, 0))	-- Move cam in front of eyes
					self.characterModel:SetFOV(34)
				end
			end
		end
	end

	if self.glassesButtonPanel and IsValid(self.glassesButtonPanel) then
		for i = 1, 2 do
			local glassesButton = self.glassesButtonPanel:Add("DButton")
			glassesButton:Dock(LEFT)
			if i == 1 then
				glassesButton:SetText("NON")
			else
				glassesButton:SetText("OUI")
			end
			glassesButton:SetWide((math.Round(self.rightCreation:GetWide() / 2) - padding))
			glassesButton:DockMargin(0, 0, padding, 0)
			glassesButton:SetFont("MenuFontNoClamp")
			glassesButton.name = glassesButton:GetText()

			table.insert(self.glassesButtonList, glassesButton)

			if self.payload.data.glasses == true and i == 2 then
				self:SetButtonSelected(glassesButton, "OUI", false)
			elseif self.payload.data.glasses == false and i == 1 then
				self:SetButtonSelected(glassesButton, "NON", false)
			else
				glassesButton.Paint = function(selfSkin, w, h)
					surface.SetDrawColor(Color(0, 0, 0, 100))
					surface.DrawRect(0, 0, w, h)

					surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
					surface.DrawOutlinedRect(0, 0, w, h)
				end
			end

			glassesButton.OnCursorEntered = function()
				surface.PlaySound("helix/ui/rollover.wav")
			end

			glassesButton.DoClick = function()
				for _, v in pairs(self.glassesButtonList) do
					v.Paint = function(this, w, h)
						self:DrawButtonUnselected(v.name, this, w, h, false)
					end
				end

				self:SetButtonSelected(glassesButton, glassesButton.name, false)
				surface.PlaySound("helix/ui/press.wav")
				if i == 2 then
					self.payload.data["glasses"] = true
					self.characterModel.Entity:SetBodygroup(8, 1)
					self.payload.data.chosenClothes["8"] = 1
				else
					self.payload.data["glasses"] = false
					self.characterModel.Entity:SetBodygroup(8, 0)
					self.payload.data.chosenClothes["8"] = 0
				end

				self:ResetModelCam()
			end
		end
	end
end

function PANEL:RefreshBeards()
	if !table.IsEmpty(self.beardButtonList) then
		table.Empty(self.beardButtonList)
	end

	if self.payload.gender == "male" then
		for _, v in pairs(self.beardButtonPanel:GetChildren()) do
			v:Remove()
		end
	end

	if self.payload.gender == "male" then
		for i = 0, 8 do
			local beardButton = self.beardButtonPanel:Add("DButton")
			beardButton:Dock(LEFT)
			if i == 0 then
				beardButton:SetText("AUCUNE BARBE")
				beardButton:SetWide((math.Round(self.rightCreation:GetWide() / 9) * 2) - padding)
			else
				beardButton:SetText(i + 1)
				beardButton:SetWide(math.Round(self.rightCreation:GetWide() / 10) - padding)
			end
			beardButton:DockMargin(0, 0, padding, 0)
			beardButton:SetFont("MenuFontNoClamp")
			beardButton.name = i

			table.insert(self.beardButtonList, beardButton)

			if self.payload.data.groups[self.beardBodygroups] == i then
				self:SetButtonSelected(beardButton, i, false)
			else
				beardButton.Paint = function(selfSkin, w, h)
					surface.SetDrawColor(Color(0, 0, 0, 100))
					surface.DrawRect(0, 0, w, h)

					surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
					surface.DrawOutlinedRect(0, 0, w, h)
				end
			end

			beardButton.OnCursorEntered = function()
				surface.PlaySound("helix/ui/rollover.wav")
			end

			beardButton.DoClick = function()
				for _, v in pairs(self.beardButtonList) do
					v.Paint = function(this, w, h)
						self:DrawButtonUnselected(v.name, this, w, h, false)
					end
				end

				self:SetButtonSelected(beardButton, i, false)
				surface.PlaySound("helix/ui/press.wav")
				self.payload.data.groups[self.beardBodygroups] = i
				self.characterModel.Entity:SetBodygroup(11, i)
				if (self.payload.faction == FACTION_CITIZEN or self.payload.faction == FACTION_ADMIN or self.payload.faction == FACTION_WORKERS or self.payload.faction == FACTION_MEDICAL) then
					if self.characterModel.Entity:LookupBone("ValveBiped.Bip01_Head1") then
						local eyepos = self.characterModel.Entity:GetBonePosition( self.characterModel.Entity:LookupBone("ValveBiped.Bip01_Head1") )
						if eyepos then
							self.characterModel:SetLookAt(eyepos)

							self.characterModel:SetCamPos(eyepos-Vector(-12, -12, 0))	-- Move cam in front of eyes
							self.characterModel:SetFOV(34)
						end
					end
				end
			end
		end
	end
end

-- A function to create a button panel
function PANEL:CreateButtonPanel(parent)
	parent:Dock(TOP)
	parent:DockMargin(0, 0, 0, 0)
	parent:SetSize(self.rightCreation:GetWide(), SScaleMin(36 / 3))
end

-- A function to create the appearances button in the left side menu
function PANEL:CreateAppearancesButton()
	self.appearancesButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.appearancesButton, "apparence")

	self.appearancesButton.DoClick = function()
		local faction = ix.faction.indices[self.payload.faction]

		self:ClearSelectedMainButtons()
		self:SetButtonSelected(self.appearancesButton, "apparence", true)
		surface.PlaySound(table.Random(self.randomClickSounds))

		self:CreateRightMenuTextPanel("Selection de l'apparence", 60)

		local modelSelectionPanel = self.rightCreation:Add("DScrollPanel")
		modelSelectionPanel:Dock(TOP)

		local modelSelectionGrid = modelSelectionPanel:Add( "DGrid" )

		local iconSize = SScaleMin(94 / 3)

		if (self.rightCreation:GetWide() - (SScaleMin(94 / 3) * 6)) >= SScaleMin(94 / 3) then
			modelSelectionGrid:SetCols( 6 )
		elseif (self.rightCreation:GetWide() - (SScaleMin(94 / 3) * 7)) >= SScaleMin(94 / 3) then
			modelSelectionGrid:SetCols( 7 )
		elseif (self.rightCreation:GetWide() - (SScaleMin(94 / 3) * 8)) >= SScaleMin(94 / 3) then
			modelSelectionGrid:SetCols( 8 )
		else
			modelSelectionGrid:SetCols( 5 )
		end

		local rowCount = math.ceil(#self:GetFactionModelsGender(faction) / modelSelectionGrid:GetCols())
		modelSelectionGrid:SetColWide( rowCount > 2 and iconSize - 5 or iconSize )
		modelSelectionGrid:SetRowHeight( iconSize )

		modelSelectionPanel:SetTall(math.Clamp(rowCount, 0, 2) * iconSize)

		self.skinButtonList = {}
		self.glassesButtonList = {}
		self.canreadButtonList = {}

		for k, v in pairs(self:GetFactionModelsGender(faction)) do
			local iconbg = vgui.Create("Panel")
			iconbg:SetSize(SScaleMin(84 / 3), SScaleMin(84 / 3))
			iconbg.Paint = function(_, w, h)
				surface.SetDrawColor(Color(0, 0, 0, 100))
				surface.DrawRect(0, 0, w, h)

				surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
				surface.DrawOutlinedRect(0, 0, w, h)
			end

			local icon = iconbg:Add("SpawnIcon")
			icon:SetSize(SScaleMin(82 / 3), SScaleMin(82 / 3))
			icon:Center()
			icon:InvalidateLayout(true)

			icon.OnCursorEntered = function()
				surface.PlaySound("helix/ui/rollover.wav")
			end

			icon.DoClick = function(this)
				self:CheckForSkinCount(k)

				self.payload:Set("model", k)

				if self.payload.data.chosenClothes[self.torsoBodygroups] then
					self.characterModel.Entity:SetBodygroup(tonumber(self.torsoBodygroups), tonumber(self.payload.data.chosenClothes[self.torsoBodygroups]))
				end

				if self.payload.data.chosenClothes[self.legsBodygroups] then
					self.characterModel.Entity:SetBodygroup(tonumber(self.legsBodygroups), tonumber(self.payload.data.chosenClothes[self.legsBodygroups]))
				end

				if self.payload.data.chosenClothes[self.shoesBodygroups] then
					self.characterModel.Entity:SetBodygroup(tonumber(self.shoesBodygroups), tonumber(self.payload.data.chosenClothes[self.shoesBodygroups]))
				end

				if self.payload.data["glasses"] == true then
					self.characterModel.Entity:SetBodygroup(8, 1)
				end

				self.payload:Set("hair", {hair = 0, color = Color(244,233,230)})

				local eyeColorTable = self:GetActiveSkinEyeColorTable()

				self.characterModel.Entity:SetSkin(eyeColorTable[1] or 0)
				self.payload.data["skin"] = eyeColorTable[1]

				self.payload.data.groups[self.beardBodygroups] = 0
				self.payload.data.groups[self.hairBodygroups] = 0

				if faction:GetNoAppearances(LocalPlayer()) != true then
					self:RefreshSkins()
				end

				self:ResetModelCam()

				surface.PlaySound("helix/ui/press.wav")
			end

			icon.PaintOver = function(this, w, h)
				if (self.payload.model == k) then
					surface.SetDrawColor(255, 78, 69, 100)

					for _ = 1, 3 do
						surface.DrawOutlinedRect(1, 1, w - 2, h - 2)
					end
				end
			end

			if (isstring(v)) then
				icon:SetModel(v)
			else
				icon:SetModel(v[1], v[2] or 0, v[3])
			end

			modelSelectionGrid:AddItem( iconbg )
		end

		self:CreateRightMenuYellowTextPanel("Votre apparence est permanante alors choissisez bien", 10)

		if faction:GetNoAppearances(LocalPlayer()) != true then
			self:CreateRightMenuTextPanel((faction.index == FACTION_VORT and "skin color/wrinkles" or "facial features"), 10)

			self.skinButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(self.skinButtonPanel)

			if faction.index != FACTION_VORT then
				self:CreateRightMenuTextPanel("Avec vous besoin de lunettes?", 20)

				self.glassesButtonPanel = self.rightCreation:Add("Panel")
				self:CreateButtonPanel(self.glassesButtonPanel)

				self:CreateRightMenuYellowTextPanel("Votre vue ne seras pas flou a moins que vous l'activer dans les paramètres", 10)
				end


			self:RefreshSkins()
		end

		if !faction.ReadOptionDisabled then
			self:CreateRightMenuTextPanel("Can you read?", 5)

			local canreadButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(canreadButtonPanel)

			-- Can read

			if !table.IsEmpty(self.canreadButtonList) then
				table.Empty(self.canreadButtonList)
			end

			if self.payload.data.canread == nil then
				self.payload.data["canread"] = true
			end

			for i = 1, 2 do
				local canreadButton = canreadButtonPanel:Add("DButton")
				canreadButton:Dock(LEFT)
				if i == 1 then
					canreadButton:SetText("NO")
				else
					canreadButton:SetText("YES")
				end

				canreadButton:SetWide((math.Round(self.rightCreation:GetWide() / 2) - padding))
				canreadButton:DockMargin(0, 0, padding, 0)
				canreadButton:SetFont("MenuFontNoClamp")
				canreadButton.name = canreadButton:GetText()

				table.insert(self.canreadButtonList, canreadButton)

				if self.payload.data.canread == true and i == 2 then
					self:SetButtonSelected(canreadButton, "YES", false)
				elseif self.payload.data.canread == false and i == 1 then
					self:SetButtonSelected(canreadButton, "NO", false)
				else
					canreadButton.Paint = function(selfSkin, w, h)
						surface.SetDrawColor(Color(0, 0, 0, 100))
						surface.DrawRect(0, 0, w, h)

						surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
						surface.DrawOutlinedRect(0, 0, w, h)
					end
				end

				canreadButton.OnCursorEntered = function()
					surface.PlaySound("helix/ui/rollover.wav")
				end

				canreadButton.DoClick = function()
					for _, v in pairs(self.canreadButtonList) do
						v.Paint = function(this, w, h)
							self:DrawButtonUnselected(v.name, this, w, h, false)
						end
					end

					self:SetButtonSelected(canreadButton, canreadButton.name, false)
					surface.PlaySound("helix/ui/press.wav")
					if i == 2 then
						self.payload.data["canread"] = true
					else
						self.payload.data["canread"] = false
					end
				end
			end

			self:CreateRightMenuYellowTextPanel("Les livres, etc. les mots seront mélangés mais conserveront une sorte de lisibilité si NON", 10)
		end

		self:CreateFinishPanel(self.characterButton, self.hairButton)
	end
end

-- A helper function to create the finish panel at the bottom of the right side menu
function PANEL:CreateFinishPanel(back, next)
	local buttonPanel = self.rightCreation:Add("Panel")
	buttonPanel:Dock(TOP)
	buttonPanel:DockMargin(SScaleMin(140 / 3), margin, 0, 0)
	buttonPanel:SetTall(SScaleMin(36 / 3))

	local backButton = buttonPanel:Add("DButton")
	local nextButton = buttonPanel:Add("DButton")
	self.finishButton = buttonPanel:Add("DButton")
	self:CreateNextBackFinishButtons(backButton, nextButton, self.finishButton, next)

	if back then
		backButton.DoClick = function()
			back.DoClick()
		end
	end

	if next then
		nextButton.DoClick = function()
			next.DoClick()
		end
	end

	self:CheckIfFinished()
end

-- A function to create the buttons for the bodygroups
function PANEL:CreateBodyGroupButtons(parent, bodygroup, min, max)
	local torsoButtonList = {}
	local shoesButtonList = {}
	local trouserButtonList = {}
	self.hairButtonList = self.hairButtonList or {}

	local function ClearSelectedBodygroups(bodygroup2)
		if bodygroup2 == "torso" then
			for _, v in pairs(torsoButtonList) do
				v.Paint = function(this, w, h)
					self:DrawButtonUnselected(v.name, this, w, h, false)
				end
			end
		elseif bodygroup2 == "shoes" then
			for _, v in pairs(shoesButtonList) do
				v.Paint = function(this, w, h)
					self:DrawButtonUnselected(v.name, this, w, h, false)
				end
			end
		elseif bodygroup2 == "legs" then
			for _, v in pairs(trouserButtonList) do
				v.Paint = function(this, w, h)
					self:DrawButtonUnselected(v.name, this, w, h, false)
				end
			end
		else
			for _, v in pairs(self.hairButtonList) do
				v.Paint = function(this, w, h)
					self:DrawButtonUnselected(v.name, this, w, h, false)
				end
			end
		end
	end

	local caTorsos = {}
	local caLegs = {}
	local caShoes = {}

	for name, v in pairs(self.ccaClothingList) do
		if v.outfitCategory == "Torso" then
			caTorsos[name] = v.bg
		end

		if v.outfitCategory == "Legs" then
			caLegs[name] = v.bg
		end

		if v.outfitCategory == "Shoes" then
			caShoes[name] = v.bg
		end
	end

	local torsos = {}
	local legs = {}
	local shoes = {}

	for name, v in pairs(self.clothingList) do
		if v.outfitCategory == "Torso" then
			torsos[name] = v.bg
		end

		if v.outfitCategory == "Legs" then
			legs[name] = v.bg
		end

		if v.outfitCategory == "Shoes" then
			shoes[name] = v.bg
		end
	end

	local hairs = {}

	local gender = self.payload.gender
	for i = 0, gender == "female" and 14 or 12 do hairs[#hairs + 1] = i end

	local usedTorsoTable = torsos
	local usedLegsTable = legs
	local usedShoesTable = shoes
	local usedHairsTable = hairs

	if self.payload.faction == FACTION_ADMIN then
		usedTorsoTable = caTorsos
		usedLegsTable = caLegs
		usedShoesTable = caShoes
	end

	local activeTable = usedTorsoTable

	if bodygroup == "legs" then
		activeTable = usedLegsTable
	end

	if bodygroup == "shoes" then
		activeTable = usedShoesTable
	end

	if bodygroup == "hair" then
		activeTable = usedHairsTable
	end

	local amount = #activeTable == 0 and #table.GetKeys(activeTable) or #activeTable

	local actualAmount = amount

	local curAdd = 1

	local activeClothingTable = self.payload.faction == FACTION_ADMIN and self.ccaClothingList or self.clothingList

	for itemName, bgValue in pairs(activeTable) do
		if min or max then
			local k = itemName
			if k < min or k > max then continue end
		end

		local bodygroupButton = parent:Add("DButton")
		bodygroupButton:Dock(LEFT)
		bodygroupButton:SetWide(math.Round(self.rightCreation:GetWide() / (actualAmount - (bodygroup != "hair" and 0 or 7))) - padding)
		bodygroupButton:SetText(isstring(itemName) and curAdd or itemName or "")
		bodygroupButton:SetFont("MenuFontNoClamp")
		bodygroupButton:DockMargin(0, 0, padding, 0)
		bodygroupButton.name = bgValue

		if activeClothingTable[itemName] and activeClothingTable[itemName].uniqueID then
			bodygroupButton.item = activeClothingTable[itemName].uniqueID
		end

		if activeClothingTable[itemName] then
			if activeClothingTable[itemName].color then
				bodygroupButton.color = activeClothingTable[itemName].color
			end
		end

		if bodygroup == "torso" then
			table.insert(torsoButtonList, bodygroupButton)
		elseif bodygroup == "shoes" then
			table.insert(shoesButtonList, bodygroupButton)
		elseif bodygroup == "legs" then
			table.insert(trouserButtonList, bodygroupButton)
		else
			table.insert(self.hairButtonList, bodygroupButton)
		end

		bodygroupButton.Paint = function(_, w, h)
			surface.SetDrawColor(Color(0, 0, 0, 100))
			surface.DrawRect(0, 0, w, h)

			surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
			surface.DrawOutlinedRect(0, 0, w, h)
		end

		local selectionTable = {"torso", "legs", "shoes", "hair"}

		for _, v2 in pairs(selectionTable) do
			if v2 != "hair" then
				if self.payload.data.chosenClothes then
					if self.payload.data.chosenClothes[v2] then
						if self.payload.data.chosenClothes[v2] == bodygroupButton.item then
							self:SetButtonSelected(bodygroupButton, bgValue, false)
						end
					end
				end
			end

			if v2 == "hair" and self.payload.hair and self.payload.hair.hair then
				if bgValue == self.payload.hair.hair then
					self:SetButtonSelected(bodygroupButton, bgValue, false)
				end
			end
		end

		bodygroupButton.OnCursorEntered = function()
			surface.PlaySound("helix/ui/rollover.wav")
		end

		bodygroupButton.DoClick = function()
			surface.PlaySound("helix/ui/press.wav")
			ClearSelectedBodygroups(bodygroup)
			self:SetButtonSelected(bodygroupButton, bgValue, false)

			if bodygroup != "hair" then
				self.characterModel.Entity:SetBodygroup(tonumber(self[bodygroup.."Bodygroups"]), bgValue)
				self.payload.data.chosenClothes[tonumber(self[bodygroup.."Bodygroups"])] = bgValue

				self.payload.data.chosenClothes[bodygroup] = activeClothingTable[itemName].uniqueID

				if !self.payload.data.chosenClothes.color then self.payload.data.chosenClothes.color = {} end
				table.Merge(self.payload.data.chosenClothes.color, bodygroupButton.color)

				for name, color in pairs(self.payload.data.chosenClothes.color) do
					self.characterModel.overrideProxyColors[name] = color
				end
			else
				self.payload:Set("hair", {hair = bgValue, color = self.payload.hair.color})
				self.payload.data.groups[self.hairBodygroups] = bgValue
				self.characterModel.Entity:SetBodygroup(self.characterModel.Entity:FindBodygroupByName("hair"), bgValue)
			end

			self:ResetModelCam()

			if bodygroup == "shoes" then
				local footpos = self.characterModel.Entity:GetBonePosition( self.characterModel.Entity:LookupBone("ValveBiped.Bip01_L_Foot") )

				if footpos then
					if self.payload.gender == "female" then
						footpos:Add(Vector(2, 0, 5))	-- Move right slightly
					else
						footpos:Add(Vector(4, 0, 5))	-- Move right slightly
					end

					self.characterModel:SetLookAt(footpos)

					self.characterModel:SetCamPos(footpos-Vector(-12, -12, 0))	-- Move cam in front of feet
					self.characterModel:SetFOV(54)
				end
			end
		end

		curAdd = curAdd + 1
	end
end

-- A function to create the hair button on the left side menu
function PANEL:CreateHairButton()
	self.hairButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.hairButton, "cheveux")
	self.hairButton.DoClick = function()
		self.beardButtonList = {}
		self:ResetModelCam()

		self:ClearSelectedMainButtons()
		self:SetButtonSelected(self.hairButton, "cheveux", true)

		surface.PlaySound(table.Random(self.randomClickSounds))

		if self.faction and self.faction.noHair then
			self:CreateRightMenuTextPanel("This faction does not allow for hair!", 60)
			return
		end

		self:CreateRightMenuTextPanel("Selection des cheveux", 60)

		if self.hairButtonList then self.hairButtonList = {} end

		local hairButtonPanel = self.rightCreation:Add("Panel")
		self:CreateButtonPanel(hairButtonPanel)
		self:CreateBodyGroupButtons(hairButtonPanel, "hair", 1, 8)

		local hairButtonPanel2 = self.rightCreation:Add("Panel")
		self:CreateButtonPanel(hairButtonPanel2)
		hairButtonPanel2:DockMargin(0, padding, 0, 0)
		self:CreateBodyGroupButtons(hairButtonPanel2, "hair", 9, 15)

		if self.payload.gender == "male" and self.faction.index != FACTION_VORT then
			self:CreateRightMenuTextPanel("beard", 20)
			self.beardButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(self.beardButtonPanel)

			self:RefreshBeards()
		end

		local chooseColorText = self:CreateRightMenuTextPanel("Choissisez la couleur", 30)
		chooseColorText:SetFont("LargerTitlesFontNoClamp")
		chooseColorText:SetTextColor(Color(255, 204, 0, 255))
		chooseColorText:SizeToContents()

		local colorButtonList = {}

		for name, tColors in pairs(ix.allowedHairColors) do
			self:CreateRightMenuTextPanel(name, 15)

			local colorButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(colorButtonPanel, 0)

			for _, color in pairs(tColors) do
				local colorButton = colorButtonPanel:Add("DButton")
				colorButton:Dock(LEFT)
				colorButton:SetWide(math.Round(self.rightCreation:GetWide() / 8 - padding))
				colorButton:SetText("")
				colorButton:DockMargin(0, 0, padding, 0)
				colorButton.color = color

				colorButton.Paint = function(_, w, h)
					surface.SetDrawColor(color)
					surface.DrawRect(0, 0, w, h)

					surface.SetDrawColor(self.payload.hair.color == color and Color(255, 204, 0, 255) or Color(111, 111, 136, (255 / 100 * 30)))
					surface.DrawOutlinedRect(0, 0, w, h)
				end

				colorButton.DoClick = function()
					if self.characterModel and IsValid(self.characterModel) then
						if !self.characterModel.overrideProxyColors then self.characterModel.overrideProxyColors = {} end

						self.characterModel.overrideProxyColors["HairColor"] = Vector(color.r / 255, color.g / 255, color.b / 255)
					end

					for _, v in pairs(colorButtonList) do
						v.Paint = function(this, w, h)
							surface.SetDrawColor(v.color)
							surface.DrawRect(0, 0, w, h)

							surface.SetDrawColor(v == colorButton and Color(255, 204, 0, 255) or Color(111, 111, 136, (255 / 100 * 30)))
							surface.DrawOutlinedRect(0, 0, w, h)
						end
					end

					self.payload:Set("hair", {hair = self.payload.hair.hair, color = color})
				end

				colorButtonList[#colorButtonList + 1] = colorButton
			end
		end

		self:CreateFinishPanel(self.appearancesButton, self.faceButton)
	end
end

-- A function to create the clothing button on the left side menu
function PANEL:CreateFaceButton()
	self.faceButton = self.leftCreation:Add("DButton")
	self:CreateMainButton(self.faceButton, "vêtements")
	self.faceButton.DoClick = function()
		self:ResetModelCam()

		self:ClearSelectedMainButtons()
		self:SetButtonSelected(self.faceButton, "vêtements", true)

		surface.PlaySound(table.Random(self.randomClickSounds))

		if self.faction:GetNoAppearances(LocalPlayer()) != true and self.faction.index != FACTION_VORT then
			self:CreateRightMenuTextPanel("veste", 60)

			local jacketButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(jacketButtonPanel)
			self:CreateBodyGroupButtons(jacketButtonPanel, "torso")

			self:CreateRightMenuTextPanel("pantalon", 30)

			local trouserButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(trouserButtonPanel)
			self:CreateBodyGroupButtons(trouserButtonPanel, "legs")

			self:CreateRightMenuTextPanel("chaussures", 30)

			local shoesButtonPanel = self.rightCreation:Add("Panel")
			self:CreateButtonPanel(shoesButtonPanel)
			self:CreateBodyGroupButtons(shoesButtonPanel, "shoes")

			self:CreateRightMenuYellowTextPanel("D'autre vêtements peuvent être acheter dans des magasins", 10)
		else
			self:CreateRightMenuTextPanel("Appearances", 60)

			local noAppearances = self.rightCreation:Add("Panel")
			noAppearances:Dock(TOP)
			noAppearances:DockMargin(0, 0 - SScaleMin(1 / 3), 0, 0)
			noAppearances:SetTall(SScaleMin(140 / 3))
			noAppearances.Paint = function(_, w, h)
				surface.SetDrawColor(Color(0, 0, 0, 100))
				surface.DrawRect(0, 0, w, h)

				surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
				surface.DrawOutlinedRect(0, 0, w, h)
			end

			local noAppearancesAvailable = noAppearances:Add("DLabel")
			noAppearancesAvailable:Dock(FILL)
			noAppearancesAvailable:SetFont("MenuFontNoClamp")
			noAppearancesAvailable:SetText("No Clothing Selection Available for this faction")
			noAppearancesAvailable:SetContentAlignment(5)
		end

		self:CreateFinishPanel(self.hairButton, self.attributesButton)
	end
end

-- A function to create a background selection panel
function PANEL:CreateBackgroundSelectionPanels(icon, iconW, iconH, title, desc, minusMargin, difficultyText)
	iconW = SScaleMin(iconW / 3)
	iconH = SScaleMin(iconH / 3)

	local backgroundPanel = self.rightCreation:Add("DSizeToContents")
	backgroundPanel:Dock(TOP)
	backgroundPanel:DockPadding(SScaleMin(90 / 3), padding, padding, SScaleMin(15 / 3))
	backgroundPanel:DockMargin(0, 0 - SScaleMin(1 / 3), 0, 0)
	backgroundPanel:SetSizeX( false )
	backgroundPanel:InvalidateLayout()
	backgroundPanel.Paint = function(_, w, h)
		surface.SetDrawColor(Color(0, 0, 0, 100))
		surface.DrawRect(0, 0, w, h)

		surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
		surface.DrawOutlinedRect(0, 0, w, h)

		surface.SetDrawColor(color_white)
		surface.SetMaterial(Material(icon))
		surface.DrawTexturedRect(SScaleMin(90 / 3) * 0.5 - iconW * 0.5, h * 0.5 - iconH * 0.5, iconW, iconH)
	end

	local textPanel = backgroundPanel:Add("DSizeToContents")
	textPanel:Dock(TOP)
	textPanel:SetSizeX( false )

	local titleText = textPanel:Add("DLabel")
	titleText:SetText(title)
	titleText:SetFont("LargerTitlesFontNoClamp")
	titleText:SizeToContents()
	titleText:Dock(TOP)
	titleText:SetTextColor(Color(255, 204, 0, 255))

	local descText = textPanel:Add("DLabel")
	descText:SetText(desc)
	descText:SetFont("MenuFontNoClamp")
	descText:SetWrap(true)
	descText:SetAutoStretchVertical(true)
	descText:Dock(TOP)

	if difficultyText then
		local textDifficulty = textPanel:Add("DLabel")
		textDifficulty:Dock(TOP)
		textDifficulty:SetText(difficultyText)
		textDifficulty:SetFont("MenuFontNoClamp")
		textDifficulty:SetWrap(true)
		textDifficulty:SetAutoStretchVertical(true)
		textDifficulty:DockMargin(0, padding, 0, 0)

		if string.match(difficultyText, "Hard") then
			textDifficulty:SetTextColor(Color(255, 78, 69, 255))
		elseif string.match(difficultyText, "This background starts with no CID.") then
			textDifficulty:SetTextColor(Color(236, 218, 101, 255))
		else
			textDifficulty:SetTextColor(Color(101, 235, 130, 255))
		end
	end

	local function PaintSelected(w, h)
		local color = ix.config.Get("color", color_white)

		surface.SetDrawColor(color.r, color.g, color.b, 200)
		for i = 1, 2 do
			local i2 = i * 2
			surface.DrawOutlinedRect(i, i, w - i2, h - i2)
		end
	end

	local buttonCover = self.rightCreation:Add("DButton")
	buttonCover:Dock(TOP)
	buttonCover.PerformLayout = function()
		buttonCover:SetWide(backgroundPanel:GetWide())
		buttonCover:SetTall(backgroundPanel:GetTall())
		buttonCover:DockMargin(0, 0 - backgroundPanel:GetTall(), 0, 0)
	end

	buttonCover:SetSize(SScaleMin(100 / 3), SScaleMin(100 / 3))

	buttonCover.Paint = function(selfButton, w, h)
		if self.payload.data["background"] == title then
			PaintSelected(w, h)
		end
	end
	buttonCover:SetText("")

	table.insert(self.backgroundButtonList, buttonCover)

	buttonCover.OnCursorEntered = function()
		surface.PlaySound("helix/ui/rollover.wav")
	end

	buttonCover.DoClick = function()
		self.payload.data["background"] = title

		surface.PlaySound("helix/ui/press.wav")
		for _, v in pairs(self.backgroundButtonList) do
			v.Paint = nil
		end

		buttonCover.Paint = function(_, w, h)
			PaintSelected(w, h)
		end

		self:CheckIfFinished()
	end
end

-- Util Functions
function PANEL:AttributesRefresh(attribute, number, bSkill)
	bSkill = bSkill or false
	if !bSkill then
		self.payload.special[attribute] = number
	else
		self.payload.skill[attribute] = number
	end

	self.attributesRemaining:SetText(self:GetPointsLeft(bSkill)..string.utf8upper(" points restants"))
	self.attributesRemaining:SizeToContents()
end

function PANEL:GetPointsSpend(bSkill)
	local pointsSpend = 0
	if !bSkill then
		for _, v in pairs(self.payload.special) do
			pointsSpend = pointsSpend + v
		end
	else
		for _, v in pairs(self.payload.skill) do
			pointsSpend = pointsSpend + v
		end
	end

	return pointsSpend
end

function PANEL:GetPointsLeft(bSkill)
	return self:GetMaxAttributePoints(bSkill) - self:GetPointsSpend(bSkill)
end


function PANEL:GetFactionModelsGender(faction)
	if self.payload.gender == "male" and faction:GetModelsMale(LocalPlayer()) then
		return faction:GetModelsMale(LocalPlayer())
	elseif self.payload.gender == "female" and faction:GetModelsFemale(LocalPlayer()) then
		return faction:GetModelsFemale(LocalPlayer())
	else
		return faction:GetModels(LocalPlayer())
	end
end

function PANEL:ClearSelectedSkins()
	for _, v in pairs(self.skinButtonList) do
		v.Paint = function(this, w, h)
			self:DrawButtonUnselected(v.name, this, w, h, false)
		end
	end
end

function PANEL:CheckForSkinCount(k)
	for _, v2 in pairs(self.skinButtonList) do
		if v2.name == 1 then
			self:SetButtonSelected(v2, k, false)
		end
	end
end

function PANEL:GetActiveSkinEyeColorTable()
	local entityModel = self.characterModel.Entity:GetModel()

	local vortEyeRedSkins = { 0, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56 }
	local vortEyeYellowSkins = { 4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59 }
	local vortEyeOrangeSkins = { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 }

	if (string.match(entityModel, "vortigaunt")) then
		local activeEyeColor = vortEyeRedSkins

		if self.payload.data["couleur des yeux"] == "JAUNE" then
			activeEyeColor = vortEyeYellowSkins
		end

		if self.payload.data["couleur des yeux"] == "ORANGE" then
			activeEyeColor = vortEyeOrangeSkins
		end

		return activeEyeColor
	end

	local eyeColorBrownSkins = { 0, 1, 2, 3, 4 }
	local eyeColorBlueSkins = { 5, 6, 7, 8, 9 }
	local eyeColorGreenSkins = { 10, 11, 12, 13, 14 }

	if (string.match(entityModel, "/male02")) then
		eyeColorBrownSkins = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }
		eyeColorBlueSkins = { 9, 10, 11, 12, 13, 14, 15, 16, 17 }
		eyeColorGreenSkins = { 18, 19, 20, 21, 22, 23, 24, 25, 26 }
	end

	if (string.match(entityModel, "/male06")) then
		eyeColorBrownSkins = { 0, 1, 2, 3, 4, 5 }
		eyeColorBlueSkins = { 6, 7, 8, 9, 10, 11 }
		eyeColorGreenSkins = { 12, 13, 14, 15, 16, 17 }
	end

	if (string.match(entityModel, "/male07")) then
		eyeColorBrownSkins = { 0, 1, 2, 3, 4, 5, 6 }
		eyeColorBlueSkins = { 7, 8, 9, 10, 11, 12, 13 }
		eyeColorGreenSkins = { 14, 15, 16, 17, 18, 19, 20 }
	end

	if (string.match(entityModel, "/male10")) then
		eyeColorBrownSkins = { 0 }
		eyeColorBlueSkins = { 1 }
		eyeColorGreenSkins = { 2 }
	end

	if (string.match(entityModel, "/female_03")) then
		eyeColorBrownSkins = { 0, 1, 2, 3 }
		eyeColorBlueSkins = { 4, 5, 6, 7 }
		eyeColorGreenSkins = { 8, 9, 10, 11 }
	end

	local activeEyeColor = eyeColorBrownSkins

	if self.payload.data["couleur des yeux"] == "BLEUS" or self.payload.data["couleur des yeux"] == "GRIS" then
		activeEyeColor = eyeColorBlueSkins
	end

	if self.payload.data["couleur des yeux"] == "VERTS" then
		activeEyeColor = eyeColorGreenSkins
	end

	if self.payload.data["couleur des yeux"] == "NOISETTES" or self.payload.data["couleur des yeux"] == "MARRONS"
	or self.payload.data["couleur des yeux"] == "AMBRES"  then
		activeEyeColor = eyeColorBrownSkins
	end

	return activeEyeColor
end

function PANEL:ResetClothingInfo()

end

function PANEL:SetStandardFactionInfo(panel)
	self.faction = ix.faction.indices[panel.faction]
	self.torsoBodygroups = "2"
	self.legsBodygroups = "3"
	self.shoesBodygroups = "4"
	self.hairBodygroups = "10"
	self.beardBodygroups = "11"

	self.payload:Set("faction", panel.faction)
	self.payload:Set("model", 1)
	self.payload:Set("gender", "female")
	self.payload:Set("data", {})
	self.payload.data["languages"] = nil
	self.payload:Set("hair", {hair = 0, color = Color(244,233,230)})

	if self.characterModel and IsValid(self.characterModel) then
		self.characterModel.overrideProxyColors = {}
		self.characterModel.overrideProxyColors["HairColor"] = Vector(244 / 255, 233 / 255, 230 / 255)
	end

	if self.faction:GetModelsFemale(LocalPlayer()) then
		self.characterModel:SetModel(self.faction:GetModelsFemale(LocalPlayer())[1] or "models/willardnetworks/citizens/female_01.mdl")
		local model = self.characterModel:GetModel()
		if model:find("models/willardnetworks/citizens/") then
			if ix.faction.indices[panel.faction].index == FACTION_CP then
				model = self.characterModel:GetModel()
				if model then
					model = string.Replace(model, "models/willardnetworks/citizens/", "models/wn7new/metropolice/")
					if self.payload.gender == "male" then
						model = string.Replace(model, "male", "male_")
					end

					self.characterModel:SetModel(model)
				end
			end
		end
	end

	self.payload.data["age"] = ""
	self.payload.data["height"] = ""
	self.payload.data["couleur des yeux"] = ""

	self.torsoBodygroups = "2"
	self.legsBodygroups = "3"
	self.shoesBodygroups = "4"
	self.hairBodygroups = "10"
	self.beardBodygroups = "11"

	self.payload.data["groups"] = {}
	self.payload.data["skin"] = 0
	self.payload.data["chosenClothes"] = {}
	self.payload.data.chosenClothes[self.beardBodygroups] = 0

	self:ResetClothingInfo()

	self.payload.data["glasses"] = false
	self.payload.data["canread"] = true

	self.payload:Set("special", {})
	self.payload.special["strength"] = 0
	self.payload.special["perception"] = 0
	self.payload.special["agility"] = 0
	self.payload.special["intelligence"] = 0

	self.payload:Set("skill", {})

	self.payload.data["background"] = ""
end

function PANEL:CheckIfFinished(name)
	for k, v in SortedPairsByMemberValue(ix.char.vars, "index") do
		if (name ~= nil and (v.category or "character") != name) then
			continue
		end

		local value = self.payload[k]

		if (!v.bNoDisplay or v.OnValidate) then
			if (v.OnValidate) then
				local result = {v:OnValidate(value, self.payload, LocalPlayer())}

				if (result[1] == false) then
					if IsValid(self.finishButton) then
						self.finishButton:SetTextColor(Color(255, 255, 255, 30))
						self.finishButton.Paint = function(_, w, h)
							self:DrawFinishButtonNonAvailable(w, h)
						end
					end

					return false
				end
			end
		end
	end

	if IsValid(self.finishButton) then
		self.finishButton:SetTextColor(color_white)
		self.finishButton.Paint = function(_, w, h)
			self:DrawFinishButtonAvailable(w, h)
		end

		self.finishButton.DoClick = function()
			surface.PlaySound("willardnetworks/charactercreation/final.wav")
			self:SendPayload()
		end
	end

	return true
end

function PANEL:GetWhitelistFactions()
	local Count = 0

	for _, v in pairs(ix.faction.teams) do
		if (ix.faction.HasWhitelist(v.index)) then
			Count = Count + 1
		end
	end

	return Count
end


function PANEL:ResetPanel()
	self:ResetPayload(true)
	self.repopulatePanels = {}
end

function PANEL:ClearSelectedMainButtons()
	for _, v in pairs(self.mainButtonList) do
		v:SetTextColor(Color(200, 200, 200, 255))
		v.Paint = function(this, w, h)
			self:DrawButtonUnselected(v.name, this, w, h, true)
		end
	end

	for _, v in pairs(self.rightCreation:GetChildren()) do
		v:SetVisible(false)
	end

	if IsValid(self.dropdownMenu) then
		self.dropdownMenu:Remove()
	end
end

function PANEL:ResetModelCam()
	self.characterModel:SetFOV(26)
	self.characterModel:SetCamPos(self.originPos)
	self.characterModel:SetLookAt(self.originLookAt)
end

-- Paint Functions
function PANEL:SetButtonSelected(parent, text, boolMainButton)
	parent:SetTextColor(color_white)
	parent.Paint = function(this, w, h)
		self:DrawButtonSelected(text, this, w, h, boolMainButton)
	end
end

function PANEL:DrawRoundedBox(parent, w, h, alpha)
	draw.RoundedBox( 10, 0, 0, parent:GetWide(), parent:GetTall(), Color(78, 79, 100, alpha) )
end

function PANEL:FadeInBars()
	ix.gui.blackBarBottom:ColorTo( Color(0, 0, 0, 255), 1, 1 )
	ix.gui.blackBarTop:ColorTo( Color(0, 0, 0, 255), 1, 1 )
	ix.gui.blackBarTop:SetVisible(true)
	ix.gui.blackBarBottom:SetVisible(true)
end

function PANEL:Dim(length, callback)
	local animationTime = 1
	self.currentDimAmount = 0
	self.currentY = 0
	self.currentScale = 1
	self.currentAlpha = 255
	self.targetDimAmount = 255
	self.targetScale = 0.9

	length = length or animationTime
	self.currentDimAmount = 0

	self:CreateAnimation(length, {
		target = {
			currentDimAmount = self.targetDimAmount,
			currentScale = self.targetScale,
			OnComplete = callback
		},
		easing = "outCubic"
	})
end

function PANEL:DrawFinishButtonAvailable(w, h)
	surface.SetDrawColor(Color(0, 0, 0, 100))
	surface.DrawRect(0, 0, w, h)

	surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
	surface.DrawOutlinedRect(0, 0, w, h)

	surface.SetDrawColor(color_white)
	surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/tick.png"))
	surface.DrawTexturedRect(w - SScaleMin(15 / 3) - padding, h * 0.5 - SScaleMin(36 / 3) * 0.5, SScaleMin(15 / 3), SScaleMin(36 / 3))
end

function PANEL:DrawFinishButtonNonAvailable(w, h)
	surface.SetDrawColor(255, 255, 255, 5)
	surface.DrawRect(0, 0, w, h)

	surface.SetDrawColor(255, 255, 255, 30)
	surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/tick.png"))
	surface.DrawTexturedRect(w - SScaleMin(15 / 3) - padding, h * 0.5 - SScaleMin(36 / 3) * 0.5, SScaleMin(15 / 3), SScaleMin(36 / 3))
end

function PANEL:DrawButtonUnselected(text, this, w, h, bMainButton)
	surface.SetDrawColor(Color(0, 0, 0, 100))
	surface.DrawRect(0, 0, w, h)

	surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
	surface.DrawOutlinedRect(0, 0, w, h)
	if bMainButton then
		if this:IsHovered() then
			this:SetTextColor(color_white)
			surface.SetDrawColor(color_white)
		else
			this:SetTextColor(Color(200, 200, 200, 255))
			surface.SetDrawColor(Color(255, 255, 255, 160))
		end

		surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/"..text..".png"))
		surface.DrawTexturedRect(SScaleMin(9 / 3), SScaleMin(9 / 3), margin, margin)
	end
end

function PANEL:DrawButtonSelected(text, this, w, h, bMainButton)
	surface.SetDrawColor(Color(255, 78, 69, 255))
	surface.DrawRect(0, 0, w, h)

	if bMainButton then
		surface.SetDrawColor(color_white)
		surface.SetMaterial(ix.util.GetMaterial("willardnetworks/mainmenu/charcreation/"..text..".png"))
		surface.DrawTexturedRect(SScaleMin(9 / 3), SScaleMin(9 / 3), margin, margin)
	end
end

function PANEL:Paint(width, height)
	surface.SetDrawColor(255, 255, 255, 0)
	surface.DrawTexturedRect(0, 0, width, height)
	BaseClass.Paint(self, width, height)
end

vgui.Register("ixCharMenuNew", PANEL, "ixCharMenuPanel")