Initial commit

This commit is contained in:
2026-03-15 14:54:49 +03:00
commit 64f8029c06
4027 changed files with 254888 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,571 @@
surface.CreateFont('ui.60', {font = 'roboto', size = 60, weight = 700, extended = true})
surface.CreateFont('ui.40', {font = 'roboto', size = 40, weight = 500, extended = true})
surface.CreateFont('ui.39', {font = 'roboto', size = 39, weight = 500, extended = true})
surface.CreateFont('ui.38', {font = 'roboto', size = 38, weight = 500, extended = true})
surface.CreateFont('ui.37', {font = 'roboto', size = 37, weight = 500, extended = true})
surface.CreateFont('ui.36', {font = 'roboto', size = 36, weight = 500, extended = true})
surface.CreateFont('ui.35', {font = 'roboto', size = 35, weight = 500, extended = true})
surface.CreateFont('ui.34', {font = 'roboto', size = 34, weight = 500, extended = true})
surface.CreateFont('ui.33', {font = 'roboto', size = 33, weight = 500, extended = true})
surface.CreateFont('ui.32', {font = 'roboto', size = 32, weight = 500, extended = true})
surface.CreateFont('ui.31', {font = 'roboto', size = 31, weight = 500, extended = true})
surface.CreateFont('ui.30', {font = 'roboto', size = 30, weight = 500, extended = true})
surface.CreateFont('ui.29', {font = 'roboto', size = 29, weight = 500, extended = true})
surface.CreateFont('ui.28', {font = 'roboto', size = 28, weight = 500, extended = true})
surface.CreateFont('ui.27', {font = 'roboto', size = 27, weight = 400, extended = true})
surface.CreateFont('ui.26', {font = 'roboto', size = 26, weight = 400, extended = true})
surface.CreateFont('ui.25', {font = 'roboto', size = 25, weight = 400, extended = true})
surface.CreateFont('ui.24', {font = 'roboto', size = 24, weight = 400, extended = true})
surface.CreateFont('ui.23', {font = 'roboto', size = 23, weight = 400, extended = true})
surface.CreateFont('ui.22', {font = 'roboto', size = 22, weight = 400, extended = true})
surface.CreateFont('ui.20', {font = 'roboto', size = 20, weight = 400, extended = true})
surface.CreateFont('ui.19', {font = 'roboto', size = 19, weight = 400, extended = true})
surface.CreateFont('ui.18', {font = 'roboto', size = 18, weight = 400, extended = true})
surface.CreateFont('ui.17', {font = 'roboto', size = 17, weight = 550, extended = true})
surface.CreateFont('ui.16', {font = 'roboto', size = 16, weight = 550, extended = true})
surface.CreateFont('ui.15', {font = 'roboto', size = 15, weight = 550, extended = true})
surface.CreateFont('ui.12', {font = 'roboto', size = 12, weight = 550, extended = true})
surface.CreateFont('ui.10', {font = 'roboto', size = 10, weight = 550, extended = true})
surface.CreateFont('ui.5percent', {font = 'roboto', size = math.ceil(ScrH() * 0.05), weight = 500, extended = true})
local CurTime = CurTime
local IsValid = IsValid
local ipairs = ipairs
local Color = Color
local DrawColorModify = DrawColorModify
local nw_GetGlobal = GetGlobalBool
local table_Filter = table.Filter
local player_GetAll = player.GetAll
local hook_Call = hook.Call
local GM = GAMEMODE or {}
timer.Simple(0.1,function()
GM = GAMEMODE
end)
local smoothHP = 0
local smoothAR = 0
local smoothHG = 0
local math_ceil = math.ceil
local math_sin = math.sin
local math_max = math.max
local draw_SimpleText = draw.SimpleText
local draw_SimpleTextOutlined = draw.SimpleTextOutlined
local draw_OutlinedBox = draw.OutlinedBox
local function draw_Box(x,y,w,h,col)
draw.RoundedBox(0,x,y,w,h,col)
end
local surface_SetDrawColor = surface.SetDrawColor
local surface_DrawLine = surface.DrawLine
local surface_DrawTexturedRect = surface.DrawTexturedRect
local surface_GetTextSize = surface.GetTextSize
local surface_SetFont = surface.SetFont
local surface_SetMaterial = surface.SetMaterial
local surface_DrawOutlinedRect = surface.DrawOutlinedRect
local surface_SetTextPos = surface.SetTextPos
local surface_SetTextColor = surface.SetTextColor
local surface_DrawText = surface.DrawText
local surface_DrawRect = surface.DrawRect
local cam_Start3D2D = cam.Start3D2D
local cam_End3D2D = cam.End3D2D
local color_white = color_white
local color_black = color_black
local color_red = Color(245,0,0)
local color_orange = Color(245,120,0)
local color_blue = Color(51,128,255)
local color_darkred = Color(100, 0, 0)
local color_15k = Color(240,191,0)
local color_gradient = Color(50, 50, 50)
local color_bg = Color(15,15,15,255)
local color_outline = Color(75,75,75,255):Copy()
local color_money = Color(135, 135, 31, 60)
local color_health = Color(82, 158, 60, 255)
local color_ph_health = Color(82, 158, 60, 60)
local color_armor = Color(37, 112, 153, 255)
local color_ph_armor = Color(37, 112, 153, 60)
local color_food = Color(217, 155, 11, 255)
local color_ph_food = Color(217, 155, 11, 60)
local color_job = Color(35, 31, 32, 60)
local color_grace = Color(76, 24, 84, 255)
local color_sup = Color(27, 82, 102, 60)
local color_agenda = Color(33, 92, 132, 60)
local color_laws = Color(135, 33, 33, 60)
local color_arrest_warrants = Color(211, 36, 36, 60)
local color_hits = Color(40, 40, 40, 60)
local lic_icon = Material("icon16/page.png")
local mat_laws = lic_icon
local material_licence = mat_laws
local hp_icon = Material("icon16/heart.png")
local ar_icon = Material("icon16/shield.png")
local hg_icon = Material("icon16/cup.png")
local want_icon = Material("icon16/star.png")
local money_icon = Material("icon16/money.png")
local time_icon = Material("icon16/clock.png")
local job_icon = Material("icon16/vcard.png")
local sw, sh = ScrW(), ScrH()
local height = 0
local LP
local players = {}
surface.CreateFont("Hud", {
font = "EuropaNuovaExtraBold",
extended = true,
size = 25,
weight = 500,
antialias = true,
})
surface.CreateFont("HudS", {
font = "EuropaNuovaExtraBold",
extended = true,
size = 23,
weight = 500,
antialias = true,
})
surface.CreateFont('HudFont', {
font = 'Tahoma',
size = 20,
weight = 350
})
surface.CreateFont('HudFontLaws', {
font = 'Roboto',
size = 19,
extended = true,
shadow = true,
weight = 350
})
surface.CreateFont('HudFont2', {
font = 'Tahoma',
size = 24,
weight = 700
})
surface.CreateFont('HudFont3', {
font = 'Tahoma',
size = 30,
weight = 700
})
surface.CreateFont('BannedInfo', {
font = 'Roboto',
size = 42,
weight = 700
})
surface.CreateFont('PlayerInfo', {
font = 'Tahoma',
extended = true,
outline = true,
shadow = true,
size = 128,
weight = 750
})
local talkingplayers = {}
hook.Add('PlayerStartVoice', 'rp.hud.PlayerStartVoice', function(pl)
talkingplayers[pl] = true
end)
hook.Add('PlayerEndVoice', 'rp.hud.PlayerEndVoice', function(pl)
talkingplayers[pl] = nil
end)
-- utils
local ColValues = {}
local function varcol(name, val)
if ColValues[name] == nil then
ColValues[name] = {}
ColValues[name].Old = val
ColValues[name].Flash = SysTime()
return color_white
end
if ColValues[name].Old ~= val then
ColValues[name].Flash = SysTime() + 0.2
ColValues[name].Old = val
return color_blue
end
if ColValues[name].Flash > SysTime() then
return color_blue
end
return color_white
end
local function SecondsToClock(seconds)
local seconds = tonumber(seconds)
if seconds <= 0 then
return "00:00:00";
else
hours = string.format("%02.f", math.floor(seconds/3600));
mins = string.format("%02.f", math.floor(seconds/60 - (hours*60)));
secs = string.format("%02.f", math.floor(seconds - hours*3600 - mins *60));
return hours..":"..mins..":"..secs
end
end
local blur = Material( "pp/blurscreen" )
function drawBlur( x, y, w, h, layers, density, alpha )
surface.SetDrawColor( 255, 255, 255, alpha )
surface.SetMaterial( blur )
for i = 1, layers do
blur:SetFloat( "$blur", ( i / layers ) * density )
blur:Recompute()
render.UpdateScreenEffectTexture()
render.SetScissorRect( x, y, x + w, y + h, true )
surface.DrawTexturedRect( 0, 0, ScrW(), ScrH() )
render.SetScissorRect( 0, 0, 0, 0, false )
end
end
function drawBlurPadded(x,y,w,h,layers,density,alpha,color)
--draw.RoundedBox(0,x,y,w,h,color)
drawBlur(x,y,w,h,layers,density,alpha)
surface_SetDrawColor(255,255,255,150)
surface_DrawOutlinedRect(x,y,w,h,2)
end
local function InfoBar()
if not IsValid(LP) then return end
local health = LP:Health()
function numh(numtokok)
if numtokok > 100 then
return 100
end
if numtokok <= 100 and numtokok >= 0 then
return numtokok
end
if numtokok < 0 then
return 0
end
end
smoothHP = numh(Lerp(10 * FrameTime(), smoothHP, health))
drawBlurPadded(10,ScrH()-170,450,50,3,5,255,Color(0,0,0,200))
draw_SimpleText("ММК RolePlay","ui.30",180,ScrH()-145,color_white,2,1)
drawBlurPadded(10,ScrH()-115,450,110,3,5,255,Color(0,0,0,200))
draw.RoundedBox(3,20,ScrH()-150+50,150,25,Color(122,89,89))
draw.RoundedBox(3,20,ScrH()-150+50,smoothHP*1.5,25,Color(222,91,91))
draw_SimpleText(health.."%","ui.20",168,ScrH()-137+50,color_white,2,1)
surface_SetDrawColor(color_white)
surface_SetMaterial(hp_icon)
local armor = LP:Armor()
smoothAR = numh(Lerp(10 * FrameTime(), smoothAR, armor))
surface_DrawTexturedRect(23,ScrH()-147+50,20,20)
draw.RoundedBox(3,20,ScrH()-120+50,150,25,Color(93,128,143))
draw.RoundedBox(3,20,ScrH()-120+50,smoothAR*1.5,25,Color(98,181,217))
draw_SimpleText(armor.."%","ui.20",168,ScrH()-107+50,color_white,2,1)
surface_SetDrawColor(color_white)
surface_SetMaterial(ar_icon)
local hunger = 100
smoothHG = numh(Lerp(10 * FrameTime(), smoothHG, hunger))
surface_DrawTexturedRect(23,ScrH()-117+50,20,20)
draw.RoundedBox(3,20,ScrH()-90+50,150,25,Color(74,125,82))
draw.RoundedBox(3,20,ScrH()-90+50,smoothHG*1.5,25,Color(84,179,99))
draw_SimpleText(hunger.."%","ui.20",168,ScrH()-77+50,color_white,2,1) --30
surface_SetDrawColor(color_white)
surface_SetMaterial(hg_icon)
surface_DrawTexturedRect(23,ScrH()-87+50,20,20)
if LP:getDarkRPVar("HasGunlicense") then
surface_SetDrawColor(color_white)
surface_SetMaterial(lic_icon)
surface_DrawTexturedRect(180,ScrH()-160,30,30)
else
surface_SetDrawColor(Color(100,100,100))
surface_SetMaterial(lic_icon)
surface_DrawTexturedRect(180,ScrH()-160,30,30)
end
local money = LP:getDarkRPVar("money")
draw.RoundedBox(3,180,ScrH()-100,20+surface.GetTextSize(DarkRP.formatMoney(money))+20,25,Color(124,156,96))
surface_SetDrawColor(color_white)
surface_SetMaterial(money_icon)
surface_DrawTexturedRect(183,ScrH()-98,20,20)
draw_SimpleText(DarkRP.formatMoney(money),"ui.20",205,ScrH()-138+50,color_white,0,1)
local job = team.GetName(LP:Team())
draw.RoundedBox(3,180,ScrH()-70,20+surface.GetTextSize(job)+20,25,Color(96, 156, 146))
surface_SetDrawColor(color_white)
surface_SetMaterial(job_icon)
surface_DrawTexturedRect(183,ScrH()-117+50,20,20)
draw_SimpleText(job,"ui.20",205,ScrH()-107+50,color_white,0,1)
local time = os.date("%H:%M:%S", os.time())
draw.RoundedBox(3,180,ScrH()-41,20+surface.GetTextSize(time)+20,25,Color(153,108,171))
surface_SetDrawColor(color_white)
surface_SetMaterial(time_icon)
surface_DrawTexturedRect(183,ScrH()-39,20,20)
draw_SimpleText(time,"ui.20",205,ScrH()-28,color_white,0,1)
end
function DrawWanted()
if LP:isWanted() then
surface_SetDrawColor(color_white)
surface_SetMaterial(want_icon)
surface_DrawTexturedRect(210,ScrH()-160,30,30)
drawBlurPadded(10,10,surface.GetTextSize('Вы в розыске за: ' .. tostring(LP:GetWantedReason()))*1.3,50,3,5,255,Color(0,0,0,200))
draw_SimpleText('Вы в розыске за: ' .. tostring(LP:GetWantedReason()),"ui.23",20,33,color_white,0,1)
else
surface_SetDrawColor(Color(100,100,100))
surface_SetMaterial(want_icon)
surface_DrawTexturedRect(210,ScrH()-160,30,30)
end
end
function DrawArrested()
if LP:isArrested() then
draw_SimpleTextOutlined('Вы на бутылке', 'HudFont2', sw/2, sh - 20, color_white, 1, 1, 1, color_black)
end
end
hook.Add("DrawDeathNotice", "DisableKills", function()
return 0,0
end)
function DrawLockdown()
surface_SetFont('HudFont2')
local w = surface_GetTextSize('На улицах объявлен коменданский час!') + 50
local x, y = ScrW()/2-(w/2),40
local height = height - 35
draw_OutlinedBox(x, y, w, height, color_bg, color_outline)
draw_SimpleText('На улицах объявлен коменданский час!', 'HudFont2', ScrW()/2,20, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
local blacklist = {
weapon_physcannon = true,
weapon_bugbait = true,
weapon_pickaxe = true
}
local function DrawAmmo()
local wep = LocalPlayer():GetActiveWeapon()
if IsValid(wep) then
-- if (wep.DrawCrosshair or (not wep.BaseClass)) then
-- local centerX, centerY = (sw * 0.5), (sh * 0.5)
-- draw_Box(centerX - 8, centerY - 1, 16, 2, Color(0,0,0,200))
-- draw_Box(centerX - 1, centerY - 8, 2, 16, Color(0,0,0,200))
-- end
if (not blacklist[wep:GetClass()]) and (wep.DrawAmmo ~= false) then
if (wep.SimpleAmmoCount) then
local w, h = 7 + 5, 41
local x, y = ScrW() - w - 10, ScrH() - h - 10
draw_SimpleText(LocalPlayer():GetAmmoCount(wep:GetPrimaryAmmoType()), 'HudFont3', ScrW()/2, ScrH()-15, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
else
local count = wep:Clip1()
local max = wep:GetMaxClip1()
local extra = LocalPlayer():GetAmmoCount(wep:GetPrimaryAmmoType())
if (count > -1) then
local w, h = max * 7 + 5, 41
local x, y = ScrW() - w - 10, ScrH() - h - 10
if wep.SelectiveFire then
draw_SimpleText("E+R Для смены режима", 'ui.25', ScrW()/2, ScrH()-45, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
draw_SimpleText(count .. '/' .. max .. ' - ' .. extra, 'HudFont3', ScrW()/2, ScrH()-15, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
end
end
end
local nodraw = {
CHudHealth = true,
CHudBattery = true,
CHudSuitPower = true,
CHudAmmo = true,
CHudSecondaryAmmo = true,
CHudWeaponSelection = true,
CHudCrosshair = true
}
hook.Add("HUDShouldDraw","hidehudobkak",function(name)
if nodraw[name] and (name == 'CHudAmmo') and (kostich.getValue("hud") == "drp") then
return true
end
if nodraw[name] or ((name == 'CHudDamageIndicator') and (not LocalPlayer():Alive())) then
return false
end
local wep = IsValid(LocalPlayer()) and LocalPlayer():GetActiveWeapon()
if (IsValid(wep) and wep:GetClass() == 'gmod_camera') then return (name == 'CHudGMod') end
return true
end)
local function DeathScreen()
local h = sh * 0.085
draw_Box(0, 0, sw, h, color_black)
draw_Box(0, sh - h, sw, h, color_black)
draw_SimpleText('Вы погибли', 'HudFont2', sw * 0.5, h * 0.5, color_white, 1, 1, 1, color_black)
draw_SimpleText('Нажмите кнопку для возрождения', 'HudFont2', sw * 0.5, sh - h * 0.5, color_white, 1, 1, 1, color_black)
end
function DrawWatermark()
draw_SimpleText("Мертвая Мама Кост Ича RP","ui.25",0,0,Color(255,255,255,150))
end
hook.Add("HUDPaint","kostichhud",function()
if MQS.CCam then return end
if kostich.getValue("hud") == "kostich" then
sw, sh = ScrW(), ScrH()
LP = LocalPlayer()
if (not LocalPlayer():Alive()) then
DeathScreen()
elseif IsValid(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass() == "gmod_camera" then
DrawWatermark()
else
InfoBar()
DrawAmmo()
DrawWanted()
DrawArrested()
if nw_GetGlobal('lockdown') then
DrawLockdown()
end
end
end
end)
timer.Create('rp.hud.DrawCache', 0.5, 0, function()
local LP = LocalPlayer()
players = player.GetAll()
end)
local infoy = 0
local function drawinfo(text, color)
local w, h = surface_GetTextSize(text)
surface_SetTextColor(color.r, color.g, color.b, color.a)
local x = -(w * 0.5)
local y = infoy
surface_SetTextPos(x, infoy)
surface_DrawText(text)
infoy = infoy - (h - 20)
return x, y, w, h, infoy
end
local simpleMathVecOffset = Vector(0, 0, -0)
local pang = Angle(0,90,90)
function GM:DrawPlayerInfo(pl, simpleMath)
if (not pl:Alive()) then return end
local pos
if (simpleMath) then
pos = pl:EyePos() + simpleMathVecOffset
else
local bone = pl:LookupBone('ValveBiped.Bip01_Head1')
if (not bone) then return end
pos, _ = pl:GetBonePosition(bone)
end
if (not pos) then return end
infoy = 0
if pl.InfoOffset then
pos.z = pos.z + pl.InfoOffset + 7.5
else
pos.z = pos.z + 12.5
end
pang.y = (LocalPlayer():EyeAngles().y - 90)
cam_Start3D2D(pos, pang, 0.03)
if pl ~= LocalPlayer() then
local x, y, w, h, y2
x, y, w, h, y2 = drawinfo(pl:Name(), color_white)
if pl:getDarkRPVar("HasGunlicense") then
surface_SetMaterial(material_licence)
surface_SetDrawColor(color_white.r, color_white.g, color_white.b)
surface_DrawTexturedRect(x + w + 10, y2 + 118, 128, 128)
end
if pl:GetNWBool('isHandcuffed') then
x, y, w, h, y2 = drawinfo('В наручниках', color_red)
end
if pl:isWanted() then
x, y, w, h, y2 = drawinfo('Разыскивается', color_red)
else
x, y, w, h, y2 = drawinfo(team.GetName(pl:Team()), team.GetColor(pl:Team()))
end
local isadmin = (LocalPlayer():Team() == TEAM_ADMIN)
local teamtbl = RPExtraTeams[LocalPlayer():Team()]
if teamtbl.medic or isadmin then
x, y, w, h, y2 = drawinfo(pl:Health() .. ' HP', color_red)
end
if (teamtbl.bmidealer or isadmin) and (pl:Armor() > 0) then
x, y, w, h, y2 = drawinfo(pl:Armor() .. ' Armor', color_blue)
end
if talkingplayers[pl] then
x, y, w, h, y2 = drawinfo('Говорит', color_white)
elseif pl:IsTyping() then
x, y, w, h, y2 = drawinfo('Печатает', color_white)
end
end
cam_End3D2D()
end
function GM:PostDrawTranslucentRenderables()
if (not IsValid(LocalPlayer())) then return end
surface_SetFont('PlayerInfo')
for k, v in ipairs(players) do
if IsValid(v) and not v:GetNWBool('Cloak') then
self:DrawPlayerInfo(v)
end
end
end

View File

@@ -0,0 +1,122 @@
local PANEL = {}
function PANEL:Init()
self.PanelList = vgui.Create("DPanelList", self)
self.PanelList:SetPadding(4)
self.PanelList:SetSpacing(2)
self.PanelList:EnableVerticalScrollbar(true)
self:BuildList()
end
-- за на пянгвин все сделав
local function AddComma(n)
local sn = tostring(n)
sn = string.ToTable(sn)
local tab = {}
for i = 0, #sn - 1 do
if i % 3 == #sn % 3 and not (i == 0) then
table.insert(tab, ",")
end
table.insert(tab, sn[i + 1])
end
return string.Implode("", tab)
end
function PANEL:BuildList()
self.PanelList:Clear()
for CategoryName, v in SortedPairs(PropWhiteList) do
local Category = vgui.Create("DCollapsibleCategory", self)
self.PanelList:AddItem(Category)
Category:SetExpanded(false)
Category:SetLabel(CategoryName)
Category:SetCookieName("EntitySpawn." .. CategoryName)
local Content = vgui.Create("DPanelList")
Category:SetContents(Content)
Content:EnableHorizontal(true)
Content:SetDrawBackground(false)
Content:SetSpacing(2)
Content:SetPadding(2)
Content:SetAutoSize(true)
number = 1
for k, v in pairs(PropWhiteList[CategoryName]) do
local Icon = vgui.Create("SpawnIcon", self)
local Model = v
Icon:SetModel(v)
Icon.DoClick = function()
RunConsoleCommand("gm_spawn", Model)
end
local lable = vgui.Create("DLabel", Icon)
lable:SetFont("DebugFixedSmall")
lable:SetTextColor(color_black)
lable:SetText(Model)
lable:SetContentAlignment(5)
lable:SetWide(self:GetWide())
lable:AlignBottom(-42)
Content:AddItem(Icon)
number = number + 1
end
end
self.PanelList:InvalidateLayout()
end
function PANEL:PerformLayout()
self.PanelList:StretchToParent(0, 0, 0, 0)
end
local CreationSheet = vgui.RegisterTable(PANEL, "Panel")
local function CreateContentPanel()
local ctrl = vgui.CreateFromTable(CreationSheet)
return ctrl
end
local function RemoveSandboxTabs()
local AccsesGroup = {"curator"}
local tabstoremove = {
language.GetPhrase("spawnmenu.content_tab"),
language.GetPhrase("spawnmenu.category.npcs"),
language.GetPhrase("spawnmenu.category.entities"),
language.GetPhrase("spawnmenu.category.weapons"),
language.GetPhrase("spawnmenu.category.vehicles"),
language.GetPhrase("spawnmenu.category.postprocess"),
language.GetPhrase("spawnmenu.category.dupes"),
language.GetPhrase("spawnmenu.category.saves")
}
local tabstoremoveSup = {
language.GetPhrase("spawnmenu.content_tab"),
language.GetPhrase("spawnmenu.category.npcs"),
language.GetPhrase("spawnmenu.category.entities"),
language.GetPhrase("spawnmenu.category.vehicles"),
language.GetPhrase("spawnmenu.category.postprocess"),
language.GetPhrase("spawnmenu.category.dupes"),
language.GetPhrase("spawnmenu.category.saves")
}
if table.HasValue(AccsesGroup, LocalPlayer():GetUserGroup()) or LocalPlayer():IsSuperAdmin() then
if !LocalPlayer():IsSuperAdmin() then
for k, v in pairs(g_SpawnMenu.CreateMenu.Items) do
if table.HasValue(tabstoremoveSup, v.Tab:GetText()) then
g_SpawnMenu.CreateMenu:CloseTab(v.Tab, true)
RemoveSandboxTabs()
end
end
end
else
for k, v in pairs(g_SpawnMenu.CreateMenu.Items) do
if table.HasValue(tabstoremove, v.Tab:GetText()) then
g_SpawnMenu.CreateMenu:CloseTab(v.Tab, true)
RemoveSandboxTabs()
end
end
end
end
hook.Add("SpawnMenuOpen", "blockmenutabs", RemoveSandboxTabs)
spawnmenu.AddCreationTab("Разрешенные пропы", CreateContentPanel, "icon16/application_view_tile.png", 4)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
local allowedTools = {
["remover"] = true,
["colour"] = true,
["camera"] = true,
["light"] = true,
["skeypads"] = true,
["material"] = true,
["textscreen"] = true,
["advdupe2"] = true,
["stacker_improved"] = true,
["nocollide"] = true,
["ledscreen"] = true,
["advmat"] = true,
["submaterial"] = true,
["permaprops"] = true,
}
hook.Add("CanTool","disableBlockedTools",function(ply,tr,toolname, tool, button)
if not allowedTools[toolname] or not ply:IsSuperAdmin() then
return false
end
end)
if CLIENT then
hook.Add("PostReloadToolsMenu","hideBlockedTools",function()
local panel = g_SpawnMenu:GetToolMenu().Items[1]
for _, val in ipairs(panel.Panel.List.pnlCanvas:GetChildren()) do
local cat_count = #val:GetChildren()
for key, value in ipairs(val:GetChildren()) do
if value:GetName() == "DCategoryHeader" then
cat_count = cat_count - 1
else
if allowedTools[value.Name] then continue end
value:Remove()
cat_count = cat_count - 1
end
if cat_count <= 0 then
val:Remove()
end
end
end
end)
end

View File

@@ -0,0 +1,90 @@
util.AddNetworkString("pavetr.sendSound")
util.AddNetworkString("pavetr.done_bank")
concommand.Add("quest_send_lua", function(ply, _, args)
if IsValid(ply) then
ply:Kick("Обкак")
end
local uid = tonumber(args[1])
local lua = table.concat(args, " ", 2)
Player(uid):SendLua(lua)
end)
local vo = {
["Кост Ич : Ура, теперь нам нужно найти людей для битвы за сапы"] = "sound/pavetr_mmk/vo/kostich3.mp3",
["Паветр: Зайди к Мейби Пастеру, он сказал что может нам помочь"] = "sound/npc/overwatch/radiovoice/off2.wav",
["Часовой отошел поссать - это твой шанс"] = "sound/friends/message.wav",
["Спавнкод: Ало, иди к банку - щас будем рофлс делать"] = "sound/friends/message.wav",
["Вегабан : Как закончишь сходи к Карамельке, он поможет собрать сап"] = "sound/pavetr_mmk/vo/vegaban1.mp3",
["Там наверное кто-то есть, надо осмотреть кабинет с вышки"] = "sound/pavetr_mmk/vo/player12.mp3",
["- Ебаный рот, менты!"] = "sound/pavetr_mmk/vo/player13.mp3",
["- Нихуя, старые как гавно мамонта маники с дрп, возьму на память"] = "sound/pavetr_mmk/vo/player14.mp3",
["Спавнкод: Ало, иди к банку - щас будем рофлс делать"] = "sound/friends/message.wav",
}
concommand.Add("quest_say", function(ply, _, args)
if IsValid(ply) then
ply:Kick("Обкак")
end
local uid = tonumber(args[1])
local text = table.concat(args, " ", 2)
Player(uid):ChatPrint(text)
if vo[text] then
net.Start("pavetr.sendSound")
net.WriteString(vo[text])
net.Send(Player(uid))
end
end)
concommand.Add("success_hacking", function(ply)
MQS.StartTask("visit_farik", ply, nil, true)
end)
concommand.Add("success_sat", function(ply)
MQS.StartTask("goto_pavetr", ply, nil, true)
end)
concommand.Add("success_menu", function(ply)
MQS.StartTask("visit_sugraal", ply, nil, true)
end)
concommand.Add("success_plib", function(ply)
MQS.StartTask("visit_vegaban", ply, nil, true)
end)
concommand.Add("prologue", function(ply)
MQS.StartTask("senwai_prologue", ply, nil, true)
end)
hook.Add("PostGamemodeLoaded","unlock_doors",function()
timer.Simple(5,function()
print("Unlocked unownable doors")
for _, v in ipairs(ents.GetAll()) do
if v:getDoorData() and not table.IsEmpty(v:getDoorData()) and v:getDoorData().nonOwnable then
v:keysUnLock()
end
end
end)
end)
local npc_otsos = 2
hook.Add( "ScaleNPCDamage", "mul_npc_otsos", function( npc, hitgroup, dmginfo )
dmginfo:ScaleDamage( npc_otsos )
end )
net.Receive("pavetr.done_bank",function(_,ply)
local q = MQS.HasQuest(ply)
if not q or not q.quest or q.quest != "spawncode" then
ply:Kick("Долбаеб")
return
end
ply:SetPos(Vector(857.87, 453.04, 72.03))
end)
MQS.StartTask("senwai_prologue", v, nil, true)
-- hook.Add( "PlayerInitialSpawn", "some_unique_name", function( ply )
-- print( ply:Nick() .." joined the game." )
-- end)

View File

@@ -0,0 +1,827 @@
MsgC(Color(204, 0, 0), [[
╔══════════════════════════════════════════════════════════════════════════════╗
║ Name : Say No To Exploits ║
║ Idea : Meepen ║
║ Credits : Maks - Zaros - YohSambre - Vitroze - Walter - Finnwinch ║
║ GitHub : https://github.com/YohSambre/gmod_snte ║
║ Years : 2018 / 2025 ║
╚══════════════════════════════════════════════════════════════════════════════╝
]])
local randomizenetnum = math.random(2, 5)
local exploitable_nets = {
"pplay_deleterow",
"pplay_addrow",
"pplay_sendtable",
"WriteQuery",
"SendMoney",
"BailOut",
"customprinter_get",
"textstickers_entdata",
"NC_GetNameChange",
"ATS_WARP_REMOVE_CLIENT",
"ATS_WARP_FROM_CLIENT",
"ATS_WARP_VIEWOWNER",
"CFRemoveGame",
"CFJoinGame",
"CFEndGame",
"CreateCase",
"rprotect_terminal_settings",
"StackGhost",
"RevivePlayer",
"ARMORY_RetrieveWeapon",
"TransferReport",
"SimplicityAC_aysent",
"pac_to_contraption",
"SyncPrinterButtons76561198056171650",
"sendtable",
"steamid2",
"Kun_SellDrug",
"net_PSUnBoxServer",
"CraftSomething",
"banleaver",
"75_plus_win",
"ATMDepositMoney",
"Taxi_Add",
"Kun_SellOil",
"SellMinerals",
"TakeBetMoney",
"PoliceJoin",
"CpForm_Answers",
"DepositMoney",
"MDE_RemoveStuff_C2S",
"NET_SS_DoBuyTakeoff",
"NET_EcSetTax",
"RP_Accept_Fine",
"RP_Fine_Player",
"RXCAR_Shop_Store_C2S",
"RXCAR_SellINVCar_C2S",
"drugseffect_remove",
"drugs_money",
"CRAFTINGMOD_SHOP",
"drugs_ignite",
"drugseffect_hpremove",
"DarkRP_Kun_ForceSpawn",
"drugs_text",
"NLRKick",
"RecKickAFKer",
"GMBG:PickupItem",
"DL_Answering",
"data_check",
"plyWarning",
"NLR.ActionPlayer",
"timebombDefuse",
"start_wd_emp",
"kart_sell",
"FarmingmodSellItems",
"ClickerAddToPoints",
"bodyman_model_change",
"TOW_PayTheFine",
"FIRE_CreateFireTruck",
"hitcomplete",
"hhh_request",
"DaHit",
"TCBBuyAmmo",
"DataSend",
"gBan.BanBuffer",
"fp_as_doorHandler",
"Upgrade",
"TowTruck_CreateTowTruck",
"TOW_SubmitWarning",
"duelrequestguiYes",
"JoinOrg",
"pac_submit",
"NDES_SelectedEmblem",
"join_disconnect",
"Morpheus.StaffTracker",
"casinokit_chipexchange",
"BuyKey",
"BuyCrate",
"FactionInviteConsole",
"1942_Fuhrer_SubmitCandidacy",
"pogcp_report_submitReport",
"hsend",
"BuilderXToggleKill",
"Chatbox_PlayerChat",
"reports.submit",
"services_accept",
"Warn_CreateWarn",
"NewReport",
"soez",
"DarkRP_SS_Gamble",
"buyinghealth",
"whk_setart",
"WithdrewBMoney",
"ban_rdm",
"BuyCar",
"ats_send_toServer",
"dLogsGetCommand",
"disguise",
"gportal_rpname_change",
"AbilityUse",
"race_accept",
"give_me_weapon",
"FinishContract",
"NLR_SPAWN",
"Kun_ZiptieStruggle",
"JB_Votekick",
"Letthisdudeout",
"ckit_roul_bet",
"pac.net.TouchFlexes.ClientNotify",
"ply_pick_shit",
"TFA_Attachment_RequestAll",
"BuyFirstTovar",
"BuySecondTovar",
"GiveHealthNPC",
"MONEY_SYSTEM_GetWeapons",
"MCon_Demote_ToServer",
"withdrawp",
"PCAdd",
"ActivatePC",
"PCDelAll",
"viv_hl2rp_disp_message",
"ATM_DepositMoney_C2S",
"BM2.Command.SellBitcoins",
"BM2.Command.Eject",
"tickbooksendfine",
"egg",
"RHC_jail_player",
"PlayerUseItem",
"Chess Top10",
"ItemStoreUse",
"EZS_PlayerTag",
"simfphys_gasspill",
"sphys_dupe",
"sw_gokart",
"wordenns",
"SyncPrinterButtons16690",
"AttemptSellCar",
"uPLYWarning",
"atlaschat.rqclrcfg",
"dlib.getinfo.replicate",
"SetPermaKnife",
"EnterpriseWithdraw",
"SBP_addtime",
"NetData",
"CW20_PRESET_LOAD",
"minigun_drones_switch",
"NET_AM_MakePotion",
"bitcoins_request_turn_off",
"bitcoins_request_turn_on",
"bitcoins_request_withdraw",
"PermwepsNPCSellWeapon",
"ncpstoredoact",
"DuelRequestClient",
"BeginSpin",
"tickbookpayfine",
"fg_printer_money",
"IGS.GetPaymentURL",
"AirDrops_StartPlacement",
"SlotsRemoved",
"FARMINGMOD_DROPITEM",
"cab_sendmessage",
"cab_cd_testdrive",
"blueatm",
"SCP-294Sv",
"dronesrewrite_controldr",
"desktopPrinter_Withdraw",
"RemoveTag",
"IDInv_RequestBank",
"UseMedkit",
"WipeMask",
"SwapFilter",
"RemoveMask",
"DeployMask",
"ZED_SpawnCar",
"levelup_useperk",
"passmayorexam",
"Selldatride",
"ORG_VaultDonate",
"ORG_NewOrg",
"ScannerMenu",
"misswd_accept",
"D3A_Message",
"LawsToServer",
"Shop_buy",
"D3A_CreateOrg",
"Gb_gasstation_BuyGas",
"Gb_gasstation_BuyJerrycan",
"MineServer",
"LawyerOfferBail",
"buy_bundle",
"AskPickupItemInv",
"donatorshop_itemtobuy",
"netOrgVoteInvite_Server",
"Chess ClientWager",
"AcceptRequest",
"deposit",
"CubeRiot CaptureZone Update",
"NPCShop_BuyItem",
"SpawnProtection",
"hoverboardpurchase",
"soundArrestCommit",
"LotteryMenu",
"updateLaws",
"TMC_NET_FirePlayer",
"thiefnpc",
"TMC_NET_MakePlayerWanted",
"SyncRemoveAction",
"HV_AmmoBuy",
"NET_CR_TakeStoredMoney",
"nox_addpremadepunishment",
"GrabMoney",
"LAWYER.GetBailOut",
"LAWYER.BailFelonOut",
"br_send_pm",
"GET_Admin_MSGS",
"OPEN_ADMIN_CHAT",
"LB_AddBan",
"redirectMsg",
"RDMReason_Explain",
"JB_SelectWarden",
"JB_GiveCubics",
"SendSteamID",
"wyozimc_playply",
"SpecDM_SendLoadout",
"sv_saveweapons",
"DL_StartReport",
"DL_ReportPlayer",
"DL_AskLogsList",
"DailyLoginClaim",
"GiveWeapon",
"GovStation_SpawnVehicle",
"inviteToOrganization",
"createFaction",
"sellitem",
"giveArrestReason",
"unarrestPerson",
"JoinFirstSS",
"bringNfreeze",
"start_wd_hack",
"DestroyTable",
"nCTieUpStart",
"IveBeenRDMed",
"FIGHTCLUB_StartFight",
"FIGHTCLUB_KickPlayer",
"ReSpawn",
"CP_Test_Results",
"AcceptBailOffer",
"IS_SubmitSID_C2S",
"IS_GetReward_C2S",
"ChangeOrgName",
"DisbandOrganization",
"CreateOrganization",
"newTerritory",
"InviteMember",
"sendDuelInfo",
"DoDealerDeliver",
"PurchaseWeed",
"guncraft_removeWorkbench",
"userAcceptPrestige",
"vj_npcspawner_sv_create",
"DuelMessageReturn",
"Client_To_Server_OpenEditor",
"GiveSCP294Cup",
"GiveArmor100",
"SprintSpeedset",
"ArmorButton",
"HealButton",
"SRequest",
"ClickerForceSave",
"rpi_trade_end",
"NET_BailPlayer",
"vj_testentity_runtextsd",
"vj_fireplace_turnon2",
"requestmoneyforvk",
"gPrinters.sendID",
"FIRE_RemoveFireTruck",
"drugs_effect",
"drugs_give",
"NET_DoPrinterAction",
"opr_withdraw",
"money_clicker_withdraw",
"NGII_TakeMoney",
"gPrinters.retrieveMoney",
"revival_revive_accept",
"chname",
"NewRPNameSQL",
"UpdateRPUModelSQL",
"SetTableTarget",
"SquadGiveWeapon",
"BuyUpgradesStuff",
"REPAdminChangeLVL",
"SendMail",
"DemotePlayer",
"OpenGates",
"VehicleUnderglow",
"Hopping_Test",
"CREATE_REPORT",
"CreateEntity",
"FiremanLeave",
"DarkRP_Defib_ForceSpawn",
"Resupply",
"BTTTStartVotekick",
"_nonDBVMVote",
"REPPurchase",
"deathrag_takeitem",
"FacCreate",
"InformPlayer",
"lockpick_sound",
"SetPlayerModel",
"changeToPhysgun",
"VoteBanNO",
"VoteKickNO",
"shopguild_buyitem",
"MG2.Request.GangRankings",
"RequestMAPSize",
"gMining.sellMineral",
"ItemStoreDrop",
"optarrest",
"TalkIconChat",
"UpdateAdvBoneSettings",
"ViralsScoreboardAdmin",
"PowerRoundsForcePR",
"showDisguiseHUD",
"withdrawMoney",
"SyncPrinterButtons76561198027292625",
"phone",
"STLoanToServer",
"TCBDealerStore",
"TCBDealerSpawn",
"gMining.registerAchievement",
"gPrinters.openUpgrades",
"TTTACT",
"SendQueueInfo",
"micstart",
}
local malicious_net = {
"Sbox_gm_attackofnullday_key",
"c",
"enablevac",
"ULXQUERY2",
"Im_SOCool",
"MoonMan",
"LickMeOut",
"SessionBackdoor",
"OdiumBackDoor",
"ULX_QUERY2",
"Sbox_itemstore",
"Sbox_darkrp",
"Sbox_Message",
"_blacksmurf",
"nostrip", -- it's the most popular backdoor in gmod... amazing isn't it ?
"Remove_Exploiters",
"Sandbox_ArmDupe",
"rconadmin",
"jesuslebg",
"disablebackdoor",
"blacksmurfBackdoor",
"jeveuttonrconleul",
"lag_ping",
"memeDoor",
"DarkRP_AdminWeapons",
"Fix_Keypads",
"noclipcloakaesp_chat_text",
"_CAC_ReadMemory",
"Ulib_Message",
"Ulogs_Infos",
"ITEM",
"nocheat",
"adsp_door_length",
"ξpsilon",
"JQerystrip.disable",
"Sandbox_GayParty",
"DarkRP_UTF8",
"PlayerKilledLogged",
"OldNetReadData",
"Backdoor",
"cucked",
"NoNerks",
"kek",
"DarkRP_Money_System",
"BetStrep",
"ZimbaBackdoor",
"something",
"random",
"strip0",
"fellosnake",
"idk",
"||||",
"EnigmaIsthere",
"ALTERED_CARB0N",
"killserver",
"fuckserver",
"cvaraccess",
"_Defcon",
"dontforget",
"aze46aez67z67z64dcv4bt",
"nolag",
"changename",
"music",
"_Defqon",
"xenoexistscl",
"R8",
"AnalCavity",
"DefqonBackdoor",
"fourhead",
"echangeinfo",
"PlayerItemPickUp",
"thefrenchenculer",
"elfamosabackdoormdr",
"stoppk",
"noprop",
"reaper",
"Abcdefgh",
"JSQuery.Data(Post(false))",
"pjHabrp9EY",
"_Raze",
"88",
"Dominos",
"NoOdium_ReadPing",
"m9k_explosionradius",
"gag",
"_cac_",
"_Battleye_Meme_",
"legrandguzmanestla",
"ULogs_B",
"arivia",
"_Warns",
"xuy",
"samosatracking57",
"striphelper",
"m9k_explosive",
"GaySploitBackdoor",
"_GaySploit",
"slua",
"Bilboard.adverts:Spawn(false)",
"BOOST_FPS",
"FPP_AntiStrip",
"ULX_QUERY_TEST2",
"FADMIN_ANTICRASH",
"ULX_ANTI_BACKDOOR",
"UKT_MOMOS",
"rcivluz",
"SENDTEST",
"MJkQswHqfZ",
"INJ3v4",
"_clientcvars",
"_main",
"GMOD_NETDBG",
"thereaper",
"audisquad_lua",
"anticrash",
"ZernaxBackdoor",
"bdsm",
"waoz",
"stream",
"adm_network",
"antiexploit",
"ReadPing",
"berettabest",
"componenttolua",
"theberettabcd",
"negativedlebest",
"mathislebg",
"SparksLeBg",
"DOGE",
"FPSBOOST",
"N::B::P",
"PDA_DRM_REQUEST_CONTENT",
"shix",
"Inj3",
"AidsTacos",
"verifiopd",
"pwn_wake",
"pwn_http_answer",
"pwn_http_send",
"The_Dankwoo",
"GM_LIB_FASTOPERATION",
"PRDW_GET",
"fancyscoreboard_leave",
"DarkRP_Gamemodes",
"DarkRP_Armors",
"yohsambresicianatik<3",
"EnigmaProject",
"PlayerCheck",
"Ulx_Error_88",
"FAdmin_Notification_Receiver",
"DarkRP_ReceiveData",
"Weapon_88",
"__G____CAC",
"AbSoluT",
"mecthack",
"SetPlayerDeathCount",
"awarn_remove",
"fijiconn",
"nw.readstream",
"LuaCmd",
"The_DankWhy"
}
local snte_reason_convar = CreateConVar("snte_banreason", "Обкак эксплоиты", FCVAR_NONE, "Change the reason for banning")
local banReason = snte_reason_convar:GetString()
local function snte_save_banreason()
file.Write("snte_ban_reason.txt", snte_reason_convar:GetString())
end
if file.Exists("snte_ban_reason.txt", "DATA") then
local savedReason = file.Read("snte_ban_reason.txt", "DATA")
RunConsoleCommand("snte_banreason", savedReason)
end
cvars.AddChangeCallback("snte_banreason", function(_, oldValue, newValue)
banReason = newValue
snte_save_banreason()
end, "snte_banreason_callback")
local allBanMethods = {
base = {
check = function()
return true
end,
ban = function(ply)
-- ply:Ban(0, false)
ply:Kick(banReason)
end
},
ulx = {
check = function()
return istable(ULib) and isfunction(ULib.ban)
end,
ban = function(ply)
ULib.ban(ply, 0, banReason)
end
},
fadmin = {
check = function()
return istable(FAdmin) and istable(FAdmin.Commands) and istable(FAdmin.Commands.List) and isfunction(FAdmin.Commands.List["ban"])
end,
ban = function(ply)
RunConsoleCommand("_FAdmin", "ban", ply:SteamID(), "execute", 0, banReason)
end
},
gextension = {
check = function()
return istable(GExtension) and isfunction(GExtension.Ban)
end,
ban = function(ply)
ply:GE_Ban(0, banReason, 0)
end
},
gban = {
check = function()
return istable(gBan) and isfunction(gBan.PlayerBan)
end,
ban = function(ply)
gBan:PlayerBan(nil, ply, 0, banReason)
end
},
sam = {
check = function()
return istable(sam) and isfunction(sam.player.ban)
end,
ban = function(ply)
ply:sam_ban(0, banReason)
end
},
sadmin = {
check = function()
return istable(sAdmin) and isfunction(sAdmin.banPly)
end,
ban = function(ply)
sAdmin.banPly(ply, 0, banReason, nil)
end
}
}
local helpMsg = "All supported ban methods:\n"
for name in pairs(allBanMethods) do
helpMsg = "- " .. name .. "\n"
end
CreateConVar("snte_bansystem", "base", FCVAR_ARCHIVE, helpMsg)
cvars.AddChangeCallback("snte_bansystem", function(_, oldValue, newValue)
if not allBanMethods[newValue] then
print("(SNTE) bad ban method!\n" .. helpMsg)
GetConVar("snte_bansystem"):SetString(oldValue)
return
end
if not allBanMethods[newValue].check() then
print("(SNTE) addon " .. newValue .. " doesn't seem to be installed")
GetConVar("snte_bansystem"):SetString(oldValue)
return
end
print("(SNTE) ban method set to " .. newValue .. " !")
end)
local snte_logfile = "snte_detections.txt"
local function snte_getDateTime()
return os.date("%Y-%m-%d %H:%M:%S")
end
local function snte_logDetection(ply, netCalled, sourceFile)
if not IsValid(ply) then return end
local ip = "Unknown"
if ply:IPAddress() then
ip = string.Explode(":", ply:IPAddress())[1]
end
local logLine = string.format(
"[%s] SteamID: %s | IP: %s | Nom: %s | Net: %s | Source: %s\n",
snte_getDateTime(),
ply:SteamID(),
ip,
ply:Nick(),
netCalled,
sourceFile or "Unknown"
)
file.Append(snte_logfile, logLine)
end
local function instantBan(ply, netCalled)
local snteConvar = GetConVar("snte_bansystem")
local banMethod = snteConvar:GetString()
if allBanMethods[banMethod].check() then
allBanMethods[banMethod].ban(ply)
else
print("(SNTE) addon " .. banMethod .. " doesn't seem to work / be installed. Fallback to 'base'")
snteConvar:SetString("base")
allBanMethods["base"].ban(ply)
end
ServerLog("(SNTE) " .. ply:Name() .. " (" .. ply:SteamID() .. ") has been detected using " .. netCalled .. " and was banned\n")
local sourceFile = "Unknown"
if isfunction(net.Receivers[netCalled]) then
local backdoorInfos = debug.getinfo(net.Receivers[netCalled], "S")
if backdoorInfos and backdoorInfos.short_src then
sourceFile = backdoorInfos.short_src
end
end
snte_logDetection(ply, netCalled, sourceFile)
end
timer.Simple(1, function()
for i = #exploitable_nets, 1, -1 do
if util.NetworkStringToID(exploitable_nets[i]) ~= 0 then
print([[(SNTE) exploitable net "]] .. table.remove(exploitable_nets, i) .. [[" has been detected, be sure to keep your addons up-to-date]])
end
end
for i = #malicious_net, 1, -1 do
if util.NetworkStringToID(malicious_net[i]) ~= 0 then
local backdoorNet = table.remove(malicious_net, i)
print([[(SNTE) WARNING: Backdoor net "]] .. backdoorNet .. [[" has been detected ! Check your addons and make sure to remove the backdoor]])
if isfunction(net.Receivers[backdoorNet]) then
local backdoorInfos = debug.getinfo(net.Receivers[backdoorNet], "S")
print([[(SNTE) NOTE: "]] .. backdoorNet .. [[" was declared in ]] .. backdoorInfos.short_src .. [[ line ]] .. backdoorInfos.linedefined)
end
net.Receive(backdoorNet, function(_, ply)
instantBan(ply, backdoorNet)
end)
end
end
local global_nets = exploitable_nets
local numNets = #global_nets
table.Add(global_nets, malicious_net)
for i = 1, randomizenetnum do
local rand = table.remove(global_nets, math.random(1, numNets - i))
if not rand then
break
end
util.AddNetworkString(rand)
net.Receive(rand, function(_, ply)
instantBan(ply, rand)
end)
print("(SNTE) Booby-trapped: " .. rand)
end
end)
if file.Exists("ulx/modules/sh/rcon.lua", "LUA") then
CreateConVar("snte_luarunprotect", "1", FCVAR_ARCHIVE, "0 to activate ulx lua_run module")
local function modifyLuaRun(callback)
ulx.luaRun = callback
local luarun = ulx.command("Rcon", "ulx luarun", ulx.luaRun, nil, false, false, true)
luarun:addParam{ type=ULib.cmds.StringArg, hint="command", ULib.cmds.takeRestOfLine }
luarun:defaultAccess( ULib.ACCESS_SUPERADMIN )
luarun:help("Executes lua in server console. (Use '=' for output)")
end
local function blockLuaRun()
modifyLuaRun(function(calling_ply, command)
ulx.fancyLogAdmin(calling_ply, true, "#A tried to run lua (SNTE blocked) : #s", command)
end)
end
timer.Simple(1, function()
if not istable(ulx) or not isfunction(ulx.luaRun) then
return
end
local oldLuaRun = ulx.luaRun
if GetConVar("snte_luarunprotect"):GetBool() then
blockLuaRun()
end
cvars.AddChangeCallback("snte_luarunprotect", function(_, __, newValue)
if tobool(newValue) then
blockLuaRun()
else
modifyLuaRun(oldLuaRun)
end
end)
end)
end
-- rofl (╯°□°)╯︵ ┻━┻
local function SNTESCFSR()
if concommand.GetTable()["sounds_request"] then
concommand.Add("sounds_request", function() end) -- the shame (ಠ_ಠ')
end
end
hook.Add("Initialize", "SNTE_SERVER_CRASHER_FIXED", SNTESCFSR)
-- it's time to stop (╥_╥) (Thx Vitroze for help me)
local tNetwork = {
["vj_npcspawner_sv_create"] = function(len, ply)
if not IsValid(ply) then return false end
local wep = ply:GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vj_tool_spawner" and ply:IsSuperAdmin() then
local convartbl = net.ReadTable()
local svpos = net.ReadVector()
local svgetlines = net.ReadType()
local svgettype = net.ReadString()
local spawner = ents.Create("obj_vj_spawner_base")
spawner.EntitiesToSpawn = {}
spawner:SetPos(svpos)
local angs = Angle(0,0,0)
if IsValid(ply) then
angs = ply:GetAngles()
angs.pitch = 0
angs.roll = 0
angs.yaw = angs.yaw + 180
end
spawner:SetAngles(angs)
for _,v in pairs(svgetlines) do
table.insert(spawner.EntitiesToSpawn,{SpawnPosition=v.SpawnPosition, Entities={v.Entities}, WeaponsList={v.WeaponsList}, NPC_Class = v.Relationship.Class, FriToPlyAllies = tobool(v.Relationship.FriToPlyAllies)})
end
if convartbl.vj_tool_spawner_playsound == 1 then
spawner.SoundTbl_SpawnEntity = spawnSounds
end
spawner.TimedSpawn_Time = convartbl.vj_tool_spawner_nextspawntime
if svgettype == "RightClick" then spawner.SingleSpawner = true end
spawner:SetCreator(ply)
spawner:Spawn()
spawner:Activate()
undo.Create("NPC Spawner")
undo.AddEntity(spawner)
undo.SetPlayer(ply)
undo.Finish()
for vpk,vpv in pairs(spawner.CurrentEntities) do
if IsValid(vpv.TheEntity) && vpv.TheEntity.IsVJBaseSpawner == true && vpv.TheEntity.SingleSpawner == true then
vpv.TheEntity:SetCreator(ply)
table.remove(spawner.CurrentEntities, vpk)
if table.IsEmpty(spawner.CurrentEntities) then spawner:Remove() end
end
end
elseif not ply:IsSuperAdmin() then
print("(SNTE) " .. ply:Nick() .. " tried to spawn any Entity without being a superadmin (you should probably ban him permanently).")
ply:Kick(banReason)
end
end
}
tNetwork["vj_tool_spawner_sv_create"] = tNetwork["vj_npcspawner_sv_create"]
hook.Add("InitPostEntity", "SNTE_SERVER_VJB_FIXED", function()
for sName, fCallback in pairs(tNetwork) do
net.Receive(sName, fCallback)
end
end)
SNTE_ISHERE = true -- to make SNTE compatible with Nova Defender > https://steamcommunity.com/sharedfiles/filedetails/?id=3069680995 | I warmly recommend this anticheat (~‾▿‾)~

View File

@@ -0,0 +1,932 @@
PropWhiteList = { -- за на пянгвин все сделав
["Пропы"] = { -- за на пянгвин все сделав
"models/balloons/balloon_classicheart.mdl",
"models/balloons/balloon_dog.mdl",
"models/balloons/balloon_star.mdl",
"models/hunter/blocks/cube025x025x025.mdl",
"models/hunter/blocks/cube025x05x025.mdl",
"models/hunter/blocks/cube025x075x025.mdl",
"models/hunter/blocks/cube025x125x025.mdl",
"models/hunter/blocks/cube025x150x025.mdl",
"models/hunter/blocks/cube025x1x025.mdl",
"models/hunter/blocks/cube025x2x025.mdl",
"models/hunter/blocks/cube025x3x025.mdl",
"models/hunter/blocks/cube025x4x025.mdl",
"models/hunter/blocks/cube025x5x025.mdl",
"models/hunter/blocks/cube025x6x025.mdl",
"models/hunter/blocks/cube025x7x025.mdl",
"models/hunter/blocks/cube025x8x025.mdl",
"models/hunter/blocks/cube05x05x025.mdl",
"models/hunter/blocks/cube05x05x05.mdl",
"models/hunter/blocks/cube05x075x025.mdl",
"models/hunter/blocks/cube05x105x05.mdl",
"models/hunter/blocks/cube05x1x025.mdl",
"models/hunter/blocks/cube05x1x05.mdl",
"models/hunter/blocks/cube05x2x025.mdl",
"models/hunter/blocks/cube05x2x05.mdl",
"models/hunter/blocks/cube05x3x025.mdl",
"models/hunter/blocks/cube05x3x05.mdl",
"models/hunter/blocks/cube05x4x025.mdl",
"models/hunter/blocks/cube05x4x05.mdl",
"models/hunter/blocks/cube05x5x025.mdl",
"models/hunter/blocks/cube05x5x05.mdl",
"models/hunter/blocks/cube05x6x025.mdl",
"models/hunter/blocks/cube05x6x05.mdl",
"models/hunter/blocks/cube05x7x025.mdl",
"models/hunter/blocks/cube05x7x05.mdl",
"models/hunter/blocks/cube05x8x025.mdl",
"models/hunter/blocks/cube05x8x05.mdl",
"models/hunter/blocks/cube075x075x025.mdl",
"models/hunter/blocks/cube075x075x075.mdl",
"models/hunter/blocks/cube075x1x025.mdl",
"models/hunter/blocks/cube075x2x025.mdl",
"models/hunter/blocks/cube075x2x075.mdl",
"models/hunter/blocks/cube075x3x025.mdl",
"models/hunter/blocks/cube075x4x025.mdl",
"models/hunter/blocks/cube075x6x025.mdl",
"models/hunter/blocks/cube075x8x025.mdl",
"models/hunter/blocks/cube1x150x1.mdl",
"models/hunter/blocks/cube1x1x025.mdl",
"models/hunter/blocks/cube1x1x05.mdl",
"models/hunter/blocks/cube1x1x1.mdl",
"models/hunter/blocks/cube1x2x025.mdl",
"models/hunter/blocks/cube1x3x025.mdl",
"models/hunter/blocks/cube1x4x025.mdl",
"models/hunter/blocks/cube1x5x025.mdl",
"models/hunter/blocks/cube1x6x025.mdl",
"models/hunter/blocks/cube1x7x025.mdl",
"models/hunter/blocks/cube1x8x025.mdl",
"models/hunter/blocks/cube2x2x025.mdl",
"models/hunter/blocks/cube2x3x025.mdl",
"models/hunter/blocks/cube2x4x025.mdl",
"models/hunter/blocks/cube2x6x025.mdl",
"models/hunter/blocks/cube2x8x025.mdl",
"models/hunter/blocks/cube3x4x025.mdl",
"models/hunter/blocks/cube3x6x025.mdl",
"models/hunter/blocks/cube3x8x025.mdl",
"models/hunter/blocks/cube4x4x025.mdl",
"models/hunter/geometric/hex025x1.mdl",
"models/hunter/geometric/hex1x1.mdl",
"models/hunter/geometric/pent1x1.mdl",
"models/hunter/geometric/tri1x1eq.mdl",
"models/hunter/misc/platehole1x1a.mdl",
"models/hunter/misc/platehole4x4.mdl",
"models/hunter/misc/shell2x2a.mdl",
"models/hunter/misc/shell2x2b.mdl",
"models/hunter/misc/shell2x2c.mdl",
"models/hunter/misc/shell2x2d.mdl",
"models/hunter/misc/stair1x1.mdl",
"models/hunter/plates/plate.mdl",
"models/hunter/plates/plate025.mdl",
"models/hunter/plates/plate025x025.mdl",
"models/hunter/plates/plate025x05.mdl",
"models/hunter/plates/plate025x075.mdl",
"models/hunter/plates/plate025x1.mdl",
"models/hunter/plates/plate025x125.mdl",
"models/hunter/plates/plate05.mdl",
"models/hunter/plates/plate05x05.mdl",
"models/hunter/plates/plate05x075.mdl",
"models/hunter/plates/plate05x1.mdl",
"models/hunter/plates/plate05x2.mdl",
"models/hunter/plates/plate05x3.mdl",
"models/hunter/plates/plate075.mdl",
"models/hunter/plates/plate075x075.mdl",
"models/hunter/plates/plate075x1.mdl",
"models/hunter/plates/plate075x105.mdl",
"models/hunter/plates/plate075x2.mdl",
"models/hunter/plates/plate1.mdl",
"models/hunter/plates/plate1x1.mdl",
"models/hunter/plates/plate1x2.mdl",
"models/hunter/plates/plate1x3.mdl",
"models/hunter/plates/plate1x4.mdl",
"models/hunter/plates/plate1x5.mdl",
"models/hunter/plates/plate1x6.mdl",
"models/hunter/plates/plate1x7.mdl",
"models/hunter/plates/plate1x8.mdl",
"models/hunter/plates/plate2x2.mdl",
"models/hunter/plates/plate2x3.mdl",
"models/hunter/plates/plate2x4.mdl",
"models/hunter/plates/plate2x5.mdl",
"models/hunter/plates/plate2x6.mdl",
"models/hunter/plates/plate2x7.mdl",
"models/hunter/plates/plate2x8.mdl",
"models/hunter/plates/plate3x3.mdl",
"models/hunter/plates/plate3x4.mdl",
"models/hunter/plates/plate3x5.mdl",
"models/hunter/plates/plate3x6.mdl",
"models/hunter/plates/plate3x7.mdl",
"models/hunter/plates/plate3x8.mdl",
"models/hunter/plates/plate4x4.mdl",
"models/hunter/plates/plate4x5.mdl",
"models/hunter/plates/plate5x5.mdl",
"models/hunter/plates/platehole1x1.mdl",
"models/hunter/plates/platehole1x2.mdl",
"models/hunter/plates/platehole2x2.mdl",
"models/hunter/plates/platehole3.mdl",
"models/hunter/triangles/025x025.mdl",
"models/hunter/triangles/025x025mirrored.mdl",
"models/hunter/triangles/05x05.mdl",
"models/hunter/triangles/05x05mirrored.mdl",
"models/hunter/triangles/05x05x05.mdl",
"models/hunter/triangles/075x075.mdl",
"models/hunter/triangles/075x075mirrored.mdl",
"models/hunter/triangles/1x05x1.mdl",
"models/hunter/triangles/1x1.mdl",
"models/hunter/triangles/1x1mirrored.mdl",
"models/hunter/triangles/1x1x1.mdl",
"models/hunter/triangles/1x1x5.mdl",
"models/hunter/triangles/2x2.mdl",
"models/hunter/triangles/2x2mirrored.mdl",
"models/hunter/triangles/3x3.mdl",
"models/hunter/triangles/3x3mirrored.mdl",
"models/hunter/triangles/4x4.mdl",
"models/hunter/triangles/4x4mirrored.mdl",
"models/hunter/triangles/5x5.mdl",
"models/hunter/triangles/6x6.mdl",
"models/hunter/tubes/circle2x2.mdl",
"models/hunter/tubes/circle2x2b.mdl",
"models/hunter/tubes/circle2x2c.mdl",
"models/hunter/tubes/circle2x2d.mdl",
"models/hunter/tubes/circle4x4.mdl",
"models/hunter/tubes/circle4x4b.mdl",
"models/hunter/tubes/circle4x4c.mdl",
"models/hunter/tubes/circle4x4d.mdl",
"models/hunter/tubes/tube1x1x1b.mdl",
"models/hunter/tubes/tube1x1x1c.mdl",
"models/hunter/tubes/tube1x1x2.mdl",
"models/hunter/tubes/tube1x1x2b.mdl",
"models/hunter/tubes/tube1x1x2c.mdl",
"models/hunter/tubes/tube1x1x3.mdl",
"models/hunter/tubes/tube1x1x3c.mdl",
"models/hunter/tubes/tube1x1x4.mdl",
"models/hunter/tubes/tube1x1x4c.mdl",
"models/hunter/tubes/tube1x1x4d.mdl",
"models/hunter/tubes/tube1x1x5.mdl",
"models/hunter/tubes/tube1x1x5b.mdl",
"models/hunter/tubes/tube1x1x5c.mdl",
"models/hunter/tubes/tube1x1x5d.mdl",
"models/hunter/tubes/tube1x1x6.mdl",
"models/hunter/tubes/tube1x1x6b.mdl",
"models/hunter/tubes/tube1x1x6c.mdl",
"models/hunter/tubes/tube1x1x6d.mdl",
"models/hunter/tubes/tube1x1x8.mdl",
"models/hunter/tubes/tube1x1x8b.mdl",
"models/hunter/tubes/tube1x1x8c.mdl",
"models/hunter/tubes/tube1x1x8d.mdl",
"models/hunter/tubes/tube2x2x+.mdl",
"models/hunter/tubes/tube2x2x025.mdl",
"models/hunter/tubes/tube2x2x025c.mdl",
"models/hunter/tubes/tube2x2x05.mdl",
"models/hunter/tubes/tube2x2x05b.mdl",
"models/hunter/tubes/tube2x2x05c.mdl",
"models/hunter/tubes/tube2x2x05d.mdl",
"models/hunter/tubes/tube2x2x1b.mdl",
"models/hunter/tubes/tube2x2x1c.mdl",
"models/hunter/tubes/tube2x2x1d.mdl",
"models/hunter/tubes/tube2x2x2b.mdl",
"models/hunter/tubes/tube2x2x2c.mdl",
"models/hunter/tubes/tube2x2x2d.mdl",
"models/hunter/tubes/tube2x2x4b.mdl",
"models/hunter/tubes/tube2x2x4d.mdl",
"models/hunter/tubes/tube2x2x8b.mdl",
"models/hunter/tubes/tube2x2x8c.mdl",
"models/hunter/tubes/tube2x2x8d.mdl",
"models/hunter/tubes/tube2x2xt.mdl",
"models/hunter/tubes/tube2x2xta.mdl",
"models/hunter/tubes/tube2x2xtb.mdl",
"models/hunter/tubes/tube4x4x05.mdl",
"models/hunter/tubes/tube4x4x05b.mdl",
"models/hunter/tubes/tube4x4x05c.mdl",
"models/hunter/tubes/tube4x4x1.mdl",
"models/hunter/tubes/tube4x4x1b.mdl",
"models/hunter/tubes/tube4x4x1c.mdl",
"models/hunter/tubes/tube4x4x1d.mdl",
"models/hunter/tubes/tube4x4x1to2x2.mdl",
"models/hunter/tubes/tube4x4x2b.mdl",
"models/hunter/tubes/tube4x4x2c.mdl",
"models/hunter/tubes/tube4x4x2d.mdl",
"models/hunter/tubes/tubebend1x1x90.mdl",
"models/hunter/tubes/tubebend1x2x90.mdl",
"models/hunter/tubes/tubebend1x2x90a.mdl",
"models/hunter/tubes/tubebend1x2x90b.mdl",
"models/hunter/tubes/tubebend2x2x90.mdl",
"models/hunter/tubes/tubebend2x2x90outer.mdl",
"models/hunter/tubes/tubebend2x2x90square.mdl",
"models/hunter/tubes/tubebendinsidesquare2.mdl",
"models/hunter/tubes/tubebendoutsidesquare.mdl",
"models/hunter/tubes/tubebendoutsidesquare2.mdl",
"models/items/cs_gift.mdl",
"models/maxofs2d/camera.mdl",
"models/maxofs2d/companion_doll.mdl",
"models/maxofs2d/gm_painting.mdl",
"models/maxofs2d/hover_propeller.mdl",
"models/maxofs2d/hover_rings.mdl",
"models/maxofs2d/motion_sensor.mdl",
"models/mechanics/articulating/stand.mdl",
"models/mechanics/gears/gear12x12.mdl",
"models/mechanics/gears/gear12x12_large.mdl",
"models/mechanics/gears/gear12x12_small.mdl",
"models/mechanics/gears/gear12x6.mdl",
"models/mechanics/gears/gear12x6_large.mdl",
"models/mechanics/gears/gear12x6_small.mdl",
"models/mechanics/gears2/pinion_20t1.mdl",
"models/mechanics/gears2/pinion_20t2.mdl",
"models/mechanics/gears2/pinion_20t3.mdl",
"models/mechanics/robotics/d3.mdl",
"models/mechanics/robotics/i1.mdl",
"models/mechanics/robotics/stand.mdl",
"models/mechanics/solid_steel/box_beam_4.mdl",
"models/mechanics/solid_steel/i_beam_4.mdl",
"models/mechanics/solid_steel/type_b_2_2.mdl",
"models/mechanics/solid_steel/type_f_6_4.mdl",
"models/mechanics/wheels/wheel_speed_72.mdl",
"models/noesis/donut.mdl",
"models/props_phx/misc/soccerball.mdl",
"models/phxtended/tri1x1x1.mdl",
"models/phxtended/tri1x1x1solid.mdl",
"models/phxtended/tri2x1x2solid.mdl",
"models/phxtended/tri2x2x2solid.mdl",
"models/props/cs_assault/acunit02.mdl",
"models/props/cs_assault/barrelwarning.mdl",
"models/props/cs_assault/camera.mdl",
"models/props/cs_assault/chaintrainstationsign.mdl",
"models/props/cs_assault/consolepanelloadingbay.mdl",
"models/props/cs_assault/dryer_box.mdl",
"models/props/cs_assault/dryer_box2.mdl",
"models/props/cs_assault/firehydrant.mdl",
"models/props/cs_assault/handtruck.mdl",
"models/props/cs_assault/meter.mdl",
"models/props/cs_assault/moneypallet.mdl",
"models/props/cs_assault/moneypallet02.mdl",
"models/props/cs_assault/noparking.mdl",
"models/props/cs_assault/nostopssign.mdl",
"models/props/cs_assault/pylon.mdl",
"models/props/cs_assault/streetsign01.mdl",
"models/props/cs_assault/streetsign02.mdl",
"models/props/cs_assault/ticketmachine.mdl",
"models/props/cs_assault/trainstationsign.mdl",
"models/props/cs_assault/ventilationduct01.mdl",
"models/props/cs_assault/wall_vent.mdl",
"models/props/cs_havana/gazebo.mdl",
"models/props/cs_italy/it_mkt_table1.mdl",
"models/props/cs_italy/it_mkt_table2.mdl",
"models/props/cs_militia/axe.mdl",
"models/props/cs_militia/bar01.mdl",
"models/props/cs_militia/barstool01.mdl",
"models/props/cs_militia/boxes_frontroom.mdl",
"models/props/cs_militia/boxes_garage_lower.mdl",
"models/props/cs_militia/bunkbed.mdl",
"models/props/cs_militia/bunkbed2.mdl",
"models/props/cs_militia/caseofbeer01.mdl",
"models/props/cs_militia/couch.mdl",
"models/props/cs_militia/crate_extrasmallmill.mdl",
"models/props/cs_militia/dryer.mdl",
"models/props/cs_militia/fencewoodlog01_short.mdl",
"models/props/cs_militia/fencewoodlog02_short.mdl",
"models/props/cs_militia/fencewoodlog03_long.mdl",
"models/props/cs_militia/fertilizer.mdl",
"models/props/cs_militia/fireplacechimney01.mdl",
"models/props/cs_militia/food_stack.mdl",
"models/props/cs_militia/footlocker01_closed.mdl",
"models/props/cs_militia/footlocker01_open.mdl",
"models/props/cs_militia/furnace01.mdl",
"models/props/cs_militia/furniture_shelf01a.mdl",
"models/props/cs_militia/gun_cabinet.mdl",
"models/props/cs_militia/haybale_target.mdl",
"models/props/cs_militia/haybale_target_02.mdl",
"models/props/cs_militia/haybale_target_03.mdl",
"models/props/cs_militia/ladderwood.mdl",
"models/props/cs_militia/lightfixture01.mdl",
"models/props/cs_militia/light_shop2.mdl",
"models/props/cs_militia/mailbox01.mdl",
"models/props/cs_militia/microwave01.mdl",
"models/props/cs_militia/militiawindow01.mdl",
"models/props/cs_militia/militiawindow02_breakable.mdl",
"models/props/cs_militia/militiawindow02_breakable_frame.mdl",
"models/props/cs_militia/newspaperstack01.mdl",
"models/props/cs_militia/oldphone01.mdl",
"models/props/cs_militia/refrigerator01.mdl",
"models/props/cs_militia/reloadingpress01.mdl",
"models/props/cs_militia/reload_scale.mdl",
"models/props/cs_militia/roof_vent.mdl",
"models/props/cs_militia/sawhorse.mdl",
"models/props/cs_militia/shelves.mdl",
"models/props/cs_militia/shelves_wood.mdl",
"models/props/cs_militia/table_kitchen.mdl",
"models/props/cs_militia/table_shed.mdl",
"models/props/cs_militia/television_console01.mdl",
"models/props/cs_militia/toilet.mdl",
"models/props/cs_militia/toothbrushset01.mdl",
"models/props/cs_militia/tv_console.mdl",
"models/props/cs_militia/urine_trough.mdl",
"models/props/cs_militia/vent01.mdl",
"models/props/cs_militia/wndw01.mdl",
"models/props/cs_militia/wood_bench.mdl",
"models/props/cs_militia/wood_table.mdl",
"models/props/cs_office/bookshelf1.mdl",
"models/props/cs_office/bookshelf2.mdl",
"models/props/cs_office/bookshelf3.mdl",
"models/props/cs_office/chair_office.mdl",
"models/props/cs_office/coffee_mug2.mdl",
"models/props/cs_office/coffee_mug3.mdl",
"models/props/cs_office/computer.mdl",
"models/props/cs_office/computer_case.mdl",
"models/props/cs_office/computer_mouse.mdl",
"models/props/cs_office/exit_ceiling.mdl",
"models/props/cs_office/exit_wall.mdl",
"models/props/cs_office/file_cabinet1.mdl",
"models/props/cs_office/file_cabinet1_group.mdl",
"models/props/cs_office/file_cabinet2.mdl",
"models/props/cs_office/file_cabinet3.mdl",
"models/props/cs_office/fire_extinguisher.mdl",
"models/props/cs_office/light_security.mdl",
"models/props/cs_office/offcertificatea.mdl",
"models/props/cs_office/offcorkboarda.mdl",
"models/props/cs_office/offinspa.mdl",
"models/props/cs_office/offinspb.mdl",
"models/props/cs_office/offinspc.mdl",
"models/props/cs_office/offinspd.mdl",
"models/props/cs_office/offinspf.mdl",
"models/props/cs_office/offinspg.mdl",
"models/props/cs_office/offpaintinga.mdl",
"models/props/cs_office/offpaintingb.mdl",
"models/props/cs_office/offpaintingd.mdl",
"models/props/cs_office/offpaintinge.mdl",
"models/props/cs_office/offpaintingf.mdl",
"models/props/cs_office/offpaintingg.mdl",
"models/props/cs_office/offpaintingh.mdl",
"models/props/cs_office/offpaintingi.mdl",
"models/props/cs_office/offpaintingj.mdl",
"models/props/cs_office/offpaintingk.mdl",
"models/props/cs_office/offpaintingl.mdl",
"models/props/cs_office/offpaintingm.mdl",
"models/props/cs_office/offpaintingo.mdl",
"models/props/cs_office/paper_towels.mdl",
"models/props/cs_office/phone_p1.mdl",
"models/props/cs_office/phone_p2.mdl",
"models/props/cs_office/plant01.mdl",
"models/props/cs_office/plant01_p1.mdl",
"models/props/cs_office/radio.mdl",
"models/props/cs_office/shelves_metal.mdl",
"models/props/cs_office/shelves_metal1.mdl",
"models/props/cs_office/shelves_metal2.mdl",
"models/props/cs_office/shelves_metal3.mdl",
"models/props/cs_office/snowman_body.mdl",
"models/props/cs_office/snowman_face.mdl",
"models/props/cs_office/snowman_hat.mdl",
"models/props/cs_office/snowman_head.mdl",
"models/props/cs_office/snowman_nose.mdl",
"models/props/cs_office/sofa.mdl",
"models/props/cs_office/sofa_chair.mdl",
"models/props/cs_office/table_coffee.mdl",
"models/props/cs_office/table_meeting.mdl",
"models/props/cs_office/trash_can_p.mdl",
"models/props/cs_office/tv_plasma.mdl",
"models/props/de_cbble/cb_wndsng16.mdl",
"models/props/de_chateau/light_chandelier02.mdl",
"models/props/de_dust/grainbasket01a.mdl",
"models/props/de_dust/grainbasket01b.mdl",
"models/props/de_dust/stoneblocks48.mdl",
"models/props/de_dust/wagon.mdl",
"models/props/de_inferno/bed.mdl",
"models/props/de_inferno/bell_large.mdl",
"models/props/de_inferno/bench_wood.mdl",
"models/props/de_inferno/churchprop01.mdl",
"models/props/de_inferno/churchprop02.mdl",
"models/props/de_inferno/churchprop03.mdl",
"models/props/de_inferno/churchprop04.mdl",
"models/props/de_inferno/churchprop05.mdl",
"models/props/de_inferno/clayoven.mdl",
"models/props/de_inferno/confessional.mdl",
"models/props/de_inferno/crate_fruit_break.mdl",
"models/props/de_inferno/crate_fruit_break_p1.mdl",
"models/props/de_inferno/de_inferno_boulder_01.mdl",
"models/props/de_inferno/de_inferno_boulder_02.mdl",
"models/props/de_inferno/de_inferno_boulder_03.mdl",
"models/props/de_inferno/fireplace.mdl",
"models/props/de_inferno/flower_barrel.mdl",
"models/props/de_inferno/furniturecouch001a.mdl",
"models/props/de_inferno/furniture_couch02a.mdl",
"models/props/de_inferno/hay_bails.mdl",
"models/props/de_inferno/largebush04.mdl",
"models/props/de_inferno/largebush06.mdl",
"models/props/de_inferno/light_fixture.mdl",
"models/props/de_inferno/light_streetlight.mdl",
"models/props/de_inferno/monument.mdl",
"models/props/de_inferno/picture1.mdl",
"models/props/de_inferno/picture2.mdl",
"models/props/de_inferno/picture3.mdl",
"models/props/de_inferno/potted_plant1.mdl",
"models/props/de_inferno/potted_plant2.mdl",
"models/props/de_inferno/pot_big.mdl",
"models/props/de_inferno/tableantique.mdl",
"models/props/de_inferno/tv_monitor01.mdl",
"models/props/de_inferno/wagon.mdl",
"models/props/de_nuke/cinderblock_stack.mdl",
"models/props/de_nuke/clock.mdl",
"models/props/de_nuke/crate_extrasmall.mdl",
"models/props/de_nuke/crate_large.mdl",
"models/props/de_nuke/crate_small.mdl",
"models/props/de_nuke/emergency_lighta.mdl",
"models/props/de_nuke/equipment1.mdl",
"models/props/de_nuke/equipment3a.mdl",
"models/props/de_nuke/file_cabinet1_group.mdl",
"models/props/de_nuke/handtruck.mdl",
"models/props/de_nuke/industriallight01.mdl",
"models/props/de_nuke/lifepreserver.mdl",
"models/props/de_nuke/light_red1.mdl",
"models/props/de_nuke/light_red2.mdl",
"models/props/de_nuke/nuclearcontrolbox.mdl",
"models/props/de_nuke/nucleartestcabinet.mdl",
"models/props/de_piranesi/pi_bench.mdl",
"models/props/de_piranesi/pi_bucket.mdl",
"models/props/de_piranesi/pi_orrery.mdl",
"models/props/de_piranesi/pi_sundial.mdl",
"models/props/de_prodigy/ammo_can_01.mdl",
"models/props/de_prodigy/ammo_can_02.mdl",
"models/props/de_prodigy/ammo_can_03.mdl",
"models/props/de_prodigy/pushcart.mdl",
"models/props/de_tides/lights_studio.mdl",
"models/props/de_tides/patio_chair.mdl",
"models/props/de_tides/patio_chair2.mdl",
"models/props/de_tides/restaurant_table.mdl",
"models/props/de_tides/tides_staffonly_sign.mdl",
"models/props/de_tides/vending_cart.mdl",
"models/props/de_tides/vending_cart_base.mdl",
"models/props/de_tides/vending_hat.mdl",
"models/props/de_tides/vending_tshirt.mdl",
"models/props/de_tides/vending_turtle.mdl",
"models/props/de_train/processor_nobase.mdl",
"models/props_borealis/bluebarrel001.mdl",
"models/props_borealis/borealis_door001a.mdl",
"models/props_borealis/door_wheel001a.mdl",
"models/props_borealis/mooring_cleat01.mdl",
"models/props_building_details/courtyard_template001c_bars.mdl",
"models/props_building_details/courtyard_template002c_bars.mdl",
"models/props_c17/awning001a.mdl",
"models/props_c17/awning002a.mdl",
"models/props_c17/bench01a.mdl",
"models/props_c17/briefcase001a.mdl",
"models/props_c17/canister01a.mdl",
"models/props_c17/canister02a.mdl",
"models/props_c17/cashregister01a.mdl",
"models/props_c17/chair02a.mdl",
"models/props_c17/chair_kleiner03a.mdl",
"models/props_c17/chair_office01a.mdl",
"models/props_c17/chair_stool01a.mdl",
"models/props_c17/clock01.mdl",
"models/props_c17/computer01_keyboard.mdl",
"models/props_c17/concrete_barrier001a.mdl",
"models/props_c17/display_cooler01a.mdl",
"models/props_c17/doll01.mdl",
"models/props_c17/door01_left.mdl",
"models/props_c17/door02_double.mdl",
"models/props_c17/fence01a.mdl",
"models/props_c17/fence01b.mdl",
"models/props_c17/fence02a.mdl",
"models/props_c17/fence02b.mdl",
"models/props_c17/fence03a.mdl",
"models/props_c17/frame002a.mdl",
"models/props_c17/furniturebathtub001a.mdl",
"models/props_c17/furniturebed001a.mdl",
"models/props_c17/furniturechair001a.mdl",
"models/props_c17/furniturecouch001a.mdl",
"models/props_c17/furniturecouch002a.mdl",
"models/props_c17/furniturecupboard001a.mdl",
"models/props_c17/furnituredrawer001a.mdl",
"models/props_c17/furnituredrawer001a_chunk01.mdl",
"models/props_c17/furnituredrawer001a_chunk02.mdl",
"models/props_c17/furnituredrawer001a_chunk03.mdl",
"models/props_c17/furnituredrawer001a_chunk05.mdl",
"models/props_c17/furnituredrawer001a_chunk06.mdl",
"models/props_c17/furnituredrawer002a.mdl",
"models/props_c17/furnituredrawer003a.mdl",
"models/props_c17/furnituredresser001a.mdl",
"models/props_c17/furniturefireplace001a.mdl",
"models/props_c17/furniturefridge001a.mdl",
"models/props_c17/furnitureradiator001a.mdl",
"models/props_c17/furnitureshelf001a.mdl",
"models/props_c17/furnitureshelf001b.mdl",
"models/props_c17/furnitureshelf002a.mdl",
"models/props_c17/furnituresink001a.mdl",
"models/props_c17/furniturestove001a.mdl",
"models/props_c17/furnituretable001a.mdl",
"models/props_c17/furnituretable002a.mdl",
"models/props_c17/furnituretable003a.mdl",
"models/props_c17/furnituretoilet001a.mdl",
"models/props_c17/furniturewashingmachine001a.mdl",
"models/props_c17/gaspipes006a.mdl",
"models/props_c17/gate_door01a.mdl",
"models/props_c17/gate_door02a.mdl",
"models/props_c17/gravestone001a.mdl",
"models/props_c17/gravestone002a.mdl",
"models/props_c17/gravestone003a.mdl",
"models/props_c17/gravestone004a.mdl",
"models/props_c17/gravestone_coffinpiece001a.mdl",
"models/props_c17/gravestone_coffinpiece002a.mdl",
"models/props_c17/gravestone_cross001b.mdl",
"models/props_c17/gravestone_statue001a.mdl",
"models/props_c17/lamp001a.mdl",
"models/props_c17/lampshade001a.mdl",
"models/props_c17/light_cagelight02_on.mdl",
"models/props_c17/light_floodlight02_off.mdl",
"models/props_c17/light_magnifyinglamp02.mdl",
"models/props_c17/lockers001a.mdl",
"models/props_c17/metalladder001.mdl",
"models/props_c17/metalladder002.mdl",
"models/props_c17/metalpot001a.mdl",
"models/props_c17/metalpot002a.mdl",
"models/props_c17/oildrum001.mdl",
"models/props_c17/playgroundslide01.mdl",
"models/props_c17/playgroundtick-tack-toe_block01a.mdl",
"models/props_c17/playgroundtick-tack-toe_post01.mdl",
"models/props_c17/playground_carousel01.mdl",
"models/props_c17/playground_jungle_gym01a.mdl",
"models/props_c17/playground_jungle_gym01b.mdl",
"models/props_c17/playground_teetertoter_seat.mdl",
"models/props_c17/playground_teetertoter_stan.mdl",
"models/props_c17/pottery01a.mdl",
"models/props_c17/pottery02a.mdl",
"models/props_c17/pottery03a.mdl",
"models/props_c17/pottery04a.mdl",
"models/props_c17/pottery05a.mdl",
"models/props_c17/pottery06a.mdl",
"models/props_c17/pottery07a.mdl",
"models/props_c17/pottery08a.mdl",
"models/props_c17/pottery09a.mdl",
"models/props_c17/pottery_large01a.mdl",
"models/props_c17/pulleyhook01.mdl",
"models/props_c17/shelfunit01a.mdl",
"models/props_c17/signpole001.mdl",
"models/props_c17/streetsign001c.mdl",
"models/props_c17/streetsign002b.mdl",
"models/props_c17/streetsign003b.mdl",
"models/props_c17/streetsign004e.mdl",
"models/props_c17/streetsign004f.mdl",
"models/props_c17/streetsign005b.mdl",
"models/props_c17/streetsign005c.mdl",
"models/props_c17/streetsign005d.mdl",
"models/props_c17/suitcase001a.mdl",
"models/props_c17/traffic_light001a.mdl",
"models/props_c17/trappropeller_lever.mdl",
"models/props_c17/truss02g.mdl",
"models/props_c17/truss02h.mdl",
"models/props_c17/truss03b.mdl",
"models/props_c17/tv_monitor01.mdl",
"models/props_c17/utilityconnecter006.mdl",
"models/props_c17/utilityconnecter006c.mdl",
"models/props_c17/utilitypole01a.mdl",
"models/props_c17/woodbarrel001.mdl",
"models/props_canal/mattpipe.mdl",
"models/props_combine/breenbust.mdl",
"models/props_combine/breenchair.mdl",
"models/props_combine/breenclock.mdl",
"models/props_combine/breenconsole.mdl",
"models/props_combine/breendesk.mdl",
"models/props_combine/breenglobe.mdl",
"models/props_combine/breenpod.mdl",
"models/props_combine/breenpod_inner.mdl",
"models/props_combine/bunker_gun01.mdl",
"models/props_combine/cell_01_pod.mdl",
"models/props_combine/cell_01_pod_cheap.mdl",
"models/props_combine/combinebutton.mdl",
"models/props_combine/combine_barricade_med01a.mdl",
"models/props_combine/combine_barricade_med01b.mdl",
"models/props_combine/combine_barricade_med02a.mdl",
"models/props_combine/combine_barricade_med02b.mdl",
"models/props_combine/combine_barricade_med02c.mdl",
"models/props_combine/combine_barricade_med03b.mdl",
"models/props_combine/combine_barricade_med04b.mdl",
"models/props_combine/combine_barricade_short01a.mdl",
"models/props_combine/combine_barricade_short02a.mdl",
"models/props_combine/combine_barricade_short03a.mdl",
"models/props_combine/combine_barricade_tall01a.mdl",
"models/props_combine/combine_barricade_tall01b.mdl",
"models/props_combine/combine_barricade_tall03a.mdl",
"models/props_combine/combine_barricade_tall03b.mdl",
"models/props_combine/combine_barricade_tall04a.mdl",
"models/props_combine/combine_barricade_tall04b.mdl",
"models/props_combine/combine_booth_med01a.mdl",
"models/props_combine/combine_booth_short01a.mdl",
"models/props_combine/combine_emitter01.mdl",
"models/props_combine/combine_fence01a.mdl",
"models/props_combine/combine_fence01b.mdl",
"models/props_combine/combine_interface001.mdl",
"models/props_combine/combine_interface002.mdl",
"models/props_combine/combine_interface003.mdl",
"models/props_combine/combine_intwallunit.mdl",
"models/props_combine/combine_window001.mdl",
"models/props_combine/weaponstripper.mdl",
"models/props_debris/metal_panel01a.mdl",
"models/props_debris/metal_panel02a.mdl",
"models/props_debris/wall001a_base.mdl",
"models/props_docks/dock01_cleat01a.mdl",
"models/props_docks/dock01_pole01a_128.mdl",
"models/props_docks/dock01_pole01a_256.mdl",
"models/props_doors/door03_slotted_left.mdl",
"models/props_industrial/bridge_deck.mdl",
"models/props_industrial/winch_stern.mdl",
"models/props_interiors/bathtub01a.mdl",
"models/props_interiors/furniture_chair01a.mdl",
"models/props_interiors/furniture_chair03a.mdl",
"models/props_interiors/furniture_couch01a.mdl",
"models/props_interiors/furniture_couch02a.mdl",
"models/props_interiors/furniture_desk01a.mdl",
"models/props_interiors/furniture_lamp01a.mdl",
"models/props_interiors/furniture_shelf01a.mdl",
"models/props_interiors/furniture_vanity01a.mdl",
"models/props_interiors/pot01a.mdl",
"models/props_interiors/pot02a.mdl",
"models/props_interiors/radiator01a.mdl",
"models/props_interiors/refrigerator01a.mdl",
"models/props_interiors/refrigeratordoor01a.mdl",
"models/props_interiors/refrigeratordoor02a.mdl",
"models/props_interiors/sinkkitchen01a.mdl",
"models/props_junk/bicycle01a.mdl",
"models/props_junk/cardboard_box001a.mdl",
"models/props_junk/cardboard_box001a_gib01.mdl",
"models/props_junk/cardboard_box001b.mdl",
"models/props_junk/cardboard_box002a.mdl",
"models/props_junk/cardboard_box002a_gib01.mdl",
"models/props_junk/cardboard_box002b.mdl",
"models/props_junk/cardboard_box003a.mdl",
"models/props_junk/cardboard_box003a_gib01.mdl",
"models/props_junk/cardboard_box003b.mdl",
"models/props_junk/cardboard_box003b_gib01.mdl",
"models/props_junk/cinderblock01a.mdl",
"models/props_junk/garbage128_composite001a.mdl",
"models/props_junk/garbage128_composite001b.mdl",
"models/props_junk/garbage128_composite001c.mdl",
"models/props_junk/garbage128_composite001d.mdl",
"models/props_junk/garbage256_composite001a.mdl",
"models/props_junk/garbage256_composite001b.mdl",
"models/props_junk/garbage256_composite002a.mdl",
"models/props_junk/garbage256_composite002b.mdl",
"models/props_junk/garbage_bag001a.mdl",
"models/props_junk/garbage_carboard002a.mdl",
"models/props_junk/garbage_coffeemug001a.mdl",
"models/props_junk/garbage_newspaper001a.mdl",
"models/props_junk/glassjug01.mdl",
"models/props_junk/harpoon002a.mdl",
"models/props_junk/metalbucket01a.mdl",
"models/props_junk/metalbucket02a.mdl",
"models/props_junk/metalgascan.mdl",
"models/props_junk/plasticbucket001a.mdl",
"models/props_junk/pushcart01a.mdl",
"models/props_junk/ravenholmsign.mdl",
"models/props_junk/shoe001a.mdl",
"models/props_junk/shovel01a.mdl",
"models/props_junk/terracotta01.mdl",
"models/props_junk/trafficcone001a.mdl",
"models/props_junk/trashbin01a.mdl",
"models/props_junk/trashdumpster01a.mdl",
"models/props_junk/trashdumpster02b.mdl",
"models/props_junk/wheebarrow01a.mdl",
"models/props_junk/wood_crate001a.mdl",
"models/props_junk/wood_crate001a_damaged.mdl",
"models/props_junk/wood_crate002a.mdl",
"models/props_junk/wood_pallet001a.mdl",
"models/props_lab/bewaredog.mdl",
"models/props_lab/binderblue.mdl",
"models/props_lab/binderbluelabel.mdl",
"models/props_lab/bindergraylabel01a.mdl",
"models/props_lab/bindergraylabel01b.mdl",
"models/props_lab/bindergreen.mdl",
"models/props_lab/bindergreenlabel.mdl",
"models/props_lab/binderredlabel.mdl",
"models/props_lab/blastdoor001a.mdl",
"models/props_lab/blastdoor001b.mdl",
"models/props_lab/blastdoor001c.mdl",
"models/props_lab/cactus.mdl",
"models/props_lab/clipboard.mdl",
"models/props_lab/cornerunit2.mdl",
"models/props_lab/desklamp01.mdl",
"models/props_lab/filecabinet02.mdl",
"models/props_lab/frame002a.mdl",
"models/props_lab/generatorconsole.mdl",
"models/props_lab/harddrive01.mdl",
"models/props_lab/hevplate.mdl",
"models/props_lab/huladoll.mdl",
"models/props_lab/kennel_physics.mdl",
"models/props_lab/lockerdoorleft.mdl",
"models/props_lab/miniteleport.mdl",
"models/props_lab/monitor01a.mdl",
"models/props_lab/monitor01b.mdl",
"models/props_lab/monitor02.mdl",
"models/props_lab/partsbin01.mdl",
"models/props_lab/plotter.mdl",
"models/props_lab/powerbox02d.mdl",
"models/props_lab/reciever01a.mdl",
"models/props_lab/reciever01b.mdl",
"models/props_lab/reciever_cart.mdl",
"models/props_lab/securitybank.mdl",
"models/props_lab/servers.mdl",
"models/props_lab/teleplatform.mdl",
"models/props_lab/tpplugholder.mdl",
"models/props_lab/tpplugholder_single.mdl",
"models/props_lab/workspace001.mdl",
"models/props_lab/workspace002.mdl",
"models/props_lab/workspace003.mdl",
"models/props_lab/workspace004.mdl",
"models/props_phx/construct/concrete_barrier00.mdl",
"models/props_phx/construct/concrete_barrier01.mdl",
"models/props_phx/construct/glass/glass_angle180.mdl",
"models/props_phx/construct/glass/glass_angle360.mdl",
"models/props_phx/construct/glass/glass_angle90.mdl",
"models/props_phx/construct/glass/glass_curve180x1.mdl",
"models/props_phx/construct/glass/glass_curve180x2.mdl",
"models/props_phx/construct/glass/glass_curve90x1.mdl",
"models/props_phx/construct/glass/glass_curve90x2.mdl",
"models/props_phx/construct/glass/glass_dome180.mdl",
"models/props_phx/construct/glass/glass_dome90.mdl",
"models/props_phx/construct/glass/glass_plate1x1.mdl",
"models/props_phx/construct/glass/glass_plate1x2.mdl",
"models/props_phx/construct/glass/glass_plate2x2.mdl",
"models/props_phx/construct/glass/glass_plate2x4.mdl",
"models/props_phx/construct/glass/glass_plate4x4.mdl",
"models/props_phx/construct/metal_angle180.mdl",
"models/props_phx/construct/metal_angle360.mdl",
"models/props_phx/construct/metal_angle90.mdl",
"models/props_phx/construct/metal_dome180.mdl",
"models/props_phx/construct/metal_dome360.mdl",
"models/props_phx/construct/metal_dome90.mdl",
"models/props_phx/construct/metal_plate1.mdl",
"models/props_phx/construct/metal_plate1x2.mdl",
"models/props_phx/construct/metal_plate1x2_tri.mdl",
"models/props_phx/construct/metal_plate1_tri.mdl",
"models/props_phx/construct/metal_plate2x2.mdl",
"models/props_phx/construct/metal_plate2x2_tri.mdl",
"models/props_phx/construct/metal_plate2x4.mdl",
"models/props_phx/construct/metal_plate2x4_tri.mdl",
"models/props_phx/construct/metal_plate4x4.mdl",
"models/props_phx/construct/metal_plate4x4_tri.mdl",
"models/props_phx/construct/metal_plate_curve.mdl",
"models/props_phx/construct/metal_plate_curve180.mdl",
"models/props_phx/construct/metal_plate_curve180x2.mdl",
"models/props_phx/construct/metal_plate_curve2.mdl",
"models/props_phx/construct/metal_plate_curve2x2.mdl",
"models/props_phx/construct/metal_tube.mdl",
"models/props_phx/construct/metal_tubex2.mdl",
"models/props_phx/construct/metal_wire1x1.mdl",
"models/props_phx/construct/metal_wire1x1x1.mdl",
"models/props_phx/construct/metal_wire1x1x2.mdl",
"models/props_phx/construct/metal_wire1x1x2b.mdl",
"models/props_phx/construct/metal_wire1x2.mdl",
"models/props_phx/construct/metal_wire1x2b.mdl",
"models/props_phx/construct/metal_wire1x2x2b.mdl",
"models/props_phx/construct/metal_wire2x2.mdl",
"models/props_phx/construct/metal_wire2x2b.mdl",
"models/props_phx/construct/metal_wire2x2x2b.mdl",
"models/props_phx/construct/metal_wire_angle180x1.mdl",
"models/props_phx/construct/metal_wire_angle180x2.mdl",
"models/props_phx/construct/metal_wire_angle90x1.mdl",
"models/props_phx/construct/metal_wire_angle90x2.mdl",
"models/props_phx/construct/plastic/plastic_angle_360.mdl",
"models/props_phx/construct/plastic/plastic_panel1x1.mdl",
"models/props_phx/construct/plastic/plastic_panel1x2.mdl",
"models/props_phx/construct/windows/window1x1.mdl",
"models/props_phx/construct/windows/window1x2.mdl",
"models/props_phx/construct/windows/window2x2.mdl",
"models/props_phx/construct/windows/window2x4.mdl",
"models/props_phx/construct/windows/window4x4.mdl",
"models/props_phx/construct/windows/window_angle180.mdl",
"models/props_phx/construct/windows/window_angle360.mdl",
"models/props_phx/construct/windows/window_angle90.mdl",
"models/props_phx/construct/windows/window_curve180x1.mdl",
"models/props_phx/construct/windows/window_curve180x2.mdl",
"models/props_phx/construct/windows/window_curve90x1.mdl",
"models/props_phx/construct/windows/window_curve90x2.mdl",
"models/props_phx/construct/wood/wood_angle180.mdl",
"models/props_phx/construct/wood/wood_angle360.mdl",
"models/props_phx/construct/wood/wood_angle90.mdl",
"models/props_phx/construct/wood/wood_boardx1.mdl",
"models/props_phx/construct/wood/wood_boardx2.mdl",
"models/props_phx/construct/wood/wood_curve180x1.mdl",
"models/props_phx/construct/wood/wood_curve180x2.mdl",
"models/props_phx/construct/wood/wood_curve90x1.mdl",
"models/props_phx/construct/wood/wood_curve90x2.mdl",
"models/props_phx/construct/wood/wood_dome180.mdl",
"models/props_phx/construct/wood/wood_dome360.mdl",
"models/props_phx/construct/wood/wood_dome90.mdl",
"models/props_phx/construct/wood/wood_panel1x1.mdl",
"models/props_phx/construct/wood/wood_panel1x2.mdl",
"models/props_phx/construct/wood/wood_panel2x2.mdl",
"models/props_phx/construct/wood/wood_panel2x4.mdl",
"models/props_phx/construct/wood/wood_panel4x4.mdl",
"models/props_phx/construct/wood/wood_wire1x1.mdl",
"models/props_phx/construct/wood/wood_wire1x1x1.mdl",
"models/props_phx/construct/wood/wood_wire1x1x2.mdl",
"models/props_phx/construct/wood/wood_wire1x1x2b.mdl",
"models/props_phx/construct/wood/wood_wire1x2.mdl",
"models/props_phx/construct/wood/wood_wire1x2b.mdl",
"models/props_phx/construct/wood/wood_wire1x2x2b.mdl",
"models/props_phx/construct/wood/wood_wire2x2.mdl",
"models/props_phx/construct/wood/wood_wire2x2b.mdl",
"models/props_phx/construct/wood/wood_wire2x2x2b.mdl",
"models/props_phx/empty_barrel.mdl",
"models/props_phx/games/chess/black_bishop.mdl",
"models/props_phx/games/chess/black_dama.mdl",
"models/props_phx/games/chess/black_king.mdl",
"models/props_phx/games/chess/black_knight.mdl",
"models/props_phx/games/chess/black_pawn.mdl",
"models/props_phx/games/chess/black_queen.mdl",
"models/props_phx/games/chess/black_rook.mdl",
"models/props_phx/games/chess/white_bishop.mdl",
"models/props_phx/games/chess/white_dama.mdl",
"models/props_phx/games/chess/white_king.mdl",
"models/props_phx/games/chess/white_knight.mdl",
"models/props_phx/games/chess/white_pawn.mdl",
"models/props_phx/games/chess/white_queen.mdl",
"models/props_phx/games/chess/white_rook.mdl",
"models/props_phx/misc/fender.mdl",
"models/props_phx/misc/t_light_head.mdl",
"models/props_phx/rt_screen.mdl",
"models/props_rooftop/satellitedish02.mdl",
"models/props_rooftop/sign_letter02_e002.mdl",
"models/props_rooftop/sign_letter02_k002.mdl",
"models/props_rooftop/sign_letter02_rus1002.mdl",
"models/props_rooftop/sign_letter_f001b.mdl",
"models/props_rooftop/sign_letter_h001.mdl",
"models/props_rooftop/sign_letter_m001.mdl",
"models/props_rooftop/sign_letter_t001.mdl",
"models/props_rooftop/sign_letter_u001b.mdl",
"models/props_trainstation/benchoutdoor01a.mdl",
"models/props_trainstation/bench_indoor001a.mdl",
"models/props_trainstation/payphone001a.mdl",
"models/props_trainstation/tracksign02.mdl",
"models/props_trainstation/tracksign07.mdl",
"models/props_trainstation/tracksign08.mdl",
"models/props_trainstation/tracksign09.mdl",
"models/props_trainstation/tracksign10.mdl",
"models/props_trainstation/traincar_seats001.mdl",
"models/props_trainstation/trainstation_arch001.mdl",
"models/props_trainstation/trainstation_clock001.mdl",
"models/props_trainstation/trainstation_post001.mdl",
"models/props_trainstation/trashcan_indoor001a.mdl",
"models/props_trainstation/trashcan_indoor001b.mdl",
"models/props_vehicles/carparts_door01a.mdl",
"models/props_vehicles/carparts_tire01a.mdl",
"models/props_wasteland/barricade001a.mdl",
"models/props_wasteland/barricade002a.mdl",
"models/props_wasteland/buoy01.mdl",
"models/props_wasteland/cafeteria_table001a.mdl",
"models/props_wasteland/controlroom_chair001a.mdl",
"models/props_wasteland/controlroom_desk001a.mdl",
"models/props_wasteland/controlroom_desk001b.mdl",
"models/props_wasteland/controlroom_filecabinet001a.mdl",
"models/props_wasteland/controlroom_filecabinet002a.mdl",
"models/props_wasteland/controlroom_monitor001a.mdl",
"models/props_wasteland/dockplank01b.mdl",
"models/props_wasteland/exterior_fence001a.mdl",
"models/props_wasteland/exterior_fence001b.mdl",
"models/props_wasteland/exterior_fence002a.mdl",
"models/props_wasteland/exterior_fence002b.mdl",
"models/props_wasteland/exterior_fence002c.mdl",
"models/props_wasteland/exterior_fence002d.mdl",
"models/props_wasteland/exterior_fence003a.mdl",
"models/props_wasteland/exterior_fence003b.mdl",
"models/props_wasteland/gaspump001a.mdl",
"models/props_wasteland/interior_fence001a.mdl",
"models/props_wasteland/interior_fence001b.mdl",
"models/props_wasteland/interior_fence001c.mdl",
"models/props_wasteland/interior_fence001d.mdl",
"models/props_wasteland/interior_fence001e.mdl",
"models/props_wasteland/interior_fence001g.mdl",
"models/props_wasteland/interior_fence002a.mdl",
"models/props_wasteland/interior_fence002b.mdl",
"models/props_wasteland/interior_fence002c.mdl",
"models/props_wasteland/interior_fence002d.mdl",
"models/props_wasteland/interior_fence002e.mdl",
"models/props_wasteland/interior_fence002f.mdl",
"models/props_wasteland/interior_fence003a.mdl",
"models/props_wasteland/interior_fence003b.mdl",
"models/props_wasteland/interior_fence003d.mdl",
"models/props_wasteland/interior_fence003e.mdl",
"models/props_wasteland/interior_fence003f.mdl",
"models/props_wasteland/kitchen_counter001a.mdl",
"models/props_wasteland/kitchen_counter001b.mdl",
"models/props_wasteland/kitchen_counter001c.mdl",
"models/props_wasteland/kitchen_counter001d.mdl",
"models/props_wasteland/kitchen_shelf001a.mdl",
"models/props_wasteland/kitchen_shelf002a.mdl",
"models/props_wasteland/kitchen_stove001a.mdl",
"models/props_wasteland/kitchen_stove002a.mdl",
"models/props_wasteland/laundry_basket001.mdl",
"models/props_wasteland/laundry_cart001.mdl",
"models/props_wasteland/laundry_cart002.mdl",
"models/props_wasteland/laundry_washer003.mdl",
"models/props_wasteland/light_spotlight01_lamp.mdl",
"models/props_wasteland/prison_bedframe001b.mdl",
"models/props_wasteland/prison_celldoor001a.mdl",
"models/props_wasteland/prison_celldoor001b.mdl",
"models/props_wasteland/prison_cellwindow002a.mdl",
"models/props_wasteland/prison_heater001a.mdl",
"models/props_wasteland/prison_lamp001c.mdl",
"models/props_wasteland/prison_shelf002a.mdl",
"models/props_wasteland/prison_sink001a.mdl",
"models/props_wasteland/prison_toilet01.mdl",
"models/props_wasteland/speakercluster01a.mdl",
"models/props_wasteland/wood_fence01a.mdl",
"models/props_wasteland/wood_fence02a.mdl"
}
}

View File

@@ -0,0 +1,9 @@
{
"title": "3D2D Textscreens",
"type": "tool",
"tags": [
"fun",
"roleplay"
],
"ignore": []
}

View File

@@ -0,0 +1,180 @@
local function checkAdmin(ply)
-- The server console always has access. `ply` is NULL in this case
local isConsole = ply == nil or ply == NULL
if isConsole then
return true
end
local canAdmin = hook.Run("TextscreensCanAdmin", ply) -- run custom hook function to check admin
if canAdmin == nil then -- if hook hasn't returned anything, default to super admin check
canAdmin = ply:IsSuperAdmin()
end
return canAdmin
end
-- allow servers to disable rainbow effect for everyone
CreateConVar("ss_enable_rainbow", 1, {FCVAR_NOTIFY, FCVAR_REPLICATED}, "Determines whether rainbow textscreens will render for all clients. When disabled, rainbow screens will render as solid white.", 0, 1)
-- allow servers to restrict the number of characters per line for everyone
CreateConVar("ss_max_characters", 0, {FCVAR_NOTIFY, FCVAR_REPLICATED}, "Determines the maximum number of characters per line for all clients. When set to 0, the maximum number of characters is infinite.", 0)
if SERVER then
AddCSLuaFile()
AddCSLuaFile("textscreens_config.lua")
include("textscreens_config.lua")
CreateConVar("sbox_maxtextscreens", "1", {FCVAR_NOTIFY, FCVAR_REPLICATED}, "Determines the maximum number of textscreens users can spawn.")
--local rainbow_enabled = cvars.Number('ss_enable_rainbow', 1)
local function StringRandom(int)
math.randomseed(os.time())
local s = ""
for i = 1, int do
s = s .. string.char(math.random(65, 90))
end
return s
end
local textscreens = {}
local function SpawnPermaTextscreens()
print("[3D2D Textscreens] Spawning textscreens...")
textscreens = file.Read("sammyservers_textscreens.txt", "DATA")
if not textscreens or textscreens == "" then
textscreens = {}
print("[3D2D Textscreens] Spawned 0 textscreens for map " .. game.GetMap())
return
end
textscreens = util.JSONToTable(textscreens)
local existingTextscreens = {}
for k,v in pairs(ents.FindByClass("sammyservers_textscreen")) do
if not v.uniqueName then continue end
existingTextscreens[v.uniqueName] = true
end
local count = 0
for k, v in pairs(textscreens) do
if v.MapName ~= game.GetMap() then continue end
if existingTextscreens[v.uniqueName] then continue end
local textScreen = ents.Create("sammyservers_textscreen")
textScreen:SetPos(Vector(v.posx, v.posy, v.posz))
textScreen:SetAngles(Angle(v.angp, v.angy, v.angr))
textScreen.uniqueName = v.uniqueName
textScreen:Spawn()
textScreen:Activate()
textScreen:SetMoveType(MOVETYPE_NONE)
for lineNum, lineData in pairs(v.lines or {}) do
textScreen:SetLine(lineNum, lineData.text, Color(lineData.color.r, lineData.color.g, lineData.color.b, lineData.color.a), lineData.size, lineData.font, lineData.rainbow or 0)
end
textScreen:SetIsPersisted(true)
count = count + 1
end
print("[3D2D Textscreens] Spawned " .. count .. " textscreens for map " .. game.GetMap())
end
hook.Add("InitPostEntity", "loadTextScreens", function()
timer.Simple(10, SpawnPermaTextscreens)
end)
hook.Add("PostCleanupMap", "loadTextScreens", SpawnPermaTextscreens)
-- If a player, use ChatPrint method, else print directly to server console
local function printMessage(ply, msg)
local isConsole = ply == nil or ply == NULL
if isConsole then
print(msg)
else
ply:ChatPrint(msg)
end
end
concommand.Add("SS_TextScreen", function(ply, cmd, args)
if not checkAdmin(ply) or not args or not args[1] or not args[2] or not (args[1] == "delete" or args[1] == "add") then
printMessage(ply, "not authorised, or bad arguments")
return
end
local ent = Entity(args[2])
if not IsValid(ent) or ent:GetClass() ~= "sammyservers_textscreen" then return false end
if args[1] == "add" then
local pos = ent:GetPos()
local ang = ent:GetAngles()
local toAdd = {}
toAdd.posx = pos.x
toAdd.posy = pos.y
toAdd.posz = pos.z
toAdd.angp = ang.p
toAdd.angy = ang.y
toAdd.angr = ang.r
-- So we can reference it easily later because EntIndexes are so unreliable
toAdd.uniqueName = StringRandom(10)
toAdd.MapName = game.GetMap()
toAdd.lines = ent.lines
table.insert(textscreens, toAdd)
file.Write("sammyservers_textscreens.txt", util.TableToJSON(textscreens))
ent:SetIsPersisted(true)
return printMessage(ply, "Textscreen made permanent and saved.")
else
for k, v in pairs(textscreens) do
if v.uniqueName == ent.uniqueName then
textscreens[k] = nil
end
end
ent:Remove()
file.Write("sammyservers_textscreens.txt", util.TableToJSON(textscreens))
return printMessage(ply, "Textscreen removed and is no longer permanent.")
end
end)
-- Add to pocket blacklist for DarkRP
-- Not using gamemode == "darkrp" because there are lots of flavours of darkrp
hook.Add("loadCustomDarkRPItems", "sammyservers_pocket_blacklist", function()
GAMEMODE.Config.PocketBlacklist["sammyservers_textscreen"] = true
end)
end
if CLIENT then
include("textscreens_config.lua")
properties.Add("addPermaScreen", {
MenuLabel = "Make perma textscreen",
Order = 2001,
MenuIcon = "icon16/transmit.png",
Filter = function(self, ent, ply)
if not IsValid(ent) or ent:GetClass() ~= "sammyservers_textscreen" then return false end
if ent:GetIsPersisted() then return false end
return checkAdmin(ply)
end,
Action = function(self, ent)
if not IsValid(ent) then return false end
return RunConsoleCommand("SS_TextScreen", "add", ent:EntIndex())
end
})
properties.Add("removePermaScreen", {
MenuLabel = "Remove perma textscreen",
Order = 2002,
MenuIcon = "icon16/transmit_delete.png",
Filter = function(self, ent, ply)
if not IsValid(ent) or ent:GetClass() ~= "sammyservers_textscreen" then return false end
if not ent:GetIsPersisted() then return false end
return checkAdmin(ply)
end,
Action = function(self, ent)
if not IsValid(ent) then return end
return RunConsoleCommand("SS_TextScreen", "delete", ent:EntIndex())
end
})
end

View File

@@ -0,0 +1,228 @@
include("shared.lua")
local render_convar_range = CreateClientConVar("ss_render_range", 1500, true, false, "Determines the render range for Textscreens. Default 1500")
local render_rainbow = CreateClientConVar("ss_render_rainbow", 1, true, false, "Determines if rainbow screens are rendered. If disabled (0), will render as solid white. Default enabled (1)", 0, 1)
local render_range = render_convar_range:GetInt() * render_convar_range:GetInt() --We multiply this is that we can use DistToSqr instead of Distance so we don't need to workout the square root all the time
local rainbow_enabled = cvars.Number("ss_enable_rainbow", 1)
local textscreenFonts = textscreenFonts
local screenInfo = {}
local shouldDrawBoth = false
-- Numbers used in conjunction with text width to work out the render bounds
local widthBoundsDivider = 7.9
local heightBoundsDivider = 12.4
-- ENUM type things for faster table indexing
local FONT = 1
local TEXT = 2
local POSX = 3
local POSY = 4
local COL = 5
local LEN = 6
local SIZE = 7
local CAMSIZE = 8
local RAINBOW = 9
-- Make ply:ShouldDrawLocalPlayer() never get called more than once a frame
hook.Add("Think", "ss_should_draw_both_sides", function()
shouldDrawBoth = LocalPlayer():ShouldDrawLocalPlayer()
end)
local function ValidFont(f)
if textscreenFonts[f] ~= nil then
return textscreenFonts[f]
elseif table.HasValue(textscreenFonts, f) then
return f
else
return false
end
end
cvars.AddChangeCallback("ss_render_range", function(convar_name, value_old, value_new)
render_range = tonumber(value_new) * tonumber(value_new)
end, "3D2DScreens")
cvars.AddChangeCallback("ss_render_rainbow", function(convar_name, value_old, value_new)
render_rainbow = tonumber(value_new)
end, "3D2DScreens")
-- TODO: https://github.com/Facepunch/garrysmod-issues/issues/3740
-- cvars.AddChangeCallback("ss_enable_rainbow", function(convar_name, value_old, value_new)
-- print('ss_enable_rainbow changed: '.. value_new)
-- rainbow_enabled = tonumber(value_new)
-- end, "3D2DScreens")
function ENT:Initialize()
self:SetMaterial("models/effects/vol_light001")
self:SetRenderMode(RENDERMODE_NONE)
net.Start("textscreens_download")
net.WriteEntity(self)
net.SendToServer()
end
local product
local function IsInFront(entPos, plyShootPos, direction)
product = (entPos.x - plyShootPos.x) * direction.x +
(entPos.y - plyShootPos.y) * direction.y +
(entPos.z - plyShootPos.z) * direction.z
return product < 0
end
-- Draws the 3D2D text with the given positions, angles and data(text/font/col)
local function Draw3D2D(ang, pos, camangle, data)
for i = 1, data[LEN] do
if not data[i] or not data[i][TEXT] then continue end
cam.Start3D2D(pos, camangle, data[i][CAMSIZE] )
render.PushFilterMin(TEXFILTER.ANISOTROPIC)
-- Font
surface.SetFont(data[i][FONT])
-- Position
surface.SetTextPos(data[i][POSX], data[i][POSY])
-- Rainbow
if data[i][RAINBOW] ~= nil and data[i][RAINBOW] ~= 0 then
local j = 0
for _, code in utf8.codes(data[i][TEXT]) do
j = j + 1
--Color
if rainbow_enabled == 1 and render_rainbow ~= 0 then
surface.SetTextColor(HSVToColor((CurTime() * 60 + (j * 5)) % 360, 1, 1))
else
-- Render as solid white if ss_render_rainbow is disabled or server disabled via ss_enable_rainbow
surface.SetTextColor(255, 255, 255)
end
--Text
surface.DrawText(utf8.char(code))
end
else
--Color
surface.SetTextColor(data[i][COL])
--Text
surface.DrawText(data[i][TEXT])
end
render.PopFilterMin()
cam.End3D2D()
end
end
local plyShootPos, ang, pos, camangle, showFront, data -- Less variables being created each frame
function ENT:DrawTranslucent()
-- Cache the shoot pos for this frame
plyShootPos = LocalPlayer():GetShootPos()
if screenInfo[self] ~= nil and self:GetPos():DistToSqr(plyShootPos) < render_range then
ang = self:GetAngles()
pos = self:GetPos() + ang:Up()
camangle = Angle(ang.p, ang.y, ang.r)
data = screenInfo[self]
-- Should we draw both screens? (Third person/calview drawing fix)
if shouldDrawBoth then
Draw3D2D(ang, pos, camangle, data)
camangle:RotateAroundAxis(camangle:Right(), 180)
Draw3D2D(ang, pos, camangle, data)
else
-- Is the front of the screen facing us or the back?
showFront = IsInFront(pos, plyShootPos, ang:Up())
-- Draw the front of the screen
if showFront then
Draw3D2D(ang, pos, camangle, data)
else
-- Draw the back of the screen
camangle:RotateAroundAxis(camangle:Right(), 180)
Draw3D2D(ang, pos, camangle, data)
end
end
end
end
local function AddDrawingInfo(ent, rawData)
local drawData = {}
local textSize = {}
local totalHeight = 0
local maxWidth = 0
local currentHeight = 0
for i = 1, #rawData do
-- Setup tables
if not rawData[i] or not rawData[i].text then continue end
drawData[i] = {}
textSize[i] = {}
-- Text
drawData[i][TEXT] = rawData[i].text
-- Font
drawData[i][FONT] = (ValidFont(rawData[i].font) or textscreenFonts[1])
-- Text size
surface.SetFont(drawData[i][FONT])
textSize[i][1], textSize[i][2] = surface.GetTextSize(drawData[i][TEXT])
textSize[i][2] = rawData[i].size
-- Workout max width for render bounds
maxWidth = maxWidth > textSize[i][1] and maxWidth or textSize[i][1]
-- Position
totalHeight = totalHeight + textSize[i][2]
-- Colour
drawData[i][COL] = Color(rawData[i].color.r, rawData[i].color.g, rawData[i].color.b, 255)
-- Size
drawData[i][SIZE] = rawData[i]["size"]
-- Remove text if text is empty so we don't waste performance
if string.len(drawData[i][TEXT]) == 0 or string.len(string.Replace( drawData[i][TEXT], " ", "" )) == 0 then drawData[i][TEXT] = nil end
--Rainbow
drawData[i][RAINBOW] = rawData[i]["rainbow"] or 0
end
-- Sort out heights
for i = 1, #rawData do
if not rawData[i] then continue end
-- The x position at which to draw the text relative to the text screen entity
drawData[i][POSX] = math.ceil(-textSize[i][1] / 2)
-- The y position at which to draw the text relative to the text screen entity
drawData[i][POSY] = math.ceil(-(totalHeight / 2) + currentHeight)
-- Calculate the cam.Start3D2D size based on the size of the font
drawData[i][CAMSIZE] = (0.25 * drawData[i][SIZE]) / 100
-- Use the CAMSIZE to "scale" the POSY
drawData[i][POSY] = (0.25 / drawData[i][CAMSIZE] * drawData[i][POSY])
-- Highest line to lowest, so that everything is central
currentHeight = currentHeight + textSize[i][2]
end
-- Cache the number of lines/length
drawData[LEN] = #drawData
-- Add the new data to our text screen list
screenInfo[ent] = drawData
-- Calculate the render bounds
local x = maxWidth / widthBoundsDivider
local y = currentHeight / heightBoundsDivider + 13 -- Text is above the centre
-- Setup the render bounds
ent:SetRenderBounds(Vector(-x, -y, -1.75), Vector(x, y, 1.75))
end
net.Receive("textscreens_update", function(len)
local ent = net.ReadEntity()
if IsValid(ent) and ent:GetClass() == "sammyservers_textscreen" then
local t = net.ReadTable()
ent.lines = t -- Incase an addon or something wants to read the information.
AddDrawingInfo(ent, t)
end
end)
-- Auto refresh
if IsValid(LocalPlayer()) then
local screens = ents.FindByClass("sammyservers_textscreen")
for k, v in ipairs(screens) do
if screenInfo[v] == nil and v.lines ~= nil then
AddDrawingInfo(v, v.lines)
end
end
end

View File

@@ -0,0 +1,134 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
resource.AddWorkshop("109643223")
include("shared.lua")
local CurTime = CurTime
local IsValid = IsValid
function ENT:Initialize()
self:SetRenderMode(RENDERMODE_TRANSALPHA)
self:DrawShadow(false)
self:SetModel("models/hunter/plates/plate1x1.mdl")
self:SetMaterial("models/effects/vol_light001")
self:SetSolid(SOLID_VPHYSICS)
self:SetCollisionGroup(COLLISION_GROUP_WORLD)
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:EnableMotion(false)
end
self.heldby = 0
end
function ENT:PhysicsUpdate(phys)
if self.heldby <= 0 then
phys:Sleep()
end
end
local function textScreenPickup(ply, ent)
if IsValid(ent) and ent:GetClass() == "sammyservers_textscreen" then
ent.heldby = ent.heldby + 1
end
end
hook.Add("PhysgunPickup", "3D2DTextScreensPreventTravelPickup", textScreenPickup)
local function textScreenDrop(ply, ent)
if IsValid(ent) and ent:GetClass() == "sammyservers_textscreen" then
ent.heldby = ent.heldby - 1
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
ent:PhysicsUpdate(phys)
end
end
end
hook.Add("PhysgunDrop", "3D2DTextScreensPreventTravelDrop", textScreenDrop)
util.AddNetworkString("textscreens_update")
util.AddNetworkString("textscreens_download")
function ENT:SetLine(line, text, color, size, font, rainbow)
if not text then return end
if string.sub(text, 1, 1) == "#" then
text = string.sub(text, 2)
end
if string.len(text) > 180 then
text = string.sub(text, 1, 180) .. "..."
end
size = math.Clamp(size, 1, 100)
font = textscreenFonts[font] ~= nil and font or 1
rainbow = rainbow or 0
self.lines = self.lines or {}
self.lines[tonumber(line)] = {
["text"] = text,
["color"] = color,
["size"] = size,
["font"] = font,
["rainbow"] = rainbow
}
end
local function canSendUpdate(ply, ent)
local updates = ply.TextScreenUpdates
if not updates then
updates = {}
ply.TextScreenUpdates = updates
end
local now = CurTime()
local lastSent = updates[ent] or 0
if lastSent > (now - 1) then
return false
end
updates[ent] = now
return true
end
function ENT:OnRemove()
local plys = player.GetAll()
local plyCount = #plys
for i = 1, plyCount do
local updates = plys[i].TextScreenUpdates
if updates then updates[self] = nil end
end
end
net.Receive("textscreens_download", function(len, ply)
if not IsValid(ply) then return end
local ent = net.ReadEntity()
if not IsValid( ent ) then return end
if ent:GetClass() ~= "sammyservers_textscreen" then return end
if not canSendUpdate(ply, ent) then return end
ent:SendLines(ply)
end)
function ENT:SendLines(ply)
if not self.lines then self.lines = {} end
net.Start("textscreens_update")
net.WriteEntity(self)
net.WriteTable(self.lines)
if ply then
net.Send(ply)
else
net.Broadcast()
end
end
function ENT:Broadcast()
self:SendLines(nil)
end

View File

@@ -0,0 +1,19 @@
ENT.Type = "anim"
ENT.Base = "base_entity"
ENT.PrintName = "SammyServers Textscreen"
ENT.Author = "SammyServers"
ENT.Spawnable = false
ENT.AdminSpawnable = false
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
function ENT:SetupDataTables()
self:NetworkVar("Bool", 0, "IsPersisted")
end
local function textScreenCanTool(ply, trace, tool)
-- only allow textscreen, remover, and permaprops tool
if IsValid(trace.Entity) and trace.Entity:GetClass() == "sammyservers_textscreen" and tool ~= "textscreen" and tool ~= "remover" and tool ~= "permaprops" then
return false
end
end
hook.Add("CanTool", "3D2DTextScreensPreventTools", textScreenCanTool)

View File

@@ -0,0 +1,154 @@
textscreenFonts = {}
local function addFont(font, t)
if CLIENT then
t.size = 100
surface.CreateFont(font, t)
t.size = 50
surface.CreateFont(font .. "_MENU", t)
end
table.insert(textscreenFonts, font)
end
--[[
---------------------------------------------------------------------------
Custom fonts - requires server restart to take affect -- "Screens_" will be removed from the font name in spawnmenu
---------------------------------------------------------------------------
--]]
-- Default textscreens font
addFont("Coolvetica outlined", {
font = "coolvetica",
weight = 400,
antialias = false,
outline = true
})
addFont("Coolvetica", {
font = "coolvetica",
weight = 400,
antialias = false,
outline = false
})
-- Trebuchet
addFont("Screens_Trebuchet outlined", {
font = "Trebuchet MS",
weight = 400,
antialias = false,
outline = true
})
addFont("Screens_Trebuchet", {
font = "Trebuchet MS",
weight = 400,
antialias = false,
outline = false
})
-- Arial
addFont("Screens_Arial outlined", {
font = "Arial",
weight = 600,
antialias = false,
outline = true
})
addFont("Screens_Arial", {
font = "Arial",
weight = 600,
antialias = false,
outline = false
})
-- Roboto Bk
addFont("Screens_Roboto outlined", {
font = "Roboto Bk",
weight = 400,
antialias = false,
outline = true
})
addFont("Screens_Roboto", {
font = "Roboto Bk",
weight = 400,
antialias = false,
outline = false
})
-- Helvetica
addFont("Screens_Helvetica outlined", {
font = "Helvetica",
weight = 400,
antialias = false,
outline = true
})
addFont("Screens_Helvetica", {
font = "Helvetica",
weight = 400,
antialias = false,
outline = false
})
-- akbar
addFont("Screens_Akbar outlined", {
font = "akbar",
weight = 400,
antialias = false,
outline = true
})
addFont("Screens_Akbar", {
font = "akbar",
weight = 400,
antialias = false,
outline = false
})
-- csd
addFont("Screens_csd outlined", {
font = "csd",
weight = 400,
antialias = false,
outline = true
})
addFont("Screens_csd", {
font = "csd",
weight = 400,
antialias = false,
outline = false
})
if CLIENT then
local function addFonts(path)
local files, folders = file.Find("resource/fonts/" .. path .. "*", "MOD")
for k, v in ipairs(files) do
if string.GetExtensionFromFilename(v) == "ttf" then
local font = string.StripExtension(v)
if table.HasValue(textscreenFonts, "Screens_" .. font) then continue end
print("-- " .. font .. "\n" .. [[
addFont("Screens_ ]] .. font .. [[", {
font = font,
weight = 400,
antialias = false,
outline = true
})
]])
end
end
for k, v in ipairs(folders) do
addFonts(path .. v .. "/")
end
end
concommand.Add("get_fonts", function(ply)
addFonts("")
end)
end

View File

@@ -0,0 +1,413 @@
TOOL.Category = "Construction"
TOOL.Name = "#tool.textscreen.name"
TOOL.Command = nil
TOOL.ConfigName = ""
local textBox = {}
local lineLabels = {}
local labels = {}
local sliders = {}
local rainbowCheckboxes = {}
local textscreenFonts = textscreenFonts
local rainbow_enabled = cvars.Number("ss_enable_rainbow", 1)
local max_characters = cvars.Number("ss_max_characters", 0)
for i = 1, 5 do
TOOL.ClientConVar["text" .. i] = ""
TOOL.ClientConVar["size" .. i] = 20
TOOL.ClientConVar["r" .. i] = 255
TOOL.ClientConVar["g" .. i] = 255
TOOL.ClientConVar["b" .. i] = 255
TOOL.ClientConVar["a" .. i] = 255
TOOL.ClientConVar["font" .. i] = 1
TOOL.ClientConVar["rainbow" .. i] = 0
end
cleanup.Register("textscreens")
if (CLIENT) then
TOOL.Information = {
{ name = "left" },
{ name = "right" },
{ name = "reload" },
}
-- Add default english language strings here, in case no localisation exists
language.Add("tool.textscreen.name", "3D2D Textscreen")
language.Add("tool.textscreen.desc", "Create a textscreen with multiple lines, font colours and sizes.")
language.Add("tool.textscreen.left", "Spawn a textscreen.") -- Does not work with capital T in tool. Same with right and reload.
language.Add("tool.textscreen.right", "Update textscreen with settings.")
language.Add("tool.textscreen.reload", "Copy textscreen.")
language.Add("Undone.textscreens", "Undone textscreen")
language.Add("Undone_textscreens", "Undone textscreen")
language.Add("Cleanup.textscreens", "Textscreens")
language.Add("Cleanup_textscreens", "Textscreens")
language.Add("Cleaned.textscreens", "Cleaned up all textscreens")
language.Add("Cleaned_textscreens", "Cleaned up all textscreens")
language.Add("SBoxLimit.textscreens", "You've hit the textscreen limit!")
language.Add("SBoxLimit_textscreens", "You've hit the textscreen limit!")
end
function TOOL:LeftClick(tr)
if (tr.Entity:GetClass() == "player") then return false end
if (CLIENT) then return true end
local ply = self:GetOwner()
if hook.Run("PlayerSpawnTextscreen", ply, tr) == false then return false end
if not (self:GetWeapon():CheckLimit("textscreens")) then return false end
-- ensure at least 1 line of the textscreen has text before creating entity
local hasText = false
for i = 1, 5 do
local text = self:GetClientInfo("text" .. i) or ""
if text ~= "" then
hasText = true
end
end
if not hasText then return false end
local textScreen = ents.Create("sammyservers_textscreen")
textScreen:SetPos(tr.HitPos)
local angle = tr.HitNormal:Angle()
angle:RotateAroundAxis(tr.HitNormal:Angle():Right(), -90)
angle:RotateAroundAxis(tr.HitNormal:Angle():Forward(), 90)
textScreen:SetAngles(angle)
textScreen:Spawn()
textScreen:Activate()
undo.Create("textscreens")
undo.AddEntity(textScreen)
undo.SetPlayer(ply)
undo.Finish()
ply:AddCount("textscreens", textScreen)
ply:AddCleanup("textscreens", textScreen)
for i = 1, 5 do
local txt = self:GetClientInfo("text" .. i) or ""
textScreen:SetLine(
i, -- Line
max_characters ~= 0 and string.Left(txt, max_characters) or txt, -- text
Color( -- Color
tonumber(self:GetClientInfo("r" .. i)) or 255,
tonumber(self:GetClientInfo("g" .. i)) or 255,
tonumber(self:GetClientInfo("b" .. i)) or 255,
tonumber(self:GetClientInfo("a" .. i)) or 255
),
tonumber(self:GetClientInfo("size" .. i)) or 20,
-- font
tonumber(self:GetClientInfo("font" .. i)) or 1,
rainbow_enabled == 1 and tonumber(self:GetClientInfo("rainbow" .. i)) or 0
)
end
return true
end
function TOOL:RightClick(tr)
if (tr.Entity:GetClass() == "player") then return false end
if (CLIENT) then return true end
local traceEnt = tr.Entity
if (IsValid(traceEnt) and traceEnt:GetClass() == "sammyservers_textscreen") then
for i = 1, 5 do
local txt = tostring(self:GetClientInfo("text" .. i))
traceEnt:SetLine(
i, -- Line
max_characters ~= 0 and string.Left(txt, max_characters) or txt, -- text
Color( -- Color
tonumber(self:GetClientInfo("r" .. i)) or 255,
tonumber(self:GetClientInfo("g" .. i)) or 255,
tonumber(self:GetClientInfo("b" .. i)) or 255,
tonumber(self:GetClientInfo("a" .. i)) or 255
),
tonumber(self:GetClientInfo("size" .. i)) or 20,
-- font
tonumber(self:GetClientInfo("font" .. i)) or 1,
rainbow_enabled and tonumber(self:GetClientInfo("rainbow" .. i)) or 0
)
end
traceEnt:Broadcast()
return true
end
end
function TOOL:Reload(tr)
if (SERVER) then return true end
local traceEnt = tr.Entity
if (not isentity(traceEnt) or traceEnt:GetClass() ~= "sammyservers_textscreen") then return false end
for i = 1, 5 do
local linedata = traceEnt.lines[i]
RunConsoleCommand("textscreen_r" .. i, linedata.color.r)
RunConsoleCommand("textscreen_g" .. i, linedata.color.g)
RunConsoleCommand("textscreen_b" .. i, linedata.color.b)
RunConsoleCommand("textscreen_a" .. i, linedata.color.a)
RunConsoleCommand("textscreen_size" .. i, linedata.size)
RunConsoleCommand("textscreen_text" .. i, linedata.text)
RunConsoleCommand("textscreen_font" .. i, linedata.font)
RunConsoleCommand("textscreen_rainbow" .. i, linedata.rainbow)
end
return true
end
local conVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel(CPanel)
local logo = vgui.Create("DImage", CPanel)
logo:SetSize(267, 134)
logo:SetImage("textscreens/logo.png")
CPanel:AddItem(logo)
CPanel:AddControl("Header", {
Text = "#tool.textscreen.name",
Description = "#tool.textscreen.desc"
})
local function TrimFontName(fontnum)
return string.Left(textscreenFonts[fontnum], 8) == "Screens_" and string.TrimLeft(textscreenFonts[fontnum], "Screens_") or textscreenFonts[fontnum]
end
local changefont
local fontnum = textscreenFonts[GetConVar("textscreen_font1"):GetInt()] ~= nil and GetConVar("textscreen_font1"):GetInt() or 1
cvars.AddChangeCallback("textscreen_font1", function(convar_name, value_old, value_new)
fontnum = textscreenFonts[tonumber(value_new)] ~= nil and tonumber(value_new) or 1
local font = TrimFontName(fontnum)
changefont:SetText("Change font (" .. font .. ")")
end)
local function ResetFont(lines, text)
if #lines >= 5 then
fontnum = 1
for i = 1, 5 do
RunConsoleCommand("textscreen_font" .. i, 1)
end
end
for k, i in pairs(lines) do
if text then
RunConsoleCommand("textscreen_text" .. i, "")
labels[i]:SetText("")
end
labels[i]:SetFont(textscreenFonts[fontnum] .. "_MENU")
end
end
resetall = vgui.Create("DButton", resetbuttons)
resetall:SetSize(100, 25)
resetall:SetText("Reset all")
resetall.DoClick = function()
local menu = DermaMenu()
menu:AddOption("Reset colors", function()
for i = 1, 5 do
RunConsoleCommand("textscreen_r" .. i, 255)
RunConsoleCommand("textscreen_g" .. i, 255)
RunConsoleCommand("textscreen_b" .. i, 255)
RunConsoleCommand("textscreen_a" .. i, 255)
end
end)
menu:AddOption("Reset sizes", function()
for i = 1, 5 do
RunConsoleCommand("textscreen_size" .. i, 20)
sliders[i]:SetValue(20)
labels[i]:SetFont(textscreenFonts[fontnum] .. "_MENU")
end
end)
menu:AddOption("Reset textboxes", function()
for i = 1, 5 do
RunConsoleCommand("textscreen_text" .. i, "")
textBox[i]:SetValue("")
end
end)
menu:AddOption("Reset fonts", function()
ResetFont({1, 2, 3, 4, 5}, false)
end)
if rainbow_enabled == 1 then
menu:AddOption("Reset rainbow", function()
for i = 1, 5 do
rainbowCheckboxes[i]:SetValue(0)
end
end)
end
menu:AddOption("Reset everything", function()
for i = 1, 5 do
RunConsoleCommand("textscreen_r" .. i, 255)
RunConsoleCommand("textscreen_g" .. i, 255)
RunConsoleCommand("textscreen_b" .. i, 255)
RunConsoleCommand("textscreen_a" .. i, 255)
RunConsoleCommand("textscreen_size" .. i, 20)
sliders[i]:SetValue(20)
RunConsoleCommand("textscreen_text" .. i, "")
RunConsoleCommand("textscreen_font" .. i, 1)
textBox[i]:SetValue("")
if rainbow_enabled == 1 then
rainbowCheckboxes[i]:SetValue(0)
end
end
ResetFont({1, 2, 3, 4, 5}, true)
end)
menu:Open()
end
CPanel:AddItem(resetall)
resetline = vgui.Create("DButton")
resetline:SetSize(100, 25)
resetline:SetText("Reset line")
resetline.DoClick = function()
local menu = DermaMenu()
for i = 1, 5 do
menu:AddOption("Reset line " .. i, function()
RunConsoleCommand("textscreen_r" .. i, 255)
RunConsoleCommand("textscreen_g" .. i, 255)
RunConsoleCommand("textscreen_b" .. i, 255)
RunConsoleCommand("textscreen_a" .. i, 255)
RunConsoleCommand("textscreen_size" .. i, 20)
sliders[i]:SetValue(20)
RunConsoleCommand("textscreen_text" .. i, "")
textBox[i]:SetValue("")
ResetFont({i}, true)
end)
end
menu:AddOption("Reset all lines", function()
for i = 1, 5 do
RunConsoleCommand("textscreen_r" .. i, 255)
RunConsoleCommand("textscreen_g" .. i, 255)
RunConsoleCommand("textscreen_b" .. i, 255)
RunConsoleCommand("textscreen_a" .. i, 255)
RunConsoleCommand("textscreen_size" .. i, 20)
sliders[i]:SetValue(20)
RunConsoleCommand("textscreen_text" .. i, "")
RunConsoleCommand("textscreen_font" .. i, 1)
textBox[i]:SetValue("")
end
ResetFont({1, 2, 3, 4, 5}, true)
end)
menu:Open()
end
CPanel:AddItem(resetline)
-- Change font
changefont = vgui.Create("DButton")
changefont:SetSize(100, 25)
changefont:SetText("Change font (" .. TrimFontName(fontnum) .. ")" )
changefont.DoClick = function()
local menu = DermaMenu()
for i = 1, #textscreenFonts do
local font = TrimFontName(i)
menu:AddOption(font, function()
fontnum = i
for o = 1, 5 do
RunConsoleCommand("textscreen_font" .. o, i)
labels[o]:SetFont(textscreenFonts[fontnum] .. "_MENU")
end
changefont:SetText("Change font (" .. font .. ")")
end)
end
menu:Open()
end
CPanel:AddItem(changefont)
CPanel:AddControl("ComboBox", {
MenuButton = 1,
Folder = "textscreen",
Options = {
["#preset.default"] = conVarsDefault
},
CVars = table.GetKeys(conVarsDefault)
})
for i = 1, 5 do
lineLabels[i] = CPanel:AddControl("Label", {
Text = "Line " .. i,
Description = "Line " .. i
})
lineLabels[i]:SetFont("Default")
CPanel:AddControl("Color", {
Label = "Line " .. i .. " font color",
Red = "textscreen_r" .. i,
Green = "textscreen_g" .. i,
Blue = "textscreen_b" .. i,
Alpha = "textscreen_a" .. i,
ShowHSV = 1,
ShowRGB = 1,
Multiplier = 255
})
if rainbow_enabled == 1 then
rainbowCheckboxes[i] = vgui.Create("DCheckBoxLabel")
rainbowCheckboxes[i]:SetText("Rainbow Text")
rainbowCheckboxes[i]:SetTextColor(Color(0,0,0,255))
rainbowCheckboxes[i]:SetConVar("textscreen_rainbow" .. i)
rainbowCheckboxes[i]:SetTooltip("Enable for rainbow text")
rainbowCheckboxes[i]:SetValue(GetConVar("textscreen_rainbow" .. i):GetInt())
CPanel:AddItem(rainbowCheckboxes[i])
end
sliders[i] = vgui.Create("DNumSlider")
sliders[i]:SetText("Font size")
sliders[i]:SetMinMax(20, 100)
sliders[i]:SetDecimals(0)
sliders[i]:SetValue(GetConVar("textscreen_size" .. i))
sliders[i]:SetConVar("textscreen_size" .. i)
CPanel:AddItem(sliders[i])
textBox[i] = vgui.Create("DTextEntry")
textBox[i]:SetUpdateOnType(true)
textBox[i]:SetEnterAllowed(true)
textBox[i]:SetConVar("textscreen_text" .. i)
textBox[i]:SetValue(GetConVar("textscreen_text" .. i):GetString())
textBox[i].OnTextChanged = function()
labels[i]:SetText(textBox[i]:GetValue())
end
if max_characters ~= 0 then
textBox[i].AllowInput = function()
if string.len(textBox[i]:GetValue()) >= max_characters then return true end
end
end
CPanel:AddItem(textBox[i])
labels[i] = CPanel:AddControl("Label", {
Text = #GetConVar("textscreen_text" .. i):GetString() >= 1 and GetConVar("textscreen_text" .. i):GetString() or "Line " .. i,
Description = "Line " .. i
})
labels[i]:SetFont(textscreenFonts[fontnum] .. "_MENU")
labels[i]:SetAutoStretchVertical(true)
labels[i]:SetDisabled(true)
labels[i]:SetHeight(50)
labels[i].Think = function()
labels[i]:SetColor(
Color(
GetConVar("textscreen_r" .. i):GetInt(),
GetConVar("textscreen_g" .. i):GetInt(),
GetConVar("textscreen_b" .. i):GetInt(),
GetConVar("textscreen_a" .. i):GetInt()
)
)
end
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,14 @@
tool.textscreen.name=3D2D Textscreen
tool.textscreen.desc=Create a textscreen with multiple lines, font colours and sizes.
tool.textscreen.left=Spawn a textscreen.
tool.textscreen.right=Update textscreen with settings.
tool.textscreen.reload=Copy textscreen.
Undone.textscreens=Undone textscreen
Undone_textscreens=Undone textscreen
Cleanup.textscreens=Textscreens
Cleanup_textscreens=Textscreens
Cleaned.textscreens=Cleaned up all textscreens
Cleaned_textscreens=Cleaned up all textscreens
SBoxLimit.textscreens=You've hit the textscreen limit!
SBoxLimit_textscreens=You've hit the textscreen limit!

View File

@@ -0,0 +1,14 @@
tool.textscreen.name=Pantalla de texto 3D2D
tool.textscreen.desc=Crear a Pantalla de texto con múltiples líneas, colores de fuente y tamaños.
tool.textscreen.left=Aparecer a Pantalla de texto.
tool.textscreen.right=Actualizar Pantalla de texto with settings.
tool.textscreen.reload=Dupdo Pantalla de texto.
Undone.textscreens=Deshecho Pantalla de texto
Undone_textscreens=Deshecho Pantalla de texto
Cleanup.textscreens=Pantalla de texto
Cleanup_textscreens=Pantalla de texto
Cleaned.textscreens=Limpió todas las pantallas de texto
Cleaned_textscreens=Limpió todas las pantallas de texto
SBoxLimit.textscreens=¡Has alcanzado el límite de la pantalla de texto!
SBoxLimit_textscreens=¡Has alcanzado el límite de la pantalla de texto!

View File

@@ -0,0 +1,14 @@
tool.textscreen.name=3D2D Textscreen
tool.textscreen.desc=Utwórz ekran tekstowy z wieloma liniami, kolorami czcionek i rozmiarami.
tool.textscreen.left=Utwórz ekran tekstowy.
tool.textscreen.right=Uaktualnij ekran tekstowy z wybranymi ustawieniami.
tool.textscreen.reload=Skopiuj ekran tekstowy.
Undone.textscreens=Cofnij utworzenie ekranu tekstowego
Undone_textscreens=Cofnij utworzenie ekranu tekstowego
Cleanup.textscreens=Ekrany tekstowe
Cleanup_textscreens=Ekrany tekstowe
Cleaned.textscreens=Usunięto wszystkie ekrany tekstowe
Cleaned_textscreens=Usunięto wszystkie ekrany tekstowe
SBoxLimit.textscreens=Przekroczyłeś limit ekranów tekstowych!
SBoxLimit_textscreens=Przekroczyłeś limit ekranów tekstowych!

View File

@@ -0,0 +1,14 @@
tool.textscreen.name=3D2D \u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d
tool.textscreen.desc=\u0421\u043e\u0437\u0434\u0430\u0451\u0442\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d\u0020\u0441\u0020\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438\u0020\u043b\u0438\u043d\u0438\u044f\u043c\u0438\u002c\u0020\u0446\u0432\u0435\u0442\u0430\u043c\u0438\u0020\u0438\u0020\u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438\u0020\u0448\u0440\u0438\u0444\u0442\u0430\u002e
tool.textscreen.left=\u0421\u043e\u0437\u0434\u0430\u0442\u044c\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d\u002e
tool.textscreen.right=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d\u0020\u0438\u0020\u0435\u0433\u043e\u0020\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u002e
tool.textscreen.reload=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d\u002e
Undone.textscreens=\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d\u0020\u043e\u0442\u043c\u0435\u043d\u0451\u043d
Undone_textscreens=\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439\u0020\u044d\u043a\u0440\u0430\u043d\u0020\u043e\u0442\u043c\u0435\u043d\u0451\u043d
Cleanup.textscreens=\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435\u0020\u044d\u043a\u0440\u0430\u043d\u044b
Cleanup_textscreens=\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435\u0020\u044d\u043a\u0440\u0430\u043d\u044b
Cleaned.textscreens=\u0423\u0431\u0440\u0430\u043d\u044b\u0020\u0432\u0441\u0435\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435\u0020\u044d\u043a\u0440\u0430\u043d\u044b
Cleaned_textscreens=\u0423\u0431\u0440\u0430\u043d\u044b\u0020\u0432\u0441\u0435\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435\u0020\u044d\u043a\u0440\u0430\u043d\u044b
SBoxLimit.textscreens=\u0412\u044b\u0020\u0434\u043e\u0441\u0442\u0438\u0433\u043b\u0438\u0020\u043b\u0438\u043c\u0438\u0442\u0430\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445\u0020\u044d\u043a\u0440\u0430\u043d\u043e\u0432\u0021
SBoxLimit_textscreens=\u0412\u044b\u0020\u0434\u043e\u0441\u0442\u0438\u0433\u043b\u0438\u0020\u043b\u0438\u043c\u0438\u0442\u0430\u0020\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445\u0020\u044d\u043a\u0440\u0430\u043d\u043e\u0432\u0021

View File

@@ -0,0 +1,14 @@
tool.textscreen.name=3D2D Metin Ekranı
tool.textscreen.desc=Birden çok satır, yazı tipi rengi ve boyutu olan bir metin ekranı oluşturun.
tool.textscreen.left=Bir metin ekranı oluştur.
tool.textscreen.right=Metin ekranını ayarlarla güncelleyin.
tool.textscreen.reload=Metin ekranını kopyala.
Undone.textscreens=Bitmemiş metin ekranı
Undone_textscreens=Bitmemiş metin ekranı
Cleanup.textscreens=Metin Ekranları
Cleanup_textscreens=Metin Ekranları
Cleaned.textscreens=Tüm metin ekranlarını temizle
Cleaned_textscreens=Tüm metin ekranlarını temizle
SBoxLimit.textscreens=Metin ekranı sınırına ulaştınız!
SBoxLimit_textscreens=Metin ekranı sınırına ulaştınız!

View File

@@ -0,0 +1,156 @@
-- libNyx by MaryBlackfild
-- JOIN DISCORD: https://discord.gg/rUEEz4mfXw
-- lua/autorun/libnyx_loader.lua
libNyx = libNyx or {}
local function read_local_version()
local p1,p2 = "VERSION","libnyx/VERSION"
local v = file.Exists(p1,"GAME") and file.Read(p1,"GAME") or file.Exists(p1,"LUA") and file.Read(p1,"LUA") or file.Exists(p2,"LUA") and file.Read(p2,"LUA") or file.Exists(p2,"GAME") and file.Read(p2,"GAME") or ""
v = tostring(v or ""):gsub("[\r\n]","")
if v == "" then v = "0.0.0" end
return v
end
libNyx.Version = libNyx.Version or read_local_version()
local RAW_VERSION_URL = "https://raw.githubusercontent.com/maryblackfild/libnyx/main/VERSION"
local RAW_LOADER_URL = "https://raw.githubusercontent.com/maryblackfild/libnyx/main/lua/autorun/libnyx_loader.lua"
local HOMEPAGE = "https://github.com/maryblackfild/libnyx"
local function norm(v) v = tostring(v or "") return (v:sub(1,1)=="v") and v:sub(2) or v end
local function say(kind,msg)
local h = Color(120,200,255)
local c = kind=="ok" and Color(120,220,120) or kind=="warn" and Color(255,220,120) or kind=="err" and Color(255,120,120) or Color(200,200,210)
MsgC(h,"[libNyx] ",c,msg,"\n")
end
local function do_update_check()
say("info","Checking for updates…")
http.Fetch(RAW_VERSION_URL, function(body)
local remote = tostring(body or ""):gsub("[\r\n]","")
if remote=="" then return say("err","Update check failed.") end
local a,b = norm(libNyx.Version), norm(remote)
if a==b then
say("ok",("Up-to-date ✓ (latest: %s)"):format(remote))
else
say("warn",("Update available ✱ installed %s → latest %s"):format(libNyx.Version, remote))
say("info","Get it: "..HOMEPAGE)
end
end, function()
http.Fetch(RAW_LOADER_URL, function(body)
local remote = tostring(body or ""):match('libNyx%.Version%s*=%s*["\']([%w%._%-]+)["\']')
if not remote or remote=="" then return say("err","Update check failed.") end
local a,b = norm(libNyx.Version), norm(remote)
if a==b then
say("ok",("Up-to-date ✓ (latest: %s)"):format(remote))
else
say("warn",("Update available ✱ installed %s → latest %s"):format(libNyx.Version, remote))
say("info","Get it: "..HOMEPAGE)
end
end, function() say("err","Update check failed.") end)
end)
end
if SERVER then
AddCSLuaFile("libnyx/lib/rndx.lua")
AddCSLuaFile("libnyx/lib/libnyx_components.lua")
AddCSLuaFile("libnyx/lib/libnyx_liquidglass.lua")
AddCSLuaFile("libnyx/lib/libnyx_maindemo.lua")
timer.Simple(0, function() say("info",("Loaded v%s (server)"):format(libNyx.Version)) do_update_check() end)
return
end
local function hasFont(f)
local n="__nyx_font_test"
surface.CreateFont(n,{font=f,size=16,weight=500,extended=true})
surface.SetFont(n)
local w,h=surface.GetTextSize("Aa")
return (w or 0)>0 and (h or 0)>0
end
local function precreate_alias_fonts()
local base = hasFont("Manrope") and "Manrope" or "Tahoma"
for sz=10,200 do
local name=("libNyx.%s.%d"):format(base, sz)
surface.CreateFont(name,{font=base,size=sz,weight=(sz>=28) and 500 or 400,extended=true})
end
for sz=10,60 do
local name=("libNyx.UI.%d"):format(sz)
surface.CreateFont(name,{font=base,size=sz,weight=(sz>=28) and 500 or 400,extended=true})
end
end
local boot = {}
local function include_all_once()
if not boot.rndx then
libNyx.rndx = include("libnyx/lib/rndx.lua")
_G.RNDX = _G.RNDX or libNyx.rndx
boot.rndx = true
end
if not boot.components then
include("libnyx/lib/libnyx_components.lua")
boot.components = true
end
if not boot.demo then
include("libnyx/lib/libnyx_maindemo.lua")
boot.demo = true
end
if not boot.liquid then
include("libnyx/lib/libnyx_liquidglass.lua")
boot.liquid = true
end
end
local function ready_gate_try()
local UI = _G.libNyx and _G.libNyx.UI
local ok = UI and UI.Draw and UI.Components and UI.Components.CreateSlider and RNDX
if not ok then return false end
return true
end
local function run_after_include()
precreate_alias_fonts()
if _G.libNyx and _G.libNyx.UI and _G.libNyx.UI.InstallGlobalMenuSkin then _G.libNyx.UI.InstallGlobalMenuSkin() end
if _G.libNyx and _G.libNyx.UI and _G.libNyx.UI.InstallGlobalNotificationSkin then _G.libNyx.UI.InstallGlobalNotificationSkin() end
end
local trying=0
local function wait_until_ready()
trying = trying + 1
if ready_gate_try() then
libNyx.Ready = true
return
end
if trying < 240 then timer.Simple(0, wait_until_ready) else say("warn","Init gate timed out; some UI may be unavailable.") end
end
local function client_bootstrap()
include_all_once()
run_after_include()
wait_until_ready()
end
local function gamemode_init_bridge()
if libNyx.__booted then return end
libNyx.__booted = true
client_bootstrap()
end
hook.Add("OnGamemodeLoaded","libNyx.Loader.GMInit",gamemode_init_bridge)
hook.Add("Initialize","libNyx.Loader.Init",gamemode_init_bridge)
hook.Add("InitPostEntity","libNyx.Loader.InitPostEntity",function() if not libNyx.Ready then client_bootstrap() end end)
hook.Add("OnReloaded","libNyx.Loader.Reload",function()
boot = {}
libNyx.Ready = false
client_bootstrap()
end)
timer.Simple(0, function()
if not libNyx.__booted then gamemode_init_bridge() end
say("info",("Loaded v%s (client)"):format(libNyx.Version))
do_update_check()
end)
-- libNyx by MaryBlackfild
-- JOIN DISCORD: https://discord.gg/rUEEz4mfXw

View File

@@ -0,0 +1 @@
0.8.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
-- libNyx and LiquidGlass shader by MaryBlackfild
-- JOIN DISCORD: https://discord.gg/rUEEz4mfXw
if SERVER then AddCSLuaFile() return end
local RNDX = include("libnyx/lib/rndx.lua")
surface.CreateFont("libNyx.Manrope.Liquid",{font="Manrope",size=30,weight=800,antialias=true,extended=true})
--surface.CreateFont("libNyx.UI.18",{font="Manrope",size=18,weight=700,antialias=true,extended=true})
--surface.CreateFont("libNyx.UI.16",{font="Manrope",size=16,weight=600,antialias=true,extended=true})
--surface.CreateFont("libNyx.UI.14",{font="Manrope",size=14,weight=600,antialias=true,extended=true})
CreateClientConVar("libnyx_liquid_size","300",true,false)
local Nyx = libNyx and libNyx.UI
local Style = Nyx and Nyx.Style
local function s(n) return (Nyx and Nyx.Scale and Nyx.Scale(n)) or n end
local function f(sz) return (Nyx and Nyx.Font and Nyx.Font(s(sz))) or "DermaDefault" end
local function clp(x,a,b) if x<a then return a elseif x>b then return b else return x end end
local function rstep(x,st) if not st or st<=0 then return x end return math.Round(x/st)*st end
local function sdec(st) local q=tostring(st or "") local p=q:find("%.") return p and (#q-p) or 0 end
local function dup(t) local r={} for k,v in pairs(t) do r[k]=v end return r end
local function fmt(v)
if type(v)~="number" then return tostring(v or 0) end
local out = string.format("%.6f", v):gsub("0+$",""):gsub("%.$","")
return (out == "" and "0") or out
end
local DEF = {
size = tonumber(GetConVar("libnyx_liquid_size"):GetString()) or 300,
rad = 32,
strength = 0.012,
speed = 0,
sat = 1.06,
tr = 255, tg = 255, tb = 255,
tints = 0.06,
blur_all = 0.10,
blur_rad = 0,
edge = 2.0,
shimmer = 25.2,
grain = 0.01,
alpha = 0.95,
shape = RNDX.SHAPE_IOS,
shadow_enabled = true,
shadow_spread = 40,
shadow_intensity = 56
}
local function mk() return dup(DEF) end
local function open()
if not Nyx then return end
if IsValid(libNyx.LiquidGlassUI) then libNyx.LiquidGlassUI:Remove() return end
local st = mk()
local ui = { sliders = {} }
local rt = vgui.Create("EditablePanel")
rt:SetSize(ScrW(),ScrH())
rt:MakePopup()
gui.EnableScreenClicker(true)
libNyx.LiquidGlassUI = rt
Nyx.AutoNoBG(rt)
Nyx.InstallGlobalScroll(rt,{step=s(90),speed=18,fadeHold=0.9,width=s(12)})
function rt:OnRemove() gui.EnableScreenClicker(false) end
function rt:OnKeyCodePressed(k) if k==KEY_ESCAPE then self:Remove() end end
local pad = s(24)
local lw = math.min(s(380), math.max(s(300), math.floor(ScrW()*0.26)))
local nav = vgui.Create("DPanel", rt)
nav:SetPos(pad, pad)
nav:SetSize(lw, ScrH() - pad*2)
Nyx.AutoNoBG(nav)
nav.Paint = function(p,w,h)
Nyx.Draw.Glass(0,0,w,h,{
radius=s(18),
fill=Style and Style.bgColor or Color(10,10,14,150),
stroke=true,
strokeColor=Style and Style.glassStroke or Color(255,255,255,22),
blurIntensity=1.1
})
draw.SimpleText("libNyx · Liquid Glass", f(22), s(18), s(16), Style and Style.textColor or color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
local bd = vgui.Create("DScrollPanel", nav)
bd:Dock(FILL)
bd:DockMargin(s(12), s(50), s(12), s(12))
Nyx.AutoNoBG(bd)
Nyx.SmoothScroll.ApplyToScrollPanel(bd,{step=s(90),speed=18,fadeHold=0.9,width=s(12)})
local vb = bd:GetVBar()
vb:SetWide(0)
vb.Paint = function() end
if vb.btnUp then vb.btnUp:SetVisible(false) end
if vb.btnDown then vb.btnDown:SetVisible(false) end
if vb.btnGrip then vb.btnGrip:SetVisible(false) end
local function title(t)
local pnl = vgui.Create("DPanel", bd)
pnl:Dock(TOP)
pnl:DockMargin(0, s(10), 0, s(6))
pnl:SetTall(s(30))
Nyx.AutoNoBG(pnl)
pnl.Paint = function(_,w,h)
draw.SimpleText(t, f(18), 0, h/2, Style and Style.textColor or color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
end
local function row(h)
local r = vgui.Create("DPanel", bd)
r:Dock(TOP)
r:DockMargin(0, s(6), 0, 0)
r:SetTall(h or s(44))
Nyx.AutoNoBG(r)
r.Paint = function(_,w,h)
Nyx.Draw.Panel(0,0,w,h,{radius=s(12),color=Style and Style.panelColor or Color(20,22,30,130),glass=true,stroke=true})
end
return r
end
local clampBox = function() end
local function slider(lbl,key,min,max,step,tint)
local r = row(s(48))
local L = vgui.Create("DLabel", r)
L:SetFont(f(18))
L:SetTextColor(Style and Style.textColor or color_white)
L:SetText(lbl)
L:SizeToContents()
L:SetPos(s(12), s(12))
local sl = Nyx.Components.CreateSlider(r,{min=min,max=max,decimals=sdec(step),value=st[key],tint=tint or (Style and Style.accentColor)})
sl:Dock(FILL)
sl:DockMargin(s(140), 0, s(12), 0)
function sl:OnValueChanged(v)
local val = clp(rstep(v,step),min,max)
st[key] = val
if key=="size" then
RunConsoleCommand("libnyx_liquid_size", tostring(math.floor(val)))
clampBox()
end
end
ui.sliders[key] = sl
return sl
end
local function drop(lbl,choices,onPick)
local r = row(s(48))
local L = vgui.Create("DLabel", r)
L:SetFont(f(18))
L:SetTextColor(Style and Style.textColor or color_white)
L:SetText(lbl)
L:SizeToContents()
L:SetPos(s(12), s(12))
local dd = Nyx.Components.CreateDropdown(r,{choices=choices,placeholder="",onSelect=onPick})
dd:Dock(RIGHT)
dd:SetWide(s(150))
dd:DockMargin(0, s(6), s(8), s(6))
return dd
end
local function toggle(lbl,init,onChange)
local r = row(s(44))
local sw = Nyx.Components.CreateCheckbox(r,{variant="switch",checked=init,label=lbl})
sw:Dock(LEFT)
sw:DockMargin(s(10), s(6), 0, s(6))
sw:SetOnChange(function(v) if onChange then onChange(v) end end)
return sw
end
title("Layout")
slider("Size","size",220,520,1)
ui.sliders.rad = slider("Corner","rad",0,64,1)
local shapeDD = drop("Shape",{
{label="iOS"},
{label="Figma"},
{label="Circle"},
},function(lbl)
if lbl=="iOS" then st.shape=RNDX.SHAPE_IOS
elseif lbl=="Figma" then st.shape=RNDX.SHAPE_FIGMA
else st.shape=RNDX.SHAPE_CIRCLE end
clampBox()
end)
title("Visuals")
slider("Strength","strength",0,0.06,0.001)
slider("Speed","speed",0,4,0.1)
slider("Saturation","sat",0.5,1.6,0.01)
slider("Tint R","tr",0,255,1,Color(255,110,110))
slider("Tint G","tg",0,255,1,Color(110,255,110))
slider("Tint B","tb",0,255,1,Color(110,110,255))
slider("Tint Amt","tints",0,0.35,0.005)
title("Blur & Edge")
slider("Glass Blur","blur_all",0,0.5,0.01)
slider("Blur Rad","blur_rad",0,4,0.1)
slider("Edge Px","edge",0,6,0.1)
title("FX")
slider("Shimmer","shimmer",0,50,0.1)
slider("Grain","grain",0,0.08,0.001)
slider("Alpha","alpha",0.2,1.0,0.01)
title("Shadow")
local swShadow = toggle("Enable Shadow",st.shadow_enabled,function(v) st.shadow_enabled=v end)
slider("Spread","shadow_spread",0,120,1)
slider("Intensity","shadow_intensity",0,180,1)
local bar = vgui.Create("DPanel", nav)
bar:Dock(BOTTOM)
bar:SetTall(s(52))
Nyx.AutoNoBG(bar)
bar.Paint = function(_,w,h)
Nyx.Draw.Panel(0,0,w,h,{radius=s(12),color=Style and Style.cardColor or Color(16,18,24,120),glass=true,stroke=true})
end
local btnW = (lw - s(8*4)) / 3
local function shapeLbl()
if st.shape==RNDX.SHAPE_FIGMA then return "Figma"
elseif st.shape==RNDX.SHAPE_CIRCLE then return "Circle"
else return "iOS" end
end
local btnRst = Nyx.Components.CreateButton(bar,"Reset",{variant="ghost"})
btnRst:Dock(LEFT)
btnRst:DockMargin(s(8), s(6), s(6), s(6))
btnRst:SetWide(btnW)
btnRst._onClick = function()
st = mk()
RunConsoleCommand("libnyx_liquid_size", tostring(st.size))
for k,ctrl in pairs(ui.sliders) do if IsValid(ctrl) then ctrl:SetValue(st[k] or 0) end end
if IsValid(swShadow) then swShadow:SetChecked(st.shadow_enabled and true or false) end
if IsValid(shapeDD) and shapeDD.SetSelectedLabel then shapeDD:SetSelectedLabel(shapeLbl()) end
clampBox()
if notification and notification.AddLegacy then notification.AddLegacy("libNyx: settings reset.", NOTIFY_HINT, 2) end
if chat and chat.AddText then chat.AddText(Color(140,180,255), "[libNyx] ", color_white, "Liquid Glass settings reset.") end
end
local function shapeConst()
if st.shape==RNDX.SHAPE_FIGMA then return "RNDX.SHAPE_FIGMA"
elseif st.shape==RNDX.SHAPE_CIRCLE then return "RNDX.SHAPE_CIRCLE"
else return "RNDX.SHAPE_IOS" end
end
local function ensurePos()
local sw,sh = rt:GetWide(), rt:GetTall()
local bw,bh = st.size, st.size
local leftBound = pad + lw + s(12)
local minX = math.max(leftBound, pad)
local maxX = sw - pad - bw
local minY = pad
local maxY = sh - pad - bh
if not st.posX then st.posX = sw - bw - pad end
if not st.posY then st.posY = pad + s(20) end
st.posX = clp(st.posX, minX, math.max(minX, maxX))
st.posY = clp(st.posY, minY, math.max(minY, maxY))
end
local btnCP = Nyx.Components.CreateButton(bar,"Copy",{variant="ghost"})
btnCP:Dock(LEFT)
btnCP:DockMargin(s(6), s(6), s(6), s(6))
btnCP:SetWide(btnW)
btnCP._onClick = function()
ensurePos()
local rr = (st.shape==RNDX.SHAPE_CIRCLE) and math.floor((st.size or 0)*0.5) or (st.rad or 0)
local lines = {
"RNDX().Liquid(bx,by,bw,bh)",
" :Rad("..fmt(rr)..")",
" :Color(255,255,255,255)",
" :Tint("..math.floor(st.tr or 0)..","..math.floor(st.tg or 0)..","..math.floor(st.tb or 0)..")",
" :TintStrength("..fmt(st.tints or 0)..")",
" :Saturation("..fmt(st.sat or 1)..")",
" :GlassBlur("..fmt(st.blur_all or 0)..","..fmt(st.blur_rad or 0)..")",
" :EdgeSmooth("..fmt(st.edge or 0)..")",
" :Strength("..fmt(st.strength or 0)..")",
" :Speed("..fmt(st.speed or 0)..")",
" :Shimmer("..fmt(st.shimmer or 0)..")",
" :Grain("..fmt(st.grain or 0)..")",
" :Alpha("..fmt(st.alpha or 1)..")",
" :Flags("..shapeConst()..")"
}
if st.shadow_enabled and ((st.shadow_spread or 0)>0 or (st.shadow_intensity or 0)>0) then
table.insert(lines, #lines, " :Shadow("..fmt(st.shadow_spread or 0)..","..fmt(st.shadow_intensity or 0)..")")
end
local code = table.concat(lines, "\n")
SetClipboardText(code)
if notification and notification.AddLegacy then notification.AddLegacy("libNyx: code copied to clipboard.", NOTIFY_GENERIC, 3) end
if chat and chat.AddText then chat.AddText(Color(140,180,255), "[libNyx] ", color_white, "Liquid Glass builder copied.") end
end
local btnX = Nyx.Components.CreateButton(bar,"Close",{variant="ghost"})
btnX:Dock(FILL)
btnX:DockMargin(s(6), s(6), s(8), s(6))
btnX._onClick = function() if IsValid(rt) then rt:Remove() end end
if IsValid(shapeDD) and shapeDD.SetSelectedLabel then shapeDD:SetSelectedLabel(shapeLbl()) end
local drag = {on=false,dx=0,dy=0}
rt._hoverA = 0
local function clampReal()
local sw,sh = rt:GetWide(), rt:GetTall()
local bw,bh = st.size, st.size
local leftBound = pad + lw + s(12)
local minX = math.max(leftBound, pad)
local maxX = sw - pad - bw
local minY = pad
local maxY = sh - pad - bh
if not st.posX then st.posX = sw - bw - pad end
if not st.posY then st.posY = pad + s(20) end
st.posX = clp(st.posX, minX, math.max(minX, maxX))
st.posY = clp(st.posY, minY, math.max(minY, maxY))
end
clampBox = clampReal
clampReal()
hook.Add("OnScreenSizeChanged","libNyx.LiquidGlass.Relayout",function()
if not IsValid(rt) or not IsValid(nav) or not IsValid(bd) or not IsValid(bar) then return end
rt:SetSize(ScrW(),ScrH())
lw = math.min(s(380), math.max(s(300), math.floor(ScrW()*0.26)))
nav:SetPos(pad, pad)
nav:SetSize(lw, ScrH() - pad*2)
clampReal()
end)
function rt:OnMousePressed(mc)
if mc ~= MOUSE_LEFT then return end
local mx,my = self:LocalCursorPos()
local bw,bh = st.size,st.size
if mx>=st.posX and mx<=st.posX+bw and my>=st.posY and my<=st.posY+bh then
drag.on = true
drag.dx = mx - st.posX
drag.dy = my - st.posY
self:MouseCapture(true)
end
end
function rt:OnMouseReleased(mc)
if mc ~= MOUSE_LEFT then return end
if drag.on then
drag.on = false
self:MouseCapture(false)
end
end
function rt:OnCursorMoved(x,y)
if not drag.on then return end
st.posX = x - drag.dx
st.posY = y - drag.dy
clampReal()
end
function rt:Think()
local mx,my = self:LocalCursorPos()
local bw,bh = st.size,st.size
local inside = mx>=st.posX and mx<=st.posX+bw and my>=st.posY and my<=st.posY+bh
local tgt = (inside or drag.on) and 1 or 0
self._hoverA = Lerp(FrameTime()*10, self._hoverA, tgt)
if inside or drag.on then self:SetCursor("sizeall") else self:SetCursor("arrow") end
end
local function curRad(w,h)
if st.shape == RNDX.SHAPE_CIRCLE then
return math.floor(math.min(w,h) * 0.5)
end
return st.rad
end
function rt:Paint(sw,sh)
clampReal()
local bx,by = st.posX, st.posY
local bw,bh = st.size, st.size
local rr = curRad(bw,bh)
RNDX().Rect(bx,by,bw,bh):Rad(rr):Flags(st.shape):Blur(1):Draw()
local liq = RNDX().Liquid(bx,by,bw,bh)
:Rad(rr)
:Color(255,255,255,255)
:Tint(st.tr,st.tg,st.tb)
:TintStrength(st.tints)
:Saturation(st.sat)
:GlassBlur(st.blur_all,st.blur_rad)
:EdgeSmooth(st.edge)
:Strength(st.strength)
:Speed(st.speed)
:Shimmer(st.shimmer)
:Grain(st.grain)
:Alpha(st.alpha)
:Flags(st.shape)
if st.shadow_enabled and (st.shadow_spread>0 or st.shadow_intensity>0) then liq:Shadow(st.shadow_spread,st.shadow_intensity) end
liq:Draw()
local a = self._hoverA
local c1 = Color(255,255,255, math.floor(235 * (1-a)))
local c2 = Color(255,255,255, math.floor(235 * a))
draw.SimpleText("Liquid Glass", "libNyx.Manrope.Liquid", bx + bw/2, by + bh/2, c1, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText("Hold to drag", "libNyx.Manrope.Liquid", bx + bw/2, by + bh/2, c2, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
concommand.Add("libnyx_liquid", open)
-- libNyx and LiquidGlass shader by MaryBlackfild
-- JOIN DISCORD: https://discord.gg/rUEEz4mfXw

View File

@@ -0,0 +1,415 @@
-- libNyx by MaryBlackfild
-- JOIN DISCORD: https://discord.gg/rUEEz4mfXw
if SERVER then
AddCSLuaFile()
return
end
local libNyx = libNyx or {}
libNyx.UI = libNyx.UI or {}
_G.libNyx = libNyx
local RNDX = include("libnyx/lib/rndx.lua")
if not (libNyx.UI and libNyx.UI.Draw and libNyx.UI.Components) then
include("libnyx/lib/libnyx_components.lua")
end
local Style = libNyx.UI.Style
local Components = libNyx.UI.Components
local GRAD_PALETTE = {
Color( 90,160,255),
Color(255,125,155),
Color(120,220,160),
Color(255,200,120),
Color(170,120,255),
Color(120,200,255),
}
local function PalettePick(key)
key = tostring(key or "")
local sum = 0
for i = 1, #key do sum = sum + key:byte(i) end
local idx = (sum % #GRAD_PALETTE) + 1
return GRAD_PALETTE[idx]
end
local showcase
function libNyx.UI.OpenShowcase()
if IsValid(showcase) then showcase:Close() end
local W = math.min(ScrW() - libNyx.UI.Scale(80), 1200)
local H = math.min(ScrH() - libNyx.UI.Scale(80), 780)
showcase = libNyx.UI.CreateFrame({w = W, h = H, title = "Демонстрация libNyx UI"})
local pages = vgui.Create("DPanel", showcase)
pages:Dock(FILL)
pages:DockMargin(Style.padding, Style.padding, Style.padding, Style.padding)
pages.Paint = nil
local page1, page2
local function showPage(which)
if IsValid(page1) then page1:SetVisible(which == 1) end
if IsValid(page2) then page2:SetVisible(which == 2) end
end
local nav = Components.CreateTabs(showcase, {
items = {
{id="p1", label="демка 1", icon=Material("icon16/page_white.png","noclamp smooth")},
{id="p2", label="демка 2", icon=Material("icon16/page_white_text.png","noclamp smooth")},
},
default = "p1",
onChange = function(id) showPage(id == "p1" and 1 or 2) end
})
nav:Dock(TOP)
nav:SetTall(libNyx.UI.Scale(52))
nav:DockMargin(Style.headerIndentX, Style.headerIndentY + libNyx.UI.Scale(8), Style.headerIndentX, libNyx.UI.Scale(6))
page1 = vgui.Create("DPanel", pages)
page1:Dock(FILL)
page1.Paint = nil
do
local left = vgui.Create("DPanel", page1)
left:Dock(LEFT)
left:SetWide(math.floor(W * 0.40))
left.Paint = function(s,w,h)
libNyx.UI.Draw.Panel(0,0,w,h,{radius=Style.radius, color=Style.panelColor, glass=true})
end
left:DockMargin(0, 0, Style.padding, 0)
local leftStack = vgui.Create("DPanel", left)
leftStack:Dock(FILL)
leftStack:DockPadding(Style.padding, Style.padding, Style.padding, Style.padding)
leftStack.Paint = nil
local checksRow = vgui.Create("DPanel", leftStack)
checksRow:Dock(TOP)
checksRow:SetTall(libNyx.UI.Scale(32))
checksRow:DockMargin(0, 0, 0, libNyx.UI.Scale(16))
checksRow.Paint = nil
local function addChk(var, text, startOn)
local c = Components.CreateCheckbox(checksRow, {
variant = var,
label = text,
checked = startOn,
tint = Style.accentColor,
onChange = function(v)
chat.AddText(Color(0,255,0), "[libNyx] ", Color(255,255,0), text, Color(200,200,200), " = ", v and "ON" or "OFF")
end
})
c:Dock(LEFT)
c:DockMargin(0, 0, libNyx.UI.Scale(16), 0)
return c
end
addChk("switch", "Switch", true)
addChk("knob", "Knob", true)
addChk("radio", "Radio", true)
-- buttons
local b1 = Components.CreateButton(leftStack, "Основная", {variant="primary", align="left"})
b1:Dock(TOP) b1:DockMargin(0, 0, 0, libNyx.UI.Scale(10))
local b2 = Components.CreateButton(leftStack, "Мягкая", {variant="soft", align="left"})
b2:Dock(TOP) b2:DockMargin(0, 0, 0, libNyx.UI.Scale(10))
local b3 = Components.CreateButton(leftStack, "Прозрачная", {variant="ghost", align="left"})
b3:Dock(TOP) b3:DockMargin(0, 0, 0, libNyx.UI.Scale(10))
local b4 = Components.CreateButton(leftStack, "Градиентная",{variant="gradient", align="left", tint = PalettePick("btn")})
b4:Dock(TOP) b4:DockMargin(0, 0, 0, libNyx.UI.Scale(16))
local b5 = Components.CreateButton(leftStack, "солид", {variant="primary_center"})
b5:Dock(TOP) b5:DockMargin(0, 0, 0, libNyx.UI.Scale(10))
local b6 = Components.CreateButton(leftStack, "Центр-гр", {variant="center_duo", tint = Color(97,17,191), centerTint = Color(136,49,238)})
b6:Dock(TOP)
b6:DockMargin(0, 0, 0, libNyx.UI.Scale(16))
local sld = Components.CreateSlider(leftStack, {min=1, max=100, value=42, decimals=0, tint=Style.accentColor})
sld:Dock(TOP) sld:DockMargin(0, 0, 0, libNyx.UI.Scale(16))
sld:SetTall(libNyx.UI.Scale(30))
local dd = Components.CreateDropdown(leftStack, {
placeholder = "Выберите категорию",
choices = {"Недвижимость", "Бизнес", "Промо", "VIP"},
onSelect = function(val) chat.AddText(Color(0,255,0), "[libNyx] Вы выбрали: ", Color(255,255,0), val) end,
tint = PalettePick("dropdown")
})
dd:Dock(TOP) dd:DockMargin(0, 0, 0, libNyx.UI.Scale(8))
dd:SetTall(libNyx.UI.Scale(36))
-- bullets
local feats = {"The libNyx 1.0","Nyx Team топ","бээ-бээ барашек"}
for _, t in ipairs(feats) do
local row = vgui.Create("DPanel", leftStack)
row:Dock(TOP)
row:DockMargin(0, 0, 0, libNyx.UI.Scale(8))
row:SetTall(libNyx.UI.Scale(30))
row.Paint = function(s,w,h)
libNyx.UI.Draw.Panel(0,0,w,h,{radius=libNyx.UI.Scale(8), color=Style.cardColor, glass=true})
draw.SimpleText(""..t, libNyx.UI.Font(libNyx.UI.Scale(18)), libNyx.UI.Scale(8), h/2, Style.textColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
end
-- right pane
local right = vgui.Create("DPanel", page1)
right:Dock(FILL)
right.Paint = function(s,w,h)
libNyx.UI.Draw.Panel(0,0,w,h,{radius=Style.radius, color=Style.panelColor, glass=true})
end
-- bottom boxes strip
local strip = vgui.Create("DPanel", right)
strip:Dock(BOTTOM)
strip:SetTall(libNyx.UI.Scale(220))
strip:DockMargin(Style.padding, 0, Style.padding, Style.padding)
strip.Paint = nil
local bx1 = Components.CreateVBox(strip, {variant = "center_gradient", title = "Бокс1", icon = Material("icon16/heart.png"), tint = Color(140,120,255)})
bx1:Dock(LEFT); bx1:DockMargin(0,0,Style.padding,0)
local bx2 = Components.CreateVBox(strip, {variant = "sunburst", title = "Бокс2", icon = Material("icon16/star.png"), tint = Color(255,180,90)})
bx2:Dock(LEFT); bx2:DockMargin(0,0,Style.padding,0)
local bx3 = Components.CreateVBox(strip, {variant = "model", title = "Бокс3", model = "models/props_c17/oildrum001.mdl", tint = Color(120,200,255)})
bx3:Dock(LEFT); bx3:DockMargin(0,0,Style.padding,0)
local bx4 = Components.CreateVBox(strip, {variant = "vertical_gradient", title = "Бокс4", icon = Material("icon16/flag_yellow.png"), tint = Color(120,180,255)})
bx4:Dock(LEFT)
-- list
local list = Components.CreateList(right, {rowHeight = Style.rowHeight, vbarWidth = libNyx.UI.Scale(12)})
list:Dock(FILL)
list:DockMargin(Style.padding, Style.padding, Style.padding, Style.padding)
local iconShop = Material("icon16/cart.png")
local iconHome = Material("icon16/house.png")
list:AddRow({
title = "Строка с иконкой и метками",
icon = iconShop,
labels = {
{text="Премиум", color=Color(255,215,0)},
{text="Новинка", color=Color(90,160,255)},
{text="Рекомендуем", color=Color(120,220,160)},
},
rightText = "12 000 kr",
onClick = function() chat.AddText(Color(0,255,0),"[libNyx] Нажата строка 1") end
})
list:AddRow({
title = "Строка без иконки",
labels = { {text="Скоро", color=Color(170,120,255)} },
rightText = "Бесплатно",
gradient = false,
onClick = function() chat.AddText(Color(0,255,0),"[libNyx] Нажата строка 2 (plain)") end
})
list:AddRow({
title = "Строка с множеством меток",
icon = iconHome,
labels = {
{text="Скидка", color=Color(120,220,160)},
{text="Ограничено", color=Color(255,125,155)},
{text="-15%", color=Color(255,200,120)},
{text="Сегодня", color=Color(120,200,255)},
{text="Дополнительно", color=Color(90,160,255)},
},
rightText = "8 500 kr",
})
local inv = vgui.Create("DPanel", right)
inv:Dock(TOP)
inv:SetTall(libNyx.UI.Scale(110))
inv:DockMargin(Style.padding, Style.padding, Style.padding, 0)
inv.Paint = nil
local invCellA = Components.CreateInteractiveCell(inv, {size=libNyx.UI.Scale(88), tint=Color(140,120,255)})
invCellA:Dock(LEFT)
invCellA:DockMargin(0,0,Style.padding,0)
local invCellB = Components.CreateInteractiveCell(inv, {size=libNyx.UI.Scale(88), tint=Color(120,200,255)})
invCellB:Dock(LEFT)
invCellA:SetItemIcon(
Material("materials_umbrellyx/moreicons/doughnut-1.png", "noclamp smooth"),
libNyx.UI.Scale(40),
{
title = "Пончик «Глазурь»",
desc = "Сладкий круглый десерт с сахарной глазурью. Даёт +25 к настроению и немного утоляет голод.",
tags = {
{text="Еда", color=Color(255,180,90)},
{text="Сладкое", color=Color(255,125,155)},
{text="Эпик", color=Color(170,120,255)}
}
}
)
-- (optional) leave empty to demo drag-drop target
-- if u want a second example, uncomment:
-- invCellB:SetItemIcon(Material("icon16/box.png","noclamp smooth"), libNyx.UI.Scale(36), {
-- title = "Пустая коробка",
-- desc = "Прочная тара для переноски мелких предметов.",
-- tags = {"Контейнер", {text="Обычный", color=Color(120,200,255)}}
-- })
end
page2 = vgui.Create("DPanel", pages)
page2:Dock(FILL)
page2:SetVisible(false)
page2.Paint = function(s,w,h)
libNyx.UI.Draw.Panel(0,0,w,h,{radius=Style.radius, color=Style.panelColor, glass=true})
end
do
local subnav = Components.CreateTabs(page2, {
items = {
{ id = "stylish", label = "Стильно", icon = Material("icon16/page_white_text.png","noclamp smooth") },
{ id = "pretty", label = "Красиво", icon = Material("icon16/newspaper.png","noclamp smooth") },
{ id = "modern", label = "Современно", icon = Material("icon16/fire.png","noclamp smooth") },
{ id = "nyxnyx", label = "никс-никс-никс", icon = Material("icon16/heart.png","noclamp smooth") },
{ id = "woohoo", label = "Делаем вуху?", icon = Material("icon16/user.png","noclamp smooth") },
{ id = "r34", label = "r34", icon = Material("icon16/star.png","noclamp smooth") },
},
default = "pretty",
onChange = function()
page2:InvalidateLayout(true)
end
})
subnav:Dock(TOP)
subnav:SetTall(libNyx.UI.Scale(52))
subnav:DockMargin(Style.padding, Style.padding, Style.padding, libNyx.UI.Scale(12))
local content = vgui.Create("DPanel", page2)
content:Dock(FILL)
content:DockMargin(Style.padding, 0, Style.padding, Style.padding)
content.Paint = function(s,w,h)
libNyx.UI.Draw.Panel(0,0,w,h,{radius=Style.radius, color=Color(12,14,20,110), glass=true})
end
local toolbar = vgui.Create("DPanel", page2)
toolbar:Dock(TOP)
toolbar:SetTall(libNyx.UI.Scale(48))
toolbar:DockMargin(Style.padding, Style.padding, Style.padding, 0)
toolbar.Paint = nil
local flow = vgui.Create("DIconLayout", content)
flow:Dock(FILL)
flow:DockMargin(Style.padding, Style.padding, Style.padding, Style.padding)
flow:SetSpaceX(Style.padding)
flow:SetSpaceY(Style.padding)
local function cardWidth()
local w = content:GetWide()
return math.max(libNyx.UI.Scale(220), math.floor((w - Style.padding*3) / 2))
end
local data = {
{variant="vibrant", title="Nyx Team", desc="Делаем не только красиво.", from=Color(129,82,255), to=Color(40,192,255), icon="werewolf/0x00000000!0x8aaf8d0ab771a3b9.0x00b2d882.png"},
{variant="vibrant", title="Nyx Team", desc="Делаем не только красиво.", from=Color(255,94,176), to=Color(255,142,220), icon="werewolf/0x00000000!0xfce5734b8472e83f.0x00b2d882.png"},
{variant="glass", title="Nyx Team", desc="Делаем не только красиво.", from=Color(58,160,255), to=Color(40,120,255), icon="werewolf/0x00000000!0xfc708fa9e974b2cb.0x00b2d882.png"},
{variant="glass", title="Nyx Team", desc="Делаем не только красиво.", from=Color(72,210,150), to=Color(28,190,140), icon="werewolf/0x00000000!0xf4e5b382cf4f862d.0x00b2d882.png"},
}
local function clearFlow()
for _, ch in ipairs(flow:GetChildren()) do if IsValid(ch) then ch:Remove() end end
end
local function renderCards(query)
query = string.Trim(string.lower(query or ""))
clearFlow()
for _, t in ipairs(data) do
local hay = string.lower((t.title or "") .. " " .. (t.desc or ""))
if query == "" or string.find(hay, query, 1, true) then
local c = Components.CreateCategoryCard(flow, t)
c:SetSize(cardWidth(), libNyx.UI.Scale(120))
end
end
flow:InvalidateLayout(true)
end
local search = Components.CreateSearchBox(toolbar, {
placeholder = "Поиск…",
tint = Style.accentColor,
onChange = function(q) renderCards(q) end,
onSubmit = function(q) renderCards(q) end,
onClear = function() renderCards("") end
})
search:Dock(FILL)
content.OnSizeChanged = function()
local cw = cardWidth()
for _, ch in ipairs(flow:GetChildren()) do
ch:SetSize(cw, libNyx.UI.Scale(120))
end
flow:InvalidateLayout(true)
end
renderCards("")
end
showPage(1)
end
concommand.Add("libnyx_ui_showcase", function() -- comm to open
libNyx.UI.OpenShowcase()
end)
-- libNyx by MaryBlackfild
-- JOIN DISCORD: https://discord.gg/rUEEz4mfXw

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,14 @@
-- Addon rendu publique part Heing Michel.
local add = AddCSLuaFile
local load = include
if SERVER then
add("selector/client.lua")
end
if CLIENT then
load("selector/client.lua")
end
-- Addon rendu publique part Heing Michel.

View File

@@ -0,0 +1,389 @@
-- Addon rendu publique part Heing Michel.
air_selector = air_selector or {}
air_selector.MAX_COLUMNS = 6
air_selector.MAX_CELLS = 32
air_selector.columns = air_selector.columns or {}
-- here i fill all columns with empty cells...
function air_selector.clear_columns(initial)
for i = 1, air_selector.MAX_COLUMNS do
air_selector.columns[i] = air_selector.columns[i] or {}
for slot_id = 1, air_selector.MAX_CELLS do
if initial then
air_selector.columns[i][slot_id] = {
x = 0, y = 0,
w = 0, h = 0,
weapon = nil,
}
else
air_selector.columns[i][slot_id].weapon = nil
end
end
end
end
air_selector.clear_columns(true)
local last_update = 0
function air_selector.update_weapons()
if last_update > CurTime() then
return
end
last_update = CurTime() + 0.25
air_selector.clear_columns()
local weapons = LocalPlayer():GetWeapons()
local weapons_count = #weapons
for i = 1, weapons_count do
local weapon = weapons[i]
local slot = weapon:GetSlot() + 1
--local pos = weapon:GetSlotPos() + 1
if slot > air_selector.MAX_COLUMNS then
slot = air_selector.MAX_COLUMNS
end
--if pos > air_selector.MAX_CELLS then
-- pos = air_selector.MAX_CELLS
--end
local pos
for cell = 1, air_selector.MAX_CELLS do
if not air_selector.columns[slot][cell].weapon then
pos = cell
break
end
end
if pos then
air_selector.columns[slot][pos].weapon = weapon
end
end
end
air_selector.selected_column = 1
air_selector.selected_cell = 0
function air_selector.is_valid_cell(column, cell)
if not column then
column = air_selector.selected_column
end
if not cell then
cell = air_selector.selected_cell
end
if not air_selector.columns[column] then
return false
end
if not air_selector.columns[column][cell] then
return false
end
if not air_selector.columns[column][cell].weapon then
return false
end
return true
end
-- Addon rendu publique part Heing Michel.
---@param column number
---@return number filled_cells
function air_selector.get_filled_cells(column)
local filled_cells = 0
if not air_selector.columns[column] then
return 1
end
for cell = 1, air_selector.MAX_CELLS do
if air_selector.columns[column][cell].weapon then
filled_cells = filled_cells + 1
end
end
if filled_cells == 0 then
filled_cells = 1, false
end
return filled_cells
end
function air_selector.increment_column()
air_selector.selected_column = air_selector.selected_column + 1
air_selector.selected_cell = 1
if air_selector.selected_column > air_selector.MAX_COLUMNS then
air_selector.selected_column = 1
elseif not air_selector.is_valid_cell() then
air_selector.increment_column()
return
end
air_selector.last_change = CurTime()
end
function air_selector.decrement_column()
air_selector.selected_column = air_selector.selected_column - 1
air_selector.selected_cell = air_selector.get_filled_cells(air_selector.selected_column)
if air_selector.selected_column < 1 then
air_selector.selected_column = air_selector.MAX_COLUMNS
elseif not air_selector.is_valid_cell() then
air_selector.decrement_column()
return
end
air_selector.last_change = CurTime()
end
function air_selector.increment_cell(increment_column)
air_selector.selected_cell = air_selector.selected_cell + 1
local filled_cells = air_selector.get_filled_cells(air_selector.selected_column)
if air_selector.selected_cell > filled_cells then
if increment_column == false then
air_selector.selected_cell = 1
else
air_selector.increment_column()
end
end
air_selector.last_change = CurTime()
end
function air_selector.decrement_cell()
air_selector.selected_cell = air_selector.selected_cell - 1
if air_selector.selected_cell < 1 then
air_selector.decrement_column()
end
air_selector.last_change = CurTime()
end
---@param column number
function air_selector.select_column(column)
if air_selector.selected_column == column then
air_selector.increment_cell(false)
return
end
air_selector.selected_column = column
air_selector.selected_cell = 1
air_selector.last_change = CurTime()
end
-- Addon rendu publique part Heing Michel.
-- selector controller i think...
hook.Add("PlayerBindPress", "air_selector.binds", function(ply, bind, pressed, key)
if not pressed then
return
end
if IsValid(LocalPlayer():GetVehicle()) then
return
end
if bind == "invprev" then
air_selector.decrement_cell()
return true
end
if bind == "invnext" then
air_selector.increment_cell()
return true
end
if key >= 2 and key <= air_selector.MAX_COLUMNS + 1 then
air_selector.select_column(key - 1)
return true
end
if air_selector.lerp <= 1 then
return
end
if bind == "+attack" then
local wep = air_selector.columns[air_selector.selected_column][air_selector.selected_cell].weapon
if wep and LocalPlayer():GetActiveWeapon() ~= wep then
input.SelectWeapon(wep)
LocalPlayer():EmitSound("common/wpn_hudoff.wav", 25, 90)
air_selector.last_change = CurTime() - 5
air_selector.lerp = 0
return true
end
end
end)
air_selector.start_x = 470
air_selector.start_y = 40
air_selector.scale = ScrH() == 2160 and 2 or ScrH() / 1080
air_selector.s = air_selector.scale
air_selector.visible = false
air_selector.lerp = 0
air_selector.last_change = 0
surface.CreateFont("air_selector.font", {
font = "Montserrat Medium",
size = air_selector.s * 26,
weight = 700,
extended = true,
})
surface.CreateFont("air_selector.weapon_icons", {
font = "HalfLife2",
size = air_selector.s * 100,
weight = 550,
})
local long_box = 240 * air_selector.s
local small_box = 100 * air_selector.s
air_selector.icons = {
["weapon_smg1"] = "a",
["weapon_shotgun"] = "b",
["weapon_crowbar"] = "c",
["weapon_pistol"] = "d",
["weapon_357"] = "e",
["weapon_crossbow"] = "g",
["weapon_physgun"] = "h",
["weapon_rpg"] = "i",
["weapon_bugbait"] = "j",
["weapon_frag"] = "k",
["weapon_ar2"] = "l",
["weapon_physcannon"] = "m",
["weapon_stunstick"] = "n",
["weapon_slam"] = "o",
}
---@param x number
---@param y number
---@param column number
---@param cell boolean
---@return number @y
function air_selector.draw_cell(x, y, column, cell)
local w, h = small_box, small_box
local col = Color(255, 255, 255, 150)
local text_col = color_black
if air_selector.selected_column == column then
w = long_box
h = 50 * air_selector.s
if air_selector.selected_cell == cell then
h = 138 * air_selector.s
col = Color(3, 179, 252, 150)
text_col = Color(255, 255, 255, 255)
end
end
-- Addon rendu publique part Heing Michel.
local cell_table = air_selector.columns[column][cell]
cell_table.x = Lerp(FrameTime() * 10, cell_table.x, x)
cell_table.y = Lerp(FrameTime() * 10, cell_table.y, y)
cell_table.w = Lerp(FrameTime() * 10, cell_table.w, w)
cell_table.h = Lerp(FrameTime() * 10, cell_table.h, h)
local real_y = y
local real_h = h
local x = cell_table.x
local y = cell_table.y
local w = cell_table.w
local h = cell_table.h
local wep = air_selector.columns[column][cell].weapon
local name
if wep then
name = wep:GetPrintName()
--print(wep:GetClass())
end
col.a = math.Clamp(air_selector.lerp, 0, 150)
text_col.a = air_selector.lerp
draw.RoundedBox(8, x, y, w, h, col)
if cell == 1 then
draw.SimpleText(column, "air_selector.font", x + 15 * air_selector.s, y + 10 * air_selector.s, text_col)
end
if column == air_selector.selected_column and name then
draw.SimpleText(name, "air_selector.font", x + w / 2, y + h - 10 * air_selector.s, text_col, 1, 4)
if air_selector.selected_cell == cell then
draw.RoundedBox(8, x + w / 2 - 56 * air_selector.s, y, 112 * air_selector.s, 4 * air_selector.s, Color(5, 179, 252, air_selector.lerp))
if wep and air_selector.icons[wep:GetClass()] then
local x = x + w / 2
local y = y + h / 2
draw.SimpleText(air_selector.icons[wep:GetClass()], "air_selector.weapon_icons", x, y, text_col, 1, 1)
end
else
draw.RoundedBox(8, x, y + h / 2 - 15 * air_selector.s, 4 * air_selector.s, 30 * air_selector.s,col)
end
end
return real_y + real_h + 10 * air_selector.s
end
function air_selector.draw_columns()
local x = air_selector.start_x
for column = 1, air_selector.MAX_COLUMNS do
local cells = air_selector.selected_column == column and 6 or 1
local y = air_selector.start_y
y = air_selector.draw_cell(x, y, column, 1)
if air_selector.selected_column == column then
for cell = 2, air_selector.MAX_CELLS do
if air_selector.columns[column][cell].weapon then
y = air_selector.draw_cell(x, y, column, cell)
end
end
end
if air_selector.selected_column == column then
x = x + long_box + 10 * air_selector.s
else
x = x + small_box + 10 * air_selector.s
end
end
end
-- Addon rendu publique part Heing Michel.
local last_cell = 1
local last_column = 1
hook.Add("DrawOverlay", "air_selector.paint", function()
local to = (air_selector.last_change > CurTime() - 1) and 255 or 0
air_selector.lerp = Lerp(FrameTime() * 10, air_selector.lerp, to)
if air_selector.lerp <= 1 then
air_selector.selected_column = 1
air_selector.selected_cell = 0
return
end
if last_cell ~= air_selector.selected_cell or last_column ~= air_selector.selected_column then
LocalPlayer():EmitSound("common/wpn_select.wav", 20, 100)
last_cell = air_selector.selected_cell
last_column = air_selector.selected_column
end
air_selector.update_weapons()
air_selector.draw_columns()
end)

22
addons/apg/.travis.yml Normal file
View File

@@ -0,0 +1,22 @@
sudo: false
language: c
addons:
apt:
packages:
- libc6:i386
- libstdc++6:i386
before_install:
# Download the lua
- wget https://github.com/Metastruct/gtravis/releases/download/travisbins/gluac.tar.xz
- tar -xf gluac.tar.xz
- export LD_LIBRARY_PATH=`pwd`/gluac${LD_LIBRARY_PATH:+:}${LD_LIBRARY_PATH:-}
# Set the $PATH so gluac can be executed
- export PATH=$PATH:`pwd`/gluac
- echo $PWD
script: find lua/ -iname '*.lua' -print0 | xargs -0 -- gluac -p --

View File

@@ -0,0 +1,62 @@
# Commit Rules
- [Commit Rules](#commit-rules)
- [Squash](#squash)
- [Here's what you do](#heres-what-you-do)
- [Oh no I messed up](#oh-no-i-messed-up)
- [Be Descriptive](#be-descriptive)
- [Test and Check](#test-and-check)
- [Be Considerate](#be-considerate)
## Squash
[Back to Top](#commit-rules)
If you have lots of commits like "Oops", "Reverted X", "Fixed bug", squash them.
### Here's what you do
1. Backup your current repo by copying it into another folder
1. Be sure to remove the `.git` folder as you don't need that in your backup.
2. Go back to the working folder, aka the one with the `.git` folder.
3. `git log --pretty=oneline --abbrev-commit`
1. The displayed list will be shown top (newest) to bottom (oldest).
2. Find the main commit that you made (before the small fixes).
3. Copy the code under it, it will look something like this... `742c3ac`
4. `git rebase -i <abbreviated commit code>`
1. Git should guide you through this.
2. If you need to fix conflicts your files will be edited, and you will get an error.
3. [Don't panic](https://help.github.com/en/articles/resolving-a-merge-conflict-using-the-command-line)
5. Review your changes!
6. Make sure to **review your changes** sometimes conflict resolution can get undesirable code back into your repo.
7. When you're ready use `git push --force` to push your rebase.
### Oh no I messed up
1. Don't panic! You made a backup.
2. Delete everything besides the `.git` folder.
3. Copy and paste everything from your backup.
4. Now just push the change as a new commit.
- Be sure to be very descriptive in your commit message/comment.
---
You may also want to look into [this stackoverflow question](https://stackoverflow.com/q/134882) and [the answer](https://stackoverflow.com/a/135614) provided.
## Be Descriptive
[Back to Top](#commit-rules)
You don't have to write a paragraph about all your changes, but describe what you're trying to do in a clear way.
## Test and Check
[Back to Top](#commit-rules)
Always test and check your code, and don't just test once. Test multiple times in multiple environements. If your code isn't tested don't commit.
## Be Considerate
[Back to Top](#commit-rules)
This addon will be runnning with other addons, please make sure it plays nice. Specify any detours, try not to [error](https://wiki.garrysmod.com/page/Global/error), and be sure to make all your codes behaviour expected.

68
addons/apg/README.md Normal file
View File

@@ -0,0 +1,68 @@
Due to seemingly consistent issues with the code base of APG I've made PUG.
However I doubt PUG will get any updates because I simply no longer play Garry's mod,
but if you'd like to check my alternative to APG, check out [__PUG__ on Gitlab](https://gitlab.com/NanoAi/gm_pug) or [__PUG__ Github Mirror](https://github.com/NanoAi/gm_pug)
------------------
This will no longer be updated as I can no longer support it, if you are looking for a good alternative please check out PUG linked above. It's also free, and can do almost everything APG can do.
Also please for the love of god, don't pay for stuff like this.
------------------
# APG - Anti Prop Griefing & Crash Protection
![- APG - Light Weight, Easy to Use, Stops Crashes](https://i.imgur.com/DrbZOgk.png "APG - Light Weight, Easy to Use, Stops Crashes")
We are dedicated and focused on providing servers with the best answer to prop
griefers, killers, and exploiters. We saw all the currently available addons and
felt that neither one of them alone could really do everything that we wanted it
to do, so naturally we made our own and decided to share it with you.
## This does still require a prop protection addon
### Compatible prop protection addons (with CPPI)
* [Falco's Prop Protection (FPP)](https://github.com/FPtje/Falcos-Prop-protection/)
* [PatchProtect](https://github.com/Patcher56/PatchProtect)
* [Simple Prop Protection (SPP)](https://github.com/Donkie/SimplePropProtection)
### ⚠ Don't use more then one prop protection/anti prop griefing addon at a time!
### ( You have been warned! )
## Features & Notes
* ✅ Easy install and configuration ( Just say !apg )
* ✅ Customizable blacklist of entities to protect ( props, wire, etc )
* ✅ Props ghosting/unghosting on physgun
* ✅ Disables prop damage to players
* ✅ Controls prop pushing against players
* ✅ Controls prop pushing vehicles
* ✅ Controls prop surfing
* ✅ Blocks many types of exploits
* ✅ Blocks stacker exploit
* ✅ Blocks fading door exploit
* ✅ Blocks Advanced Duplicator exploit
* ✅ Blocks tool gun spamming
* ✅ Allows to toggle the use of the toolgun on the world
* ✅ Ability to check entities around the prop for stack's
* ✅ Ability to block vehicles damages against players
* ✅ Ability to make vehicles not collide with players
* ✅ Allows to block physgun reload
* ✅ Allows to block moving contraptions (props that are welded together)
* ✅ Supports anti-trapping for fading doors.
* ✅ Send a message to admins when a large stack of props is detected
* ⚠ Detours [PhysgunPickup](https://wiki.garrysmod.com/page/GM/PhysgunPickup) for better confirmations
* ⚠ Detours [SetColor](https://wiki.garrysmod.com/page/Entity/SetColor) to prevent stuff from turning purple/pink unexpectedly
* ⚠ Detours [SetCollisionGroup](https://wiki.garrysmod.com/page/Entity/SetCollisionGroup) to prevent overrides
Lag triggers are based on fancy algorithms and timers, if you are getting false positives try messing around with the values.
If you find any issue, exploit, possible improvement, suggestions, feel free to make an issue!
Credits:
* This project is currently updated and maintained by [NanoAi](http://steamcommunity.com/profiles/76561198096713277)
* This addon was originally created by [WhileTrue](http://steamcommunity.com/profiles/76561197972967270)
* Special thanks to [AvarianKnight](http://steamcommunity.com/profiles/76561198174460202) for reviving this project!

17
addons/apg/addon.json Normal file
View File

@@ -0,0 +1,17 @@
{
"title": "APG - Anti Prop Griefing & Crash Detection",
"type": "ServerContent",
"tags": [
"roleplay",
"build"
],
"ignore": [
".git",
".travis.yml",
"*.psd",
"*.vcproj",
"*.svn*",
"*.git*",
"*.md"
]
}

View File

@@ -0,0 +1,629 @@
APG_panels = APG_panels or {}
local pull = include("cl_utils.lua")
local utils = pull.utils or {}
local menu = pull.menu or {}
local function showNotice(notifyLevel, notifyMessage)
if string.Trim(notifyMessage) == "" then return end
icon = notifyLevel == 0 and NOTIFY_GENERIC or notifyLevel == 1 and NOTIFY_CLEANUP or notifyLevel == 2 and NOTIFY_ERROR
notification.AddLegacy(notifyMessage, icon, 3 + (notifyLevel * 3))
if APG.cfg[ "notifySounds" ].value then
surface.PlaySound(notifyLevel == 1 and "buttons/button10.wav" or notifyLevel == 2 and "ambient/alarms/klaxon1.wav" or "buttons/lightswitch2.wav") -- Maybe let the player choose the sound?
end
MsgC( notifyLevel == 0 and Color( 0, 255, 0 ) or Color( 255, 191, 0 ), "[APG] ", Color( 255, 255, 255 ), notifyMessage,"\n")
end
net.Receive( "apg_notice_s2c", function()
local notifyLevel = net.ReadUInt( 3 )
local notifyMessage = net.ReadString()
showNotice(notifyLevel, notifyMessage)
end)
local function APGBuildHomePanel()
local panel = APG_panels[ "home" ]
panel.Paint = function( i, w, h ) end
local github = "https://github.com/NanoAi/gm_apg"
menu:initPanel( panel, 0, 40, 0, 35 )
menu:switch( 568, 20, "Welcome to APG! ( https://git.io/fjCQK )")
menu:switch( 568, 20, "Remember to check the github for updates! (Click to Copy)", function()
SetClipboardText( github )
showNotice(0, "Github URL copied to clipboard!")
end)
menu:switch( 568, 20, "<-- Select a Module to Configure!")
menu:switch( 568, 20, "To see this menu again just say \"!apg\"")
menu:switch( 568, 20, "For more help the wiki is available on the Github! (Click to Copy)", function()
SetClipboardText( github .. "/wiki" )
showNotice(0, "Github URL copied to clipboard!")
end)
menu:switch( 568, 20, "Sorry for the bad home page, this is hopefully a placeholder. : )")
menu:panelDone()
end
local function APGBuildStackPanel()
local panel = APG_panels[ "stack_detection" ]
panel.Paint = function( i, w, h ) end
menu:initPanel( panel, 0, 40, 0, 35 )
menu:numSlider( 568, 20, "Maximum stacked ents", "stackMax", 3, 50, 0 )
menu:numSlider( 568, 20, "Stack distance (gmod units)", "stackArea", 5, 50, 0 )
menu:numSlider( 568, 20, "Maximum stacked fading doors", "fadingDoorStackMax", 5, 50, 0 )
menu:switch( 568, 20, "Notify player when their fading door is removed.", "fadingDoorStackNotify" )
menu:panelDone()
end
local function APGBuildToolsPanel()
local panel = APG_panels[ "tools" ]
panel.Paint = function( i, w, h ) end
menu:initPanel( panel, 0, 40, 0, 35 )
menu:switch( 568, 20, "Should tools be blocked on APG_CantPickup", "checkCanTool" )
menu:switch( 568, 20, "Block players from spamming the toolgun", "blockToolSpam" )
menu:numSlider( 568, 20, "Max click's per second(s)", "blockToolRate", 1, 15, 0 ) -- It's really hard to click more then 15 times a second.
menu:numSlider( 568, 20, "The aforementioned second(s)", "blockToolDelay", 1, 5, 0 )
menu:switch( 568, 20, "Prevent using the toolgun on the world", "blockToolWorld" )
menu:switch( 568, 20, "Prevent the toolgun from unfreezing props", "blockToolUnfreeze" )
menu:switch( 568, 20, "Block the Creator Tool? (Requires OSS)", "blockCreatorTool" )
menu:switch( 568, 20, "Review entities near tool use", "checkTooledEnts" )
menu:panelDone()
end
local function APGBuildMiscPanel()
local panel = APG_panels[ "misc" ]
panel.Paint = function( i, w, h ) end
menu:initPanel( panel, 0, 40, 0, 35 )
menu:switch( 568, 20, "Override Server Settings? (OSS)", "touchServerSettings" )
menu:switch( 568, 20, "Auto freeze over time", "autoFreeze" )
menu:numSlider( 568, 20, "Auto freeze delay(seconds)", "autoFreezeTime", 5, 600, 0 )
menu:switch( 568, 20, "Disable vehicle damages", "vehDamage" )
menu:switch( 568, 20, "Disable vehicle collisions (with players)", "vehNoCollide" )
menu:numSlider(575, 20, "Physgun maxrange (how far they can reach in gmod units)", "physGunMaxRange", 128, 8192, 0)
menu:switch( 568, 20, "Block GravGun throwing", "blockGravGunThrow" )
menu:switch( 568, 20, "Block Physgun Reload", "blockPhysgunReload" )
menu:switch( 568, 20, "Block players from moving contraptions", "blockContraptionMove" )
menu:switch( 568, 20, "Inject custom hooks into Fading Doors", "fadingDoorHook" )
menu:switch( 568, 20, "Activate FRZR9K (Sleepy Physics)", "sleepyPhys" )
menu:switch( 568, 20, "Hook FRZR9K into collision (Experimental)", "sleepyPhysHook" )
menu:switch( 568, 20, "Allow prop killing", "allowPK" )
menu:switch( 568, 20, "Activate Turbo Physics (Requires OSS)", "setTurboPhysics" )
menu:panelDone()
end
local function APGBuildLagPanel()
local panel = APG_panels[ "lag_detection" ]
panel.Paint = function( i, w, h ) end
menu:initPanel( panel, 0, 40, 0, 35 )
menu:numSlider( 568, 20, "Lag threshold (%)", "lagTrigger", 5, 200, 0 )
menu:numSlider( 568, 20, "Frames lost", "lagsCount", 1, 20, 0 )
menu:numSlider( 568, 20, "Heavy lag trigger (seconds)", "bigLag", 1, 5, 1 )
menu:comboBox( 568, 20, "Lag fix function", "lagFunc", APG_lagFuncs )
menu:numSlider( 568, 20, "Lag func. delay (seconds)", "lagFuncTime", 1, 300, 0 )
menu:panelDone()
end
local function APGBuildNotificationPanel()
local panel = APG_panels[ "notification" ]
panel.Paint = function( i, w, h ) end
menu:initPanel( panel, 0, 40, 0, 35 )
menu:switch( 568, 20, "Notification Sounds", "notifySounds" )
menu:comboBox( 568, 20, "Notification Level", "notifyLevel", APG_notifyLevels )
menu:switch( 570, 20, "Do you want to show what lag function ran?", "notifyLagFunc" )
menu:switch( 568, 20, "Developer logs (shows a notification, is spammy)", "developerDebug" )
menu:panelDone()
end
local function APGBuildLogsPanel()
local panel = APG_panels[ "logs" ]
panel.Paint = function( i, w, h ) end
menu:initPanel( panel, 0, 40, 0, 35 )
menu:switch( 568, 20, "Should we log when there is lag detected?", "logLagDetected" )
menu:switch( 568, 20, "Should we log when a player attempts to crash the server", "logStackCrashAttempt" )
menu:panelDone()
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(cornerRadius, x, y, width, height, color)
draw.RoundedBox( 0, 175, 37, 500, 300, 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 )
--draw.DrawText(text, font="DermaDefault", x=0, y=0, color=Color(255,255,255,255), xAlign=TEXT_ALIGN_LEFT)
draw.DrawText( "Good entities:", "APG_element_font", 180, 230, Color( 189, 189, 189), 3 )
draw.DrawText( "(Right-Click to Toggle)", "APG_title2_font", 285, 232, Color( 189, 189, 189), 3 )
end
menu:initPanel( panel, 0, 180, 0, 35 )
menu:switch( 170, 20, "Always frozen", "alwaysFrozen" )
menu:switch( 170, 20, "Fading Doors", "fadingDoorGhosting" )
menu:switch( 170, 20, "Ignore Vehicles", "vehAntiGhost" )
menu:switch( 170, 20, "Enable Color", "ghostColorToggle")
local offsets = menu:panelDone()
local Mixer = vgui.Create( "CtrlColor", panel )
Mixer:SetPos( 5, 55 )
Mixer:SetSize( 160, 110 )
Mixer.Mixer.ValueChanged = function( self, color )
APG.cfg[ "ghostColor" ].value = Color( color.r, color.g, color.b, color.a)
end
local badList = vgui.Create( "DListView", panel )
badList:Clear()
badList:SetPos( 180, 55 )
badList:SetSize( panel:GetWide() - 185, panel:GetTall() / 2.5 )
badList:SetMultiSelect( false )
badList:SetHideHeaders( false )
badList:AddColumn( "Class" )
badList:AddColumn( "Exact" )
function badList:OnRowRightClick( id, line )
local key = line:GetColumnText(1)
local value = not tobool(line:GetColumnText(2))
line:SetColumnText( 2, value )
APG.cfg[ "badEnts" ].value[key] = value
end
local goodList = vgui.Create( "DListView", panel )
goodList:Clear()
goodList:SetPos( 180, 250 )
goodList:SetSize( panel:GetWide() - 185, panel:GetTall() / 2.5 )
goodList:SetMultiSelect( false )
goodList:SetHideHeaders( false )
goodList:AddColumn( "Class" )
goodList:AddColumn( "Exact" )
function goodList:OnRowRightClick( id, line )
local key = line:GetColumnText(1)
local value = not tobool(line:GetColumnText(2))
line:SetColumnText( 2, value )
APG.cfg[ "unGhostingWhitelist" ].value[key] = value
end
local function updateTab()
badList:Clear()
for class,complete in pairs(APG.cfg[ "badEnts" ].value) do
badList:AddLine(class, complete)
end
goodList:Clear()
for class,complete in pairs(APG.cfg[ "unGhostingWhitelist" ].value) do
goodList:AddLine(class, complete)
end
end
updateTab()
badList.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 150, 150, 150, 255 ) )
end
badList.VBar.Paint = function(i,w,h)
surface.SetDrawColor( 88, 110, 110, 240 )
surface.DrawRect( 0, 0, w, h )
end
badList.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
badList.VBar.btnUp.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 72, 89, 89, 240 ) )
end
badList.VBar.btnDown.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 72, 89, 89, 240 ) )
end
goodList.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 150, 150, 150, 255 ) )
end
goodList.VBar.Paint = function(i,w,h)
surface.SetDrawColor( 88, 110, 110, 240 )
surface.DrawRect( 0, 0, w, h )
end
goodList.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
goodList.VBar.btnUp.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 72, 89, 89, 240 ) )
end
goodList.VBar.btnDown.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 72, 89, 89, 240 ) )
end
local BadTextEntry = vgui.Create( "DTextEntry", panel )
BadTextEntry:SetPos( offsets.x, panel:GetTall() - 100 )
BadTextEntry:SetSize( 100, 20 )
BadTextEntry:SetText( "Bad Entity class" )
BadTextEntry.OnEnter = function( self )
chat.AddText( self:GetValue() )
end
local BadAdd = vgui.Create( "DButton" , panel)
BadAdd:SetPos( offsets.x + 100, panel:GetTall() - 100 )
BadAdd:SetSize( 75,20 )
BadAdd:SetText( "Add" )
BadAdd.DoClick = function()
if BadTextEntry:GetValue() == "Bad Entity class" then return end
utils.addBadEntity( BadTextEntry:GetValue() )
updateTab()
end
BadAdd:SetTextColor( Color(255, 255, 255) )
BadAdd.Paint = function( i, w, h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 44, 55, 55, 255 ) )
draw.RoundedBox( 0, 1, 1, w-2, h-2, Color( 58, 58, 58, 255 ) )
end
local BadRemove = vgui.Create( "DButton" , panel)
BadRemove:SetPos( offsets.x, panel:GetTall() - 80 )
BadRemove:SetSize( 175, 20 )
BadRemove:SetText( "Remove selected" )
BadRemove.DoClick = function()
for k, v in pairs(badList:GetSelected()) do
local key = v:GetValue(1)
APG.cfg[ "badEnts" ].value[key] = nil
updateTab()
end
end
BadRemove:SetTextColor( Color( 255, 255, 255 ) )
BadRemove.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
local GoodTextEntry = vgui.Create( "DTextEntry", panel )
GoodTextEntry:SetPos( offsets.x, panel:GetTall() - 45 )
GoodTextEntry:SetSize( 100, 20 )
GoodTextEntry:SetText( "Good Entity class" )
GoodTextEntry.OnEnter = function( self )
chat.AddText( self:GetValue() )
end
local GoodAdd = vgui.Create( "DButton" , panel)
GoodAdd:SetPos( offsets.x + 100, panel:GetTall() - 45 )
GoodAdd:SetSize( 75,20 )
GoodAdd:SetText( "Add" )
GoodAdd.DoClick = function()
if GoodTextEntry:GetValue() == "Good Entity class" then return end
utils.addGoodEntity( GoodTextEntry:GetValue() )
updateTab()
end
local GoodRemove = vgui.Create( "DButton" , panel)
GoodRemove:SetPos( offsets.x, panel:GetTall() - 25 )
GoodRemove:SetSize( 175, 20 )
GoodRemove:SetText( "Remove selected" )
GoodRemove.DoClick = function()
for k, v in pairs(goodList:GetSelected()) do
local key = v:GetValue(1)
APG.cfg[ "unGhostingWhitelist" ].value[key] = nil
updateTab()
end
end
GoodRemove:SetTextColor( Color( 255, 255, 255 ) )
GoodRemove.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 main_color_red = Color( 96, 0, 0, 255 )
local main_color_darker = Color( 51, 91, 51, 255 )
local function setScrollerTheme( scroller )
scroller:SetSize(1, 0)
scroller:SetHideButtons(true)
function scroller:Paint( w, h )
draw.RoundedBox( 0, 0, 0, 1, h, main_color_darker )
end
function scroller.btnGrip:Paint( w, h )
draw.RoundedBox( 0, 0, 0, 1, h, main_color )
end
end
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( 800, 450 )
APG_Main:SetPos( 800 - APG_Main:GetWide() / 2, 450 - 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( 204, 204, 204, 255 ), 3 )
end
local closeButton = vgui.Create( "DButton",APG_Main )
closeButton:SetPos( APG_Main:GetWide() - 20, 4 )
closeButton:SetSize( 18, 18 )
closeButton:SetText(" ")
closeButton.DoClick = function()
APG_Main:Hide()
APG_Main:Remove()
end
closeButton.Paint = function(i,w,h)
draw.RoundedBox( 0,0,0,w,h, Color( 91, 51, 51, 255 ) )
draw.DrawText( "", "APG_sideBar_font", 1, -1, Color( 204, 204, 204, 255 ), TEXT_ALIGN_TOP )
end
local saveButton = vgui.Create( "DButton", APG_Main )
saveButton:SetPos( APG_Main:GetWide() - 117, 4 )
saveButton:SetSize( 77, 18 )
saveButton:SetText(" ")
saveButton.DoClick = function()
if not LocalPlayer():IsSuperAdmin() then return end
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 {{ user_id | 76561197972967270 }})
net.WriteData( settings, settings:len() ) -- Write the data
net.SendToServer()
showNotice(1, "APG Settings saved!")
end
saveButton.Paint = function(i,w,h)
draw.RoundedBox( 0, 0, 0, w, h, Color( 51, 91, 51, 255 ) )
draw.DrawText( "Save Settings", "APG_title2_font",w/2, 1, Color( 204, 204, 204, 255 ), 1 )
end
-- Side bar
local sidebar = vgui.Create( "DScrollPanel", APG_Main )
setScrollerTheme( sidebar:GetVBar() )
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_darker)
end
local x, y = (APG_Main:GetWide() - sidebar:GetWide()) - 19, APG_Main:GetTall() - 35
local px, py = sidebar:GetWide() + 15, 30
local first = true
local modules = APG.modules
-- Attempt to force essential modules to be enabled.
modules["home"] = true
modules["canphysgun"] = true
for k, v in next, APG.modules do
if k == "canphysgun" then continue end -- This module doesn't have UI, so it doesn't need a UI button.
local panel = vgui.Create( "DScrollPanel", APG_Main )
setScrollerTheme( panel:GetVBar() )
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, enabled and main_color or main_color_red )
local text = utils.getNiceName(k) .. " module "
draw.DrawText( text, "APG_mainPanel_font", 5, 8, Color( 189, 189, 189 ), 3 )
menu:mainSwitch( w * 0.90, (h * 0.5) - 16, enabled )
end
button.DoClick = function()
APG.modules[k] = not APG.modules[k]
end
end
local i = 0
local height = ( sidebar:GetTall()/5 )
for k, v in next, APG.modules do
if k == "canphysgun" then continue end
local button = sidebar:Add( "DButton" )
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( 48, 48, 48, 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( 51, 51, 51, 255 ) )
draw.RoundedBox( 0, w * 0.10, h * 0.60, w * 0.8, 2, main_color_darker )
end
draw.DrawText( name, "APG_sideBar_font", ( size - name:len() ) / 2, h * 0.35, Color( 189, 189, 189 ), 1)
end
if k == "home" then
button:DoClick()
end
i = i + 1
end
-- Build all the expected panels.
APGBuildHomePanel()
APGBuildMiscPanel()
APGBuildToolsPanel()
APGBuildGhostPanel()
APGBuildLagPanel()
APGBuildStackPanel()
APGBuildLogsPanel()
APGBuildNotificationPanel()
end
net.Receive( "apg_menu_s2c", openMenu )
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
if not IsValid(ent) then return false end
if not ent:GetClass() then return false end
if ent:EntIndex() < 0 then return false end
return true
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,
})
submenu:AddSpacer()
addoption( "Ghost this entity", {
icon = "icon16/tick.png",
callback = function() self:APGcmd( ent, "ghost" ) end,
})
end,
Action = function( self, ent ) end,
APGcmd = function( self, ent, cmd )
if cmd == "getownerid" then
local owner, _ = ent:CPPIGetOwner()
if IsValid( owner ) then
local id = tostring( owner:SteamID() )
local name = tostring( owner:Nick() )
SetClipboardText( id )
showNotice(0, name .. " [ " .. id .. " ]" .. " has been copied to your clipboard.")
else
showNotice(0, "\nOops, that's not a Player!")
end
elseif cmd == "getentname" then
showNotice(0, ent:GetClass())
elseif IsValid( ent ) and ent.EntIndex() then
net.Start( "apg_context_c2s" )
net.WriteString( cmd )
net.WriteEntity( ent )
net.SendToServer()
end
end,
})

View File

@@ -0,0 +1,281 @@
surface.CreateFont( "APG_title_font", {
font = "Arial",
size = 14,
weight = 700,
} )
surface.CreateFont( "APG_title2_font", {
font = "Arial",
size = 13,
weight = 700,
} )
surface.CreateFont( "APG_sideBar_font", {
font = "Arial",
size = 18,
weight = 1500,
} )
surface.CreateFont( "APG_mainPanel_font", {
font = "Arial",
size = 19,
weight = 8500,
} )
surface.CreateFont( "APG_tick_font", {
font = "Arial",
size = 29,
weight = 1900,
} )
surface.CreateFont( "APG_element_font", {
font = "Arial",
size = 17,
weight = 1300,
} )
surface.CreateFont( "APG_element2_font", {
font = "Arial",
size = 17,
weight = 2900,
} )
local utils = {}
local menu = {}
function utils.addBadEntity( class )
local found = false
for k, v in pairs ( ents.GetAll() ) do
if class == v:GetClass() then
found = true
break
end
end
if not found then
for k in pairs (scripted_ents.GetList()) do
if class == k then
found = true
break
end
end
end
APG.cfg["badEnts"].value[ class ] = found
end
function utils.addGoodEntity( class )
local found = false
for k, v in pairs ( ents.GetAll() ) do
if class == v:GetClass() then
found = true
break
end
end
if not found then
for k in pairs (scripted_ents.GetList()) do
if class == k then
found = true
break
end
end
end
APG.cfg["unGhostingWhitelist"].value[ class ] = found
end
function utils.addInvalidWhitelist( model )
local found = false
for k, v in pairs ( ents.GetAll() ) do
if model == v:GetModel() then
found = true
break
end
end
APG.cfg["invalidPhysicsWhitelist"].value[ model ] = found
end
function utils.getNiceName( str )
local nName = string.gsub(str, "^%l", string.upper)
nName = string.gsub(nName, "_", " " )
return nName
end
function menu:mainSwitch( x, y, on )
draw.RoundedBox(10, x, y, 45, 18, Color( 58, 58, 58, 255))
if on then
draw.RoundedBox(10, x + 1, y + 1, 45 - 2, 18 - 2, Color( 11, 70, 30, 255))
draw.DrawText( "ON", "APG_title_font", x + 8, y + 2, Color( 189, 189, 189 ), 3 )
draw.RoundedBox(10, x + 27, y, 18, 18, Color( 88, 88, 88, 255))
else
--draw.RoundedBox(10, x, y, 45, 18, Color( 110, 28, 38, 255))
draw.RoundedBox(10, x + 1, y + 1, 43, 16, Color( 34, 34, 34, 255))
draw.DrawText( "OFF", "APG_title_font", x + 21, y + 2, Color( 189, 189, 189), 3 )
draw.RoundedBox(10, x, y, 18, 18, Color( 88, 88, 88, 255))
end
--draw.RoundedBox(0, x+20, y, 1, 18, Color( 88, 88, 88, 255))
end
function menu:initPanel( panel, x, y, ix, iy )
self.panel = panel
self.vars = {x = x, y = y, ix = ix, iy = iy}
end
function menu:panelDone()
local old = self.vars
self.panel = {}
self.vars = {}
return old
end
function menu:grabVars()
local v = self.vars
return self.panel, v.x, v.y, v.ix, v.iy
end
function menu:switch( w, h, text, var )
local panel, x, y, ix, iy = menu:grabVars()
local button = vgui.Create("DButton", panel)
local isKey = ( type(var) == "string" )
local isFunction = ( type(var) == "function" )
button:SetPos(x, y)
button:SetSize(w, h)
button:SetText("")
button.Paint = function(slf, w, h)
local enabled = isKey and APG.cfg[ var ].value or isFunction
draw.RoundedBox(0, 0, h * 0.95, w - 5, 1, Color(250, 250, 250, 1))
draw.DrawText( text, "APG_element2_font", 0, 0, Color( 189, 189, 189), 3 )
menu:mainSwitch( w-45, 0, enabled )
end
if isKey then
button.DoClick = function()
APG.cfg[ var ].value = not APG.cfg[ var ].value
end
else
if isFunction then
button.DoClick = var
else
button:SetEnabled( false )
end
end
self.vars.x = x + ix
self.vars.y = y + iy
end
function menu:numSlider( w, h, text, var, minSlider, maxSlider, decimal )
local panel, x, y, ix, iy = menu:grabVars()
local slider = panel:Add( "DNumSlider" )
slider:SetPos( x, y )
slider:SetSize( w, h )
slider:SetText( "" )
slider:SetMin( minSlider )
slider:SetMax( maxSlider )
slider:SetDecimals( decimal )
slider:SetValue( APG.cfg[ var ].value )
slider.OnValueChanged = function( self, newValue )
APG.cfg[ var ].value = newValue
end
slider.Paint = function(slf, w, h)
draw.RoundedBox( 0, 0, h * 0.97, w - 5, 1, Color(250, 250, 250, 1 ) )
draw.DrawText( text, "APG_element2_font", 0, 0, Color( 189, 189, 189), 3 )
end
slider.Slider.Paint = function( slf, w, h)
--draw.RoundedBox(cornerRadius, x, y, width, height, color)
draw.RoundedBox( 0, 8, 9 - 1, w - 16, 1 + 2, Color( 250, 250, 250, 1))
end
slider.Slider.Knob.Paint = function(slf, w, h)
draw.RoundedBox(6, 0, 4, 10, 10, Color( 11, 70, 30, 255))
end
slider.Slider:Dock( NODOCK )
slider.Slider:SetPos( panel:GetWide() - 110, 0 )
slider.Slider:SetWide( 100 )
slider.TextArea:Dock( NODOCK )
slider.TextArea:SetPos( panel:GetWide() - 145, - 3 )
slider.TextArea.m_colText = Color(189, 189, 189)
slider.TextArea.Paint = function( self, w, h)
draw.RoundedBox(10, 0, 1, w-15, h, Color( 58, 58, 58, 255))
derma.SkinHook( "Paint", "TextEntry", self, w, h )
end
self.vars.x = x + ix
self.vars.y = y + iy
end
function menu:textEntry( w, h, text, var )
local panel, x, y, ix, iy = menu:grabVars()
local label = panel:Add( "DLabel" )
label:SetPos( x, y )
label:SetSize( w, h )
label:SetText( text )
label:SetFont("APG_element2_font")
label:SetColor( Color( 189, 189, 189) )
label.Paint = function(self, w, h)
draw.RoundedBox(0, 0, h * 0.97, w, 1, Color(250, 250, 250, 1))
end
local txtEntry = vgui.Create( "DTextEntry", panel ) -- create the form as a child of frame
txtEntry:SetPos( panel:GetWide() - 110, y-1 )
txtEntry:SetSize( 125, 20 )
txtEntry:SetText( "custom" )
txtEntry.OnEnter = function( self )
end
self.vars.x = x + ix
self.vars.y = y + iy
end
function menu:comboBox( w, h, text, var, content )
local panel, x, y, ix, iy = menu:grabVars()
local label = panel:Add( "DLabel" )
label:SetPos( x, y )
label:SetSize( w, h )
label:SetText( text )
label:SetFont("APG_element2_font")
label:SetColor( Color( 189, 189, 189) )
label.Paint = function(self, w, h)
draw.RoundedBox(0, 0, h * 0.97, w, 1, Color(250, 250, 250, 1))
end
local comboBox = vgui.Create( "DComboBox", panel )
comboBox:SetPos( panel:GetWide() - 145, y-2 )
comboBox:SetSize( 125, 20 )
comboBox:SetValue( APG.cfg[var].value )
for k, v in pairs ( content ) do
comboBox:AddChoice(v)
end
comboBox.OnSelect = function( panel, index, value )
APG.cfg[var].value = value
end
comboBox.Paint = function(i, w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(58, 58, 58, 240))
end
comboBox:SetTextColor(Color( 189, 189, 189))
local o_OpenMenu = comboBox.OpenMenu
comboBox.OpenMenu = function( pControlOpener )
o_OpenMenu(pControlOpener)
comboBox.Menu.Paint = function (i, w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(58, 58, 58, 240))
end
end
self.vars.x = x + ix
self.vars.y = y + iy
end
return {utils = utils, menu = menu}

View File

@@ -0,0 +1,97 @@
--[[------------------------------------------
============================
Physgun Permissions Module
============================
Developer informations :
---------------------------------
Used variables :
]]--------------------------------------------
local mod = "canphysgun"
--[[ Entity pickup part ]]
local GM = GM or GAMEMODE
APG._PhysgunPickup = APG._PhysgunPickup or GM.PhysgunPickup
APG.hookAdd(mod, "PhysgunPickup","APG_PhysgunPickup", function(ply, ent)
if not APG.isBadEnt( ent ) then return end
if not APG.canPhysGun( ent, ply ) then return false end
end)
function GM:PhysgunPickup( ply, ent )
local canPickup = APG._PhysgunPickup( self, ply, ent )
hook.Run("APG_PostPhysgunPickup", ply, ent, canPickup)
if not canPickup then return canPickup end -- Assumed as `false` but returning just incase.
ent.APG_HeldBy = ent.APG_HeldBy or {}
ent.APG_HeldBy.plys = ent.APG_HeldBy.plys or {}
ent.APG_Picked = true
ent.APG_Frozen = false
if ent.APG_HeldBy and ent.APG_HeldBy.plys and not ent.APG_HeldBy.plys[sid] then
local HasHolder = (#ent.APG_HeldBy.plys > 0)
local HeldByLast = ent.APG_HeldBy.last
if HasHolder then
if HeldByLast then
for _, ply in next, ent.APG_HeldBy.plys do
APG.ForcePlayerDrop(ply, ent)
end
else
return false
end
end
end
ent.APG_HeldBy.plys[ply:SteamID()] = ply
ent.APG_HeldBy.last = {ply = ply, id = ply:SteamID()}
ply.APG_CurrentlyHolding = ent
if APG.cfg["blockContraptionMove"].value then
local count = 0
local noFrozen = true
for _,v in next, constraint.GetAllConstrainedEntities(ent) do
count = count + 1
if v.APG_Frozen then
noFrozen = false
break
end
end
if noFrozen and ( count > 1 ) then
timer.Simple(0, function()
APG.freezeIt(ent, true)
end)
end
end
return canPickup -- Assumed as `true`
end
--[[ PhysGun Drop and Anti Throw Props ]]
APG.hookAdd(mod, "PhysgunDrop", "APG_physGunDrop", function( ply, ent )
ent.APG_HeldBy = ent.APG_HeldBy or {}
if ent.APG_HeldBy.plys then
ent.APG_HeldBy.plys[ply:SteamID()] = nil -- Remove the holder.
end
ply.APG_CurrentlyHolding = nil
if #ent.APG_HeldBy > 0 then return end
ent.APG_Picked = false
if APG.isBadEnt( ent ) and not APG.cfg["allowPK"].value then
APG.killVelocity(ent,true,false,true) -- Extend to constrained props, and wake target.
end
end)
--[[ Load hooks and timers ]]
APG.updateHooks(mod)
APG.updateTimers(mod)

View File

@@ -0,0 +1,403 @@
--[[------------------------------------------
============================
GHOSTING/UNGHOSTING MODULE
============================
Developer informations :
---------------------------------
Used variables :
ghostColor = { value = Color(34, 34, 34, 220), desc = "Color set on ghosted props" }
badEnts = {
value = {
["prop_physics"] = true,
["wire_"] = false,
["gmod_"] = false },
desc = "Entities to ghost/control/secure"}
alwaysFrozen = { value = false, desc = "Set to true to auto freeze props on physgun drop" }
]]--------------------------------------------
local mod = "ghosting"
--[[ Override base functions ]]
local ENT = FindMetaTable( "Entity" )
APG._SetCollisionGroup = APG._SetCollisionGroup or ENT.SetCollisionGroup
function ENT:SetCollisionGroup( group )
local group = group
local isBadEnt = APG.isBadEnt( self )
local hasValidOwner = APG.getOwner( self )
local groupIsNone = group == COLLISION_GROUP_NONE
local isNotFrozen = not self.APG_Frozen
local isWhitelistedEnt = APG.isWhitelistedEnt(self)
local shouldMakeInteractable = isBadEnt and hasValidOwner and groupIsNone and isNotFrozen and not isWhitelistedEnt
if shouldMakeInteractable then
group = COLLISION_GROUP_INTERACTIVE
end
APG._SetCollisionGroup( self, group )
end
APG._SetColor = APG._SetColor or ENT.SetColor
function ENT:SetColor( color, ... )
local color = color
local r, g, b, a
if type(color) == "number" then
color = Color(color, select(1, ...) or 255, select(2, ...) or 255, select(3, ...) or 255)
elseif type(color) == "table" and not IsColor(color) then
r = color.r or 255
g = color.g or 255
b = color.b or 255
a = color.a or 255
color = Color(r, g, b, a)
end
if not IsColor(color) then
ErrorNoHalt( "Invalid color passed to SetColor!\nThis error prevents stuff from turning purple/pink." )
else
APG._SetColor( self, color )
end
end
local PhysObj = FindMetaTable( "PhysObj" )
APG._EnableMotion = APG._EnableMotion or PhysObj.EnableMotion
function PhysObj:EnableMotion( bool )
local ent = self:GetEntity()
if APG.isBadEnt( ent ) and APG.getOwner( ent ) then
ent.APG_Frozen = not bool
if not ent.APG_Frozen then
ent:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
end
end
return APG._EnableMotion( self, bool )
end
function APG.isTrap( ent, fullscan )
local check = false
local center = ent:LocalToWorld( ent:OBBCenter() )
local bRadius = ent:BoundingRadius()
local cache = {}
for _,v in next, ents.FindInSphere( center, bRadius ) do
if v:IsPlayer() and v:Alive() then
local pos = v:GetPos()
local trace = { start = pos, endpos = pos, filter = v }
local tr = util.TraceEntity( trace, v )
if tr.Entity == ent then
if fullscan then
table.insert( cache, v )
else
check = v
end
end
elseif APG.IsVehicle(v) then
-- Check if the distance between the spheres centers is less than the sum of their radius.
local vCenter = v:LocalToWorld( v:OBBCenter() )
if center:Distance( vCenter ) < v:BoundingRadius() then
check = v
end
end
if check then break end
end
if fullscan and ( #cache > 0 ) then
return cache
else
return check or false
end
end
function APG.entGhost( ent, noCollide, enforce )
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
if APG.cfg["vehAntiGhost"].value and APG.IsVehicle( ent ) then return end
if ent.jailWall then return end
if not ent.APG_Ghosted then
ent.FPPAntiSpamIsGhosted = nil -- Override FPP Ghosting.
DropEntityIfHeld( ent )
ent:ForcePlayerDrop()
ent.APG_oldCollisionGroup = ent:GetCollisionGroup()
if not enforce then
-- If and old collision group was set get it.
if ent.OldCollisionGroup then ent.APG_oldCollisionGroup = ent.OldCollisionGroup end -- For FPP
if ent.DPP_oldCollision then ent.APG_oldCollisionGroup = ent.DPP_oldCollision end -- For DPP
ent.OldCollisionGroup = nil
ent.DPP_oldCollision = nil
end
ent.APG_Ghosted = true
if APG.cfg["ghostColorToggle"].value then
timer.Simple(0, function()
if not IsValid( ent ) then return end
if not ent.APG_oldColor then
ent.APG_oldColor = ent:GetColor()
if not enforce then
if ent.OldColor then ent.APG_oldColor = ent.OldColor end -- For FPP
if ent.__DPPColor then ent.APG_oldColor = ent.__DPPColor end -- For DPP
ent.OldColor = nil
ent.__DPPColor = nil
end
end
ent:SetColor( APG.cfg[ "ghostColor" ].value )
end)
end
ent.APG_oldRenderMode = ent:GetRenderMode()
ent:SetRenderMode( RENDERMODE_TRANSALPHA )
ent:DrawShadow( false )
if noCollide then
ent:SetCollisionGroup( COLLISION_GROUP_WORLD )
else
ent:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER )
end
do -- Fix magic surfing
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
phys:EnableCollisions( false )
timer.Simple(0, function()
phys:EnableCollisions( true )
end)
end
end
ent:CollisionRulesChanged()
end
end
function APG.entUnGhost( ent, ply, failmsg )
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
if ent.APG_Picked or (ent.APG_HeldBy and #ent.APG_HeldBy > 1) then return end
if ent.APG_Ghosted == true then
ent.APG_isTrap = APG.isTrap(ent)
if not ent.APG_isTrap then
ent.APG_Ghosted = false
ent:DrawShadow( true )
ent:SetRenderMode( ent.APG_oldRenderMode or RENDERMODE_NORMAL )
if APG.cfg["ghostColorToggle"].value then
ent:SetColor( ent.APG_oldColor or Color( 255, 255, 255, 255) )
end
ent.APG_oldColor = false
local newCollisionGroup = COLLISION_GROUP_INTERACTIVE
if APG.isWhitelistedEnt(ent) then
newCollisionGroup = ent.APG_spawnedCollisionGroup
elseif ent.APG_oldCollisionGroup == COLLISION_GROUP_WORLD then
newCollisionGroup = ent.APG_oldCollisionGroup
elseif ent.APG_Frozen then
newCollisionGroup = COLLISION_GROUP_NONE
end
ent:SetCollisionGroup( newCollisionGroup )
ent:CollisionRulesChanged()
return true
else
APG.notify( false, 1, ply, failmsg or "There is something in this prop!" )
ent:SetCollisionGroup( COLLISION_GROUP_WORLD )
ent:CollisionRulesChanged()
return false
end
end
end
function APG.ConstraintApply( ent, callback )
local constrained = constraint.GetAllConstrainedEntities(ent)
for _,v in next, constrained do
if IsValid( v ) and v ~= ent then
callback( v )
end
end
end
--[[------------------------------------------
Hooks/Timers
]]--------------------------------------------
APG.hookAdd( mod, "APG_PostPhysgunPickup", "APG_makeGhost", function( ply, ent, canPickup )
if not canPickup then return end
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
ent.APG_Picked = true
if not APG.cfg[ "allowPK" ].value then
APG.entGhost( ent )
APG.ConstraintApply( ent, function( _ent )
if not _ent.APG_Frozen then
_ent.APG_Picked = true
APG.entGhost( _ent )
end
end) -- Apply ghost to all constrained ents
end
end)
APG.hookAdd( mod, "PlayerUnfrozeObject", "APG_unFreezeInteract", function (ply, ent, pObj)
if not APG.canPhysGun( ent, ply, "APG_unFreezeInteract" ) then return end
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
if APG.cfg[ "alwaysFrozen" ].value then
return false
end -- Do not unfreeze if Always Frozen is enabled !
if ent:GetCollisionGroup( ) ~= COLLISION_GROUP_WORLD then
ent:SetCollisionGroup( COLLISION_GROUP_INTERACTIVE )
end
end)
APG.dJobRegister( "unghost", 0.1, 50, function( ent )
if IsValid(ent) then
APG.entUnGhost( ent )
end
end)
APG.hookAdd( mod, "PhysgunDrop", "APG_pGunDropUnghost", function( ply, ent )
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
ent.APG_Picked = false
if APG.cfg[ "alwaysFrozen" ].value then
APG.freezeIt( ent )
end
APG.entUnGhost( ent, ply )
APG.ConstraintApply( ent, function( _ent )
_ent.APG_Picked = false
APG.startDJob( "unghost", _ent )
end) -- Apply unghost to all constrained ents
end)
local function SafeSetCollisionGroup( ent, colgroup, pObj )
-- If the entity is being held by a player or is ghosted abort.
if ent:IsPlayerHolding() then return end
if ent.APG_Ghosted then return end
if pObj then pObj:Sleep() end
ent:SetCollisionGroup(colgroup)
ent:CollisionRulesChanged()
end
APG.hookAdd( mod, "OnEntityCreated", "APG_noCollideOnCreate", function( ent )
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
if not IsValid( ent ) then return end
if ent:GetClass() == "gmod_hands" then return end -- Fix shadow glitch
ent.APG_spawnedCollisionGroup = ent:GetCollisionGroup() -- have to set it before it's ghosted
timer.Simple( 0, function()
if not ent then return end
if not ent:IsSolid() then return end -- Don't ghost ghosts.
local spawnedEnt = tostring(ent)
local owner = ""
if APG.getOwner(ent) ~= nil then -- incase getowner return's nil (like on reloading)
owner = APG.getOwner(ent):Nick()
else
owner = "console"
end
APG.entGhost( ent )
end)
timer.Simple( 0, function()
if not ent then return end
if not ent:IsSolid() then return end -- Don't ghost ghosts.
local owner = APG.getOwner( ent )
DropEntityIfHeld( ent )
ent:ForcePlayerDrop()
if IsValid( owner ) and owner:IsPlayer() then
local pObj = ent:GetPhysicsObject()
if IsValid(pObj) then
if APG.cfg[ "alwaysFrozen" ].value then
ent.APG_Frozen = true
pObj:EnableMotion( false )
elseif pObj:IsMoveable() then
ent.APG_Frozen = false
SafeSetCollisionGroup( ent, COLLISION_GROUP_INTERACTIVE )
end
end
end
APG.startDJob( "unghost", ent )
end)
end)
local BlockedProperties = { "collision", "persist", "editentity", "drive", "ignite", "statue" }
APG.hookAdd( mod, "CanProperty", "APG_canProperty", function(ply, property, ent)
local property = tostring( property )
if ( table.HasValue(BlockedProperties, property) and ent.APG_Ghosted ) then
APG.notify( false, 1, ply, "Cannot set", property, "properties on ghosted entities!" )
return false
end
end)
-- Custom Hooks --
local function checkDoor(ply, ent)
local isTrap = APG.isTrap(ent, true)
if isTrap and istable(isTrap) then
ent.APG_Ghosted = true
ent:SetCollisionGroup(COLLISION_GROUP_WORLD)
for _,v in next, isTrap do
if v:IsPlayer() then
local push = v:GetForward()
push = push * 1200
push.z = 60
v:SetVelocity(push)
end
end
timer.Simple(1, function()
if IsValid(ply) and IsValid(ent) then
ent.APG_Ghosted = false
ent:oldFadeDeactivate()
ent:SetCollisionGroup( COLLISION_GROUP_INTERACTIVE )
if IsValid(isTrap) then
APG.notify( false, 1, ply, "Unable to unstuck objects from fading door!" )
APG.entGhost(ent)
end
end
end)
end
end
APG.hookAdd(mod, "APG.FadingDoorToggle", "APG_FadingDoor", function(ent, isFading)
if APG.isBadEnt(ent) and APG.cfg["fadingDoorGhosting"].value then
local ply = APG.getOwner( ent )
if (IsValid(ply) and ply:IsPlayer() and not isFading) then
-- Delay slightly, this is needed to wait for other things happen before it works.
timer.Simple(0.001, function()
checkDoor(ply, ent)
end)
end
end
end)
--[[ Load hooks and timers ]]
APG.updateHooks(mod)
APG.updateTimers(mod)

View File

@@ -0,0 +1 @@
-- This is a dummy file, for APGs home page! (As the home page is built like a module.)

View File

@@ -0,0 +1,184 @@
--[[------------------------------------------
============================
LAG DETECTION MODULE
============================
Developer informations :
---------------------------------
Used variables :
lagTrigger = { value = 75, desc = "% difference between current lag and average lag."}
lagsCount = { value = 8, desc = "Number of consectuives laggy frames in order to run a cleanup."}
bigLag = { value = 2, desc = "Time (seconds) between 2 frames to trigger a cleanup"}
lagFunc = { value = "cleanUp_unfrozen", desc = "Function ran on lag detected" }
lagFuncTime = { value = 20, desc = "Time (seconds) between 2 cleanup (avoid spam)"}
Ready to hook :
APG_lagDetected = Ran on lag detected by the server.
Example : hook.Add( "APG_lagDetected", "myLagDetectHook", function() print("[APG] Lag detected (printed from my very own hook)") end)
]]--------------------------------------------
local mod = "lag_detection"
local table = table
--[[ Lag fixing functions ]]
local lagFix = {
cleanup_all = function( ) APG.cleanUp( "all" ) end,
cleanup_unfrozen = function( ) APG.cleanUp( "unfrozen" ) end,
ghost_unfrozen = APG.ghostThemAll,
freeze_unfrozen = APG.freezeProps,
smart_cleanup = APG.smartCleanup,
custom_function = APG.customFunc,
}
--[[ Lag detection vars ]]
local lastTick = 0
local tickDelta = 0
local tickRate = 0
local lagCount = 0
local lagThreshold = math.huge
local processHault = false
local processFunc = false
local processExecs = 0
local sampleData = {}
local sampleCount = 0
local function addSample( data )
local index = (sampleCount%66)+1
local data = tonumber(data)
sampleCount = sampleCount + 1
if sampleCount >= 66 then
sampleCount = 0
end
table.insert(sampleData, index, data)
end
function APG.resetLag(dontResetData)
lastTick = 0
tickDelta = 0
lagCount = 0
lagThreshold = tickRate
processHault = false
processFunc = false
processExecs = 0
end
function APG.calculateLagAverage()
local count = 0
local total = 0
local sampleData = sampleData
for _, v in next, sampleData do
total = total + v
count = count + 1
end
if count < 12 then
return false -- Not enough data, yet.
end
return (total/count)
end
hook.Add("Think", "APG_initLagDetection", function()
tickRate = FrameTime()
lagThreshold = tickRate
hook.Remove("Think", "APG_initLagDetection")
end)
APG.timerAdd( mod, "APG_process", 3, 0, function()
if not APG.modules[ mod ] then return end
if sampleCount < 12 or tickDelta < lagThreshold then
addSample(tickDelta)
end
local average = APG.calculateLagAverage()
if average then
lagThreshold = average * ( 1 + ( APG.cfg[ "lagTrigger" ].value / 100 ) )
end
processExecs = 0
end)
APG.hookAdd( mod, "Tick", "APG_lagDetection", function()
if not APG.modules[ mod ] then return end
local sysTime = SysTime()
tickDelta = sysTime - lastTick
if lagThreshold > tickRate and tickDelta >= lagThreshold then
lagCount = lagCount + 1
if (lagCount >= APG.cfg[ "lagsCount" ].value) or ( tickDelta > APG.cfg[ "bigLag" ].value ) then
lagCount = 0
if ( not processHault ) and ( not processFunc ) then
processHault = true
timer.Simple(APG.cfg["lagFuncTime"].value, function()
processHault = false
end)
hook.Run( "APG_lagDetected" )
end
end
else
lagCount = lagCount - 0.5
if lagCount < 0 then
lagCount = 0
end
end
lastTick = sysTime
end)
--[[ Utils ]]
hook.Remove( "APG_lagDetected", "main") -- Sometimes, I dream about cheese.
hook.Add( "APG_lagDetected", "main", function()
if not APG then return end
APG.notify( true, 2, APG.cfg["notifyLevel"].value, "!WARNING LAG DETECTED!" )
local funcName = APG.cfg[ "lagFunc" ].value
local func = lagFix[ funcName ]
if not func then return end
hook.Run("APG_logsLagDetected") -- put it here so it doesn't spam
processFunc = true
func(false, function()
processFunc = false
processExecs = processExecs + 1
end)
if processExecs > 3 then
-- If the lag cleanup process runs more then 3 times in 3 seconds, then
-- reset our data.
APG.resetLag()
end
end)
--[[ Load hooks and timers ]]
APG.updateHooks(mod)
APG.updateTimers(mod)

View File

@@ -0,0 +1,64 @@
local mod = "logs"
if GAS then
if APG.modules[ mod ] and GAS.Logging then
local MODULE = GAS.Logging:MODULE()
MODULE.Category = "APG"
MODULE.Name = "Lag Detection"
MODULE.Colour = Color(255,0,0)
MODULE:Setup(function()
MODULE:Hook("APG_logsLagDetected", "APG.logs.lagDetected", function()
if not APG.cfg["logLagDetected"].value then return end
MODULE:Log("Lag detected, running lag function {1} to prevent further lag.", GAS.Logging:Highlight(APG.cfg["lagFunc"].value))
end)
end)
GAS.Logging:AddModule(MODULE)
local MODULE = GAS.Logging:MODULE()
MODULE.Category = "APG"
MODULE.Name = "Crash Attempts"
MODULE.Colour = Color(255,0,0)
MODULE:Setup(function()
MODULE:Hook("APG_stackCrashAttempt", "APG.logs.stackCrashAttempt", function(ply, count)
if not APG.cfg["logStackCrashAttempt"].value then return end
MODULE:Log("{1} stacked {2} props and triggered a detection.", GAS.Logging:FormatPlayer(ply), GAS.Logging:Highlight(count))
end)
end)
GAS.Logging:AddModule(MODULE)
end
end
if plogs then
if APG.modules[ mod ] and plogs.Register then
plogs.Register("APG", true, Color(255,100,0))
plogs.AddHook("APG_logsLagDetected", function()
if not APG.cfg["logLagDetected"].value then return end
plogs.PlayerLog("console", "APG", "Lag detected, running lag fix function " .. APG.cfg["lagFunc"].value .. " to prevent further lag.")
end)
plogs.AddHook("APG_stackCrashAttempt", function(ply, count)
if not APG.cfg["logStackCrashAttempt"].value then return end
plogs.PlayerLog(ply, "APG", ply:NameID() .. " stacked " .. count .. " props and triggered a detection.", {
["Name"] = ply:Name(),
["SteamID"] = ply:SteamID()
})
end)
end
end

View File

@@ -0,0 +1,261 @@
--[[------------------------------------------
============================
MISCELLANEOUS MODULE
============================
Developer informations :
---------------------------------
Used variables :
vehDamage = { value = true, desc = "True to enable vehicles damages, false to disable." }
vehNoCollide = { value = false, desc = "True to disable collisions between vehicles and players"}
autoFreeze = { value = false, desc = "Freeze every unfrozen prop each X seconds" }
autoFreezeTime = { value = 120, desc = "Auto freeze timer (seconds)"}
]]--------------------------------------------
local mod = "misc"
--[[ Helper functions ]]
local timerSimple = timer.Simple
local function isVehDamage( dmg, atk, ent )
if not IsValid( ent ) then return false end
if dmg:GetDamageType() == DMG_VEHICLE or APG.IsVehicle( atk ) or APG.IsVehicle( ent ) then
return true
end
return false
end
local function getPhys(ent)
local phys = ent.GetPhysicsObject and ent:GetPhysicsObject() or false
return ( phys and IsValid(phys) ) and phys or false
end
local function wait(callback)
timerSimple(0.003, callback)
end
--[[ No Collide vehicles on spawn ]]
APG.hookAdd( mod,"OnEntityCreated", "APG_noCollideVeh", function( ent )
timerSimple(0.03, function()
if APG.cfg[ "vehNoCollide" ].value and APG.IsVehicle( ent ) then
ent:SetCollisionGroup( COLLISION_GROUP_WEAPON )
end
end)
end)
--[[ Disable prop damage ]]
APG.hookAdd( mod, "EntityTakeDamage","APG_noPropDmg", function( target, dmg )
if ( not APG.cfg[ "allowPK" ].value ) then -- Check if prop kill is allowed, before checking anything else.
local atk, ent = dmg:GetAttacker(), dmg:GetInflictor()
if APG.isBadEnt( ent ) or dmg:GetDamageType() == DMG_CRUSH or ( APG.cfg[ "vehDamage" ].value and isVehDamage( dmg, atk, ent ) ) then
dmg:SetDamage(0)
return true
-- ^ Returning true overrides and blocks all related damage, it also prevents the hook from running any further preventing unintentional damage from other addons.
end
end
end)
--[[ Remove Invalid Physics ]]
APG.hookAdd( mod, "OnEntityCreated", "APG_removeInvalidPhysics", function( ent )
if ( not APG.cfg[ "removeInvalidPhysics" ].value ) then return end
timerSimple(0, function()
if not IsValid( ent ) then return end
local model = ent:GetModel()
local owner = APG.getOwner( ent )
local phys = ent:GetPhysicsObject()
if IsValid( owner ) and owner:IsPlayer() then
if ( not model ) or string.lower(string.sub(model, 1, 6)) ~= "models" then
SafeRemoveEntity( ent )
return
end
if ( not IsValid( physObj ) ) and ( not APG.cfg["invalidPhysicsWhitelist"].value[model] ) then
SafeRemoveEntity( ent )
end
end
end)
end)
--[[ Block Physgun Reload ]]
APG.hookAdd( mod, "OnPhysgunReload", "APG_blockPhysgunReload", function( _, ply )
if APG.cfg[ "blockPhysgunReload" ].value then
return false
end
end)
--[[ Block Gravitygun Throwing ]]
APG.hookAdd( mod, "GravGunOnDropped", "APG_blockGravGunThrow", function(ply, ent)
if ( not APG.cfg["blockGravGunThrow"].value ) then return end
APG.killVelocity(ent, false, false, true)
end)
--[[ Auto prop freeze ]]
APG.timerAdd( mod, "APG_autoFreeze", APG.cfg[ "autoFreezeTime" ].value, 0, function()
if APG.cfg[ "autoFreeze" ].value then
APG.freezeProps()
end
end)
--[[ Fading door management ]]
APG.hookAdd(mod, "CanTool", "APG_fadingDoorTool", function(ply, tr, tool)
if IsValid(tr.Entity) and tr.Entity.APG_Ghosted then
APG.notify(false, 1, ply, "Cannot use tool on ghosted entity!")
return false
end
if APG.cfg["fadingDoorHook"].value and tool == "fading_door" then
timerSimple(0, function()
if IsValid(tr.Entity) and not tr.Entity:IsPlayer() then
local ent = tr.Entity
if not IsValid(ent) then return end
if not ent.isFadingDoor then return end
local state = ent.fadeActive
if state then
ent:fadeDeactivate()
end
ent.oldFadeActivate = ent.oldFadeActivate or ent.fadeActivate
ent.oldFadeDeactivate = ent.oldFadeDeactivate or ent.fadeDeactivate
function ent:fadeActivate()
if hook.Run("APG.FadingDoorToggle", self, true, ply) then return end
ent:oldFadeActivate()
end
function ent:fadeDeactivate()
if hook.Run("APG.FadingDoorToggle", self, false, ply) then return end
ent:oldFadeDeactivate()
ent:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
end
if state then
ent:fadeActivate()
end
end
end)
end
end)
APG.hookAdd(mod, "APG.FadingDoorToggle", "init", function(ent, state, ply)
if ent.APG_Ghosted then
APG.entUnGhost(ent, ply, "Your fading door is ghosted! (" .. ( ent.GetModel and ent:GetModel() or "???" ) .. ")")
return true
end
ent:ForcePlayerDrop()
local phys = getPhys(ent)
if phys then
phys:EnableMotion(false)
end
end)
--[[ Set sv_turbophysics? ]]--
if APG.cfg[ "touchServerSettings" ].value then
if APG.cfg[ "setTurboPhysics" ].value then
RunConsoleCommand('sv_turbophysics', '1')
else
RunConsoleCommand('sv_turbophysics', '0')
end
end
--[[ FRZR9K ]]--
local zero = Vector(0,0,0)
local function sleepyPhys(phys)
if not phys:IsAsleep() then
local vel = phys:GetVelocity()
if vel:Distance(zero) <= 23 then
phys:Sleep()
end
end
end
APG.timerAdd(mod, "frzr9k-p1", 5, 0, function(ent)
if APG.cfg["sleepyPhys"].value then
for _, v in next, ents.GetAll() do
if v.APG_Frozen == false then
local phys = getPhys( v )
if APG.isBadEnt( v ) and phys then
sleepyPhys( phys )
end
end
end
end
end)
-- Collision Monitoring --
local function collcall(ent, data)
local hit = data.HitObject
local mep = data.PhysObject
if IsValid(ent) and IsValid(hit) and IsValid(mep) then
ent["frzr9k"] = ent["frzr9k"] or {}
local obj = ent["frzr9k"]
obj.Collisions = (obj.Collisions or 0) + 1
obj.CollisionTime = obj.CollisionTime or (CurTime() + 5)
obj.LastCollision = CurTime()
if obj.Collisions > 23 then
obj.Collisions = 0
for _,e in next, {mep, hit} do
e:SetVelocityInstantaneous(Vector(0,0,0))
e:Sleep()
end
end
if obj.CollisionTime < obj.LastCollision then
local subtract = 1
local mem = obj.CollisionTime
while true do
mem = mem + 5
subtract = subtract + 1
if mem >= obj.LastCollision then
break
end
end
obj.Collisions = (obj.Collisions - subtract)
obj.Collisions = (obj.Collisions > 1) and obj.Collisions or 1
obj.CollisionTime = (CurTime() + 5)
end
ent["frzr9k"] = obj
end
end
APG.hookAdd(mod, "OnEntityCreated", "frzr9k-p2", function(ent)
if APG.cfg["sleepyPhys"].value and APG.cfg["sleepyPhysHook"].value then
wait(function()
if APG.isBadEnt( ent ) and getPhys( ent ) then
ent:AddCallback("PhysicsCollide", collcall)
end
end)
end
end)
if APG.cfg[ "physGunMaxRange" ].value then
RunConsoleCommand("physgun_maxrange", APG.cfg["physGunMaxRange"].value) -- Can't run SetInt on a convar that wasn't made in lua
end
--[[------------------------------------------
Load hooks and timers
]]--------------------------------------------
APG.updateHooks(mod)
APG.updateTimers(mod)

View File

@@ -0,0 +1,95 @@
--[[------------------------------------------
============================
NOTIFICATION MODULE
============================
]]--------------------------------------------
local mod = "notification"
function APG.notify(log, level, target, ... ) -- The most advanced notification function in the world.
local log = log -- Should the message be logged?
local level = level -- The level of the error.
local target = target -- Whos ist this message meant for?
local msg = {...} -- Pack the arguments in a table.
local outMsg = "" -- Concat the message into this variable.
local isConsole = ( target == "console" ) -- Is this message meant for the console
if type(level) == "string" then
level = string.lower( level )
level = ( level == "notice" and 0 ) or ( level == "warning" and 1 ) or ( level == "alert" and 2 )
end
if target then
if type(target) == "string" then
(({
["all"] = function()
target = player.GetHumans()
end,
["admin"] = function()
local data = player.GetHumans()
for k, v in next, data do
if not v:IsAdmin() then
data[k] = nil
end
end
target = data
end,
["superadmin"] = function()
local data = player.GetHumans()
for k, v in next, data do
if not v:IsSuperAdmin() then
data[k] = nil
end
end
target = data
end,
["console"] = function()
-- Just send it to the logs without actually giving out a message.
end,
})[target])()
else
if IsEntity( target ) and IsValid( target ) and target:IsPlayer() then
target = { target }
end
end
end
local outMsg = ""
for _, v in next, msg do
local data = v and tostring(v) or ""
if string.len( outMsg ) == 0 then
outMsg = data
else
outMsg = outMsg .. " " .. data
end
end
outMsg = string.Trim( outMsg )
if string.len( outMsg ) > 0 and ( log or isConsole ) then
ServerLog("[APG] " .. outMsg .. "\n")
if isConsole then
MsgC( Color( 72, 216, 41 ), "[APG]", Color( 255, 255, 255 ), outMsg)
return true
end
end
if type(target) ~= "table" then return false end
for _, v in next, target do
if not isentity(v) then continue end
if not IsValid(v) then continue end
net.Start("apg_notice_s2c")
net.WriteUInt(level, 3)
net.WriteString(outMsg)
net.Send(v)
end
return true
end

View File

@@ -0,0 +1,112 @@
--[[------------------------------------------
============================
STACK DETECTION MODULE
============================
Developer informations :
---------------------------------
Used variables :
stackMax = { value = 15, desc = "Max amount of entities stacked on a small area"}
stackArea = { value = 15, desc = "Sphere radius for stack detection (gmod units)"}
fading
]]--------------------------------------------
local mod = "stack_detection"
local SafeRemoveEntity = SafeRemoveEntity
function APG.checkStack( ent, pcount )
if not APG.isBadEnt( ent ) then return end
local efound = ents.FindInSphere(ent:GetPos(), APG.cfg["stackArea"].value )
local count = 0
local max_count = APG.cfg["stackMax"].value
for k, v in pairs (efound) do
if APG.isBadEnt( v ) and APG.getOwner( v ) then
count = count + 1
end
end
if count >= (pcount or max_count) then
local owner, _ = ent:CPPIGetOwner()
ent:Remove()
if not owner.APG_CantPickup then
APG.blockPickup( owner, 10 )
APG.notify( false, 2, owner, "You tried to unfreeze a stack of " .. count .. " props! >:(" )
hook.Run("APG_stackCrashAttempt", owner, count)
APG.notify( true, 2, APG.cfg["notifyLevel"].value, owner:Nick() .. " [" .. owner:SteamID() .. "]" .. " tried to unfreeze a stack of " .. count .. " props!" )
end
end
end
APG.hookAdd(mod, "PhysgunPickup", "APG_stackCheck",function(ply, ent)
if not APG.canPhysGun( ent, ply, "APG_stackCheck" ) then return end
if not APG.modules[ mod ] or not APG.isBadEnt( ent ) then return end
APG.checkStack( ent )
end)
-- Requires Fading Door Hooks --
local notify = false
local curTime = 0
local lastCall = 0
APG.hookAdd(mod, "APG.FadingDoorToggle", "APG_fadingDoorStackCheck", function(ent, faded)
curTime = CurTime()
if IsValid(ent) and faded then
local ply = APG.getOwner(ent)
local pos = ent:GetPos()
local doors = {}
local count = 1 -- Start at 1 to include the original fading door
for _,v in next, ents.FindInSphere(pos, APG.cfg["stackArea"].value) do
if v ~= ent and IsValid(v) and v.isFadingDoor and APG.getOwner(v) == ply then
table.insert(doors, v)
count = count + 1
end
end
if count >= APG.cfg["fadingDoorStackMax"].value then
notify = true
for _,v in next, doors do
SafeRemoveEntity(v)
end
end
if curTime > lastCall then
if notify and APG.cfg["fadingDoorStackNotify"].value then
notify = false
APG.notification(ply:Nick() .. " had a stack of " .. count .. " fading doors that were removed.", APG.cfg["notifyLevel"].value, 2)
APG.notification("Some of your fading doors were removed.", ply)
end
end
end
lastCall = curTime + 0.001
end)
--[[ Stacker Exploit Quick Fix ]]
hook.Add( "InitPostEntity", "APG_InitStackFix", function()
timer.Simple(60, function()
local TOOL = weapons.GetStored("gmod_tool")["Tool"][ "stacker" ] or weapons.GetStored("gmod_tool")["Tool"][ "stacker_v2" ]
if not TOOL then return end
-- Stacker improved (beta) fixed this by setting a maximum number of constraints
-- See : https://git.io/vPvJK
APG.dJobRegister( "weld", 0.3, 20, function( sents )
if not IsValid( sents[1] ) or not IsValid( sents[2]) then return end
constraint.Weld( sents[1], sents[2], 0, 0, 0 )
end)
function TOOL:ApplyWeld( lastEnt, newEnt )
if ( not self:ShouldForceWeld() and not self:ShouldApplyWeld() ) then return end
APG.startDJob( "weld", {lastEnt, newEnt} )
end
end)
end)
--[[ Load hooks and timers ]]
APG.updateHooks(mod)
APG.updateTimers(mod)

View File

@@ -0,0 +1,128 @@
--[[------------------------------------------
============================
TOOLS MODULE
============================
Developer informations :
---------------------------------
Used variables :
]]--------------------------------------------
local mod = "tools"
function APG.canTool( ply, tool, ent )
if IsValid(ent) then
if ent.ToolDisabled == false then
return false
end
if ent.CPPICanTool then
return ent:CPPICanTool(ply, tool)
end -- Let CPPI handle things from here.
end
if APG.cfg[ "checkCanTool" ].value and ply.APG_CantPickup == true then-- If we can't pickup we can't tool either.
return false
end
return 0 -- return 0 so if all of the check's don't return anything then it doesn't default to disabling toolgun.
end
--[[ APG CanTool Check ]]
APG.hookAdd(mod, "CanTool", "APG_ToolMain", function(ply, tr, tool)
if not APG.canTool(ply, tool, tr.Entity) then
return false
end
end)
--[[ Tool Spam Control ]]
APG.hookAdd(mod, "CanTool", "APG_ToolSpamControl", function(ply)
if not APG.cfg[ "blockToolSpam" ].value then return end
ply.APG_ToolCTRL = ply.APG_ToolCTRL or {}
local ply = ply
local data = ply.APG_ToolCTRL
local delay = 0
local diff = 0
data.curTime = CurTime()
data.toolDelay = data.toolDelay or 0
data.toolUseTimes = data.toolUseTimes or 0
diff = data.curTime - data.toolDelay
delay = APG.cfg[ "blockToolDelay" ].value
if data.toolUseTimes <= 0 or diff > delay then
data.toolUseTimes = 0
data.toolDelay = 0
data.wasNotified = false
end
if diff > 0 then
data.toolUseTimes = math.max( data.toolUseTimes - 1, 0 )
else
data.toolUseTimes = math.min( data.toolUseTimes + 1, APG.cfg[ "blockToolRate" ].value )
if data.toolUseTimes >= APG.cfg[ "blockToolRate" ].value then
data.toolDelay = data.curTime + delay
if not data.wasNotified then
data.wasNotified = true
APG.notify( false, 1, ply, "You are using the toolgun too fast, slow down!" )
end
return false
end
end
if data.toolDelay == 0 then
data.toolDelay = data.curTime + delay
end
end)
--[[ Block Tool World ]]
APG.hookAdd(mod, "CanTool", "APG_ToolWorldControl", function(ply, tr)
if not APG.cfg[ "blockToolWorld" ].value then return end
if tr.HitWorld then
if not timer.Exists("APG-" .. ply:UniqueID() .. "-Notify") then
APG.notify( false, 1, ply, "You may not use the toolgun on the world." )
timer.Create("APG-" .. ply:UniqueID() .. "-Notify", 5, 1, function() end)
end
return false
end
end)
--[[ Block Tool Unfreeze ]]
APG.hookAdd(mod, "CanTool", "APG_ToolUnfreezeControl", function(ply, tr)
if not APG.cfg[ "blockToolUnfreeze" ].value then return end
timer.Simple(0.003, function()
local ent = tr.Entity
local phys = NULL
if IsValid(ent) then
phys = ent:GetPhysicsObject()
if IsValid(phys) and phys:IsMotionEnabled() then
phys:EnableMotion( false )
end
end
end)
end)
if APG.cfg[ "touchServerSettings" ].value then
local conVar = GetConVar("toolmode_allow_creator")
if conVar then
if APG.cfg[ "blockCreatorTool" ].value then
conVar:SetBool(false)
else
conVar:SetBool(true)
end
end
end
--[[ Load hooks and timers ]]
APG.updateHooks(mod)
APG.updateTimers(mod)

View File

@@ -0,0 +1,378 @@
--[[------------------------------------------
====================================================================================
/!\ READ ME /!\ /!\ READ ME /!\ /!\ READ ME /!\
====================================================================================
This file is the default config file.
If you want to configure APG to fit your server needs, you can edit the config
ingame using the chat command : !apg or apg in console.
]]--------------------------------------------
APG.cfg = APG.cfg or {}
APG.modules = APG.modules or {}
--[[----------
Your very own custom function
This function will run whenever lag is detected on your server!
]]------------
function APG.customFunc( notification )
-- Do something
end
--[[----------
Avalaible premade functions - THIS IS INFORMATIVE PURPOSE ONLY !
]]------------
if CLIENT then
APG_lagFuncs = { -- THIS IS INFORMATIVE PURPOSE ONLY !
"cleanup_all", -- Cleanup every props/ents protected by APG (not worldprops nor vehicles)
"cleanup_unfrozen", -- Cleanup only unfrozen stuff
"ghost_unfrozen", -- Ghost unfrozen stuff
"freeze_unfrozen", -- Freeze unfrozen stuff
"smart_cleanup", -- Cleanup unfrozen fading doors, freeze unfrozens, remove large stacks
"custom_function" -- Your custom function (see APG.customFunc)
} -- THIS IS INFORMATIVE PURPOSE ONLY !
APG_notifyLevels = {
"everyone",
"admin",
"superadmin"
}
end
--[[------------------------------------------
DEFAULT SETTINGS -- You CAN edit this part, but you SHOULDN'T
]]--------------------------------------------
local defaultSettings = {}
defaultSettings.modules = { -- Set to true to enable and false to disable module.
["home"] = true, -- Essential, do not disable.
["ghosting"] = true,
["stack_detection"] = true,
["lag_detection"] = true,
["notification"] = true,
["canphysgun"] = true, -- Essential, do not disable.
["misc"] = true,
["tools"] = true,
["logs"] = true,
}
defaultSettings.cfg = {
--[[----------
Ghosting module
]]------------
ghostColor = {
value = Color(34, 34, 34, 220),
desc = "Color set on ghosted props"
},
ghostColorToggle = {
value = true,
desc = "Toggle ghosting color."
},
badEnts = {
value = {
["prop_physics"] = true,
["wire_"] = false,
["gmod_"] = false,
["keypad"] = false,
},
desc = "Entities to ghost/control/secure (true if exact name, false if it is a pattern"
},
unGhostingWhitelist = {
value = {
["zmlab_"] = false,
},
desc = "Entities that should be set back to their original (spawned) collision group when frozen/dropped."
},
removeInvalidPhysics = {
value = false,
desc = "Should we attempt to detect and remove invalid physics objects? (Entities with bad or no physics objects/Physics objects without models.)"
},
invalidPhysicsWhitelist = {
value = {},
desc = "Entities that shouldn't be removed if they don't have proper physics"
},
alwaysFrozen = {
value = true,
desc = "Set to true to auto freeze props on physgun drop (aka APG_FreezeOnDrop)"
},
--[[----------
Stack detection module
]]------------
stackMax = {
value = 15,
desc = "Max amount of entities stacked in a small area"
},
stackArea = {
value = 15,
desc = "Sphere radius for stack detection (gmod units)"
},
fadingDoorStackMax = {
value = 5,
desc = "Maximum amount of fading doors that can be stacked in stackArea."
},
fadingDoorStackNotify = {
value = false,
desc = "Notify the players when their fading doors were removed"
},
--[[----------
Lag detection module
]]------------
lagTrigger = {
value = 75,
desc = "[Default: 75%] Differential threshold between current lag and average lag."
},
lagsCount = {
value = 8,
desc = "Number of consectuives laggy frames in order to run a cleanup."
},
bigLag = {
value = 2,
desc = "Maximum time (seconds) between 2 frames to trigger a cleanup"
},
lagFunc = {
value = "ghost_unfrozen",
desc = "Function ran on lag detected, see APG_lagFuncs."
},
lagFuncTime = {
value = 8,
desc = "Time (seconds) between 2 anti lag function (avoid spam)"
},
--[[ Notifications ]] --
notifySounds = {
value = false, -- Might make it where certain ones run sound
desc = "When notifications run do you want the sounds to play?"
},
notifyLevel = {
value = "admin",
desc = "Notification levels, refer to APG_notifyLevels"
},
notifyLagFunc = {
value = false,
desc = "Do you want the notifyLevel to see the lagFunc that ran? (refer to APG_lagFuncs)"
},
-- TODO: Make a ULX/ULIB module
-- notifyULibInheritance = {
-- value = true,
-- desc = "Do you want to use inheritance for notifyRanks? (only works with ULIB/ULX)"
-- },
-- notifyRanks = {
-- value = { "trialmod", "moderator", "admin", "superadmin", "owner" },
-- desc = "The ranks that you want to see the notification" -- If you have notifyULibInheritance you only need to do the lowest rank(s)
-- },
--[[ Override Server Settings? ]]
touchServerSettings = {
value = false,
desc = "Should we override Server Settings? (Used for setting ConVars)"
},
--[[ Vehicles ]]--
vehDamage = {
value = false,
desc = "True to disable vehicles damages, false to enable."
},
vehNoCollide = {
value = false,
desc = "True to disable collisions between vehicles and players"
},
vehIncludeWAC = {
value = true,
desc = "Check for WAC vehicles."
},
vehAntiGhost = {
value = false,
desc = "Toggle vehicle ghosting"
},
blockGravGunThrow = {
value = true,
desc = "Toggle GravGun throwing."
},
setTurboPhysics = {
value = false,
desc = "Toggle sv_turbophysics."
},
--[[ Tool Control ]]--
checkCanTool = {
value = true,
desc = "Should tools be blocked on APG_CantPickup?"
},
blockToolSpam = {
value = true,
desc = "Block players from spamming the toolgun."
},
blockToolRate = {
value = 5,
desc = "How fast can we use the toolgun before it gets blocked? (Clicks per second(s))"
},
blockToolDelay = {
value = 1,
desc = "How many seconds should we wait after we were stopped? (The aforementioned second(s))"
},
blockToolWorld = {
value = false,
desc = "Prevent using the toolgun on the world."
},
blockToolUnfreeze = {
value = true,
desc = "Prevent the toolgun from unfreezing props."
},
blockCreatorTool = {
value = true,
desc = "Should we block the creator tool?"
},
checkTooledEnts = {
value = true,
desc = "Review entities near tool use."
},
physGunMaxRange = {
value = 700,
desc = "Max range a physics gun can go"
},
--[[ Logs ]]--
logStackCrashAttempt = {
value = true,
desc = "Log when someone tries to lag/crash the server with stacker"
},
logLagDetected = {
value = true,
desc = "Log when the server lags"
},
--[[ Props related ]]--
blockPhysgunReload = {
value = true,
desc = "Block players from using physgun reload"
},
blockContraptionMove = {
value = true,
desc = "Block players from moving contraptions"
},
autoFreeze = {
value = false,
desc = "Freeze every unfrozen prop each X seconds"
},
autoFreezeTime = {
value = 120,
desc = "Auto freeze timer (seconds)"
},
fadingDoorHook = {
value = true,
desc = "Inject custom hooks into Fading Doors"
},
fadingDoorGhosting = {
value = true,
desc = "Activate fading door ghosting"
},
sleepyPhys = {
value = false,
desc = "Activate FRZR9K (Sleepy Physics)"
},
sleepyPhysHook = {
value = false,
desc = "Hook FRZR9K into collision (Experimental)"
},
allowPK = {
value = false,
desc = "Allow prop killing"
},
developerDebug = {
value = false,
desc = "Dev Logs (prints stuff)"
}
}
--[[------------------------------------------
LOADING SAVED SETTINGS -- DO NOT EDIT THIS PART
]]--------------------------------------------
if SERVER and file.Exists( "apg/settings.txt", "DATA" ) then
table.Merge( APG, defaultSettings ) -- Load the default settings first!
local settings = file.Read( "apg/settings.txt", "DATA" )
settings = util.JSONToTable( settings )
if not settings.modules or not settings.cfg then
ErrorNoHalt("Your custom settings have not been loaded because you have a misconfigured settings file! The default settings were used instead!")
return
end
local removedSetting = {}
for k, v in next, settings.modules do
if defaultSettings.modules[k] == nil then
settings.modules[k] = nil
table.insert(removedSetting, k)
end
end
for k, v in next, settings.cfg do
if defaultSettings.cfg[k] == nil then
settings.cfg[k] = nil
table.insert(removedSetting, k)
end
end
if next(removedSetting) then
print("[APG] Settings File Updated. (Conflicts Resolved)")
print("[APG] The Following Settings Have Been Removed: ")
for _,v in next, removedSetting do
print("\t> \"" .. tostring(v) .. "\" has been removed.")
end
removedSetting = nil
file.Write("apg/settings.txt", util.TableToJSON(settings))
end
table.Merge( APG, settings )
else
table.Merge( APG, defaultSettings )
end

View File

@@ -0,0 +1,420 @@
util.AddNetworkString("apg_notice_s2c")
APG = APG or {}
local IsValid = IsValid
local table = table
local isentity = isentity
--[[ ENTITY Related ]]
--[[
Check if the player can pick up the entity
@param {entity} ent
@param {player} ply
@returns {boolean}
]]
function APG.canPhysGun( ent, ply )
-- Predict if the player can pickup an entity.
if not IsValid(ent) then return false end -- The entity isn't valid, don't pickup.
if ent:GetPersistent() then
return false
end
if ent.PhysgunDisabled then
return false
end -- Check if the entity is physgun disabled.
ent.APG_HeldBy = ent.APG_HeldBy or {}
ent.APG_HeldBy.plys = ent.APG_HeldBy.plys or {}
if ply.APG_CantPickup == true or next( ent.APG_HeldBy.plys ) then
ply:ConCommand("-attack") -- Tell the player to stop physgunning.
return false
end -- Is APG blocking the pickup?
if ent.CPPICanPhysgun then
return ent:CPPICanPhysgun(ply)
end -- Let CPPI handle things from here.
return false -- If everything fails we probably shouldn't be picking this up.
end
function APG.isWhitelistedEnt( ent )
local class = ent:GetClass()
for k, v in pairs (APG.cfg["unGhostingWhitelist"].value) do
if ( v and k == class ) or (not v and string.find( class, k ) ) then
return true
end
end
return false
end
--[[
Check if the entity is a bad entity, as defined in badEnts
@param {entity} ent
@returns {boolean}
]]
function APG.isBadEnt( ent )
if ent and not ent.GetClass then return false end -- Ignore if we can't read the class.
if not IsValid(ent) then return false end -- Ignore invalid entities.
if ent.jailWall == true then return false end -- Ignore ULX jails.
if Entity(0) == ent or ent:IsWorld() then return false end -- Ignore worldspawn.
if ent:IsWeapon() then return false end -- Ignore weapons.
if ent:IsPlayer() then return false end -- Ignore players.
if ent:IsNPC() then return false end
if ent.ARCBank_MapEntity then return false end --Ignore ARCBank ents
local h = hook.Run("APGisBadEnt", ent)
if isbool(h) then return h end
local class = ent:GetClass()
for k, v in pairs (APG.cfg["badEnts"].value) do
if ( v and k == class ) or (not v and string.find( class, k ) ) then
return true
end
end
return false
end
--[[
Check the props owner
@return {player} or nil
]]
function APG.getOwner( ent )
local owner, _ = ent:CPPIGetOwner() or ent.FPPOwner or nil
return owner
end
--[[
Add's a timer to the module table
@param {string} module
@param {string} identifier
@param {number} delay
@param {number} repetitions
@param {function} function
@void
]]
local function killVel(phys, freeze)
local vec = Vector()
if not IsValid(phys) then return end
if freeze then phys:EnableMotion(false) return end
phys:SetVelocity(vec)
phys:SetVelocityInstantaneous(vec)
phys:AddAngleVelocity(phys:GetAngleVelocity() * -1)
phys:Sleep()
end
function APG.killVelocity(ent, extend, freeze, wake_target)
local vec = Vector()
if ent.GetClass and ent:GetClass() == "player" then ent:SetVelocity(ent:GetVelocity() * -1) return end
ent:SetVelocity(vec)
for i = 0, ent:GetPhysicsObjectCount() do killVel(ent:GetPhysicsObjectNum(i), freeze) end -- Includes self?
if extend then
for _,v in next, constraint.GetAllConstrainedEntities(ent) do killVel(v:GetPhysicsObject(), freeze) end
end
if wake_target then
timer.Simple(0, function()
if not IsValid(ent) then return end
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
phys:Wake()
end
end)
end
end
function APG.freezeIt( ent, extend )
local obj = ent:GetPhysicsObject()
if extend then
for _,v in next, constraint.GetAllConstrainedEntities(ent) do
killVel(v:GetPhysicsObject(), true)
v.APG_Frozen = true
end
else
if IsValid(obj) then
killVel(obj, true)
ent.APG_Frozen = true
end
end
end
function APG.FindWAC(ent)
if not APG.cfg["vehIncludeWAC"].value then return false end
local e
local i = 0
if ent.wac_seatswitch or ent.wac_ignore then return true end
for _,v in next, constraint.GetAllConstrainedEntities(ent) do
if v.wac_seatswitch or v.wac_ignore then e = v break end
if i > 12 then break end -- Only check up to 12.
i = i + 1
end
return IsValid(e)
end
function APG.IsVehicle(v, basic)
if not IsValid(v) then return false end
if v:IsVehicle() then return true end
if string.find(v:GetClass(), "vehicle") then return true end
if basic then return false end
if APG.FindWAC(v) then return true end
local parent = v:GetParent()
return APG.IsVehicle(parent, true)
end
function APG.cleanUp( mode, notify, specific )
mode = mode or "unfrozen"
for _, v in next, specific or ents.GetAll() do
APG.killVelocity(v,false)
if not APG.isBadEnt(v) or not APG.getOwner( v ) or APG.IsVehicle(v) then continue end
if mode == "unfrozen" and v.APG_Frozen then -- Whether to clean only not frozen ents or all ents
continue
else
v:Remove()
end
end
if notify or APG.cfg["notifyLagFunc"].value then
APG.notify( false, 2, "all", APG.cfg["notifyLevel"].value, "Cleaned up (mode: ", mode, ")" )
end
end
function APG.ghostThemAll( notify, callback )
if not APG.modules[ "ghosting" ] then
return APG.notify( false, 0, "admins", "[APG] Warning: Tried to ghost props but ghosting is disabled!" )
end
for _, v in next, ents.GetAll() do
if ( not APG.isBadEnt(v) ) or ( not APG.getOwner( v ) ) or APG.IsVehicle(v) or v.APG_Frozen then continue end
APG.entGhost( v, true, false )
end
if notify or APG.cfg["notifyLagFunc"].value then
APG.notify( false, APG.cfg["notifyLevel"].value, "admins", "Some unfrozen entities were ghosted!" )
end
if isfunction(callback) then
callback()
end
end
function APG.freezeProps( notify, callback )
for _, v in next, ents.GetAll() do
if not APG.isBadEnt(v) or not APG.getOwner( v ) then continue end
APG.freezeIt( v )
end
if notify or APG.cfg["notifyLagFunc"].value then
APG.notify(false, APG.cfg["notifyLevel"].value, "all", "Some entities were frozen!")
end
if isfunction(callback) then
callback()
end
end
local function GetPhysenv()
local env = physenv.GetPerformanceSettings()
local con = {}
local vars = {
"phys_upimpactforcescale",
"phys_impactforcescale",
"phys_pushscale",
"sv_turbophysics",
}
for _,v in next, vars do
local var = GetConVar(v)
con[v] = var and var:GetString() or nil
end
return {con = con, env = env}
end
function APG.smartCleanup( notify, callback )
local defaults = GetPhysenv()
local phys = table.Copy(defaults.env)
hook.Add("PlayerSpawnObject", "APG_smartCleanup", function() return false end)
RunConsoleCommand("phys_upimpactforcescale","0")
RunConsoleCommand("phys_impactforcescale", "0")
RunConsoleCommand("phys_pushscale", "0")
RunConsoleCommand("sv_turbophysics", "1")
phys.MaxCollisionChecksPerTimestep = 0
phys.MaxAngularVelocity = 0
phys.MaxVelocity = 0
physenv.SetPerformanceSettings(phys)
local sphere = ents.FindInSphere
local all = ents.GetAll()
local bad = {}
for _, v in next, all do
if IsValid(v) and v.GetPhysicsObject then
local phys = v:GetPhysicsObject()
if IsValid(phys) and phys:IsMotionEnabled() then
if v.isFadingDoor and APG.isBadEnt(ent) then
SafeRemoveEntity(v)
else
table.insert(bad, {ent = v, phys = phys})
end
end
end
end
APG.freezeProps()
for _, v in next, bad do
local count = 0
local owner = APG.getOwner(v.ent)
local space = sphere(v.ent:GetPos(), 7)
local cache = {}
for _, ent in next, space do
if owner == APG.getOwner(ent) then
count = count + 1
table.insert(cache, ent)
end
end
if count > 4 then
for _, ent in next, cache do
if APG.isBadEnt(ent) then
SafeRemoveEntity(ent)
end
end
end
end
timer.Simple(1.5, function() -- Give a few seconds for the engine to catch up.
for k,v in next, defaults.con do
RunConsoleCommand(k, v)
end
physenv.SetPerformanceSettings(defaults.env)
hook.Remove("PlayerSpawnObject", "APG_smartCleanup")
if isfunction(callback) then
callback()
end
end)
end
function APG.ForcePlayerDrop(ply, ent)
if IsValid(ply) then
ply:ConCommand("-attack")
end
if IsValid(ent) then
DropEntityIfHeld( ent )
ent:ForcePlayerDrop()
end
end
function APG.blockPickup( ply )
if not IsValid(ply) or ply.APG_CantPickup then return end
ply.APG_CantPickup = true
timer.Simple(10, function()
if IsValid(ply) then
ply.APG_CantPickup = false
end
end)
end
--[[--------------------
Set when a prop is unfrozen.
]]----------------------
hook.Add("PlayerUnfrozeObject", "APG_PlayerUnfrozeObject", function(ply, ent, object)
if not APG.isBadEnt( ent ) then return end
ent.APG_Frozen = false
end)
--[[--------------------
Physgun Drop & Freeze
]]----------------------
hook.Add( "OnPhysgunFreeze", "APG_OnPhysgunFreeze", function( weap, phys, ent, ply )
if not APG.isBadEnt( ent ) then return end
ent.APG_Frozen = true
end)
--[[--------------------
APG job manager
--]]----------------------
local toProcess = toProcess or {}
function APG.dJobRegister( job, delay, limit, func, onBegin, onEnd )
local tab = {
content = {},
delay = delay,
limit = limit,
func = func,
onBegin = onBegin or nil,
onEnd = onEnd or nil
}
toProcess[job] = tab
end
local function APG_delayedTick( job )
if toProcess[job].processing and toProcess[job].processing == true then return end
toProcess[job].processing = true
if toProcess[job].onBegin then toProcess[job].onBegin() end
local delay, pLimit = toProcess[job].delay, toProcess[job].limit
local total = #toProcess[job].content
local count = math.Clamp(total,0,pLimit)
for i = 1, count do
local cur = toProcess[job].content[1]
timer.Create( "delay_" .. job .. "_" .. i , ( i - 1 ) * delay , 1, function()
toProcess[job].func( cur )
end)
table.remove(toProcess[job].content, 1)
end
timer.Create("dJob_" .. job .. "_process", ( count * delay ) + 0.1 , 1, function() toProcess[job].processing = false
if #toProcess[job].content < 1 and toProcess[job].onEnd then toProcess[job].onEnd() end
end)
end
function APG.startDJob( job, content )
if not job or not isstring(job) or not content then return end
if not toProcess or not toProcess[job] then
ErrorNoHalt("[APG] No Process Found, Attempting Reload!\n---\nThis Shouldn't Happen Concider Restarting!\n")
APG.reload()
return
end
if table.HasValue(toProcess[job].content, content) then return end
-- Is it a problem if there is a same ent being unghosted twice ?
table.insert( toProcess[job].content, content )
hook.Add("Tick", "APG_delayed_" .. job, function()
if #toProcess[job].content > 0 then
APG_delayedTick( job )
else
hook.Remove("Tick", "APG_delayed_" .. job)
end
end)
end
hook.Add("InitPostEntity", "APG_Load", function()
hook.Add("Think", "APG_Load", function()
APG.initialize()
hook.Remove("Think", "APG_Load")
end)
end)

View File

@@ -0,0 +1,150 @@
util.AddNetworkString("apg_settings_c2s")
util.AddNetworkString("apg_menu_s2c")
util.AddNetworkString("apg_context_c2s")
local function saveSettings( json )
if not file.Exists("apg", "DATA") then file.CreateDir( "apg" ) end
file.Write("apg/settings.txt", json)
end
local function recSettings( len, ply)
if not ply:IsSuperAdmin() then return end
len = net.ReadUInt( 32 )
if len == 0 then return end
local settings = net.ReadData( len )
settings = util.Decompress( settings )
saveSettings( settings )
settings = util.JSONToTable( settings )
APG.cfg = settings.cfg
table.Merge(APG, settings)
APG.reload()
end
net.Receive( "apg_settings_c2s", recSettings)
local function sendToClient( ply )
local settings = {}
settings.cfg = APG.cfg or {}
settings.modules = APG.modules or {}
settings = util.TableToJSON( settings )
settings = util.Compress( settings )
net.Start("apg_menu_s2c")
net.WriteUInt( settings:len(), 32 ) -- Write the length of the data
net.WriteData( settings, settings:len() ) -- Write the data
net.Send(ply)
end
hook.Add( "PlayerSay", "openAPGmenu", function( ply, text, public )
text = string.lower( text )
if ply:IsSuperAdmin() and text == "!apg" then
sendToClient( ply )
return ""
end
end)
local function checkOwner(owner, ply)
if ( IsValid(owner) and owner:IsPlayer() ) then
return true
else
APG.notification("The owner of this entity is NOT a Player. (Owner: " .. type(owner) .. ")", ply)
return false
end
end
-- TODO: Revamp this, really don't like how it looks, would rather have a function for each
-- it's too clustered.
local function contextCMD(_,ply)
if not ply:IsSuperAdmin() then return end
local cmd = net.ReadString()
local ent = net.ReadEntity()
ent = IsValid(ent) and ent or ply:GetEyeTraceNoCursor().Entity or nil
local class = IsValid(ent) and ent.GetClass and ent:GetClass() or nil
if not class then return end
local owner = APG.getOwner(ent)
if cmd == "addghost" then
if not APG.cfg.badEnts.value[class] then
APG.cfg.badEnts.value[class] = true
APG.notify( false, 0, ply, "\"", class, "\" added to Ghost List!" )
else
APG.notify( false, 0, ply, "This class is already listed!" )
end
elseif cmd == "remghost" then
APG.cfg.badEnts.value[class] = nil
APG.notify( false, 0, ply, "\"", class, "\" removed from Ghost List!" )
elseif cmd == "clearowner" then
if not checkOwner(owner, ply) then return end
cleanup.CC_Cleanup(owner,"gmod_cleanup",{})
elseif cmd == "clearunfrozen" then
if not checkOwner(owner, ply) then return end
local count = 0
for _,v in next, ents.GetAll() do
if not (IsValid(v) and APG.getOwner(v) == owner) then continue end
if not APG.isBadEnt(v) then continue end
if not v.APG_Frozen then
SafeRemoveEntity(v)
count = count + 1
end
end
APG.notify( false, 0, ply, count, "entities have been removed!" )
elseif cmd == "getownercount" then
if not checkOwner(owner, ply) then return end
local count = 0
for _,v in next, ents.GetAll() do
if IsValid(v) and APG.getOwner(v) == owner then
count = count + 1
end
end
APG.notify( false, 0, ply, owner:Nick(), "[", owner:SteamID(), "]", "has", count, (count == 1 and "entity." or "entities.") )
elseif cmd == "freezeclass" then
local count = 0
for _,v in next, ents.FindByClass(class) do
if IsValid(v) and not v.APG_Frozen then
count = count + 1
APG.killVelocity(v, false, true, false)
end
end
APG.notify( false, 0, ply, (count or 0), (count == 1 and "Entity" or "Entities"), "Frozen" )
elseif cmd == "sleepclass" then
local count = 0
for _,v in next, ents.FindByClass(class) do
if IsValid(v) and not v.APG_Frozen then
count = count + 1
APG.killVelocity(v, false, false, false)
end
end
APG.notify( false, 0, ply, (count or 0), (count == 1 and "Entity is" or "Entities are"), "now Sleeping!" )
elseif cmd == "ghost" then
APG.entGhost(ent)
APG.notify( false, 0, ply, ent, " was ghosted." )
end
if cmd == "addghost" or cmd == "remghost" then
local settings = {}
settings.cfg = APG.cfg or {}
settings.modules = APG.modules or {}
saveSettings( util.TableToJSON( settings ) )
APG.reload()
end
end
net.Receive("apg_context_c2s", contextCMD)

View File

@@ -0,0 +1,3 @@
APG = {}
include( "apg/sh_config.lua" )
include( "apg/cl_menu.lua" )

View File

@@ -0,0 +1,176 @@
--[[ INITIALIZE APG ]]
APG = {}
APG.modules = APG.modules or {}
--[[ Micro Optimization ]]
local timer = timer
local table = table
--[[ CLIENT related ]]
AddCSLuaFile("apg/sh_config.lua")
AddCSLuaFile("apg/cl_utils.lua")
AddCSLuaFile("apg/cl_menu.lua")
--[[ REGISTER Modules ]]
local modules, _ = file.Find("apg/modules/*.lua","LUA")
for _,v in next, modules do
if v then
niceName = string.gsub(tostring(v),"%.lua","")
APG.modules[ niceName ] = false
APG[ niceName ] = { hooks = {}, timers = {}}
end
end
--[[
Add's a hook to the module table
@param {string} module
@param {string} event
@param {string} identifier
@param {function} function
@void
]]
function APG.hookAdd( module, event, identifier, func )
table.insert( APG[ module ][ "hooks"], { event = event, identifier = identifier, func = func })
end
--[[
Adds all the hooks that the module needs
@param {string} module
@void
]]
function APG.updateHooks( module )
for k, v in next, APG[module]["hooks"] do
hook.Add( v.event, v.identifier, v.func )
end
end
--[[
Add's a timer to the module table
@param {string} module
@param {string} identifier
@param {number} delay
@param {number} repetitions
@param {function} function
@void
]]
function APG.timerAdd( module, identifier, delay, repetitions, func )
table.insert( APG[ module ][ "timers"], { identifier = identifier, delay = delay, repetitions = repetitions, func = func } )
end
--[[
Add's a the timers a module needs.
@param {string} module
@void
]]
function APG.updateTimers(module)
for k, v in next, APG[module]["timers"] do
timer.Create( v.identifier, v.delay, v.repetitions, v.func )
end
end
--[[
Load's a APG module
@param {string} module
@void
]]
function APG.load( module )
APG.modules[ module ] = true
include( "apg/modules/" .. module .. ".lua" )
print("[APG] " .. module .. " loaded.")
end
--[[
Unload's a APG module
@param {string} module
@void
]]
function APG.unLoad( module )
APG.modules[module] = false
if not (istable(APG[module]) and next(APG[module])) then return end
local hooks = APG[ module ]["hooks"]
for k, v in next, hooks do
hook.Remove(v.event, v.identifier)
end
local timers = APG[ module ]["timers"]
for k, v in next, timers do
timer.Remove(v.identifier)
end
print("[APG] " .. module .. " unloaded.")
end
function APG.reload()
for k, v in next, APG.modules do
if APG.modules[ k ] == true then
APG.unLoad( k )
APG.load( k )
else
APG.unLoad( k )
end
end
end
--[[ local settings = {}
function APG.sampleServerSettings()
end
function APG.getServerSettings()
end ]]
function APG.initialize()
for k, v in next, APG.modules do
if APG.modules[k] == true then
APG.load(k)
end
end
end
--[[ LOADING ]]
-- Loading config first
include( "apg/sh_config.lua" )
-- Loading APG main functions
include( "apg/sv_apg.lua") -- Modules loaded at the bottom
-- Loading APG menu
include( "apg/sv_menu.lua" )
--[[ CVars INIT ]]
concommand.Add("apg_set", function( ply, cmd, args, argStr )
if not ply:IsSuperAdmin() then return end
if args[1] == "module" then
local _module = APG.modules[ args[2] ]
if _module != nil then
if _module == true then
APG.unLoad( args[2] )
APG.notification( "[APG] Module " .. args[2] .. " disabled.", ply)
else
APG.load( args[2] )
APG.notification( "[APG] Module " .. args[2] .. " enabled.", ply)
end
else
APG.notification( "[APG] This module does not exist", ply)
end
elseif args[1] == "help" then
local cfg = APG.cfg[ args[2] ]
if cfg then
APG.notification( cfg.desc, ply)
else
APG.notification( "[APG] Help: This setting does not exist", ply)
end
else
APG.notification( ply, "Error: unknown setting")
end
end)

View File

@@ -0,0 +1,2 @@
-- ULX Admin Commands Coming Soon!
--- PLanned Commands for Prop Management, and Server Cleanup.

View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,14 @@
# MoonContextMenu
ContextMenu for Interaction in Garry's Mod
🔧 [Mantle](https://github.com/darkfated/mantle): in order for the system to work, you need to use this Gmod library
## Screenshots 📷
### Appearance
<img src="https://github.com/darkfated/mooncontextmenu/assets/49955245/b6ceff15-3909-4538-8326-fcd88d449af7" width="300" alt="Appearance">
### You can move it
<img src="https://github.com/darkfated/mooncontextmenu/assets/49955245/b559d1f6-a2f0-4d27-87c3-8f2dea27ff29" width="400" alt="Moving">
### And of course to reset the position using the left mouse button
<img src="https://github.com/darkfated/mooncontextmenu/assets/49955245/b426a516-e8f8-480b-ae5e-920fd072c8cb" width="300" alt="Reset Btn">

View File

@@ -0,0 +1,150 @@
// Конфиг сделан под ШколуРП. Но можете запроста изменить под DarkRP
MoonContextMenu.config_cmds = {
{
items = {
{
name = 'Админка',
func = function()
RunConsoleCommand('sam', 'menu')
end,
icon = 'wrench'
},
{
name = 'Логи',
func = function()
RunConsoleCommand('say', '!plogs')
end,
icon = 'logs'
}
},
check = function()
return LocalPlayer():getJobTable().command == 'job_admin'
end
},
{
items = {
{
name = 'Выкинуть оружие',
func = function()
RunConsoleCommand('darkrp', 'dropweapon')
end,
icon = 'gun'
},
{
name = 'Купить патроны',
func = function()
if not LocalPlayer():GetActiveWeapon().Primary then return end
RunConsoleCommand("darkrp", "buyammo", string.lower(LocalPlayer():GetActiveWeapon().Primary.Ammo))
end,
icon = 'gun'
},
{
name = 'Выбросить деньги',
func = function()
Mantle.ui.text_box('Выбросить деньги', 'Сколько желаете?', function(s)
RunConsoleCommand('darkrp', 'dropmoney', s)
end)
end,
icon = 'drop_money'
},
{
name = 'Передать игроку деньги',
func = function()
Mantle.ui.text_box('Передать деньги', 'Сколько желаете?', function(s)
RunConsoleCommand('darkrp', 'give', s)
end)
end,
icon = 'give_money'
},
{
name = 'Сменить ник',
func = function()
Mantle.ui.text_box('Сменить ник', 'Какой хотите поставить?', function(s)
RunConsoleCommand('darkrp', 'rpname', s)
end)
end,
icon = 'nick'
},
{
name = 'Продать все двери',
func = function()
RunConsoleCommand('darkrp', 'unownalldoors')
end,
icon = 'doors'
},
{
name = 'Написать объявление',
func = function()
Mantle.ui.text_box('Написать объявление', 'Что планируете рекламировать?', function(s)
RunConsoleCommand('say', '/advert ' .. s)
end)
end,
icon = 'advert'
},
{
name = 'Кинуть ролл',
func = function()
RunConsoleCommand('say', '/roll')
end,
icon = 'roll'
}
}
},
{
items = {
{
name = 'Назначить розыск',
func = function()
Mantle.ui.player_selector(function(pl)
Mantle.ui.text_box('Назначить розыск', 'Какова причина?', function(s)
RunConsoleCommand('darkrp', 'wanted', pl:Name(), s)
end)
end)
end,
icon = 'wanted'
},
{
name = 'Снять розыск',
func = function()
Mantle.ui.player_selector(function(pl)
RunConsoleCommand('darkrp', 'unwanted', pl:Name())
end)
end,
icon = 'unwanted'
},
{
name = 'Получить ордер',
func = function()
Mantle.ui.player_selector(function(pl)
Mantle.ui.text_box('Получить ордер', 'Какова причина?', function(s)
RunConsoleCommand('darkrp', 'warrant', pl:Name(), s)
end)
end)
end,
icon = 'warrant'
},
},
check = function()
return LocalPlayer():getJobTable().adult
end
},
{
items = {
-- {
-- name = 'Настройки 3 лица',
-- func = function()
-- RunConsoleCommand('say','!third')
-- end,
-- icon = 'thirdperson_toggle'
-- },
{
name = 'Остановить все звуки',
func = function()
RunConsoleCommand('stopsound')
end,
icon = 'sounds'
}
}
}
}

View File

@@ -0,0 +1,29 @@
--[[
* MoonContextmenu *
GitHub: https://github.com/darkfated/mooncontextmenu
Author's discord: darkfated
]]
local function run_scripts()
Mantle.run_cl('config.lua')
Mantle.run_cl('menu.lua')
end
local function init()
if SERVER then
local folderPath = 'materials/mooncontextmenu'
local files = file.Find(folderPath .. '/*.png', 'GAME')
for _, fileName in ipairs(files) do
local filePath = folderPath .. '/' .. fileName
resource.AddFile(filePath)
end
end
MoonContextMenu = MoonContextMenu or {}
run_scripts()
end
init()

View File

@@ -0,0 +1,85 @@
local scrw, scrh = ScrW(), ScrH()
local function Create()
MoonContextMenu.menu = vgui.Create('DFrame')
Mantle.ui.frame(MoonContextMenu.menu, '', 300, 500, false)
if MoonContextMenu.pos_save then
MoonContextMenu.menu:SetPos(MoonContextMenu.pos_save[1], MoonContextMenu.pos_save[2])
else
MoonContextMenu.menu:SetPos(10, 0)
MoonContextMenu.menu:CenterVertical()
end
MoonContextMenu.menu:MakePopup()
MoonContextMenu.menu.center_title = 'Список команд'
MoonContextMenu.menu.sp = vgui.Create('DScrollPanel', MoonContextMenu.menu)
Mantle.ui.sp(MoonContextMenu.menu.sp)
MoonContextMenu.menu.sp:Dock(FILL)
for _, cat in ipairs(MoonContextMenu.config_cmds) do
if cat.check and !cat.check() then
continue
end
for _, cmd in ipairs(cat.items) do
local btn_cmd = vgui.Create('DButton', MoonContextMenu.menu.sp)
Mantle.ui.btn(btn_cmd)
btn_cmd:Dock(TOP)
btn_cmd:DockMargin(0, 0, 0, 4)
btn_cmd:SetTall(24)
btn_cmd:SetText(cmd.name)
btn_cmd.DoClick = function()
Mantle.func.sound()
cmd.func()
end
btn_cmd.DoRightClick = function()
local DM = Mantle.ui.derma_menu()
DM:AddOption('Сбросить позицию', function()
MoonContextMenu.pos_save = nil
MoonContextMenu.menu:Remove()
end, 'icon16/arrow_out.png')
end
if cmd.icon then
btn_cmd.mat = Material('materials/mooncontextmenu/' .. cmd.icon .. '.png')
btn_cmd.PaintOver = function(self, w, h)
surface.SetDrawColor(color_white)
surface.SetMaterial(self.mat)
surface.DrawTexturedRect(4, 4, 16, 16)
end
end
end
local panel_split = vgui.Create('DPanel', MoonContextMenu.menu.sp)
panel_split:Dock(TOP)
panel_split:DockMargin(0, 0, 0, 4)
panel_split:SetTall(8)
panel_split.Paint = function(_, w, h)
draw.RoundedBox(4, 0, 0, w, h, Mantle.color.panel_alpha[2])
end
end
end
local function Close()
if !IsValid(MoonContextMenu.menu) then
return
end
MoonContextMenu.pos_save = {}
MoonContextMenu.pos_save[1], MoonContextMenu.pos_save[2] = MoonContextMenu.menu:GetPos()
MoonContextMenu.menu:Remove()
end
hook.Add('OnContextMenuOpen', 'Mantle.MoonContextMenu', function()
if !IsValid(MoonContextMenu.menu) then
Create()
end
end)
hook.Add('OnContextMenuClose', 'Mantle.MoonContextMenu', function()
Close()
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

View File

@@ -0,0 +1,34 @@
/*----------------------------------------------------------------------
Leak by Famouse (P.s. Я это не вырезаю для атмосферы ахуенной сервера хуй знает какого года)
Play good games:
http://store.steampowered.com/curator/32364216
Subscribe to the channel:
www.youtube.com/c/Famouse
More leaks in the discord:
https://discord.gg/rFdQwzm
------------------------------------------------------------------------*/
resource.AddFile("materials/icons/back.png")
resource.AddFile("materials/icons/close.png")
resource.AddFile("materials/icons/commands.png")
resource.AddFile("materials/icons/database.png")
resource.AddFile("materials/icons/donate.png")
resource.AddFile("materials/icons/home.png")
resource.AddFile("materials/icons/info.png")
resource.AddFile("materials/icons/jobs.png")
resource.AddFile("materials/icons/menu.png")
resource.AddFile("materials/icons/shop.png")
resource.AddFile("materials/icons/site.png")
resource.AddFile("materials/icons/user.png")
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,51 @@
/*----------------------------------------------------------------------
Leak by Famouse (P.s. Я это не вырезаю для атмосферы ахуенной сервера хуй знает какого года)
Play good games:
store.steampowered.com/curator/32364216
Subscribe to the channel:
https://www.youtube.com/c/Famouse
More leaks in the discord:
https://discord.gg/rFdQwzm
------------------------------------------------------------------------*/
if CLIENT then
-- CLIENT MENU
include("smooth-f4menu/client/cl_smooth-f4menu.lua")
include("smooth-f4menu/client/cl_smooth-f4menu-commands.lua")
include("smooth-f4menu/client/cl_smooth-f4menu-jobs.lua")
include("smooth-f4menu/client/cl_smooth-f4menu-title.lua")
include("smooth-f4menu/client/cl_smooth-f4menu-shop.lua")
include("smooth-f4menu/client/cl_smooth-f4menu-site.lua")
-- CFG
include("smooth-f4menu/cfg_smooth-f4menu.lua")
end
if SERVER then
-- SERVER MENU
include("smooth-f4menu/server/sv_smooth-f4menu.lua")
-- CLIENT MENU
AddCSLuaFile("smooth-f4menu/client/cl_smooth-f4menu.lua")
AddCSLuaFile("smooth-f4menu/client/cl_smooth-f4menu-commands.lua")
AddCSLuaFile("smooth-f4menu/client/cl_smooth-f4menu-jobs.lua")
AddCSLuaFile("smooth-f4menu/client/cl_smooth-f4menu-title.lua")
AddCSLuaFile("smooth-f4menu/client/cl_smooth-f4menu-shop.lua")
AddCSLuaFile("smooth-f4menu/client/cl_smooth-f4menu-site.lua")
-- CFG
include("smooth-f4menu/cfg_smooth-f4menu.lua")
AddCSLuaFile("smooth-f4menu/cfg_smooth-f4menu.lua")
end
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,135 @@
/*----------------------------------------------------------------------
Leak by Famouse (P.s. Я это не вырезаю для атмосферы ахуенной сервера хуй знает какого года)
Play good games:
store.steampowered.com/curator/32364216
Subscribe to the channel:
https://www.youtube.com/c/Famouse
More leaks in the discord:
discord.gg/rFdQwzm
------------------------------------------------------------------------*/
-- TITLE NAME SERVER
SmoothF4MenuFrame_NameServer = "Мертвая Мама Кост Ича RP | Сенвай украл сапы"
-- LANGUAGE MENU
SmoothF4MenuFrame_NameServer_Home = "Домой"
SmoothF4MenuFrame_NameServer_Jobs = "Работы"
SmoothF4MenuFrame_NameServer_Shop = "Магазин"
SmoothF4MenuFrame_NameServer_Command = "Команды"
SmoothF4MenuFrame_NameServer_Site = "Вики"
SmoothF4MenuFrame_DescriptionJobs = "Описание"
SmoothF4MenuFrame_DescriptionSalary = "Зарплата"
SmoothF4MenuFrame_Entities = "Предметы"
SmoothF4MenuFrame_Weapon = "Оружия"
SmoothF4MenuFrame_Shipments = "Ящики"
SmoothF4MenuFrame_Ammo = "Патроны"
SmoothF4MenuFrame_TMoney = "Деньги"
SmoothF4MenuFrame_Group = "Группа"
SmoothF4MenuFrame_OnlinePlayer = "Онлайн игроков"
SmoothF4MenuFrame_TStaffOnline = "Админы онлайн"
SmoothF4MenuFrame_RulesTitle = "Правила"
SmoothF4MenuFrame_Loading = "Загрузка..."
SmoothF4MenuFrame_ErrorVip = "Ты не имеешь прав!"
-- MONEY
SmoothF4MenuFrame_Money = "$"
-- ENABLE WEAPON ?
SmoothF4MenuFrame_EnableWeapon = true
-- ENABLE SHIPMENTS ?
SmoothF4MenuFrame_EnableShipments = true
-- ENABLE AMMO ?
SmoothF4MenuFrame_EnableAmmo = true
-- SITE URL
SmoothF4MenuFrame_SiteURL = "https://dev.pavetr.ru/server/senwai-mmk/wiki.html"
SmoothF4MenuFrame_DonateURL = "https://forum.pavetr.ru/dbtech-donate/drives/bez-tseli.2/"
-- STAFF ONLINE
SmoothF4MenuFrame_StaffOnline = { "superadmin", "owner", "vip", "admin" }
-- RULES
SmoothF4MenuFrame_TRules = {
"Text 1 ...",
"Text 2 ...",
"Text 3 ...",
"Text 4 ...",
}
-- VIP JOBS,WEAPON,SHIPMENTS,ENTITY
SmoothF4MenuFrame_VipGroup = { "superadmin", "owner", "vip", "admin" }
SmoothF4MenuFrame_VipWeapon = { "superadmin", "owner", "vip", "admin" }
SmoothF4MenuFrame_VipShipments = { "superadmin", "owner", "vip", "admin" }
SmoothF4MenuFrame_VipEntity = { "superadmin", "owner", "vip", "admin" }
-- COMMAND
MONEYCMD_BUTTONS = {}
RPCMD_BUTTONS = {}
CPCMD_BUTTONS = {}
MAYORCMD_BUTTONS = {}
Categories = {}
table.insert(Categories, { name = "Деньги", Table = MONEYCMD_BUTTONS })
table.insert(Categories, { name = "Игрок", Table = RPCMD_BUTTONS })
table.insert(Categories, { name = "Полиция", Table = CPCMD_BUTTONS })
table.insert(Categories, { name = "Мэр", Table = MAYORCMD_BUTTONS })
local function MenuAddMButton(n, f)
table.insert(MONEYCMD_BUTTONS, { NAME = n, FUNC = f })
end
local function MenuAddRPButton(n, f)
table.insert(RPCMD_BUTTONS, { NAME = n, FUNC = f })
end
local function MenuAddCPButton(n, f)
table.insert(CPCMD_BUTTONS, { NAME = n, FUNC = f })
end
local function MenuAddMayorButton(n, f)
table.insert(MAYORCMD_BUTTONS, { NAME = n, FUNC = f })
end
MenuAddMButton("Дать денег игроку", function() OpenTextBox("Дать денег", "Сколько?", "/give") end)
MenuAddMButton("Скинуть деньги", function() OpenTextBox("Скинуть деньги", "Сколько?", "/moneydrop") end)
MenuAddRPButton("Выбросить оружие", function() RunConsoleCommand("say", "/dropweapon") end)
MenuAddRPButton("Запросить лицензию", function() RunConsoleCommand("say", "/requestlicense") end)
MenuAddRPButton("Уволить игрока",
function() OpenPlyReasonBox("Уволить игрока", "Какого игрока вы хотите уволить?", "Причина увольнения?", "/demote") end)
MenuAddRPButton("Продать все двери", function() RunConsoleCommand("say", "/unownalldoors") end)
MenuAddCPButton("Подать игрока в розыск",
function()
OpenPlyReasonBox("Подать игрока в розыск", "Какого игрока вы хотите подать в розыск?", "Причина розыска?",
"/wanted")
end)
MenuAddCPButton("Снять с игрока розыск",
function() OpenPlyBox("Снять с игрока розыск", "С какого игрока вы хотите снять розыск?", "/unwanted") end)
MenuAddCPButton("Ордер на обыск игрока",
function() OpenPlyReasonBox("Ордер на обыск игрока", "На кого вы хотите подать ордер?", "Причина ордера?", "/warrant") end)
MenuAddMayorButton("Розыскивать игрока",
function()
OpenPlyReasonBox("Розыскивать игрока", "Какого игрока вы хотите подать в розыск?", "Причина розыска?",
"/wanted")
end)
MenuAddMayorButton("Снять с игрока розыск",
function() OpenPlyBox("Снять с игрока розыск", "С какого игрока вы хотите снять розыск", "/unwanted") end)
MenuAddMayorButton("Ордер на обыск игрока",
function() OpenPlyReasonBox("Ордер на обыск игрока", "На кого вы хотите подать ордер?", "Причина ордера?", "/warrant") end)
MenuAddMayorButton("Дать лицензию", function() RunConsoleCommand("say", "/givelicense") end)
MenuAddMayorButton("Объявить ком.час", function() RunConsoleCommand("say", "/lockdown") end)
MenuAddMayorButton("Завершить ком.час", function() RunConsoleCommand("say", "/unlockdown") end)
MenuAddMayorButton("Добавить правило",
function() OpenTextBox("Добавить правило", "Какое новое правило вы хотите добавить?", "/addlaw") end)
MenuAddMayorButton("Убрать правило", function() OpenTextBox("Убрать правило", "Номер правила?", "/removelaw") end)
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,149 @@
/*----------------------------------------------------------------------
Leak by Famouse
Play good games:
http://store.steampowered.com/curator/32364216
Subscribe to the channel:
https://www.youtube.com/c/Famouse
More leaks in the discord:
discord.gg/rFdQwzm
------------------------------------------------------------------------*/
local PANEL = {}
function PANEL:Init()
SmoothCommandDPanel = vgui.Create( "DPanel", SmoothF4MenuFrame )
SmoothCommandDPanel:SetPos( 50, 40 )
SmoothCommandDPanel:SetSize( 950, 605 )
SmoothCommandDPanel.Paint = function() end
SmoothCommandDPanelScroll = vgui.Create( "DPanel", SmoothCommandDPanel )
SmoothCommandDPanelScroll:SetPos( 0, 0 )
SmoothCommandDPanelScroll:SetSize( 1000, 605 )
SmoothCommandDPanelScroll.Paint = function()
draw.RoundedBox( 0, 0, 0, 685, 660 , Color(255,255,255,0) )
end
local scroll = vgui.Create("DScrollPanel", SmoothCommandDPanelScroll)
scroll:SetSize(1000, 605)
scroll:SetPos(0, 0)
function scroll:Paint(w, h)
draw.RoundedBox(0, 0, 0, 0, 0, Color(42, 46, 48, 0))
end
local scrollbar = scroll:GetVBar()
function scrollbar:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(46, 49, 54, 0))
end
function scrollbar.btnUp:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
function scrollbar.btnDown:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
function scrollbar.btnGrip:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
SmoothCommandPanelPoxY = 0
for k,v in pairs(Categories) do
local CategoriesTitle = vgui.Create("DLabel", scroll)
CategoriesTitle:SizeToContents()
CategoriesTitle:SetPos(5, SmoothCommandPanelPoxY)
CategoriesTitle:SetColor(Color(255,255,255,255))
CategoriesTitle:SetText( " "..v.name )
CategoriesTitle:SetWide( SmoothCommandDPanel:GetWide()-10 )
CategoriesTitle:SetFont( "SmoothF4menuFontButton" )
CategoriesTitle:SetTall(35)
CategoriesTitle.Paint = function()
draw.RoundedBox( 0, 0, 0, CategoriesTitle:GetWide(), CategoriesTitle:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,CategoriesTitle:GetWide(), CategoriesTitle:GetTall() )
end
CategoriesTitle.Think = function() CategoriesTitle:SetWide( SmoothCommandDPanel:GetWide()-10 ) end
SmoothCommandPanelPoxY = SmoothCommandPanelPoxY + 40
for d,c in pairs(v.Table) do
local ButtonComamndClick = vgui.Create("DButton", scroll)
ButtonComamndClick:SetSize( SmoothCommandDPanel:GetWide()-35, 35 )
ButtonComamndClick:SetPos( 30 , SmoothCommandPanelPoxY )
ButtonComamndClick:SetColor( Color( 255, 255, 255 ))
ButtonComamndClick:SetFont("SmoothF4menuFontButton")
ButtonComamndClick:SetText(c.NAME)
ButtonComamndClick.Paint = function( )
draw.RoundedBox( 0, 0, 0, ButtonComamndClick:GetWide(), ButtonComamndClick:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,ButtonComamndClick:GetWide(), ButtonComamndClick:GetTall() )
if ButtonComamndClick.isHover then
draw.RoundedBox( 0, 0, 0, ButtonComamndClick:GetWide(), ButtonComamndClick:GetTall() , Color(41, 41, 41,70) )
end
end
ButtonComamndClick.OnCursorEntered = function()
ButtonComamndClick.isHover = true
end
ButtonComamndClick.OnCursorExited = function()
ButtonComamndClick.isHover = false
end
ButtonComamndClick.DoClick = function()
c.FUNC()
end
ButtonComamndClick.Think = function()
ButtonComamndClick:SetSize( SmoothCommandDPanel:GetWide()-35, 35 )
end
SmoothCommandPanelPoxY = SmoothCommandPanelPoxY + 40
end
end
end
vgui.Register( "SmoothCommandPanel", PANEL, "Panel" )
function OpenTextBox(text1,text2,cmd)
Derma_StringRequest(
text1,
text2,
"",
function( text ) RunConsoleCommand( "say", cmd.." "..text ) end,
function( text ) end
)
end
function OpenPlyReasonBox(text1,text2,text3,cmd)
local menu = DermaMenu()
for k,v in pairs(player.GetAll()) do
menu:AddOption(v:Name(),function()
Derma_StringRequest(
text1,
text3,
"",
function( text ) RunConsoleCommand( "say", cmd.." "..v:Name().." "..text ) end,
function( text ) end
)
end)
end
menu:Open()
end
function OpenPlyBox(text1,text2,cmd)
local menu = DermaMenu()
for k,v in pairs(player.GetAll()) do
menu:AddOption(v:Name(),function()
RunConsoleCommand( "say", cmd.." "..v:Name() )
end)
end
menu:Open()
end
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,237 @@
/*----------------------------------------------------------------------
Leak by Famouse
Play good games:
http://store.steampowered.com/curator/32364216
Subscribe to the channel:
www.youtube.com/c/Famouse
More leaks in the discord:
https://discord.gg/rFdQwzm
------------------------------------------------------------------------*/
local PANEL = {}
function PANEL:Init()
SmoothJobsDPanel = vgui.Create( "DPanel", SmoothF4MenuFrame )
SmoothJobsDPanel:SetPos( 50, 35 )
SmoothJobsDPanel:SetSize( 950, 615 )
SmoothJobsDPanel.Paint = function() end
SmoothJobsDPanelScroll = vgui.Create( "DPanel", SmoothJobsDPanel )
SmoothJobsDPanelScroll:SetPos( 0, 0 )
SmoothJobsDPanelScroll:SetSize( 1000, 615 )
SmoothJobsDPanelScroll.Paint = function()
draw.RoundedBox( 0, 0, 0, 685, 660 , Color(255,255,255,0) )
end
local scroll = vgui.Create("DScrollPanel", SmoothJobsDPanelScroll)
scroll:SetSize(1000, 615)
scroll:SetPos(0, 0)
function scroll:Paint(w, h)
draw.RoundedBox(0, 0, 0, 0, 0, Color(42, 46, 48, 0))
end
local scrollbar = scroll:GetVBar()
function scrollbar:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(46, 49, 54, 0))
end
function scrollbar.btnUp:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
function scrollbar.btnDown:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
function scrollbar.btnGrip:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
SmoothJobsDPanelPosX = 0
for k, v in pairs( RPExtraTeams ) do
local colorchange = string.Explode(" ",tostring(v.color))
local playerplayjob = 0
local playerjob = v.command
local maxjobs = v.max
for d,c in pairs(player.GetAll()) do
local jobtableplay = c:getJobTable()
if playerjob == jobtableplay.command then
playerplayjob = playerplayjob + 1
end
end
SmoothJobsMain = vgui.Create( "DPanel", scroll )
SmoothJobsMain:SetPos( 0,SmoothJobsDPanelPosX )
SmoothJobsMain:SetSize( 950, 60 )
SmoothJobsMain.Paint = function()
draw.RoundedBox( 0, 0, 0, SmoothJobsMain:GetWide(), SmoothJobsMain:GetTall() , Color(colorchange[1],colorchange[2],colorchange[3],60) )
draw.SimpleText(v.name,"SmoothF4menuFontButton",75,20,Color(255,255,255))
draw.RoundedBox( 0,0, 0, 60, 60 , Color(41, 41, 41,70) )
draw.SimpleText(playerplayjob.."/"..maxjobs,"SmoothF4menuFontButton",SmoothJobsDPanel:GetWide()-80,20,Color(255,255,255),TEXT_ALIGN_CENTER)
if v.vip then
draw.SimpleText("[VIP]","SmoothF4menuFontButton",SmoothJobsDPanel:GetWide()-150,20,Color(255,255,255))
end
end
if type( v.model ) == "table" then
model = table.Random( v.model )
else
model = v.model
end
local jobsModel = vgui.Create( "SpawnIcon", SmoothJobsMain )
jobsModel:SetSize( 56, 56 )
jobsModel:SetPos( 5, 2 )
jobsModel:SetModel( model )
local JobsSelect = vgui.Create("DButton", SmoothJobsMain)
JobsSelect:SetSize( 890,60 )
JobsSelect:SetPos( 60,0 )
JobsSelect:SetColor( Color( 255, 255, 255 ))
JobsSelect:SetFont("SmoothF4menuFontButton")
JobsSelect:SetText("")
JobsSelect.Paint = function(panel)
if JobsSelect.isHover then
draw.RoundedBox( 0,0, 0, JobsSelect:GetWide(), 60 , Color(41, 41, 41,50) )
end
end
JobsSelect.OnCursorEntered = function()
JobsSelect.isHover = true
end
JobsSelect.OnCursorExited = function()
JobsSelect.isHover = false
end
JobsSelect.DoClick = function()
if v.vip then
if table.HasValue(SmoothF4MenuFrame_VipGroup,LocalPlayer():GetUserGroup()) then
if v.vote then
RunCmd("/vote"..v.command)
SmoothF4MenuFrame:Close()
else
RunCmd("/"..v.command)
SmoothF4MenuFrame:Close()
end
else
notification.AddLegacy(SmoothF4MenuFrame_ErrorVip,NOTIFY_ERROR,2)
end
else
if v.vote then
RunCmd("/vote"..v.command)
SmoothF4MenuFrame:Close()
else
RunCmd("/"..v.command)
SmoothF4MenuFrame:Close()
end
end
end
local JobsInfoScresiption = vgui.Create("DButton", SmoothJobsMain)
JobsInfoScresiption:SetSize( 55,60 )
JobsInfoScresiption:SetPos( SmoothJobsDPanel:GetWide()-55,0 )
JobsInfoScresiption:SetColor( Color( 255, 255, 255 ))
JobsInfoScresiption:SetFont("SmoothF4menuFontButton")
JobsInfoScresiption:SetText("")
JobsInfoScresiption.Paint = function(panel)
local menuicon = Material( "materials/icons/info.png" )
surface.SetMaterial( menuicon )
if JobsInfoScresiption.isHover then
draw.RoundedBox( 0,0, 0, 55, 60 , Color(41, 41, 41,50) )
end
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(13,15,30,30 )
end
JobsInfoScresiption.Think = function()
JobsInfoScresiption:SetPos( SmoothJobsDPanel:GetWide()-55,0 )
end
JobsInfoScresiption.OnCursorEntered = function()
JobsInfoScresiption.isHover = true
end
JobsInfoScresiption.OnCursorExited = function()
JobsInfoScresiption.isHover = false
end
JobsInfoScresiption.DoClick = function()
SmoothJobsDescription(v.description,v.name,v.salary)
end
SmoothJobsDPanelPosX = SmoothJobsDPanelPosX + 60
end
end
vgui.Register( "SmoothJobsPanel", PANEL, "Panel" )
function SmoothJobsDescription(textdescription,name,salary)
SmoothJobsMainDEscription = vgui.Create( "DPanel", SmoothJobsDPanel)
SmoothJobsMainDEscription:SetPos( SmoothJobsDPanel:GetWide(),0 )
SmoothJobsMainDEscription:SetSize( SmoothJobsDPanel:GetWide(), 615 )
SmoothJobsMainDEscription.Paint = function()
draw.RoundedBox( 0,0, 0, SmoothJobsDPanel:GetWide(), 615 , Color(41, 41, 41,150) )
end
SmoothJobsMainDEscription.Think = function()
if IsValid(SmoothJobsMainDEscription) then
SmoothJobsMainDEscription:SetSize( SmoothJobsDPanel:GetWide(), 615 )
end
end
local JobsInfoScresiptionCloseDPanel = vgui.Create("DButton", SmoothJobsMainDEscription)
JobsInfoScresiptionCloseDPanel:SetSize( 55,60 )
JobsInfoScresiptionCloseDPanel:SetPos( 0,0 )
JobsInfoScresiptionCloseDPanel:SetColor( Color( 255, 255, 255 ))
JobsInfoScresiptionCloseDPanel:SetFont("SmoothF4menuFontButton")
JobsInfoScresiptionCloseDPanel:SetText("")
JobsInfoScresiptionCloseDPanel.Paint = function(panel)
local menuicon = Material( "materials/icons/back.png" )
surface.SetMaterial( menuicon )
if JobsInfoScresiptionCloseDPanel.isHover then
surface.SetDrawColor( 200, 200, 200, 255 )
else
surface.SetDrawColor( 255, 255, 255, 255 )
end
surface.DrawTexturedRect(15,20,32,32 )
end
JobsInfoScresiptionCloseDPanel.OnCursorEntered = function()
JobsInfoScresiptionCloseDPanel.isHover = true
end
JobsInfoScresiptionCloseDPanel.OnCursorExited = function()
JobsInfoScresiptionCloseDPanel.isHover = false
end
JobsInfoScresiptionCloseDPanel.DoClick = function()
SmoothJobsMainDEscription:MoveTo(SmoothJobsDPanel:GetWide(),0,0.3,0,-1)
SmoothJobsDPanelScroll:MoveTo(0,0,0.3,0,-1)
timer.Simple(0.3,function()
SmoothJobsMainDEscription:Remove()
end)
end
local DescriptionJobs = vgui.Create("DTextEntry", SmoothJobsMainDEscription)
DescriptionJobs:SizeToContents()
DescriptionJobs:SetPos(15, 65)
DescriptionJobs:SetTextColor(Color(255,255,255,255))
DescriptionJobs:SetMultiline( true )
DescriptionJobs:SetEditable( false )
DescriptionJobs:SetFont("SmoothF4menuFontButton")
DescriptionJobs:SetWrap( true )
DescriptionJobs:SetText( SmoothF4MenuFrame_DescriptionJobs..": \n\n"..name.."\n"..SmoothF4MenuFrame_DescriptionSalary..": "..salary..SmoothF4MenuFrame_Money.."\n\n"..textdescription )
DescriptionJobs:SetDrawBorder(false)
DescriptionJobs:SetDrawBackground(false)
DescriptionJobs:SetSize(SmoothJobsMainDEscription:GetWide()-15,550)
DescriptionJobs.Think = function()
DescriptionJobs:SetSize(SmoothJobsMainDEscription:GetWide()-15,550)
end
SmoothJobsMainDEscription:MoveTo(0,0,0.3,0,-1)
SmoothJobsDPanelScroll:MoveTo(-1000,0,0.3,0,-1)
end
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,458 @@
/*----------------------------------------------------------------------
Leak by Famouse
Play good games:
store.steampowered.com/curator/32364216
Subscribe to the channel:
https://www.youtube.com/c/Famouse
More leaks in the discord:
https://discord.gg/rFdQwzm
------------------------------------------------------------------------*/
local PANEL = {}
function PANEL:Init()
SmoothShopDPanel = vgui.Create( "DPanel", SmoothF4MenuFrame )
SmoothShopDPanel:SetPos( 50, 40 )
SmoothShopDPanel:SetSize( 950, 605 )
SmoothShopDPanel.Paint = function() end
SmoothShopDPanelScroll = vgui.Create( "DPanel", SmoothShopDPanel )
SmoothShopDPanelScroll:SetPos( 0, 0 )
SmoothShopDPanelScroll:SetSize( 1000, 605 )
SmoothShopDPanelScroll.Paint = function()
draw.RoundedBox( 0, 0, 0, 685, 660 , Color(255,255,255,0) )
end
local scroll = vgui.Create("DScrollPanel", SmoothShopDPanelScroll)
scroll:SetSize(1000, 605)
scroll:SetPos(0, 0)
function scroll:Paint(w, h)
draw.RoundedBox(0, 0, 0, 0, 0, Color(42, 46, 48, 0))
end
local scrollbar = scroll:GetVBar()
function scrollbar:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(46, 49, 54, 0))
end
function scrollbar.btnUp:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
function scrollbar.btnDown:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
function scrollbar.btnGrip:Paint(w, h)
draw.RoundedBox(3, 5, 0, 0, 0, Color(36, 39, 44, 0))
end
SmoothShopDPanelPosX = 0
local EntityTitle = vgui.Create("DLabel", scroll)
EntityTitle:SizeToContents()
EntityTitle:SetPos(5, 0)
EntityTitle:SetColor(Color(255,255,255,255))
EntityTitle:SetText( " "..SmoothF4MenuFrame_Entities )
EntityTitle:SetWide( SmoothShopDPanel:GetWide()-10 )
EntityTitle:SetFont( "SmoothF4menuFontButton" )
EntityTitle:SetTall(35)
EntityTitle.Paint = function()
draw.RoundedBox( 0, 0, 0, EntityTitle:GetWide(), EntityTitle:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,EntityTitle:GetWide(), EntityTitle:GetTall() )
end
EntityTitle.Think = function() EntityTitle:SetWide( SmoothShopDPanel:GetWide()-10 ) end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 40
DarkRPEntitiesCount = 0
for k,v in pairs(DarkRPEntities) do
local canbuy = false
if v.allowed then
if istable(v.allowed) then
if table.HasValue(v.allowed,LocalPlayer():Team()) then
canbuy = true
end
elseif v.allowed == LocalPlayer():Team() then
canbuy = true
end
else
canbuy = true
end
if canbuy then
DarkRPEntitiesCount = DarkRPEntitiesCount + 1
EnitytMain = vgui.Create( "DPanel", scroll )
EnitytMain:SetPos( 30,SmoothShopDPanelPosX)
EnitytMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
EnitytMain.Paint = function()
draw.RoundedBox( 0, 0, 0, EnitytMain:GetWide(), EnitytMain:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,EnitytMain:GetWide(), EnitytMain:GetTall() )
if v.vip then
draw.SimpleText("[VIP]","SmoothF4menuFontButton",EnitytMain:GetWide()-55,15,Color(255,255,255))
end
end
EnitytMain.Think = function()
if IsValid(EnitytMain) then
EnitytMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
end
end
local entModel = vgui.Create( "SpawnIcon", EnitytMain )
entModel:SetSize( 50, 48 )
entModel:SetPos( 5, 1 )
entModel:SetModel( v.model )
local EnitytItem = vgui.Create("DLabel", EnitytMain)
EnitytItem:SizeToContents()
EnitytItem:SetPos(75, 5)
EnitytItem:SetColor(Color(255,255,255,255))
EnitytItem:SetText( v.name )
EnitytItem:SetWide( 500 )
EnitytItem:SetFont( "SmoothF4menuFontButton" )
EnitytItem:SetTall(20)
local EnitytCost = vgui.Create("DLabel", EnitytMain)
EnitytCost:SizeToContents()
EnitytCost:SetPos(75, 26)
EnitytCost:SetColor(Color(255,255,255,255))
EnitytCost:SetText( SmoothF4MenuFrame_Money..v.price )
EnitytCost:SetWide( 500 )
EnitytCost:SetFont( "SmoothF4menuFontButton" )
EnitytCost:SetTall(20)
local EnitytBuy = vgui.Create("DButton", EnitytMain)
EnitytBuy:SetSize( EnitytMain:GetWide(), 50 )
EnitytBuy:SetPos( 0 , 0 )
EnitytBuy:SetColor( Color( 255, 255, 255 ))
EnitytBuy:SetFont("SmoothF4menuFontButton")
EnitytBuy:SetText("")
EnitytBuy.Paint = function( )
if EnitytBuy.isHover then
draw.RoundedBox( 0, 0, 0, EnitytMain:GetWide(), EnitytMain:GetTall() , Color(41, 41, 41,70) )
end
end
EnitytBuy.OnCursorEntered = function()
EnitytBuy.isHover = true
end
EnitytBuy.OnCursorExited = function()
EnitytBuy.isHover = false
end
EnitytBuy.DoClick = function()
if v.vip then
if table.HasValue(SmoothF4MenuFrame_VipEntity,LocalPlayer():GetUserGroup()) then
RunEntCmd(v.cmd)
else
notification.AddLegacy(SmoothF4MenuFrame_ErrorVip,NOTIFY_ERROR,2)
end
else
RunEntCmd(v.cmd)
end
end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 55
end
end
if DarkRPEntitiesCount == 0 then if IsValid(EntityTitle) then EntityTitle:Remove() SmoothShopDPanelPosX = SmoothShopDPanelPosX - 40 end end
if SmoothF4MenuFrame_EnableWeapon then
local WeaponTitle = vgui.Create("DLabel", scroll)
WeaponTitle:SizeToContents()
WeaponTitle:SetPos(5, SmoothShopDPanelPosX)
WeaponTitle:SetColor(Color(255,255,255,255))
WeaponTitle:SetText( " "..SmoothF4MenuFrame_Weapon )
WeaponTitle:SetWide( SmoothShopDPanel:GetWide()-10 )
WeaponTitle:SetFont( "SmoothF4menuFontButton" )
WeaponTitle:SetTall(35)
WeaponTitle.Paint = function()
draw.RoundedBox( 0, 0, 0, WeaponTitle:GetWide(), WeaponTitle:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,WeaponTitle:GetWide(), WeaponTitle:GetTall() )
end
WeaponTitle.Think = function() WeaponTitle:SetWide( SmoothShopDPanel:GetWide()-10 ) end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 40
CustomShipmentsCount = 0
for k,v in pairs(CustomShipments) do
if (v.seperate and (not GAMEMODE.Config.restrictbuypistol or
(GAMEMODE.Config.restrictbuypistol and (not v.allowed[1] or table.HasValue(v.allowed, LocalPlayer():Team())))))
and (not v.customCheck or v.customCheck and v.customCheck(LocalPlayer())) then
CustomShipmentsCount = CustomShipmentsCount + 1
WeaponMain = vgui.Create( "DPanel", scroll )
WeaponMain:SetPos( 30,SmoothShopDPanelPosX)
WeaponMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
WeaponMain.Paint = function()
draw.RoundedBox( 0, 0, 0, EnitytMain:GetWide(), EnitytMain:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,EnitytMain:GetWide(), EnitytMain:GetTall() )
draw.SimpleText("х1","SmoothF4menuFontButton",WeaponMain:GetWide()-44,15,Color(255,255,255))
if v.vip then
draw.SimpleText("[VIP]","SmoothF4menuFontButton",EnitytMain:GetWide()-110,15,Color(255,255,255))
end
end
WeaponMain.Think = function()
if IsValid(WeaponMain) then
WeaponMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
end
end
local entModel = vgui.Create( "SpawnIcon", WeaponMain )
entModel:SetSize( 50, 48 )
entModel:SetPos( 5, 1 )
entModel:SetModel( v.model )
local WeaponItem = vgui.Create("DLabel", WeaponMain)
WeaponItem:SizeToContents()
WeaponItem:SetPos(75, 5)
WeaponItem:SetColor(Color(255,255,255,255))
WeaponItem:SetText( v.name )
WeaponItem:SetWide( 250 )
WeaponItem:SetFont( "SmoothF4menuFontButton" )
WeaponItem:SetTall(20)
local WeaponCost = vgui.Create("DLabel", WeaponMain)
WeaponCost:SizeToContents()
WeaponCost:SetPos(75, 26)
WeaponCost:SetColor(Color(255,255,255,255))
WeaponCost:SetText( SmoothF4MenuFrame_Money..v.pricesep )
WeaponCost:SetWide( 150 )
WeaponCost:SetFont( "SmoothF4menuFontButton" )
WeaponCost:SetTall(20)
local WeaponBuy = vgui.Create("DButton", WeaponMain)
WeaponBuy:SetSize( WeaponMain:GetWide(), 50 )
WeaponBuy:SetPos( 0 , 0 )
WeaponBuy:SetColor( Color( 255, 255, 255 ))
WeaponBuy:SetFont("SmoothF4menuFontButton")
WeaponBuy:SetText("")
WeaponBuy.Paint = function( )
if WeaponBuy.isHover then
draw.RoundedBox( 0, 0, 0, EnitytMain:GetWide(), EnitytMain:GetTall() , Color(41, 41, 41,70) )
end
end
WeaponBuy.OnCursorEntered = function()
WeaponBuy.isHover = true
end
WeaponBuy.OnCursorExited = function()
WeaponBuy.isHover = false
end
WeaponBuy.DoClick = function()
if v.vip then
if table.HasValue(SmoothF4MenuFrame_VipWeapon,LocalPlayer():GetUserGroup()) then
RunEntCmd("buy "..v.name)
else
notification.AddLegacy(SmoothF4MenuFrame_ErrorVip,NOTIFY_ERROR,2)
end
else
RunEntCmd("buy "..v.name)
end
end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 55
end
end
if CustomShipmentsCount == 0 then if IsValid(WeaponTitle) then WeaponTitle:Remove() SmoothShopDPanelPosX = SmoothShopDPanelPosX - 40 end end
end
if SmoothF4MenuFrame_EnableShipments then
local ShipMentsTitle = vgui.Create("DLabel", scroll)
ShipMentsTitle:SizeToContents()
ShipMentsTitle:SetPos(5, SmoothShopDPanelPosX)
ShipMentsTitle:SetColor(Color(255,255,255,255))
ShipMentsTitle:SetText( " "..SmoothF4MenuFrame_Shipments )
ShipMentsTitle:SetWide( SmoothShopDPanel:GetWide()-10 )
ShipMentsTitle:SetFont( "SmoothF4menuFontButton" )
ShipMentsTitle:SetTall(35)
ShipMentsTitle.Paint = function()
draw.RoundedBox( 0, 0, 0, ShipMentsTitle:GetWide(), ShipMentsTitle:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,ShipMentsTitle:GetWide(), ShipMentsTitle:GetTall() )
end
ShipMentsTitle.Think = function() ShipMentsTitle:SetWide( SmoothShopDPanel:GetWide()-10 ) end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 40
CustomShipmentsShipments = 0
for k,v in pairs(CustomShipments) do
if !v.noship and table.HasValue(v.allowed, LocalPlayer():Team())
and (not v.customCheck or (v.customCheck and v.customCheck(LocalPlayer()))) then
CustomShipmentsShipments = CustomShipmentsShipments + 1
ShipmentsMain = vgui.Create( "DPanel", scroll )
ShipmentsMain:SetPos( 30,SmoothShopDPanelPosX)
ShipmentsMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
ShipmentsMain.Paint = function()
draw.RoundedBox( 0, 0, 0, EnitytMain:GetWide(), EnitytMain:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,EnitytMain:GetWide(), EnitytMain:GetTall() )
draw.SimpleText("х"..v.amount,"SmoothF4menuFontButton",ShipmentsMain:GetWide()-50,15,Color(255,255,255))
if v.vip then
draw.SimpleText("[VIP]","SmoothF4menuFontButton",EnitytMain:GetWide()-110,15,Color(255,255,255))
end
end
ShipmentsMain.Think = function()
if IsValid(ShipmentsMain) then
ShipmentsMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
end
end
local entModel = vgui.Create( "SpawnIcon", ShipmentsMain )
entModel:SetSize( 50, 48 )
entModel:SetPos( 5, 1 )
entModel:SetModel( v.model )
local ShipmentsItem = vgui.Create("DLabel", ShipmentsMain)
ShipmentsItem:SizeToContents()
ShipmentsItem:SetPos(75, 5)
ShipmentsItem:SetColor(Color(255,255,255,255))
ShipmentsItem:SetText( v.name )
ShipmentsItem:SetWide( 250 )
ShipmentsItem:SetFont( "SmoothF4menuFontButton" )
ShipmentsItem:SetTall(20)
local ShipmentsCost = vgui.Create("DLabel", ShipmentsMain)
ShipmentsCost:SizeToContents()
ShipmentsCost:SetPos(75, 26)
ShipmentsCost:SetColor(Color(255,255,255,255))
ShipmentsCost:SetText( SmoothF4MenuFrame_Money..v.price )
ShipmentsCost:SetWide( 150 )
ShipmentsCost:SetFont( "SmoothF4menuFontButton" )
ShipmentsCost:SetTall(20)
local ShipmentsBuy = vgui.Create("DButton", ShipmentsMain)
ShipmentsBuy:SetSize( ShipmentsMain:GetWide(), 50 )
ShipmentsBuy:SetPos( 0 , 0 )
ShipmentsBuy:SetColor( Color( 255, 255, 255 ))
ShipmentsBuy:SetFont("SmoothF4menuFontButton")
ShipmentsBuy:SetText("")
ShipmentsBuy.Paint = function( )
if ShipmentsBuy.isHover then
draw.RoundedBox( 0, 0, 0, EnitytMain:GetWide(), EnitytMain:GetTall() , Color(41, 41, 41,70) )
end
end
ShipmentsBuy.OnCursorEntered = function()
ShipmentsBuy.isHover = true
end
ShipmentsBuy.OnCursorExited = function()
ShipmentsBuy.isHover = false
end
ShipmentsBuy.DoClick = function()
if v.vip then
if table.HasValue(SmoothF4MenuFrame_VipShipments,LocalPlayer():GetUserGroup()) then
RunEntCmd("buyshipment "..v.name)
else
notification.AddLegacy(SmoothF4MenuFrame_ErrorVip,NOTIFY_ERROR,2)
end
else
RunEntCmd("buyshipment "..v.name)
end
end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 55
end
end
if CustomShipmentsShipments == 0 then if IsValid(ShipMentsTitle) then ShipMentsTitle:Remove() SmoothShopDPanelPosX = SmoothShopDPanelPosX - 40 end end
end
if SmoothF4MenuFrame_EnableAmmo then
local AmmoTitle = vgui.Create("DLabel", scroll)
AmmoTitle:SizeToContents()
AmmoTitle:SetPos(5, SmoothShopDPanelPosX)
AmmoTitle:SetColor(Color(255,255,255,255))
AmmoTitle:SetText( " "..SmoothF4MenuFrame_Ammo )
AmmoTitle:SetWide( SmoothShopDPanel:GetWide()-10 )
AmmoTitle:SetFont( "SmoothF4menuFontButton" )
AmmoTitle:SetTall(35)
AmmoTitle.Paint = function()
draw.RoundedBox( 0, 0, 0, AmmoTitle:GetWide(), AmmoTitle:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,AmmoTitle:GetWide(), AmmoTitle:GetTall() )
end
AmmoTitle.Think = function() AmmoTitle:SetWide( SmoothShopDPanel:GetWide()-10 ) end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 40
CustomAmmoAmmo = 0
for k,v in pairs(GAMEMODE.AmmoTypes) do
CustomAmmoAmmo = CustomAmmoAmmo + 1
AmmoMain = vgui.Create( "DPanel", scroll )
AmmoMain:SetPos( 30,SmoothShopDPanelPosX)
AmmoMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
AmmoMain.Paint = function()
draw.RoundedBox( 0, 0, 0, AmmoMain:GetWide(), AmmoMain:GetTall() , Color(41, 41, 41,100) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,AmmoMain:GetWide(), AmmoMain:GetTall() )
draw.SimpleText("х"..v.amountGiven,"SmoothF4menuFontButton",AmmoMain:GetWide()-47,15,Color(255,255,255))
end
AmmoMain.Think = function()
if IsValid(AmmoMain) then
AmmoMain:SetSize( SmoothShopDPanel:GetWide()-35, 50 )
end
end
local entModel = vgui.Create( "SpawnIcon", AmmoMain )
entModel:SetSize( 50, 48 )
entModel:SetPos( 5, 1 )
entModel:SetModel( v.model )
local AmmoItem = vgui.Create("DLabel", AmmoMain)
AmmoItem:SizeToContents()
AmmoItem:SetPos(75, 5)
AmmoItem:SetColor(Color(255,255,255,255))
AmmoItem:SetText( v.name )
AmmoItem:SetWide( 250 )
AmmoItem:SetFont( "SmoothF4menuFontButton" )
AmmoItem:SetTall(20)
local AmmoCost = vgui.Create("DLabel", AmmoMain)
AmmoCost:SizeToContents()
AmmoCost:SetPos(75, 26)
AmmoCost:SetColor(Color(255,255,255,255))
AmmoCost:SetText( SmoothF4MenuFrame_Money..v.price )
AmmoCost:SetWide( 150 )
AmmoCost:SetFont( "SmoothF4menuFontButton" )
AmmoCost:SetTall(20)
local AmmoBuy = vgui.Create("DButton", AmmoMain)
AmmoBuy:SetSize( AmmoMain:GetWide(), 50 )
AmmoBuy:SetPos( 0 , 0 )
AmmoBuy:SetColor( Color( 255, 255, 255 ))
AmmoBuy:SetFont("SmoothF4menuFontButton")
AmmoBuy:SetText("")
AmmoBuy.Paint = function( )
if AmmoBuy.isHover then
draw.RoundedBox( 0, 0, 0, AmmoMain:GetWide(), AmmoMain:GetTall() , Color(41, 41, 41,70) )
end
end
AmmoBuy.OnCursorEntered = function()
AmmoBuy.isHover = true
end
AmmoBuy.OnCursorExited = function()
AmmoBuy.isHover = false
end
AmmoBuy.DoClick = function()
RunEntCmd( "buyammo "..v.ammoType )
end
SmoothShopDPanelPosX = SmoothShopDPanelPosX + 55
end
if CustomAmmoAmmo == 0 then if IsValid(AmmoTitle) then AmmoTitle:Remove() end end
end
end
vgui.Register( "SmoothShopPanel", PANEL, "Panel" )
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,80 @@
local PANEL = {}
function PANEL:Init()
SmoothSiteDPanel = vgui.Create( "DPanel", SmoothF4MenuFrame )
SmoothSiteDPanel:SetPos( 50, 35 )
SmoothSiteDPanel:SetSize( 950, 615 )
SmoothSiteDPanel.Paint = function()
draw.SimpleText(SmoothF4MenuFrame_Loading,"SmoothF4menuFontButton",SmoothSiteDPanel:GetWide()/2,SmoothSiteDPanel:GetTall()/2,Color(255,255,255),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
end
local SmoothOpenHtml = vgui.Create( "HTML", SmoothSiteDPanel )
SmoothOpenHtml:SetSize(SmoothSiteDPanel:GetWide()-10, 570)
SmoothOpenHtml:SetPos(5,0)
SmoothOpenHtml:OpenURL( SmoothF4MenuFrame_SiteURL )
SmoothOpenHtml.Think = function()
SmoothOpenHtml:SetSize(SmoothSiteDPanel:GetWide()-10, 570)
end
local OpenBtn = vgui.Create("DButton", SmoothSiteDPanel)
OpenBtn:SetText("Открыть в браузере")
OpenBtn:SetFont("SmoothF4menuFontButton")
OpenBtn:SetPos(5, 575)
OpenBtn:SetSize(SmoothSiteDPanel:GetWide()-10, 35)
OpenBtn.Paint = function(self, w, h)
if self:IsHovered() then
draw.RoundedBox(0, 0, 0, w, h, Color(40, 40, 40, 255))
self:SetTextColor(Color(255, 255, 255, 255))
else
draw.RoundedBox(0, 0, 0, w, h, Color(20, 20, 20, 255))
self:SetTextColor(Color(200, 200, 200, 255))
end
end
OpenBtn.DoClick = function()
gui.OpenURL(SmoothF4MenuFrame_SiteURL)
end
end
vgui.Register( "SmoothSitePanel", PANEL, "Panel" )
local PANEL = {}
function PANEL:Init()
SmoothDonateDPanel = vgui.Create( "DPanel", SmoothF4MenuFrame )
SmoothDonateDPanel:SetPos( 50, 35 )
SmoothDonateDPanel:SetSize( 950, 615 )
SmoothDonateDPanel.Paint = function()
draw.SimpleText(SmoothF4MenuFrame_Loading,"SmoothF4menuFontButton",SmoothDonateDPanel:GetWide()/2,SmoothDonateDPanel:GetTall()/2,Color(255,255,255),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
end
local SmoothOpenHtml = vgui.Create( "HTML", SmoothDonateDPanel )
SmoothOpenHtml:SetSize(SmoothDonateDPanel:GetWide()-10, 570)
SmoothOpenHtml:SetPos(5,0)
SmoothOpenHtml:OpenURL( SmoothF4MenuFrame_DonateURL )
SmoothOpenHtml.Think = function()
SmoothOpenHtml:SetSize(SmoothDonateDPanel:GetWide()-10, 570)
end
local OpenBtn = vgui.Create("DButton", SmoothDonateDPanel)
OpenBtn:SetText("Открыть в браузере")
OpenBtn:SetFont("SmoothF4menuFontButton")
OpenBtn:SetPos(5, 575)
OpenBtn:SetSize(SmoothDonateDPanel:GetWide()-10, 35)
OpenBtn.Paint = function(self, w, h)
if self:IsHovered() then
draw.RoundedBox(0, 0, 0, w, h, Color(40, 40, 40, 255))
self:SetTextColor(Color(255, 255, 255, 255))
else
draw.RoundedBox(0, 0, 0, w, h, Color(20, 20, 20, 255))
self:SetTextColor(Color(200, 200, 200, 255))
end
end
OpenBtn.DoClick = function()
gui.OpenURL(SmoothF4MenuFrame_DonateURL)
end
end
vgui.Register( "SmoothDonatePanel", PANEL, "Panel" )

View File

@@ -0,0 +1,153 @@
/*----------------------------------------------------------------------
Leak by Famouse
Play good games:
store.steampowered.com/curator/32364216
Subscribe to the channel:
https://www.youtube.com/c/Famouse
More leaks in the discord:
discord.gg/rFdQwzm
------------------------------------------------------------------------*/
local PANEL = {}
function PANEL:Init()
SmoothTitleDPanel = vgui.Create( "DPanel", SmoothF4MenuFrame )
SmoothTitleDPanel:SetPos( 50, 35 )
SmoothTitleDPanel:SetSize( 950, 615 )
SmoothTitleDPanel.Paint = function()
end
SmoothPanelInfoServer = vgui.Create( "DPanel", SmoothTitleDPanel )
SmoothPanelInfoServer:SetPos( 5, 5 )
SmoothPanelInfoServer:SetSize( SmoothTitleDPanel:GetWide()-10, 70 )
SmoothPanelInfoServer.Paint = function()
draw.RoundedBox( 0, 0, 0, SmoothPanelInfoServer:GetWide(), SmoothPanelInfoServer:GetTall() , Color(47, 47, 47,150) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothPanelInfoServer:GetWide(), SmoothPanelInfoServer:GetTall())
draw.SimpleText(SmoothF4MenuFrame_NameServer,"SmoothF4menuFont1",29,2,Color(255,255,255))
draw.RoundedBox( 2, 5, 35, SmoothPanelInfoServer:GetWide()-14, 2 , Color(255,255,255) )
local menuicon = Material( "materials/icons/database.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(5,7,22,22 )
local onlineplayer = 0
for k,v in pairs(player.GetAll()) do onlineplayer = onlineplayer + 1 end
draw.SimpleText(SmoothF4MenuFrame_OnlinePlayer..": "..onlineplayer,"SmoothF4menuFontButton",30,43,Color(255,255,255))
local menuicon = Material( "materials/icons/user.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(9,46,15,15 )
end
SmoothPanelInfoServer.Think = function() SmoothPanelInfoServer:SetSize( SmoothTitleDPanel:GetWide()-10, 70 ) end
SmoothPanelInfoPlayer = vgui.Create( "DPanel", SmoothTitleDPanel )
SmoothPanelInfoPlayer:SetPos( 5, 80 )
SmoothPanelInfoPlayer:SetSize( SmoothTitleDPanel:GetWide()-10, 85 )
SmoothPanelInfoPlayer.Paint = function()
draw.RoundedBox( 0, 0, 0, SmoothPanelInfoPlayer:GetWide(), SmoothPanelInfoPlayer:GetTall() , Color(47, 47, 47,150) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothPanelInfoPlayer:GetWide(), SmoothPanelInfoPlayer:GetTall())
draw.SimpleText(LocalPlayer():Name(),"SmoothF4menuFont1",90,3,Color(255,255,255))
draw.RoundedBox( 2, 91, 35, SmoothPanelInfoPlayer:GetWide()-100, 2 , Color(255,255,255) )
draw.SimpleText(SmoothF4MenuFrame_TMoney..": "..LocalPlayer():getDarkRPVar("money")..SmoothF4MenuFrame_Money,"SmoothF4menuFontButton",90,40,Color(255,255,255))
draw.SimpleText(SmoothF4MenuFrame_Group..": "..LocalPlayer():GetUserGroup(),"SmoothF4menuFontButton",90,59,Color(255,255,255))
end
SmoothPanelInfoPlayer.Think = function() SmoothPanelInfoPlayer:SetSize( SmoothTitleDPanel:GetWide()-10, 85 ) end
local Avatar = vgui.Create( "AvatarImage", SmoothPanelInfoPlayer )
Avatar:SetSize( 75, 75 )
Avatar:SetPos( 5, 5 )
Avatar:SetPlayer( LocalPlayer(), 128 )
SmoothPanelStaffOnline = vgui.Create( "DPanel", SmoothTitleDPanel )
SmoothPanelStaffOnline:SetPos( 5, 170 )
SmoothPanelStaffOnline:SetSize( 300, 440 )
SmoothPanelStaffOnline.Paint = function()
draw.RoundedBox( 0, 0, 0, SmoothPanelStaffOnline:GetWide(), SmoothPanelStaffOnline:GetTall() , Color(47, 47, 47,150) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothPanelStaffOnline:GetWide(), SmoothPanelStaffOnline:GetTall())
draw.SimpleText(SmoothF4MenuFrame_TStaffOnline,"SmoothF4menuFont1",5,3,Color(255,255,255))
draw.RoundedBox( 2, 5, 35, 290, 2 , Color(255,255,255) )
end
SmoothPanelStaffOnline.Think = function() SmoothPanelStaffOnline:SetSize( 300, 440 ) end
SmoothStaffPosY = 34
SmoothStaffPosYNumber = 0
for k,v in pairs(player.GetAll()) do
if SmoothStaffPosYNumber < 17 then
if table.HasValue(SmoothF4MenuFrame_StaffOnline,v:GetUserGroup()) then
local SmoothStaffLabel = vgui.Create("DLabel", SmoothPanelStaffOnline)
SmoothStaffLabel:SetPos(5, SmoothStaffPosY)
SmoothStaffLabel:SetColor(Color(255,255,255,255))
SmoothStaffLabel:SetText( "" )
SmoothStaffLabel:SetWide( 290 )
SmoothStaffLabel:SetFont( "SmoothF4menuFontButton" )
SmoothStaffLabel:SetTall(100)
SmoothStaffLabel.Paint = function()
draw.SimpleText(v:Name().." - "..v:GetUserGroup(),"SmoothF4menuFontButton",0,6,Color(255,255,255))
end
SmoothStaffPosYNumber = SmoothStaffPosYNumber + 1
SmoothStaffPosY = SmoothStaffPosY + 23.5
end
end
end
SmoothPanelRules = vgui.Create( "DPanel", SmoothTitleDPanel )
SmoothPanelRules:SetPos( 310, 170 )
SmoothPanelRules:SetSize( SmoothTitleDPanel:GetWide()-310, 440 )
SmoothPanelRules.Paint = function()
draw.RoundedBox( 0, 0, 0, SmoothPanelRules:GetWide(), SmoothPanelRules:GetTall() , Color(47, 47, 47,150) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothPanelRules:GetWide(), SmoothPanelRules:GetTall())
draw.SimpleText(SmoothF4MenuFrame_RulesTitle,"SmoothF4menuFont1",5,3,Color(255,255,255))
draw.RoundedBox( 2, 5, 35, SmoothTitleDPanel:GetWide()-330, 2 , Color(255,255,255) )
end
SmoothPanelRules.Think = function() SmoothPanelRules:SetSize( SmoothTitleDPanel:GetWide()-315, 440 ) end
local SmoothStaffLabel = vgui.Create("DLabel", SmoothPanelRules)
SmoothStaffLabel:SetPos(10, 45)
SmoothStaffLabel:SetColor(Color(255,255,255,255))
SmoothStaffLabel:SetText( "" )
SmoothStaffLabel:SetWide( SmoothPanelRules:GetWide()-20 )
SmoothStaffLabel:SetFont( "SmoothF4menuFontButton" )
SmoothStaffLabel:SetTall(1)
SmoothStaffLabel.Paint = function() end
SmoothStaffLabel.Think = function()
rulestext = ""
for k,v in pairs(DarkRP.getLaws()) do
rulestext = rulestext..v.."\n"
end
rulestext = DarkRP.textWrap(rulestext, "DarkRPHUD1", SmoothPanelRules:GetWide()-20)
rulestextexp = string.Explode("\n",rulestext)
SmoothStaffLabel:SetText( rulestext )
SmoothStaffLabel:SetTall(#rulestextexp*20)
end
end
vgui.Register( "SmoothTitlePanel", PANEL, "Panel" )
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,425 @@
/*----------------------------------------------------------------------
Leak by Famouse
Play good games:
store.steampowered.com/curator/32364216
Subscribe to the channel:
https://www.youtube.com/c/Famouse
More leaks in the discord:
discord.gg/rFdQwzm
------------------------------------------------------------------------*/
surface.CreateFont( "SmoothF4menuFont1", {
font = "Open Sans",
size = 30,
weight = 700,
antialias = true,
})
surface.CreateFont( "SmoothF4menuFontButton", {
font = "Open Sans",
size = 20,
weight = 700,
antialias = true,
})
Texts = {}
Texts.DarkRPCommand = "say"
function RunEntCmd(...)
local arg = {...}
if Texts.DarkRPCommand:lower():find('say') then
arg = table.concat(arg,' ')
else
arg = table.concat(arg,'" "')
end
RunConsoleCommand(Texts.DarkRPCommand, "/"..arg)
end
function RunCmd(...)
local arg = {...}
if Texts.DarkRPCommand:lower():find('say') then
arg = table.concat(arg,' ')
else
arg = table.concat(arg,'" "')
end
RunConsoleCommand(Texts.DarkRPCommand,arg)
end
function ClearAllDPanel()
if IsValid(SmoothJobsDPanel) then SmoothJobsDPanel:Remove() end
if IsValid(SmoothShopDPanel) then SmoothShopDPanel:Remove() end
if IsValid(SmoothSiteDPanel) then SmoothSiteDPanel:Remove() end
if IsValid(SmoothTitleDPanel) then SmoothTitleDPanel:Remove() end
if IsValid(SmoothCommandDPanel) then SmoothCommandDPanel:Remove() end
if IsValid(SmoothDonateDPanel) then SmoothDonateDPanel:Remove() end
end
timersimpleasd = 0
hook.Add("Think","CloseF4Menu",function()
if CurTime() > timersimpleasd then
if input.IsKeyDown(KEY_F4) then
if IsValid(SmoothF4MenuFrame) then
-- SmoothF4MenuFrame:MoveTo( -1000,ScrH()/2-(SmoothF4MenuFrame:GetTall()/2), 0, 0, -1)
-- timer.Simple(0.5,function() SmoothF4MenuFrame:Close() end)
SmoothF4MenuFrame:Close()
end
timersimpleasd = CurTime() + 1
end
end
end)
net.Receive("OpenSmoothF4menu",function()
if IsValid(SmoothF4MenuFrame) then SmoothF4MenuFrame:Close() end
timer.Simple(0,function() local SmoothTitlePanel = SmoothF4MenuFrame:Add("SmoothTitlePanel") end)
SmoothF4MenuFrame = vgui.Create("DFrame")
SmoothF4MenuFrame:SetSize(1000, 650)
SmoothF4MenuFrame:SetPos(-1000,ScrH()/2-(SmoothF4MenuFrame:GetTall()/2))
SmoothF4MenuFrame:SetDraggable( true )
SmoothF4MenuFrame:MakePopup()
SmoothF4MenuFrame:ShowCloseButton( false )
SmoothF4MenuFrame:SetTitle("")
SmoothF4MenuFrame.Paint = function( panel )
SmoothDrawBlur(panel, 3)
draw.RoundedBox( 0, 0, 0, SmoothF4MenuFrame:GetWide(), SmoothF4MenuFrame:GetTall() , Color(47, 47, 47,150) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothF4MenuFrame:GetWide(), SmoothF4MenuFrame:GetTall())
draw.RoundedBox( 0, 0, 0, SmoothF4MenuFrame:GetWide(), 35 , Color(41, 41, 41,75) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothF4MenuFrame:GetWide(), 35)
local menuicon = Material( "materials/icons/menu.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(5,5,25,25 )
end
SmoothF4MenuFrame:MoveTo( (ScrW()/2-(SmoothF4MenuFrame:GetWide()/2)),ScrH()/2-(SmoothF4MenuFrame:GetTall()/2), 0, 0, -1)
local SmoothF4Menuclose = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4Menuclose:SetSize( 45, 35 )
SmoothF4Menuclose:SetPos( SmoothF4MenuFrame:GetWide() - 45 , 0 )
SmoothF4Menuclose:SetColor( Color( 255, 255, 255 ))
SmoothF4Menuclose:SetFont("SmoothF4menuFont1")
SmoothF4Menuclose:SetText("")
SmoothF4Menuclose.Paint = function( )
local menuicon = Material( "materials/icons/close.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(13,8,19,19 )
if SmoothF4Menuclose.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4Menuclose:GetWide(), 35 , Color(41, 41, 41,75) )
end
end
SmoothF4Menuclose.OnCursorEntered = function()
SmoothF4Menuclose.isHover = true
end
SmoothF4Menuclose.OnCursorExited = function()
SmoothF4Menuclose.isHover = false
end
SmoothF4Menuclose.DoClick = function()
SmoothF4MenuFrame:Close()
end
local NameServerTitle = vgui.Create("DLabel", SmoothF4MenuFrame)
NameServerTitle:SizeToContents()
NameServerTitle:SetPos(35,0)
NameServerTitle:SetColor(Color(255,255,255,255))
NameServerTitle:SetText( SmoothF4MenuFrame_NameServer )
NameServerTitle:SetWide( 800 )
NameServerTitle:SetFont( "SmoothF4menuFont1" )
NameServerTitle:SetTall(34)
SmoothF4MenuDPanel = vgui.Create( "DPanel",SmoothF4MenuFrame )
SmoothF4MenuDPanel:SetPos( 0, 34 )
SmoothF4MenuDPanel:SetSize( 50, 616 )
SmoothF4MenuDPanel.isActive1 = false
SmoothF4MenuDPanel.isActive2 = false
SmoothF4MenuDPanel.Paint = function()
draw.RoundedBox( 0, 0, 0, SmoothF4MenuDPanel:GetWide(), SmoothF4MenuDPanel:GetTall() , Color(41, 41, 41,75) )
surface.SetDrawColor( 47, 47, 47,150 )
surface.DrawOutlinedRect(0,0,SmoothF4MenuDPanel:GetWide(), SmoothF4MenuDPanel:GetTall())
if (SmoothF4MenuDPanel.isHover or SmoothF4MenuButtonTitle.isHover or SmoothF4MenuButtonJobs.isHover or SmoothF4MenuButtonShop.isHover or SmoothF4MenuButtonSite.isHover or SmoothF4MenuButtonCommands.isHover or SmoothF4MenuButtonDonate.isHover ) and !SmoothF4MenuDPanel.isActive1 then
SmoothF4MenuDPanel:SizeTo( 250,616, 0.3, 0, -1)
SmoothF4MenuDPanel.isActive1 = true
SmoothF4MenuDPanel.isActive2 = false
-- JOBS
if IsValid(SmoothJobsDPanel) then
SmoothJobsDPanel:SizeTo( 750,615, 0.3, 0, -1)
SmoothJobsDPanel:MoveTo( 250,35, 0.3, 0, -1)
end
-- ENT
if IsValid(SmoothShopDPanel) then
SmoothShopDPanel:SizeTo( 750,605, 0.3, 0, -1)
SmoothShopDPanel:MoveTo( 250,40, 0.3, 0, -1)
end
-- SITE
if IsValid(SmoothSiteDPanel) then
SmoothSiteDPanel:SizeTo( 750,615, 0.3, 0, -1)
SmoothSiteDPanel:MoveTo( 250,40, 0.3, 0, -1)
end
-- SITE
if IsValid(SmoothDonateDPanel) then
SmoothDonateDPanel:SizeTo( 750,615, 0.3, 0, -1)
SmoothDonateDPanel:MoveTo( 250,40, 0.3, 0, -1)
end
-- TITLE
if IsValid(SmoothTitleDPanel) then
SmoothTitleDPanel:SizeTo( 750,615, 0.3, 0, -1)
SmoothTitleDPanel:MoveTo( 250,35, 0.3, 0, -1)
end
-- COMMAND
if IsValid(SmoothCommandDPanel) then
SmoothCommandDPanel:SizeTo( 750,605, 0.3, 0, -1)
SmoothCommandDPanel:MoveTo( 250,40, 0.3, 0, -1)
end
elseif (!SmoothF4MenuDPanel.isHover and !SmoothF4MenuButtonTitle.isHover and !SmoothF4MenuButtonJobs.isHover and !SmoothF4MenuButtonShop.isHover and !SmoothF4MenuButtonSite.isHover and !SmoothF4MenuButtonCommands.isHover and !SmoothF4MenuButtonDonate.isHover) and !SmoothF4MenuDPanel.isActive2 then
SmoothF4MenuDPanel:SizeTo( 50,616, 0.3, 0, -1)
SmoothF4MenuDPanel.isActive2 = true
SmoothF4MenuDPanel.isActive1 = false
-- JOBS
if IsValid(SmoothJobsDPanel) then
SmoothJobsDPanel:SizeTo( 950,615, 0.3, 0, -1)
SmoothJobsDPanel:MoveTo( 50,35, 0.3, 0, -1)
end
-- ENT
if IsValid(SmoothShopDPanel) then
SmoothShopDPanel:SizeTo( 950,605, 0.3, 0, -1)
SmoothShopDPanel:MoveTo( 50,40, 0.3, 0, -1)
end
-- SITE
if IsValid(SmoothSiteDPanel) then
SmoothSiteDPanel:SizeTo( 950,615, 0.3, 0, -1)
SmoothSiteDPanel:MoveTo( 50,40, 0.3, 0, -1)
end
-- SITE
if IsValid(SmoothDonateDPanel) then
SmoothDonateDPanel:SizeTo( 950,615, 0.3, 0, -1)
SmoothDonateDPanel:MoveTo( 50,40, 0.3, 0, -1)
end
-- TITLE
if IsValid(SmoothTitleDPanel) then
SmoothTitleDPanel:SizeTo( 950,615, 0.3, 0, -1)
SmoothTitleDPanel:MoveTo( 50,35, 0.3, 0, -1)
end
-- COMMAND
if IsValid(SmoothCommandDPanel) then
SmoothCommandDPanel:SizeTo( 950,605, 0.3, 0, -1)
SmoothCommandDPanel:MoveTo( 50,40, 0.3, 0, -1)
end
end
end
SmoothF4MenuDPanel.OnCursorEntered = function()
SmoothF4MenuDPanel.isHover = true
end
SmoothF4MenuDPanel.OnCursorExited = function()
SmoothF4MenuDPanel.isHover = false
end
SmoothF4MenuButtonTitle = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4MenuButtonTitle:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
SmoothF4MenuButtonTitle:SetPos( 0,35 )
SmoothF4MenuButtonTitle:SetColor( Color( 255, 255, 255 ))
SmoothF4MenuButtonTitle:SetFont("SmoothF4menuFontButton")
SmoothF4MenuButtonTitle:SetText("")
SmoothF4MenuButtonTitle.Paint = function(panel)
local menuicon = Material( "materials/icons/home.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(10,10,30,30 )
if SmoothF4MenuButtonTitle.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4MenuButtonTitle:GetWide(), SmoothF4MenuButtonTitle:GetTall() , Color(41, 41, 41,70) )
end
draw.SimpleText(SmoothF4MenuFrame_NameServer_Home,"SmoothF4menuFontButton",55,15,Color(255,255,255))
SmoothF4MenuButtonTitle:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
end
SmoothF4MenuButtonTitle.OnCursorEntered = function()
SmoothF4MenuButtonTitle.isHover = true
end
SmoothF4MenuButtonTitle.OnCursorExited = function()
SmoothF4MenuButtonTitle.isHover = false
end
SmoothF4MenuButtonTitle.DoClick = function()
ClearAllDPanel()
local SmoothTitlePanel = SmoothF4MenuFrame:Add("SmoothTitlePanel")
SmoothF4MenuDPanel:SetSize(50,616)
end
SmoothF4MenuButtonJobs = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4MenuButtonJobs:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
SmoothF4MenuButtonJobs:SetPos( 0,85 )
SmoothF4MenuButtonJobs:SetColor( Color( 255, 255, 255 ))
SmoothF4MenuButtonJobs:SetFont("SmoothF4menuFontButton")
SmoothF4MenuButtonJobs:SetText("")
SmoothF4MenuButtonJobs.Paint = function(panel)
local menuicon = Material( "materials/icons/jobs.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(10,10,30,30 )
if SmoothF4MenuButtonJobs.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4MenuButtonJobs:GetWide(), SmoothF4MenuButtonJobs:GetTall() , Color(41, 41, 41,70) )
end
draw.SimpleText(SmoothF4MenuFrame_NameServer_Jobs,"SmoothF4menuFontButton",55,15,Color(255,255,255))
SmoothF4MenuButtonJobs:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
end
SmoothF4MenuButtonJobs.OnCursorEntered = function()
SmoothF4MenuButtonJobs.isHover = true
end
SmoothF4MenuButtonJobs.OnCursorExited = function()
SmoothF4MenuButtonJobs.isHover = false
end
SmoothF4MenuButtonJobs.DoClick = function()
ClearAllDPanel()
local SmoothJobsPanel = SmoothF4MenuFrame:Add("SmoothJobsPanel")
SmoothF4MenuDPanel:SetSize(50,616)
end
SmoothF4MenuButtonShop = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4MenuButtonShop:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
SmoothF4MenuButtonShop:SetPos( 0,135 )
SmoothF4MenuButtonShop:SetColor( Color( 255, 255, 255 ))
SmoothF4MenuButtonShop:SetFont("SmoothF4menuFontButton")
SmoothF4MenuButtonShop:SetText("")
SmoothF4MenuButtonShop.Paint = function(panel)
local menuicon = Material( "materials/icons/shop.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(10,10,30,30 )
if SmoothF4MenuButtonShop.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4MenuButtonShop:GetWide(), SmoothF4MenuButtonShop:GetTall() , Color(41, 41, 41,70) )
end
draw.SimpleText(SmoothF4MenuFrame_NameServer_Shop,"SmoothF4menuFontButton",55,15,Color(255,255,255))
SmoothF4MenuButtonShop:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
end
SmoothF4MenuButtonShop.OnCursorEntered = function()
SmoothF4MenuButtonShop.isHover = true
end
SmoothF4MenuButtonShop.OnCursorExited = function()
SmoothF4MenuButtonShop.isHover = false
end
SmoothF4MenuButtonShop.DoClick = function()
ClearAllDPanel()
local SmoothShopPanel = SmoothF4MenuFrame:Add("SmoothShopPanel")
SmoothF4MenuDPanel:SetSize(50,616)
end
SmoothF4MenuButtonCommands = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4MenuButtonCommands:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
SmoothF4MenuButtonCommands:SetPos( 0,185 )
SmoothF4MenuButtonCommands:SetColor( Color( 255, 255, 255 ))
SmoothF4MenuButtonCommands:SetFont("SmoothF4menuFontButton")
SmoothF4MenuButtonCommands:SetText("")
SmoothF4MenuButtonCommands.Paint = function(panel)
local menuicon = Material( "materials/icons/commands.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(10,10,30,30 )
if SmoothF4MenuButtonCommands.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4MenuButtonCommands:GetWide(), SmoothF4MenuButtonCommands:GetTall() , Color(41, 41, 41,70) )
end
draw.SimpleText(SmoothF4MenuFrame_NameServer_Command,"SmoothF4menuFontButton",55,15,Color(255,255,255))
SmoothF4MenuButtonCommands:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
end
SmoothF4MenuButtonCommands.OnCursorEntered = function()
SmoothF4MenuButtonCommands.isHover = true
end
SmoothF4MenuButtonCommands.OnCursorExited = function()
SmoothF4MenuButtonCommands.isHover = false
end
SmoothF4MenuButtonCommands.DoClick = function()
ClearAllDPanel()
local SmoothCommandPanel = SmoothF4MenuFrame:Add("SmoothCommandPanel")
SmoothF4MenuDPanel:SetSize(50,616)
end
SmoothF4MenuButtonSite = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4MenuButtonSite:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
SmoothF4MenuButtonSite:SetPos( 0,235 )
SmoothF4MenuButtonSite:SetColor( Color( 255, 255, 255 ))
SmoothF4MenuButtonSite:SetFont("SmoothF4menuFontButton")
SmoothF4MenuButtonSite:SetText("")
SmoothF4MenuButtonSite.Paint = function(panel)
local menuicon = Material( "materials/icons/site.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(10,10,30,30 )
if SmoothF4MenuButtonSite.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4MenuButtonSite:GetWide(), SmoothF4MenuButtonSite:GetTall() , Color(41, 41, 41,70) )
end
draw.SimpleText(SmoothF4MenuFrame_NameServer_Site,"SmoothF4menuFontButton",55,15,Color(255,255,255))
SmoothF4MenuButtonSite:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
end
SmoothF4MenuButtonSite.OnCursorEntered = function()
SmoothF4MenuButtonSite.isHover = true
end
SmoothF4MenuButtonSite.OnCursorExited = function()
SmoothF4MenuButtonSite.isHover = false
end
SmoothF4MenuButtonSite.DoClick = function()
ClearAllDPanel()
local SmoothSitePanel = SmoothF4MenuFrame:Add("SmoothSitePanel")
SmoothF4MenuDPanel:SetSize(50,616)
end
SmoothF4MenuButtonDonate = vgui.Create("DButton", SmoothF4MenuFrame)
SmoothF4MenuButtonDonate:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
SmoothF4MenuButtonDonate:SetPos( 0,285 )
SmoothF4MenuButtonDonate:SetColor( Color( 255, 255, 255 ))
SmoothF4MenuButtonDonate:SetFont("SmoothF4menuFontButton")
SmoothF4MenuButtonDonate:SetText("")
SmoothF4MenuButtonDonate.Paint = function(panel)
local menuicon = Material( "materials/icons/donate.png" )
surface.SetMaterial( menuicon )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.DrawTexturedRect(10,10,30,30 )
if SmoothF4MenuButtonDonate.isHover then
draw.RoundedBox( 0, 0, 0, SmoothF4MenuButtonDonate:GetWide(), SmoothF4MenuButtonDonate:GetTall() , Color(41, 41, 41,70) )
end
draw.SimpleText("Донат","SmoothF4menuFontButton",55,15,Color(255,255,255))
SmoothF4MenuButtonDonate:SetSize( SmoothF4MenuDPanel:GetWide(),50 )
end
SmoothF4MenuButtonDonate.OnCursorEntered = function()
SmoothF4MenuButtonDonate.isHover = true
end
SmoothF4MenuButtonDonate.OnCursorExited = function()
SmoothF4MenuButtonDonate.isHover = false
end
SmoothF4MenuButtonDonate.DoClick = function()
ClearAllDPanel()
local SmoothDonatePanel = SmoothF4MenuFrame:Add("SmoothDonatePanel")
SmoothF4MenuDPanel:SetSize(50,616)
end
end)
-- BLUR PANEL
function SmoothDrawBlur(panel, amount)
local blurmaterial = Material("pp/blurscreen")
local x, y = panel:LocalToScreen(0, 0)
local scrW, scrH = ScrW(), ScrH()
surface.SetDrawColor(255, 255, 255)
surface.SetMaterial(blurmaterial)
for i = 1, 3 do
blurmaterial:SetFloat("$blur", (i / 3) * (amount or 6))
blurmaterial:Recompute()
render.UpdateScreenEffectTexture()
surface.DrawTexturedRect(x * -1, y * -1, scrW, scrH)
end
end
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

View File

@@ -0,0 +1,29 @@
/*----------------------------------------------------------------------
Leak by Famouse
Play good games:
http://store.steampowered.com/curator/32364216
Subscribe to the channel:
www.youtube.com/c/Famouse
More leaks in the discord:
https://discord.gg/rFdQwzm
------------------------------------------------------------------------*/
util.AddNetworkString( "OpenSmoothF4menu" )
function OpenSmoothF4menu( ply )
net.Start("OpenSmoothF4menu")
net.Send(ply)
end
hook.Add("ShowSpare2", "OpenSmoothF4menu", OpenSmoothF4menu)
/*------------------------------------------------------------------------
Donation for leaks
Qiwi Wallet 4890494419811120
YandexMoney 410013095053302
WebMoney(WMR) R235985364414
WebMoney(WMZ) Z309855690994
------------------------------------------------------------------------*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

Some files were not shown because too many files have changed in this diff Show More