Initial commit
2144
addons/!kostich/lua/autorun/client/!event_stuff.lua
Normal file
571
addons/!kostich/lua/autorun/client/hud.lua
Normal 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
|
||||||
122
addons/!kostich/lua/autorun/client/proplist.lua
Normal 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)
|
||||||
686
addons/!kostich/lua/autorun/client/rndx_cl.lua
Normal file
44
addons/!kostich/lua/autorun/hidetools.lua
Normal 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
|
||||||
90
addons/!kostich/lua/autorun/server/event_quests.lua
Normal 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)
|
||||||
827
addons/!kostich/lua/autorun/server/snte.lua
Normal 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 (~‾▿‾)~
|
||||||
932
addons/!kostich/lua/autorun/sh_proplist.lua
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
9
addons/3d2d_textscreens/addon.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"title": "3D2D Textscreens",
|
||||||
|
"type": "tool",
|
||||||
|
"tags": [
|
||||||
|
"fun",
|
||||||
|
"roleplay"
|
||||||
|
],
|
||||||
|
"ignore": []
|
||||||
|
}
|
||||||
180
addons/3d2d_textscreens/lua/autorun/textscreens_util.lua
Normal 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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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)
|
||||||
154
addons/3d2d_textscreens/lua/textscreens_config.lua
Normal 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
|
||||||
@@ -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
|
||||||
BIN
addons/3d2d_textscreens/materials/textscreens/logo.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
@@ -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!
|
||||||
@@ -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!
|
||||||
@@ -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!
|
||||||
@@ -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
|
||||||
@@ -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!
|
||||||
156
addons/_libnyx/lua/autorun/libnyx.lua
Normal 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
|
||||||
1
addons/_libnyx/lua/libnyx/VERSION
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0.8.0
|
||||||
3205
addons/_libnyx/lua/libnyx/lib/libnyx_components.lua
Normal file
410
addons/_libnyx/lua/libnyx/lib/libnyx_liquidglass.lua
Normal 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
|
||||||
415
addons/_libnyx/lua/libnyx/lib/libnyx_maindemo.lua
Normal 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
|
||||||
756
addons/_libnyx/lua/libnyx/lib/rndx.lua
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-Bold.ttf
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-ExtraBold.ttf
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-ExtraLight.ttf
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-Light.ttf
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-Medium.ttf
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-Regular.ttf
Normal file
BIN
addons/_libnyx/resource/fonts/Manrope-SemiBold.ttf
Normal file
BIN
addons/_libnyx/sound/nyx_uniqueui/nyxclick_2.mp3
Normal file
BIN
addons/_libnyx/sound/nyx_uniqueui/nyxclick_3.mp3
Normal file
14
addons/air_selector/lua/autorun/air_weaponselector_init.lua
Normal 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.
|
||||||
389
addons/air_selector/lua/selector/client.lua
Normal 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
@@ -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 --
|
||||||
62
addons/apg/CONTRIBUTING.md
Normal 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
@@ -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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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
@@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
629
addons/apg/lua/apg/cl_menu.lua
Normal 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,
|
||||||
|
})
|
||||||
281
addons/apg/lua/apg/cl_utils.lua
Normal 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}
|
||||||
97
addons/apg/lua/apg/modules/canphysgun.lua
Normal 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)
|
||||||
403
addons/apg/lua/apg/modules/ghosting.lua
Normal 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)
|
||||||
1
addons/apg/lua/apg/modules/home.lua
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-- This is a dummy file, for APGs home page! (As the home page is built like a module.)
|
||||||
184
addons/apg/lua/apg/modules/lag_detection.lua
Normal 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)
|
||||||
64
addons/apg/lua/apg/modules/logs.lua
Normal 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
|
||||||
261
addons/apg/lua/apg/modules/misc.lua
Normal 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)
|
||||||
95
addons/apg/lua/apg/modules/notification.lua
Normal 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
|
||||||
112
addons/apg/lua/apg/modules/stack_detection.lua
Normal 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)
|
||||||
128
addons/apg/lua/apg/modules/tools.lua
Normal 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)
|
||||||
378
addons/apg/lua/apg/sh_config.lua
Normal 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
|
||||||
420
addons/apg/lua/apg/sv_apg.lua
Normal 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)
|
||||||
150
addons/apg/lua/apg/sv_menu.lua
Normal 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)
|
||||||
3
addons/apg/lua/autorun/client/cl_apg_init.lua
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
APG = {}
|
||||||
|
include( "apg/sh_config.lua" )
|
||||||
|
include( "apg/cl_menu.lua" )
|
||||||
176
addons/apg/lua/autorun/server/sv_apg_init.lua
Normal 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)
|
||||||
2
addons/apg/lua/autorun/sh_apg.lua
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- ULX Admin Commands Coming Soon!
|
||||||
|
--- PLanned Commands for Prop Management, and Server Cleanup.
|
||||||
2
addons/cmenu_darkfated_ultracode/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
674
addons/cmenu_darkfated_ultracode/LICENSE
Normal 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>.
|
||||||
14
addons/cmenu_darkfated_ultracode/README.md
Normal 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">
|
||||||
@@ -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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
@@ -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)
|
||||||
|
After Width: | Height: | Size: 455 B |
|
After Width: | Height: | Size: 443 B |
|
After Width: | Height: | Size: 291 B |
|
After Width: | Height: | Size: 491 B |
|
After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 411 B |
|
After Width: | Height: | Size: 566 B |
|
After Width: | Height: | Size: 391 B |
|
After Width: | Height: | Size: 444 B |
|
After Width: | Height: | Size: 645 B |
|
After Width: | Height: | Size: 740 B |
|
After Width: | Height: | Size: 478 B |
|
After Width: | Height: | Size: 322 B |
|
After Width: | Height: | Size: 503 B |
|
After Width: | Height: | Size: 348 B |
|
After Width: | Height: | Size: 299 B |
|
After Width: | Height: | Size: 722 B |
34
addons/f4/lua/autorun/server/resource.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
51
addons/f4/lua/autorun/smooth-f4menu.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
135
addons/f4/lua/smooth-f4menu/cfg_smooth-f4menu.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
149
addons/f4/lua/smooth-f4menu/client/cl_smooth-f4menu-commands.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
237
addons/f4/lua/smooth-f4menu/client/cl_smooth-f4menu-jobs.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
458
addons/f4/lua/smooth-f4menu/client/cl_smooth-f4menu-shop.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
80
addons/f4/lua/smooth-f4menu/client/cl_smooth-f4menu-site.lua
Normal 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" )
|
||||||
153
addons/f4/lua/smooth-f4menu/client/cl_smooth-f4menu-title.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
425
addons/f4/lua/smooth-f4menu/client/cl_smooth-f4menu.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
29
addons/f4/lua/smooth-f4menu/server/sv_smooth-f4menu.lua
Normal 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
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
BIN
addons/f4/materials/icons/back.png
Normal file
|
After Width: | Height: | Size: 478 B |
BIN
addons/f4/materials/icons/close.png
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
addons/f4/materials/icons/commands.png
Normal file
|
After Width: | Height: | Size: 621 B |
BIN
addons/f4/materials/icons/database.png
Normal file
|
After Width: | Height: | Size: 650 B |
BIN
addons/f4/materials/icons/donate.png
Normal file
|
After Width: | Height: | Size: 699 B |
BIN
addons/f4/materials/icons/home.png
Normal file
|
After Width: | Height: | Size: 704 B |
BIN
addons/f4/materials/icons/info.png
Normal file
|
After Width: | Height: | Size: 773 B |