mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
58
gamemodes/helix/plugins/charcreation/cl_plugin.lua
Normal file
58
gamemodes/helix/plugins/charcreation/cl_plugin.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
-- Glasses stuff
|
||||
ix.option.Add("useImmersiveGlasses", ix.type.bool, true, {
|
||||
category = "appearance",
|
||||
hidden = function()
|
||||
return ix.config.Get("forceImmersiveGlasses")
|
||||
end
|
||||
})
|
||||
|
||||
netstream.Hook("OpenBeardStyling", function(target)
|
||||
if (IsValid(ix.gui.menu)) then
|
||||
ix.gui.menu:Remove()
|
||||
end
|
||||
|
||||
if IsValid(beardStyling) then
|
||||
beardStyling:Remove()
|
||||
end
|
||||
|
||||
local beardStyling = vgui.Create("BeardStyling")
|
||||
beardStyling:CustomInit(target)
|
||||
end)
|
||||
|
||||
netstream.Hook("GetStylingConfirmation", function(attempter)
|
||||
Derma_Query("Someone wants to style your hair/beard! Allow?", "Hair/Beard Styling", "Allow", function()
|
||||
netstream.Start("AcceptStyling", attempter)
|
||||
end, "Disallow")
|
||||
end)
|
||||
|
||||
-- Called when blurry screen space effects should be rendered.
|
||||
function PLUGIN:RenderScreenspaceEffects()
|
||||
if (!ix.config.Get("forceImmersiveGlasses")) then
|
||||
if (!ix.option.Get("useImmersiveGlasses", true)) then return end
|
||||
end
|
||||
|
||||
local client = LocalPlayer()
|
||||
if (client:GetMoveType() == MOVETYPE_NOCLIP and !client:InVehicle()) then return end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
if (!character) then return end
|
||||
|
||||
local needsGlasses = character:GetGlasses()
|
||||
local hasGlasses = character:HasGlasses()
|
||||
if ((needsGlasses and !hasGlasses) or (!needsGlasses and hasGlasses)) then
|
||||
DrawToyTown(28,ScrH())
|
||||
end
|
||||
end
|
||||
463
gamemodes/helix/plugins/charcreation/derma/cl_beardstyling.lua
Normal file
463
gamemodes/helix/plugins/charcreation/derma/cl_beardstyling.lua
Normal file
@@ -0,0 +1,463 @@
|
||||
--[[
|
||||
| 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 PANEL = {}
|
||||
local padding = SScaleMin(10 / 3)
|
||||
|
||||
local function Paint(self, 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
|
||||
|
||||
function PANEL:CustomInit(target)
|
||||
self:SetSize(ScrW(), ScrH())
|
||||
|
||||
local background = self:Add("Panel")
|
||||
background:SetSize(self:GetSize())
|
||||
background.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(Color(63, 58, 115, 220))
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
Derma_DrawBackgroundBlur( this, 1 )
|
||||
end
|
||||
|
||||
self.innerContent = background:Add("EditablePanel")
|
||||
self.innerContent:SetSize(SScaleMin(1300 / 3), SScaleMin(900 / 3))
|
||||
self.innerContent:Center()
|
||||
self.innerContent:MakePopup()
|
||||
self.innerContent.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(0, 0, 0, 130)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
Schema:AllowMessage(self.innerContent)
|
||||
|
||||
self:DrawTopBar()
|
||||
self:DrawModel()
|
||||
self:DrawLeftSide()
|
||||
end
|
||||
|
||||
function PANEL:DrawTopBar()
|
||||
local topbar = self.innerContent:Add("Panel")
|
||||
topbar:SetSize(self.innerContent:GetWide(), SScaleMin(50 / 3))
|
||||
topbar:Dock(TOP)
|
||||
topbar.Paint = function( this, w, h )
|
||||
surface.SetDrawColor(0, 0, 0, 130)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
local titleText = topbar:Add("DLabel")
|
||||
titleText:SetFont("CharCreationBoldTitleNoClamp")
|
||||
titleText:Dock(LEFT)
|
||||
titleText:SetText("Hair/Beard Styling")
|
||||
titleText:DockMargin(SScaleMin(10 / 3), 0, 0, 0)
|
||||
titleText:SetContentAlignment(4)
|
||||
titleText:SizeToContents()
|
||||
|
||||
local exit = topbar:Add("DImageButton")
|
||||
exit:SetImage("willardnetworks/tabmenu/navicons/exit.png")
|
||||
exit:SetSize(SScaleMin(20 / 3), SScaleMin(20 / 3))
|
||||
exit:DockMargin(0, SScaleMin(15 / 3), SScaleMin(10 / 3), SScaleMin(15 / 3))
|
||||
exit:Dock(RIGHT)
|
||||
exit.DoClick = function()
|
||||
self:Remove()
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:DrawModel()
|
||||
local target = self.target or LocalPlayer()
|
||||
local characterModelList = self.innerContent:Add("Panel")
|
||||
characterModelList:Dock(RIGHT)
|
||||
characterModelList:SetWide(self.innerContent:GetWide() * 0.5)
|
||||
characterModelList.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(Color(255, 255, 255, 30));
|
||||
surface.DrawOutlinedRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
local imgBackground = characterModelList:Add("DImage")
|
||||
imgBackground:SetImage(ix.faction.indices[target:Team()].inventoryImage or
|
||||
"materials/willardnetworks/tabmenu/inventory/backgrounds/street.png")
|
||||
imgBackground:SetKeepAspect(true)
|
||||
imgBackground:Dock(FILL)
|
||||
imgBackground:DockMargin(1, 1, 1, 1)
|
||||
|
||||
self.characterModel = imgBackground:Add("ixModelPanel")
|
||||
self.characterModel:Dock(FILL)
|
||||
|
||||
local styleButton = characterModelList:Add("DButton")
|
||||
styleButton:Dock(BOTTOM)
|
||||
styleButton:SetFont("MenuFontLargerBoldNoFix")
|
||||
styleButton:SetText("Style")
|
||||
styleButton:SetTall(SScaleMin(50 / 3))
|
||||
styleButton.DoClick = function()
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
local char = target.GetCharacter and target:GetCharacter()
|
||||
|
||||
local hairBG = target:FindBodygroupByName("hair")
|
||||
local beard = target:FindBodygroupByName("beard")
|
||||
|
||||
local curHair = target:GetBodygroup(hairBG)
|
||||
local curBeard = target:GetBodygroup(beard)
|
||||
local newHair = self.characterModel.Entity:GetBodygroup(hairBG)
|
||||
local newBeard = self.characterModel.Entity:GetBodygroup(beard)
|
||||
local curHairColor = char and char.GetHair and char:GetHair() and char:GetHair().color or color_white
|
||||
local newHairColor = self.hairColor
|
||||
|
||||
if (curHair != newHair) or (curBeard != newBeard) or (curHairColor and newHairColor and curHairColor != newHairColor) then
|
||||
netstream.Start("SetHairBeardBodygroup", newHair, newBeard, newHairColor, target)
|
||||
target:NotifyLocalized("You've successfully styled your beard/hair!")
|
||||
self:Remove()
|
||||
else
|
||||
target:NotifyLocalized("You cannot select the same hair/beard you already have!")
|
||||
end
|
||||
end
|
||||
|
||||
styleButton.Paint = function(this, w, h)
|
||||
Paint(this, w, h)
|
||||
end
|
||||
|
||||
self:SetCharacter()
|
||||
|
||||
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(60)
|
||||
self.characterModel.PaintModel = self.characterModel.Paint
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:SetCharacter()
|
||||
local target = self.target or LocalPlayer()
|
||||
local model = target:GetModel()
|
||||
self.characterModel:SetModel(model, target:GetSkin(), true)
|
||||
|
||||
local isCP = model:find("wn7new")
|
||||
local indexName = isCP and "cp_Head" or "headwear"
|
||||
local index = target:FindBodygroupByName(indexName)
|
||||
|
||||
if index != -1 then
|
||||
if self.characterModel.Entity:GetBodygroup(index) > 0 then
|
||||
self.characterModel.Entity:SetBodygroup(index, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local curHair = target:GetCharacter():GetHair()
|
||||
local hairValue = curHair and curHair.hair
|
||||
if hairValue then
|
||||
local hairIndex = target:FindBodygroupByName("hair")
|
||||
self.characterModel.Entity:SetBodygroup(hairIndex, hairValue)
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:DrawLeftSide()
|
||||
self.leftSide = self.innerContent:Add("Panel")
|
||||
self.leftSide:Dock(LEFT)
|
||||
self.leftSide:SetWide(self.innerContent:GetWide() * 0.5)
|
||||
self.leftSide.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(Color(255, 255, 255, 10));
|
||||
surface.DrawRect(0, 0, w, h )
|
||||
|
||||
surface.SetDrawColor(Color(255, 255, 255, 30));
|
||||
surface.DrawOutlinedRect(0, 0, w + 1, h)
|
||||
end
|
||||
|
||||
self:DrawShaveTrimButtons()
|
||||
|
||||
local beardBodygroup = self.characterModel.Entity:GetBodygroup(11)
|
||||
|
||||
local beardPart = self.leftSide:Add("DScrollPanel")
|
||||
beardPart:Dock(BOTTOM)
|
||||
beardPart:SetTall((beardBodygroup != 5 and beardBodygroup != 8 and SScaleMin(100 / 3)) or (self.innerContent:GetTall() - SScaleMin(50 / 3)) * 0.5)
|
||||
beardPart.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(color_white)
|
||||
surface.DrawRect(0, 0, w, 1)
|
||||
end
|
||||
beardPart:DockMargin(0, padding * 3 - 1, 0, 0)
|
||||
|
||||
local hairParts = self.leftSide:Add("Panel")
|
||||
hairParts:Dock(FILL)
|
||||
|
||||
local hairPart = hairParts:Add("DScrollPanel")
|
||||
hairPart:Dock(LEFT)
|
||||
hairPart:SetWide(self.innerContent:GetWide() * 0.25)
|
||||
|
||||
local hairColorPart = hairParts:Add("DScrollPanel")
|
||||
hairColorPart:Dock(FILL)
|
||||
|
||||
local titleText = hairPart:Add("DLabel")
|
||||
titleText:SetFont("CharCreationBoldTitleNoClamp")
|
||||
titleText:Dock(TOP)
|
||||
titleText:SetText("Hair")
|
||||
titleText:DockMargin(0, padding * 3 - 1, 0, 0)
|
||||
titleText:SetContentAlignment(5)
|
||||
titleText:SizeToContents()
|
||||
|
||||
local titleText2 = hairColorPart:Add("DLabel")
|
||||
titleText2:SetFont("CharCreationBoldTitleNoClamp")
|
||||
titleText2:Dock(TOP)
|
||||
titleText2:SetText("Hair Color")
|
||||
titleText2:DockMargin(0, padding * 3 - 1, 0, 0)
|
||||
titleText2:SetContentAlignment(5)
|
||||
titleText2:SizeToContents()
|
||||
|
||||
self:DrawHairButtons(hairPart, hairColorPart)
|
||||
|
||||
if beardBodygroup == 5 or beardBodygroup == 8 then
|
||||
self:DrawBeardButtons(beardPart)
|
||||
else
|
||||
local notEnough = beardPart:Add("DLabel")
|
||||
notEnough:SetText("There is not enough beard to style...")
|
||||
notEnough:SetFont("MenuFontLargerBoldNoFix")
|
||||
notEnough:SetContentAlignment(5)
|
||||
notEnough:Dock(TOP)
|
||||
notEnough:DockMargin(0, padding * 3 - 1, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:DrawBeardButtons(beardPart)
|
||||
local target = self.target or LocalPlayer()
|
||||
for i = 1, 6 do
|
||||
local beardButton = beardPart:Add("DButton")
|
||||
local sideMargins = self.leftSide:GetWide() * 0.1
|
||||
beardButton:Dock(TOP)
|
||||
beardButton:SetTall(SScaleMin(50 / 3))
|
||||
beardButton:SetFont("MenuFontLargerBoldNoFix")
|
||||
beardButton:SetText("Style "..i)
|
||||
beardButton:DockMargin(sideMargins, padding * 3 - 1, sideMargins, 0)
|
||||
|
||||
beardButton.DoClick = function()
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
local beard = target:FindBodygroupByName("beard")
|
||||
if i == 5 then
|
||||
self.characterModel.Entity:SetBodygroup(beard, 6)
|
||||
elseif i == 6 then
|
||||
self.characterModel.Entity:SetBodygroup(beard, 7)
|
||||
else
|
||||
self.characterModel.Entity:SetBodygroup(beard, i)
|
||||
end
|
||||
end
|
||||
|
||||
beardButton.OnCursorEntered = function()
|
||||
surface.PlaySound("helix/ui/rollover.wav")
|
||||
end
|
||||
|
||||
beardButton.Paint = function(this, w, h)
|
||||
Paint(this, w, h)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:DrawHairButtons(hairPart, hairColorPart)
|
||||
local target = self.target or LocalPlayer()
|
||||
local gender = target.GetCharacter and target:GetCharacter():GetGender() or "female"
|
||||
local hairs = {}
|
||||
for i = 0, gender == "female" and 14 or 12 do hairs[#hairs + 1] = i end
|
||||
|
||||
local curStyle = 0
|
||||
for _, hairID in pairs(hairs) do
|
||||
curStyle = curStyle + 1
|
||||
local hairButton = hairPart:Add("DButton")
|
||||
local sideMargins = self.leftSide:GetWide() * 0.1
|
||||
hairButton:Dock(TOP)
|
||||
hairButton:SetTall(SScaleMin(50 / 3))
|
||||
hairButton:SetFont("MenuFontLargerBoldNoFix")
|
||||
hairButton:SetText("Style "..curStyle)
|
||||
hairButton:DockMargin(sideMargins, padding * 3 - 1, sideMargins, 0)
|
||||
|
||||
hairButton.DoClick = function()
|
||||
local hairBG = target:FindBodygroupByName("hair")
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
self.characterModel.Entity:SetBodygroup(hairBG, hairID)
|
||||
end
|
||||
|
||||
hairButton.OnCursorEntered = function()
|
||||
surface.PlaySound("helix/ui/rollover.wav")
|
||||
end
|
||||
|
||||
hairButton.Paint = function(this, w, h)
|
||||
Paint(this, w, h)
|
||||
end
|
||||
end
|
||||
|
||||
for _, colorTable in pairs(ix.allowedHairColors) do
|
||||
for _, color in pairs(colorTable) do
|
||||
local hairButton = hairColorPart:Add("DButton")
|
||||
local sideMargins = self.leftSide:GetWide() * 0.1
|
||||
hairButton:Dock(TOP)
|
||||
hairButton:SetTall(SScaleMin(50 / 3))
|
||||
hairButton:SetFont("MenuFontLargerBoldNoFix")
|
||||
hairButton:SetText("")
|
||||
hairButton:DockMargin(sideMargins, padding * 3 - 1, sideMargins, 0)
|
||||
|
||||
hairButton.DoClick = function()
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
|
||||
if self.characterModel and IsValid(self.characterModel) then
|
||||
self.characterModel.overrideProxyColors = {HairColor = Vector(color.r / 255, color.g / 255, color.b / 255)}
|
||||
end
|
||||
|
||||
self.hairColor = color
|
||||
end
|
||||
|
||||
hairButton.OnCursorEntered = function()
|
||||
surface.PlaySound("helix/ui/rollover.wav")
|
||||
end
|
||||
|
||||
hairButton.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(color)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:DrawShaveTrimButtons()
|
||||
local target = self.target or LocalPlayer()
|
||||
local buttonPanel = self.leftSide:Add("Panel")
|
||||
buttonPanel:Dock(BOTTOM)
|
||||
buttonPanel:SetTall(SScaleMin(50 / 3))
|
||||
|
||||
local shaveButton = buttonPanel:Add("DButton")
|
||||
shaveButton:Dock(FILL)
|
||||
shaveButton:SetText("Shave")
|
||||
shaveButton:SetFont("MenuFontLargerBoldNoFix")
|
||||
shaveButton:SetWide(self.leftSide:GetWide() * 0.5)
|
||||
shaveButton.DoClick = function()
|
||||
surface.PlaySound("willardnetworks/charactercreation/boop1.wav")
|
||||
self:CreateWarningPanel()
|
||||
end
|
||||
|
||||
local gender = target.GetCharacter and target:GetCharacter():GetGender() or "female"
|
||||
if gender == "female" then shaveButton:SetDisabled(true) end
|
||||
|
||||
shaveButton.Paint = function(this, w, h)
|
||||
if gender == "female" then
|
||||
surface.SetDrawColor(255, 255, 255, 5)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
return
|
||||
end
|
||||
|
||||
Paint(this, w, h)
|
||||
end
|
||||
|
||||
local beardBodygroup = self.characterModel.Entity:GetBodygroup(11)
|
||||
|
||||
if beardBodygroup == 0 then
|
||||
shaveButton:SetDisabled(true)
|
||||
shaveButton.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(255, 255, 255, 5)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
shaveButton.OnCursorEntered = function() end
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:CreateWarningPanel()
|
||||
local warningPanel = vgui.Create("Panel")
|
||||
warningPanel:SetAlpha(0)
|
||||
warningPanel:MakePopup()
|
||||
warningPanel:SetSize(ScrW(), ScrH())
|
||||
warningPanel:AlphaTo(255, 0.5, 0)
|
||||
warningPanel.Paint = function(this, w, h)
|
||||
surface.SetDrawColor(0, 0, 0, 230)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
local warningContent = warningPanel:Add("Panel")
|
||||
warningContent:SetSize(ScrW() * 0.4, SScaleMin(95 / 3))
|
||||
warningContent:Center()
|
||||
|
||||
local label = warningContent:Add("DLabel")
|
||||
label:SetFont("CharCreationBoldTitleNoClamp")
|
||||
label:SetText("This will remove your beard, are you sure?")
|
||||
label:SetContentAlignment(5)
|
||||
label:Dock(TOP)
|
||||
label:SizeToContents()
|
||||
|
||||
local warningButtons = warningContent:Add("Panel")
|
||||
warningButtons:Dock(TOP)
|
||||
warningButtons:DockMargin(0, padding, 0, 0)
|
||||
warningButtons:SetTall(SScaleMin(50 / 3))
|
||||
|
||||
local yes = warningButtons:Add("DButton")
|
||||
yes:Dock(LEFT)
|
||||
yes:SetWide(warningContent:GetWide() * 0.5)
|
||||
yes:SetText("YES")
|
||||
yes:SetFont("CharCreationBoldTitleNoClamp")
|
||||
yes:SetContentAlignment(6)
|
||||
yes:SetTextColor(Color(200, 200, 200, 255))
|
||||
yes:SetTextInset(padding * 2, 0)
|
||||
yes.Paint = function(this, w, h)
|
||||
if this:IsHovered() then
|
||||
this:SetTextColor(Color(255, 255, 255, 255))
|
||||
else
|
||||
this:SetTextColor(Color(200, 200, 200, 255))
|
||||
end
|
||||
end
|
||||
|
||||
local target = self.target or LocalPlayer()
|
||||
|
||||
yes.DoClick = function()
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
surface.PlaySound("npc/antlion/idle1.wav")
|
||||
warningPanel:AlphaTo(0, 0.5, 0, function()
|
||||
local beard = target:FindBodygroupByName("beard")
|
||||
warningPanel:Remove()
|
||||
self:Remove()
|
||||
|
||||
netstream.Start("RemoveBeardBodygroup", target)
|
||||
self.characterModel.Entity:SetBodygroup(beard, 0)
|
||||
end)
|
||||
end
|
||||
|
||||
local no = warningButtons:Add("DButton")
|
||||
no:Dock(RIGHT)
|
||||
no:SetWide(warningContent:GetWide() * 0.5)
|
||||
no:SetText("NO")
|
||||
no:SetFont("CharCreationBoldTitleNoClamp")
|
||||
no:SetTextColor(Color(200, 200, 200, 255))
|
||||
no:SetContentAlignment(4)
|
||||
no:SetTextInset(padding * 2, 0)
|
||||
no.Paint = function(this, w, h)
|
||||
if this:IsHovered() then
|
||||
this:SetTextColor(Color(255, 255, 255, 255))
|
||||
else
|
||||
this:SetTextColor(Color(200, 200, 200, 255))
|
||||
end
|
||||
end
|
||||
no.DoClick = function()
|
||||
surface.PlaySound("helix/ui/press.wav")
|
||||
warningPanel:AlphaTo(0, 0.5, 0, function()
|
||||
warningPanel:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
yes.OnCursorEntered = function()
|
||||
surface.PlaySound("helix/ui/rollover.wav")
|
||||
end
|
||||
|
||||
no.OnCursorEntered = function()
|
||||
surface.PlaySound("helix/ui/rollover.wav")
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:SetTarget(target)
|
||||
self.target = target
|
||||
end
|
||||
|
||||
vgui.Register("BeardStyling", PANEL, "EditablePanel")
|
||||
@@ -0,0 +1,30 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
ITEM.name = "[Audio Player] Learn to Read"
|
||||
ITEM.uniqueID = "audiobook_reading"
|
||||
ITEM.model = "models/props_lab/reciever01d.mdl"
|
||||
ITEM.width = 1
|
||||
ITEM.height = 1
|
||||
ITEM.description = "Listening to this rustic device will improve your reading capability."
|
||||
ITEM.category = "Audiobooks"
|
||||
|
||||
ITEM.functions.Listen = {
|
||||
OnRun = function(itemTable)
|
||||
local client = itemTable.player
|
||||
local character = client:GetCharacter()
|
||||
|
||||
character:SetCanread(true)
|
||||
|
||||
client:NotifyLocalized("I feel much better at reading now.")
|
||||
end
|
||||
}
|
||||
89
gamemodes/helix/plugins/charcreation/items/sh_razor.lua
Normal file
89
gamemodes/helix/plugins/charcreation/items/sh_razor.lua
Normal file
@@ -0,0 +1,89 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
ITEM.name = "Hairdresser tools"
|
||||
ITEM.uniqueID = "beard_razor"
|
||||
ITEM.model = "models/props_junk/cardboard_box004a.mdl"
|
||||
ITEM.width = 1
|
||||
ITEM.height = 1
|
||||
ITEM.description = "A tool for creative souls in an otherwise depressing landscape."
|
||||
ITEM.category = "Tools"
|
||||
|
||||
ITEM.functions.Style = {
|
||||
icon = "icon16/paintbrush.png",
|
||||
OnRun = function(itemTable)
|
||||
local client = itemTable.player
|
||||
if !client or client and !IsValid(client) then return end
|
||||
|
||||
local model = client:GetModel()
|
||||
if model:find("willardnetworks/citizens/") or model:find("wn7new") then
|
||||
if !client.CantPlace then
|
||||
client.CantPlace = true
|
||||
netstream.Start(client, "OpenBeardStyling")
|
||||
|
||||
timer.Simple(3, function()
|
||||
if client then
|
||||
client.CantPlace = false
|
||||
end
|
||||
end)
|
||||
else
|
||||
client:NotifyLocalized("You need to wait before you can do this!")
|
||||
return false
|
||||
end
|
||||
else
|
||||
client:NotifyLocalized("You don't have hair/beard to style!")
|
||||
return false
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
ITEM.functions.Style2 = {
|
||||
icon = "icon16/paintbrush.png",
|
||||
name = "Style Other",
|
||||
OnRun = function(itemTable)
|
||||
local client = itemTable.player
|
||||
if !client or client and !IsValid(client) then return end
|
||||
|
||||
local target = client:GetEyeTraceNoCursor().Entity
|
||||
if !target or target and !IsValid(target) then
|
||||
client:Notify("Invalid target!")
|
||||
return false
|
||||
end
|
||||
|
||||
if target:GetModel():find("willardnetworks/citizens/") then
|
||||
if !client.CantPlace then
|
||||
client.CantPlace = true
|
||||
|
||||
if target:IsBot() then
|
||||
netstream.Start(client, "OpenBeardStyling", target)
|
||||
else
|
||||
netstream.Start(target, "GetStylingConfirmation", client)
|
||||
end
|
||||
|
||||
timer.Simple(3, function()
|
||||
if client then
|
||||
client.CantPlace = false
|
||||
end
|
||||
end)
|
||||
else
|
||||
client:NotifyLocalized("You need to wait before you can do this!")
|
||||
return false
|
||||
end
|
||||
else
|
||||
client:NotifyLocalized("Target doesn't have hair/beard to style!")
|
||||
return false
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
}
|
||||
180
gamemodes/helix/plugins/charcreation/libs/sh_faction.lua
Normal file
180
gamemodes/helix/plugins/charcreation/libs/sh_faction.lua
Normal file
@@ -0,0 +1,180 @@
|
||||
--[[
|
||||
| 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 CITIZEN_MODELS = {
|
||||
"models/humans/group01/male_01.mdl",
|
||||
"models/humans/group01/male_02.mdl",
|
||||
"models/humans/group01/male_04.mdl",
|
||||
"models/humans/group01/male_05.mdl",
|
||||
"models/humans/group01/male_06.mdl",
|
||||
"models/humans/group01/male_07.mdl",
|
||||
"models/humans/group01/male_08.mdl",
|
||||
"models/humans/group01/male_09.mdl",
|
||||
"models/humans/group02/male_01.mdl",
|
||||
"models/humans/group02/male_03.mdl",
|
||||
"models/humans/group02/male_05.mdl",
|
||||
"models/humans/group02/male_07.mdl",
|
||||
"models/humans/group02/male_09.mdl",
|
||||
"models/humans/group01/female_01.mdl",
|
||||
"models/humans/group01/female_02.mdl",
|
||||
"models/humans/group01/female_03.mdl",
|
||||
"models/humans/group01/female_06.mdl",
|
||||
"models/humans/group01/female_07.mdl",
|
||||
"models/humans/group02/female_01.mdl",
|
||||
"models/humans/group02/female_03.mdl",
|
||||
"models/humans/group02/female_06.mdl",
|
||||
"models/humans/group01/female_04.mdl"
|
||||
}
|
||||
|
||||
--- Loads factions from a directory.
|
||||
-- @realm shared
|
||||
-- @string directory The path to the factions files.
|
||||
function ix.faction.LoadFromDir(directory)
|
||||
for _, v in ipairs(file.Find(directory.."/*.lua", "LUA")) do
|
||||
local niceName = v:sub(4, -5)
|
||||
|
||||
FACTION = ix.faction.teams[niceName] or {index = table.Count(ix.faction.teams) + 1, isDefault = false}
|
||||
if (PLUGIN) then
|
||||
FACTION.plugin = PLUGIN.uniqueID
|
||||
end
|
||||
|
||||
ix.util.Include(directory.."/"..v, "shared")
|
||||
|
||||
if (!FACTION.name) then
|
||||
FACTION.name = "Unknown"
|
||||
ErrorNoHalt("Faction '"..niceName.."' is missing a name. You need to add a FACTION.name = \"Name\"\n")
|
||||
end
|
||||
|
||||
if (!FACTION.description) then
|
||||
FACTION.description = "noDesc"
|
||||
ErrorNoHalt("Faction '"..niceName.."' is missing a description. You need to add a FACTION.description = \"Description\"\n")
|
||||
end
|
||||
|
||||
if (!FACTION.color) then
|
||||
FACTION.color = Color(150, 150, 150)
|
||||
ErrorNoHalt("Faction '"..niceName.."' is missing a color. You need to add FACTION.color = Color(1, 2, 3)\n")
|
||||
end
|
||||
|
||||
team.SetUp(FACTION.index, FACTION.name or "Unknown", FACTION.color or Color(125, 125, 125))
|
||||
|
||||
FACTION.models = FACTION.models or CITIZEN_MODELS
|
||||
FACTION.uniqueID = FACTION.uniqueID or niceName
|
||||
|
||||
for _, v2 in pairs(FACTION.models) do
|
||||
if (isstring(v2)) then
|
||||
util.PrecacheModel(v2)
|
||||
elseif (istable(v2)) then
|
||||
util.PrecacheModel(v2[1])
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetModels) then
|
||||
function FACTION:GetModels(client)
|
||||
return self.models
|
||||
end
|
||||
end
|
||||
|
||||
-- GENDERS
|
||||
if (!FACTION.GetModelsMale) then
|
||||
function FACTION:GetModelsMale(client)
|
||||
return self.models.male
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetModelsFemale) then
|
||||
function FACTION:GetModelsFemale(client)
|
||||
return self.models.female
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetNoGender) then
|
||||
function FACTION:GetNoGender(client)
|
||||
return self.noGender
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetNoGenetics) then
|
||||
function FACTION:GetNoGenetics(client)
|
||||
return self.noGenetics
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetNoAppearances) then
|
||||
function FACTION:GetNoAppearances(client)
|
||||
return self.noAppearances
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetReadOptionDisabled) then
|
||||
function FACTION:GetReadOptionDisabled(client)
|
||||
return self.ReadOptionDisabled
|
||||
end
|
||||
end
|
||||
|
||||
if (!FACTION.GetNoBackground) then
|
||||
function FACTION:GetNoBackground(client)
|
||||
return self.noBackground
|
||||
end
|
||||
end
|
||||
|
||||
ix.faction.indices[FACTION.index] = FACTION
|
||||
ix.faction.teams[niceName] = FACTION
|
||||
FACTION = nil
|
||||
end
|
||||
end
|
||||
|
||||
ix.command.Add("PlyWhitelist", {
|
||||
description = "@cmdPlyWhitelist",
|
||||
privilege = "Manage Character Whitelist",
|
||||
superAdminOnly = true,
|
||||
arguments = {
|
||||
ix.type.player,
|
||||
ix.type.text
|
||||
},
|
||||
OnRun = function(self, client, target, name)
|
||||
if (name == "") then
|
||||
return "@invalidArg", 2
|
||||
end
|
||||
|
||||
local faction = ix.faction.teams[name]
|
||||
|
||||
if (!faction) then
|
||||
for _, v in ipairs(ix.faction.indices) do
|
||||
if (ix.util.StringMatches(L(v.name, client), name) or ix.util.StringMatches(v.uniqueID, name)) then
|
||||
faction = v
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (faction) then
|
||||
local result, text = hook.Run("CanWhitelistPlayer", target, faction)
|
||||
if (result == false) then
|
||||
return "@"..(text or "invalidFaction")
|
||||
end
|
||||
|
||||
if (target:SetWhitelisted(faction.index, true)) then
|
||||
if faction.OnWhitelist then
|
||||
faction:OnWhitelist(target)
|
||||
end
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (self:OnCheckAccess(v) or v == target) then
|
||||
v:NotifyLocalized("whitelist", client:GetName(), target:GetName(), L(faction.name, v))
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
return "@invalidFaction"
|
||||
end
|
||||
end
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
do
|
||||
for _, proxy in pairs(PLUGIN.proxyList) do
|
||||
matproxy.Add( {
|
||||
name = proxy,
|
||||
|
||||
init = function( self, _, values )
|
||||
-- Store the name of the variable we want to set
|
||||
self.ResultTo = values.resultvar
|
||||
end,
|
||||
|
||||
bind = function( self, mat, ent )
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
|
||||
-- If entity is a ragdoll try to convert it into the player
|
||||
-- ( this applies to their corpses )
|
||||
if ( ent:IsRagdoll() ) then
|
||||
local owner = ent:GetRagdollOwner()
|
||||
if ( IsValid( owner ) ) then ent = owner end
|
||||
end
|
||||
|
||||
-- SHOULD return a Vector with the items stored-/character's stored hair colour.
|
||||
local clrFallback = Vector( 255 / 255, 255 / 255, 255 / 255 )
|
||||
|
||||
local entColor = ent.GetProxyColors and ent:GetProxyColors() or false
|
||||
|
||||
local ragdollNWVector = ent:GetNWVector(proxy, false)
|
||||
|
||||
local character = ent.GetCharacter and ent:GetCharacter() or false
|
||||
local charProxyColors = character and character.GetProxyColors and character:GetProxyColors() or {}
|
||||
|
||||
local color = entColor and entColor[proxy] or ragdollNWVector or charProxyColors[proxy] or clrFallback
|
||||
|
||||
if istable(color) and color.r then
|
||||
color = Vector(color.r / 255, color.g / 255, color.b / 255)
|
||||
end
|
||||
|
||||
mat:SetVector(self.ResultTo, color)
|
||||
end
|
||||
} )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.proxyList = {
|
||||
"HeadGearColor",
|
||||
"HairColor",
|
||||
"TorsoColor",
|
||||
"ShirtColor",
|
||||
"PantsColor",
|
||||
"ShoesColor"
|
||||
}
|
||||
|
||||
ix.char.RegisterVar("proxyColors", {
|
||||
field = "proxyColors",
|
||||
fieldType = ix.type.text,
|
||||
default = {},
|
||||
bNoDisplay = true
|
||||
})
|
||||
@@ -0,0 +1,32 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
-- could just call ixPlayer on the ragdoll but then the colors will change on the ragdoll according to what the player is doing
|
||||
-- in their inventory (even if they are dead)
|
||||
|
||||
function PLUGIN:OnCharacterFallover(client, entity, bFallenOver)
|
||||
if (entity == nil or !IsValid(entity)) then return end
|
||||
|
||||
local character = client.GetCharacter and client:GetCharacter()
|
||||
if (!character) then return end
|
||||
|
||||
local colorProxies = character:GetProxyColors() or {}
|
||||
for proxy, vector in pairs(colorProxies) do
|
||||
local color = vector
|
||||
if !isvector(color) and istable(color) and color.r then
|
||||
color = Vector(color.r / 255, color.g / 255, color.b / 255)
|
||||
end
|
||||
|
||||
entity:SetNWVector(proxy, color)
|
||||
end
|
||||
end
|
||||
324
gamemodes/helix/plugins/charcreation/sh_plugin.lua
Normal file
324
gamemodes/helix/plugins/charcreation/sh_plugin.lua
Normal file
@@ -0,0 +1,324 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.name = "Char Creation Necessities"
|
||||
PLUGIN.author = "Fruity"
|
||||
PLUGIN.description = "Required stuff for the char creation such as gender etc."
|
||||
PLUGIN.TIMER_DELAY = PLUGIN.TIMER_DELAY or 60
|
||||
|
||||
ix.util.Include("sv_plugin.lua")
|
||||
ix.util.Include("cl_plugin.lua")
|
||||
ix.util.Include("matproxies/sv_matproxies.lua")
|
||||
ix.util.Include("matproxies/sh_matproxies.lua")
|
||||
ix.util.Include("matproxies/cl_matproxies.lua")
|
||||
|
||||
ix.lang.AddTable("english", {
|
||||
optUseImmersiveGlasses = "Use Immersive Glasses",
|
||||
optdUseImmersiveGlasses = "Make use of immersive glasses, blurring the sight of your character if they need glasses and aren't wearing any."
|
||||
})
|
||||
|
||||
ix.lang.AddTable("spanish", {
|
||||
optdUseImmersiveGlasses = "Utiliza las gafas de inmersión, difuminando la vista de tu personaje si necesita gafas y no las lleva puestas.",
|
||||
optUseImmersiveGlasses = "Utilizar gafas inmersivas"
|
||||
})
|
||||
|
||||
ix.char.RegisterVar("glasses", {
|
||||
field = "glasses",
|
||||
fieldType = ix.type.bool,
|
||||
default = false,
|
||||
isLocal = true,
|
||||
bNoDisplay = true
|
||||
})
|
||||
|
||||
ix.char.RegisterVar("canread", {
|
||||
field = "canread",
|
||||
fieldType = ix.type.bool,
|
||||
default = true,
|
||||
isLocal = true,
|
||||
bNoDisplay = true
|
||||
})
|
||||
|
||||
ix.char.RegisterVar("beardProgress", {
|
||||
field = "beard",
|
||||
fieldType = ix.type.number,
|
||||
default = 0,
|
||||
bNoNetworking = true,
|
||||
bNoDisplay = true
|
||||
})
|
||||
|
||||
ix.allowedHairColors = {
|
||||
greys = {
|
||||
Color(244,233,230),
|
||||
Color(221,202,195),
|
||||
Color(182,170,165),
|
||||
Color(151,132,126),
|
||||
Color(111,101,98),
|
||||
Color(126,122,121),
|
||||
Color(89,89,89)
|
||||
},
|
||||
browns = {
|
||||
Color(95,52,39),
|
||||
Color(101,66,56),
|
||||
Color(62,50,47),
|
||||
Color(80,69,66),
|
||||
Color(138,106,96),
|
||||
Color(164,149,137),
|
||||
Color(85,72,56),
|
||||
Color(83,61,50)
|
||||
},
|
||||
light = {
|
||||
Color(223,186,155),
|
||||
Color(172,129,94),
|
||||
Color(145,124,109),
|
||||
Color(229,200,170),
|
||||
Color(203,191,177),
|
||||
Color(184,151,120),
|
||||
Color(230,206,168),
|
||||
Color(255,216,149)
|
||||
},
|
||||
["soft blue"] = {
|
||||
Color(161,165,167),
|
||||
Color(125,132,135)
|
||||
}
|
||||
}
|
||||
|
||||
ix.char.RegisterVar("hair", {
|
||||
field = "hair",
|
||||
fieldType = ix.type.table,
|
||||
default = {},
|
||||
isLocal = true,
|
||||
bNoDisplay = true,
|
||||
OnValidate = function(self, data, payload, client)
|
||||
if !payload.hair or payload.hair and !istable(payload.hair) then
|
||||
return false, "You did not select hair/hair color!"
|
||||
end
|
||||
|
||||
if !istable(payload.hair) then
|
||||
return false, "Something went wrong with the hair selection!"
|
||||
end
|
||||
|
||||
if !payload.hair.hair then
|
||||
return false, "You did not select hair!"
|
||||
end
|
||||
|
||||
if !payload.hair.color then
|
||||
return false, "You did not select hair color!"
|
||||
end
|
||||
|
||||
local found = false
|
||||
for _, v in pairs(ix.allowedHairColors) do
|
||||
if !table.HasValue(v, payload.hair.color) then continue end
|
||||
|
||||
found = true
|
||||
break
|
||||
end
|
||||
|
||||
if !found then
|
||||
return false, "You did not select an allowed hair color!"
|
||||
end
|
||||
|
||||
if !isnumber(payload.hair.hair) then
|
||||
return false, "You did not select an allowed hair!"
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
OnGet = function(self, default)
|
||||
local hair = self.vars.hair
|
||||
|
||||
return hair or {}
|
||||
end,
|
||||
OnAdjust = function(self, client, data, value, newData)
|
||||
newData.hair = value
|
||||
end
|
||||
})
|
||||
|
||||
ix.config.Add("forceImmeseriveGlasses", true, "Force the glasses effect to draw, even if the client disables the option for them.", nil, {
|
||||
category = "characters"
|
||||
})
|
||||
|
||||
do
|
||||
local CHAR = ix.meta.character
|
||||
function CHAR:HasGlasses()
|
||||
for _, v in pairs(self:GetInventory():GetItems()) do
|
||||
if (v.glasses and v:GetData("equip")) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
ix.char.vars["model"].OnDisplay = function(self, container, payload) end
|
||||
ix.char.vars["model"].OnValidate = function(self, value, payload, client)
|
||||
local faction = ix.faction.indices[payload.faction]
|
||||
|
||||
if (faction) then
|
||||
local gender = payload.gender
|
||||
local models
|
||||
if gender == "male" and faction:GetModelsMale(client) then
|
||||
models = faction:GetModelsMale(client)
|
||||
elseif gender == "female" and faction:GetModelsFemale(client) then
|
||||
models = faction:GetModelsFemale(client)
|
||||
else
|
||||
models = faction:GetModels(client)
|
||||
end
|
||||
|
||||
if (!payload.model or !models[payload.model]) then
|
||||
return false, "You did not select a model!"
|
||||
end
|
||||
else
|
||||
return false, "You did not select a model!"
|
||||
end
|
||||
end
|
||||
|
||||
ix.char.vars["model"].OnAdjust = function(self, client, data, value, newData)
|
||||
local faction = ix.faction.indices[data.faction]
|
||||
|
||||
if (faction) then
|
||||
local gender = data.gender
|
||||
local model
|
||||
if gender == "male" and faction:GetModelsMale(client) then
|
||||
model = faction:GetModelsMale(client)[value]
|
||||
elseif gender == "female" and faction:GetModelsFemale(client) then
|
||||
model = faction:GetModelsFemale(client)[value]
|
||||
else
|
||||
model = faction:GetModels(client)[value]
|
||||
end
|
||||
|
||||
if (isstring(model)) then
|
||||
newData.model = model
|
||||
elseif (istable(model)) then
|
||||
newData.model = model[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ix.char.vars["model"].ShouldDisplay = function(self, container, payload)
|
||||
local faction = ix.faction.indices[payload.faction]
|
||||
|
||||
if faction then
|
||||
local gender = payload.gender
|
||||
if gender == "male" and faction:GetModelsMale(LocalPlayer()) then
|
||||
return #faction:GetModelsMale(LocalPlayer()) > 1
|
||||
elseif gender == "female" and faction:GetModelsFemale(LocalPlayer()) then
|
||||
return #faction:GetModelsFemale(LocalPlayer()) > 1
|
||||
else
|
||||
return #faction:GetModels(LocalPlayer()) > 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Registers the var "Gender"
|
||||
ix.char.RegisterVar("gender", {
|
||||
field = "gender",
|
||||
fieldType = ix.type.string,
|
||||
default = "male",
|
||||
bNoDisplay = true,
|
||||
OnSet = function(self, value)
|
||||
local client = self:GetPlayer()
|
||||
|
||||
if (IsValid(client)) then
|
||||
self.vars.gender = value
|
||||
|
||||
-- @todo refactor networking of character vars so this doesn't need to be repeated on every OnSet override
|
||||
net.Start("ixCharacterVarChanged")
|
||||
net.WriteUInt(self:GetID(), 32)
|
||||
net.WriteString("gender")
|
||||
net.WriteType(self.vars.gender)
|
||||
net.Broadcast()
|
||||
end
|
||||
end,
|
||||
OnGet = function(self, default)
|
||||
local gender = self.vars.gender
|
||||
|
||||
return gender or 0
|
||||
end,
|
||||
OnValidate = function(self, data, payload, client)
|
||||
local faction = ix.faction.indices[payload.faction]
|
||||
if (payload.gender == "female" or payload.gender == "male") then
|
||||
return true
|
||||
end
|
||||
|
||||
if faction then
|
||||
if faction:GetNoGender(client) == true then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false, "You did not select a gender!"
|
||||
end,
|
||||
OnAdjust = function(self, client, data, value, newData)
|
||||
newData.gender = value
|
||||
end
|
||||
})
|
||||
|
||||
ix.char.vars["data"].OnValidate = function(self, datas, payload, client)
|
||||
local faction = ix.faction.indices[payload.faction]
|
||||
|
||||
if faction then
|
||||
if (!payload.data["background"] or payload.data["background"] == "") and faction:GetNoBackground(client) != true then
|
||||
return false, "You did not select your background!"
|
||||
end
|
||||
|
||||
if faction:GetNoGenetics(client) then
|
||||
return true
|
||||
end
|
||||
|
||||
if !payload.data.age or payload.data["age"] == "" then
|
||||
return false, "You did not select your age!"
|
||||
end
|
||||
|
||||
if !payload.data.height or payload.data["height"] == "" then
|
||||
return false, "You did not select your height!"
|
||||
end
|
||||
|
||||
if faction.name != "Vortigaunt" then
|
||||
if !payload.data["eye color"] or payload.data["eye color"] == "" then
|
||||
return false, "You did not select your eye color!"
|
||||
end
|
||||
end
|
||||
|
||||
if payload.data.skin < 0 then
|
||||
return false, "You did not select a valid skin!"
|
||||
end
|
||||
|
||||
if payload.data.groups then
|
||||
if payload.data.groups["2"]then
|
||||
if payload.data.groups["2"] < 0 then
|
||||
return false, "You did not select a valid torso!"
|
||||
end
|
||||
end
|
||||
|
||||
if payload.data.groups["3"] then
|
||||
if payload.data.groups["3"] < 0 then
|
||||
return false, "You did not select valid trousers!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if faction:GetNoAppearances(client) then
|
||||
return true
|
||||
end
|
||||
|
||||
if faction:GetReadOptionDisabled(client) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
ix.char.vars["data"].OnAdjust = function(self, client, datas, value, newData)
|
||||
newData.data = value
|
||||
end
|
||||
218
gamemodes/helix/plugins/charcreation/sv_plugin.lua
Normal file
218
gamemodes/helix/plugins/charcreation/sv_plugin.lua
Normal file
@@ -0,0 +1,218 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
function PLUGIN:PlayerLoadedCharacter(client, character)
|
||||
if (character:GetGlasses() and !character:HasGlasses()) then
|
||||
timer.Simple(3, function()
|
||||
if (IsValid(client) and !character:HasGlasses()) then
|
||||
client:NotifyLocalized("I need my glasses on to see properly..")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Beard stuff
|
||||
local uniqueID = "ixBeard" .. client:SteamID64()
|
||||
local gender = character:GetGender()
|
||||
if (gender == "male" and !ix.faction.Get(client:Team()).noBeard) then
|
||||
timer.Create(uniqueID, PLUGIN.TIMER_DELAY, 0, function()
|
||||
if (IsValid(client)) then
|
||||
PLUGIN:BeardPlayerTick(client)
|
||||
else
|
||||
timer.Remove(uniqueID)
|
||||
end
|
||||
end)
|
||||
else
|
||||
timer.Remove(uniqueID)
|
||||
end
|
||||
|
||||
local hairTable = character.GetHair and character:GetHair() or {}
|
||||
if !table.IsEmpty(hairTable) then
|
||||
local color = hairTable.color
|
||||
local charProxies = character:GetProxyColors() or {}
|
||||
|
||||
charProxies["HairColor"] = color
|
||||
|
||||
character:SetProxyColors(charProxies)
|
||||
else
|
||||
client:Notify("We've added new hairs and hair colors, please select via the menu.")
|
||||
netstream.Start(client, "OpenBeardStyling")
|
||||
end
|
||||
|
||||
local curModel = client:GetModel()
|
||||
if curModel:find("willardnetworks/citizens/male") and !curModel:find("willardnetworks/citizens/male_") then
|
||||
local beardIndex = client:FindBodygroupByName("beard")
|
||||
local curBeard = client:GetBodygroup(beardIndex)
|
||||
character:SetModel(string.gsub(curModel, "male", "male_"))
|
||||
|
||||
for i = 0, client:GetNumBodyGroups() do
|
||||
client:SetBodygroup(i, 0)
|
||||
end
|
||||
|
||||
timer.Simple(2, function()
|
||||
if !client or client and !IsValid(client) then return end
|
||||
if !character then return end
|
||||
|
||||
local groups = {}
|
||||
if curBeard then
|
||||
groups[beardIndex] = curBeard
|
||||
end
|
||||
|
||||
local hairIndex = client:FindBodygroupByName("hair")
|
||||
groups[hairIndex] = hairTable.hair
|
||||
character:SetData("groups", groups)
|
||||
|
||||
if hairTable.hair then
|
||||
client:SetBodygroup(hairIndex, hairTable.hair)
|
||||
end
|
||||
|
||||
if curBeard then
|
||||
client:SetBodygroup(beardIndex, curBeard)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:AdjustCreationPayload(client, payload, newPayload)
|
||||
if (newPayload.data.glasses != nil) then
|
||||
newPayload.glasses = newPayload.data.glasses
|
||||
newPayload.data.glasses = nil
|
||||
end
|
||||
|
||||
if (newPayload.data.canread != nil) then
|
||||
newPayload.canread = newPayload.data.canread
|
||||
newPayload.data.canread = nil
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:BeardPlayerTick(client)
|
||||
local character = client:GetCharacter()
|
||||
if (character) then
|
||||
if (!client:Alive()) then return end
|
||||
|
||||
local beardProgress = character:GetBeardProgress() + 1
|
||||
character:SetBeardProgress(beardProgress)
|
||||
|
||||
if (beardProgress == 180 * 8) then
|
||||
local index = client:FindBodygroupByName("beard")
|
||||
local groups = character:GetData("groups", {})
|
||||
groups[index] = 8
|
||||
client:SetBodygroup(index, 8)
|
||||
character:SetData("groups", groups)
|
||||
client:NotifyLocalized("I should really trim my beard.")
|
||||
elseif (beardProgress == 180 * 16) then
|
||||
local index = client:FindBodygroupByName("beard")
|
||||
local groups = character:GetData("groups", {})
|
||||
groups[index] = 5
|
||||
client:SetBodygroup(index, 5)
|
||||
character:SetData("groups", groups)
|
||||
client:NotifyLocalized("My beard is getting really long now.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
netstream.Hook("RemoveBeardBodygroup", function(client, target)
|
||||
if target and IsValid(target) then
|
||||
if client != target then
|
||||
client = target
|
||||
end
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
local index = client:FindBodygroupByName("beard")
|
||||
if client:GetBodygroup( index ) <= 0 then
|
||||
client:NotifyLocalized("I don't have any beard!")
|
||||
return false
|
||||
end
|
||||
|
||||
local groups = character:GetData("groups", {})
|
||||
groups[index] = 0
|
||||
client:SetBodygroup(index, 0)
|
||||
character:SetData("groups", groups)
|
||||
character:SetBeardProgress(0)
|
||||
end)
|
||||
|
||||
netstream.Hook("SetHairBeardBodygroup", function(client, hairID, beardID, hairColor, target)
|
||||
if target and IsValid(target) then
|
||||
if client != target then
|
||||
client = target
|
||||
end
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
local gender = character:GetGender()
|
||||
|
||||
local beardBGIndex = client:FindBodygroupByName("beard")
|
||||
local hairBGIndex = client:FindBodygroupByName("hair")
|
||||
|
||||
local curHair = client:GetBodygroup(hairBGIndex)
|
||||
local curBeard = beardBGIndex != -1 and client:GetBodygroup(beardBGIndex) or false
|
||||
|
||||
local groups = character:GetData("groups", {})
|
||||
|
||||
if gender != "female" and curBeard and beardID and curBeard != beardID then
|
||||
local beardProgress = character:GetBeardProgress()
|
||||
|
||||
if (beardProgress < (180 * 8)) and client:GetBodygroup(beardBGIndex) != 5 and client:GetBodygroup(beardBGIndex) != 8 then
|
||||
return false
|
||||
end
|
||||
|
||||
character:SetBeardProgress(0)
|
||||
|
||||
groups[beardBGIndex] = beardID
|
||||
client:SetBodygroup(beardBGIndex, beardID)
|
||||
end
|
||||
|
||||
if hairID and curHair != hairID or hairColor then
|
||||
local hairData = character:GetHair()
|
||||
|
||||
if hairID then
|
||||
groups[hairBGIndex] = hairID
|
||||
local bgName = client:GetModel():find("wn7new") and "cp_Head" or "headwear"
|
||||
if client:GetBodygroup(client:FindBodygroupByName(bgName)) <= 0 then
|
||||
client:SetBodygroup(hairBGIndex, hairID)
|
||||
end
|
||||
|
||||
hairData.hair = hairID
|
||||
end
|
||||
|
||||
if hairColor then
|
||||
hairData.color = hairColor
|
||||
|
||||
local charProxies = character:GetProxyColors() or {}
|
||||
|
||||
charProxies["HairColor"] = hairColor
|
||||
|
||||
character:SetProxyColors(charProxies)
|
||||
end
|
||||
|
||||
character:SetHair(hairData)
|
||||
end
|
||||
|
||||
character:SetData("groups", groups)
|
||||
end)
|
||||
|
||||
function PLUGIN:InitializedPlugins()
|
||||
Schema.charCreationItems = {}
|
||||
for _, v in pairs(ix.item.list) do
|
||||
if (v.charCreation or v.adminCreation) and v.bodyGroups then
|
||||
Schema.charCreationItems[v.uniqueID] = {bodygroups = v.bodyGroups, proxy = v.proxy or false}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
netstream.Hook("AcceptStyling", function(target, attempter)
|
||||
if !target or !attempter then return end
|
||||
if !IsValid(target) or !IsValid(attempter) then return end
|
||||
|
||||
netstream.Start(attempter, "OpenBeardStyling", target)
|
||||
end)
|
||||
Reference in New Issue
Block a user