supinus

NHES2DZST

Nov 12th, 2024 (edited)
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local config = ac.configValues({
  2.   hubUrl = ""
  3. })
  4.  
  5. ---@class NoHesiClient
  6. local NoHesiClient = class("NoHesiClient")
  7.  
  8.  
  9. local closestcar = 1
  10.  
  11.  
  12. -- Import the WebBrowser library
  13. local WebBrowser = require('shared/web/browser')
  14. ui.setAsynchronousImagesLoading(true)
  15.  
  16. -- Configure the WebBrowser
  17. WebBrowser.configure({
  18.   targetFPS = 240,
  19. })
  20.  
  21. -- Create an instance of the browser with initial parameters
  22. local browser = WebBrowser({
  23.   size = vec2(500, 400),  -- Set the size of the browser window
  24.   backgroundColor = rgbm(0,0,0,0),  -- Set the background color
  25.   directRender = true,  -- Enabl direct rendering
  26.   redirectAudio = true,  -- Enabele audio redirection
  27. })
  28.  
  29. -- Store the last size of the browser window
  30. local lastSize = vec2(450, 420)
  31. -- Initialize mouse buttons states
  32. local mouseButtons = {false, false, false}
  33.  
  34.  
  35. function checkAndLoadVideo()
  36. local rootFolder = ac.getFolder(ac.FolderID.Root) .. "\\cache\\remote_assets\\nohesivideo"
  37. local targetFile = rootFolder .. "\\2_90FPS_2.wmv"
  38. print("Checking if target file exists: " .. targetFile)
  39.  
  40. -- Check if the file exists
  41. if not io.fileExists(targetFile) then
  42.     print("File does not exist, starting download process.")
  43.     local function onAssetsLoaded(err, folder)
  44.         if err then
  45.             print("Error loading assets: " .. err)
  46.             return
  47.         else
  48.             print("Assets loaded successfully.")
  49.         end
  50.  
  51.         -- Path to the file to move
  52.         local sourceFile = folder .. "\\2_90FPS_2.wmv"
  53.         print("Source file path: " .. sourceFile)
  54.  
  55.         -- Create the directory if it doesn't exist
  56.         if not io.dirExists(rootFolder) then
  57.             print("Target directory does not exist, creating: " .. rootFolder)
  58.             io.createDir(rootFolder)
  59.         else
  60.             print("Target directory already exists.")
  61.         end
  62.  
  63.         -- Attempt to move the file
  64.         print("Attempting to move file from " .. sourceFile .. " to " .. targetFile)
  65.         if io.move(sourceFile, targetFile) then
  66.             print("File successfully moved to " .. targetFile)
  67.             loadVideoInPlayer(targetFile)
  68.         else
  69.             print("Failed to move the file. Checking permissions and file locks.")
  70.         end
  71.     end
  72.     -- Start downloading and unpacking the assets
  73.     print("Initiating download from URL.")
  74.     web.loadRemoteAssets("https://cdn.discordapp.com/attachments/880053607024717854/1209263927045652591/2_90FPS_2.zip?ex=65e649cb&is=65d3d4cb&hm=33f584a885ac8ea30f635cea6c28831a9ea8bf0e17e4799a51597b2bc1b81d00&", onAssetsLoaded)
  75. else
  76.     print("File already exists, loading into MediaPlayer.")
  77.     loadVideoInPlayer(targetFile)
  78. end
  79. end
  80.  
  81.  
  82.  
  83.  
  84. local htmlContent = [[
  85. <!DOCTYPE html>
  86. <html lang='en'>
  87. <head>
  88. <meta charset='UTF-8'>
  89. <link rel="preconnect" href="https://fonts.googleapis.com">
  90. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  91. <link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,slnt,wdth,wght,GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,[email protected],-10..0,25..151,100..1000,-200..150,323..603,25..135,649..854,-305..-98,560..788,416..570,528..760&display=swap" rel="stylesheet">
  92.  
  93. <style>
  94.  
  95.  
  96.  
  97. .shake-top {
  98.   animation: shake-top 0.8s cubic-bezier(0.455, 0.030, 0.515, 0.955) both;
  99. }
  100.  
  101. @keyframes shake-top {
  102.   0%, 100% {
  103.     transform: rotate(0deg);
  104.     transform-origin: 50% 0;
  105.   }
  106.   10% {
  107.     transform: rotate(2deg);
  108.   }
  109.   20%, 40%, 60% {
  110.     transform: rotate(-4deg);
  111.   }
  112.   30%, 50%, 70% {
  113.     transform: rotate(4deg);
  114.   }
  115.   80% {
  116.     transform: rotate(-2deg);
  117.   }
  118.   90% {
  119.     transform: rotate(2deg);
  120.   }
  121. }
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128. .blink-2 {
  129.   animation: blink-2 0.4s both;
  130. }
  131.  
  132. @keyframes blink-2 {
  133.   0% {
  134.     opacity: 1;
  135.   }
  136.   50% {
  137.     opacity: 0.1;
  138.   }
  139.   100% {
  140.     opacity: 1;
  141.   }
  142. }
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149. :root {
  150.   --font-family: 'Roboto Flex', sans-serif;
  151.   --second-family: 'Roboto', sans-serif;
  152.   --main-color: #B130FF; /* Purple color */
  153. }
  154.  
  155.  
  156. body, html {
  157.   height: 100%;
  158.   margin: 0;
  159.   display: flex;
  160.   justify-content: left;
  161.   align-items: baseline;
  162.   background-color: rgba(0, 0, 0, 0.0)/* Dark background */
  163.  
  164. }
  165.  
  166. .dashboard {
  167.   justify-content: flex-start; /* Это изменение выровняет все содержимое dashboard, включая logo, слева */
  168. }
  169.  
  170. .logo {
  171.   justify-content: flex-start;
  172.   width: 100%;
  173. }
  174.  
  175.  
  176.  
  177. .logo-text {
  178.    
  179.   margin-left: 10px;
  180.   font-size: 24px;
  181.   font-weight: 700;
  182.   font-family: var(--second-family);
  183. }
  184.  
  185. .score-section {
  186.   display: flex;
  187.   align-items: center; /* This will vertically center the items */
  188.   margin-top: 20px; /* Adjust as necessary */
  189. }
  190.  
  191. .score-text {
  192.    margin-top: -13px; /* Поднимает элемент на 10 пикселей вверх */
  193.   font-family: 'Roboto Flex', sans-serif;
  194.   font-weight: 1000; /* Extra Black - Обратите внимание, что максимальный доступный вес может быть 900 для некоторых шрифтов */
  195.   font-size: 26px;
  196.   line-height: 106%;
  197.   letter-spacing: 0.03em;
  198.   text-transform: uppercase;
  199.   color: #fff;
  200.  
  201.   /* Применение настроек переменных шрифтов */
  202.   font-variation-settings: 'wdth' 111, 'GRAD' 0, 'slnt' 0, 'XTRA' 496, 'XOPQ' 96, 'YOPQ' 79, 'YTLC' 416, 'YTUC' 712, 'YTAS' 649, 'YTDE' -203, 'YTFI' 738, 'opsz' 79;
  203. }
  204. .score-badge {
  205.   margin-top: -40px; /* Поднимает элемент вверх */
  206.   margin-left: 20px; /* Поднимает элемент вверх */
  207.   border: 1.2px solid rgba(255, 255, 255, 0.13); /* Оставляем рамку как есть, если она вам нужна */
  208.   border-radius: 4px;
  209.   padding: 4px 8px 4px 4px; /* Измененные паддинги */
  210.   width: 71px; /* Измененная ширина */
  211.   height: 21px; /* Измененная высота */
  212.   background: rgba(1, 1, 1, 1); /* Новый цвет фона */
  213.   display: flex;
  214.   justify-content: center;
  215.   align-items: center;
  216.   gap: 6px; /* Добавляем пространство между SVG и текстом */
  217. }
  218.  
  219. .score-badge-text {
  220.   font-family: 'Roboto Flex', sans-serif;
  221.   font-weight: 740; /* Medium */
  222.   font-size: 16px; /* Размер шрифта оставляем как был */
  223.   color: rgba(238, 237, 238, 0.87); /* Цвет текста оставляем как был */
  224.   font-variation-settings: 'wdth' 151, 'GRAD' 0, 'slnt' 0, 'XTRA' 468, 'XOPQ' 96, 'YOPQ' 79, 'YTLC' 514, 'YTUC' 712, 'YTAS' 750, 'YTDE' -203, 'YTFI' 738, 'opsz' 21;
  225. }
  226.  
  227.  
  228. .speed-up {
  229.   margin-top: -20px; /* Поднимает элемент на 10 пикселей вверх */
  230.   font-family: 'Roboto Flex', sans-serif;
  231.   font-weight: 700; /* Bold */
  232.   font-stretch: expanded;
  233.   font-style: oblique 10deg; /* Для курсива */
  234.   font-size: 11px;
  235.   line-height: 82%;
  236.   text-transform: uppercase;
  237.   color: #ff2074;
  238.   border: 0.49px solid rgba(255, 0, 95, 0.68);
  239.   border-radius: 8px;
  240.   padding: 7px 13px;
  241.   width: 210px;
  242.   height: 15px;
  243.   background: rgba(255, 32, 116, 0.15);
  244.   display: flex;
  245.   justify-content: center;
  246.   align-items: center;
  247.  
  248.  
  249.   /* Использование переменных шрифтов */
  250.   font-variation-settings: 'wdth' 151, 'slnt' -10, 'XTRA' 468, 'XOPQ' 96, 'YOPQ' 79, 'YTLC' 514, 'YTUC' 712, 'YTAS' 750, 'YTDE' -203, 'YTFI' 738;
  251. }
  252.  
  253. .points-info {
  254.   font-weight: 1000; /* Extra Black - убедитесь, что шрифт поддерживает это значение */
  255.   font-size: 22px;
  256.   line-height: 100%;
  257.   text-transform: uppercase;
  258.   color: #fff; /* White color */
  259.   font-family: 'Roboto Flex', sans-serif;
  260.   font-variation-settings: 'wdth' 111, 'GRAD' 0, 'slnt' 0, 'XTRA' 496, 'XOPQ' 96, 'YOPQ' 79, 'YTLC' 416, 'YTUC' 712, 'YTAS' 649, 'YTDE' -203, 'YTFI' 738, 'opsz' 79;
  261.   margin-top: 40px; /* Adjust space from the SPEED UP block */
  262. }
  263.  
  264. .block-model {
  265. display: flex;
  266. justify-content: flex-start; /* Выравнивает элементы по левому краю */
  267. gap: 9px; /* Использует переменную для расстояния между элементами */
  268. margin-top: 10px; /* Отступ сверху */
  269. padding-left: var(--padding-left-block-model); /* Если нужен отступ слева для всего контейнера */
  270. width: 100%; /* Занимает всю доступную ширину */
  271. }
  272.  
  273.  
  274. .item {
  275. display: flex;
  276. flex-direction: column; /* Устанавливает направление элементов в колонку */
  277. align-items: center; /* Центрирует элементы по горизонтали */
  278. }
  279.  
  280. .combo-text {
  281. font-weight: 700;
  282. font-size: 12px;
  283. line-height: 0%;
  284. letter-spacing: -0.02em;
  285. text-transform: uppercase;
  286. text-align: center;
  287. color: var(--combo-text-color, rgba(238, 237, 238, 0.68)); /* Значение по умолчанию */
  288. font-family: 'Roboto Flex', sans-serif;
  289. margin-bottom: 8px; /* Отступ между текстом COMBO и объектом */
  290. font-variation-settings: 'wdth' 151, 'slnt' -10, 'GRAD' 0, 'XTRA' 468, 'XOPQ' 96, 'YOPQ' 79, 'YTLC' 514, 'YTUC' 712, 'YTAS' 750, 'YTDE' -203, 'YTFI' 738, 'opsz' 10;
  291.  
  292. }
  293.  
  294.  
  295. .object {
  296. border: 0.86px solid rgba(255, 255, 255, 0.13);
  297. border-radius: 6px;
  298. padding: 5px 6px;
  299. width: 61px;
  300. height: 20px;
  301. background: rgba(255, 255, 255, 0.08);
  302. display: flex;
  303. justify-content: center;
  304. align-items: center;
  305. }
  306.  
  307. .object-text {
  308. font-weight: 600;
  309. font-size: 14px;
  310. line-height: 143%;
  311. text-align: center;
  312. color: rgba(238, 237, 238, 0.87);
  313. font-family: 'Roboto Flex', sans-serif;
  314. }
  315.  
  316. .speed-warning {
  317. color: rgba(255, 32, 116, 1);
  318. font-family: 'Roboto Flex', sans-serif;
  319. font-size: 14px;
  320. font-weight: 700;
  321. line-height: 10px;
  322. letter-spacing: 0em;
  323. text-transform: uppercase; /* Делает весь текст в верхнем регистре */
  324. text-align: left; /* Центрирует текст по центру */
  325. font-variation-settings: 'wdth' 151, 'GRAD' 0, 'slnt' -10, 'XTRA' 468, 'XOPQ' 96, 'YOPQ' 79, 'YTLC' 514, 'YTUC' 712, 'YTAS' 750, 'YTDE' -203, 'YTFI' 738;
  326. margin-top: 20px; /* Отступ сверху, чтобы отделить текст от объектов */
  327. margin-left: 20px; /* Отступ сверху, чтобы отделить текст от объектов */
  328. display: block; /* Гарантирует, что элемент будет на новой строке */
  329.  
  330. }
  331.  
  332.  
  333.  
  334. .content {
  335. visibility: hidden; /* Содержимое скрыто, но прогружается */
  336. opacity: 0;
  337. transition: visibility 0s, opacity 1s linear; /* Плавное появление */
  338. transition-delay: 2s; /* Задержка перед началом анимации появления */
  339. }
  340.  
  341. .logo-text {
  342. position: absolute;
  343.  
  344. opacity: 0; /* Изначально текст невидим */
  345. margin-top: 30px
  346.  
  347. }
  348.  
  349.  
  350.  
  351.  
  352. </style>
  353. </head>
  354. <body>
  355.  
  356.  
  357.  
  358. </div>
  359. </div>
  360. </div>
  361. <div class="content">
  362. <div class='dashboard'>
  363. <div class='logo'>
  364.       <svg width='90' height='28' viewBox='0 0 90 28' fill='none' xmlns='http://www.w3.org/2000/svg'>
  365.       <path d='M13.3 5.2l.1-.1 1.7.5h.8q1.3-.4 2.4-.4v.5q-.5.6-.5.9l.2.9-.2.2v.1l.3 1v1.4q-.5.7-.5 1.2v.2l.7 1.7-.7 1.6.6 1v.1l-.2 1.4v2.3l.2.4v.6l-.1.7.1.2v.1l-.2 1 .2.9-2.9.4-1.3-.2-.5.1-.6-.1-.8.2-.4-.1-.4.1q-.2-.3-.3-1.2 1.1 0 1.1-2v-.2l-.2-1.1.2-1.9V16l-.5-1.5v-.4q.2-.3.6-3.1l.2-.4-.2-.7.1-.9q-.3-2.4-1-2.4-.4 0-.6-.5 0-.6 2.6-.9zm6.1.1l1.1-.1 1.8 1.2q1.4 0 3 2.1.6 2.4 1.4 2.4.1 1.3.3 1.6v1l-.1 1 .1.5-.2.5.2.5q-1 4.7-2 4.7l.1.6q-1 .2-2.4 1.9-2.3.3-2.5.7-1 0-1-1.5l1.5-.8v-.3h.1l-.1-3.7v-1.9l.1-.9-.1-.1-.2-.4h-.1l.3-.7-.2-.8.2-.1h.1l-.1-1q.2-.3.3-1.8l-.3-.5.1-.5q-.2 0-.6-1l.1-.4-.1-.7h.1l-.1-.4h-.8zm10 20.6v1.6l-.4.1-.3-.2h-.4l-.4.1v-.1h-.5l-.6.1q-.2-.1-.6-.1l-.5.1q-.6 0-.9-.2l-.5.1h-.6l-.3-.1-.4.3-.8-.2-.5.1-.2-.1h-.2l-.1-.1q-.8 0-1 .3h-.5q0-.1-.7-.2l-.2.1-.6-.2-.5.2h-.4l-.2.1q-.8-.1-.8-.3l-1.1.2-.9-.1-.9.2-.7-.2h-1.1q-.1.1-.7.2l-.3-.1h-.1v-1.7l1.2.2q.3 0 .5-.2.4 0 .7.2l.8-.2 1.2.1h.1l.2.1.4-.1h.3l.3.1.9-.1.7.1h1l.7-.1h.2l1.9-.1H22.2q.2.2.4.3l.6-.2h.4q.3-.1.6-.1h.2l.3.1.4-.1.7.1.6-.2q1.1.2 2 .2H29.4zm0-23.9v1.5l-.7-.1-.9.2-.7-.1H25.9l-.5.2-.4-.1h-.1l-.4-.1-.1.1-.7-.2-.2.1-.6-.1-.6.1h-.2l-.4-.1v.1l-.5-.1-.2.1-.2-.1h-.6l-.4.2h-.1v-.1l-.9.2-.5-.2h-1l-.1-.1-.1.1h-1.2l-.2-.1-.2.2-.5-.2-.2.1-.1-.1-.3.2-.6-.1h-.4l-.7-.2-1.5.2h-.7V1.9q0 .1.3.1h.1v-.1l.3.2h.1q.1-.1.5-.1l.2-.3 1.5.4h.1l.6-.3h.6l.1.2 1.2-.1q.3.1.7.1.2 0 .5-.2l.3.2h.3l.6-.1.6.2q.7-.1.8-.3l.2.1q.5 0 .8-.3.3 0 .5.2.9.2.9.3l.4-.1v.1h.1l.3-.1h.6l1.6-.3 1.3.2.8-.1v.1l.2-.1h.7l.7.2h.4zm1.2 3.1l1.4.5h.8l2 .1v.1q0 1.5-1.3 1.5l-1.6 1.3q0 1.1-1.5 2l-.2.6q-.9-.2-.9-.4l.3-.5-.1-.8.2-.7-.1-.2v-.1l.4-.8v-.2q-.5-.7-.5-1.2v-.6q.3-.6 1.1-.6zm5.1 1.2l1.3-.8q.8.3 1.7.3l1.5-.3q2.1.1 2.1.5-.2 1.4-.6 1.4l.1.9q-1 2.7-1.7 3.3l-.4 1.6v.8q-1.5 1.1-1.5 2.4-1.2 1.8-1.9 4.6-.4 0-1 2.2v.6l-.6.1-3.4-.5h-1.1l-.5.1q-.6 0-.6-1.2l.2-.6h-.1q0-.3 1.2-1.2l1-2.3-.1-.7 2.7-5.3q0-1.3 1.3-3.3l-.1-.1v-.2q.2-.2.5-2.3zM41.5 18h.3l.5.4-.3 1.8.6 3.2-.2.2-1-.1-.5.4-1.1-.1-1.1.2q-2.7-.2-2.7-.5.4-1.4 1.2-1.4l1.8-.7q.3 0 .3-.6 1.1 0 1.5-2.3.1-.5.7-.5zm3-16.3v1.5l-.5.1-.8-.2-.4.1-.6-.1-.6.2-.2-.1-1.9.2-.1-.1-.4.1-.2-.1q-.1-.2-.4-.2-.5.1-.5.2l-.5-.1q-.2.2-.5.2h-.2l-.3-.1h-.5l-.6-.1-.6.2q-1.1-.2-2.1-.2l-.1.1v-.1l-.5.1-.3-.1q-.2 0-.2.2-.3 0-1.3-.3l-.8.2h-.5V1.7q0 .1.1.1.5-.1 1.1-.1h1.1l.8-.1.4.1H32.7l.4-.1.1.1h.5l.5-.1q.3.1.6.1l.5-.1q.6 0 1 .2l.4-.1h.7l.3.1.3-.2.9.1.4-.1.2.1H39.8l.1.1q.7 0 1-.3l.2.1.3-.1q0 .1.7.2l.1-.1.7.2.4-.2h.7q.3 0 .5.1zm0 25.8h-.7q-.8 0-.8-.2l-1.1.2-1-.1-.8.1-.7-.1h-1.1q-.1.1-.7.1h-.3l-.3.1-.2-.1-.3.1q0-.2-.7-.3l-.9.2H33l-.1-.1h-.2l-.3.1-.2-.1q0 .1-1.1.1-.1-.1-.6-.1 0 .1-.5.1 0-.1-.5-.2h-.6V26h.3l.7-.2.7.1h.8l.5.1 1.6-.2.1.1.2-.1.2.1.1-.1.4.1.6-.1.8.1.8-.2 1.7.2q.3 0 .5-.1.4 0 .7.1l.8-.1 1.2.1v-.1h.1l.2.1.4-.1h.3l.3.1.9-.1.7.2zm5.1-22.4q1.2.3 1.2.5V6q0 .9-1.5 1.3l-.5 1.4q.7 1.8 1.5 1.8.1.3 2.5 1 1.8 1.6 2.9 1.6 0 .2 1.2 1.2v.9q.3 0 .3.2l-.1.5q.5.6.5 2.1-.3 0-.5 2.2-1.2 1.3-2.3 3-2.7.8-3.7.8H51q-.2 0-.4-.7.2-1.2 1.1-1.2 1.2 0 1.3-1.1v-1.1q-.5-2.2-3-2.2-.1-.4-2-1 0-.3-1.9-1.1-.6-1.6-.9-1.6v-.6l-1-1.3.6-1.2-.4-1.2.4-.2v-.6q1.6-2.5 2.6-2.9l.1.1h.2q.3 0 1.9-1zm6.9 0h.1q.1.9.4.9l-.1.6.1.7-.4 1.3v.1l.5 1.3v.4q0 .6-.7 1.2h-.6v-1.2Q54.4 8.1 54 7.9q-2-1-2.3-1.3v-.3q0-.9.5-.9 2.3.3 2.7.7h.5q0-.8 1.1-1zM44.9 16.8h.4q.4.2.9 1.4v.1l-.1.6q.8.6 1.3 2.5v.1h.6l1.9 1.4v.6q0 .4-1.3.4-.1-.3-.8-.6l-.1.1h-.2q-.7-.3-.7-.5-.8 0-1.4 1H45l-.3-.6.1-.6-.3-.3v-.8l-.2-.7.2-1v-.8l-.1-.5q.2-1.8.5-1.8zM59.1 1.7v1.6h-1.5l-.6.1-.8-.1-.8.2-1.7-.3q-.3 0-.5.2-.4 0-.7-.2l-.8.2-1.2-.1h-.1l-.2-.1-.4.1h-.3l-.3-.1-.9.1-.7-.1h-1l-.7.1h-.2l-1.7.1V1.8l.1-.1.1.1q.8 0 1-.2h.5q0 .1.7.1h.2l.6.1.5-.1h.4l.2-.1q.8.1.8.2l1.1-.1h1l.8-.1.7.2h1.1q.1-.1.7-.2l.3.1.3-.1h.2l.3-.1q0 .3.7.3l.9-.2h.4l.5.1h.1v-.1l.6.1h.3zm0 24v1.6q-.8 0-1.7.2l-.6-.2-.7.1-.4-.1-.3.1h-.2q-.3 0-.5-.1h-.5l-.5-.2q-.3.1-.5.3h-.6l-1.9-.1h-.2l-.6-.1h-1l-.8.1-.9-.1-.3.1h-.3l-.4-.1-.1.1H46l-1.3.1-.7-.2v-1.5l.4-.1.9.1h.9l1.1.2q0-.2.8-.3l.2.1h.5l.4.2.7-.2h.1q.7 0 .7-.1h.5q.3.3 1 .3l.1-.2.2.1.3-.1.4.1.8-.2.4.3.3-.2.1.1.5-.1.5.2q.3-.2 1-.2l.4.1q.4 0 .6-.1h1.1zM60 5.1l1 .1.9-.1q1.2 0 1.3 1.6l-1.2.7v.3q0 1.1-.7 1.8 0 2.5-.9 2.5H60q-.4 0-.7-1.7l.1-.2V10l-.1-.7.1-1.7-.1-.2v-.1l.1-.4q-.3 0-.5-1.4 0-.4 1.1-.4zm11.2-1.7l-.1-.1q-1.1 0-1.1-.1h-.2l-.2-.1q0 .2-1.5.3l-.9-.2h-1.3l-.6.1-.6-.1h-.5l-.5-.2-.8.2-.5-.1-.7.2-.7-.1h-.8l-.5-.1-1.1.1V1.7l.1.1h.2l.3-.2.2.2q0-.2 1.1-.2.1.1.6.2 0-.2.5-.2 0 .1.5.2h.6l.4-.2 1.1.3.4-.1h.1l.3-.1.9.2.5-.2.1.1.8-.2.7.3 1.1-.3 1 .1.4-.1q0 .1.5.2l.1-.2q.6 0 1.1.2.6 0 .8-.3h.2l.9.2h.2l.6-.2q1.1.2 1.3.4h.2q.3 0 .3-.2h.1v.1h.2v1.5h-.3l-.4.1q-.7-.1-.8-.2h-.2l-1.1-.1q-.7 0-.9.2h-.1l-.2-.1-.3.1v-.1h-.2q-.3.1-1.3.2zM71 27.3h-.1l-.4.1q0-.1-.2-.1l-.4.1v-.1q-.5.1-.7.2-.5-.1-.7-.3h-2.1l-.4-.1-.9.2h-.2l-.4-.1h-.3q-.3 0-.9.2l-.2-.1-.7.1h-.2l-.9-.3q-.9.3-1.2.3 0-.2-.2-.2l-.3.1-.5-.1v.1l-.1-.1q-.2 0-.4.1v-1.6l.3.1.2-.1.1.1.4-.2.8.2 1-.1q.7 0 1.2.2.5-.4.7-.4h.2l1 .2h.7l.4-.1.9.1q.2 0 .8-.2.2 0 .7.3h.1l.2-.1v.1h.1q.2-.2.3-.2h.5q.1.1.3.1.8 0 .8-.1l.6.2.3-.1H71.5l.8.2h.2l.9.1.6-.1.3.1 1.6-.3h.3q.1.2.8.2v1.5l-.6-.2-1.1.4-1.5-.2q0 .2-.3.2h-.2q-.3 0-.5-.2l-1.1.2q-.6 0-.7-.3zm.4-21.8l1.1-.3h1.8q.7 1.2.7 2.6-.4.6-.4 1.7l.2.5-.5 2h-.6q-.3 0-.6-1.4l.3-.2q0-2.3-1.2-2.8 0-.8-.8-.8l-.1-.1v-.1l.2-.5zm-3.6-.3l.5.2.6-.2q.7 0 1.3.6l-.1 2.4.1 1.1-.3.6.4 2.2q-.3 0-.4.9l.2.4-.3.7v.1l.1.4-.2 2.6q.3.4.5 2.7l-.1.5.1.4-.3.2v.6q.2.4 1.4.8l.1.6v.2q-.3 0-.6.7h-.4l-.7-.2q-.6.3-1.6.3l-.8-.3v.2l-.1-.2H67l-1 .3q-.6 0-1.5-.6l-1.2.3q0-.3-.5-.3v-.3q.3 0 .3-.6.6 0 .9-1.6l.1-.1v-1.1q0-2.6.5-2.9v-.1q-.2-1.6-.7-1.9v-.1q.4-.4.4-.8V13l-.3-2v-.1q0-.9.8-1.9 0-1.8-.4-3.4h.1l2.3.1q0-.3 1-.5z' fill='#e319d8' stroke='#1428c4' stroke-miterlimit='#10' stroke-width="1.5"/>
  366.  
  367.     </svg>
  368. </div>
  369. <div class='score-section'>
  370.   <p class='score-text'>PB 0 PTS</p>
  371.   <div class='score-badge'>
  372.   <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  373.     <path d="M15.4259 10.5856V13.502L14.9075 13.7149L6.82868 5.61646V14.1579L10.9011 18.205H7.27772L4.28613 15.225V0.213343L4.80369 0L15.4259 10.5856ZM19.1747 24L19.6922 23.7867V8.77496L16.7007 5.79503H13.0989L17.1497 9.8421V18.3835L9.07086 10.2851L8.55244 10.498V13.4144L19.1747 24Z" fill="#08060A" fill-opacity="0.83" />
  374.   </svg>
  375.   <span class='score-badge-text'>#1</span>
  376. </div>
  377.  
  378.   </div>
  379. </div>
  380. <!-- Новый элемент для SPEED UP -->
  381. <div class='speed-up'>SPEED UP!</div>
  382. <div class='points-info' id='pointsDisplay'>PB 0 PTS</div>
  383. <div class='block-model'>
  384. <div class='item'>
  385.   <p class='combo-text'>COMBO</p>
  386.   <div class='object'>
  387.     <div class='object-text' style='color: rgba(255, 214, 67, 0.87);'>0x</div>
  388.   </div>
  389. </div>
  390. <div class='item'>
  391.   <p class='combo-text'>SPEED</p>
  392.   <div class='object'>
  393.     <div class='object-text' style='color: rgba(106, 255, 103, 0.87);'>0x</div> <!-- Пример другого цвета -->
  394.   </div>
  395. </div>
  396. <div class='item'>
  397.   <p class='combo-text'>Proximity</p>
  398.   <div class='object'>
  399.     <div class='object-text' style='color: rgba(238, 237, 238, 0.87);'>0x</div> <!-- И еще один цвет -->
  400.   </div>
  401.  
  402.  
  403. </div>
  404.  
  405. </div>
  406. <p class='speed-warning'>KEEP SPEED ABOVE 95KM/H</p>
  407. </div>
  408. </div>
  409. </div>
  410.  
  411. <script>
  412. // Функция для плавного обновления числа
  413. // Функция для плавного обновления числа с поддержкой условного форматирования текста
  414. // Универсальная функция анимации для обновления числовых значений
  415. function animateValueUpdate({ selector, oldValue, newValue, isPB = false, precision = 0, unit }) {
  416.   const duration = 700;
  417.   const start = performance.now();
  418.  
  419.   function updateNumber(timestamp) {
  420.     const elapsedTime = timestamp - start;
  421.     const progress = Math.min(elapsedTime / duration, 1);
  422.     const currentNumber = oldValue + (newValue - oldValue) * progress;
  423.     // Использование локали 'en-US' для формата с запятой как разделителем тысяч
  424.     const formattedNumber = currentNumber.toLocaleString('en-US', { minimumFractionDigits: precision, maximumFractionDigits: precision });
  425.     const displayValue = isPB ? `PB: ${formattedNumber} ${unit}` : `${formattedNumber}${unit}`;
  426.  
  427.     document.querySelector(selector).textContent = displayValue;
  428.  
  429.     if (progress < 1) {
  430.       requestAnimationFrame(updateNumber);
  431.     }
  432.   }
  433.  
  434.   requestAnimationFrame(updateNumber);
  435. }
  436.  
  437. // Обработка обновления различных значений
  438. function updateValue(type, newValue) {
  439.   const selectorMap = {
  440.     bestScore: '.score-text',
  441.     currentScore: '#pointsDisplay',
  442.     combo: '.item:nth-child(1) .object-text',
  443.     speed: '.item:nth-child(2) .object-text',
  444.     proximity: '.item:nth-child(3) .object-text'
  445.   };
  446.  
  447.   const isPB = type === 'bestScore';
  448.   const selector = selectorMap[type];
  449.   const currentValueText = document.querySelector(selector)?.textContent.replace(/[^\d.-]/g, '') || "0";
  450.   const currentValue = parseFloat(currentValueText);
  451.   const precision = ['combo', 'speed', 'proximity'].includes(type) ? 1 : 0;
  452.   const unit = ['combo', 'speed', 'proximity'].includes(type) ? "x" : "PTS"; // Удаление пробела для X
  453.  
  454.   animateValueUpdate({ selector, oldValue: currentValue, newValue: parseFloat(newValue), isPB, precision, unit });
  455. }
  456.  
  457.  
  458. // Очередь для хранения данных обновлений
  459. const updateQueue = [];
  460. let isAnimating = false; // Флаг, показывающий, идет ли в данный момент анимация
  461.  
  462. function processNextUpdate() {
  463.   if (updateQueue.length === 0 || isAnimating) {
  464.     return; // Выходим, если анимация уже идёт или нет заданий в очереди
  465.   }
  466.  
  467.   isAnimating = true; // Устанавливаем флаг анимации
  468.   const data = updateQueue.shift(); // Извлекаем первый элемент очереди
  469.  
  470.   const speedUpElement = document.querySelector('.speed-up');
  471.   if (!speedUpElement) {
  472.     console.error("Элемент для обновления сообщения о ускорении не найден.");
  473.     isAnimating = false;
  474.     processNextUpdate(); // Пытаемся обработать следующий элемент в очереди
  475.     return;
  476.   }
  477.  
  478.   // Удаляем предыдущие классы анимации и добавляем новый
  479.   speedUpElement.classList.remove('blink-2', 'shake-top');
  480.   const animationClass = data.color.r === 1 && data.color.g === 0 && data.color.b === 0 ? 'shake-top' : 'blink-2';
  481.   speedUpElement.classList.add(animationClass);
  482.  
  483.   // Изменяем цвет в середине анимации blink-2
  484.   setTimeout(() => {
  485.     speedUpElement.style.background = `rgba(${data.color.r * 255}, ${data.color.g * 255}, ${data.color.b * 255}, 0.2)`;
  486.     speedUpElement.style.border = `0.49px solid rgba(${data.color.r * 255}, ${data.color.g * 255}, ${data.color.b * 255}, 0.68)`;
  487.     speedUpElement.style.color = `rgba(${data.color.r * 255}, ${data.color.g * 255}, ${data.color.b * 255}, 1)`;
  488.   }, 200); // 200ms для достижения 50% анимации blink-2
  489.  
  490.   // Обновляем текст в середине анимации
  491.   setTimeout(() => {
  492.     speedUpElement.textContent = data.message;
  493.   }, 200); // Обновляем текст одновременно с изменением цвета
  494.  
  495.   // Завершаем анимацию и удаляем классы анимации с небольшой задержкой после полного цикла
  496.   setTimeout(() => {
  497.     speedUpElement.classList.remove('blink-2', 'shake-top');
  498.     isAnimating = false;
  499.     processNextUpdate(); // Обрабатываем следующее обновление в очереди
  500.   }, 400); // Полная длительность анимации blink-2
  501. }
  502.  
  503. function updateSpeedUpMessage(data) {
  504.   updateQueue.push(data); // Добавляем данные в очередь
  505.   if (!isAnimating) {
  506.     processNextUpdate(); // Запускаем обработку очереди, если анимация не активна
  507.   }
  508. }
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518. function updatePlace(newPlace) {
  519. console.log("updatePlace called with:", newPlace); // Отладочная информация
  520.  
  521. // Поиск элемента, содержащего текст места
  522. const placeElement = document.querySelector('.score-badge-text');
  523. if (!placeElement) {
  524.   console.error("Элемент для обновления места не найден.");
  525.   return;
  526. }
  527.  
  528. // Обновление текста элемента
  529. placeElement.textContent = `${newPlace}`;
  530. }
  531.  
  532. function updateBadgeStyle() {
  533. const badge = document.querySelector('.score-badge');
  534. const badgeText = badge.querySelector('.score-badge-text');
  535. const svg = badge.querySelector('svg');
  536.  
  537. // Определение стилей для разных позиций
  538. const styleConfigs = {
  539.   1: {
  540.     backgroundColor: 'rgba(221, 3, 85, 1)',
  541.     textColor: 'rgba(8, 6, 10, 1)',
  542.     logoColor: 'rgba(8, 6, 10, 1)',
  543.     fontSize: '16px'
  544.   },
  545.   2: {
  546.     backgroundColor: 'rgba(238, 237, 238, 0.87)',
  547.     textColor: 'rgba(8, 6, 10, 1)',
  548.     logoColor: 'rgba(8, 6, 10, 1)',
  549.     fontSize: '16px'
  550.   },
  551.   3: {
  552.     backgroundColor: 'rgba(255, 129, 38, 1)',
  553.     textColor: 'rgba(8, 6, 10, 1)',
  554.     logoColor: 'rgba(8, 6, 10, 1)',
  555.     fontSize: '16px'
  556.   },
  557.   default: {
  558.     backgroundColor: 'rgba(255, 255, 255, 0.17)',
  559.     textColor: 'rgba(238, 237, 238, 0.87)',
  560.     logoColor: 'rgba(238, 237, 238, 0.52)',
  561.     fontSize: ['16px', '14px', '12px'] // Используйте динамическое определение размера шрифта
  562.   }
  563. };
  564.  
  565. const position = parseInt(badgeText.textContent.replace(/[^\d]/g, '')) || 0;
  566. const config = styleConfigs[position] || styleConfigs.default;
  567.  
  568. // Динамическое определение размера шрифта на основе позиции
  569. const fontSizeIndex = position < 100 ? 0 : position < 1000 ? 1 : 2;
  570. const finalFontSize = config.fontSize instanceof Array ? config.fontSize[fontSizeIndex] : config.fontSize;
  571.  
  572. // Применение стилей
  573. badge.style.background = config.backgroundColor;
  574. badgeText.style.color = config.textColor;
  575. badgeText.style.fontSize = finalFontSize;
  576. svg.querySelectorAll('path').forEach(path => path.setAttribute('fill', config.logoColor));
  577. }
  578.  
  579.  
  580. // Функция для управления видимостью предупреждения о скорости
  581. function speedWarningDisplay(show) {
  582. const speedWarningElement = document.querySelector('.speed-warning');
  583. if (!speedWarningElement) return; // Выходим, если элемент не найден
  584.  
  585. // Устанавливаем свойство display в зависимости от аргумента show
  586. speedWarningElement.style.display = show ? 'block' : 'none';
  587. }
  588.  
  589.  
  590.  
  591. // Обработчик события, получающий данные от AC
  592. AC.onReceive('speedblock', arg => {
  593. // Проверяем значение arg, чтобы определить, показывать или скрывать предупреждение
  594. const shouldShow = arg === 'show'; // Пример условия, arg должен быть 'show' для отображения
  595. speedWarningDisplay(shouldShow);
  596. });
  597.  
  598.  
  599.  
  600.  
  601. function setupEventHandlers() {
  602. AC.onReceive('updateBestScore', newValue => updateValue('bestScore', newValue));
  603. AC.onReceive('updateScore', newValue => updateValue('currentScore', newValue));
  604. AC.onReceive('updateCombo', newValue => updateValue('combo', newValue));
  605. AC.onReceive('updateSpeed', newValue => updateValue('speed', newValue));
  606. AC.onReceive('updateProximity', newValue => updateValue('proximity', newValue));
  607. AC.onReceive('messages', updateSpeedUpMessage);
  608. AC.onReceive('speedblock', arg => speedWarningDisplay(arg === 'show'));
  609. AC.onReceive('updatePlace', newPlace => {
  610.   updatePlace(newPlace);
  611.   updateBadgeStyle(); // Вызов для обновления стилей после изменения места
  612. });
  613.  
  614. AC.onReceive('webanim', arg => {
  615.   if(arg === "startweb") {
  616.       showContent();
  617.   }
  618. });
  619. }
  620.  
  621. function showContent() {
  622. const content = document.querySelector('.content');
  623. if(content) {
  624.   content.style.visibility = 'visible';
  625.   content.style.opacity = '1';
  626. }
  627. }
  628.  
  629. document.addEventListener('DOMContentLoaded', setupEventHandlers);
  630.  
  631.  
  632. </script>
  633.  
  634.  
  635.  
  636.  
  637. </body>
  638. </html>
  639. ]]
  640.  
  641.  
  642.  
  643. function checkAndLoadVideo()
  644. local rootFolder = ac.getFolder(ac.FolderID.Root) .. "\\cache\\remote_assets\\nohesivideo"
  645. local targetFile = rootFolder .. "\\2_90FPS_2.wmv"
  646. -- Check if the file exists
  647. if not io.fileExists(targetFile) then
  648.     -- If the file doesn't exist, first download it
  649.     local function onAssetsLoaded(err, folder)
  650.         if err then
  651.             print("Error loading assets: " .. err)
  652.             return
  653.         end
  654.  
  655.         -- Path to the file to move
  656.         local sourceFile = folder .. "\\2_90FPS_2.wmv"
  657.  
  658.         -- Create the directory if it doesn't exist
  659.         if not io.dirExists(rootFolder) then
  660.             io.createDir(rootFolder)
  661.         end
  662.  
  663.         -- Move the file
  664.         if io.move(sourceFile, targetFile) then
  665.             print("File successfully moved to " .. targetFile)
  666.             loadVideoInPlayer(targetFile)
  667.         else
  668.             print("Failed to move the file.")
  669.         end
  670.     end
  671.     -- Start downloading and unpacking the assets
  672.     web.loadRemoteAssets("https://cdn.discordapp.com/attachments/880053607024717854/1209263927045652591/2_90FPS_2.zip?ex=65e649cb&is=65d3d4cb&hm=33f584a885ac8ea30f635cea6c28831a9ea8bf0e17e4799a51597b2bc1b81d00&", onAssetsLoaded)
  673. else
  674.     -- If the file already exists, load it into MediaPlayer
  675.     loadVideoInPlayer(targetFile)
  676. end
  677. end
  678.  
  679.  
  680. ---@param address string Hub address
  681. function NoHesiClient:initialize(address)
  682.   self.address = address .. "/api/"
  683. end
  684.  
  685. function NoHesiClient:postSettings(Uix, Uiy, Uis, fpsCheck, cpuoCheck, UIToggle, UIClear)
  686.   local payload = string.format("{\"uix\": %s, \"uiy\": %s, \"uis\": %s, \"steamid\": \"%s\", \"fpscheck\": %s, \"cpuocheck\": %s, \"uitoggle\": %s, \"uiclear\": %s}", Uix, Uiy, Uis, ac.getUserSteamID(), fpsCheck, cpuoCheck, UIToggle, UIClear)
  687.   local success, err = pcall(function()
  688.       ac.signBlob(payload, function (data)
  689.           local urlEncodedData = urlEncode(ac.encodeBase64(data))
  690.           local url = self.address .. "settings?data=" .. ac.encodeBase64(payload) .. "&ip=" ..  ac.encodeBase64(ac.getServerIP()) .. "&port=" ..  ac.encodeBase64(ac.getServerPortTCP()) .. "&steamid=" ..  ac.encodeBase64(ac.getUserSteamID()) .. "&serverinfo=" ..  ac.encodeBase64(tostring(car.sessionID)..tostring(sim.randomSeed)) .. "&sig=" ..  urlEncodedData
  691.           web.post(url, function (err, response)
  692.               ac.debug("err", err)
  693.           end)
  694.       end)
  695.   end)
  696.   if not success then
  697.       ac.debug("Error occurred:", err)
  698.   end
  699. end
  700.  
  701. function NoHesiClient:getSettings(callback)
  702.   local payload = ac.getUserSteamID()
  703.   local success, err = pcall(function()
  704.       ac.signBlob(payload, function (data)
  705.           local urlEncodedData = urlEncode(ac.encodeBase64(data))
  706.           local url = self.address .. "settings?data=" .. ac.encodeBase64(payload) .. "&ip=" ..  ac.encodeBase64(ac.getServerIP()) .. "&port=" ..  ac.encodeBase64(ac.getServerPortTCP()) .. "&steamid=" ..  ac.encodeBase64(ac.getUserSteamID()) .. "&serverinfo=" ..  ac.encodeBase64(tostring(car.sessionID)..tostring(sim.randomSeed)) .. "&sig=" ..  urlEncodedData
  707.           web.get(url, function (err, response)
  708.               ac.debug("err", err)
  709.               callback(JSON.parse(response.body))
  710.           end)
  711.       end)
  712.   end)
  713.  
  714.   if not success then
  715.       ac.debug("Error occurred:", err)
  716.   end
  717. end
  718.  
  719. function NoHesiClient:postScore(score, combo, speed, time, distance, callback)
  720.   local payload = string.format("{\"score\": \"%s\", \"combo\": %s, \"avg_speed\": %s, \"run_time\": %s, \"run_distance\": %s, \"steamid\": \"%s\", \"input\": %s, \"car_model\": \"%s\", \"server\": \"%s\"}", score, combo, speed, time, distance, ac.getUserSteamID(), sim.inputMode, ac.getCarID(0):lower(), ac.getServerIP() .. ":" .. ac.getServerPortTCP())
  721.   local success, err = pcall(function()
  722.       ac.signBlob(payload, function (data)
  723.           local urlEncodedData = urlEncode(ac.encodeBase64(data))
  724.           local url = self.address .. "score?data=" .. ac.encodeBase64(payload) .. "&ip=" ..  ac.encodeBase64(ac.getServerIP()) .. "&port=" ..  ac.encodeBase64(ac.getServerPortTCP()) .. "&steamid=" ..  ac.encodeBase64(ac.getUserSteamID()) .. "&serverinfo=" ..  ac.encodeBase64(tostring(car.sessionID)..tostring(sim.randomSeed)) .. "&sig=" ..  urlEncodedData
  725.           web.post(url, function (err, response)
  726.               ac.debug("err", err)
  727.               callback(JSON.parse(response.body))
  728.           end)
  729.       end)
  730.   end)
  731.  
  732.   if not success then
  733.       ac.debug("Error occurred:", err)
  734.   end
  735. end
  736.  
  737. function NoHesiClient:getScore(callback)
  738.   local payload = ac.getUserSteamID()
  739.   local success, err = pcall(function()
  740.       ac.signBlob(payload, function (data)
  741.           local urlEncodedData = urlEncode(ac.encodeBase64(data))
  742.           local url = self.address .. "score?data=" .. ac.encodeBase64(payload) .. "&ip=" ..  ac.encodeBase64(ac.getServerIP()) .. "&port=" ..  ac.encodeBase64(ac.getServerPortTCP()) .. "&steamid=" ..  ac.encodeBase64(ac.getUserSteamID()) .. "&serverinfo=" ..  ac.encodeBase64(tostring(car.sessionID)..tostring(sim.randomSeed)) .. "&sig=" ..  urlEncodedData
  743.           web.get(url, function (err, response)
  744.               ac.debug("err", err)
  745.               callback(JSON.parse(response.body))
  746.           end)
  747.       end)
  748.   end)
  749.  
  750.   if not success then
  751.       ac.debug("Error occurred:", err)
  752.   end
  753. end
  754.  
  755. function urlEncode(str)
  756.   if str then
  757.     str = string.gsub(str, "\n", "\r\n")
  758.     str = string.gsub(str, "([^%w ])",
  759.       function(c) return string.format("%%%02X", string.byte(c)) end)
  760.     str = string.gsub(str, " ", "+")
  761.   end
  762.   return str
  763. end
  764.  
  765. function script.prepare(dt)
  766. ac.log('speed' + ac.getCar(1).speedKmh)
  767. return ac.getCarState(1).speedKmh > 60
  768. end
  769.  
  770. local nohesiclient = NoHesiClient(config.hubUrl)
  771. local requiredSpeed = 95
  772. local sim = ac.getSim()
  773.  
  774. local maxcombo = 0
  775. local averageSpeed = 0
  776. local startdistance = 0
  777. local rundistance = 0
  778. local starttime = 0
  779. local runtime = 0
  780. local distancedriven = 0
  781. local timePassed = 0
  782. local speedMessageTimer = 0
  783. local mackMessageTimer = 0
  784. local totalScore = 0
  785. local comboMeter = 1
  786. local speedComboMeter = 1
  787. local proxiComboMeter = 1
  788. local comboColor = 0
  789. local dangerouslySlowTimer = 0
  790. local carsState = {}
  791. local wheelsWarningTimeout = 0
  792. local personalBest = 0
  793. local ownRank = 0
  794. local cheatcounter = 0
  795. local leaderboardByName = {}
  796. local MackMessages = { 'MAAAACK!!!!', 'MACKSAUCE!!', 'You Hesitated....', 'bRUH', 'No Shot...'}
  797. --new
  798. local CloseMessages = { 'IN THAT!!!!!', 'IN THERE.', 'D I V E', 'SKRRT!!!' }
  799. local NormalMessages = { 'Overtake', 'Smooth Move', 'Easy Breeze' }
  800. local FPS = sim.fps
  801. local CPUO = sim.cpuOccupancy
  802. local Uix, Uiy, Uis, fpsCheck, cpuoCheck, UIToggle, UIClear = nil, nil, nil, nil, nil, nil, nil
  803. local logoCheck = true
  804. --new
  805. local previousBestScore = nil
  806. local previousTotalScore = nil
  807. local previousComboMeter = nil
  808. local previousSpeedComboMeter = nil
  809. local previousProximity = nil
  810. local previousRank = nil
  811. local previousMessages = {} -- Для хранения предыдущих сообщений
  812. local previousSpeedWarningShown = nil -- Добавляем переменную состояния для предупреждения о скорости
  813.  
  814.  
  815. function OptionUI()
  816.   local uiState = ac.getUI()
  817.   ui.text('Settings list:')
  818.   ui.childWindow('##checkyo', vec2(400, 450), ui.WindowFlags.MenuBar,function ()
  819.       if ui.checkbox("Show FPS", fpsCheck) then
  820.           fpsCheck = not fpsCheck
  821.       end
  822.       if ui.checkbox("Show CPU Occupancy", cpuoCheck) then
  823.           cpuoCheck = not cpuoCheck
  824.       end
  825.       if ui.checkbox("Points UI", UIToggle) then
  826.           UIToggle = not UIToggle
  827.       end
  828.       if ui.checkbox("Clear / Dark UI", UIClear) then
  829.           UIClear = not UIClear
  830.       end
  831.  
  832.       ui.text('Points position:')
  833.       Uix = ui.slider('##slideyyo', Uix, -500, uiState.windowSize.x, 'x-axis: %0.0f')
  834.       Uiy = ui.slider('##slidexyo', Uiy, -500, uiState.windowSize.y, 'y-axis: %0.0f')
  835.       Uis = ui.slider('##slidesyo', Uis, 0, 1, 'Scale: %0.2f')
  836.       if ui.button("☁️ Save Settings", vec2(120, 20)) then
  837.           nohesiclient:postSettings(Uix, Uiy, Uis, fpsCheck, cpuoCheck, UIToggle, UIClear)
  838.       end
  839.       ui.sameLine(160, 0)
  840.       if ui.button("☁️ Load Settings", vec2(120, 20)) then
  841.           nohesiclient:getSettings(function (settings)
  842.               ac.log(settings)
  843.               if settings[1] == nil then
  844.                   Uix = uiState.windowSize.y * 0.005
  845.                   Uiy = uiState.windowSize.x * 0.0025
  846.                   Uis = uiState.windowSize.y * 0.0005
  847.                   fpsCheck = false
  848.                   cpuoCheck = false
  849.                   UIToggle = true
  850.                   UIClear = true
  851.               else
  852.                   Uix = settings[1].uix
  853.                   Uiy = settings[1].uiy
  854.                   Uis = settings[1].uis
  855.                   fpsCheck = settings[1].fpscheck
  856.                   cpuoCheck = settings[1].cpuocheck
  857.                   UIToggle = settings[1].uitoggle
  858.                   UIClear = settings[1].uiclear
  859.               end
  860.           end)
  861.       end
  862.       if ui.button("Reset", vec2(50, 20)) then
  863.           Uix = uiState.windowSize.y * 0.005
  864.           Uiy = uiState.windowSize.x * 0.0025
  865.           Uis = uiState.windowSize.y * 0.0005
  866.           fpsCheck = false
  867.           cpuoCheck = false
  868.           UIToggle = true
  869.           UIClear = true
  870.       end
  871.   end)
  872. end
  873.  
  874. function OptionUIClosed()
  875.  
  876. end
  877.  
  878. nohesiclient:getSettings(function (settings)
  879.   local uiState = ac.getUI()
  880.   if settings[1] == nil then
  881.       Uix = uiState.windowSize.y * 0.005
  882.       Uiy = uiState.windowSize.x * 0.0025
  883.       Uis = uiState.windowSize.y * 0.0005
  884.       fpsCheck = false
  885.       cpuoCheck = false
  886.       UIToggle = true
  887.       UIClear = true
  888.   else
  889.       Uix = settings[1].uix
  890.       Uiy = settings[1].uiy
  891.       Uis = settings[1].uis
  892.       fpsCheck = settings[1].fpscheck
  893.       cpuoCheck = settings[1].cpuocheck
  894.       UIToggle = settings[1].uitoggle
  895.       UIClear = settings[1].uiclear
  896.   end
  897. end)
  898.  
  899. nohesiclient:getScore(function (score)
  900.   personalBest = score.score
  901.   ownRank = score.rank
  902. end)
  903.  
  904. local function updateTopScores()
  905. local newScores = {}
  906. for name, score in pairs(leaderboardByName) do
  907.   table.insert(newScores, { Name = name, Score = score})
  908. end
  909. table.sort(newScores, function (a, b) return a.Score > b.Score end)
  910. topScores = newScores
  911. end
  912.  
  913. local personalBestEvent = ac.OnlineEvent({
  914. ac.StructItem.key("overtakePb"),
  915. score = ac.StructItem.double()
  916. }, function (sender, message)
  917. leaderboardByName[ac.getDriverName(sender.index)] = message.score
  918. updateTopScores()
  919. end)
  920.  
  921. local function broadcastPersonalBest()
  922.   if totalScore > personalBest then
  923.       personalBestEvent({ score = totalScore })
  924.   end
  925. end
  926.  
  927. local function savePersonalBest()
  928.   if totalScore > personalBest then
  929.       personalBest = totalScore
  930.       nohesiclient:postScore(totalScore, maxcombo, averageSpeed, runtime, rundistance, function (score)
  931.           personalBest = score.score
  932.           ownRank = score.rank
  933.       end)
  934.   end
  935. end
  936.  
  937. --updateLeaderboard()
  938. --setInterval(updateLeaderboard, 60)
  939. setInterval(broadcastPersonalBest, 1)
  940. if runtime > 0 then
  941.   setInterval(savePersonalBest, 5)
  942. end
  943.  
  944. local leaderboardSize = vec2(250, 80)
  945.  
  946. local uiState = ac.getUI()
  947.  
  948. function script.update(dt)
  949. if timePassed == 0 then
  950.   addMessage('Made by No Hesi', 0)
  951. end
  952.  
  953. local player = ac.getCarState(1)
  954. if player.engineLifeLeft < 1 then
  955.   ac.console('Overtake score: ' .. totalScore)
  956.   return
  957. end
  958.  
  959. distancedriven = player.distanceDrivenSessionKm
  960. timePassed = timePassed + dt
  961. speedMessageTimer = speedMessageTimer + dt
  962. mackMessageTimer = mackMessageTimer + dt
  963.  
  964.  
  965. local comboFadingRate = 0.5 * math.lerp(1, 0.1, math.lerpInvSat(player.speedKmh, 80, 200)) + player.wheelsOutside
  966. comboMeter = math.max(1, comboMeter - dt * comboFadingRate)
  967. speedComboMeter = math.floor(math.lerp(1, 3, math.lerpInvSat(player.speedKmh, 150, 300)) * 10 + 0.5) / 10
  968.  
  969.  
  970. local sim = ac.getSim()
  971. while sim.carsCount > #carsState do
  972.   carsState[#carsState + 1] = {}
  973. end
  974.  
  975. if wheelsWarningTimeout > 0 then
  976.   wheelsWarningTimeout = wheelsWarningTimeout - dt
  977. elseif player.wheelsOutside > 0 then
  978.   if wheelsWarningTimeout == 0 then
  979.   end
  980.   addMessage('Car is Out Of Zone', -1)
  981.   wheelsWarningTimeout = 60
  982. end
  983.  
  984. if player.speedKmh < requiredSpeed then
  985.   proxiComboMeter = 1
  986.   if dangerouslySlowTimer > 3 then
  987.       ac.console('Overtake score: ' .. totalScore)
  988.       comboMeter = 1
  989.       totalScore = 0
  990.  
  991.   else
  992.       if dangerouslySlowTimer < 3 then
  993.           if speedMessageTimer > 5 then
  994.               --addMessage('a'..dangerouslySlowTimer, -1)
  995.               speedMessageTimer = 0
  996.           end
  997.       end
  998.  
  999.       if dangerouslySlowTimer == 0 then
  1000.           addMessage('Speed up!', -1)
  1001.       end
  1002.  
  1003.   end
  1004.   dangerouslySlowTimer = dangerouslySlowTimer + dt
  1005.   comboMeter = 1
  1006.   if totalScore > personalBest and dangerouslySlowTimer > 3 then
  1007.       personalBest = totalScore
  1008.       --    ac.sendChatMessage('just scored a ' .. personalBest)
  1009.       nohesiclient:postScore(totalScore, maxcombo, averageSpeed, runtime, rundistance, function (score)
  1010.           personalBest = score.score
  1011.           ownRank = score.rank
  1012.       end)
  1013.   end
  1014.  
  1015.   return
  1016. else
  1017.   dangerouslySlowTimer = 0
  1018. end
  1019.  
  1020. if player.collidedWith == 0 then
  1021.  
  1022.   if totalScore > personalBest then
  1023.       personalBest = totalScore
  1024.       --    ac.sendChatMessage('just scored a ' .. personalBest)
  1025.       nohesiclient:postScore(totalScore, maxcombo, averageSpeed, runtime, rundistance, function (score)
  1026.           personalBest = score.score
  1027.           ownRank = score.rank
  1028.       end)
  1029.   end
  1030.   cheatcounter = 0
  1031.   comboMeter = 1
  1032.   totalScore = 0
  1033.   if mackMessageTimer > 1 then
  1034.           addMessage(MackMessages[math.random(1, #MackMessages)], -1)
  1035.           mackMessageTimer = 0
  1036.   end
  1037. end
  1038.  
  1039. if totalScore > 0 then
  1040.   rundistance = distancedriven - startdistance
  1041.   runtime = timePassed - starttime
  1042.   averageSpeed = (rundistance / runtime)*3600
  1043. else
  1044.   maxcombo = 0
  1045.   averageSpeed = 0
  1046.   runtime = 0
  1047.   starttime = 0
  1048.   rundistance = 0
  1049.   startdistance = 0
  1050.   proxiComboMeter = 1
  1051. end
  1052.  
  1053.  
  1054.  
  1055. local function get_closest_car_index()
  1056.   local k = 0
  1057.   local min = math.huge
  1058.   for i = 2, ac.getSim().carsCount do
  1059.       local car = ac.getCarState(i)
  1060.       local closestcarname = ac.getCarID(i-1)
  1061.       if not string.find(closestcarname, "traffic") then
  1062.           local dist = car.position:distance(player.position)
  1063.           if dist < min then
  1064.               k = i
  1065.               min = dist
  1066.           end
  1067.       end
  1068.   end
  1069.   return k
  1070. end
  1071.  
  1072. local closestcarindex = get_closest_car_index()
  1073. local closestcar = ac.getCarState(closestcarindex)
  1074. local closestcarname
  1075.  
  1076. if closestcar then
  1077.   closestcarname = ac.getCarID(closestcarindex-1)
  1078.  
  1079.   if closestcar.position:closerToThan(player.position, 20) and math.dot(car.look, player.look) > 0.2 then
  1080.       local carToPlayer = player.position - closestcar.position
  1081.       local dotProduct = closestcar.look:dot(carToPlayer)
  1082.       local dotProduct2 = closestcar.side:dot(carToPlayer)
  1083.  
  1084.       local t = math.lerpInvSat(math.abs(dotProduct), 19, 6)
  1085.       local penaltyFactor = 1 + (t^2 * 4)
  1086.       local p = math.lerpInvSat(math.abs(dotProduct)+(math.abs(dotProduct2)*penaltyFactor), 19, 6)
  1087.      
  1088.       proxiComboMeter = math.round(math.lerp(1, 4, (-(p * p) + 2 * p)), 1)
  1089.   else
  1090.       proxiComboMeter = 1
  1091.   end
  1092. else
  1093.   proxiComboMeter = 1 -- Assuming default value in case of error
  1094. end
  1095.  
  1096.  
  1097.  
  1098. for i = 2, ac.getSim().carsCount do
  1099.   local car = ac.getCarState(i)
  1100.   local state = carsState[i]
  1101.   -- ac.debug(car.collidedWith .. " COLLISION")
  1102.   if car.position:closerToThan(player.position, 4.5) then
  1103.       local drivingAlong = math.dot(car.look, player.look) > 0.2
  1104.       if not drivingAlong then
  1105.           state.drivingAlong = false
  1106.  
  1107.           if not state.nearMiss and car.position:closerToThan(player.position, 3) then
  1108.               state.nearMiss = true
  1109.  
  1110.  
  1111.           end
  1112.       end
  1113.  
  1114.  
  1115.       if not state.overtaken and not state.collided and state.drivingAlong then
  1116.           local posDir = (car.position - player.position):normalize()
  1117.           local posDot = math.dot(posDir, car.look)
  1118.           state.maxPosDot = math.max(state.maxPosDot, posDot)
  1119.           if posDot < -0.5 and state.maxPosDot > 0.5 then
  1120.               totalScore = totalScore + math.ceil(10 * comboMeter)
  1121.               if startdistance == 0 and starttime == 0 then
  1122.                   startdistance = distancedriven
  1123.                   starttime = timePassed
  1124.               end
  1125.               if cheatcounter > 10 then
  1126.                   setInterval(function() ac.sendChatMessage('debug message from the anti-cheat') end, 1, "cheat")
  1127.                   physics.engageGear(0, 0)
  1128.                   physics.setCarNoInput(true)
  1129.                   physics.teleportCarTo(0, 'PIT')
  1130.                   totalScore = 0
  1131.                   nohesiclient:postScore(totalScore, maxcombo, averageSpeed, runtime, rundistance, function (score)
  1132.                       personalBest = score.score
  1133.                       ownRank = score.rank
  1134.                   end)
  1135.                   setTimeout(function () ac.shutdownAssettoCorsa()  end, 5)
  1136.                   state.overtaken = true
  1137.               elseif car.position:closerToThan(player.position, 1.9) then
  1138.                   cheatcounter = cheatcounter + 1
  1139.                   state.overtaken = true
  1140.               elseif car.position:closerToThan(player.position, 3) then
  1141.                   comboMeter = comboMeter + (2 + speedComboMeter + proxiComboMeter - 1)
  1142.                   comboColor = comboColor + math.random(1, 90)
  1143.                   addMessage(CloseMessages[math.random(#CloseMessages)].. ' ' .. (2 + speedComboMeter + proxiComboMeter - 1) .. 'x', 2)
  1144.                   state.overtaken = true
  1145.               else
  1146.                   comboMeter = comboMeter + (speedComboMeter + proxiComboMeter - 1)
  1147.                   comboColor = comboColor + 90
  1148.                   addMessage(NormalMessages[math.random(#NormalMessages)] .. ' ' .. (speedComboMeter + proxiComboMeter - 1) .. 'x', comboMeter > 50 and 1 or 0)
  1149.                   state.overtaken = true
  1150.               end
  1151.               if comboMeter > maxcombo then
  1152.                   maxcombo = comboMeter
  1153.               end
  1154.           end
  1155.       end
  1156.  
  1157.   else
  1158.       state.maxPosDot = -1
  1159.       state.overtaken = false
  1160.       state.collided = false
  1161.       state.drivingAlong = true
  1162.       state.nearMiss = false
  1163.   end
  1164. end
  1165. end
  1166.  
  1167. local messages = {}
  1168. local glitter = {}
  1169. local glitterCount = 0
  1170.  
  1171. function addMessage(text, mood)
  1172. for i = math.min(#messages + 1, 1), 2, -1 do
  1173.   messages[i] = messages[i - 1]
  1174.   messages[i].targetPos = i
  1175. end
  1176. messages[1] = { text = text, age = 0, targetPos = 1, currentPos = 1, mood = mood }
  1177. if mood == 1 then
  1178.   for i = 1, 60 do
  1179.       local dir = vec2(math.random() - 0.5, math.random() - 0.5)
  1180.       glitterCount = glitterCount + 1
  1181.       glitter[glitterCount] = {
  1182.           color = rgbm.new(hsv(math.random() * 360, 1, 1):rgb(), 1),
  1183.           pos = vec2(80, 140) + dir * vec2(40, 20),
  1184.           velocity = dir:normalize():scale(0.2 + math.random()),
  1185.           life = 0.5 + 0.5 * math.random()
  1186.       }
  1187.   end
  1188. end
  1189. end
  1190.  
  1191. local function updateMessages(dt)
  1192. comboColor = comboColor + dt * 10 * comboMeter
  1193. if comboColor > 360 then comboColor = comboColor - 360 end
  1194.   for i = 1, #messages do
  1195.       local m = messages[i]
  1196.       m.age = m.age + dt
  1197.       m.currentPos = math.applyLag(m.currentPos, m.targetPos, 0.8, dt)
  1198.   end
  1199. end
  1200.  
  1201. local speedWarning = 0
  1202. local fontpath = ''
  1203.  
  1204.  
  1205. web.loadRemoteAssets('https://hub.nohesi.gg/ui/microgramma.zip', function (err, response)
  1206.   fontpath = response
  1207. end)
  1208.  
  1209.  
  1210.  
  1211.  
  1212. function loadVideoInPlayer(videoPath)
  1213.   player = ui.MediaPlayer()
  1214.   player:setSource(videoPath) -- Установите корректный путь к файлу
  1215.  
  1216.         :setAutoPlay(true) -- Автоматическое воспроизведение после загрузки
  1217.         :setLooping(true) -- Циклическое воспроизведение
  1218.   player:setUpdatePeriod(0.0) -- Установка периода обновления
  1219.  
  1220.   end
  1221.  
  1222.  
  1223. checkAndLoadVideo()
  1224.  
  1225.  
  1226. function add_suffix(position)
  1227.   local last_two_digits = position % 100
  1228.   if last_two_digits >= 11 and last_two_digits <= 13 then
  1229.   return "th"
  1230.   elseif position % 10 == 1 then
  1231.   return "st"
  1232.   elseif position % 10 == 2 then
  1233.   return "nd"
  1234.   elseif position % 10 == 3 then
  1235.   return "rd"
  1236.   else
  1237.   return "th"
  1238.   end
  1239. end
  1240.  
  1241.  
  1242.  
  1243. browser:navigate('data:text/html;base64,' .. ac.encodeBase64(htmlContent))
  1244. local counter = 0
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250. -- Time for the image to fully appear in seconds
  1251. local fadeInTime = 2
  1252. -- Time for the image to fully fade out in seconds
  1253. local fadeOutTime = 2
  1254. -- Flag indicating if the animation is currently active
  1255. local isAnimationActive = false -- Изначально анимация не активна
  1256. -- Flag to check if the animation has been started
  1257. local hasAnimationStarted = false
  1258. -- Current time within the animation cycle
  1259. local currentTime = 0
  1260.  
  1261. -- Function to start the animation
  1262. local function startAnimation()
  1263.     if not hasAnimationStarted and not ac.getSim().isInMainMenu then
  1264.         isAnimationActive = true
  1265.         hasAnimationStarted = true
  1266.     end
  1267. end
  1268.  
  1269. -- Animation function
  1270.   local function animate(dt)
  1271.     -- Start the animation based on the condition
  1272.     startAnimation()
  1273.    
  1274.    
  1275.     -- Stop the animation if it's not active
  1276.     if not isAnimationActive then return end
  1277.    
  1278.     -- Update the current animation time
  1279.     currentTime = currentTime + dt
  1280.     local totalTime = fadeInTime + fadeOutTime
  1281.     local alpha = 0
  1282.  
  1283.     -- Calculate the alpha value based on the current phase of the animation
  1284.     if currentTime <= fadeInTime then
  1285.         alpha = currentTime / fadeInTime
  1286.     elseif currentTime <= totalTime then
  1287.         alpha = 1 - (currentTime - fadeInTime) / fadeOutTime
  1288.         browser:sendAsync('webanim', "startweb")
  1289.     else
  1290.         isAnimationActive = false -- Deactivate the animation after completion
  1291.         currentTime = 0 -- Reset currentTime to allow the animation to be started again if needed
  1292.        
  1293.     end
  1294.  
  1295.     -- Set the alpha channel for color modulation
  1296.     local color = rgbm(1, 1, 1, alpha)
  1297.  
  1298.     -- Render the image with the animated alpha channel
  1299.     display.image({
  1300.         image = player,
  1301.         pos = vec2(0, 0),
  1302.         size = vec2(300, 300),
  1303.         color = color,
  1304.         uvStart = vec2(0, 0),
  1305.         uvEnd = vec2(1, 1)
  1306.     })
  1307. end
  1308.  
  1309. -- Schedule the animation to stop after the total duration
  1310. setTimeout(function()
  1311.   isAnimationActive = false -- Deactivate the animation after completion
  1312. end, fadeInTime + fadeOutTime)
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318. local function sendDataIfChanged()
  1319. local speedWarningShown = ac.getCar(0).speedKmh <= 90 -- true, если скорость меньше или равна 90 км/ч
  1320.  
  1321.  
  1322. local roundedComboMeter = math.floor(comboMeter * 10 + 0.5) / 10
  1323.  
  1324. if personalBest ~= previousBestScore then
  1325.     browser:sendAsync('updateBestScore', personalBest)
  1326.     previousBestScore = personalBest
  1327. end
  1328.  
  1329. if totalScore ~= previousTotalScore then
  1330.     browser:sendAsync('updateScore', totalScore)
  1331.     previousTotalScore = totalScore
  1332. end
  1333.  
  1334. -- Сравниваем округленные значения до десятых
  1335. if roundedComboMeter ~= previousComboMeter then
  1336.     browser:sendAsync('updateCombo', roundedComboMeter)
  1337.     previousComboMeter = roundedComboMeter
  1338. end
  1339.  
  1340. if speedComboMeter ~= previousSpeedComboMeter then
  1341.     browser:sendAsync('updateSpeed', speedComboMeter)
  1342.     previousSpeedComboMeter = speedComboMeter
  1343. end
  1344.  
  1345. if proxiComboMeter ~= previousProximity then
  1346.     browser:sendAsync('updateProximity', proxiComboMeter)
  1347.     previousProximity = proxiComboMeter
  1348. end
  1349.  
  1350. if ownRank ~= previousRank then
  1351.     browser:sendAsync('updatePlace', "#"..ownRank)
  1352.     previousRank = ownRank
  1353.  
  1354. end
  1355.  
  1356. -- Проверка и отправка состояния предупреждения о скорости
  1357. if speedWarningShown ~= previousSpeedWarningShown then
  1358.     browser:sendAsync('speedblock', speedWarningShown and "show" or "notshow")
  1359.     previousSpeedWarningShown = speedWarningShown
  1360. end
  1361.  
  1362.  
  1363. for i, m in ipairs(messages) do
  1364.   local prevM = previousMessages[i] or {}
  1365.   -- Преобразование результатов функции rgbm в соответствующий объект
  1366.   local colorComponents = m.mood == 1 and {r=1, g=1, b=1, m=1}
  1367.                           or m.mood == -1 and {r=1, g=0, b=0, m=1}
  1368.                           or m.mood == 2 and {r=0.714, g=0.02, b=0.976, m=1}
  1369.                           or {r=1, g=1, b=1, m=1} -- Упрощаем, всегда используем полную непрозрачность
  1370.  
  1371.   -- Проверяем, изменилось ли сообщение или его настроение
  1372.   if m.text ~= prevM.text or m.mood ~= prevM.mood then
  1373.       browser:sendAsync('messages', {message = m.text, color = colorComponents})
  1374.   end
  1375.  
  1376.   -- Обновляем предыдущее состояние сообщения
  1377.   previousMessages[i] = {text = m.text, mood = m.mood}
  1378. end
  1379.  
  1380. end
  1381.  
  1382.  
  1383.  
  1384.  
  1385. function script.drawUI(dt)
  1386.  
  1387.  
  1388. animate(ac.getScriptDeltaT())
  1389.  
  1390. updateMessages(uiState.dt)
  1391.  
  1392. ui.beginScale()
  1393. ui.beginTransparentWindow('overtakeScore', vec2(Uix, Uiy), vec2(560, 300))
  1394.  
  1395.  
  1396.  
  1397. -- Create an invisible item for spacing
  1398. ui.dummy(vec2(520, 420))
  1399. -- Get coordinates for rendering and draw the browser
  1400. local p1, p2 = ui.itemRect()
  1401. browser:draw(p1, p2, true)
  1402.  
  1403. counter = counter + ac.getScriptDeltaT()
  1404.  
  1405. if counter >= 0.1 then
  1406.   sendDataIfChanged()
  1407. counter = 0
  1408.  
  1409. end
  1410.  
  1411. -- Handle mouse input for the browser
  1412. -- nextupdate
  1413. --  local function getMouseButtons()
  1414.   --   mouseButtons[1] = uis.isMouseLeftKeyDown
  1415.   --    mouseButtons[2] = uis.isMouseRightKeyDown
  1416.   --    mouseButtons[3] = uis.isMouseMiddleKeyDown
  1417.   --    return mouseButtons
  1418. --end
  1419.  
  1420. -- browser:mouseInput(ui.mouseLocalPos():sub(p1):div(lastSize), getMouseButtons(), uis.mouseWheel, false)
  1421.  
  1422. ui.endTransparentWindow()
  1423.  
  1424.  
  1425. if logoCheck then
  1426.   ui.drawImage('https://i.imgur.com/rHHbNc0.png', vec2(100 , uiState.windowSize.y), vec2(0, uiState.windowSize.y - 100))
  1427. end
  1428.  
  1429. ui.beginOutline()
  1430. if fpsCheck then
  1431.   ui.setCursorY(0)
  1432.   ui.pushFont(ui.Font.Main)
  1433.   setInterval(function() FPS = sim.fps end, 0.1, "FPSCounter")    
  1434.   ui.text(math.floor(FPS) .. " FPS")
  1435.   ui.endOutline(rgbm(0, 0, 0, 0.3))
  1436.   ui.sameLine(100, 0)
  1437. end
  1438. if cpuoCheck then
  1439.   ui.setCursorY(0)
  1440.   ui.pushFont(ui.Font.Main)
  1441.   setInterval(function() CPUO = sim.cpuOccupancy end, 0.1, "CPUOCounter")    
  1442.   ui.text(math.floor(CPUO) .. "% CPU Occupancy")
  1443.   if fpsCheck then
  1444.       ui.sameLine(300, 0)
  1445.   else
  1446.       ui.sameLine(200, 0)
  1447.   end
  1448. end
  1449. ui.endOutline(rgbm(0, 0, 0, 0.3))
  1450. end
  1451. ui.registerOnlineExtra(ui.Icons.Burn, 'No Hesi UI Settings', nil, OptionUI, OptionUIClosed, ui.OnlineExtraFlags.Tool)
Add Comment
Please, Sign In to add comment