Files
wnsrc/gamemodes/helix/plugins/willardinterface/derma/cl_charload.lua

731 lines
21 KiB
Lua
Raw Normal View History

2024-08-04 23:12:27 +03:00
--[[
| 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/
--]]
local errorModel = "models/error.mdl"
local PANEL = {}
AccessorFunc(PANEL, "animationTime", "AnimationTime", FORCE_NUMBER)
local function SetCharacter(self, character)
self.character = character
if (character) then
self:SetModel(character:GetModel())
self:SetSkin(character:GetData("skin", 0))
for i = 0, (self:GetNumBodyGroups() - 1) do
self:SetBodygroup(i, 0)
end
local bodygroups = character:GetData("groups", nil)
if (istable(bodygroups)) then
for k, v in pairs(bodygroups) do
self:SetBodygroup(k, v)
end
end
else
self:SetModel(errorModel)
end
end
local function GetCharacter(self)
return self.character
end
function PANEL:Init()
self.activeCharacter = ClientsideModel(errorModel)
self.activeCharacter:SetNoDraw(true)
self.activeCharacter.SetCharacter = SetCharacter
self.activeCharacter.GetCharacter = GetCharacter
self.animationTime = 0.5
self.shadeY = 0
self.shadeHeight = 0
self.cameraPosition = Vector(80, 0, 35)
self.cameraAngle = Angle(0, 180, 0)
self.lastPaint = 0
end
function PANEL:ResetSequence(model, lastModel)
local sequence = model:LookupSequence("reference")
if (sequence <= 0) then
sequence = model:SelectWeightedSequence(ACT_IDLE)
end
if (sequence > 0) then
model:ResetSequence(sequence)
else
local found = false
for _, v in ipairs(model:GetSequenceList()) do
if ((v:utf8lower():find("idle") or v:utf8lower():find("fly")) and v != "idlenoise") then
model:ResetSequence(v)
found = true
break
end
end
if (!found) then
model:ResetSequence(4)
end
end
model:SetIK(false)
-- copy cycle if we can to avoid a jarring transition from resetting the sequence
if (lastModel) then
model:SetCycle(lastModel:GetCycle())
end
end
function PANEL:RunAnimation(model)
model:FrameAdvance((RealTime() - self.lastPaint) * 0.5)
end
function PANEL:LayoutEntity(model)
model:SetIK(false)
self:RunAnimation(model)
if self.activeCharacter:GetModel() == "models/willardnetworks/vortigaunt.mdl" then
if model:LookupBone("ValveBiped.head") then
local headpos = model:GetBonePosition(model:LookupBone("ValveBiped.head"))
model:SetEyeTarget(headpos-Vector(-15, 0, 0))
return
end
end
for i = 2, 7 do
model:SetFlexWeight( i, 0 )
end
for i = 0, 1 do
model:SetFlexWeight( i, 1 )
end
end
function PANEL:SetActiveCharacter(character)
self.shadeY = self:GetTall()
self.shadeHeight = self:GetTall()
-- set character immediately if we're an error (something isn't selected yet)
if (self.activeCharacter:GetModel() == errorModel) then
self.activeCharacter:SetCharacter(character)
self:ResetSequence(self.activeCharacter)
return
end
end
function PANEL:Paint(width, height)
local x, y = self:LocalToScreen(0, 0)
cam.Start3D(self.cameraPosition, self.cameraAngle, 70, x, y, width, height)
render.SetColorMaterial()
render.SetColorModulation(1, 1, 1)
render.SuppressEngineLighting(true)
render.SetLightingOrigin(self.activeCharacter:GetPos())
-- setup lighting
render.SetModelLighting(0, 1.5, 1.5, 1.5)
for i = 1, 4 do
render.SetModelLighting(i, 0.4, 0.4, 0.4)
end
render.SetModelLighting(5, 0.04, 0.04, 0.04)
-- clip anything out of bounds
local curparent = self
local rightx = self:GetWide()
local leftx = 0
local topy = 0
local bottomy = self:GetTall()
local previous = curparent
while (curparent:GetParent() != nil) do
local lastX, lastY = previous:GetPos()
curparent = curparent:GetParent()
topy = math.Max(lastY, topy + lastY)
leftx = math.Max(lastX, leftx + lastX)
bottomy = math.Min(lastY + previous:GetTall(), bottomy + lastY)
rightx = math.Min(lastX + previous:GetWide(), rightx + lastX)
previous = curparent
end
ix.util.ResetStencilValues()
render.SetStencilWriteMask(1)
render.SetStencilTestMask(1)
render.SetStencilReferenceValue(1)
render.SetStencilFailOperation(STENCIL_KEEP)
render.SetStencilZFailOperation(STENCIL_KEEP)
self:LayoutEntity(self.activeCharacter)
render.SetScissorRect(leftx, topy + self.shadeHeight, rightx, bottomy, true)
self.activeCharacter:DrawModel()
render.SetScissorRect(leftx, topy, rightx, bottomy, true)
render.SetStencilCompareFunction(STENCIL_EQUAL)
render.SetStencilPassOperation(STENCIL_KEEP)
render.SetStencilEnable(false)
render.SetScissorRect(0, 0, 0, 0, false)
render.SuppressEngineLighting(false)
cam.End3D()
self.lastPaint = RealTime()
end
function PANEL:OnRemove()
self.activeCharacter:Remove()
end
vgui.Register("ixCharMenuCarousel", PANEL, "Panel")
-- character load panel
PANEL = {}
AccessorFunc(PANEL, "animationTime", "AnimationTime", FORCE_NUMBER)
AccessorFunc(PANEL, "backgroundFraction", "BackgroundFraction", FORCE_NUMBER)
function PANEL:Init()
local parent = self:GetParent()
self.animationTime = 1
self.backgroundFraction = 1
-- main panel
self.panel = self:AddSubpanel("main")
self.panel:SetSize(parent:GetSize())
self.panel:SetTitle("")
self.panel.OnSetActive = function()
self:CreateAnimation(self.animationTime, {
index = 2,
target = {backgroundFraction = 1},
easing = "outQuint",
})
end
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)
self.panel.avoidPadding = true
-- Character Count
local Count = 0
for _, _ in pairs(ix.characters) do
Count = Count + 1
end
self.CharacterCount = Count
local charImageH = SScaleMin(500 / 3)
local charPanelW = SScaleMin(300 / 3)
local charTextH = SScaleMin(80 / 3)
local margin = SScaleMin(20 / 3)
local panelLoad = self.panel:Add("Panel")
local titleLabel = panelLoad:Add("DLabel")
titleLabel:SetTextColor(color_white)
titleLabel:SetFont("MainMenuNewTitleFont")
titleLabel:SetText(string.utf8upper("Postacie"))
titleLabel:SizeToContents()
titleLabel:SetContentAlignment(5)
titleLabel:Dock(TOP)
titleLabel:DockMargin(0, 0, 0, SScaleMin(50 / 3))
local panelLoadWBelowEqual4 = (self.CharacterCount) * charPanelW + ((self.CharacterCount - 1) * margin)
local panelLoad4 = (4) * charPanelW + ((4 - 1) * margin)
if panelLoadWBelowEqual4 < titleLabel:GetWide() then panelLoadWBelowEqual4 = titleLabel:GetWide() end
if panelLoad4 < titleLabel:GetWide() then panelLoad4 = titleLabel:GetWide() end
if self.CharacterCount <= 4 then
panelLoad:SetSize(panelLoadWBelowEqual4, titleLabel:GetTall() + SScaleMin(50 / 3) + SScaleMin(590 / 3) + (margin * 3) + SScaleMin(30 / 3))
else
panelLoad:SetSize(panelLoad4, titleLabel:GetTall() + SScaleMin(50 / 3) + SScaleMin(590 / 3) + (margin * 3) + SScaleMin(30 / 3))
end
panelLoad:Center()
self.charactersPanel = panelLoad:Add("Panel")
self.charactersPanel:SetSize(panelLoad:GetWide(), SScaleMin(590 / 3))
self.charactersPanel:Dock(TOP)
self.characterImages = self.charactersPanel:Add("Panel")
self.characterText = self.charactersPanel:Add("Panel")
if self.CharacterCount == 1 then
self.characterImages:SetSize(charPanelW, charImageH)
self.characterText:SetSize(charPanelW, charTextH + margin)
else
self.characterImages:SetSize((self.CharacterCount) * charPanelW + ((self.CharacterCount - 1) * margin), charImageH)
self.characterText:SetSize((self.CharacterCount) * charPanelW + ((self.CharacterCount - 1) * margin), charTextH + margin + (margin * 0.5) + SScaleMin(10 / 3))
end
self.characterImages:Center()
local x, y = self.characterImages:GetPos()
self.characterImages:SetPos(x, 0)
self.characterText:Center()
x, y = self.characterText:GetPos()
self.characterText:SetPos(x, self.characterImages:GetTall())
if self.CharacterCount > 4 then
self.characterText:SetPos(0, self.characterImages:GetTall())
self.characterImages:SetPos(0, 0)
self.nextButton = self.panel:Add("DImageButton")
self.nextButton:SetSize(SScaleMin(32 / 3), SScaleMin(32 / 3))
self.nextButton:SetImage("willardnetworks/charselect/arrow_right.png")
self.nextButton:Center()
x, y = self.nextButton:GetPos()
self.nextButton:MoveRightOf(panelLoad)
local x2, y2 = self.nextButton:GetPos()
self.nextButton:SetPos(x2 + margin, y)
self.nextButton.OnCursorEntered = function()
surface.PlaySound("helix/ui/rollover.wav")
self.nextButton:SetColor( Color( 210, 210, 210, 255 ) )
end
self.nextButton.OnCursorExited = function()
self.nextButton:SetColor( Color( 255, 255, 255, 255 ) )
end
self.nextButton.DoClick = function()
x, y = self.characterImages:GetPos()
x2, y2 = self.characterText:GetPos()
local pos1, pos2 = math.Round(math.abs( x )), math.Round(((self.CharacterCount - 5) * (charPanelW + margin)))
if pos1 == pos2 or math.abs(pos1 - pos2) <= charPanelW - 10 then
self.nextButton:SetVisible(false)
end
self.characterImages:MoveTo( x - (charPanelW + margin), y, 0.1, 0, 1 )
self.characterText:MoveTo( x2 - (charPanelW + margin), y2, 0.1, 0, 1 )
surface.PlaySound("helix/ui/press.wav")
if IsValid(self.previousButton) then
return
else
self.previousButton = self.panel:Add("DImageButton")
self.previousButton:SetSize(SScaleMin(32 / 3), SScaleMin(32 / 3))
self.previousButton:SetImage("willardnetworks/charselect/arrow_left.png")
self.previousButton:Center()
x, y = self.previousButton:GetPos()
self.previousButton:MoveLeftOf(panelLoad)
x2, y2 = self.previousButton:GetPos()
self.previousButton:SetPos(x2 - margin, y)
self.previousButton.OnCursorEntered = function()
surface.PlaySound("helix/ui/rollover.wav")
self.previousButton:SetColor( Color( 210, 210, 210, 255 ) )
end
self.previousButton.OnCursorExited = function()
self.previousButton:SetColor( Color( 255, 255, 255, 255 ) )
end
self.previousButton.DoClick = function()
x, y = self.characterImages:GetPos()
x2, y2 = self.characterText:GetPos()
if IsValid(self.nextButton) then
self.nextButton:SetVisible(true)
end
surface.PlaySound("helix/ui/press.wav")
self.characterImages:MoveTo( x + (charPanelW + margin), y, 0.1, 0, 1 )
self.characterText:MoveTo( x2 + (charPanelW + margin), y2, 0.1, 0, 1 )
if IsValid(self.previousButton) then
pos1, pos2 = math.Round(x, 0), math.Round((0 - (charPanelW + margin)), 0)
if pos1 == pos2 or math.abs(pos1 - pos2) <= charPanelW - 10 then
self.previousButton:Remove()
end
end
end
end
end
end
for i = 1, #ix.characters do
local id = ix.characters[i]
local character = ix.char.loaded[id]
if (!character) then
continue
end
local index = character:GetFaction()
local faction = ix.faction.indices[index]
local image = self.characterImages:Add("DImageButton")
image:SetKeepAspect(true)
image:SetImage(faction.selectImage or "willardnetworks/charselect/citizen2.png")
image:Dock(LEFT)
if i == 1 then
image:DockMargin(0, 0, 0, 0)
else
image:DockMargin(0, 0, margin, 0)
end
image.id = character:GetID()
image:MoveToBack()
image:SetSize( charPanelW, charImageH )
image.PaintOver = function(self, w, h)
surface.SetDrawColor(Color(73, 82, 87, 255))
surface.DrawOutlinedRect(0, 0, w, h)
end
local model = image:Add("ixCharMenuCarousel")
model:SetActiveCharacter(character)
model:SetSize(SScaleMin(649 / 3), SScaleMin(540 / 3))
model:SetPos(0 - SScaleMin(169 / 3))
self.characterTextPanel = self.characterText:Add("Panel")
self.characterTextPanel:Dock(RIGHT)
self.characterTextPanel:SetWide(charPanelW)
self.characterTextPanel.id = character:GetID()
if i == 1 then
self.characterTextPanel:DockMargin(0, 0, 0, 0)
else
self.characterTextPanel:DockMargin(0, 0, margin, 0)
end
local nameText = self.characterTextPanel:Add("DLabel")
nameText:SetFont("WNMenuFontNoClamp")
if string.utf8len( character:GetName() ) > 17 then
nameText:SetText(string.utf8upper(string.utf8sub(character:GetName(), 1, 16) .."..."))
else
nameText:SetText(string.utf8upper(character:GetName()))
end
nameText:SizeToContents()
nameText:Dock(TOP)
nameText:DockMargin(0, SScaleMin(10 / 3), 0, 0)
nameText:SetContentAlignment(5)
local factionText = self.characterTextPanel:Add("DLabel")
factionText:SetFont("WNMenuFontNoClamp")
if (faction.name) == "Overwatch Transhuman Arm" then
factionText:SetText("ŻOŁNIERZ OVERWATCH")
else
factionText:SetText(string.utf8upper(faction.name))
end
factionText:SizeToContents()
factionText:Dock(TOP)
factionText:SetContentAlignment(5)
factionText:SetTextColor(Color(200, 200, 200, 200))
local buttons = self.characterTextPanel:Add("Panel")
buttons:SetSize(self.characterTextPanel:GetWide(), margin)
buttons:Dock(TOP)
buttons:DockMargin(0, margin * 0.5, 0, 0)
local centerButtons = buttons:Add("Panel")
centerButtons:SetSize((margin * 2) + SScaleMin(15 / 3), buttons:GetTall())
centerButtons:Center()
local loadChar = centerButtons:Add("DImageButton")
loadChar:SetSize(margin, margin)
loadChar:SetImage("willardnetworks/charselect/check.png")
loadChar:Dock(LEFT)
loadChar.OnCursorEntered = function()
surface.PlaySound("helix/ui/rollover.wav")
loadChar:SetColor( Color( 210, 210, 210, 255 ) )
end
loadChar.OnCursorExited = function()
loadChar:SetColor( Color( 255, 255, 255, 255 ) )
end
loadChar.DoClick = function()
self.character = character
self:SetMouseInputEnabled(false)
self:Slide("down", self.animationTime, function()
net.Start("ixCharacterChoose")
net.WriteUInt(self.character:GetID(), 32)
net.SendToServer()
end, true)
end
local deleteButton = centerButtons:Add("DImageButton")
deleteButton:SetSize(margin, margin)
deleteButton:SetImage("willardnetworks/charselect/delete.png")
deleteButton:Dock(RIGHT)
deleteButton.OnCursorEntered = function()
surface.PlaySound("helix/ui/rollover.wav")
deleteButton:SetColor( Color( 210, 210, 210, 255 ) )
end
deleteButton.OnCursorExited = function()
deleteButton:SetColor( Color( 255, 255, 255, 255 ) )
end
deleteButton.DoClick = function()
self.character = character
self:SetActiveSubpanel("delete")
if self.deleteModel and IsValid(self.deleteModel) then
self.deleteModel.overrideProxyColors = character:GetProxyColors()
end
end
end
if (ix.config.Get("CharCreationDisabled", false) and !CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Character Creation Bypass") and #ix.characters == 0) then
Derma_Query( "Czy chcesz połączyć się z serwerem miasta?", "Nie masz żadnych postaci w tej lokalizacji.", "TAK", function()
RunConsoleCommand("connect", 'hl2rp.willard.network')
end, "NIE")
end
local backPanel = panelLoad:Add("Panel")
backPanel:Dock(TOP)
backPanel:SetSize(panelLoad:GetWide(), SScaleMin(30 / 3))
backPanel:DockMargin(0, margin * 2, 0, 0)
self.back = backPanel:Add("DButton")
self.back:SetText(string.utf8upper("Wróć"))
self.back:SetContentAlignment(6)
self.back:SetSize(SScaleMin(90 / 3), SScaleMin(30 / 3))
self.back:SetTextColor(self.aFontColor)
self.back:SetFont("MainMenuNewButtonFont")
self.back:Center()
self.back:SetTextInset(SScaleMin(10 / 3), 0)
self.back.Paint = function( self, 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.back.OnCursorEntered = function()
surface.PlaySound("helix/ui/rollover.wav")
self.back:SetTextColor(self.aFontHoverColor)
end
self.back.OnCursorExited = function()
self.back:SetTextColor(self.aFontColor)
end
self.back.DoClick = function()
self:SlideDown()
parent.mainPanel:Undim()
end
-- character deletion panel
self.delete = self:AddSubpanel("delete")
self.delete:SetTitle(nil)
self.delete.OnSetActive = function()
self.delete.avoidPadding = true
self.deleteModel:SetModel(self.character:GetModel())
if self.character:GetData("skin") then
self.deleteModel.Entity:SetSkin(self.character:GetData("skin"))
end
local bodygroups = self.character:GetData("groups", nil)
if (istable(bodygroups)) then
for k, v in pairs(bodygroups) do
if self.deleteModel.Entity then
self.deleteModel.Entity:SetBodygroup(k, v)
end
end
end
self:CreateAnimation(self.animationTime, {
index = 2,
target = {backgroundFraction = 0},
easing = "outQuint"
})
end
local deleteInfo = self.delete:Add("Panel")
deleteInfo:SetSize(parent:GetWide() * 0.5, parent:GetTall())
deleteInfo:Dock(LEFT)
self.deleteModel = deleteInfo:Add("ixModelPanel")
self.deleteModel:Dock(FILL)
self.deleteModel:SetModel(errorModel)
self.deleteModel:SetFOV(78)
self.deleteModel.PaintModel = self.deleteModel.Paint
local deleteNag = self.delete:Add("Panel")
deleteNag:SetTall(parent:GetTall() * 0.6)
deleteNag:Dock(BOTTOM)
local deleteTitle = deleteNag:Add("DLabel")
deleteTitle:SetFont("WNMenuTitleNoClamp")
deleteTitle:SetText(string.utf8upper("czy na pewno?"))
deleteTitle:SetTextColor(Color(243, 69, 42, 255))
deleteTitle:SizeToContents()
deleteTitle:Dock(TOP)
local deleteText = deleteNag:Add("DLabel")
deleteText:SetFont("WNSmallerMenuTitleNoClamp")
deleteText:SetText("Ta postać zostanie nieodwracalnie usunięta!")
deleteText:SetTextColor(color_white)
deleteText:SetContentAlignment(7)
deleteText:Dock(TOP)
deleteText:SizeToContents()
local yesnoPanel = deleteNag:Add("Panel")
yesnoPanel:Dock(TOP)
yesnoPanel:SetTall(SScaleMin(60 / 3))
yesnoPanel:DockMargin(0, margin, 0, 0)
local yes = yesnoPanel:Add("DButton")
yes:Dock(LEFT)
yes:SetWide(SScaleMin(100 / 3))
yes:DockMargin(0, 0, SScaleMin(40 / 3), 0)
yes:SetFont("WNSmallerMenuTitleNoClamp")
yes:SetText(string.utf8upper("tak"))
yes.Paint = function(self, w, h) end
yes:SetContentAlignment(4)
yes.DoClick = function()
self.CharacterCount = self.CharacterCount - 1
local id = self.character:GetID()
parent:ShowNotice(1, L("deleteComplete", self.character:GetName()))
self:SetActiveSubpanel("main")
net.Start("ixCharacterDelete")
net.WriteUInt(id, 32)
net.SendToServer()
for k, v in pairs(self.characterImages:GetChildren()) do
if v.id == id then
v:Remove()
end
end
for k, v in pairs(self.characterText:GetChildren()) do
if v.id == id then
v:Remove()
end
end
if self.CharacterCount == 1 then
self.characterImages:SetSize(charPanelW, charImageH)
self.characterText:SetSize(charPanelW, charTextH + margin)
else
self.characterImages:SetSize((self.CharacterCount) * charPanelW + ((self.CharacterCount - 1) * margin), charImageH)
self.characterText:SetSize((self.CharacterCount) * charPanelW + ((self.CharacterCount - 1) * margin), charTextH + margin)
end
if self.CharacterCount > 4 then
self.characterImages:SetPos(0, 0)
self.characterText:SetPos(0, self.characterImages:GetTall())
else
if IsValid(self.nextButton) then
self.nextButton:Remove()
end
if IsValid(self.previousButton) then
self.previousButton:Remove()
end
self.characterImages:Center()
local x, y = self.characterImages:GetPos()
self.characterImages:SetPos(x, 0)
self.characterText:Center()
local x, y = self.characterText:GetPos()
self.characterText:SetPos(x, self.characterImages:GetTall())
end
if IsValid(self.characterTextPanel) then
if self.CharacterCount == 1 then
self.characterTextPanel:DockMargin(0, 0, 0, 0)
end
end
end
local no = yesnoPanel:Add("DButton")
no:Dock(LEFT)
no:SetWide(SScaleMin(100 / 3))
no:SetFont("WNSmallerMenuTitleNoClamp")
no:SetText(string.utf8upper("nie"))
no:SetContentAlignment(6)
no.Paint = function(self, w, h) end
no.DoClick = function()
self:SetActiveSubpanel("main")
end
-- finalize setup
self:SetActiveSubpanel("main", 0)
end
function PANEL:OnCharacterDeleted(character)
local parent = self:GetParent()
local bHasCharacter = #ix.characters > 0
if (self.bActive and #ix.characters == 0) then
self:SlideDown()
parent.mainPanel.loadButton:SetDisabled(true)
parent.mainPanel.loadButton:SetTextColor(self.aFontLockedButtonColor)
parent.mainPanel.loadButton.OnCursorEntered = function()
if (!bHasCharacter) then
parent.mainPanel.loadButton:SetTextColor(self.aFontLockedButtonColor)
return
end
end
parent.mainPanel.loadButton.OnCursorExited = function()
if (!bHasCharacter) then
parent.mainPanel.loadButton:SetTextColor(self.aFontLockedButtonColor)
return
end
end
end
end
function PANEL:OnSlideUp()
self.bActive = true
end
function PANEL:OnSlideDown()
self.bActive = false
end
function PANEL:Paint(width, height)
end
vgui.Register("ixCharMenuLoad", PANEL, "ixCharMenuPanel")