This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 0e770b2b49
commit 94063e4369
7342 changed files with 1718932 additions and 14 deletions

View 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 = "Apparence",
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

View 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")

View File

@@ -0,0 +1,31 @@
--[[
| 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 = "[Lecteur audio] Apprendre à lire"
ITEM.uniqueID = "audiobook_reading"
ITEM.model = "models/props_lab/reciever01d.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.description = "L'écoute de cet appareil rustique améliorera votre capacité de lecture."
ITEM.category = "Livres Audio"
ITEM.functions.Listen = {
name = "Écouter",
OnRun = function(itemTable)
local client = itemTable.player
local character = client:GetCharacter()
character:SetCanread(true)
client:NotifyLocalized("Je me sens plus à l'aise avec la lecture.")
end
}

View 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("Vous devez attendre avant de pouvoir faire ça!")
return false
end
else
client:NotifyLocalized("Vous n'avez pas de barbe ou de cheveux!")
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("Vous devez attendre avant de pouvoir faire ça!")
return false
end
else
client:NotifyLocalized("la cible n'avez pas de barbe ou de cheveux!")
return false
end
return false
end
}

View 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.."' manque un nom. Vous devez ajouter un FACTION.name = \"Name\"\n")
end
if (!FACTION.description) then
FACTION.description = "noDesc"
ErrorNoHalt("Faction '"..niceName.."' manque une description. Vous devez ajouter un FACTION.description = \"Description\"\n")
end
if (!FACTION.color) then
FACTION.color = Color(150, 150, 150)
ErrorNoHalt("Faction '"..niceName.."' manque une couleur. Vous devez ajouter FACTION.color = Color(1, 2, 3)\n")
end
team.SetUp(FACTION.index, FACTION.name or "Inconnue", 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
})

View File

@@ -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

View File

@@ -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
})

View File

@@ -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

View File

@@ -0,0 +1,329 @@
--[[
| 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 = "Utilisez des lunettes",
optdUseImmersiveGlasses = "Utilisez des lunettes, brouillant la vue de votre personnage s'il a besoin de lunettes et n'en porte pas."
})
ix.lang.AddTable("french", {
optUseImmersiveGlasses = "Utilisez des lunettes",
optdUseImmersiveGlasses = "Utilisez des lunettes, brouillant la vue de votre personnage s'il a besoin de lunettes et n'en porte pas."
})
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 = {
gris = {
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)
},
marrons = {
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)
},
blonds = {
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)
},
["teinte de bleu"] = {
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, "Vous n'avez pas sélectionné les cheveux/la couleur des cheveux !"
end
if !istable(payload.hair) then
return false, "Quelque chose s'est mal passé avec la sélection de cheveux!"
end
if !payload.hair.hair then
return false, "Vous n'avez pas sélectionné les cheveux!"
end
if !payload.hair.color then
return false, "Vous n'avez pas sélectionné la couleur des cheveux!"
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, "Vous n'avez pas sélectionné de couleur de cheveux autorisée !"
end
if !isnumber(payload.hair.hair) then
return false, "Vous n'avez pas sélectionné de poil autorisé !"
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, "Forcer l'effet des lunettes, même si le client désactive l'option pour eux.", nil, {
category = "Personnages"
})
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, "Vous n'avez pas sélectionné de modèle !"
end
else
return false, "Vous n'avez pas sélectionné de modèle!"
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, "Vous n'avez pas sélectionné de sexe !"
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, "Vous n'avez pas sélectionné votre background !"
end
if faction:GetNoGenetics(client) then
return true
end
if !payload.data.age or payload.data["age"] == "" then
return false, "Vous n'avez pas sélectionné votre âge !"
end
if !payload.data.height or payload.data["height"] == "" then
return false, "Vous n'avez pas sélectionné votre taille !"
end
if faction.name != "Vortigaunt" then
if !payload.data["couleur des yeux"] or payload.data["couleur des yeux"] == "" then
return false, "Vous n'avez pas sélectionné la couleur de vos yeux !"
end
end
if payload.data.skin < 0 then
return false, "Vous n'avez pas sélectionné de skin valide !"
end
if payload.data.groups then
if payload.data.groups["2"]then
if payload.data.groups["2"] < 0 then
return false, "Vous n'avez pas sélectionné de torse valide !"
end
end
if payload.data.groups["3"] then
if payload.data.groups["3"] < 0 then
return false, "Vous n'avez pas sélectionné de pantalon valide !"
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

View 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("J'ai besoin de mes lunettes pour voir clair...")
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("Nous avons ajouté de nouveaux cheveux et couleurs de cheveux, veuillez sélectionner via le 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("Je devrais tailler ma barbe...")
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("Ma barbe devient longue...")
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("Vous n'avez pas de barbe !")
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)