local PLUGIN = PLUGIN PLUGIN.lastMarkerPress = 0 -- Клиентские данные PLUGIN.currentSquad = PLUGIN.currentSquad or nil PLUGIN.activeMarkers = PLUGIN.activeMarkers or {} -- Получение сетевых данных net.Receive("ixSquadSync", function() local jsonData = net.ReadString() local data = util.JSONToTable(jsonData) -- Если пришла пустая таблица - очищаем данные отряда if not data or not data.id then PLUGIN.currentSquad = nil -- Очищаем маркеры for _, markerID in ipairs(PLUGIN.activeMarkers) do if Adv_Compass_RemoveMarker then Adv_Compass_RemoveMarker(markerID) end end PLUGIN.activeMarkers = {} else PLUGIN.currentSquad = data end end) net.Receive("ixSquadNotify", function() local message = net.ReadString() LocalPlayer():Notify(message) end) net.Receive("ixSquadInvite", function() local squadID = net.ReadString() local inviterName = net.ReadString() -- Создаем окно приглашения local frame = vgui.Create("DFrame") frame:SetSize(400, 150) frame:Center() frame:SetTitle("") frame:SetDraggable(false) frame:ShowCloseButton(false) frame:MakePopup() frame.Paint = function(s, w, h) draw.RoundedBox(8, 0, 0, w, h, Color(25, 25, 28)) surface.SetDrawColor(Color(1, 67, 29)) surface.DrawRect(0, 0, w, 3) end local title = vgui.Create("DLabel", frame) title:SetPos(0, 20) title:SetSize(400, 30) title:SetFont("F4Menu_Category") title:SetTextColor(Color(255, 255, 255)) title:SetText("Приглашение в отряд") title:SetContentAlignment(5) local text = vgui.Create("DLabel", frame) text:SetPos(20, 55) text:SetSize(360, 40) text:SetFont("F4Menu_Item") text:SetTextColor(Color(200, 200, 200)) text:SetText(inviterName .. " приглашает вас вступить в отряд") text:SetContentAlignment(5) text:SetWrap(true) local acceptBtn = vgui.Create("DButton", frame) acceptBtn:SetPos(20, 105) acceptBtn:SetSize(175, 30) acceptBtn:SetText("Принять") acceptBtn:SetFont("F4Menu_Item") acceptBtn:SetTextColor(Color(255, 255, 255)) acceptBtn.Paint = function(s, w, h) draw.RoundedBox(6, 0, 0, w, h, s:IsHovered() and Color(1, 87, 39) or Color(1, 67, 29)) end acceptBtn.DoClick = function() net.Start("ixSquadAcceptInvite") net.SendToServer() frame:Close() end local declineBtn = vgui.Create("DButton", frame) declineBtn:SetPos(205, 105) declineBtn:SetSize(175, 30) declineBtn:SetText("Отклонить") declineBtn:SetFont("F4Menu_Item") declineBtn:SetTextColor(Color(255, 255, 255)) declineBtn.Paint = function(s, w, h) draw.RoundedBox(6, 0, 0, w, h, s:IsHovered() and Color(70, 25, 25) or Color(50, 25, 25)) end declineBtn.DoClick = function() net.Start("ixSquadDeclineInvite") net.SendToServer() frame:Close() end -- Автоматическое закрытие через 30 секунд timer.Simple(30, function() if IsValid(frame) then frame:Close() end end) end) PLUGIN.worldMarker = nil PLUGIN.nextMarkerTime = 0 net.Receive("ixSquadWorldMarker", function() local pos = net.ReadVector() local name = net.ReadString() PLUGIN.worldMarker = { pos = pos, name = name, expire = CurTime() + 10 } end) net.Receive("ixSquadUpdateMarkers", function() for _, markerID in ipairs(PLUGIN.activeMarkers) do if Adv_Compass_RemoveMarker then Adv_Compass_RemoveMarker(markerID) end end PLUGIN.activeMarkers = {} local count = net.ReadUInt(8) local markerColor = ix.config.Get("squadMarkerColor", Color(0, 255, 0)) for i = 1, count do local pos = net.ReadVector() local name = net.ReadString() local ent = net.ReadEntity() if IsValid(ent) and mCompass_AddEntityMarker then -- Используем маркер на сущности для отслеживания движения local markerID = mCompass_AddEntityMarker( LocalPlayer(), ent, {LocalPlayer()}, CurTime() + 1, -- 1 секунда (обновляется регулярно) markerColor, "", -- Иконка (пустая, используем стандартную) name ) table.insert(PLUGIN.activeMarkers, markerID) end end end) -- Очистка при закрытии function PLUGIN:ShutDown() for _, markerID in ipairs(self.activeMarkers) do if Adv_Compass_RemoveMarker then Adv_Compass_RemoveMarker(markerID) end end self.activeMarkers = {} end -- Вспомогательные функции function PLUGIN:GetCurrentSquad() return self.currentSquad end function PLUGIN:IsInSquad() return self.currentSquad ~= nil end function PLUGIN:IsSquadLeader() if not self.currentSquad then return false end return self.currentSquad.leader == LocalPlayer():SteamID() end PLUGIN.wasGPressed = false PLUGIN.nextMarkerTime = 0 hook.Add("Think", "ixSquadPlaceMarkerKey", function() local ply = LocalPlayer() if not IsValid(ply) then return end if vgui.CursorVisible() then return end if gui.IsGameUIVisible() then return end if ix and ix.gui and ix.gui.menu and IsValid(ix.gui.menu) then return end local isDown = input.IsKeyDown(KEY_G) if isDown and not PLUGIN.wasGPressed then PLUGIN.wasGPressed = true if not PLUGIN:IsInSquad() then LocalPlayer():Notify("Вы не состоите в отряде") return end if CurTime() < PLUGIN.nextMarkerTime then LocalPlayer():Notify("Метка будет доступна через " .. math.ceil(PLUGIN.nextMarkerTime - CurTime()) .. " сек.") return end local tr = ply:GetEyeTrace() if not tr.Hit then return end PLUGIN.nextMarkerTime = CurTime() + 5 net.Start("ixSquadPlaceMarker") net.WriteVector(tr.HitPos) net.SendToServer() end if not isDown then PLUGIN.wasGPressed = false end end) local icon = Material("materials/squads/eye1.png") hook.Add("HUDPaint", "ixSquadDrawWorldMarkerHUD", function() local m = PLUGIN.worldMarker if not m then return end if CurTime() > m.expire then PLUGIN.worldMarker = nil return end local screen = m.pos:ToScreen() local dist = LocalPlayer():GetPos():Distance(m.pos) local scale = math.Clamp(1 - (dist / 3000), 0.4, 1) local size = 96 surface.SetMaterial(icon) surface.SetDrawColor(255, 255, 255, 255) surface.DrawTexturedRect(screen.x - size/2, screen.y - size/2, size, size) surface.SetFont("DermaLarge") local tw, th = surface.GetTextSize(m.name) draw.SimpleText( m.name, "DermaLarge", screen.x, screen.y + size/2 + 10, Color(255, 255, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, scale ) end)