Files
VnUtest/garrysmod/addons/shkaf/lua/entities/wardrobe_ent/init.lua
2026-03-31 10:27:04 +03:00

352 lines
12 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
resource.AddFile("materials/wardrobe_ui/body.png")
resource.AddFile("materials/wardrobe_ui/fon.png")
util.AddNetworkString("SandboxWardrobeOpen")
util.AddNetworkString("SandboxWardrobeApply")
util.AddNetworkString("SandboxWardrobeAdminOpen")
util.AddNetworkString("SandboxWardrobeAdminUpdate")
util.AddNetworkString("SandboxWardrobeCommanderOpen")
util.AddNetworkString("SandboxWardrobeCommanderApply")
util.AddNetworkString("SandboxWardrobeSavePreset")
if not file.Exists("wardrobe_presets", "DATA") then
file.CreateDir("wardrobe_presets")
end
net.Receive("SandboxWardrobeSavePreset", function(len, ply)
if not IsValid(ply) then return end
local presets = net.ReadTable()
local steamID64 = ply:SteamID64()
if steamID64 then
local json = util.TableToJSON(presets, true)
if json then
file.Write("wardrobe_presets/" .. steamID64 .. ".txt", json)
end
end
end)
-- =====================================================================
-- ПСЕВДО-ФУНКЦИИ: Замените на свои реальные проверки!
-- =====================================================================
-- Проверяет, является ли игрок командиром подразделения.
-- Замените тело функции на свою логику, например:
-- return ply:GetNWBool("IsSquadLeader", false)
-- return ply:Team() == TEAM_COMMANDER
-- return ply.isCommander == true
local function IsCommander(ply)
-- ЗАГЛУШКА: Сейчас возвращает true для суперадминов.
-- Замените на реальную проверку!
return IsValid(ply) and ply:IsSuperAdmin()
end
-- Возвращает таблицу игроков, которые находятся в подразделении этого командира.
-- Замените тело функции на свою логику, например:
-- return GetSquadByLeader(ply)
-- return team.GetPlayers(ply:Team())
-- return ply:GetSquadMembers()
local function GetSquadMembers(commander)
-- ЗАГЛУШКА: Сейчас возвращает всех игроков на сервере кроме самого командира.
-- Замените на реальную логику получения списка подразделения!
local members = {}
for _, ply in ipairs(player.GetAll()) do
if ply ~= commander then
table.insert(members, ply)
end
end
return members
end
-- =====================================================================
-- СИСТЕМА РАЗБЛОКИРОВКИ БОДИГРУПП (АДМИН)
-- =====================================================================
local function SanitizeData(tbl, depth)
depth = depth or 1
local out = {}
for k, v in pairs(tbl) do
local keyStr = tostring(k)
if depth == 1 then
if type(k) == "number" and k > 1e15 then continue end
if type(k) == "string" and string.find(keyStr, "e%+") then continue end
end
if type(v) == "table" then
out[keyStr] = SanitizeData(v, depth + 1)
else
out[keyStr] = v
end
end
return out
end
function LoadWardrobeUnlocked()
if file.Exists("wardrobe_unlocked.txt", "DATA") then
local content = file.Read("wardrobe_unlocked.txt", "DATA")
local parsed = util.JSONToTable(content, true, true)
if parsed then
WARDROBE_UNLOCKED = SanitizeData(parsed)
else
WARDROBE_UNLOCKED = {}
end
else
WARDROBE_UNLOCKED = {}
end
end
LoadWardrobeUnlocked()
function SaveWardrobeUnlocked()
local json = util.TableToJSON(WARDROBE_UNLOCKED, true)
if json then
file.Write("wardrobe_unlocked.txt", json)
end
end
-- =====================================================================
-- АДМИН ПАНЕЛЬ
-- =====================================================================
concommand.Add("wardrobe_admin", function(ply, cmd, args)
if IsValid(ply) and not ply:IsSuperAdmin() then
ply:ChatPrint("У вас нет прав (нужна группа superadmin).")
return
end
net.Start("SandboxWardrobeAdminOpen")
net.WriteTable(WARDROBE_UNLOCKED)
net.Send(ply)
end)
net.Receive("SandboxWardrobeAdminUpdate", function(len, ply)
if not IsValid(ply) or not ply:IsSuperAdmin() then return end
local sid64 = net.ReadString()
local model = string.lower(net.ReadString())
local bg_id = tostring(net.ReadUInt(8))
local bg_val = tostring(net.ReadUInt(8))
local state = net.ReadBool()
WARDROBE_UNLOCKED[sid64] = WARDROBE_UNLOCKED[sid64] or {}
WARDROBE_UNLOCKED[sid64][model] = WARDROBE_UNLOCKED[sid64][model] or {}
WARDROBE_UNLOCKED[sid64][model][bg_id] = WARDROBE_UNLOCKED[sid64][model][bg_id] or {}
if state then
WARDROBE_UNLOCKED[sid64][model][bg_id][bg_val] = true
else
WARDROBE_UNLOCKED[sid64][model][bg_id][bg_val] = nil
if table.IsEmpty(WARDROBE_UNLOCKED[sid64][model][bg_id]) then WARDROBE_UNLOCKED[sid64][model][bg_id] = nil end
if table.IsEmpty(WARDROBE_UNLOCKED[sid64][model]) then WARDROBE_UNLOCKED[sid64][model] = nil end
if table.IsEmpty(WARDROBE_UNLOCKED[sid64]) then WARDROBE_UNLOCKED[sid64] = nil end
end
SaveWardrobeUnlocked()
end)
-- =====================================================================
-- ПАНЕЛЬ КОМАНДИРА
-- =====================================================================
concommand.Add("wardrobe_commander", function(ply, cmd, args)
if not IsValid(ply) then return end
if not IsCommander(ply) then
ply:ChatPrint("Вы не являетесь командиром подразделения.")
return
end
local members = GetSquadMembers(ply)
local membersData = {}
for _, member in ipairs(members) do
if IsValid(member) then
table.insert(membersData, {
nick = member:Nick(),
sid64 = member:SteamID64(),
model = member:GetModel(),
entIndex = member:EntIndex(),
})
end
end
net.Start("SandboxWardrobeCommanderOpen")
net.WriteTable(membersData)
net.Send(ply)
end)
net.Receive("SandboxWardrobeCommanderApply", function(len, ply)
if not IsValid(ply) then return end
if not IsCommander(ply) then return end
local targetEntIndex = net.ReadUInt(16)
local isWipe = net.ReadBool()
local target = Entity(targetEntIndex)
if not IsValid(target) or not target:IsPlayer() then
ply:ChatPrint("Целевой игрок не найден.")
return
end
-- Проверяем что целевой игрок находится в подразделении командира
local members = GetSquadMembers(ply)
local isMember = false
for _, member in ipairs(members) do
if member == target then
isMember = true
break
end
end
if not isMember then
ply:ChatPrint("Этот игрок не в вашем подразделении.")
return
end
if isWipe then
target:SetSkin(0)
local bgs = target:GetBodyGroups()
for _, bg in ipairs(bgs) do
target:SetBodygroup(bg.id, 0)
end
ply:ChatPrint("Сброшена экипировка для: " .. target:Nick())
return
end
local bodygroups = net.ReadTable()
local skin = net.ReadUInt(8)
for idx, value in pairs(bodygroups) do
target:SetBodygroup(idx, value)
end
target:SetSkin(skin)
ply:ChatPrint("Экипировка применена для: " .. target:Nick())
end)
-- =====================================================================
-- ЛОГИКА ЭНТИТИ ГАРДЕРОБА
-- =====================================================================
function ENT:Initialize()
self:SetModel("models/props_wasteland/controlroom_storagecloset001a.mdl")
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
local phys = self:GetPhysicsObject()
if IsValid(phys) then phys:Wake() end
self.playerCooldowns = {}
end
function ENT:GetModelBodygroups(model)
local tempEnt = ents.Create("prop_dynamic")
if not IsValid(tempEnt) then return {} end
tempEnt:SetModel(model)
tempEnt:Spawn()
local bodygroups = {}
for i = 0, tempEnt:GetNumBodyGroups() - 1 do
local name = tempEnt:GetBodygroupName(i)
local count = tempEnt:GetBodygroupCount(i)
if count > 1 then
bodygroups[i] = {name = name, count = count, index = i}
end
end
tempEnt:Remove()
return bodygroups
end
function ENT:GetModelSkinCount(model)
local tempEnt = ents.Create("prop_dynamic")
if not IsValid(tempEnt) then return 0 end
tempEnt:SetModel(model)
tempEnt:Spawn()
local skinCount = tempEnt:SkinCount() or 0
tempEnt:Remove()
return skinCount
end
function ENT:Use(activator)
if not IsValid(activator) or not activator:IsPlayer() then return end
local steamID = activator:SteamID()
local now = CurTime()
if self.playerCooldowns[steamID] and (now - self.playerCooldowns[steamID]) < 2 then return end
local model = activator:GetModel()
if not model then return end
local bodygroups = self:GetModelBodygroups(model)
local skinCount = self:GetModelSkinCount(model)
local availableBodygroups = {}
for idx, data in pairs(bodygroups) do
availableBodygroups[idx] = data
end
local availableSkins = {}
for i = 0, skinCount - 1 do
table.insert(availableSkins, i)
end
local currentBodygroups = {}
for idx in pairs(availableBodygroups) do
currentBodygroups[idx] = activator:GetBodygroup(idx)
end
local currentSkin = activator:GetSkin()
local steamID64 = activator:SteamID64()
local unlocked = {}
if steamID64 and WARDROBE_UNLOCKED[steamID64] and WARDROBE_UNLOCKED[steamID64][string.lower(model)] then
unlocked = WARDROBE_UNLOCKED[steamID64][string.lower(model)]
end
local presets = {}
if steamID64 and file.Exists("wardrobe_presets/" .. steamID64 .. ".txt", "DATA") then
local content = file.Read("wardrobe_presets/" .. steamID64 .. ".txt", "DATA")
if content and content ~= "" then
presets = util.JSONToTable(content) or {}
end
end
self.playerCooldowns[steamID] = now
net.Start("SandboxWardrobeOpen")
net.WriteString(model)
net.WriteTable(availableBodygroups)
net.WriteTable(availableSkins)
net.WriteTable(currentBodygroups)
net.WriteUInt(currentSkin, 8)
net.WriteTable(unlocked)
net.WriteTable(presets)
net.Send(activator)
end
net.Receive("SandboxWardrobeApply", function(len, client)
if not IsValid(client) then return end
local isWipe = net.ReadBool()
if isWipe then
client:SetSkin(0)
local bgs = client:GetBodyGroups()
for _, bg in ipairs(bgs) do
client:SetBodygroup(bg.id, 0)
end
return
end
local bodygroups = net.ReadTable()
local skin = net.ReadUInt(8)
for idx, value in pairs(bodygroups) do
client:SetBodygroup(idx, value)
end
client:SetSkin(skin)
end)