add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
PLUGIN.captureData = PLUGIN.captureData or {}
net.Receive("ixCaptureSync", function()
local plugin = ix.plugin.Get("capture")
if (!plugin) then return end
local point = net.ReadEntity()
local progress = net.ReadFloat()
local owner = net.ReadUInt(8)
local capturing = net.ReadUInt(8)
local players = net.ReadUInt(8)
local blocked = net.ReadBool()
if (IsValid(point)) then
plugin.captureData[point] = {
progress = progress,
owner = owner,
capturing = capturing,
players = players,
blocked = blocked
}
end
end)
local PANEL = {}
function PANEL:Init()
self.progress = 0
self.targetProgress = 0
self.alpha = 0
self.targetAlpha = 0
self.blinkAlpha = 0
end
function PANEL:SetCaptureData(data)
self.targetProgress = data.progress or 0
self.owner = data.owner or 0
self.capturing = data.capturing or 0
self.players = data.players or 0
self.blocked = data.blocked or false
if (data.capturing and data.capturing > 0) then
self.targetAlpha = 255
else
self.targetAlpha = 0
end
end
function PANEL:Think()
self.progress = Lerp(FrameTime() * 5, self.progress, self.targetProgress)
self.alpha = Lerp(FrameTime() * 8, self.alpha, self.targetAlpha)
if (self.blocked) then
self.blinkAlpha = math.abs(math.sin(CurTime() * 5)) * 255
else
self.blinkAlpha = 0
end
local plugin = ix.plugin.Get("capture")
if (plugin) then
self:SetSize(plugin.hudWidth, plugin.hudHeight)
self:SetPos(ScrW() - plugin.hudWidth - plugin.hudPosX, plugin.hudPosY)
end
end
function PANEL:Paint(w, h)
if (self.alpha < 1) then return end
surface.SetAlphaMultiplier(self.alpha / 255)
local barW = 40
local barH = h
local padding = 10
local barX = (w - barW) / 2
draw.RoundedBox(8, barX, 0, barW, barH, ColorAlpha(Color(20, 20, 20), self.alpha * 0.9))
if (self.progress > 0) then
local fillH = (barH - 4) * (self.progress / 100)
local color = Color(100, 150, 255)
if (self.capturing and self.capturing > 0) then
if (self.capturing == FACTION_RUSSIAN) then
color = Color(200, 50, 50)
elseif (self.capturing == FACTION_UKRAINE) then
color = Color(50, 100, 200)
end
end
if (self.blocked) then
color = ColorAlpha(color, self.blinkAlpha)
end
draw.RoundedBox(6, barX + 2, 2, barW - 4, fillH, ColorAlpha(color, self.alpha))
end
local text = string.format("%.0f%%", self.progress)
if (self.players and self.players > 0) then
text = text .. "\n(" .. self.players .. ")"
end
draw.SimpleText(text, "DermaDefault", w / 2, barH + 15, ColorAlpha(color_white, self.alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
surface.SetAlphaMultiplier(1)
end
vgui.Register("ixCaptureUI", PANEL, "DPanel")
function PLUGIN:HUDPaint()
local ply = LocalPlayer()
if (!IsValid(ply)) then return end
for point, data in pairs(self.captureData) do
if (IsValid(point) and ply:GetPos():Distance(point:GetPos()) <= self.captureRadius) then
if (!IsValid(self.captureUI)) then
self.captureUI = vgui.Create("ixCaptureUI")
end
self.captureUI:SetCaptureData(data)
return
end
end
if (IsValid(self.captureUI)) then
self.captureUI:SetCaptureData({progress = 0, owner = 0, capturing = 0, players = 0, blocked = false})
end
end
function PLUGIN:OnReloaded()
if (IsValid(self.captureUI)) then
self.captureUI:Remove()
self.captureUI = nil
end
end

View File

@@ -0,0 +1,117 @@
ENT.Type = "anim"
ENT.PrintName = "Точка захвата"
ENT.Category = "[FT] Захват точек"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.RenderGroup = RENDERGROUP_BOTH
ENT.bNoPersist = true
function ENT:SetupDataTables()
self:NetworkVar("Float", 0, "CaptureProgress")
self:NetworkVar("Int", 0, "OwnerFaction")
self:NetworkVar("Int", 1, "FlagSkin")
end
if SERVER then
function ENT:Initialize()
self:SetModel("models/flag/ua_flag_rework.mdl")
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_NONE)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
local phys = self:GetPhysicsObject()
if (IsValid(phys)) then
phys:EnableMotion(false)
end
-- Установка начального скина (никто не захватил)
self:SetFlagSkin(2)
self:SetSkin(2)
self:SetOwnerFaction(0)
local plugin = ix.plugin.Get("capture")
if (plugin) then
plugin:RegisterCapturePoint(self)
end
end
-- Функция для установки владельца с автоматической сменой скина
function ENT:SetOwnerFactionID(factionID)
self:SetOwnerFaction(factionID or 0)
local skinID = 2 -- По умолчанию никто
if factionID == FACTION_RUSSIAN then
skinID = 1 -- РФ - скин 1
elseif factionID == FACTION_UKRAINE then
skinID = 0 -- ВСУ - скин 0
end
self:SetFlagSkin(skinID)
self:SetSkin(skinID)
end
function ENT:Use(activator, caller)
end
else
function ENT:Draw()
self:DrawModel()
-- Синхронизация скина с NetworkVar
local skinID = self:GetFlagSkin()
if skinID and self:GetSkin() ~= skinID then
self:SetSkin(skinID)
end
--local plugin = ix.plugin.Get("capture")
--if (!plugin or !plugin.captureData[self]) then return end
--
--local data = plugin.captureData[self]
--local pos = self:GetPos() + Vector(0, 0, plugin.labelOffsetZ)
--local ang = EyeAngles()
--ang:RotateAroundAxis(ang:Forward(), 90)
--ang:RotateAroundAxis(ang:Right(), 90)
--cam.Start3D2D(pos, Angle(0, ang.y, 90), plugin.labelScale)
-- if (data.capturing and data.capturing > 0) then
-- local barW = 400
-- local barH = 60
-- local x, y = -barW / 2, -barH / 2
--
-- draw.RoundedBox(8, x, y - 80, barW, barH, Color(20, 20, 20, 230))
--
-- local fillW = (barW - 8) * (data.progress / 100)
-- local color = Color(100, 150, 255)
--
-- if (data.capturing == FACTION_RUSSIAN) then
-- color = Color(200, 50, 50)
-- elseif (data.capturing == FACTION_UKRAINE) then
-- color = Color(50, 100, 200)
-- end
--
-- draw.RoundedBox(6, x + 4, y - 76, fillW, barH - 8, color)
--
-- local text = string.format("%.0f%%", data.progress)
-- draw.SimpleText(text, "DermaLarge", 0, -80, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
-- end
--
-- local ownerText = "Никем не захвачена"
-- local ownerColor = Color(150, 150, 150)
--
-- if (data.owner and data.owner > 0) then
-- local faction = ix.faction.Get(data.owner)
-- if (faction) then
-- ownerText = faction.name
-- if (data.owner == FACTION_RUSSIAN) then
-- ownerColor = Color(200, 50, 50)
-- elseif (data.owner == FACTION_UKRAINE) then
-- ownerColor = Color(50, 100, 200)
-- end
-- end
-- end
--
-- draw.SimpleText(ownerText, "DermaLarge", 0, 0, ownerColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
--cam.End3D2D()
end
end

View File

@@ -0,0 +1,44 @@
PLUGIN.name = "Capture Points"
PLUGIN.author = "RefoselTeamWork"
PLUGIN.description = "Система захвата точек"
PLUGIN.captureRadius = 1024
PLUGIN.captureBaseTime = 35
PLUGIN.moneyReward = 3000
PLUGIN.arsenalReward = 500
PLUGIN.vehicleReward = 500
-- Настройки периодических наград
PLUGIN.tickInterval = 60 -- Интервал начисления в секундах
PLUGIN.tickSupplyPerPoint = 200 -- Очки снабжения за одну точку
PLUGIN.tickVehiclePerPoint = 150 -- Очки техники за одну точку
PLUGIN.hudPosX = 0
PLUGIN.hudPosY = 20
PLUGIN.hudWidth = 200
PLUGIN.hudHeight = 300
PLUGIN.labelOffsetZ = 80
PLUGIN.labelScale = 0.1
PLUGIN.factionMinOnline = {
[FACTION_RUSSIAN] = 1,
[FACTION_UKRAINE] = 0
}
PLUGIN.defaultPoints = {
{pos = Vector(-6788.718262, -2758.777832, 620.980103), ang = Angle(0, 90, 0)},
{pos = Vector(-386.355896, -13121.211914, 139.868973), ang = Angle(0, 90, 0)},
{pos = Vector(4969.474121, -10055.811523, 114.868973), ang = Angle(0, 90, 0)},
{pos = Vector(15625.968750, -13238.951172, 282.868958), ang = Angle(0, 90, 0)},
{pos = Vector(12809.052734, -4790.340820, 115.868973), ang = Angle(0, 90, 0)},
{pos = Vector(13539.985352, 4858.571289, 121.868973), ang = Angle(0, 90, 0)},
{pos = Vector(1916.585205, 2236.532715, 226.868958), ang = Angle(0, 90, 0)},
{pos = Vector(5527.783203, 2510.990479, 736.868958), ang = Angle(0, 90, 0)},
}
PLUGIN.minCapturePlayers = 1
ix.util.Include("sv_plugin.lua")
ix.util.Include("cl_plugin.lua")

View File

@@ -0,0 +1,414 @@
util.AddNetworkString("ixCaptureSync")
PLUGIN.capturePoints = PLUGIN.capturePoints or {}
function PLUGIN:GetPlayersInRadius(point, radius)
local players = {}
local pos = point:GetPos()
for _, ply in ipairs(player.GetAll()) do
if ply:Alive() and pos:Distance(ply:GetPos()) <= radius and not (ply.IsAdminMode and ply:IsAdminMode()) then
table.insert(players, ply)
end
end
return players
end
function PLUGIN:GetFactionFromPlayers(players)
local factions = {}
for _, ply in ipairs(players) do
local char = ply:GetCharacter()
if (char) then
local faction = char:GetFaction()
factions[faction] = (factions[faction] or 0) + 1
end
end
return factions
end
function PLUGIN:GetFactionOnlineCount(faction)
local count = 0
for _, ply in ipairs(player.GetAll()) do
local char = ply:GetCharacter()
if char and char:GetFaction() == faction and not (ply.IsAdminMode and ply:IsAdminMode()) then
count = count + 1
end
end
return count
end
function PLUGIN:CanFactionCapture(faction)
local minOnline = self.factionMinOnline[faction]
if (!minOnline) then return true end
local online = self:GetFactionOnlineCount(faction)
return online >= minOnline
end
function PLUGIN:CanCapture(factions)
local count = 0
for _ in pairs(factions) do
count = count + 1
end
return count == 1
end
function PLUGIN:GiveRewards(faction, players)
for _, ply in ipairs(players) do
local char = ply:GetCharacter()
if (char) then
char:GiveMoney(self.moneyReward)
ply:Notify("Вы получили " .. self.moneyReward .. " за захват точки!")
end
end
if (ix.plugin.list["arsenal"]) then
ix.plugin.list["arsenal"]:AddFactionSupply(faction, self.arsenalReward)
end
if (ix.plugin.list["vehicles"]) then
ix.plugin.list["vehicles"]:AddFactionPoints(faction, self.vehicleReward)
end
-- Логируем выдачу наград
local serverlogsPlugin = ix.plugin.list["serverlogs"]
if (serverlogsPlugin) then
local factionName = ix.faction.Get(faction).name or tostring(faction)
local message = string.format("Фракция '%s' получила награду за захват: %d снабжения, %d очков техники, %d денег на игрока",
factionName, self.arsenalReward, self.vehicleReward, self.moneyReward)
serverlogsPlugin:AddLog("CAPTURE_REWARD", message, nil, {
faction = faction,
factionName = factionName,
arsenalReward = self.arsenalReward,
vehicleReward = self.vehicleReward,
moneyReward = self.moneyReward,
playerCount = #players
})
end
end
function PLUGIN:ProcessCapture(point)
local players = self:GetPlayersInRadius(point, self.captureRadius)
if (#players == 0) then
if point.capturingFaction != nil then
point.capturingFaction = nil
point.capturingPlayers = 0
self:SyncCapturePoint(point)
end
return
end
local factions = self:GetFactionFromPlayers(players)
if (!self:CanCapture(factions)) then
if point.capturingFaction != nil or !point.captureBlocked then
point.capturingFaction = nil
point.capturingPlayers = 0
point.captureBlocked = true
self:SyncCapturePoint(point)
end
return
end
point.captureBlocked = false
local faction, playerCount = next(factions)
if (playerCount < self.minCapturePlayers) then
if point.capturingFaction != nil or !point.captureBlocked then
point.capturingFaction = nil
point.capturingPlayers = 0
point.captureBlocked = true
self:SyncCapturePoint(point)
end
return
end
if (!self:CanFactionCapture(faction)) then
if point.capturingFaction != nil or !point.captureBlocked then
point.capturingFaction = nil
point.capturingPlayers = 0
point.captureBlocked = true
self:SyncCapturePoint(point)
end
return
end
if (point.ownerFaction == faction) then
if point.captureProgress != 100 or point.capturingFaction != nil then
point.captureProgress = 100
point.capturingFaction = nil
point.capturingPlayers = 0
self:SyncCapturePoint(point)
end
return
end
-- Логируем начало захвата при первом касании
if (!point.capturingFaction or point.capturingFaction != faction) then
-- Сбрасываем прогресс если начинается захват другой фракцией
point.captureProgress = 0
-- Уведомляем владельцев о захвате
if (point.ownerFaction and point.ownerFaction != 0 and point.ownerFaction != faction) then
local capturerName = ix.faction.Get(faction).name or "Противник"
for _, v in ipairs(player.GetAll()) do
local char = v:GetCharacter()
if (char and char:GetFaction() == point.ownerFaction) then
v:Notify("ВНИМАНИЕ! Ваша точка захватывается фракцией " .. capturerName .. "!")
end
end
end
local serverlogsPlugin = ix.plugin.list["serverlogs"]
if (serverlogsPlugin) then
local factionName = ix.faction.Get(faction).name or tostring(faction)
local pointPos = tostring(point:GetPos())
local message = string.format("Фракция '%s' начала захват точки (позиция: %s)", factionName, pointPos)
serverlogsPlugin:AddLog("CAPTURE_START", message, nil, {
faction = faction,
factionName = factionName,
playerCount = playerCount,
pointPosition = pointPos
})
end
end
point.capturingFaction = faction
point.capturingPlayers = playerCount
local baseSpeed = 100 / self.captureBaseTime -- Progress per second
local captureSpeed = baseSpeed * playerCount * FrameTime()
point.captureProgress = (point.captureProgress or 0) + captureSpeed
if (point.captureProgress >= 100) then
point.captureProgress = 100
local oldOwner = point.ownerFaction
point.ownerFaction = faction
point:SetOwnerFactionID(faction)
point.capturingFaction = nil
point.capturingPlayers = 0
self:GiveRewards(faction, players)
self:SaveData()
-- Логируем успешный захват точки
local serverlogsPlugin = ix.plugin.list["serverlogs"]
if (serverlogsPlugin) then
local factionName = ix.faction.Get(faction).name or tostring(faction)
local pointPos = tostring(point:GetPos())
local oldFactionData = oldOwner and ix.faction.Get(oldOwner)
local oldFactionName = (oldFactionData and oldFactionData.name) or (oldOwner and tostring(oldOwner)) or "Нейтральная"
local message = string.format("Точка захвачена фракцией '%s' (предыдущий владелец: %s)", factionName, oldFactionName)
serverlogsPlugin:AddLog("CAPTURE_COMPLETE", message, nil, {
faction = faction,
factionName = factionName,
oldOwner = oldOwner,
oldOwnerName = oldFactionName,
playerCount = playerCount,
pointPosition = pointPos
})
end
for _, ply in ipairs(player.GetAll()) do
local char = ply:GetCharacter()
if (char and char:GetFaction() == faction) then
ply:Notify("Точка захвачена вашей фракцией!")
end
end
end
-- Only sync if progress changed significantly, something started/stopped, or a timer passed
local curTime = CurTime()
point.nextSync = point.nextSync or 0
if (point.lastSyncProgress == nil or
math.abs(point.captureProgress - point.lastSyncProgress) >= 1 or
curTime >= point.nextSync) then
self:SyncCapturePoint(point)
point.lastSyncProgress = point.captureProgress
point.nextSync = curTime + 0.2 -- Sync at most 5 times per second
end
end
function PLUGIN:SyncCapturePoint(point)
net.Start("ixCaptureSync")
net.WriteEntity(point)
net.WriteFloat(point.captureProgress or 0)
net.WriteUInt(point.ownerFaction or 0, 8)
net.WriteUInt(point.capturingFaction or 0, 8)
net.WriteUInt(point.capturingPlayers or 0, 8)
net.WriteBool(point.captureBlocked or false)
net.Broadcast()
end
function PLUGIN:Think()
if (!self.nextTickReward) then
self.nextTickReward = CurTime() + (self.tickInterval or 300)
elseif (CurTime() >= self.nextTickReward) then
self:ProcessPeriodicRewards()
self.nextTickReward = CurTime() + (self.tickInterval or 300)
end
for _, point in ipairs(self.capturePoints) do
if (IsValid(point)) then
self:ProcessCapture(point)
end
end
if (!self.nextAutoSave or CurTime() >= self.nextAutoSave) then
self:SaveData()
self.nextAutoSave = CurTime() + 60
end
end
function PLUGIN:RegisterCapturePoint(point)
table.insert(self.capturePoints, point)
point.captureProgress = 0
point.ownerFaction = nil
point:SetOwnerFactionID(0)
point.capturingFaction = nil
point.capturingPlayers = 0
end
function PLUGIN:EntityRemoved(entity)
if (entity:GetClass() == "ix_capture_point") then
for i, point in ipairs(self.capturePoints) do
if (point == entity) then
table.remove(self.capturePoints, i)
break
end
end
end
end
function PLUGIN:SaveData()
local data = {}
for _, point in ipairs(ents.FindByClass("ix_capture_point")) do
if IsValid(point) then
data[#data + 1] = {
pos = point:GetPos(),
angles = point:GetAngles(),
ownerFaction = point.ownerFaction or 0,
captureProgress = point.captureProgress or 0
}
end
end
self:SetData(data)
end
function PLUGIN:LoadData()
local data = self:GetData()
if (!data or #data == 0) then
for _, v in ipairs(self.defaultPoints or {}) do
local point = ents.Create("ix_capture_point")
if IsValid(point) then
point:SetPos(v.pos)
point:SetAngles(v.ang)
point:Spawn()
timer.Simple(0.1, function()
if IsValid(point) then
point.ownerFaction = 0
point:SetOwnerFactionID(0)
point.captureProgress = 0
end
end)
end
end
return
end
for _, v in ipairs(data) do
local point = ents.Create("ix_capture_point")
if IsValid(point) then
point:SetPos(v.pos)
point:SetAngles(v.angles)
point:Spawn()
timer.Simple(0.1, function()
if IsValid(point) then
point.ownerFaction = v.ownerFaction
point:SetOwnerFactionID(v.ownerFaction or 0)
point.captureProgress = v.captureProgress or 0
self:SyncCapturePoint(point)
end
end)
end
end
end
function PLUGIN:OnUnloaded()
self:SaveData()
end
-- Подсчет захваченных точек каждой фракцией
function PLUGIN:GetCapturedPointsCount()
local counts = {}
for _, point in ipairs(self.capturePoints) do
if IsValid(point) and point.ownerFaction and point.ownerFaction ~= 0 then
counts[point.ownerFaction] = (counts[point.ownerFaction] or 0) + 1
end
end
return counts
end
-- Периодическое начисление очков
function PLUGIN:ProcessPeriodicRewards()
local counts = self:GetCapturedPointsCount()
for faction, pointCount in pairs(counts) do
if pointCount > 0 then
local supplyReward = pointCount * self.tickSupplyPerPoint
local vehicleReward = pointCount * self.tickVehiclePerPoint
if ix.plugin.list["arsenal"] then
ix.plugin.list["arsenal"]:AddFactionSupply(faction, supplyReward)
end
if ix.plugin.list["vehicles"] then
ix.plugin.list["vehicles"]:AddFactionPoints(faction, vehicleReward)
end
local factionName = ix.faction.Get(faction).name or "Фракция"
for _, ply in ipairs(player.GetAll()) do
local char = ply:GetCharacter()
if char and char:GetFaction() == faction then
ply:Notify(string.format("Ваша фракция получила: +%d снабжения, +%d очков техники (точек: %d)",
supplyReward, vehicleReward, pointCount))
end
end
end
end
end
ix.command.Add("CaptureSystemSave", {
description = "Сохранить точки захвата",
superAdminOnly = true,
OnRun = function(self, client)
local plugin = ix.plugin.Get("capture")
if (!plugin) then
return "@commandNoExist"
end
plugin:SaveData()
local count = #ents.FindByClass("ix_capture_point")
client:Notify("Точки захвата сохранены (" .. count .. " шт.)")
end
})