--[[------------------------------------------ A.P.G. - a lightweight Anti Prop Griefing solution (v2.2.0) Made by : - While True (http://steamcommunity.com/id/76561197972967270) - LuaTenshi (http://steamcommunity.com/id/76561198096713277) Licensed to : http://steamcommunity.com/id/76561198136465722 ]]-------------------------------------------- APG_panels = APG_panels or {} local utils = include( "cl_utils.lua" ) or { } local function APGBuildStackPanel() local panel = APG_panels["stack_detection"] panel.Paint = function( i, w, h) end utils.numSlider(panel, 0, 40, 500, 20, "Maximum stacked ents", "stackMax", 3, 50, 0 ) utils.numSlider(panel, 0, 75, 500, 20, "Stack distance (gmod units)", "stackArea", 5, 50, 0) end local function APGBuildMiscPanel() local panel = APG_panels["misc"] panel.Paint = function( i, w, h) end utils.switch( panel, 0, 40, 395, 20, "Auto freeze over time", "autoFreeze" ) utils.numSlider(panel, 0, 70, 500, 20, "Auto freeze delay(seconds)", "autoFreezeTime", 5, 600, 0 ) utils.switch( panel, 0, 100, 395, 20, "Disable vehicle damages", "vehDamage" ) utils.switch( panel, 0, 130, 395, 20, "Disable vehicle collisions (with players)", "vehNoCollide" ) utils.switch( panel, 0, 160, 395, 20, "Block Physgun Reload", "blockPhysgunReload" ) --APG_numSlider(panel, 0, 75, 500, 20, "Vehicle NoCollide", "vehNoCollide", 5, 50, 0) end local function APGBuildLagPanel() local panel = APG_panels["lag_detection"] panel.Paint = function( i, w, h) end utils.numSlider(panel, 0, 40, 500, 20, "Lag threshold (%)", "lagTrigger", 5, 1000, 0 ) utils.numSlider(panel, 0, 75, 500, 20, "Frames lost", "lagsCount", 1, 20, 0) utils.numSlider(panel, 0, 110, 500, 20, "Heavy lag trigger (seconds)", "bigLag", 1, 5, 1) utils.comboBox(panel, 0, 145, 500, 20, "Lag fix function", "lagFunc", APG_lagFuncs) utils.numSlider(panel, 0, 180, 500, 20, "Lag func. delay (seconds)", "lagFuncTime", 1, 300, 0) --utils.numSlider(panel, 0, 215, 500, 20, "Notification mode ", "lagFuncNotify", 0, 2, 0) end local function APGBuildToolHackPanel() local panel = APG_panels["misc2"] panel.Paint = function( i, w, h) end utils.switch( panel, 0, 40, 395, 20, "Inject custom hooks into Fading Doors", "thFadingDoors" ) utils.switch( panel, 0, 75, 395, 20, "Activate fading door ghosting", "FadingDoorGhosting" ) utils.switch( panel, 0, 105, 395, 20, "Activate FRZR9K (Sleepy Physics)", "frzr9k" ) utils.switch( panel, 0, 135, 395, 20, "Allow prop killing (Won't work well with ghosting)", "AllowPK" ) end local function APGBuildGhostPanel() local panel = APG_panels["ghosting"] panel.Paint = function( i, w, h) draw.RoundedBox(0,0,37,170,135,Color( 38, 38, 38, 255)) draw.DrawText( "Ghosting color:", "APG_element_font",5, 37, Color( 189, 189, 189), 3 ) draw.RoundedBox(0,175,37,250,250,Color( 38, 38, 38, 255)) draw.DrawText( "Bad entities:", "APG_element_font", 180, 37, Color( 189, 189, 189), 3 ) draw.DrawText( "(Right-Click to Toggle)", "APG_title2_font", 280, 38, Color( 189, 189, 189), 3 ) end utils.switch( panel, 0, 180, 170, 20, "Always frozen", "alwaysFrozen" ) local Mixer = vgui.Create( "CtrlColor", panel ) Mixer:SetPos(5,55) Mixer:SetSize(160,110) Mixer.Mixer.ValueChanged = function(self,color) APG.cfg["ghost_color"].value = Color( color.r, color.g, color.b, color.a) end local dList = vgui.Create("DListView", panel) dList:Clear() dList:SetPos( 180, 55 ) dList:SetSize(panel:GetWide() - 185, panel:GetTall()-5-55) dList:SetMultiSelect(false) dList:SetHideHeaders(false) dList:AddColumn("Class") dList:AddColumn("Exact") function dList:OnRowRightClick( id, line ) local key = line:GetColumnText(1) local value = !tobool(line:GetColumnText(2)) line:SetColumnText(2, value) APG.cfg["bad_ents"].value[key] = value end local function updtTab() dList:Clear() for class,complete in pairs(APG.cfg["bad_ents"].value) do dList:AddLine(class, complete) end end updtTab() dList.Paint = function(i,w,h) draw.RoundedBox(0,0,0,w,h,Color(150, 150, 150, 255)) end dList.VBar.Paint = function(i,w,h) surface.SetDrawColor(88, 110, 110, 240) surface.DrawRect(0,0,w,h) end dList.VBar.btnGrip.Paint = function(i,w,h) surface.SetDrawColor(255, 83, 13,50) surface.DrawRect(0,0,w,h) draw.RoundedBox( 0, 1,1,w-2,h-2, Color( 72, 89, 89, 255 ) ) end dList.VBar.btnUp.Paint = function(i,w,h) draw.RoundedBox( 0, 0,0,w,h, Color( 72, 89, 89, 240 ) ) end dList.VBar.btnDown.Paint = function(i,w,h) draw.RoundedBox( 0, 0,0,w,h, Color( 72, 89, 89, 240 ) ) end local TextEntry = vgui.Create( "DTextEntry", panel ) TextEntry:SetPos( 180, 240 ) TextEntry:SetSize( 150,20 ) TextEntry:SetText( "Entity class" ) TextEntry.OnEnter = function( self ) chat.AddText( self:GetValue() ) end local Add = vgui.Create( "DButton" , panel) Add:SetPos( 320, 240 ) Add:SetSize( 75,20 ) Add:SetText( "Add" ) Add.DoClick = function() if TextEntry:GetValue() == "Entity class" then return end utils.addBadEntity( TextEntry:GetValue() ) updtTab() end Add:SetTextColor(Color(255,255,255)) Add.Paint = function(i,w,h) draw.RoundedBox(0,0,0,w,h,Color(44, 55, 55, 240)) draw.RoundedBox(0,1,1,w-2,h-2,Color( 58, 58, 58, 255)) end local Remove = vgui.Create( "DButton" , panel) Remove:SetPos( 180, 260 ) Remove:SetSize( 215,20 ) Remove:SetText( "Remove selected" ) Remove.DoClick = function() for k,v in pairs(dList:GetSelected()) do local key = v:GetValue(1) APG.cfg["bad_ents"].value[key] = nil updtTab() end end Remove:SetTextColor(Color(255,255,255)) Remove.Paint = function(i,w,h) draw.RoundedBox(0,0,0,w,h,Color( 58, 58, 58, 255)) draw.RoundedBox(0,0,0,w,1,Color(30, 30, 30, 125)) end end local main_color = Color(32, 255, 0,255) local function openMenu( len ) len = net.ReadUInt( 32 ) if len == 0 then return end local settings = net.ReadData( len ) settings = util.Decompress( settings ) settings = util.JSONToTable( settings ) APG.cfg = settings.cfg table.Merge(APG, settings) local APG_Main = vgui.Create( "DFrame" ) APG_Main:SetSize( 550 , 320) APG_Main:SetPos( ScrW()/2- APG_Main:GetWide()/2, ScrH()/2 - APG_Main:GetTall()/2) APG_Main:SetTitle( "" ) APG_Main:SetVisible( true ) APG_Main:SetDraggable( true ) APG_Main:MakePopup() APG_Main:ShowCloseButton(false) APG_Main.Paint = function(i,w,h) draw.RoundedBox(4,0,0,w,h,Color(34, 34, 34,255)) draw.RoundedBox(0,0,23,w,1,main_color) local name = "A.P.G. - Anti Prop Griefing Solution" draw.DrawText( name, "APG_title_font",8, 5, Color( 189, 189, 189), 3 ) end local closeButton = vgui.Create("DButton",APG_Main) closeButton:SetPos(APG_Main:GetWide() - 20,4) closeButton:SetSize(16,16) closeButton:SetText('') closeButton.DoClick = function() APG_Main:Remove() end closeButton.Paint = function(i,w,h) draw.RoundedBox(0,0,0,w,h,Color(255, 255, 255,3)) draw.DrawText( "✕", "APG_sideBar_font",0, -2, Color( 189, 189, 189), 3 ) end local saveButton = vgui.Create("DButton",APG_Main) saveButton:SetPos(APG_Main:GetWide() - 96,4) saveButton:SetSize(72,16) saveButton:SetText('') saveButton.DoClick = function() local settings = APG settings = util.TableToJSON( settings ) settings = util.Compress( settings ) net.Start("apg_settings_c2s") net.WriteUInt( settings:len(), 32 ) -- Write the length of the data (up to 172054108) net.WriteData( settings, settings:len() ) -- Write the data net.SendToServer() APG_Main:Remove() end saveButton.Paint = function(i,w,h) draw.RoundedBox(0,0,0,w,h,Color(255, 255, 255,3)) draw.DrawText( "Save settings", "APG_title2_font",w/2, 1, Color( 189, 189, 189), 1 ) end -- Side bar local sidebar = vgui.Create("DPanel",APG_Main) sidebar:SetSize( APG_Main:GetWide() / 4 , APG_Main:GetTall() - 35) sidebar:SetPos(0,30) sidebar.Paint = function(i,w,h) draw.RoundedBox(0,0,0,w,h,Color( 33, 33, 33,255)) draw.RoundedBox(0,w-1,0,1,h,main_color) end local x,y = APG_Main:GetWide() - 150,APG_Main:GetTall() - 35 local px, py = 145,30 local first = true for k, v in next, APG.modules do local panel = vgui.Create("DPanel",APG_Main) panel:SetSize(x,y) panel:SetPos(px, py) panel:SetVisible(first) panel.Paint = function() end APG_panels[k] = panel first = false local button = vgui.Create("DButton",panel) button:SetPos(0,0) button:SetSize(panel:GetWide(),35) button:SetText("") button.UpdateColours = function( label, skin ) label:SetTextStyleColor( Color( 189, 189, 189 ) ) end button.Paint = function(slf, w, h) local enabled = APG.modules[k] draw.RoundedBox(0,0,h*0.85,w-5,1, Color(0, 96, 0,255)) local text = utils.getNiceName(k) .. " module " draw.DrawText( text, "APG_mainPanel_font",5, 8, Color( 189, 189, 189), 3 ) utils.mainSwitch( w-48, 7.5, enabled ) end button.DoClick = function() APG.modules[k] = not APG.modules[k] end end local i = 0 local height = (sidebar:GetTall() - 20) / table.Count(APG.modules) for k,v in next , APG.modules do local button = vgui.Create("DButton",sidebar) button:SetPos(5,(height + 5) * i) button:SetSize(sidebar:GetWide() - 10 ,height) button:SetText("") button.DoClick = function() for l,m in next, APG_panels do if k != l then APG_panels[l]:SetVisible(false) else APG_panels[l]:SetVisible(true) end end end local size = sidebar:GetWide() button.Paint = function(_,w,h) local name = utils.getNiceName(k) if button.Hovered then draw.RoundedBox(5,0,0,w,h,Color(46, 46, 46,255)) draw.RoundedBox(0,2,2,w-4,h-4,Color( 36, 36,36, 255)) end if APG_panels[k]:IsVisible() then draw.RoundedBox(0,0,0,w,h,Color( 36, 36,36, 255)) draw.RoundedBox(0,w*0.15,h*0.72,w*0.7,1, Color(0, 96, 0,255)) end draw.DrawText( name, "APG_sideBar_font",(size - name:len())/2, h*0.35, Color( 189, 189, 189), 1) end i = i + 1 end APGBuildMiscPanel() APGBuildGhostPanel() APGBuildLagPanel() APGBuildStackPanel() APGBuildToolHackPanel() end net.Receive( "apg_menu_s2c", openMenu ) local function showNotice() local level = tonumber(net.ReadUInt(3)) local msg = tostring(net.ReadString()) octolib.notify.show(level == 0 and 'rp' or level == 1 and 'ooc' or level == 2 and 'warning', msg) surface.PlaySound(level == 1 and "common/wpn_denyselect.wav" or level == 2 and "common/wpn_denyselect.wav" or "buttons/button15.wav") MsgC(level == 0 and Color(0,255,0) or Color(255,191,0), "[APG] ", Color(255,255,255), msg,"\n") end net.Receive( "apg_notice_s2c", showNotice ) properties.Add( "apgoptions", { MenuLabel = "APG Options", -- Name to display on the context menu Order = 9999, -- The order to display this property relative to other properties MenuIcon = "icon16/fire.png", -- The icon to display next to the property Filter = function( self, ent, ply ) -- A function that determines whether an entity is valid for this property if not ply:IsSuperAdmin() then return false end return (ent.GetClass and ent:GetClass() and IsValid(ent) and ent:EntIndex() > 0) end, MenuOpen = function( self, option, ent, tr ) local submenu = option:AddSubMenu() local function addoption(str, data) local menu = submenu:AddOption(str, data.callback) if data.icon then menu:SetImage( data.icon ) end return menu end addoption( "Sleep entities of this Class", { icon = "icon16/clock.png", callback = function() self:APGcmd(ent, "sleepclass") end, }) addoption( "Freeze entities of this Class", { icon = "icon16/bell_delete.png", callback = function() self:APGcmd(ent, "freezeclass") end, }) submenu:AddSpacer() addoption( "Cleanup Owner - Unfrozens", { icon = "icon16/cog_delete.png", callback = function() self:APGcmd(ent, "clearunfrozen") end, }) addoption( "Cleanup Owner", { icon = "icon16/bin_closed.png", callback = function() self:APGcmd(ent, "clearowner") end, }) submenu:AddSpacer() addoption( "Get Owner SteamID", { icon = "icon16/user.png", callback = function() self:APGcmd(ent, "getownerid") end, }) addoption( "Get Owner Entity Count", { icon = "icon16/brick.png", callback = function() self:APGcmd(ent, "getownercount") end, }) submenu:AddSpacer() addoption( "Add this entity class to the Ghosting List", { icon = "icon16/cross.png", callback = function() self:APGcmd(ent, "addghost") end, }) addoption( "Remove this entity class from the Ghosting List", { icon = "icon16/tick.png", callback = function() self:APGcmd(ent, "remghost") end, }) end, Action = function( self, ent ) end, APGcmd = function(self, ent, cmd) if cmd == "getownerid" then local owner, _ = ent:CPPIGetOwner() if IsValid(owner) and owner.SteamID then local id = tostring(owner:SteamID()) SetClipboardText(id) chat.AddText(Color(0,255,0), "\n\""..id.."\" has been copied to your clipboard.\n") else chat.AddText(Color(255,0,0), "\nOops, that's not a Player!\n") end elseif IsValid(ent) and ent.EntIndex then net.Start("apg_context_c2s") net.WriteString(cmd) net.WriteEntity(ent) net.SendToServer() end end, })