Files
VnUtest/garrysmod/gamemodes/militaryrp/plugins/capture/sv_plugin.lua
2026-03-31 10:27:04 +03:00

415 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.
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
})