Files
VnUtest/garrysmod/gamemodes/militaryrp/schema/derma/cl_character.lua
2026-03-31 10:27:04 +03:00

499 lines
18 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Масштабирование для меню
local function GetScale()
local scale = ScrH() / 1080
return math.Clamp(scale, 0.5, 2.0)
end
local function ScaleSize(val)
return math.max(1, math.Round(val * GetScale()))
end
local function ScalePos(val)
return math.Round(val * GetScale())
end
local function CreateMenuFonts()
surface.CreateFont("ixMenuButtonFont_Adaptive", {
font = "Roboto",
size = math.max(ScaleSize(18), 12),
weight = 500,
antialias = true
})
surface.CreateFont("ixMenuButtonHugeFont_Adaptive", {
font = "Roboto",
size = math.max(ScaleSize(32), 20),
weight = 700,
antialias = true
})
end
CreateMenuFonts()
hook.Add("OnScreenSizeChanged", "CharMenu_UpdateFonts", CreateMenuFonts)
local CharMenu = {}
function CharMenu:Init()
if IsValid(ix.gui.characterMenu) then
ix.gui.characterMenu:Remove()
end
self:SetSize(ScrW(), ScrH())
self:SetPos(0, 0)
-- Переменные для совместимости
self.bClosing = false
self.currentAlpha = 255
self.bMenuShouldClose = false
-- Проверяем наличие персонажа
self:CheckCharacterAndLoad()
ix.gui.characterMenu = self
ix.gui.menu = self -- Для совместимости
self:MakePopup()
self:SetKeyboardInputEnabled(true)
self:SetMouseInputEnabled(true)
end
function CharMenu:CheckCharacterAndLoad()
-- Ждем немного пока загрузятся данные персонажей
timer.Simple(0.5, function()
if not IsValid(self) then return end
local hasCharacter = LocalPlayer().GetCharacter and LocalPlayer():GetCharacter()
if hasCharacter then
-- Если персонаж уже загружен, закрываем меню
print("Персонаж уже загружен, закрываем меню")
self:Close(true)
return
end
local characters = ix.characters
if (#characters > 0) then
local firstChar = characters[1]
if not firstChar then
return
end
net.Start("ixCharacterChoose")
net.WriteUInt(firstChar, 32)
net.SendToServer()
else
-- Если персонажей нет, показываем выбор стороны
print("Персонажей нет, показываем выбор фракции")
self:ShowFactionSelection()
end
end)
end
function CharMenu:ShowFactionSelection()
-- Очищаем предыдущие панели
if IsValid(self.currentPanel) then
self.currentPanel:Remove()
end
-- Создаем панель выбора фракции
self.currentPanel = vgui.Create("DPanel", self)
self.currentPanel:SetSize(ScrW(), ScrH())
self.currentPanel:SetPos(0, 0)
-- Фон
local backgroundImage = vgui.Create("DImage", self.currentPanel)
backgroundImage:SetSize(ScrW(), ScrH())
backgroundImage:SetPos(0, 0)
backgroundImage:SetImage("ft_ui/military/vnu/charcreate/bg.png")
-- Верхняя панель
CreateMenuFonts()
local topBar = vgui.Create("DPanel", self.currentPanel)
topBar:SetSize(ScrW() + 2, ScaleSize(100))
topBar:SetPos(-1, 0)
topBar.Paint = function(panel, w, h)
surface.SetDrawColor(Color(13, 13, 13))
surface.DrawRect(0, 0, w, h)
end
-- Логотип
local logo = vgui.Create("DImage", self.currentPanel)
logo:SetSize(ScaleSize(150), ScaleSize(53))
logo:SetPos(ScrW()/2 - ScaleSize(75), ScalePos(23))
logo:SetImage("ft_ui/military/vnu/charcreate/logo.png")
-- Заголовок
local title = vgui.Create("DLabel", self.currentPanel)
title:SetText("ВЫБОР СТОРОНЫ")
title:SetFont("ixMenuButtonHugeFont_Adaptive")
title:SetTextColor(color_white)
title:SizeToContents()
title:SetPos(ScrW()/2 - title:GetWide()/2, ScalePos(187))
-- Панель ВСУ
local ukrainePanel = vgui.Create("DPanel", self.currentPanel)
ukrainePanel:SetSize(ScaleSize(425), ScaleSize(500))
ukrainePanel:SetPos(ScrW()/2 - ScaleSize(425) - ScaleSize(25), ScalePos(310))
ukrainePanel.Paint = function(panel, w, h)
surface.SetDrawColor(Color(0, 0, 0, 180))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
-- Панель России
local russiaPanel = vgui.Create("DPanel", self.currentPanel)
russiaPanel:SetSize(ScaleSize(425), ScaleSize(500))
russiaPanel:SetPos(ScrW()/2 + ScaleSize(25), ScalePos(310))
russiaPanel.Paint = function(panel, w, h)
surface.SetDrawColor(Color(0, 0, 0, 180))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
-- Изображения фракций
local ukraineImage = vgui.Create("DImage", self.currentPanel)
ukraineImage:SetSize(ScaleSize(200), ScaleSize(200))
ukraineImage:SetPos(ScrW()/2 - ScaleSize(425) - ScaleSize(25) + ScaleSize(113), ScalePos(333))
ukraineImage:SetImage("ft_ui/military/vnu/charcreate/ukraine.png")
local russiaImage = vgui.Create("DImage", self.currentPanel)
russiaImage:SetSize(ScaleSize(295), ScaleSize(200))
russiaImage:SetPos(ScrW()/2 + ScaleSize(25) + ScaleSize(65), ScalePos(333))
russiaImage:SetImage("ft_ui/military/vnu/charcreate/russia.png")
-- Кнопки выбора
local ukraineButton = vgui.Create("DButton", self.currentPanel)
ukraineButton:SetSize(ScaleSize(425), ScaleSize(75))
ukraineButton:SetPos(ScrW()/2 - ScaleSize(425) - ScaleSize(25), ScalePos(818))
ukraineButton:SetText("")
ukraineButton.Paint = function(panel, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(29, 29, 29))
surface.DrawOutlinedRect(0, 0, w, h, 3)
draw.SimpleText("УКРАИНА", "ixMenuButtonHugeFont_Adaptive", w/2, h/2, Color(255, 255, 255, 218), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if panel:IsHovered() then
surface.SetDrawColor(Color(255, 255, 255, 30))
surface.DrawRect(0, 0, w, h)
end
end
ukraineButton.DoClick = function()
self:ShowCharacterCreation(FACTION_UKRAINE)
end
local russiaButton = vgui.Create("DButton", self.currentPanel)
russiaButton:SetSize(ScaleSize(425), ScaleSize(75))
russiaButton:SetPos(ScrW()/2 + ScaleSize(25), ScalePos(818))
russiaButton:SetText("")
russiaButton.Paint = function(panel, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(29, 29, 29))
surface.DrawOutlinedRect(0, 0, w, h, 3)
draw.SimpleText("РОССИЯ", "ixMenuButtonHugeFont_Adaptive", w/2, h/2, Color(255, 255, 255, 218), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if panel:IsHovered() then
surface.SetDrawColor(Color(255, 255, 255, 30))
surface.DrawRect(0, 0, w, h)
end
end
russiaButton.DoClick = function()
self:ShowCharacterCreation(FACTION_RUSSIAN)
end
end
function CharMenu:ShowCharacterCreation(faction)
-- Очищаем предыдущие панели
if IsValid(self.currentPanel) then
self.currentPanel:Remove()
end
self.currentPanel = vgui.Create("DPanel", self)
self.currentPanel:SetSize(ScrW(), ScrH())
self.currentPanel:SetPos(0, 0)
-- Фон
local backgroundImage = vgui.Create("DImage", self.currentPanel)
backgroundImage:SetSize(ScrW(), ScrH())
backgroundImage:SetPos(0, 0)
backgroundImage:SetImage("ft_ui/military/vnu/charcreate/bg.png")
-- Верхняя панель
CreateMenuFonts()
local topBar = vgui.Create("DPanel", self.currentPanel)
topBar:SetSize(ScrW() + 2, ScaleSize(100))
topBar:SetPos(-1, 0)
topBar.Paint = function(panel, w, h)
surface.SetDrawColor(Color(13, 13, 13))
surface.DrawRect(0, 0, w, h)
end
-- Логотип
local logo = vgui.Create("DImage", self.currentPanel)
logo:SetSize(ScaleSize(150), ScaleSize(53))
logo:SetPos(ScrW()/2 - ScaleSize(75), ScalePos(23))
logo:SetImage("ft_ui/military/vnu/charcreate/logo.png")
-- Основная панель
local mainPanel = vgui.Create("DPanel", self.currentPanel)
mainPanel:SetSize(ScaleSize(1500), ScaleSize(750))
mainPanel:SetPos(ScrW()/2 - ScaleSize(750), ScalePos(199))
mainPanel.Paint = function(panel, w, h)
surface.SetDrawColor(Color(13, 13, 13, 200))
surface.DrawRect(0, 0, w, h)
end
-- Заголовки
local title = vgui.Create("DLabel", self.currentPanel)
title:SetText("СОЗДАНИЕ ПЕРСОНАЖА")
title:SetFont("ixMenuButtonHugeFont_Adaptive")
title:SetTextColor(color_white)
title:SizeToContents()
title:SetPos(ScrW()/2 - title:GetWide()/2, ScalePos(224))
-- Разделители
local divider1 = vgui.Create("DPanel", self.currentPanel)
divider1:SetSize(ScaleSize(770), ScaleSize(2))
divider1:SetPos(ScrW()/2 - ScaleSize(385), ScalePos(314))
divider1.Paint = function(panel, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawRect(0, 0, w, h)
end
-- Поля ввода
local startX = ScrW()/2 - ScaleSize(420)
-- Имя
local nameLabel = vgui.Create("DLabel", self.currentPanel)
nameLabel:SetText("Ваше имя")
nameLabel:SetFont("ixMenuButtonFont_Adaptive")
nameLabel:SetTextColor(color_white)
nameLabel:SizeToContents()
nameLabel:SetPos(startX, ScalePos(360))
local nameEntry = vgui.Create("DTextEntry", self.currentPanel)
nameEntry:SetSize(ScaleSize(265), ScaleSize(50))
nameEntry:SetPos(startX, ScalePos(401))
nameEntry:SetFont("ixMenuButtonFont_Adaptive")
nameEntry:SetTextColor(Color(255, 255, 255, 230))
nameEntry:SetDrawBackground(false)
nameEntry.Paint = function(panel, w, h)
surface.SetDrawColor(Color(23, 23, 23))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 1)
panel:DrawTextEntryText(Color(255, 255, 255, 230), Color(30, 130, 255), Color(255, 255, 255, 230))
end
-- Фамилия
local lastNameLabel = vgui.Create("DLabel", self.currentPanel)
lastNameLabel:SetText("Ваша фамилия")
lastNameLabel:SetFont("ixMenuButtonFont_Adaptive")
lastNameLabel:SetTextColor(color_white)
lastNameLabel:SizeToContents()
lastNameLabel:SetPos(startX + ScaleSize(285), ScalePos(360))
local lastNameEntry = vgui.Create("DTextEntry", self.currentPanel)
lastNameEntry:SetSize(ScaleSize(265), ScaleSize(50))
lastNameEntry:SetPos(startX + ScaleSize(285), ScalePos(401))
lastNameEntry:SetFont("ixMenuButtonFont_Adaptive")
lastNameEntry:SetTextColor(Color(255, 255, 255, 230))
lastNameEntry:SetDrawBackground(false)
lastNameEntry.Paint = nameEntry.Paint
-- Позывной
local callSignLabel = vgui.Create("DLabel", self.currentPanel)
callSignLabel:SetText("Ваш позывной")
callSignLabel:SetFont("ixMenuButtonFont_Adaptive")
callSignLabel:SetTextColor(color_white)
callSignLabel:SizeToContents()
callSignLabel:SetPos(startX + ScaleSize(570), ScalePos(360))
local callSignEntry = vgui.Create("DTextEntry", self.currentPanel)
callSignEntry:SetSize(ScaleSize(265), ScaleSize(50))
callSignEntry:SetPos(startX + ScaleSize(570), ScalePos(401))
callSignEntry:SetFont("ixMenuButtonFont_Adaptive")
callSignEntry:SetTextColor(Color(255, 255, 255, 230))
callSignEntry:SetDrawBackground(false)
callSignEntry.Paint = nameEntry.Paint
-- Кнопка создания
local createButton = vgui.Create("DButton", self.currentPanel)
createButton:SetSize(ScaleSize(300), ScaleSize(80))
createButton:SetPos(ScrW()/2 - ScaleSize(150), ScrH() - ScaleSize(120))
createButton:SetText("")
createButton.Paint = function(panel, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(29, 29, 29))
surface.DrawOutlinedRect(0, 0, w, h, 3)
draw.SimpleText("СОЗДАТЬ", "ixMenuButtonHugeFont_Adaptive", w/2, h/2, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if panel:IsHovered() then
surface.SetDrawColor(Color(255, 255, 255, 30))
surface.DrawRect(0, 0, w, h)
end
end
createButton.DoClick = function()
local name = nameEntry:GetText()
local lastName = lastNameEntry:GetText()
local callSign = callSignEntry:GetText()
if name == "" or lastName == "" or callSign == "" then
print("Ошибка: Заполните все поля!")
return
end
local fullName = name .. " " .. lastName .. " '" .. callSign .. "'"
print("Создание персонажа: " .. fullName)
self:CreateCharacter(faction, fullName)
end
self.selectedFaction = faction
end
function CharMenu:CreateCharacter(faction, name)
if self.awaitingResponse then
print("Уже ожидаем ответ от сервера...")
return
end
-- Подготавливаем данные для создания персонажа
local payload = {
name = name,
faction = faction,
model = "models/player/group01/male_04.mdl",
description = "Солдат"
}
print("Отправка запроса на создание персонажа...")
PrintTable(payload)
-- Отправляем запрос на создание персонажа
net.Start("ixCharacterCreate")
net.WriteUInt(table.Count(payload), 8)
for k, v in pairs(payload) do
net.WriteString(k)
net.WriteType(v)
end
net.SendToServer()
-- Ждем ответа от сервера
self.awaitingResponse = true
-- Таймаут на случай проблем с соединением
timer.Create("CharCreateTimeout", 10, 1, function()
if IsValid(ix.gui.characterMenu) and ix.gui.characterMenu.awaitingResponse then
ix.gui.characterMenu.awaitingResponse = false
Derma_Message("Таймаут создания персонажа! Проверьте соединение.", "Ошибка", "OK")
end
end)
end
-- Методы для совместимости с Helix
function CharMenu:IsClosing()
return self.bClosing or false
end
function CharMenu:GetAlpha()
return self.currentAlpha or 255
end
function CharMenu:GetCharacterOverview()
-- Заглушка для совместимости
return nil
end
function CharMenu:Close(bFromMenu)
self.bClosing = true
if ix.gui.loading then
ix.gui.loading:Remove()
end
self:Remove()
end
function CharMenu:Paint(w, h)
-- Черный фон
surface.SetDrawColor(Color(0, 0, 0, 255))
surface.DrawRect(0, 0, w, h)
end
vgui.Register("ixCharMenu", CharMenu, "EditablePanel")
-- Исправляем CalcView hook
hook.Add("CalcView", "MilitaryRPMenuFix", function(ply, origin, angles, fov)
local menu = ix.gui.characterMenu or ix.gui.menu
if IsValid(menu) and not menu:IsClosing() then
-- Возвращаем стандартный вид, чтобы избежать ошибок
return {
origin = origin,
angles = angles,
fov = fov,
drawviewer = false
}
end
end)
-- Глобальные сетевые обработчики (устанавливаются один раз при загрузке файла)
net.Receive("ixCharacterLoad", function()
local characters = net.ReadUInt(8)
local charList = {}
for i = 1, characters do
charList[i] = net.ReadUInt(32)
end
ix.characters = charList
print("Получен список персонажей: ", table.concat(charList, ", "))
-- Если меню открыто, обновляем его
if IsValid(ix.gui.characterMenu) then
ix.gui.characterMenu:CheckCharacterAndLoad()
end
end)
net.Receive("ixCharacterAuthed", function()
timer.Remove("CharCreateTimeout")
local id = net.ReadUInt(32)
local characters = net.ReadUInt(8)
local charList = {}
for i = 1, characters do
charList[i] = net.ReadUInt(32)
end
ix.characters = charList
print("Персонаж успешно создан! ID: " .. id)
print("Теперь доступно персонажей: " .. characters)
-- Автоматически выбираем созданного персонажа
if id then
print("Автовыбор персонажа ID: " .. id)
net.Start("ixCharacterChoose")
net.WriteUInt(id, 32)
net.SendToServer()
end
-- Закрываем меню если оно открыто
if IsValid(ix.gui.characterMenu) then
ix.gui.characterMenu.awaitingResponse = false
ix.gui.characterMenu:Close(true)
end
end)
net.Receive("ixCharacterAuthFailed", function()
timer.Remove("CharCreateTimeout")
local fault = net.ReadString()
local args = net.ReadTable()
print("Ошибка создания персонажа: " .. fault)
PrintTable(args)
-- Показываем ошибку пользователю
if IsValid(ix.gui.characterMenu) then
ix.gui.characterMenu.awaitingResponse = false
Derma_Message("Ошибка создания персонажа: " .. fault, "Ошибка", "OK")
end
end)