add sborka
This commit is contained in:
414
garrysmod/gamemodes/militaryrp/plugins/capture/sv_plugin.lua
Normal file
414
garrysmod/gamemodes/militaryrp/plugins/capture/sv_plugin.lua
Normal 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
|
||||
})
|
||||
Reference in New Issue
Block a user