Advertisement
SHCREW

sdrfegv

Oct 28th, 2020
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 58.60 KB | None | 0 0
  1. XeninUI = XeninUI or {}
  2. XeninUI.ORM = XeninUI.ORM or {}
  3.  
  4. function XeninUI:CreateFont(name, size, weight, mergeTbl)
  5. local tbl = {
  6. font = "Montserrat Medium",
  7. -- Changing font... to match the old look we had to increase size by two
  8. size = size + 2,
  9. weight = weight or 500,
  10. extended = true
  11. }
  12.  
  13. if (mergeTbl) then
  14. table.Merge(tbl, mergeTbl)
  15. end
  16.  
  17. surface.CreateFont(name, tbl)
  18. end
  19.  
  20. XeninUI.Branding = false -- Material("xenin/pantheon.png", "smooth")
  21.  
  22. -- Materials
  23. XeninUI.Materials = {
  24. CloseButton = Material("xenin/closebutton.png", "noclamp smooth"),
  25. Search = Material("xenin/search.png", "noclamp smooth")
  26. }
  27.  
  28. -- Animation
  29. XeninUI.TransitionTime = 0.15
  30.  
  31. -- UI theme
  32. XeninUI.Theme = {
  33. Primary = Color(48, 48, 48),
  34. Navbar = Color(41, 41, 41),
  35. Background = Color(30, 30, 30),
  36. Accent = Color(41, 128, 185),
  37. OrangeRed = Color(228, 104, 78),
  38. Red = Color(230, 58, 64),
  39. Green = Color(46, 204, 113),
  40. Blue = Color(41, 128, 185),
  41. Yellow = Color(201, 176, 15),
  42. Purple = Color(142, 68, 173)
  43. }
  44.  
  45. XeninUI.Frame = {
  46. Width = 960,
  47. Height = 720
  48. }
  49.  
  50. local scrW, scrH = ScrW(), ScrH()
  51. --[[
  52. This code was generated by LAUX, a Lua transpiler
  53. LAUX is a fork of LAU with additional changes.
  54.  
  55. More info & source code can be found at: https://gitlab.com/sleeppyy/laux
  56. ]]
  57. local blur = Material("pp/blurscreen")
  58.  
  59. function XeninUI:DrawBlur(panel, amount)
  60. local x, y = panel:LocalToScreen(0, 0)
  61. local scrW, scrH = ScrW(), ScrH()
  62. surface.SetDrawColor(255, 255, 255)
  63. surface.SetMaterial(blur)
  64.  
  65. for i = 1, 3 do
  66. blur:SetFloat("$blur", (i / 3) * (amount or 6))
  67. blur:Recompute()
  68. render.UpdateScreenEffectTexture()
  69. surface.DrawTexturedRect(x * -1, y * -1, scrW, scrH)
  70. end
  71. end
  72.  
  73. if CLIENT then
  74. CreateClientConVar("xenin_hud_blur", 0)
  75. end
  76.  
  77. function XeninUI:DrawBlurHUD(x, y, w, h, amt)
  78. local X, Y = 0, 0
  79. surface.SetDrawColor(255, 255, 255)
  80. surface.SetMaterial(blur)
  81.  
  82. for i = 1, amt or 5 do
  83. blur:SetFloat("$blur", (i / 3) * 5)
  84. blur:Recompute()
  85. render.UpdateScreenEffectTexture()
  86. render.SetScissorRect(x, y, x + w, y + h, true)
  87. surface.DrawTexturedRect(X * -1, Y * -1, ScrW(), ScrH())
  88. render.SetScissorRect(0, 0, 0, 0, false)
  89. end
  90. end
  91.  
  92. function XeninUI:FormatTime(seconds, format)
  93. if (not seconds) then
  94. seconds = 0
  95. end
  96.  
  97. local hours = math.floor(seconds / 3600)
  98. local minutes = math.floor((seconds / 60) % 60)
  99. seconds = math.floor(seconds % 60)
  100.  
  101. return string.format(format, hours, minutes, seconds)
  102. end
  103.  
  104. local mat_white = Material("vgui/white")
  105.  
  106. function draw.SimpleLinearGradient(x, y, w, h, startColor, endColor, horizontal)
  107. draw.LinearGradient(x, y, w, h, {
  108. {
  109. offset = 0,
  110. color = startColor
  111. },
  112. {
  113. offset = 1,
  114. color = endColor
  115. }
  116. }, horizontal)
  117. end
  118.  
  119. function draw.LinearGradient(x, y, w, h, stops, horizontal)
  120. if #stops == 0 then
  121. return
  122. elseif #stops == 1 then
  123. surface.SetDrawColor(stops[1].color)
  124. surface.DrawRect(x, y, w, h)
  125.  
  126. return
  127. end
  128.  
  129. table.SortByMember(stops, "offset", true)
  130. render.SetMaterial(mat_white)
  131. mesh.Begin(MATERIAL_QUADS, #stops - 1)
  132.  
  133. for i = 1, #stops - 1 do
  134. local offset1 = math.Clamp(stops[i].offset, 0, 1)
  135. local offset2 = math.Clamp(stops[i + 1].offset, 0, 1)
  136. if offset1 == offset2 then continue end
  137. local deltaX1, deltaY1, deltaX2, deltaY2
  138. local color1 = stops[i].color
  139. local color2 = stops[i + 1].color
  140. local r1, g1, b1, a1 = color1.r, color1.g, color1.b, color1.a
  141. local r2, g2, b2, a2
  142. local r3, g3, b3, a3 = color2.r, color2.g, color2.b, color2.a
  143. local r4, g4, b4, a4
  144.  
  145. if horizontal then
  146. r2, g2, b2, a2 = r3, g3, b3, a3
  147. r4, g4, b4, a4 = r1, g1, b1, a1
  148. deltaX1 = offset1 * w
  149. deltaY1 = 0
  150. deltaX2 = offset2 * w
  151. deltaY2 = h
  152. else
  153. r2, g2, b2, a2 = r1, g1, b1, a1
  154. r4, g4, b4, a4 = r3, g3, b3, a3
  155. deltaX1 = 0
  156. deltaY1 = offset1 * h
  157. deltaX2 = w
  158. deltaY2 = offset2 * h
  159. end
  160.  
  161. mesh.Color(r1, g1, b1, a1)
  162. mesh.Position(Vector(x + deltaX1, y + deltaY1))
  163. mesh.AdvanceVertex()
  164. mesh.Color(r2, g2, b2, a2)
  165. mesh.Position(Vector(x + deltaX2, y + deltaY1))
  166. mesh.AdvanceVertex()
  167. mesh.Color(r3, g3, b3, a3)
  168. mesh.Position(Vector(x + deltaX2, y + deltaY2))
  169. mesh.AdvanceVertex()
  170. mesh.Color(r4, g4, b4, a4)
  171. mesh.Position(Vector(x + deltaX1, y + deltaY2))
  172. mesh.AdvanceVertex()
  173. end
  174.  
  175. mesh.End()
  176. end
  177.  
  178. function XeninUI:DrawRotatedTexture(x, y, w, h, angle, cx, cy)
  179. cx, cy = cx or w / 2, cy or w / 2
  180.  
  181. if (cx == w / 2 and cy == w / 2) then
  182. surface.DrawTexturedRectRotated(x, y, w, h, angle)
  183. else
  184. local vec = Vector(w / 2 - cx, cy - h / 2, 0)
  185. vec:Rotate(Angle(180, angle, -180))
  186. surface.DrawTexturedRectRotated(x - vec.x, y + vec.y, w, h, angle)
  187. end
  188. end
  189.  
  190. function XeninUI:FormatMoney(number, decimals)
  191. decimals = decimals or 2
  192.  
  193. if (number >= 1000000000) then
  194. return DarkRP.formatMoney(math.Round(number / 1000000000, 2)) .. " bil"
  195. elseif (number >= 1000000) then
  196. return DarkRP.formatMoney(math.Round(number / 1000000, 2)) .. " mil"
  197. elseif (number > 10000) then
  198. return DarkRP.formatMoney(math.Round(number / 1000, 2)) .. "k"
  199. end
  200.  
  201. return DarkRP.formatMoney(number)
  202. end
  203.  
  204. function XeninUI:DateToString(date)
  205. if not date then return "now" end
  206. local dif = os.ServerTime() - date
  207.  
  208. if dif < 60 then
  209. return "a moment ago"
  210. elseif dif < (60 * 60) then
  211. local mins = math.Round(dif / 60, 0)
  212. local str = mins .. " minute" .. (mins == 1 and "" or "s") .. " ago"
  213.  
  214. return str
  215. elseif dif < (60 * 60) * 24 then
  216. return os.date("%H:%M", date)
  217. else
  218. return os.date("%d/%m/%Y", date)
  219. end
  220.  
  221. return "?"
  222. end
  223.  
  224. if not XeninUI.__AddedPanelFunctions then
  225. local PNL = FindMetaTable("Panel")
  226. local Old_Remove = Old_Remove or PNL.Remove
  227.  
  228. function PNL:Remove()
  229. for k, v in pairs(self.hooks or {}) do
  230. hook.Remove(v.name, k)
  231. end
  232.  
  233. for k, v in pairs(self.timers or {}) do
  234. timer.Remove(k)
  235. end
  236.  
  237. Old_Remove(self)
  238. end
  239.  
  240. function PNL:AddHook(name, identifier, func)
  241. identifier = identifier .. " - " .. CurTime()
  242. self.hooks = self.hooks or {}
  243.  
  244. self.hooks[identifier] = {
  245. name = name,
  246. func = function(...)
  247. if IsValid(self) then return func(self, ...) end
  248. end
  249. }
  250.  
  251. hook.Add(name, identifier, self.hooks[identifier].func)
  252. end
  253.  
  254. function PNL:GetHooks()
  255. return self.hooks or {}
  256. end
  257.  
  258. function PNL:AddTimer(identifier, delay, rep, func)
  259. self.timers = self.timers or {}
  260. self.timers[identifier] = true
  261.  
  262. timer.Create(identifier, delay, rep, function(...)
  263. if IsValid(self) then
  264. func(self, ...)
  265. end
  266. end)
  267. end
  268.  
  269. function PNL:GetTimers()
  270. return self.timers or {}
  271. end
  272.  
  273. function PNL:LerpAlpha(alpha, time, callback)
  274. callback = callback or function() end
  275. self.Alpha = self.Alpha or 0
  276. local oldThink = self.Think
  277.  
  278. self.Think = function(pnl)
  279. if oldThink then
  280. oldThink(pnl)
  281. end
  282.  
  283. self:SetAlpha(pnl.Alpha >= 250 and 255 or pnl.Alpha)
  284. end
  285.  
  286. self:Lerp("Alpha", alpha, time, function()
  287. self.Think = oldThink
  288. callback(self)
  289. end)
  290. end
  291.  
  292. XeninUI.__AddedPanelFunctions = true
  293. end
  294.  
  295. local matLoading = Material("xenin/loading.png", "smooth")
  296.  
  297. function XeninUI:DrawLoadingCircle(x, y, size, col)
  298. surface.SetMaterial(matLoading)
  299. surface.SetDrawColor(col or ColorAlpha(XeninUI.Theme.Accent, 100))
  300. XeninUI:DrawRotatedTexture(x, y, size, size, ((ct or CurTime()) % 360) * -100)
  301. end
  302.  
  303. local function toLines(text, font, mWidth)
  304. surface.SetFont(font)
  305. local buffer = {}
  306. local nLines = {}
  307.  
  308. for word in string.gmatch(text, "%S+") do
  309. local w, h = surface.GetTextSize(table.concat(buffer, " ") .. " " .. word)
  310.  
  311. if w > mWidth then
  312. table.insert(nLines, table.concat(buffer, " "))
  313. buffer = {}
  314. end
  315.  
  316. table.insert(buffer, word)
  317. end
  318.  
  319. if #buffer > 0 then
  320. table.insert(nLines, table.concat(buffer, " "))
  321. end
  322.  
  323. return nLines
  324. end
  325.  
  326. local function drawMultiLine(text, font, mWidth, spacing, x, y, color, alignX, alignY, sAmt, sAlpha)
  327. local mLines = toLines(text, font, mWidth)
  328. local amt = #mLines - 1
  329.  
  330. for i, line in pairs(mLines) do
  331. if (sAmt and sAlpha) then
  332. XeninUI:DrawShadowText(line, font, x, y + (i - 1) * spacing - amt * spacing / 2, color, alignX, alignY, sAmt, sAlpha)
  333. else
  334. draw.SimpleText(line, font, x, y + (i - 1) * spacing - amt * spacing / (alignY == TEXT_ALIGN_CENTER and 2 or 1), color, alignX, alignY)
  335. end
  336. end
  337.  
  338. return amt * spacing
  339. end
  340.  
  341. XeninUI.DrawMultiLine = drawMultiLine
  342. local matCredit = Material("xenin/credit_small.png", "smooth")
  343.  
  344. function XeninUI:DrawCreditsText(text, font, x, y, col, xAlign, yAlign, textY, iconColor, spacing)
  345. textY = textY or 1
  346. iconColor = iconColor or color_white
  347. spacing = spacing or 4
  348. surface.SetFont(font)
  349. local tw, th = surface.GetTextSize(text)
  350. local size = th
  351.  
  352. if (xAlign == TEXT_ALIGN_LEFT) then
  353. surface.SetMaterial(matCredit)
  354. surface.SetDrawColor(iconColor)
  355. surface.DrawTexturedRect(x, y, size, size)
  356. draw.SimpleText(text, font, x + size + spacing, y + textY, col, xAlign, yAlign)
  357. elseif (xAlign == TEXT_ALIGN_CENTER) then
  358. x = x + size / 2 + 2
  359. surface.SetMaterial(matCredit)
  360. surface.SetDrawColor(iconColor)
  361. surface.DrawTexturedRect(x - tw / 2 - size - spacing, y, size, size)
  362. draw.SimpleText(text, font, x, y + textY, col, xAlign, yAlign)
  363. elseif (xAlign == TEXT_ALIGN_RIGHT) then
  364. x = x + size / 2 + 2
  365. surface.SetMaterial(matCredit)
  366. surface.SetDrawColor(iconColor)
  367. surface.DrawTexturedRect(x - tw - size - spacing, y, size, size)
  368. draw.SimpleText(text, font, x, y + textY, col, xAlign, yAlign)
  369. end
  370. end
  371.  
  372. function XeninUI:DrawArc(x, y, ang, p, rad, color, seg)
  373. seg = seg or 80
  374. ang = (-ang) + 180
  375. local circle = {}
  376.  
  377. table.insert(circle, {
  378. x = x,
  379. y = y
  380. })
  381.  
  382. for i = 0, seg do
  383. local a = math.rad((i / seg) * -p + ang)
  384.  
  385. table.insert(circle, {
  386. x = x + math.sin(a) * rad,
  387. y = y + math.cos(a) * rad
  388. })
  389. end
  390.  
  391. surface.SetDrawColor(color)
  392. draw.NoTexture()
  393. surface.DrawPoly(circle)
  394. end
  395.  
  396. function XeninUI:CalculateArc(x, y, ang, p, rad, seg)
  397. seg = seg or 80
  398. ang = (-ang) + 180
  399. local circle = {}
  400.  
  401. table.insert(circle, {
  402. x = x,
  403. y = y
  404. })
  405.  
  406. for i = 0, seg do
  407. local a = math.rad((i / seg) * -p + ang)
  408.  
  409. table.insert(circle, {
  410. x = x + math.sin(a) * rad,
  411. y = y + math.cos(a) * rad
  412. })
  413. end
  414.  
  415. return circle
  416. end
  417.  
  418. function XeninUI:DrawCachedArc(circle, color)
  419. surface.SetDrawColor(color)
  420. draw.NoTexture()
  421. surface.DrawPoly(circle)
  422. end
  423.  
  424. function XeninUI:DrawRoundedBoxEx(radius, x, y, w, h, col, tl, tr, bl, br)
  425. x = math.floor(x)
  426. y = math.floor(y)
  427. w = math.floor(w)
  428. h = math.floor(h)
  429. radius = math.Clamp(math.floor(radius), 0, math.min(h / 2, w / 2))
  430.  
  431. if (radius == 0) then
  432. surface.SetDrawColor(col)
  433. surface.DrawRect(x, y, w, h)
  434.  
  435. return
  436. end
  437.  
  438. surface.SetDrawColor(col)
  439. surface.DrawRect(x + radius, y, w - radius * 2, radius)
  440. surface.DrawRect(x, y + radius, w, h - radius * 2)
  441. surface.DrawRect(x + radius, y + h - radius, w - radius * 2, radius)
  442.  
  443. if tl then
  444. XeninUI:DrawArc(x + radius, y + radius, 270, 90, radius, col, radius)
  445. else
  446. surface.SetDrawColor(col)
  447. surface.DrawRect(x, y, radius, radius)
  448. end
  449.  
  450. if tr then
  451. XeninUI:DrawArc(x + w - radius, y + radius, 0, 90, radius, col, radius)
  452. else
  453. surface.SetDrawColor(col)
  454. surface.DrawRect(x + w - radius, y, radius, radius)
  455. end
  456.  
  457. if bl then
  458. XeninUI:DrawArc(x + radius, y + h - radius, 180, 90, radius, col, radius)
  459. else
  460. surface.SetDrawColor(col)
  461. surface.DrawRect(x, y + h - radius, radius, radius)
  462. end
  463.  
  464. if br then
  465. XeninUI:DrawArc(x + w - radius, y + h - radius, 90, 90, radius, col, radius)
  466. else
  467. surface.SetDrawColor(col)
  468. surface.DrawRect(x + w - radius, y + h - radius, radius, radius)
  469. end
  470. end
  471.  
  472. function XeninUI:DrawRoundedBox(radius, x, y, w, h, col)
  473. XeninUI:DrawRoundedBoxEx(radius, x, y, w, h, col, true, true, true, true)
  474. end
  475.  
  476. function XeninUI:MaskInverse(maskFn, drawFn, pixel)
  477. pixel = pixel or 1
  478. render.ClearStencil()
  479. render.SetStencilEnable(true)
  480. render.SetStencilWriteMask(1)
  481. render.SetStencilTestMask(1)
  482. render.SetStencilFailOperation(STENCILOPERATION_REPLACE)
  483. render.SetStencilPassOperation(STENCILOPERATION_REPLACE)
  484. render.SetStencilZFailOperation(STENCILOPERATION_KEEP)
  485. render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_NEVER)
  486. render.SetStencilReferenceValue(pixel)
  487. maskFn()
  488. render.SetStencilFailOperation(STENCILOPERATION_REPLACE)
  489. render.SetStencilPassOperation(STENCILOPERATION_REPLACE)
  490. render.SetStencilZFailOperation(STENCILOPERATION_KEEP)
  491. render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
  492. render.SetStencilReferenceValue(pixel - 1)
  493. drawFn()
  494. render.SetStencilEnable(false)
  495. render.ClearStencil()
  496. end
  497.  
  498. function XeninUI:Mask(maskFn, drawFn, pixel)
  499. pixel = pixel or 1
  500. render.ClearStencil()
  501. render.SetStencilEnable(true)
  502. render.SetStencilWriteMask(1)
  503. render.SetStencilTestMask(1)
  504. render.SetStencilFailOperation(STENCILOPERATION_REPLACE)
  505. render.SetStencilPassOperation(STENCILOPERATION_KEEP)
  506. render.SetStencilZFailOperation(STENCILOPERATION_KEEP)
  507. render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_NEVER)
  508. render.SetStencilReferenceValue(pixel)
  509. maskFn()
  510. render.SetStencilFailOperation(STENCILOPERATION_KEEP)
  511. render.SetStencilPassOperation(STENCILOPERATION_REPLACE)
  512. render.SetStencilZFailOperation(STENCILOPERATION_KEEP)
  513. render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
  514. render.SetStencilReferenceValue(pixel)
  515. drawFn()
  516. render.SetStencilEnable(false)
  517. render.ClearStencil()
  518. end
  519.  
  520. XeninUI:CreateFont("XeninUI.NPC.Overhead", 160)
  521.  
  522. function XeninUI:DrawNPCOverhead(npc, tbl)
  523. local alpha = tbl.alpha or 255
  524. local text = tbl.text or npc.PrintName or "NO NAME"
  525. local icon = tbl.icon
  526. local hover = tbl.sin
  527. local xOffset = tbl.xOffset or 0
  528. local textOffset = tbl.textOffset or 0
  529. local col = tbl.color or XeninUI.Theme.Accent
  530. col = ColorAlpha(col, alpha)
  531. local str = text
  532. surface.SetFont("XeninUI.NPC.Overhead")
  533. local width = surface.GetTextSize(str)
  534. width = width + 40
  535.  
  536. if icon then
  537. width = width + (64 * 3)
  538. else
  539. width = width + 64
  540. end
  541.  
  542. local center = 900 / 2
  543. local x = -width / 2 - 30 + (xOffset or 0)
  544. local y = 220
  545. local sin = math.sin(CurTime() * 2)
  546.  
  547. if hover then
  548. y = math.Round(y + (sin * 30))
  549. end
  550.  
  551. local h = 64 * 3
  552. local isLookingAt
  553.  
  554. if (alpha > 0.5) then
  555. isLookingAt = LocalPlayer():GetEyeTrace().Entity == npc
  556. end
  557.  
  558. npc.overheadAlpha = npc.overheadAlpha or 0
  559.  
  560. if isLookingAt then
  561. npc.overheadAlpha = math.Clamp(npc.overheadAlpha + (FrameTime() * 3), 0, 1)
  562. else
  563. npc.overheadAlpha = math.Clamp(npc.overheadAlpha - (FrameTime() * 3), 0, 1)
  564. end
  565.  
  566. local darkerColor = Color(col.r * 0.5, col.g * 0.5, col.b * 0.5)
  567. XeninUI:DrawRoundedBox(64, x, y, width, h, ColorAlpha(darkerColor, npc.overheadAlpha * 255))
  568. XeninUI:DrawRoundedBox(64, x + 8, y + 8, width - 16, h - 16, ColorAlpha(col, npc.overheadAlpha * 255))
  569. local textX = not icon and (width / 2) or h
  570. XeninUI:DrawShadowText(str, "XeninUI.NPC.Overhead", x + textX + textOffset, h / 2 + y - 10, Color(225, 225, 225, alpha), icon and TEXT_ALIGN_LEFT or TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 5, 125)
  571.  
  572. if icon then
  573. surface.SetDrawColor(255, 255, 255, alpha)
  574. surface.SetMaterial(icon)
  575. local margin = tbl.icon_margin or tbl.iconMargin or 30
  576. surface.DrawTexturedRect(x + margin, y + margin, h - (margin * 2), h - (margin * 2))
  577. end
  578. end
  579.  
  580. function XeninUI:DrawShadowText(text, font, x, y, col, xAlign, yAlign, amt, shadow)
  581. for i = 1, amt do
  582. draw.SimpleText(text, font, x + i, y + i, Color(0, 0, 0, i * (shadow or 50)), xAlign, yAlign)
  583. end
  584.  
  585. draw.SimpleText(text, font, x, y, col, xAlign, yAlign)
  586. end
  587.  
  588. function XeninUI:DrawOutlinedText(str, font, x, y, col, xAlign, yAlign, outlineCol, thickness)
  589. thickness = thickness or 1
  590.  
  591. for i = 1, thickness do
  592. draw.SimpleText(str, font, x - thickness, y - thickness, outlineCol or color_black, xAlign, yAlign)
  593. draw.SimpleText(str, font, x - thickness, y + thickness, outlineCol or color_black, xAlign, yAlign)
  594. draw.SimpleText(str, font, x + thickness, y - thickness, outlineCol or color_black, xAlign, yAlign)
  595. draw.SimpleText(str, font, x + thickness, y + thickness, outlineCol or color_black, xAlign, yAlign)
  596. end
  597.  
  598. draw.SimpleText(str, font, x, y, col, xAlign, yAlign)
  599. end
  600.  
  601. function XeninUI:DrawHollowArc(cx, cy, radius, thickness, startang, endang, roughness, color)
  602. surface.SetDrawColor(color)
  603. local arc = self:CacheHollowArc(cx, cy, radius, thickness, startang, endang, roughness)
  604.  
  605. for i, vertex in pairs(arc) do
  606. surface.DrawPoly(vertex)
  607. end
  608. end
  609.  
  610. function XeninUI:CacheHollowArc(cx, cy, radius, thickness, startang, endang, roughness)
  611. local triarc = {}
  612. local roughness = math.max(roughness or 1, 1)
  613. local step = roughness
  614. local startang, endang = startang or 0, endang or 0
  615.  
  616. if startang > endang then
  617. step = math.abs(step) * -1
  618. end
  619.  
  620. local inner = {}
  621. local r = radius - thickness
  622.  
  623. for deg = startang, endang, step do
  624. local rad = math.rad(deg)
  625. local ox, oy = cx + (math.cos(rad) * r), cy + (-math.sin(rad) * r)
  626.  
  627. table.insert(inner, {
  628. x = ox,
  629. y = oy,
  630. u = (ox - cx) / radius + .5,
  631. v = (oy - cy) / radius + .5
  632. })
  633. end
  634.  
  635. local outer = {}
  636.  
  637. for deg = startang, endang, step do
  638. local rad = math.rad(deg)
  639. local ox, oy = cx + (math.cos(rad) * radius), cy + (-math.sin(rad) * radius)
  640.  
  641. table.insert(outer, {
  642. x = ox,
  643. y = oy,
  644. u = (ox - cx) / radius + .5,
  645. v = (oy - cy) / radius + .5
  646. })
  647. end
  648.  
  649. for tri = 1, #inner * 2 do
  650. local p1, p2, p3
  651. p1 = outer[math.floor(tri / 2) + 1]
  652. p3 = inner[math.floor((tri + 1) / 2) + 1]
  653.  
  654. if tri % 2 == 0 then
  655. p2 = outer[math.floor((tri + 1) / 2)]
  656. else
  657. p2 = inner[math.floor((tri + 1) / 2)]
  658. end
  659.  
  660. table.insert(triarc, {p1, p2, p3})
  661. end
  662.  
  663. return triarc
  664. end
  665.  
  666. function XeninUI:DualText(title, subtitle, x, y, w, h)
  667. x = x or 0
  668. y = y or 0
  669. surface.SetFont(title[2])
  670. local tW, tH = surface.GetTextSize(title[1])
  671. surface.SetFont(subtitle[2])
  672. local sW, sH = surface.GetTextSize(subtitle[1])
  673. XeninUI:DrawShadowText(title[1], title[2], x, y + (h / 2 - sH / 2), title[3], title[4], TEXT_ALIGN_CENTER, title[5], title[6])
  674. XeninUI:DrawShadowText(subtitle[1], subtitle[2], x, y + (h / 2 + tH / 2), subtitle[3], subtitle[4], TEXT_ALIGN_CENTER, subtitle[5], subtitle[6])
  675. end
  676.  
  677. function XeninUI:DrawIconRotated(x, y, w, h, rotation, pnl, col, loadCol)
  678. col = col or color_white
  679. loadCol = loadCol or XeninUI.Theme.Accent
  680.  
  681. if (pnl.Icon and type(pnl.Icon) == "IMaterial") then
  682. surface.SetMaterial(pnl.Icon)
  683. surface.SetDrawColor(col)
  684. XeninUI:DrawRotatedTexture(x, y, w, h, rotation)
  685. elseif (pnl.Icon ~= nil) then
  686. XeninUI:DrawLoadingCircle(h, h, h, loadCol)
  687. end
  688. end
  689.  
  690. --[[
  691. This code was generated by LAUX, a Lua transpiler
  692. LAUX is a fork of LAU with additional changes.
  693.  
  694. More info & source code can be found at: https://gitlab.com/sleeppyy/laux
  695. ]]
  696. local PNL = FindMetaTable("Panel")
  697.  
  698. function PNL:LerpColor(var, to, duration, callback)
  699. if (not duration) then
  700. duration = XeninUI.TransitionTime
  701. end
  702.  
  703. local color = self[var]
  704. local anim = self:NewAnimation(duration)
  705. anim.Color = to
  706.  
  707. anim.Think = function(anim, pnl, fract)
  708. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  709.  
  710. if (not anim.StartColor) then
  711. anim.StartColor = color
  712. end
  713.  
  714. local newColor = XeninUI:LerpColor(newFract, anim.StartColor, anim.Color)
  715. self[var] = newColor
  716. end
  717.  
  718. anim.OnEnd = function()
  719. if callback then
  720. callback(self)
  721. end
  722. end
  723. end
  724.  
  725. function PNL:LerpVector(var, to, duration, callback)
  726. if (not duration) then
  727. duration = XeninUI.TransitionTime
  728. end
  729.  
  730. local vector = self[var]
  731. local anim = self:NewAnimation(duration)
  732. anim.Vector = to
  733.  
  734. anim.Think = function(anim, pnl, fract)
  735. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  736.  
  737. if (not anim.StartVector) then
  738. anim.StartVector = vector
  739. end
  740.  
  741. local newColor = XeninUI:LerpVector(newFract, anim.StartVector, anim.Vector)
  742. self[var] = newColor
  743. end
  744.  
  745. anim.OnEnd = function()
  746. if callback then
  747. callback(self)
  748. end
  749. end
  750. end
  751.  
  752. function XeninUI:Ease(t, b, c, d)
  753. t = t / d
  754. local ts = t * t
  755. local tc = ts * t
  756.  
  757. return b + c * (-2 * tc + 3 * ts)
  758. end
  759.  
  760. function XeninUI:EaseInOutQuintic(t, b, c, d)
  761. t = t / d
  762. local ts = t * t
  763. local tc = ts * t
  764.  
  765. return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc)
  766. end
  767.  
  768. function XeninUI:RemoveDebounce(name)
  769. timer.Remove("_debounce." .. name)
  770. end
  771.  
  772. function XeninUI:Debounce(name, wait, func)
  773. if timer.Exists("_debounce." .. name) then
  774. timer.Remove("_debounce." .. name)
  775. end
  776.  
  777. timer.Create("_debounce." .. name, wait, 1, function()
  778. func()
  779. timer.Remove("_debounce." .. name)
  780. end)
  781. end
  782.  
  783. function XeninUI:LerpColor(fract, from, to)
  784. return Color(Lerp(fract, from.r, to.r), Lerp(fract, from.g, to.g), Lerp(fract, from.b, to.b), Lerp(fract, from.a or 255, to.a or 255))
  785. end
  786.  
  787. function XeninUI:GetAngleBetweenTwoVectors(a, b)
  788. local vec = (a - b):GetNormalized()
  789. local ang = vec:Angle()
  790.  
  791. return ang
  792. end
  793.  
  794. function XeninUI:GetVector2DDistance(a, b)
  795. return math.sqrt((a.x - b.x) ^ 2 + (a.y - b.y) ^ 2)
  796. end
  797.  
  798. function XeninUI:LerpVector(frac, from, to, ease)
  799. local newFract = ease and ease(frac, 0, 1, 1) or XeninUI:Ease(frac, 0, 1, 1)
  800.  
  801. return LerpVector(newFract, from, to)
  802. end
  803.  
  804. function XeninUI:LerpAngle(frac, from, to, ease)
  805. local newFract = ease and ease(frac, 0, 1, 1) or XeninUI:Ease(frac, 0, 1, 1)
  806.  
  807. return LerpAngle(newFract, from, to)
  808. end
  809.  
  810. function XeninUI:Map(tbl, func)
  811. local newTbl = {}
  812.  
  813. for i, v in pairs(tbl) do
  814. newTbl[i] = func(v, i)
  815. end
  816.  
  817. return newTbl
  818. end
  819.  
  820. function XeninUI:Hue2RGB(p, q, t)
  821. if t < 0 then
  822. t = t + 1
  823. end
  824.  
  825. if t > 1 then
  826. t = t - 1
  827. end
  828.  
  829. if t < 1 / 6 then return p + (q - p) * 6 * t end
  830. if t < 1 / 2 then return q end
  831. if t < 2 / 3 then return p + (q - p) * (2 / 3 - t) * 6 end
  832.  
  833. return p
  834. end
  835.  
  836. function XeninUI:HSLToColor(h, s, l, a)
  837. local r, g, b
  838. local t = h / (2 * math.pi)
  839.  
  840. if s == 0 then
  841. r, g, b = l, l, l
  842. else
  843. local q
  844.  
  845. if l < 0.5 then
  846. q = l * (1 + s)
  847. else
  848. q = l + s - l * s
  849. end
  850.  
  851. local p = 2 * l - q
  852. r = self:Hue2RGB(p, q, t + 1 / 3)
  853. g = self:Hue2RGB(p, q, t)
  854. b = self:Hue2RGB(p, q, t - 1 / 3)
  855. end
  856.  
  857. return Color(r * 255, g * 255, b * 255, (a or 1) * 255)
  858. end
  859.  
  860. function XeninUI:ColorToHSL(col)
  861. local r = col.r / 255
  862. local g = col.g / 255
  863. local b = col.b / 255
  864. local max, min = math.max(r, g, b), math.min(r, g, b)
  865. local b = max + min
  866. local h = b / 2
  867. if max == min then return 0, 0, h end
  868. local s, l = h, h
  869. local d = max - min
  870. s = l > .5 and d / (2 - b) or d / b
  871.  
  872. if max == r then
  873. h = (g - b) / d + (g < b and 6 or 0)
  874. elseif max == g then
  875. h = (b - r) / d + 2
  876. elseif max == b then
  877. h = (r - g) / d + 4
  878. end
  879.  
  880. return h * .16667, s, l
  881. end
  882.  
  883. function XeninUI:DecToHex(d, zeros)
  884. return string.format("%0" .. (zeros or 2) .. "x", d)
  885. end
  886.  
  887. function XeninUI:RGBToHex(color)
  888. return "#" .. self:DecToHex(math.max(math.min(color.r, 255), 0)) .. self:DecToHex(math.max(math.min(color.g, 255), 0)) .. self:DecToHex(math.max(math.min(color.b, 255), 0))
  889. end
  890.  
  891. function XeninUI:HexToRGB(hex)
  892. hex = hex:gsub("#", "")
  893.  
  894. if (#hex == 3) then
  895. local r = hex:sub(1, 1)
  896. local g = hex:sub(2, 2)
  897. local b = hex:sub(3, 3)
  898.  
  899. return Color(tonumber("0x" .. r .. r), tonumber("0x" .. g .. g), tonumber("0x" .. b .. b))
  900. end
  901.  
  902. return Color(tonumber("0x" .. hex:sub(1, 2)), tonumber("0x" .. hex:sub(3, 4)), tonumber("0x" .. hex:sub(5, 6)))
  903. end
  904.  
  905. function PNL:LerpAngle(var, to, duration, callback)
  906. if (not duration) then
  907. duration = XeninUI.TransitionTime
  908. end
  909.  
  910. local angle = self[var]
  911. local anim = self:NewAnimation(duration)
  912. anim.Angle = to
  913.  
  914. anim.Think = function(anim, pnl, fract)
  915. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  916.  
  917. if (not anim.StartAngle) then
  918. anim.StartAngle = angle
  919. end
  920.  
  921. local newColor = XeninUI:LerpAngle(newFract, anim.StartAngle, anim.Angle)
  922. self[var] = newColor
  923. end
  924.  
  925. anim.OnEnd = function()
  926. if callback then
  927. callback(self)
  928. end
  929. end
  930. end
  931.  
  932. function PNL:EndAnimations()
  933. for i, v in pairs(self.m_AnimList or {}) do
  934. if v.OnEnd then
  935. v:OnEnd(self)
  936. end
  937.  
  938. self.m_AnimList[i] = nil
  939. end
  940. end
  941.  
  942. function PNL:Lerp(var, to, duration, callback)
  943. if (not duration) then
  944. duration = XeninUI.TransitionTime
  945. end
  946.  
  947. local varStart = self[var]
  948. local anim = self:NewAnimation(duration)
  949. anim.Goal = to
  950.  
  951. anim.Think = function(anim, pnl, fract)
  952. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  953.  
  954. if (not anim.Start) then
  955. anim.Start = varStart
  956. end
  957.  
  958. local new = Lerp(newFract, anim.Start, anim.Goal)
  959. self[var] = new
  960. end
  961.  
  962. anim.OnEnd = function()
  963. if callback then
  964. callback(self)
  965. end
  966. end
  967. end
  968.  
  969. function PNL:LerpMove(x, y, duration, callback)
  970. if (not duration) then
  971. duration = XeninUI.TransitionTime
  972. end
  973.  
  974. local anim = self:NewAnimation(duration)
  975. anim.Pos = Vector(x, y)
  976.  
  977. anim.Think = function(anim, pnl, fract)
  978. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  979.  
  980. if (not anim.StartPos) then
  981. anim.StartPos = Vector(pnl.x, pnl.y, 0)
  982. end
  983.  
  984. local new = LerpVector(newFract, anim.StartPos, anim.Pos)
  985. self:SetPos(new.x, new.y)
  986. end
  987.  
  988. anim.OnEnd = function()
  989. if callback then
  990. callback(self)
  991. end
  992. end
  993. end
  994.  
  995. function PNL:LerpMoveY(y, duration, callback)
  996. if (not duration) then
  997. duration = XeninUI.TransitionTime
  998. end
  999.  
  1000. local anim = self:NewAnimation(duration)
  1001. anim.Pos = y
  1002.  
  1003. anim.Think = function(anim, pnl, fract)
  1004. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  1005.  
  1006. if (not anim.StartPos) then
  1007. anim.StartPos = pnl.y
  1008. end
  1009.  
  1010. local new = Lerp(newFract, anim.StartPos, anim.Pos)
  1011. self:SetPos(pnl.x, new)
  1012. end
  1013.  
  1014. anim.OnEnd = function()
  1015. if callback then
  1016. callback(self)
  1017. end
  1018. end
  1019. end
  1020.  
  1021. function PNL:LerpMoveX(x, duration, callback)
  1022. if (not duration) then
  1023. duration = XeninUI.TransitionTime
  1024. end
  1025.  
  1026. local anim = self:NewAnimation(duration)
  1027. anim.Pos = x
  1028.  
  1029. anim.Think = function(anim, pnl, fract)
  1030. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  1031.  
  1032. if (not anim.StartPos) then
  1033. anim.StartPos = pnl.x
  1034. end
  1035.  
  1036. local new = Lerp(newFract, anim.StartPos, anim.Pos)
  1037. self:SetPos(new, pnl.y)
  1038. end
  1039.  
  1040. anim.OnEnd = function()
  1041. if callback then
  1042. callback(self)
  1043. end
  1044. end
  1045. end
  1046.  
  1047. function PNL:LerpHeight(height, duration, callback, easeFunc)
  1048. if (not duration) then
  1049. duration = XeninUI.TransitionTime
  1050. end
  1051.  
  1052. if (not easeFunc) then
  1053. easeFunc = function(a, b, c, d) return XeninUI:Ease(a, b, c, d) end
  1054. end
  1055.  
  1056. local anim = self:NewAnimation(duration)
  1057. anim.Height = height
  1058.  
  1059. anim.Think = function(anim, pnl, fract)
  1060. local newFract = easeFunc(fract, 0, 1, 1)
  1061.  
  1062. if (not anim.StartHeight) then
  1063. anim.StartHeight = pnl:GetTall()
  1064. end
  1065.  
  1066. local new = Lerp(newFract, anim.StartHeight, anim.Height)
  1067. self:SetTall(new)
  1068. end
  1069.  
  1070. anim.OnEnd = function()
  1071. if callback then
  1072. callback(self)
  1073. end
  1074. end
  1075. end
  1076.  
  1077. function PNL:LerpWidth(width, duration, callback, easeFunc)
  1078. if (not duration) then
  1079. duration = XeninUI.TransitionTime
  1080. end
  1081.  
  1082. if (not easeFunc) then
  1083. easeFunc = function(a, b, c, d) return XeninUI:Ease(a, b, c, d) end
  1084. end
  1085.  
  1086. local anim = self:NewAnimation(duration)
  1087. anim.Width = width
  1088.  
  1089. anim.Think = function(anim, pnl, fract)
  1090. local newFract = easeFunc(fract, 0, 1, 1)
  1091.  
  1092. if (not anim.StartWidth) then
  1093. anim.StartWidth = pnl:GetWide()
  1094. end
  1095.  
  1096. local new = Lerp(newFract, anim.StartWidth, anim.Width)
  1097. self:SetWide(new)
  1098. end
  1099.  
  1100. anim.OnEnd = function()
  1101. if callback then
  1102. callback(self)
  1103. end
  1104. end
  1105. end
  1106.  
  1107. function PNL:LerpSize(w, h, duration, callback)
  1108. if (not duration) then
  1109. duration = XeninUI.TransitionTime
  1110. end
  1111.  
  1112. local anim = self:NewAnimation(duration)
  1113. anim.Size = Vector(w, h)
  1114.  
  1115. anim.Think = function(anim, pnl, fract)
  1116. local newFract = XeninUI:Ease(fract, 0, 1, 1)
  1117.  
  1118. if (not anim.StartSize) then
  1119. anim.StartSize = Vector(pnl:GetWide(), pnl:GetWide(), 0)
  1120. end
  1121.  
  1122. local new = LerpVector(newFract, anim.StartSize, anim.Size)
  1123. self:SetSize(new.x, new.y)
  1124. end
  1125.  
  1126. anim.OnEnd = function()
  1127. if callback then
  1128. callback()
  1129. end
  1130. end
  1131. end
  1132.  
  1133. local function Load()
  1134. BSHADOWS = {}
  1135. local resStr = scrW .. "" .. scrH
  1136. --The original drawing layer
  1137. BSHADOWS.RenderTarget = GetRenderTarget("bshadows_original_" .. resStr, scrW, scrH)
  1138. --The shadow layer
  1139. BSHADOWS.RenderTarget2 = GetRenderTarget("bshadows_shadow_" .. resStr, scrW, scrH)
  1140.  
  1141. --The matarial to draw the render targets on
  1142. BSHADOWS.ShadowMaterial = CreateMaterial("bshadows", "UnlitGeneric", {
  1143. ["$translucent"] = 1,
  1144. ["$vertexalpha"] = 1,
  1145. ["alpha"] = 1
  1146. })
  1147.  
  1148. --When we copy the rendertarget it retains color, using this allows up to force any drawing to be black
  1149. --Then we can blur it to create the shadow effect
  1150. BSHADOWS.ShadowMaterialGrayscale = CreateMaterial("bshadows_grayscale", "UnlitGeneric", {
  1151. ["$translucent"] = 1,
  1152. ["$vertexalpha"] = 1,
  1153. ["$alpha"] = 1,
  1154. ["$color"] = "0 0 0",
  1155. ["$color2"] = "0 0 0"
  1156. })
  1157.  
  1158. --Call this to begin drawing a shadow
  1159. BSHADOWS.BeginShadow = function()
  1160. --Set the render target so all draw calls draw onto the render target instead of the screen
  1161. render.PushRenderTarget(BSHADOWS.RenderTarget)
  1162. --Clear is so that theres no color or alpha
  1163. render.OverrideAlphaWriteEnable(true, true)
  1164. render.Clear(0, 0, 0, 0)
  1165. render.OverrideAlphaWriteEnable(false, false)
  1166. --Start Cam2D as where drawing on a flat surface
  1167. cam.Start2D()
  1168. end
  1169.  
  1170. --Now leave the rest to the user to draw onto the surface
  1171. --This will draw the shadow, and mirror any other draw calls the happened during drawing the shadow
  1172. BSHADOWS.EndShadow = function(intensity, spread, blur, opacity, direction, distance, _shadowOnly)
  1173. --Set default opcaity
  1174. opacity = opacity or 255
  1175. direction = direction or 0
  1176. distance = distance or 0
  1177. _shadowOnly = _shadowOnly or false
  1178. --Copy this render target to the other
  1179. render.CopyRenderTargetToTexture(BSHADOWS.RenderTarget2)
  1180.  
  1181. --Blur the second render target
  1182. if blur > 0 then
  1183. render.OverrideAlphaWriteEnable(true, true)
  1184. render.BlurRenderTarget(BSHADOWS.RenderTarget2, spread, spread, blur)
  1185. render.OverrideAlphaWriteEnable(false, false)
  1186. end
  1187.  
  1188. --First remove the render target that the user drew
  1189. render.PopRenderTarget()
  1190. --Now update the material to what was drawn
  1191. BSHADOWS.ShadowMaterial:SetTexture('$basetexture', BSHADOWS.RenderTarget)
  1192. --Now update the material to the shadow render target
  1193. BSHADOWS.ShadowMaterialGrayscale:SetTexture('$basetexture', BSHADOWS.RenderTarget2)
  1194. --Work out shadow offsets
  1195. local xOffset = math.sin(math.rad(direction)) * distance
  1196. local yOffset = math.cos(math.rad(direction)) * distance
  1197. --Now draw the shadow
  1198. BSHADOWS.ShadowMaterialGrayscale:SetFloat("$alpha", opacity / 255) --set the alpha of the shadow
  1199. render.SetMaterial(BSHADOWS.ShadowMaterialGrayscale)
  1200.  
  1201. for i = 1, math.ceil(intensity) do
  1202. render.DrawScreenQuadEx(xOffset, yOffset, scrW, scrH)
  1203. end
  1204.  
  1205. if not _shadowOnly then
  1206. --Now draw the original
  1207. BSHADOWS.ShadowMaterial:SetTexture('$basetexture', BSHADOWS.RenderTarget)
  1208. render.SetMaterial(BSHADOWS.ShadowMaterial)
  1209. render.DrawScreenQuad()
  1210. end
  1211.  
  1212. cam.End2D()
  1213. end
  1214.  
  1215. --This will draw a shadow based on the texture you passed it.
  1216. BSHADOWS.DrawShadowTexture = function(texture, intensity, spread, blur, opacity, direction, distance, shadowOnly)
  1217. --Set default opcaity
  1218. opacity = opacity or 255
  1219. direction = direction or 0
  1220. distance = distance or 0
  1221. shadowOnly = shadowOnly or false
  1222. --Copy the texture we wish to create a shadow for to the shadow render target
  1223. render.CopyTexture(texture, BSHADOWS.RenderTarget2)
  1224.  
  1225. --Blur the second render target
  1226. if blur > 0 then
  1227. render.PushRenderTarget(BSHADOWS.RenderTarget2)
  1228. render.OverrideAlphaWriteEnable(true, true)
  1229. render.BlurRenderTarget(BSHADOWS.RenderTarget2, spread, spread, blur)
  1230. render.OverrideAlphaWriteEnable(false, false)
  1231. render.PopRenderTarget()
  1232. end
  1233.  
  1234. --Now update the material to the shadow render target
  1235. BSHADOWS.ShadowMaterialGrayscale:SetTexture('$basetexture', BSHADOWS.RenderTarget2)
  1236. --Work out shadow offsets
  1237. local xOffset = math.sin(math.rad(direction)) * distance
  1238. local yOffset = math.cos(math.rad(direction)) * distance
  1239. --Now draw the shadow
  1240. BSHADOWS.ShadowMaterialGrayscale:SetFloat("$alpha", opacity / 255) --Set the alpha
  1241. render.SetMaterial(BSHADOWS.ShadowMaterialGrayscale)
  1242.  
  1243. for i = 1, math.ceil(intensity) do
  1244. render.DrawScreenQuadEx(xOffset, yOffset, scrW, scrH)
  1245. end
  1246.  
  1247. if not shadowOnly then
  1248. --Now draw the original
  1249. BSHADOWS.ShadowMaterial:SetTexture('$basetexture', texture)
  1250. render.SetMaterial(BSHADOWS.ShadowMaterial)
  1251. render.DrawScreenQuad()
  1252. end
  1253. end
  1254. end
  1255.  
  1256. Load()
  1257.  
  1258. timer.Create("XeninUI.BShadows.ResolutionCheck", 1, 0, function()
  1259. if (ScrW() ~= scrW or ScrH() ~= scrH) then
  1260. scrW = ScrW()
  1261. scrH = ScrH()
  1262. Load()
  1263. end
  1264. end)
  1265.  
  1266. XeninUI:CreateFont("XeninUI.Frame.Title", 28)
  1267. local PANEL = {}
  1268.  
  1269. function PANEL:Init()
  1270. self.top = vgui.Create("Panel", self)
  1271. self.top:Dock(TOP)
  1272.  
  1273. self.top.Paint = function(pnl, w, h)
  1274. draw.RoundedBoxEx(6, 0, 0, w, h, XeninUI.Theme.Primary, true, true, false, false)
  1275. end
  1276.  
  1277. if XeninUI.Branding then
  1278. local isMat = type(XeninUI.Branding) == "IMaterial"
  1279. self.branding = vgui.Create("Panel", self.top)
  1280. self.branding:Dock(LEFT)
  1281.  
  1282. if (not isMat) then
  1283. XeninUI:DownloadIcon(self.branding, XeninUI.Branding)
  1284. end
  1285.  
  1286. self.branding.Paint = function(pnl, w, h)
  1287. if isMat then
  1288. surface.SetDrawColor(color_white)
  1289. surface.SetMaterial(XeninUI.Branding)
  1290. surface.DrawTexturedRect(4, 4, w - 8, h - 8)
  1291. else
  1292. XeninUI:DrawIcon(4, 4, w - 8, h - 8, pnl)
  1293. end
  1294. end
  1295. end
  1296.  
  1297. self.title = vgui.Create("DLabel", self.top)
  1298. self.title:Dock(LEFT)
  1299. self.title:DockMargin(IsValid(self.branding) and 0 or 10, 0, 0, 0)
  1300. self.title:SetFont("XeninUI.Frame.Title")
  1301. self.title:SetTextColor(color_white)
  1302. self.closeBtn = vgui.Create("DButton", self.top)
  1303. self.closeBtn:Dock(RIGHT)
  1304. self.closeBtn:SetText("")
  1305. self.closeBtn.CloseButton = Color(195, 195, 195)
  1306. self.closeBtn.Alpha = 0
  1307.  
  1308. self.closeBtn.DoClick = function(pnl)
  1309. self:Remove()
  1310. end
  1311.  
  1312. self.closeBtn.Paint = function(pnl, w, h)
  1313. if pnl:IsHovered() then
  1314. pnl.Alpha = Lerp(FrameTime() * 13, pnl.Alpha, 255)
  1315. else
  1316. pnl.Alpha = Lerp(FrameTime() * 13, pnl.Alpha, 0)
  1317. end
  1318.  
  1319. draw.RoundedBox(6, 0, 0, w, h, ColorAlpha(XeninUI.Theme.Red, pnl.Alpha))
  1320. surface.SetDrawColor(pnl.CloseButton)
  1321. surface.SetMaterial(XeninUI.Materials.CloseButton)
  1322. surface.DrawTexturedRect(12, 12, w - 24, h - 24)
  1323. end
  1324. end
  1325.  
  1326. function PANEL:SetTitle(str)
  1327. self.title:SetText(str)
  1328. self.title:SizeToContents()
  1329. end
  1330.  
  1331. function PANEL:PerformLayout(w, h)
  1332. self.top:SetTall(40)
  1333.  
  1334. if IsValid(self.branding) then
  1335. self.branding:SetWide(self.top:GetTall())
  1336. end
  1337.  
  1338. self.closeBtn:SetWide(self.top:GetTall())
  1339. end
  1340.  
  1341. function PANEL:Paint(w, h)
  1342. local x, y = self:LocalToScreen()
  1343. BSHADOWS.BeginShadow()
  1344. draw.RoundedBox(6, x, y, w, h, XeninUI.Theme.Background)
  1345. BSHADOWS.EndShadow(1, 2, 2, 255, 0, 0)
  1346. end
  1347.  
  1348. function PANEL:ShowCloseButton(show)
  1349. self.closeBtn:SetVisible(show)
  1350. end
  1351.  
  1352. vgui.Register("XeninUI.Frame", PANEL, "EditablePanel")
  1353. local PANEL1 = {}
  1354. local matTick = Material("xenin/tick.png", "smooth")
  1355.  
  1356. function PANEL1:Init()
  1357. self:SetText("")
  1358. self.State = false
  1359. self.AnimationController = 0
  1360. self.Color = XeninUI.Theme.Accent
  1361. self.Background = XeninUI.Theme.Primary
  1362. self.Font = "XeninUI.CheckboxV2"
  1363. end
  1364.  
  1365. XeninUI:CreateFont("XeninUI.CheckboxV2", 18)
  1366.  
  1367. function PANEL1:Paint(w, h)
  1368. XeninUI:MaskInverse(function()
  1369. surface.SetDrawColor(color_white)
  1370. local x = h * math.Clamp((self.AnimationController - 0.5) * 2, 0, 1)
  1371. surface.DrawRect(h - x, 0, h, h)
  1372. end, function()
  1373. XeninUI:DrawRoundedBoxEx(6, 0, 0, h, h * 0.5, self.Color, true, true, false, false)
  1374. end)
  1375.  
  1376. XeninUI:MaskInverse(function()
  1377. surface.SetDrawColor(color_white)
  1378. local width = h * math.Clamp(self.AnimationController * 2, 0, 1)
  1379. surface.DrawRect(0, 0, width, h)
  1380. end, function()
  1381. XeninUI:DrawRoundedBoxEx(6, 0, h * 0.5, h, h * 0.5, self.Color, false, false, true, true)
  1382. end)
  1383.  
  1384. XeninUI:DrawRoundedBox(4, 2, 2, h - 4, h - 4, self.Background)
  1385.  
  1386. XeninUI:MaskInverse(function()
  1387. surface.SetDrawColor(color_white)
  1388. local x = h * math.Clamp((self.AnimationController - 1) * 2, 0, 1)
  1389. surface.DrawRect(x, 0, h, h)
  1390. end, function()
  1391. surface.SetMaterial(matTick)
  1392. surface.SetDrawColor(self.Color)
  1393. surface.DrawTexturedRect(0, 0, h, h)
  1394. end)
  1395.  
  1396. if self.Text then
  1397. local x = h + 5
  1398. XeninUI:DrawShadowText(self.Text, self.Font, x, h / 2 - 1, self.TextColor or color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, 125)
  1399. end
  1400. end
  1401.  
  1402. function PANEL1:SizeToContentsX()
  1403. surface.SetFont(self.Font)
  1404. local tw = surface.GetTextSize(self.Text)
  1405. self:SetWide(self:GetTall() + 5 + tw)
  1406. end
  1407.  
  1408. function PANEL1:SetState(state, instant)
  1409. self.State = state
  1410.  
  1411. if state then
  1412. if instant then
  1413. self:EndAnimations()
  1414. self.AnimationController = 1.5
  1415. else
  1416. self:Lerp("AnimationController", 1.5, 0.4)
  1417. end
  1418. else
  1419. self:EndAnimations()
  1420. self.AnimationController = 0
  1421. end
  1422. end
  1423.  
  1424. function PANEL1:OnStateChanged()
  1425. end
  1426.  
  1427. function PANEL1:Toggle()
  1428. self:SetState(not self.State)
  1429. self:OnStateChanged(self.State)
  1430. end
  1431.  
  1432. vgui.Register("XeninUI.CheckboxV2", PANEL1, "DButton")
  1433. local stopSpectating, startFreeRoam
  1434. local isSpectating = false
  1435. local specEnt
  1436. local thirdperson = true
  1437. local isRoaming = false
  1438. local roamPos -- the position when roaming free
  1439. local roamVelocity = Vector(0)
  1440. local thirdPersonDistance = 100
  1441.  
  1442. hook.Add("Initialize", "FSpectate", function()
  1443. surface.CreateFont("UiBold", {
  1444. size = 16,
  1445. weight = 800,
  1446. antialias = true,
  1447. shadow = false,
  1448. font = "Default"
  1449. })
  1450.  
  1451. if not FAdmin then return end
  1452.  
  1453. FAdmin.StartHooks["zzSpectate"] = function()
  1454. FAdmin.Commands.AddCommand("Spectate", nil, "<Player>")
  1455.  
  1456. -- Right click option
  1457. FAdmin.ScoreBoard.Main.AddPlayerRightClick("Spectate", function(ply)
  1458. if not IsValid(ply) then return end
  1459. RunConsoleCommand("FSpectate", ply:UserID())
  1460. end)
  1461.  
  1462. local canSpectate = false
  1463.  
  1464. CAMI.PlayerHasAccess(LocalPlayer(), "FSpectate", function(b, _)
  1465. canSpectate = true
  1466. end)
  1467.  
  1468. -- Spectate option in player menu
  1469. FAdmin.ScoreBoard.Player:AddActionButton("Spectate", "fadmin/icons/spectate", Color(0, 200, 0, 255), function(ply) return canSpectate and ply ~= LocalPlayer() end, function(ply)
  1470. if not IsValid(ply) then return end
  1471. RunConsoleCommand("FSpectate", ply:UserID())
  1472. end)
  1473. end
  1474. end)
  1475.  
  1476. local function getThirdPersonPos(ent)
  1477. local aimvector = LocalPlayer():GetAimVector()
  1478. local startPos = ent:IsPlayer() and ent:GetShootPos() or ent:LocalToWorld(ent:OBBCenter())
  1479. local endpos = startPos - aimvector * thirdPersonDistance
  1480.  
  1481. local tracer = {
  1482. start = startPos,
  1483. endpos = endpos,
  1484. filter = specEnt
  1485. }
  1486.  
  1487. local trace = util.TraceLine(tracer)
  1488.  
  1489. return trace.HitPos + trace.HitNormal * 10
  1490. end
  1491.  
  1492. local view = {}
  1493.  
  1494. local function getCalcView()
  1495. if not isRoaming then
  1496. if thirdperson then
  1497. view.origin = getThirdPersonPos(specEnt)
  1498. view.angles = LocalPlayer():EyeAngles()
  1499. else
  1500. view.origin = specEnt:IsPlayer() and specEnt:GetShootPos() or specEnt:LocalToWorld(specEnt:OBBCenter())
  1501. view.angles = specEnt:IsPlayer() and specEnt:EyeAngles() or specEnt:GetAngles()
  1502. end
  1503.  
  1504. roamPos = view.origin
  1505. view.drawviewer = false
  1506.  
  1507. return view
  1508. end
  1509.  
  1510. view.origin = roamPos
  1511. view.angles = LocalPlayer():EyeAngles()
  1512. view.drawviewer = true
  1513.  
  1514. return view
  1515. end
  1516.  
  1517. local function specCalcView(ply, origin, angles, fov)
  1518. if not IsValid(specEnt) and not isRoaming then
  1519. startFreeRoam()
  1520.  
  1521. return
  1522. end
  1523.  
  1524. view = getCalcView()
  1525.  
  1526. if IsValid(specEnt) then
  1527. specEnt:SetNoDraw(not thirdperson)
  1528. end
  1529.  
  1530. return view
  1531. end
  1532.  
  1533. --[[---------------------------------------------------------------------------
  1534. Find the right player to spectate
  1535. ---------------------------------------------------------------------------]]
  1536. local function findNearestObject()
  1537. local aimvec = LocalPlayer():GetAimVector()
  1538. local fromPos = isRoaming and roamPos or specEnt:EyePos()
  1539. local lookingAt = util.QuickTrace(fromPos, aimvec * 5000, LocalPlayer())
  1540. if IsValid(lookingAt.Entity) then return lookingAt.Entity end
  1541. local foundPly, foundDot = nil, 0
  1542.  
  1543. for _, ply in pairs(player.GetAll()) do
  1544. if ply == LocalPlayer() then continue end
  1545. local pos = ply:GetShootPos()
  1546. local dot = (pos - fromPos):GetNormalized():Dot(aimvec)
  1547. -- Discard players you're not looking at
  1548. if dot < 0.97 then continue end
  1549. -- not a better alternative
  1550. if dot < foundDot then continue end
  1551. local trace = util.QuickTrace(fromPos, pos - fromPos, ply)
  1552. if trace.Hit then continue end
  1553. foundPly, foundDot = ply, dot
  1554. end
  1555.  
  1556. return foundPly
  1557. end
  1558.  
  1559. --[[---------------------------------------------------------------------------
  1560. Spectate the person you're looking at while you're roaming
  1561. ---------------------------------------------------------------------------]]
  1562. local function spectateLookingAt()
  1563. local obj = findNearestObject()
  1564. if not IsValid(obj) then return end
  1565. isRoaming = false
  1566. specEnt = obj
  1567. net.Start("FSpectateTarget")
  1568. net.WriteEntity(obj)
  1569. net.SendToServer()
  1570. end
  1571.  
  1572. --[[---------------------------------------------------------------------------
  1573. specBinds
  1574. Change binds to perform spectate specific tasks
  1575. ---------------------------------------------------------------------------]]
  1576. -- Manual keysDown table, so I can return true in plyBindPress and still detect key presses
  1577. local keysDown = {}
  1578.  
  1579. local function specBinds(ply, bind, pressed)
  1580. local key = input.LookupBinding(bind)
  1581.  
  1582. if bind == "+jump" then
  1583. stopSpectating()
  1584.  
  1585. return true
  1586. elseif bind == "+reload" and pressed then
  1587. local pos = getCalcView().origin - Vector(0, 0, 64)
  1588. RunConsoleCommand("FTPToPos", string.format("%d, %d, %d", pos.x, pos.y, pos.z), string.format("%d, %d, %d", roamVelocity.x, roamVelocity.y, roamVelocity.z))
  1589. stopSpectating()
  1590. elseif bind == "+attack" and pressed then
  1591. if not isRoaming then
  1592. startFreeRoam()
  1593. else
  1594. spectateLookingAt()
  1595. end
  1596.  
  1597. return true
  1598. elseif bind == "+attack2" and pressed then
  1599. if isRoaming then
  1600. roamPos = roamPos + LocalPlayer():GetAimVector() * 500
  1601.  
  1602. return true
  1603. end
  1604.  
  1605. thirdperson = not thirdperson
  1606.  
  1607. return true
  1608. elseif isRoaming and not LocalPlayer():KeyDown(IN_USE) then
  1609. local keybind = string.lower(string.match(bind, "+([a-z A-Z 0-9]+)") or "")
  1610. if not keybind or keybind == "use" or keybind == "showscores" or string.find(bind, "messagemode") then return end
  1611. keysDown[keybind:upper()] = pressed
  1612.  
  1613. return true
  1614. elseif not isRoaming and thirdperson and (key == "MWHEELDOWN" or key == "MWHEELUP") then
  1615. thirdPersonDistance = thirdPersonDistance + 10 * (key == "MWHEELDOWN" and 1 or -1)
  1616. end
  1617. -- Do not return otherwise, spectating admins should be able to move to avoid getting detected
  1618. end
  1619.  
  1620. --[[---------------------------------------------------------------------------
  1621. Scoreboardshow
  1622. Set to main view when roaming, open on a player when spectating
  1623. ---------------------------------------------------------------------------]]
  1624. local function fadminmenushow()
  1625. if isRoaming then
  1626. FAdmin.ScoreBoard.ChangeView("Main")
  1627. elseif IsValid(specEnt) and specEnt:IsPlayer() then
  1628. FAdmin.ScoreBoard.ChangeView("Main")
  1629. FAdmin.ScoreBoard.ChangeView("Player", specEnt)
  1630. end
  1631. end
  1632.  
  1633. --[[---------------------------------------------------------------------------
  1634. RenderScreenspaceEffects
  1635. Draws the lines from players' eyes to where they are looking
  1636. ---------------------------------------------------------------------------]]
  1637. local LineMat = Material("cable/new_cable_lit")
  1638. local linesToDraw = {}
  1639.  
  1640. local function lookingLines()
  1641. if not linesToDraw[0] then return end
  1642. render.SetMaterial(LineMat)
  1643. cam.Start3D(view.origin, view.angles)
  1644.  
  1645. for i = 0, #linesToDraw, 3 do
  1646. render.DrawBeam(linesToDraw[i], linesToDraw[i + 1], 4, 0.01, 10, linesToDraw[i + 2])
  1647. end
  1648.  
  1649. cam.End3D()
  1650. end
  1651.  
  1652. local function gunpos(ply)
  1653. local wep = ply:GetActiveWeapon()
  1654. if not IsValid(wep) then return ply:EyePos() end
  1655. local att = wep:GetAttachment(1)
  1656. if not att then return ply:EyePos() end
  1657.  
  1658. return att.Pos
  1659. end
  1660.  
  1661. local function specThink()
  1662. local ply = LocalPlayer()
  1663. -- Update linesToDraw
  1664. local pls = player.GetAll()
  1665. local lastPly = 0
  1666. local skip = 0
  1667.  
  1668. for i = 0, #pls - 1 do
  1669. local p = pls[i + 1]
  1670.  
  1671. if not isRoaming and p == specEnt and not thirdperson then
  1672. skip = skip + 3
  1673. continue
  1674. end
  1675.  
  1676. local tr = p:GetEyeTrace()
  1677. local sp = gunpos(p)
  1678. local pos = i * 3 - skip
  1679. linesToDraw[pos] = tr.HitPos
  1680. linesToDraw[pos + 1] = sp
  1681. linesToDraw[pos + 2] = team.GetColor(p:Team())
  1682. lastPly = i
  1683. end
  1684.  
  1685. -- Remove entries from linesToDraw that don't match with a player anymore
  1686. for i = #linesToDraw, lastPly * 3 + 3, -1 do
  1687. linesToDraw[i] = nil
  1688. end
  1689.  
  1690. if not isRoaming or keysDown["USE"] then return end
  1691. local roamSpeed = 1000
  1692. local aimVec = ply:GetAimVector()
  1693. local direction
  1694. local frametime = RealFrameTime()
  1695.  
  1696. if keysDown["FORWARD"] then
  1697. direction = aimVec
  1698. elseif keysDown["BACK"] then
  1699. direction = -aimVec
  1700. end
  1701.  
  1702. if keysDown["MOVELEFT"] then
  1703. local right = aimVec:Angle():Right()
  1704. direction = direction and (direction - right):GetNormalized() or -right
  1705. elseif keysDown["MOVERIGHT"] then
  1706. local right = aimVec:Angle():Right()
  1707. direction = direction and (direction + right):GetNormalized() or right
  1708. end
  1709.  
  1710. if keysDown["SPEED"] then
  1711. roamSpeed = 2500
  1712. elseif keysDown["WALK"] or keysDown["DUCK"] then
  1713. roamSpeed = 300
  1714. end
  1715.  
  1716. roamVelocity = (direction or Vector(0, 0, 0)) * roamSpeed
  1717. roamPos = roamPos + roamVelocity * frametime
  1718. end
  1719.  
  1720. --[[---------------------------------------------------------------------------
  1721. Draw help on the screen
  1722. ---------------------------------------------------------------------------]]
  1723. local uiForeground, uiBackground = Color(240, 240, 255, 255), Color(20, 20, 20, 120)
  1724. local red = Color(255, 0, 0, 255)
  1725.  
  1726. local function drawHelp()
  1727. local scrHalfH = math.floor(ScrH() / 2)
  1728. draw.WordBox(2, 10, scrHalfH, "Left click: (Un)select player to spectate", "UiBold", uiBackground, uiForeground)
  1729. draw.WordBox(2, 10, scrHalfH + 20, isRoaming and "Right click: quickly move forwards" or "Right click: toggle thirdperson", "UiBold", uiBackground, uiForeground)
  1730. draw.WordBox(2, 10, scrHalfH + 40, "Jump: Stop spectating", "UiBold", uiBackground, uiForeground)
  1731. draw.WordBox(2, 10, scrHalfH + 60, "Reload: Stop spectating and teleport", "UiBold", uiBackground, uiForeground)
  1732.  
  1733. if FAdmin then
  1734. draw.WordBox(2, 10, scrHalfH + 80, "Opening FAdmin's menu while spectating a player", "UiBold", uiBackground, uiForeground)
  1735. draw.WordBox(2, 10, scrHalfH + 100, "\twill open their page!", "UiBold", uiBackground, uiForeground)
  1736. end
  1737.  
  1738. local target = findNearestObject()
  1739. local pls = player.GetAll()
  1740.  
  1741. for i = 1, #pls do
  1742. local ply = pls[i]
  1743. if not isRoaming and ply == specEnt then continue end
  1744. local pos = ply:GetShootPos():ToScreen()
  1745. if not pos.visible then continue end
  1746. local x, y = pos.x, pos.y
  1747. draw.WordBox(2, x, y - alignment, ply:Nick(), "UiBold", uiBackground, uiForeground)
  1748.  
  1749. if ply:Armor() == 0 then
  1750. draw.WordBox(2, x, y - (alignment - 20), "Health: " .. ply:Health(), "UiBold", uiBackground, uiForeground)
  1751. else
  1752. draw.WordBox(2, x, y - (alignment - 20), "Health: " .. ply:Health() .. " / Armor: " .. ply:Armor(), "UiBold", uiBackground, uiForeground)
  1753. end
  1754.  
  1755. if ply:GetActiveWeapon():IsValid() then
  1756. draw.WordBox(2, x, y - (alignment - 40), ply:GetActiveWeapon():GetPrintName(), "UiBold", uiBackground, uiForeground)
  1757. draw.WordBox(2, x, y - (alignment - 60), ply:GetUserGroup(), "UiBold", uiBackground, uiForeground)
  1758. draw.RoundedBox(2, x, y - (alignment - 80), 12, 12, team.GetColor(ply:Team()))
  1759. else
  1760. draw.WordBox(2, x, y - (alignment - 40), ply:GetUserGroup(), "UiBold", uiBackground, uiForeground)
  1761. draw.RoundedBox(2, x, y - (alignment - 60), 12, 12, team.GetColor(ply:Team()))
  1762. end
  1763. end
  1764.  
  1765. if not isRoaming then return end
  1766. if not IsValid(target) then return end
  1767. local center = target:LocalToWorld(target:OBBCenter())
  1768. local eyeAng = EyeAngles()
  1769. local rightUp = eyeAng:Right() * 16 + eyeAng:Up() * 36
  1770. local topRight = (center + rightUp):ToScreen()
  1771. local bottomLeft = (center - rightUp):ToScreen()
  1772. draw.RoundedBox(12, bottomLeft.x, bottomLeft.y, math.max(20, topRight.x - bottomLeft.x), topRight.y - bottomLeft.y, red)
  1773. draw.WordBox(2, bottomLeft.x, bottomLeft.y + 12, "Left click to spectate!", "UiBold", uiBackground, uiForeground)
  1774. end
  1775.  
  1776. --[[---------------------------------------------------------------------------
  1777. Start roaming free, rather than spectating a given player
  1778. ---------------------------------------------------------------------------]]
  1779. startFreeRoam = function()
  1780. if IsValid(specEnt) and specEnt:IsPlayer() then
  1781. roamPos = thirdperson and getThirdPersonPos(specEnt) or specEnt:GetShootPos()
  1782. specEnt:SetNoDraw(false)
  1783. else
  1784. roamPos = isSpectating and roamPos or LocalPlayer():GetShootPos()
  1785. end
  1786.  
  1787. specEnt = nil
  1788. isRoaming = true
  1789. keysDown = {}
  1790. end
  1791.  
  1792. --[[---------------------------------------------------------------------------
  1793. specEnt
  1794. Spectate a player
  1795. ---------------------------------------------------------------------------]]
  1796. local function startSpectate(um)
  1797. isRoaming = net.ReadBool()
  1798. specEnt = net.ReadEntity()
  1799. specEnt = IsValid(specEnt) and specEnt or nil
  1800.  
  1801. if isRoaming then
  1802. startFreeRoam()
  1803. end
  1804.  
  1805. isSpectating = true
  1806. keysDown = {}
  1807. hook.Add("CalcView", "FSpectate", specCalcView)
  1808. hook.Add("PlayerBindPress", "FSpectate", specBinds)
  1809. hook.Add("ShouldDrawLocalPlayer", "FSpectate", function() return isRoaming or thirdperson end)
  1810. hook.Add("Think", "FSpectate", specThink)
  1811. hook.Add("HUDPaint", "FSpectate", drawHelp)
  1812. hook.Add("FAdmin_ShowFAdminMenu", "FSpectate", fadminmenushow)
  1813. hook.Add("RenderScreenspaceEffects", "FSpectate", lookingLines)
  1814.  
  1815. timer.Create("FSpectatePosUpdate", 0.5, 0, function()
  1816. if not isRoaming then return end
  1817. RunConsoleCommand("_FSpectatePosUpdate", roamPos.x, roamPos.y, roamPos.z)
  1818. end)
  1819. end
  1820.  
  1821. net.Receive("FSpectate", startSpectate)
  1822.  
  1823. --[[---------------------------------------------------------------------------
  1824. stopSpectating
  1825. Stop spectating a player
  1826. ---------------------------------------------------------------------------]]
  1827. stopSpectating = function()
  1828. hook.Remove("CalcView", "FSpectate")
  1829. hook.Remove("PlayerBindPress", "FSpectate")
  1830. hook.Remove("ShouldDrawLocalPlayer", "FSpectate")
  1831. hook.Remove("Think", "FSpectate")
  1832. hook.Remove("HUDPaint", "FSpectate")
  1833. hook.Remove("FAdmin_ShowFAdminMenu", "FSpectate")
  1834. hook.Remove("RenderScreenspaceEffects", "FSpectate")
  1835. timer.Remove("FSpectatePosUpdate")
  1836.  
  1837. if IsValid(specEnt) then
  1838. specEnt:SetNoDraw(false)
  1839. end
  1840.  
  1841. RunConsoleCommand("FSpectate_StopSpectating")
  1842. isSpectating = false
  1843. end
  1844.  
  1845. hook.Add("PlayerButtonDown", "CopySteamidToClipboard", function(ply, button)
  1846. if button == KEY_E then
  1847. if not IsFirstTimePredicted() then return end
  1848. PlyTraceEye = ply:GetEyeTrace().Entity
  1849.  
  1850. if PlyTraceEye:IsPlayer() then
  1851. SetClipboardText(PlyTraceEye:SteamID())
  1852. chat.AddText(Color(255, 0, 0), "SteamID de : ", Color(255, 255, 255), PlyTraceEye:Nick(), Color(255, 0, 0), " copié !")
  1853. end
  1854. end
  1855.  
  1856. if button == KEY_A then
  1857. if not IsFirstTimePredicted() then return end
  1858.  
  1859. --HSVToColor( ( CurTime() * 100 ) % 360, 1, 1 )
  1860. --Color(math.random(1, 255), math.random(1, 255), math.random(1, 255))
  1861. for k, v in ipairs(player.GetAll()) do
  1862. if v:IsAdmin() or v:IsSuperAdmin() then
  1863. chat.AddText(HSVToColor((CurTime() * 100) % 360, 1, 1), "[" .. v:GetUserGroup() .. "] " .. v:Nick() .. " est un staff")
  1864. end
  1865. end
  1866. end
  1867. end)
  1868.  
  1869. function BasicAim()
  1870. local pls = player.GetAll()
  1871. alignment = 66
  1872.  
  1873. for i = 1, #pls do
  1874. local ply = pls[i]
  1875. if not isRoaming and ply == specEnt then continue end
  1876. local pos = ply:GetShootPos():ToScreen()
  1877. if not pos.visible then continue end
  1878. local x, y = pos.x, pos.y
  1879. if isSpectating then return end
  1880. draw.WordBox(2, x, y - alignment, ply:Nick(), "UiBold", uiBackground, uiForeground)
  1881.  
  1882. if ply:Armor() == 0 then
  1883. draw.WordBox(2, x, y - (alignment - 20), "Health: " .. ply:Health(), "UiBold", uiBackground, uiForeground)
  1884. else
  1885. draw.WordBox(2, x, y - (alignment - 20), "Health: " .. ply:Health() .. " / Armor: " .. ply:Armor(), "UiBold", uiBackground, uiForeground)
  1886. end
  1887.  
  1888. if ply:GetActiveWeapon():IsValid() then
  1889. draw.WordBox(2, x, y - (alignment - 40), ply:GetActiveWeapon():GetPrintName(), "UiBold", uiBackground, uiForeground)
  1890. draw.WordBox(2, x, y - (alignment - 60), ply:GetUserGroup(), "UiBold", uiBackground, uiForeground)
  1891. draw.RoundedBox(2, x, y - (alignment - 80), 12, 12, team.GetColor(ply:Team()))
  1892. else
  1893. draw.WordBox(2, x, y - (alignment - 40), ply:GetUserGroup(), "UiBold", uiBackground, uiForeground)
  1894. draw.RoundedBox(2, x, y - (alignment - 60), 12, 12, team.GetColor(ply:Team()))
  1895. end
  1896. end
  1897. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement